class HexaPDF::Font::Type1Wrapper

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

def create_pdf_object(document)

Creates a PDF object representing the wrapped font for the given PDF document.
def create_pdf_object(document)
  fd = document.add({Type: :FontDescriptor,
                     FontName: @wrapped_font.font_name.intern,
                     FontWeight: @wrapped_font.weight_class,
                     FontBBox: @wrapped_font.bounding_box,
                     ItalicAngle: @wrapped_font.italic_angle || 0,
                     Ascent: @wrapped_font.ascender || 0,
                     Descent: @wrapped_font.descender || 0,
                     CapHeight: @wrapped_font.cap_height,
                     XHeight: @wrapped_font.x_height,
                     StemH: @wrapped_font.dominant_horizontal_stem_width,
                     StemV: @wrapped_font.dominant_vertical_stem_width || 0})
  fd.flag(:fixed_pitch) if @wrapped_font.metrics.is_fixed_pitch
  fd.flag(@wrapped_font.metrics.character_set == 'Special' ? :symbolic : :nonsymbolic)
  dict = document.add({Type: :Font, Subtype: :Type1,
                       BaseFont: @wrapped_font.font_name.intern,
                       FontDescriptor: fd})
  dict.font_wrapper = self
  document.register_listener(:complete_objects) do
    min, max = @encoding.code_to_name.keys.minmax
    dict[:FirstChar] = min
    dict[:LastChar] = max
    dict[:Widths] = (min..max).map {|code| glyph(@encoding.name(code)).width }
    if VALID_ENCODING_NAMES.include?(@encoding.encoding_name)
      dict[:Encoding] = @encoding.encoding_name
    elsif @encoding != @wrapped_font.encoding
      differences = [min]
      (min..max).each {|code| differences << @encoding.name(code) }
      dict[:Encoding] = {Differences: differences}
    end
  end
  dict
end

def custom_glyph(name, string)

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

+name+.
Returns a custom Glyph object which represents the given +string+ via the given glyph
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(@wrapped_font, name, string)
end

def decode_utf8(str)

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

Returns an array of glyph objects representing the characters in the UTF-8 encoded string.
def decode_utf8(str)
  str.codepoints.map! do |c|
    @codepoint_to_glyph[c] ||=
      begin
        name = Encoding::GlyphList.unicode_to_name(+'' << c, **@zapf_dingbats_opt)
        if @wrapped_font.metrics.character_set == 'Special' &&
            (name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
          name = @encoding.name(c)
        end
        name = +"u" << c.to_s(16).rjust(6, '0') if name == :'.notdef'
        glyph(name)
      end
  end
end

def encode(glyph)

Encodes the glyph and returns the code string.
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

def font_type

Returns the type of the font, i.e. :Type1.
def font_type
  :Type1
end

def glyph(name)

Returns a Glyph object for the given glyph name.
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(@wrapped_font, name, str)
      else
        @pdf_object.document.config['font.on_missing_glyph'].call(str, self)
      end
    end
end

def initialize(document, font, pdf_object: nil, custom_encoding: false)

respected if +pdf_object+ is not provided).
argument +custom_encoding+ can be set to +true+ so that a custom encoding is used (only
WinAnsiEncoding or, for 'Special' fonts, the font's internal encoding is used. The optional
If +pdf_object+ is provided, the PDF object's encoding is used. Otherwise, the

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

Creates a new Type1Wrapper object wrapping the Type1 font.
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

def scaling_factor

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