Skip to content

Honour user alternateNumber in GSUB Type 3 substitutions#371

Open
lehni wants to merge 1 commit into
foliojs:masterfrom
lineto:feature/gsub-type3-alternate-number
Open

Honour user alternateNumber in GSUB Type 3 substitutions#371
lehni wants to merge 1 commit into
foliojs:masterfrom
lineto:feature/gsub-type3-alternate-number

Conversation

@lehni
Copy link
Copy Markdown

@lehni lehni commented May 20, 2026

fontkit's GSUB Type 3 (Alternate Substitution) hardcodes the alternate index to 0, so user-supplied alternateNumber values (e.g. font.layout(text, { aalt: 2 })) are silently ignored and every aalt/nalt/etc. request resolves to the first alternate. This makes Type 3 features effectively read-only from a caller's perspective.

This PR:

  • Threads the user's original features object through ShapingPlan so processors can read per-feature integer values without losing them to the shaper plan's true/false normalisation.
  • Updates OTLayoutEngine.setup to overlay the user's original values onto the chosen-features map without mutating the caller's input object.
  • GSUBProcessor Type 3 now reads userFeatures[currentFeature] as a 1-based alternate index, falls back to the first alternate when no value is given or the requested index is out of range.

Test: FiraSans's aalt lookup carries multiple alternates per coverage entry. For 'A' (glyph 3) the alternate set is [1078 'ordfeminine', 764 'a.sc']. The added test shapes 'A' with { aalt: true } and { aalt: 2 } and asserts the correct glyph ID for each — matching what HarfBuzz produces for --features='aalt=1' vs --features='aalt=2'.

- Type 3 hardcoded USER_INDEX = 0; `nalt: 2` silently rendered as alt #1
- Thread user features through ShapingPlan so GSUB reads the 1-based index
- Don't mutate caller's features in OTLayoutEngine.setup; overlay instead
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant