Open arrowtype opened 4 years ago
It may be helpful to show specific TTX diffs of fonts. Not all the styles are the same, but some are. So, using fdiff, here are the most important diffs between the official statics & the Google Fonts generated statics, comparing
RecursiveSansLnrSt-Black.ttf
("before", red lines)Recursive-Black-CASL=0-CRSV=0-MONO=0-slnt=0.ttf
("after", green lines)I have reduced the diff to focus on the only the tables which I believe are likely to cause problems for users, and placed these into detail dropdowns to hopefully keep this issue readable.
This excludes hinting, which the official statics have but the generated statics lack. It is a lot of data which makes it sensible to exclude in webfonts and from this diff, but that shouldn’t really matter to desktop font users.
OS/2
(Click to expand)Significant known diff issues:
name
(Click to expand)Significant known issues:
head
(Click to expand)Possibly significant diffs:
xMin yMin xMax yMax
The generated instance keep the STAT
table from the variable font, which I previously found to cause issues for static fonts on Windows in VS Code
There may be other important diffs that I am unaware of, but these are things I know or suspect to cause problems.
Hi Stephen, thanks for this extensive study! I don't give my teams fonts from https://fonts.google.com/, I take them directly here, and with good reason I think.
STAT table
The generated instance keep the
STAT
table from the variable font, which I previously found to cause issues for static fonts on Windows in VS Code
The presence of a STAT table also poses problems for MS Office for Mac. https://github.com/clauseggers/Playfair-Display/issues/24, for example.
Thanks for the detailed report. I believe it is possible for the static fonts instantiated from the variable font to work as well as the thoughtfully-produced static fonts available from upstream, and these diffs will be helpful at determining how fontTools can be used to achieve this.
To explain the differences highlithed above by @thundernixon between the official static fonts & the Google Fonts generated static fonts, one needs to understand how each set is generated by fontmake.
The static fonts are interpolated at the source UFO level: i.e. instance UFOs are first generated from the master UFOs + .designspace (by fontmake.instantiator). Then, instance-specific metadata like the ones defined in Glyphs.app custom parameters (e.g., panose, unicode ranges, OS/2 useTypoMetrics, etc.) are applied to each instance UFOs, and finally the UFOs are converted to TTF, with their own distinct OS/2, name, head, etc. tables.
The Google Fonts generated static fonts as included in the downloadable .zip files are instantiated from the variable font built from the same set of master UFOs and .designspace used earlier to generate the static fonts. In the VF build process we first generate a set of master TTFs (one per master UFO) with interpolatable outlines (i.e. no overlaps removed), then use fontTools.varLib with these master TTFs and the same .designspace source to compute the deltas and store them in the variation tables. The new VF starts out as a copy of the default or neutral master TTF plus the the new variation tables added to it. Now, among the tables that don't change in a VF and are simply copied from the default master are OS/2, head and name table.
Finally, when the GF instances are generated from a VF (using fontTools.varLib.instancer module), the deltas from each variation tables are computed and applied to the default tables, and the variation tables removed; however, all the non-variable metadata stay as it was in the VF, i.e. same as was the default master TTF.
Also note that the fonttools instancer currently only sets the OS/2 weight/width class and and post.italicAngle from wght, wdth and slnt respectively, but does not modify the style-linking flags in head and OS/2 (https://github.com/fonttools/fonttools/issues/1264), nor modifies the name table (https://github.com/fonttools/fonttools/issues/1704).
For that at GF we internally run some other touch-ups to the thus generated instances: namely we set OS/2 fsSelection and head.macStyle bold bit if wght=700, and enable the italic bit if the instance's ital
axis position is 1.0. We also run a tool called fix_name_table that given the family name and the axis position of an instance, it uses our Axis Registry where metadata for each axis in our API is defined to update the instance style names. At the moment that tool only supports wght, wdth and ital axes, and ignores other axes (which is why Recursive style names appear incorrect and duplicated), but we are working on fixing that.
With that background, I'll now try to comment on each tables' diffs individually. I already touched upon a current limitation in our tooling that explain the differences in the name table.
the panose values you see in the GF statics is the one from the default master TTF, copied to the VF and from there to all the generated instances. Note I said "master", not the "instance" that is at the same location as the default master (usually called Regular). In the official static fonts the panose values are individually set on each instance. In Glyphs.app these values are usually set in the Instances panel as custom parameters, which are only applied in the static build pipeline, not the VF one. The master TTF used to build the VF does not get these values, hence why you see them all zeros. Even if you could set these different panose values on the individual masters (I'm not sure you can), there wouldn't be a place to store them in the VF. Panose simply does not vary (unlike other font-wide metadata defined in MVAR table). I don't know how relevant Panose is nowadays, but if we really cared to support it in the VF-generated instances, we would need to apply some sort of post-processing (same like we do for name table).
same thing for unicode ranges, they are those from the master TTF, instead of the instances. I believe Glyphs.app should let you set these at a fond-wide level (in the Font tab) so that they apply to all masters and instances. Unless the cmap coverage changes between instances (which I don't think it's the case here).
About fsSelection
, Stephen spotted an actual bug there: the bit 6 flag ("Regular") which should only be set once in a family, is kept for all our generated instances. This is also probably inherited from the VF, and in turn, from the default master (usually but not always a "Regular"). An exception is the wght=700 instance, because I see that in our fix_name_table.py internal script we explicitly un-set the bit 6 when we set the "Bold" bit. Apparently we forgot to also unset the bit 6 for all the non-Regular, non-Bold and non-Italic instances.
Bit 8 also gets unset, indicating that this isn’t a WWS family
Again if we want the VF and thus the instances generated from it to be flagged as WWS, we need to make sure the default master from which the VF is generated to be flagged as such. I suspect that in Recursive only the invidual instances have the corresponding custom parameter for WWS in the .glyphs source. We should try to copy that parameter to the font panel so that it affects all the masters/instances. Note that even if inside Glyhps.app a custom parameter appears as greyed out (to indicate that it is unsupported for the current font/master/instance panel), fontmake (via glyphsLib) will happily apply it nonetheless.
modified box values xMin yMin xMax yMax indexToLocFormat changed
this is computed automatically, you can ignore
flags
the bit 1 (the second starting from the right) is always recomputed by fonttools. It should be correct in the generated instance. Not sure about the bit 2 (third from the right) "Instructions may depend on point size", what tool set that and how. Probably again something that is set by some custom parameter and inherited along by master TTF => VF => generated instance.
The fontTools instancer keeps the VF's STAT table DesignAxes, and prunes AxisValues that are out of range and keep only those that are at the same position as the instance. Initially the instancer (formerly known as mutator) was dropping the STAT table as a whole for full static instances, but we changed it to keep the original STAT design axes as the table is supposed to be a superset of fvar and describes relations between members of a family, variable and not, see https://github.com/fonttools/fonttools/pull/2049#issuecomment-677763545 It would be interesting to investigate why the STAT table as pruned by the fonttools instancer in the GF generated instances was producing the issues reported in https://github.com/arrowtype/recursive/issues/336. Dropping STAT from the GF generated instances could be a temporary solution until we understand why that's the case.
A user wrote in,
Hi I recently downloaded Crimson font family for my work as I recently got a new laptop. As I go to use the fonts in programs such as microsoft word or acrobat adobe and only "Crimson Text" and "Crimson Text SemiBold" appear while I believe there should be 6 fonts in the font list. Can you assist in explaining why this might be? On my previous laptop, all 6 fonts were listed in the program font lists
I guess this is related to this issue.
@RosaWagner I've send you some private fonts to preview how the GF API engineering team are planning to resolve this, please take a look and post any suggestions about how they should be different, and I will do the same :)
I’ve noticed that Inter statics in the Salma ZIPs are missing Italic fonts, even though the variable font includes both wght & slnt axes.
This is probably due to Inter lacking a proper STAT table.
Current STAT table of Inter (lacks entries for weight locations and for Roman/Italic locations:
<STAT>
<Version value="0x00010001"/>
<DesignAxisRecordSize value="8"/>
<!-- DesignAxisCount=2 -->
<DesignAxisRecord>
<Axis index="0">
<AxisTag value="wght"/>
<AxisNameID value="270"/> <!-- Weight -->
<AxisOrdering value="0"/>
</Axis>
<Axis index="1">
<AxisTag value="slnt"/>
<AxisNameID value="271"/> <!-- Slant -->
<AxisOrdering value="1"/>
</Axis>
</DesignAxisRecord>
<!-- AxisValueCount=0 -->
<ElidedFallbackNameID value="2"/> <!-- Regular -->
</STAT>
Just took a look at Salma's output.
The font nametable's LGTM. They use the typo family name and typo subfamilyname correctly.
My only criticism is the filenames. They currently include the axis tags e.g Recursive~CRSV_Cursive-SemiBold.ttf
, Cabin~wdth_SemiCondensed-Bold.ttf
. I prefer them without, Recursive-CursiveSemiBold.ttf
, Cabin-SemiCondensedBold.ttf
.
@RosaWagner also pointed out that nameID 25 may be redundant.
I'm wondering if this update can handle multilingual nameRecords?
The font nametable's LGTM
My only criticism is the filenames. They currently include the axis tags
In this case, if the same style name is used in 3 axes, and only 2 are used, which 2 are used will be ambiguous, and the 3 different pairs will all look the same.
@RosaWagner also pointed out that nameID 25 may be redundant.
Yes, that isn't needed in statics.
I'm wondering if this update can handle multilingual nameRecords?
These should be stripped or handled the same way. We haven't got fontbakery checks for those, so if they are included, its by the grace of the upstream, and so probably dropping them and filing a tech debt issue to go back in and fix them all up across the library would be good.
This should now be fixed, please comment if not
This should now be fixed, please comment if not
Hi @davelab6
I downloaded Inter on https://fonts.google.com/specimen/Inter today and I tested it in Microsoft Word 365 for Mac, version 16.46 (February 2021 update).
First test:
The fonts have panose.bWeight
wrong (all at 5, corresponding to the "Book" weight), and fsSelection
bit 6 is enabled for all weights except Bold (bit 6 = Regular weight, so only Bold and Regular have a correct fsSelection
).
The fonts have a dummy STAT
table too.
In a comment above, @anthrotype wrote:
About
fsSelection
, Stephen spotted an actual bug there: the bit 6 flag ("Regular") which should only be set once in a family, is kept for all our generated instances. This is also probably inherited from the VF, and in turn, from the default master (usually but not always a "Regular"). An exception is the wght=700 instance, because I see that in our fix_name_table.py internal script we explicitly un-set the bit 6 when we set the "Bold" bit. Apparently we forgot to also unset the bit 6 for all the non-Regular, non-Bold and non-Italic instances.
Yep. Still forgotten.
Second test, with panose.bWeight
and fsSelection
corrected:
Third test, with panose.bWeight
and fsSelection
corrected, and STAT
table removed:
Like I said in my August 2020 comment, the mere presence of a STAT
table causes problems for MS Office for Mac (although the February 2021 update has improved compatibility with VFs, Word remains very demanding on the relationship between the STAT
table and the fvar
table, which doesn't apply here: no fvar
table). Remove the dummy STAT
table: problems gone.
I should point out that before each of my tests with a new version of the fonts, I emptied the contents of the following folders:
@davelab6 please reopen this (I somehow can't)
I don't think panose is relevant here, but incorrect fsSelection and incomplete STAT definitely are. We need to investigate whether our internal tools are doing the right thing. fsSelection bit 6 (Regular) should only be set once within each group of "R/I/B/BI" fonts sharing the same legacy familyName (nameID=1). If STAT table in the VF is a "dummy" (only has DesignAxes but no AxisValue records, like those fontmake generates to appease some browsers), then when creating static instances we need to drop STAT altogether. The fonttools instancer will keep it (it only drops AxisValues that falls outside the requested partial instance).
@anthrotype could you by any chance upload the corrected Inter font files here till the issue is fixed upstream?
Nevermind, found the correct files in the Inter project repo!
Nobody is assigned to this?
I just ran into this bug again today when I installed the Space Grotesk static files from the zip archive downloaded from https://fonts.google.com/specimen/Space+Grotesk.
Because Space Grotesk doesn't have a SemiBold instance defined in the variable font (issue #3411), and the tool that generates the static files still generates a file every 100 weight units, while leaving a minimal STAT
table, the static version of Space Grotesk Semibold ends up with a STAT
table that says "Weight: Regular".
MS Office for Mac reads this, and concludes that Space Grotesk Semibold is "Space Grotesk Regular", which means that we end up with two "Space Grotesk Regular" (the real one and the SemiBold).
The static fonts for Recursive that are available via the "Download Family" function of the Recursive specimen on Google Fonts have several issues that make them very unuseful in most contexts.
This is a particular problem because many designers would be likely to use static fonts to design a website or app before then using Google Fonts to provide the fonts on the web. And, many popular design tools currently work best with static fonts – exporting variable fonts to PDFs is flaky, and variable fonts aren’t yet supported at all in Figma.
Until this can be resolved, I propose that we replace the current, auto-generated fonts with the statics available from the official Recursive releases. I know this approach may not work for every family, but the Recursive statics have been specifically engineered by Ben Kiel, a type engineer with years of experience, so it would be worth making an exception to use the higher-quality fonts until the auto-generated instances can perform as well.
Issues include
Filenames
Filenames are confusing. They should do something to include the instance names, such as
RecursiveMonoCslSt-BlkItalic.otf
(an abbreviated form used in the Recursive releases – possibly, it would be even better with less abbreviation). Instead, the downloads from Google Fonts specify the weight first, then axis values, which are hard to understand without a fairly deep knowledge of the font, such asRecursive-Black-CASL=0-CRSV=1-MONO=0-slnt=0.ttf
.Font style sorting & availability
General disruption of design intent
Incorrect & Limited styles
Solutions
fvar
table.I know it takes a lot to make a service as complex as Google Fonts, and I know things like this are inevitable. But, I’m hoping it can be resolved relatively quickly, as the main solution is pretty simple. Let me know if you need any further info. Thanks!