如何在Ruby中计算String的宽度?

Jam*_*sen 6 ruby typography

String.length只会告诉我String中有多少个字符.(事实上​​,在Ruby 1.9之前,它只会告诉我有多少字节,这些字节的用处更少.)

我真的希望能够找出一个字符串的'en'宽度.例如:

'foo'.width
# => 3

'moo'.width
# => 3.5          # m's, w's, etc. are wide

'foi'.width
# => 2.5          # i's, j's, etc. are narrow

'foo bar'.width
# => 6.25         # spaces are very narrow
Run Code Online (Sandbox Code Playgroud)

如果我能得到nString 的第一个en,那就更好了:

'foo'[0, 2.en]
# => "fo"

'filial'[0, 3.en]
# => "fili"

'foo bar baz'[0, 4.5en]
# => "foo b"
Run Code Online (Sandbox Code Playgroud)

如果我可以策划整个事情,那就更好了.有些人认为空间应该是0.25en,有些人认为它应该是0.33等.

小智 14

您应该使用RMagick gem使用您想要的字体渲染"Draw"对象(您可以加载.ttf文件等)

代码看起来像这样:

   the_text = "TheTextYouWantTheWidthOf"
   label = Draw.new
   label.font = "Vera" #you can also specify a file name... check the rmagick docs to be sure
   label.text_antialias(true)
   label.font_style=Magick::NormalStyle
   label.font_weight=Magick::BoldWeight
   label.gravity=Magick::CenterGravity
   label.text(0,0,the_text)
   metrics = label.get_type_metrics(the_text)
   width = metrics.width
   height = metrics.height
Run Code Online (Sandbox Code Playgroud)

您可以在我的按钮制造商处查看它的实际操作:http://risingcode.com/button/everybodywangchungtonite

  • 只需确保将字体大小设置为“ label.pointsize = THE_SIZE”,否则RMagick的默认字体大小为12。 (2认同)

Mus*_*ify 5

使用ttfunk gem 从字体文件中读取指标。然后,您可以在 em 中获取一串文本的宽度。这是我将此示例添加到 gem 的拉取请求。

require 'rubygems'
require 'ttfunk'
require 'valuable'
# Everything you never wanted to know about glyphs:
# http://chanae.walon.org/pub/ttf/ttf_glyphs.htm

# this code is a substantial reworking of:
# https://github.com/prawnpdf/ttfunk/blob/master/examples/metrics.rb

class Font
  attr_reader :file

  def initialize(path_to_file)
    @file = TTFunk::File.open(path_to_file)
  end

  def width_of( string )
    string.split('').map{|char| character_width( char )}.inject{|sum, x| sum + x}
  end

  def character_width( character )
    width_in_units = ( horizontal_metrics.for( glyph_id( character )).advance_width )
    width_in_units.to_f / units_per_em
  end

  def units_per_em
    @u_per_em ||= file.header.units_per_em
  end

  def horizontal_metrics
    @hm = file.horizontal_metrics
  end

  def glyph_id(character)
    character_code = character.unpack("U*").first
    file.cmap.unicode.first[character_code]
  end
end
Run Code Online (Sandbox Code Playgroud)

这是在行动:

>> din = Font.new("#{File.dirname(__FILE__)}/../../fonts/DIN/DINPro-Light.ttf")
>> din.width_of("Hypertension")
=> 5.832
# which is correct! Hypertension in that font takes up about 5.832 em! It's over by maybe ... 0.015.
Run Code Online (Sandbox Code Playgroud)