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 PDF2.0 s9.9.1 at the end).

Additionally, TrueType fonts are always embedded.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

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

The optional argument pdf_object can be used to set the PDF font object that this wrapper should be associated with. If no object is set, a suitable one is automatically created.

If subset is true, the font is subset.



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 140

def initialize(document, font, pdf_object: nil, subset: true)
  @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
  @pdf_object = pdf_object || create_pdf_object(document)

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

Instance Attribute Details

#pdf_objectObject (readonly)

Returns the PDF object associated with the wrapper.



132
133
134
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 132

def pdf_object
  @pdf_object
end

#wrapped_fontObject (readonly)

Returns the wrapped TrueType font object.



129
130
131
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 129

def wrapped_font
  @wrapped_font
end

Instance Method Details

#bold?Boolean

Returns true if the font contains bold glyphs.

Returns:

  • (Boolean)


168
169
170
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 168

def bold?
  @wrapped_font.weight > 500
end

#custom_glyph(id, string) ⇒ Object

Returns a custom Glyph object which represents the given string via the given glyph id.

This functionality can be used to associate a single glyph id with multiple, different strings for replacement glyph purposes. When used in such a way, the used glyph id is often 0 which represents the missing glyph.



202
203
204
205
206
207
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 202

def custom_glyph(id, string)
  if id < 0 || id >= @wrapped_font[:maxp].num_glyphs
    raise HexaPDF::Error, "Glyph ID #{id} is invalid for font '#{@wrapped_font.full_name}'"
  end
  Glyph.new(self, id, string)
end

#decode_codepoint(codepoint) ⇒ Object

Returns a glyph object for the given Unicode codepoint.

The configuration option ‘font.on_missing_glyph’ is invoked if no glyph for a given codepoint is available.



220
221
222
223
224
225
226
227
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 220

def decode_codepoint(codepoint)
  @codepoint_to_glyph[codepoint] ||=
    if (gid = @cmap[codepoint])
      glyph(gid, +'' << codepoint)
    else
      @pdf_object.document.config['font.on_missing_glyph'].call(+'' << codepoint, self)
    end
end

#decode_utf8(str) ⇒ Object

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

See #decode_codepoint for details.



212
213
214
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 212

def decode_utf8(str)
  str.codepoints.map! {|c| @codepoint_to_glyph[c] || decode_codepoint(c) }
end

#encode(glyph) ⇒ Object

Encodes the glyph and returns the code string.



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 230

def encode(glyph)
  (@encoded_glyphs[glyph.id] ||=
    begin
      raise HexaPDF::MissingGlyphError.new(glyph) if glyph.kind_of?(InvalidGlyph)
      if @subsetter
        [[@subsetter.use_glyph(glyph.id)].pack('n'), glyph]
      else
        [[glyph.id].pack('n'), glyph]
      end
    end)[0]
end

#font_typeObject

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



158
159
160
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 158

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!



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

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

#italic?Boolean

Returns true if the font contains glyphs with an incline (italic or slant).

Returns:

  • (Boolean)


173
174
175
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 173

def italic?
  @wrapped_font.italic_angle.to_i != 0
end

#scaling_factorObject

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



163
164
165
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 163

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)


178
179
180
# File 'lib/hexapdf/font/true_type_wrapper.rb', line 178

def subset?
  !@subsetter.nil?
end