Module: Fontisan::Ufo::Compile::Gpos

Defined in:
lib/fontisan/ufo/compile/gpos.rb

Overview

Builds the OpenType GPOS (Glyph Positioning) table from UFO kerning data. Emits a minimal but valid GPOS with:

- ScriptList: DFLT script, default language system
- FeatureList: `kern` feature (feature tag "kern")
- LookupList: one PairPos lookup (format 1, individual pairs)

Each kerning pair from the UFO source becomes a PairPosRecord with an x-advance adjustment on the first glyph.

Constant Summary collapse

FEATURE_KERN =
"kern"
SCRIPT_DFLT =
"DFLT"
LANGSYS_DEFAULT =
0
VALUE_X_PLACEMENT =

ValueFormat flags (which fields are present in a ValueRecord)

0x0001
VALUE_Y_PLACEMENT =
0x0002
VALUE_X_ADVANCE =
0x0004
VALUE_Y_ADVANCE =
0x0008

Class Method Summary collapse

Class Method Details

.build(font, glyphs:) ⇒ String?

Returns GPOS table bytes, or nil if no kerning.

Parameters:

Returns:

  • (String, nil)

    GPOS table bytes, or nil if no kerning



33
34
35
36
37
38
# File 'lib/fontisan/ufo/compile/gpos.rb', line 33

def self.build(font, glyphs:)
  pairs = collect_kerning_pairs(font, glyphs)
  return nil if pairs.empty?

  build_gpos_table(pairs)
end

.collect_kerning_pairs(font, glyphs) ⇒ Array<[Integer, Integer, Integer]>

Collect kerning pairs from the UFO model. Each pair is (gid1, gid2, x_advance_delta).

Returns:

  • (Array<[Integer, Integer, Integer]>)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/fontisan/ufo/compile/gpos.rb', line 45

def self.collect_kerning_pairs(font, glyphs)
  name_to_gid = {}
  glyphs.each_with_index { |g, gid| name_to_gid[g.name] = gid }

  pairs = []
  font.kerning.each_pair do |key, value|
    # UFO kerning key is "glyph1 glyph2" or a class name.
    # We only handle individual glyph pairs (not classes).
    names = key.split
    next unless names.size == 2

    gid1 = name_to_gid[names[0]]
    gid2 = name_to_gid[names[1]]
    next unless gid1 && gid2

    pairs << [gid1, gid2, value.to_i]
  end

  pairs.sort_by { |a| [a[0], a[1]] }
end