Closed THausherr closed 3 months ago
It's unclear how a font processor should handle this: skip the incorrect entry, or really replace the GID with nothing.
While the OTF specification - written by Microsoft - does say that that GSUB2 substitutions should have >0 replacement glyphs, some of Microsoft's own fonts depend on the fact that a zero replacement glyph substitution is used to delete glyphs from the buffer, and both Uniscribe and DirectWrite are written with this in mind.
The OTF spec does not specify precisely how shaping engines should interpret layout rules; the Uniscribe/DWrite are the de facto reference implementations, and most other shaping engines (Harfbuzz, CoreText) follow this behaviour.
So yes, technically this is incorrect; but it's incorrect behaviour which is widely used, implemented by the reference implementations, and by other major shaping engines.
Here's the relevant issue in the spec: https://github.com/MicrosoftDocs/typography-issues/issues/673
Defect Report
Title
Empty GSUB type 2 substitutions in many fonts
Font
NotoSansDevanagariUI-Black
Where the font came from, and when
Site: https://github.com/notofonts/notofonts.github.io/blob/main/fonts/NotoSansDevanagari/full/otf/NotoSansDevanagariUI-Black.otf Date: 2024-5-25 (today)
Font Version
Version 2.004 (I looked in the "name" record of the font)
OS name and version
Application name and version
It was observed by working with Apache PDFBox trunk development.
Issue
A GSUB type 2 subtable replaces a single glyph with more than one glyph. https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-2-multiple-substitution-subtable "Number of glyph IDs in the substituteGlyphIDs array. This must always be greater than 0."
However many noto fonts have subtables with 0 substitute glyphs. An example is subtable 388 of NotoSansDevanagariUI-Black.otf, but there are many others. It would mean that one glyph is to be substituted with 0 glyphs.
While it was observed in fontbox development, it can be reproduced with DTL OTMaster lite 3.7 (and hopefully with whatever font software you use); here's a screenshot of GSUB subtable 387 (correct: GID 280 to be replaced with 209 and 52) and 388 (incorrect: GID 1 to be replaced with nothing)
Expected result: there shouldn't be any empty entries, i.e. the part with GID 1 shouldn't be there, which means that subtable 388 shouldn't be there either.
This bug is rather minor, the ttf specification isn't followed properly. It's unclear how a font processor should handle this: skip the incorrect entry, or really replace the GID with nothing.