Check for nested components
RosaWagner opened this issue · 17 comments
Observed behaviour
Component referring to another component (nested) are not exported correctly for ttf variable format. They take back the coordinates of the original glyph.
Expected behaviour
There should be a check to find any nested components.
Resources and exact process needed to replicate
I used Public Sans at commit uswds/public-sans@0a09945
But you can reproduce it with any font which have nested components (typically ohorn/uhorn with another accent)
This may be a more severe issue than just something messing up Samsa.
At arrowtype/recursive#412, I have described issues that occur when printing static TTFs with many printers. In summary: PostScript-based printers really mess up nested components in TTF fonts. This includes even high-end setups used for offset printing. One example of where things go wrong in current Recursive TTFs:
(There are more examples in the issue.)
There are two possible culprits:
- A problem in ttfautohint, or in how PostScript handles the hints from it
- A fundamental problem with PostScript’s handling of TTF nested components
Worse, printers that have PostScript installed apparently never update that software.
So, this check plus a script that un-nests components are probably relatively high-priority, if Google Fonts wants to give people any confidence in using the library for more than just web design. Not all of the alignment problems with TTFs & PostScript would be solved by this – it also messes up the positioning of glyph substituted via stylistic sets – but it seems that it would solve the majority of them.
There's a ufo2ft filter to unnest composites automatically. Insert the following into your UFO's lib.plist:
<key>com.github.googlei18n.ufo2ft.filters</key>
<array>
<dict>
<key>name</key>
<string>flattenComponents</string>
<key>pre</key>
<integer>1</integer>
</dict>
</array>
It's actually been in there for decades, but we don't have time to write docs so all the filters are secret.
quite depressing that in 2020 we can't still have nested glyf components
It's actually been in there for decades, but we don't have time to write docs so all the filters are secret.
I could be a good start to just drop some general lines about the existence of this mechanism and where to find the available filters and how to generally access and configure them.
I started something at googlefonts/ufo2ft#286 last century but died before I could finish the job.
The stems of all .py files in https://github.com/googlefonts/ufo2ft/tree/master/Lib/ufo2ft/filters can be used as filters.
@madig: Would it be worth making FlattenComponents
the default instead of DecomposeComponents
?
Where?
ufo2ft
Where in ufo2ft? No idea what you're talking about.
He means as default filter in the ufo2ft.preProcessor. I would rather not do that. We can make it easier for users to specify that, if a custom filter in the lib.plist is too obscure. E.g. we can add a new option to ufo2ft.compileTTF function and even add a CLI flag to fontmake. But changing the default is not a good idea. There may be legitimate use-cases that may prefer to keep the current beaviour that allows for nested components.
Should we add a --filters
argument to fontmake instead or additionally?
Can’t we just have a single option which does this?
If we aren’t prepared to make creating non-broken fonts the default, we should at least make it as easy as possible.
Can’t we just have a single option which does this?
What I’m suggesting as an alternative or as an additional option is to have a --filter
argument to fontmake that works like --feature-writer
does.
So one could do:
fontmake -m DS.designspace --filter flattenComponents
This would also work for propagateAnchors, decomposeTransformedComponents, or any custom filter.
Note to others here (and maybe this should be included in the check rationale, etc):
At least for Recursive (and another project, Name Sans) it is essential to not only flatten components but to first also decompose transformed components. Otherwise, accents like the caron (which is a 180° rotated circumflex) get really misaligned.
In a lib.plist, that looks like this:
<key>com.github.googlei18n.ufo2ft.filters</key>
<array>
<dict>
<key>name</key>
<string>decomposeTransformedComponents</string>
<key>pre</key>
<integer>1</integer>
</dict>
<dict>
<key>name</key>
<string>flattenComponents</string>
<key>pre</key>
<integer>1</integer>
</dict>
</array>
See arrowtype/recursive#412 for details.