Summary
cmap format 14 (Unicode Variation Sequences) is parsed into CmapSubtable14 but never consulted during shaping. A base character followed by a variation selector (U+FE00–FE0F, or U+E0100–E01EF as a surrogate pair) always renders the base character's default glyph, so fonts that rely on variation sequences to pick a specific glyph variant (common in CJK, e.g. standardized/IVS forms) render the wrong glyph with no error or warning.
Scope
CmapTable: add a (base, selector) pair lookup against format 14.
TextShaper.MapToGlyphs: look ahead for a following selector and consume the pair into one glyph.
CmapSubsetProcessor: discover and preserve the variation-sequence glyphs and mappings used by the subsetted text, so the embedded PDF font matches what was measured against the full font.
Two related latent bugs found while implementing this: cmap serialization unconditionally dropped format 14 subtables, and CmapSubtable14Deserializer misread multi-selector tables.
Summary
cmap format 14 (Unicode Variation Sequences) is parsed into
CmapSubtable14but never consulted during shaping. A base character followed by a variation selector (U+FE00–FE0F, or U+E0100–E01EF as a surrogate pair) always renders the base character's default glyph, so fonts that rely on variation sequences to pick a specific glyph variant (common in CJK, e.g. standardized/IVS forms) render the wrong glyph with no error or warning.Scope
CmapTable: add a (base, selector) pair lookup against format 14.TextShaper.MapToGlyphs: look ahead for a following selector and consume the pair into one glyph.CmapSubsetProcessor: discover and preserve the variation-sequence glyphs and mappings used by the subsetted text, so the embedded PDF font matches what was measured against the full font.Two related latent bugs found while implementing this: cmap serialization unconditionally dropped format 14 subtables, and
CmapSubtable14Deserializermisread multi-selector tables.