Class: Prawn::Fonts::AFM
- Inherits:
-
Prawn::Font
- Object
- Prawn::Font
- Prawn::Fonts::AFM
- Defined in:
- lib/prawn/fonts/afm.rb
Overview
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
-
.hide_m17n_warning ⇒ Boolean
Prawn would warn you if you’re using non-ASCII glyphs with AFM fonts as not all implementations provide those glyphs.
Class Method Summary collapse
-
.font_data ⇒ SynchronizedCache
Parsed AFM data cache.
-
.metrics_path ⇒ Array<String>
Paths to look for AFM files at.
Instance Method Summary collapse
-
#bbox ⇒ Array(Number, Number, Number, Number)
The font bbox.
-
#character_count(str) ⇒ Integer
Returns the number of characters in
str
(a WinAnsi-encoded string). -
#compute_width_of(string, options = {}) ⇒ Number
Compute width of a string at the specified size, optionally with kerning applied.
-
#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.
-
#glyph_present?(char) ⇒ Boolean
Does this font has a glyph for the character?.
-
#has_kerning_data? ⇒ Boolean
Does this font contain kerning data.
-
#initialize(document, name, options = {}) ⇒ AFM
constructor
A new instance of AFM.
-
#normalize_encoding(text) ⇒ String
Built-in fonts only work with WinAnsi encoding, so translate the string.
-
#to_utf8(text) ⇒ String
Encode text to UTF-8.
-
#unicode? ⇒ false
Does this font support Unicode?.
Constructor Details
#initialize(document, name, options = {}) ⇒ AFM
Returns a new instance of AFM.
Source Code
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_warning ⇒ Boolean
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.
Source Code
23 | def hide_m17n_warning |
24 | @hide_m17n_warning
|
25 | end
|
Class Method Details
.font_data ⇒ SynchronizedCache
Parsed AFM data cache.
Source Code
66 | def self.font_data |
67 | @font_data ||= SynchronizedCache.new |
68 | end
|
.metrics_path ⇒ Array<String>
Paths to look for AFM files at.
Source Code
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
#bbox ⇒ Array(Number, Number, Number, Number)
The font bbox.
Source Code
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).
Source Code
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.
Source Code
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).
Source Code
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?
Source Code
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.
Source Code
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.
Source Code
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.
Source Code
157 | def to_utf8(text) |
158 | text.encode('UTF-8') |
159 | end
|
#unicode? ⇒ false
Does this font support Unicode?
Source Code
39 | def unicode? |
40 | false
|
41 | end
|