Class: Prawn::Fonts::AFM

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

Overview

Note:

You shouldn’t use this class directly.

AFM font. AFM stands for Adobe Font Metrics. It’s not a complete font, it doesn’t provide actual glyph outlines. It only contains glyph metrics to make text layout possible. AFM is used for PDF built-in fonts. Those fonts are supposed to be present on the target system making it possible to save a little bit of space by not embedding the fonts. A file that uses these fonts can not be read on a system that doesn’t have these fonts installed.

Constant Summary collapse

BUILT_INS =

List of PDF built-in fonts.

%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
].freeze

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of AFM.

Parameters:

  • document (Prawn::Document)
  • name (String)
  • options (Hash) (defaults to: {})

Options Hash (options):

  • :family (String)
  • :style (Symbol)
Source Code
lib/prawn/fonts/afm.rb, line 75
75
def initialize(document, name, options = {})
76
  name ||= options[:family]
77
  unless BUILT_INS.include?(name)
78
    raise Prawn::Errors::UnknownFont,
79
      "#{name} (#{options[:style] || 'normal'}) is not a known font."
80
  end
81
82
  super
83
84
  file_name = @name.dup
85
  file_name << '.afm' unless /\.afm$/.match?(file_name)
86
  file_name = find_font(file_name) unless file_name[0] == '/'
87
88
  font_data = self.class.font_data[file_name] ||= parse_afm(file_name)
89
  @glyph_widths = font_data[:glyph_widths]
90
  @glyph_table = font_data[:glyph_table]
91
  @bounding_boxes = font_data[:bounding_boxes]
92
  @kern_pairs = font_data[:kern_pairs]
93
  @kern_pair_table = font_data[:kern_pair_table]
94
  @attributes = font_data[:attributes]
95
96
  @ascender = Integer(@attributes.fetch('ascender', '0'), 10)
97
  @descender = Integer(@attributes.fetch('descender', '0'), 10)
98
  @line_gap = Float(bbox[3] - bbox[1]) - (@ascender - @descender)
99
end

Class Attribute Details

.hide_m17n_warningBoolean

Prawn would warn you if you’re using non-ASCII glyphs with AFM fonts as not all implementations provide those glyphs. This attribute suppresses that warning.

Returns:

  • (Boolean)

    (false)

Source Code
lib/prawn/fonts/afm.rb, line 23
23
def hide_m17n_warning
24
  @hide_m17n_warning
25
end

Class Method Details

.font_dataSynchronizedCache

Parsed AFM data cache.

Returns:

  • (SynchronizedCache)
Source Code
lib/prawn/fonts/afm.rb, line 66
66
def self.font_data
67
  @font_data ||= SynchronizedCache.new
68
end

.metrics_pathArray<String>

Paths to look for AFM files at.

Returns:

  • (Array<String>)
Source Code
lib/prawn/fonts/afm.rb, line 46
46
def self.metrics_path
47
  @metrics_path ||=
48
    if ENV['METRICS']
49
      ENV['METRICS'].split(':')
50
    else
51
      [
52
        '.', '/usr/lib/afm',
53
        '/usr/local/lib/afm',
54
        '/usr/openwin/lib/fonts/afm',
55
        "#{Prawn::DATADIR}/fonts",
56
      ]
57
    end
58
end

Instance Method Details

#bboxArray(Number, Number, Number, Number)

The font bbox.

Returns:

  • (Array(Number, Number, Number, Number))
Source Code
lib/prawn/fonts/afm.rb, line 104
104
def bbox
105
  @bbox ||= @attributes['fontbbox'].split(/\s+/).map { |e| Integer(e) }
106
end

#character_count(str) ⇒ Integer

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

Parameters:

  • str (String)

Returns:

  • (Integer)
Source Code
lib/prawn/fonts/afm.rb, line 165
165
def character_count(str)
166
  str.length
167
end

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

Compute width of a string at the specified size, optionally with kerning applied.

Parameters:

  • string (String)

    must be encoded as WinAnsi

  • options (Hash{Symbol => any}) (defaults to: {})

Options Hash (options):

  • :size (Number)
  • :kerning (Boolean) — default: false

Returns:

  • (Number)
Source Code
lib/prawn/fonts/afm.rb, line 116
116
def compute_width_of(string, options = {})
117
  scale = (options[:size] || size) / 1000.0
118
119
  if options[:kerning]
120
    strings, numbers = kern(string).partition { |e| e.is_a?(String) }
121
    total_kerning_offset = numbers.sum
122
    (unscaled_width_of(strings.join) - total_kerning_offset) * scale
123
  else
124
    unscaled_width_of(string) * scale
125
  end
126
end

#encode_text(text, options = {}) ⇒ Array<Array(0, (String, Array)>]

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 argument must be in WinAnsi encoding (cp1252).

Parameters:

  • text (String)
  • options (Hash{Symbol => any}) (defaults to: {})

Options Hash (options):

  • :kerning (Boolean)

Returns:

  • (Array<Array(0, (String, Array)>])

    Array<Array(0, (String, Array)>]

Source Code
lib/prawn/fonts/afm.rb, line 185
185
def encode_text(text, options = {})
186
  [[0, options[:kerning] ? kern(text) : text]]
187
end

#glyph_present?(char) ⇒ Boolean

Does this font has a glyph for the character?

Parameters:

  • char (String)

Returns:

  • (Boolean)
Source Code
lib/prawn/fonts/afm.rb, line 193
193
def glyph_present?(char)
194
  !normalize_encoding(char).nil?
195
rescue Prawn::Errors::IncompatibleStringEncoding
196
  false
197
end

#has_kerning_data?Boolean

Does this font contain kerning data.

Returns:

  • (Boolean)
Source Code
lib/prawn/fonts/afm.rb, line 131
131
def has_kerning_data? # rubocop: disable Naming/PredicateName
132
  @kern_pairs.any?
133
end

#normalize_encoding(text) ⇒ String

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.

Parameters:

  • text (String)

Returns:

  • (String)
Source Code
lib/prawn/fonts/afm.rb, line 141
141
def normalize_encoding(text)
142
  text.encode('windows-1252')
143
rescue ::Encoding::InvalidByteSequenceError,
144
       ::Encoding::UndefinedConversionError
145
146
  raise Prawn::Errors::IncompatibleStringEncoding,
147
    "Your document includes text that's not compatible with the " \
148
      "Windows-1252 character set.\n" \
149
      'If you need full UTF-8 support, use external fonts instead of ' \
150
      "PDF's built-in fonts.\n"
151
end

#to_utf8(text) ⇒ String

Encode text to UTF-8.

Parameters:

  • text (String)

Returns:

  • (String)
Source Code
lib/prawn/fonts/afm.rb, line 157
157
def to_utf8(text)
158
  text.encode('UTF-8')
159
end

#unicode?false

Does this font support Unicode?

Returns:

  • (false)
Source Code
lib/prawn/fonts/afm.rb, line 39
39
def unicode?
40
  false
41
end