class HexaPDF::Font::TrueType::Subsetter

This means in particular that the resulting font file cannot be used outside of the PDF.
composite font.
subsetter implements the functionality needed when embedding a TrueType subset for a
TrueType fonts can be embedded into PDF either as a simple font or as a composite font. This
Subsets a TrueType font in the context of PDF.

def add_glyph_components

Adds the components of compound glyphs to the subset.
def add_glyph_components
  glyf = @font[:glyf]
  @glyph_map.keys.each do |gid|
    next if gid.kind_of?(Symbol)
    glyf[gid].components&.each {|cgid| use_glyph(cgid) }
  end
end

def build_font

Builds the subset font file and returns it as a binary string.
def build_font
  glyf, locations = build_glyf_table
  loca = build_loca_table(locations)
  hmtx = build_hmtx_table
  head = build_head_table(modified: Time.now, loca_type: 1)
  hhea = build_hhea_table(@glyph_map.size)
  maxp = build_maxp_table(@glyph_map.size)
  tables = {
    'head' => head,
    'hhea' => hhea,
    'maxp' => maxp,
    'glyf' => glyf,
    'loca' => loca,
    'hmtx' => hmtx,
  }
  tables['cvt '] = @font[:'cvt '].raw_data if @font[:'cvt ']
  tables['fpgm'] = @font[:fpgm].raw_data if @font[:fpgm]
  tables['prep'] = @font[:prep].raw_data if @font[:prep]
  Builder.build(tables)
end

def build_glyf_table

Builds the glyf table.
def build_glyf_table
  add_glyph_components
  orig_glyf = @font[:glyf]
  table = ''.b
  locations = []
  @glyph_map.each_key do |old_gid|
    glyph = orig_glyf[old_gid.kind_of?(Symbol) ? 0 : old_gid]
    locations << table.size
    data = glyph.raw_data
    if glyph.compound?
      data = data.dup
      glyph.component_offsets.each_with_index do |offset, index|
        data[offset, 2] = [@glyph_map[glyph.components[index]]].pack('n')
      end
    end
    table << data
  end
  locations << table.size
  [table, locations]
end

def build_head_table(modified:, loca_type:)

Builds the head table, adjusting the modification time and location table type.
def build_head_table(modified:, loca_type:)
  data = @font[:head].raw_data
  data[8, 4] = "\0\0\0\0"
  data[28, 8] = [(modified - TrueType::Table::TIME_EPOCH).to_i].pack('q>')
  data[-4, 2] = [loca_type].pack('n')
  data
end

def build_hhea_table(num_of_long_hor_metrics)

Builds the hhea table, adjusting the value of the number of horizontal metrics.
def build_hhea_table(num_of_long_hor_metrics)
  data = @font[:hhea].raw_data
  data[-2, 2] = [num_of_long_hor_metrics].pack('n')
  data
end

def build_hmtx_table

Builds the hmtx table.
def build_hmtx_table
  hmtx = @font[:hmtx]
  data = ''.b
  @glyph_map.each_key do |old_gid|
    metric = hmtx[old_gid.kind_of?(Symbol) ? 0 : old_gid]
    data << [metric.advance_width, metric.left_side_bearing].pack('n2')
  end
  data
end

def build_loca_table(locations)

Builds the loca table given the locations.
def build_loca_table(locations)
  locations.pack('N*')
end

def build_maxp_table(nr_of_glyphs)

Builds the maxp table, adjusting the number of glyphs.
def build_maxp_table(nr_of_glyphs)
  data = @font[:maxp].raw_data
  data[4, 2] = [nr_of_glyphs].pack('n')
  data
end

def initialize(font)

Creates a new Subsetter for the given TrueType Font object.
def initialize(font)
  @font = font
  @glyph_map = {0 => 0}
  @last_id = 0
end

def subset_glyph_id(glyph_id)

subset.
Returns the new subset glyph ID for the given glyph ID, or +nil+ if the glyph isn't
def subset_glyph_id(glyph_id)
  @glyph_map[glyph_id]
end

def use_glyph(glyph_id)

subset glyph ID.
Can be called multiple times with the same glyph ID, always returning the correct new

Includes the glyph with the given ID in the subset and returns the new subset glyph ID.
def use_glyph(glyph_id)
  return @glyph_map[glyph_id] if @glyph_map.key?(glyph_id)
  @last_id += 1
  # Handle codes for ASCII characters \r (13), (, ) (40, 41) and \ (92) specially so that
  # they never appear in the output (PDF serialization would need to escape them)
  if @last_id == 13 || @last_id == 40 || @last_id == 92
    @glyph_map[:"s#{@last_id}"] = @last_id
    if @last_id == 40
      @last_id += 1
      @glyph_map[:"s#{@last_id}"] = @last_id
    end
    @last_id += 1
  end
  @glyph_map[glyph_id] = @last_id
end