adobe-type-tools / cffsubr

Standalone CFF subroutinizer based on AFDKO tx
Apache License 2.0
8 stars 8 forks source link

Should this subroutinizer be run before or after hinting? #15

Open alerque opened 4 years ago

alerque commented 4 years ago

Not too long ago @khaledhosny passed on maintenance of the Libertinus font family to me. I've been working on automating the PR review and release process to work automatically through CI jobs. In messing with the build system I inadvertently changed the order of the build process from taking the built OTF file → hinting it with psautohint → running this subroutinizer and reversed the last two steps so that this subroutinizer was run, then the hinter.

The result was a wildly different font file by the numbers (diffing the TTX dumps took longer than building the font!). Everything seems to be in a different order internally and the filesize is a lot bigger overall, but oddly enough I am unable to tell the difference visually. I've typeset large chunks of data in both with zero overall difference in metrics, and done some image comparison of the rasterization it a couple apps and can't find any difference. It's entirely possible that's because I am not on a system where the kind of hinting differences that might show up would be evidenced, but at first blush at least the fonts appear the same.

Of course I can go back to the original order and almost certainly there is a good reason for it, but I can't find it documented anywhere. What, if any, is the reason for hinting before running this as opposed to hinting being the latter step?

Perhaps where in the build sequence to put this should also be part of #2.

anthrotype commented 4 years ago

I believe the subroutinizer should be run after the autohinter, as the latter has to desubroutinize the charstrings to be able to do its job. Can anybody more knowledgeable of CFF confirm? /cc @khaledhosny @madig @josh-hadley

madig commented 4 years ago

Subroutinizer must run after autohinting because psautohint just leaves everything behind uncompressed. This implies that subroutinizing somewhere in the pipeline before the autohinter is wasted effort :o

alerque commented 4 years ago

Thanks @anthrotype and @madig, that makes perfect sense.

My only sugestion would be to drop a note about this in the usage documentation. There might even be other things to note that it comes before or after, for example if one were to run gftools fix-hinting or some of the other normalization and cleanup functions, it would be useful to document somewhere what order these should be in.

anthrotype commented 4 years ago

yes, documentation is always good to have..

Maybe one source of confusion is that ufo2ft now supports cffsubr as alternative subroutinizer, so one can run cffsubr as part of fontmake pipeline; but psautohint is not integrated in neither ufo2ft nor fontmake, so if one wants to make a hinted CFF font, one has to create an un-subroutinized font with fontmake, then run psautohint on it and finally run the cffsubr on it.

Ideally the auto-hinting stage should be integrated in ufo2ft (as part of the post-processing stage) before the subroutinization happens.

alerque commented 4 years ago

All true, but I'm not coming from UFO on this project so ufo2ft isn't 100% relevant ;-) The principle still applies though. Except for the bit where it is going through UFO on the way from SFD to OTF.

Honestly my personal opinion in that granular tools are better so that end users of the tooling have more choices about how they assemble them, but that all in one tooling that handles the whole build chain by default is also useful. Hence why I am building fontship ... as the build tool that glues all the other tooling together. From the standpoint of working on that, having each stage itemized is much more flexible. For example I can currently change hinting parameters and rebuild fonts without starting from scratch, you only have to rebuild the steps after the one you are working on. Also you can skip steps (permanently or temporarily) for some workflows easier if tools like ufo2ft don't try to take over the whole end-2-end build process.

Hence having standalone projects like this one is great. If all you have is monolithic projects (i.e. psautomint only being built into AFDKO rather than being a standalone tool) then you can't itemize well, but if you have standalone projects with umbrellas that collect them all into a complete systems everybody wins.

anthrotype commented 4 years ago

Yes, i also agree with the unix philosopy of separate tools each making one thing good. By the way, fontship looks like a cool project, I'll check it out 👍

khaledhosny commented 4 years ago

Adobe’s auto hinter is rather special. Its core is a C library that don’t work with font data directly, it only understands its own textual representation of PostScript outlines and works with single glyph at a time, so no subroutines or any other form of outline sharing. The Python code decodes CFF glyphs to this textual representation and back, desubroutinizing everything in the process. So subroutinization naturally needs to be done before it.

If I were integrating psautohint into ufo2ft I’d do it even before building the CFF table, because it is just waste if the tool will then have to decode it and encode it again, and instead generate the textual glyph representation it needs from the UFO glyphs, hint, and build CFF glyphs from the result.

anthrotype commented 4 years ago

Thanks Khaled for the suggestion.

generate the textual glyph representation it needs from the UFO glyphs, hint, and build CFF glyphs from the result.

Does psautohint support generating such textual glyph representation from UFO glyphs already? I haven't looked into it yet.

khaledhosny commented 4 years ago

Does psautohint support generating such textual glyph representation from UFO glyphs already? I haven't looked into it yet.

Yes, it is does. You can autohing UFO though the output is only understood by AFDKO, but you don’t have to use the output in UFO, you should be able to able to generate CFF directly from it (there is code for this as well).