Skip to content

Honour user alternateNumber in GSUB Type 3 substitutions - #371

Merged
blikblum merged 1 commit into
foliojs:masterfrom
lineto:feature/gsub-type3-alternate-number
Oct 23, 2026
Merged

blikblum merged 1 commit into
foliojs:masterfrom
lineto:feature/gsub-type3-alternate-number

Conversation

@lehni

@lehni lehni commented May 20, 2026

Copy link
Copy Markdown
Contributor

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'.

@lehni
lehni force-pushed the feature/gsub-type3-alternate-number branch 2 times, most recently from c1abc1f to 45d36e2 Compare October 21, 2026 22:10
@blikblum

Copy link
Copy Markdown
Member

@lehni please fix the conflicts

@lehni
lehni force-pushed the feature/gsub-type3-alternate-number branch from 45d36e2 to 26b7f74 Compare October 22, 2026 23:29
@lehni

lehni commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

@blikblum Rebased onto master, conflicts resolved.

@blikblum

Copy link
Copy Markdown
Member

I tried to fix conflict manually without success

- 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
@lehni

lehni commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

@blikblum The merge lost the closing lines of the default ignorables tests. I've rebased onto master again instead.

@lehni
lehni force-pushed the feature/gsub-type3-alternate-number branch from a8d1d72 to c7344dc Compare October 23, 2026 04:18
@blikblum
blikblum merged commit d865912 into foliojs:master Oct 23, 2026
3 checks passed
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.

2 participants