Class: HexaPDF::Font::TrueTypeWrapper

Inherits:
Object
  • Object
show all
Defined in:
lib/hexapdf/font/true_type_wrapper.rb

Overview

This class wraps a generic TrueType font object and provides the methods needed for working with the font in a PDF context.

TrueType fonts can be represented in two ways in PDF: As a simple font with Subtype TrueType or as a composite font using a Type2 CIDFont. The wrapper only supports the composite font case because:

  • By using a composite font more than 256 characters can be encoded with one font object.

  • Fonts for vertical writing can potentially be used.

  • The PDF specification recommends using a composite font (see PDF1.7 s9.9 at the end).

Additionally, TrueType fonts are always embedded.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, font, subset: true) ⇒ TrueTypeWrapper

Creates a new object wrapping the TrueType font for the PDF document.

If subset is true, the font is subset.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 122

def initialize(document, font, subset: true)
  @document = document
  @wrapped_font = font
  @subsetter = (subset ? HexaPDF::Font::TrueType::Subsetter.new(font) : nil)

  @cmap = font[:cmap].preferred_table
  if @cmap.nil?
    raise HexaPDF::Error, "No mapping table for Unicode characters found for TTF " \
      "font #{font.full_name}"
  end
  @dict = build_font_dict
  @document.register_listener(:complete_objects, &method(:complete_font_dict))

  @id_to_glyph = {}
  @codepoint_to_glyph = {}
  @encoded_glyphs = {}
end

Instance Attribute Details

#dictObject (readonly)

Returns the PDF font dictionary representing the wrapped font.



117
118
119
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 117

def dict
  @dict
end

#wrapped_fontObject (readonly)

Returns the wrapped TrueType font object.



114
115
116
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 114

def wrapped_font
  @wrapped_font
end

Instance Method Details

#decode_utf8(str) ⇒ Object

Returns an array of glyph objects representing the characters in the UTF-8 encoded string.



173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 173

def decode_utf8(str)
  str.each_codepoint.map do |c|
    @codepoint_to_glyph[c] ||=
      begin
        if (gid = @cmap[c])
          glyph(gid, '' << c)
        else
          @document.config['font.on_missing_glyph'].call('' << c, font_type, @wrapped_font)
        end
      end
  end
end

#encode(glyph) ⇒ Object

Encodes the glyph and returns the code string.



187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 187

def encode(glyph)
  @encoded_glyphs[glyph] ||=
    begin
      if glyph.kind_of?(InvalidGlyph)
        raise HexaPDF::Error, "Glyph for #{glyph.str.inspect} missing"
      end
      if @subsetter
        [@subsetter.use_glyph(glyph.id)].pack('n')
      else
        [glyph.id].pack('n')
      end
    end
end

#font_typeObject

Returns the type of the font, i.e. :TrueType.



141
142
143
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 141

def font_type
  :TrueType
end

#glyph(id, str = nil) ⇒ Object

Returns a Glyph object for the given glyph ID.

The optional argument str should be the string representation of the glyph. Only use it if it is known,

Note: Although this method is public, it should normally not be used by application code!



161
162
163
164
165
166
167
168
169
170
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 161

def glyph(id, str = nil)
  @id_to_glyph[id] ||=
    begin
      if id >= 0 && id < @wrapped_font[:maxp].num_glyphs
        Glyph.new(@wrapped_font, id, str || ('' << (@cmap.gid_to_code(id) || 0xFFFD)))
      else
        @document.config['font.on_missing_glyph'].call("\u{FFFD}", font_type, @wrapped_font)
      end
    end
end

#scaling_factorObject

Returns the scaling factor for converting font units into PDF units.



146
147
148
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 146

def scaling_factor
  @scaling_factor ||= 1000.0 / @wrapped_font[:head].units_per_em
end

#subset?Boolean

Returns true if the wrapped TrueType font will be subset.

Returns:

  • (Boolean)


151
152
153
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 151

def subset?
  !@subsetter.nil?
end