Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skipExportGlyphs should be later in the pipeline #692

Open
bobh0303 opened this issue Jan 11, 2023 · 4 comments
Open

skipExportGlyphs should be later in the pipeline #692

bobh0303 opened this issue Jan 11, 2023 · 4 comments

Comments

@bobh0303
Copy link

I suggest that skipExportGlyphs should be processed later in the pipeline, at least later than flattenComponents (which is already after decomposeComponents). The current implementation results in unnecessary font bloat.

Consider this common situation: an encoded composite glyph references a component glyph that is itself a composite. Here is a concrete example (with non-relevant detail omitted) from Arabic, but it happens in Latin and other scripts as well:

<glyph name="qaf-ar" ...>
  <outline>
    <component base="qafDotless-ar"/>
    <component base="_dot2h" ... />
  </outline>
</glyph>

<glyph name="_dot2h" …>
  <outline>
    <component base="_dot1" .../>
    <component base="_dot1" .../>
  </outline>
</glyph>

<glyph name="_dot1" …>
  <outline>
    <contour>
     ...
    </contour>
  </outline>
</glyph>

We have _dot2h used as a component (of qaf-ar) but is itself a composite glyph consisting of two references to _dot1.

GoogleFonts team requires this to be flattened, so we include the flattenComponents filter which will then flatten the qaf-ar glyph. The resulting glyph, if represented in UFO-speak, would be:

<glyph name="qaf-ar" ...>
  <outline>
    <component base="behDotless-ar"/>
    <component base="_dot1" .../>
    <component base="_dot1" .../>
  </outline>
</glyph>

This was confirmed by building the TTF and dumping with ttx, which yields:

    <TTGlyph name="qaf-ar" .../>
      <component glyphName="qafDotless-ar" .../>
      <component glyphName="_dot1" ... />
      <component glyphName="_dot1" .../>
    </TTGlyph>

Now, of course, the _dot2h is no longer used — it is not encoded and all other composites referencing it would similarly have been flattened. As a result, fontBakery legitimately complains that the _dot2h glyph is unreachable.

It would be nice to now be able to utilize the skipExportGlyphs mechanism to remove the unreachable _dot2h from the resulting font and quiet the fontBakery warning.

However, since ufo2ft processes skipExportGlyphs first, and at this point qaf-ar still references _dot2h, adding _dot2h to public.skipExportGlyphs will cause the qaf-ar glyph to be [needlessly] fully decomposed into a contour glyph.

Multiplying this over all the glyphs in the font that get similarly decomposed results in a significant increase in the glyph table size. In the Lateef project, adding just _dot2h to public.skipExportGlyphs increased the glyph table by 14 kb.

If the skipExportGlyphs process were run later in the pipeline, at least after flattenComponents, then it could have the desired effect of making the font smaller.

@bobh0303
Copy link
Author

Any thoughts on this (from devs or users)?

@anthrotype
Copy link
Member

https://unifiedfontobject.org/versions/ufo3/lib.plist/#publicskipexportglyphs

the ufo spec says about public.skipExportGlyphs that the UFO compiler is responsible to "decompose the listed glyphs everywhere they are used as components", and that's what ufo2ft is doing. This is done in the preprocessor before any other filter is processed, when collecting the glyphs from a layer. It'd be difficult to untangle at this stage.

Fontmake also supports running the fonttools subsetter at the end of the build, it does that automatically when some glyphsLib specific lib keys are present, but I believe can be activated regardless if you pass the CLI option --subset.
Can you please try to see if that works for you?

https://github.com/googlefonts/fontmake/blob/eef7c40a83cbdbf1317980169fcdc36ebb5c9a12/Lib/fontmake/font_project.py#L667-L673
https://github.com/googlefonts/fontmake/blob/eef7c40a83cbdbf1317980169fcdc36ebb5c9a12/Lib/fontmake/font_project.py#L720-L791

@anthrotype
Copy link
Member

the fonttools subsetter should get rid of the orphaned glyphs if they are no longer referenced as components and have not direct cmap mappings and are not reachable via GSUB rules

@bobh0303
Copy link
Author

Thanks for your replies, Cosimo,

At this point neither fontmake nor the subsetter are in our regular workflow.

the ufo spec says about public.skipExportGlyphs that the UFO compiler is responsible to "decompose the listed glyphs everywhere they are used as components", and that's what ufo2ft is doing.

I agree, but it doesn't say that has to be done first. Seems pretty clear that ufo2ft would still be in compliance with the UFO spec if it ran flattenComponents process first, then the process required by public.skipExportGlyps, and finally all other processes (including "compilation", i.e., conversion to ttf). And the result would be a smaller font.

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

No branches or pull requests

2 participants