Class: Prawn::Font::AFM

Inherits:
Prawn::Font show all
Defined in:
lib/prawn/font/afm.rb

Constant Summary collapse

BUILT_INS =
%w[ Courier Helvetica Times-Roman Symbol ZapfDingbats
Courier-Bold Courier-Oblique Courier-BoldOblique
Times-Bold Times-Italic Times-BoldItalic
Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique ]

Instance Attribute Summary collapse

Attributes inherited from Prawn::Font

#family, #name, #options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Prawn::Font

#add_to_current_page, #ascender, #descender, #eql?, #hash, #height, #height_at, #identifier_for, #inspect, #line_gap, load, #normalize_encoding!

Constructor Details

#initialize(document, name, options = {}) ⇒ AFM

:nodoc:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/prawn/font/afm.rb', line 37

def initialize(document, name, options={}) #:nodoc:
  unless BUILT_INS.include?(name)
    raise Prawn::Errors::UnknownFont, "#{name} is not a known font."
  end

  super

  @@winansi   ||= Prawn::Encoding::WinAnsi.new # parse data/encodings/win_ansi.txt once only
  @@font_data ||= SynchronizedCache.new        # parse each ATM font file once only

  file_name = @name.dup
  file_name << ".afm" unless file_name =~ /\.afm$/
  file_name = file_name[0] == ?/ ? file_name : find_font(file_name)

  font_data = @@font_data[file_name] ||= parse_afm(file_name)
  @glyph_widths    = font_data[:glyph_widths]
  @glyph_table     = font_data[:glyph_table]
  @bounding_boxes  = font_data[:bounding_boxes]
  @kern_pairs      = font_data[:kern_pairs]
  @kern_pair_table = font_data[:kern_pair_table]
  @attributes      = font_data[:attributes]

  @ascender  = @attributes["ascender"].to_i
  @descender = @attributes["descender"].to_i
  @line_gap  = Float(bbox[3] - bbox[1]) - (@ascender - @descender)
end

Instance Attribute Details

#attributesObject (readonly)

:nodoc:



35
36
37
# File 'lib/prawn/font/afm.rb', line 35

def attributes
  @attributes
end

Class Method Details

.metrics_pathObject



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/prawn/font/afm.rb', line 23

def self.metrics_path
  if m = ENV['METRICS']
    @metrics_path ||= m.split(':')
  else
    @metrics_path ||= [
      ".", "/usr/lib/afm",
      "/usr/local/lib/afm",
      "/usr/openwin/lib/fonts/afm",
       Prawn::DATADIR+'/fonts']
  end
end

Instance Method Details

#bboxObject

The font bbox, as an array of integers



66
67
68
# File 'lib/prawn/font/afm.rb', line 66

def bbox
  @bbox ||= @attributes['fontbbox'].split(/\s+/).map { |e| Integer(e) }
end

#character_count(str) ⇒ Object

Returns the number of characters in str (a WinAnsi-encoded string).



103
104
105
# File 'lib/prawn/font/afm.rb', line 103

def character_count(str)
  str.length
end

#compute_width_of(string, options = {}) ⇒ Object

NOTE: String must be encoded as WinAnsi



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/prawn/font/afm.rb', line 71

def compute_width_of(string, options={}) #:nodoc:
  scale = (options[:size] || size) / 1000.0

  if options[:kerning]
    strings, numbers = kern(string).partition { |e| e.is_a?(String) }
    total_kerning_offset = numbers.inject(0.0) { |s,r| s + r }
    (unscaled_width_of(strings.join) - total_kerning_offset) * scale
  else
    unscaled_width_of(string) * scale
  end
end

#encode_text(text, options = {}) ⇒ Object

Perform any changes to the string that need to happen before it is rendered to the canvas. Returns an array of subset “chunks”, where each chunk is an array of two elements. The first element is the font subset number, and the second is either a string or an array (for kerned text).

For Adobe fonts, there is only ever a single subset, so the first element of the array is “0”, and the second is the string itself (or an array, if kerning is performed).

The text parameter must be in WinAnsi encoding (cp1252).



119
120
121
# File 'lib/prawn/font/afm.rb', line 119

def encode_text(text, options={})
  [[0, options[:kerning] ? kern(text) : text]]
end

#glyph_present?(char) ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
126
127
128
129
# File 'lib/prawn/font/afm.rb', line 123

def glyph_present?(char)
  if char == "_"
    true
  else
    normalize_encoding(char) != "_"
  end
end

#has_kerning_data?Boolean

Returns true if the font has kerning data, false otherwise

Returns:

  • (Boolean)


85
86
87
# File 'lib/prawn/font/afm.rb', line 85

def has_kerning_data?
  @kern_pairs.any?
end

#normalize_encoding(text) ⇒ Object

built-in fonts only work with winansi encoding, so translate the string. Changes the encoding in-place, so the argument itself is replaced with a string in WinAnsi encoding.



93
94
95
96
97
98
99
# File 'lib/prawn/font/afm.rb', line 93

def normalize_encoding(text)
  enc = @@winansi
  text.unpack("U*").collect { |i| enc[i] }.pack("C*")
rescue ArgumentError
  raise Prawn::Errors::IncompatibleStringEncoding,
    "Arguments to text methods must be UTF-8 encoded"
end

#unicode?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/prawn/font/afm.rb', line 19

def unicode?
  false
end