notofonts / devanagari

Noto Devanagari
SIL Open Font License 1.1
1 stars 2 forks source link

Empty GSUB type 2 substitutions in many fonts #41

Closed THausherr closed 3 months ago

THausherr commented 3 months ago

Defect Report

Noto fonts can be obtained from https://notofonts.github.io/ If you find a problem with a released font, then please use this template to file a defect report. Before filing your report, please check if the issue has been fixed in the latest development build. You can get development builds by finding the font family on https://notofonts.github.io/ and following the link to "Development builds".

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

This is especially important if the font came pre-installed. Windows 10 10.0.19045.4412

Application name and version

If the issue is observed using a specific app.

It was observed by working with Apache PDFBox trunk development.

Issue

Summarize the issue briefly -- one paragraph preferred

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) grafik

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.

simoncozens commented 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