Class: HexaPDF::Font::Type1Wrapper

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

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, font, pdf_object: nil, custom_encoding: false) ⇒ Type1Wrapper

Creates a new Type1Wrapper object wrapping the Type1 font.

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 pdf_object is provided, the PDF object’s encoding is used. Otherwise, the WinAnsiEncoding or, for ‘Special’ fonts, the font’s internal encoding is used. The optional argument custom_encoding can be set to true so that a custom encoding is used (only respected if pdf_object is not provided).



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/hexapdf/font/type1_wrapper.rb', line 128

def initialize(document, font, pdf_object: nil, custom_encoding: false)
  @wrapped_font = font
  @pdf_object = pdf_object || create_pdf_object(document)

  if pdf_object
    @encoding = pdf_object.encoding
    @max_code = 255 # Encoding is not modified
  elsif custom_encoding
    @encoding = Encoding::Base.new
    @encoding.code_to_name[32] = :space
    @max_code = 32 # 32 = space
  elsif @wrapped_font.metrics.character_set == 'Special'
    @encoding = @wrapped_font.encoding
    @max_code = 255 # Encoding is not modified
  else
    @encoding = Encoding.for_name(:WinAnsiEncoding)
    @max_code = 255 # Encoding is not modified
  end

  @zapf_dingbats_opt = {zapf_dingbats: (@wrapped_font.font_name == 'ZapfDingbats')}
  @name_to_glyph = {}
  @codepoint_to_glyph = {}
  @encoded_glyphs = {}
end

Instance Attribute Details

#pdf_objectObject (readonly)

Returns the PDF object associated with the wrapper.



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

def pdf_object
  @pdf_object
end

#wrapped_fontObject (readonly)

Returns the wrapped Type1 font object.



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

def wrapped_font
  @wrapped_font
end

Instance Method Details

#bold?Boolean

Returns true if the font contains bold glyphs.

Returns:

  • (Boolean)


164
165
166
# File 'lib/hexapdf/font/type1_wrapper.rb', line 164

def bold?
  @wrapped_font.weight_class > 500
end

#custom_glyph(name, string) ⇒ Object

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

This functionality can be used to associate a single glyph name with multiple, different strings for replacement glyph purposes. When used in such a way, the used glyph name is often :question.



192
193
194
195
196
197
198
# File 'lib/hexapdf/font/type1_wrapper.rb', line 192

def custom_glyph(name, string)
  unless @wrapped_font.metrics.character_metrics.key?(name)
    raise HexaPDF::Error, "Glyph named #{name.inspect} not found in " \
      "font '#{@wrapped_font.full_name}'"
  end
  Glyph.new(self, name, string)
end

#decode_codepoint(codepoint) ⇒ Object

Returns a glyph object for the given Unicode codepoint.

If a Unicode codepoint is not available as glyph object, it is tried to map the codepoint using the font’s internal encoding. This is useful, for example, for the ZapfDingbats font to use ASCII characters for accessing the glyphs.

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



215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/hexapdf/font/type1_wrapper.rb', line 215

def decode_codepoint(codepoint)
  @codepoint_to_glyph[codepoint] ||=
    begin
      name = Encoding::GlyphList.unicode_to_name(+'' << codepoint, **@zapf_dingbats_opt)
      if @wrapped_font.metrics.character_set == 'Special' &&
          (name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
        name = @encoding.name(codepoint)
      end
      name = +"u" << codepoint.to_s(16).rjust(6, '0').upcase if name == :'.notdef'
      glyph(name)
    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.



203
204
205
# File 'lib/hexapdf/font/type1_wrapper.rb', line 203

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.



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/hexapdf/font/type1_wrapper.rb', line 229

def encode(glyph)
  @encoded_glyphs[glyph.name] ||=
    begin
      raise HexaPDF::MissingGlyphError.new(glyph) if glyph.kind_of?(InvalidGlyph)
      code = @encoding.code(glyph.name)
      if code
        code.chr.freeze
      elsif @max_code < 255
        @max_code += 1
        @encoding.code_to_name[@max_code] = glyph.name
        @max_code.chr.freeze
      else
        raise HexaPDF::Error, "Used Type1 encoding has no codepoint for #{glyph.name.inspect}"
      end
    end
end

#font_typeObject

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



154
155
156
# File 'lib/hexapdf/font/type1_wrapper.rb', line 154

def font_type
  :Type1
end

#glyph(name) ⇒ Object

Returns a Glyph object for the given glyph name.



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

def glyph(name)
  @name_to_glyph[name] ||=
    begin
      str = Encoding::GlyphList.name_to_unicode(name, **@zapf_dingbats_opt)
      if @wrapped_font.metrics.character_metrics.key?(name)
        Glyph.new(self, name, str)
      else
        @pdf_object.document.config['font.on_missing_glyph'].call(str, self)
      end
    end
end

#italic?Boolean

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

Returns:

  • (Boolean)


169
170
171
# File 'lib/hexapdf/font/type1_wrapper.rb', line 169

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

#scaling_factorObject

Returns 1 since all Type1 fonts use 1000 units for the em-square.



159
160
161
# File 'lib/hexapdf/font/type1_wrapper.rb', line 159

def scaling_factor
  1
end