Class: Fontisan::Tables::Cff2::FdSelect

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/tables/cff2/fd_select.rb

Overview

Builds the FDSelect subtable for CFF2, mapping glyph IDs to Font DICT indices.

Three formats:

0 — flat array: one byte per glyph
3 — range-based (compact for clustered FDs, ≤65,534 glyphs)
4 — range-based with uint32 (for >65,534 glyphs)

For single-FD fonts (all glyphs share one Font DICT), FDSelect is omitted entirely — the CFF2 Top DICT's FontDICTSelectOffset is left unset.

Class Method Summary collapse

Class Method Details

.build(assignments) ⇒ String

Returns FDSelect bytes in the most compact format.

Parameters:

  • assignments (Array<Integer>)

    FD index per glyph (length = numGlyphs)

Returns:

  • (String)

    FDSelect bytes in the most compact format



95
96
97
98
99
# File 'lib/fontisan/tables/cff2/fd_select.rb', line 95

def self.build(assignments)
  return [0].pack("C").to_s + "".b if assignments.empty?

  format0_bytes(assignments)
end

.format0_bytes(assignments) ⇒ Object

Format 0: simple byte array. Best for random FD assignments. uint8 format (= 0) uint8 fontDICTIDs



104
105
106
# File 'lib/fontisan/tables/cff2/fd_select.rb', line 104

def self.format0_bytes(assignments)
  ([0] + assignments).pack("C*")
end

.format3_bytes(assignments) ⇒ Object

Format 3: range-based. Best for clustered FD assignments. uint8 format (= 3) uint16 numRanges Range3: { uint16 first, uint8 fontDICTID } uint16 sentinel (= numGlyphs)



113
114
115
116
117
118
119
120
121
# File 'lib/fontisan/tables/cff2/fd_select.rb', line 113

def self.format3_bytes(assignments)
  ranges = build_ranges(assignments)

  io = +""
  io << [3, ranges.size].pack("Cn")
  ranges.each { |first, fd| io << [first, fd].pack("nC") }
  io << [assignments.size].pack("n")
  io
end

.read(raw_data, offset, num_glyphs) ⇒ Array<Integer>

Read an FDSelect subtable and return the flat FD-index array (one entry per glyph).

Parameters:

  • raw_data (String)

    full CFF2 table bytes

  • offset (Integer)

    byte offset of the FDSelect

  • num_glyphs (Integer)

    glyph count (from maxp)

Returns:

  • (Array<Integer>)

    FD index per glyph



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/fontisan/tables/cff2/fd_select.rb', line 29

def self.read(raw_data, offset, num_glyphs)
  io = StringIO.new(raw_data)
  io.seek(offset)
  format = io.read(1).unpack1("C")

  case format
  when 0 then read_format0(io, num_glyphs)
  when 3 then read_format3(io, num_glyphs)
  when 4 then read_format4(io, num_glyphs)
  else
    raise CorruptedTableError, "unsupported FDSelect format: #{format}"
  end
end