-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
STAT table errors in variable fonts #2391
Comments
Hi, I tested all the VF of this repo, here are the results:
Edit: Changa (PR #3667) The issues can be summarized as follows:
|
What a great report, @thlinard! |
To optimize fixes for the above issues, it may be helpful to look at the STAT tables from the Source variable fonts: Source Serif, Source Sans, Source Code by @adobe-fonts. These define all the named Weights using Format 2, which includes not only a nominal value but also a range. Using ranges, STAT axisValue records can cover an entire axis with meaningful names. Such ranges could be automatically generated for the Google VFs, and will perhaps help the fonts perform better in a wider range of apps. The following table shows the AxisValues for the Weight designAxis in SourceSerifVariable-Roman.ttf.
Also worth considering and, as the table shows, implemented in the Source* fonts, is the use of Format 3 axisValues for an additional elidable Regular (400) record in Weight that declares Bold (700) as stylistically related. Finally, it would be good to represent the
|
Btw, Source Serif, Source Sans and Source Code are in very old versions here:
|
Our STAT setups work in MS Word and All OS X Pages, Slide etc seem ok. Our setup was made before Indesign supported VFs. @thlinard Thanks for this but I'm questioning your analysis. If I just pick Rosario Italic nameID 258 shouldn't be "Regular". NameID 258 clearly points to the Italic instance as referenced by the fvar table. Your point about We found the STAT to be a bit of a nightmare. Microsoft applications currently don't support STAT v2 which means Office apps cannot support multiple axes vfs yet. I also question whether Indesign supports vfs correctly? I don't have Indesign on my current machine so if someone could test Source Sans VF I'd be very happy. Great work from both of you and thank you. Our approach has been to push variable fonts out before applications have supported them. We'll definitely revisit this issue since it seems applications support is better |
Hi @m4rc1e You're right to question my analysis. 😀 Let's take your example, with Rosario Italic.
and certainly not to An AxisValue is defined for the Italic axis:
So, in this configuration, you put the name "Italic" in the Weight axis, while "Italic" is already in the Italic axis. When the name is composed, you get: This is for theory. In practice, my Word 2019 for macOS is unable to manage a VF, so I tested with the Apple and Adobe applications (InDesign 2020). In particular I tried Playfair Display, so obviously wrong: no duplicate appeared. So two hypotheses:
Tests with ttx and fake namerecords showed me that the second hypothesis was the right one. So, I would rephrase the issue 2 as follows:
|
Thanks for your testing and response. I'm currently wrapping my head around the following issue. I'll try and work on both of these at the same time since they're related. We'll try our best to make our fonts comply to the MS spec but we cannot guarantee the fonts will work correctly in all apps. As you've witnessed it is currently a free for all, hence why we supply static fonts for app use. |
Yes, very interesting discussion, indeed. But it'll be hard to imagine what an UI using STAT would be like without some fonts with a correct STAT implementation. |
For reference, here is the formatted STAT data for Source Serif Regular and Italic, taken from TTX dumps of the STAT tables. The only difference is the entry that asserts each font’s location on the SourceSerifVariable-Roman.ttf
SourceSerifVariable-Italic.ttf
|
Update on the latest VF released:
According to https://github.com/googlefonts/gf-docs/tree/master/Spec#stat-table this good work is due to Marc. 😀 Edit: |
Great to hear that Inconsolata is fixed – the build of April 1 looks perfect, except for the addition of Format 2 ranges which might be nice as @thlinard mentions. Nice work, @m4rc1e. Since I last posted on this thread, Samsa has been updated to handle Format 4 axisValueTables, so the old and new versions of Inconsolata can be usefully compared. |
On the subject of range definition in the STAT table, this format was initially targeted at the opsz axis, to enable the STAT table to define the range of intermediate sizes at which an opsz named instance should be used, since this isn't derivable from the names of the instances and is design-specific. I noted when examining the STAT table in Adobe's Source Serif Pro that it defines ranges for the wght axis, and I'm trying to figure out whether there‘s any point to this. Unlike opsz use ranges, which are arbitrary and design-specific, we have weight ranges implied in the CSS weight class, and it seems to me that the range across which to use a nominal weight instance can be algorithmically determined by simply using whichever instance is closest to the nominal weight value. Am I missing something? |
BTW @m4rc1e is there any reason that the variable versions of Source Serif, Source Sans and Source Code are not on Google Fonts? |
@Lorp lack of time mainly. It takes a while to diff a VF against statics to ensure there are no regressions. |
Hi @tiroj Well, I presume the same result could be achieved by algorithmic methods. The goal here is to provide a more meaningful composed name. For example, for wght=600 and for wght=539, "Source Serif Variable Semibold" and "Source Serif Variable Semibold[529]" are seen as more desirable outcomes (for a UI based on the Thus, the ranges provide better consistency, better information for the end user. Furthermore, I know many designers, who are neither font developers nor CSS developers, who don't know what a weight expressed on a scale of 1 to 1000 corresponds to. Adding the familiar name of a weight next to the precise value is a good landmark for them. |
But do you need ranges to obtain those results? I'm questioning whether a format 2 axis value table is necessary for the purposes you describe, or if a format 1 table would always be adequate for the wght axis (and probably the width axis), since the axis scales are so clearly defined and not design-specific in the same way that opsz is. If the wght scale were not mapped to the CSS weight class, then it would make sense to have ranges in the STAT table, but we have avar mappings to fit design space weight progression to the linear weight class, so ranges in the STAT table seem redundant. |
But in that case, I'd argue that the default value should actually be ‘Source Serif Variable Medium 529’, because Medium is the default for the nearest standard weight class value (500). The STAT table axis value record is providing a record of relationships between named instances, but composed names for arbitrary instances on standardised scales could derive from the scales rather than the, as in this case, incomplete set of named instances.
Right, but assigning names to the precise weight class values doesn't need ranges to be specified. A format 1 axis record table does the same thing. Let me put the question another way: Is there ever a case in which it would make sense for the range of covered by the nominal Regular weight instance to be something other than from halfway between it and the next lightest instance to halfway between it and the next heaviest instance? If the answer is yes, doesn't that imply that the avar mappings for wght are incorrect? |
In principle, absolutely (but it doesn’t imply anything is wrong with avar). When a non-linear formula is expressed in piecewise linear steps, the “half way” points between the mappings must also be mapped non-linearly to be mathematically correct. Aesthetic or pragmatic judgement might take precedence over the linear or non-linear mid-points in any case. Regarding “nearest value mapping”, it would be a useful heuristic for composing names in the absence of Format 2 ranges. |
This debate reminds me a bit of the debate "nameID 16-17 vs. nameID 21-22". Well, Adobe chooses for Source Serif Variable:
We would have wished that Adobe (or Frank Grießhammer) used their freedom a little less and conform to a predefined set of weights (the CSS class). But as Laurence pointed out, aesthetic or pragmatic reasons can explain it. But I agree, more standardization would allow the automation of ranges, without having to specify them. |
See, my reading of the Source Serif Pro variable STAT table is that Adobe did conform to the predefined set of weights; they just opted not to define a named instance for every weight in the set. Based on the format 2 wght ranges specified, the implied but unnamed Medium weight is at 500. So what the STAT table is saying is that non-variable environments should use the Regular for everything less than where Medium would be, and Semibold for everything greater than where Medium would be. There's nothing in that which couldn't be derived from using format 1 data and selecting the nearest named instance to the target weight. I understand Laurence's point about the halfway points between non-linear mappings needing to be mapped non-linearly, but that's not what the STAT table ranges do. The STAT format 2 axis record provides information about which named instance to use for a given range when not using interpolation. It's targeting non-variable environments in which named instances behave like static fonts, and the format 2 axis record was defined to provide size range information for optical size (directly akin to the abandoned OS/2 version 5 size fields). BTW, it strikes me that not only shouldn't it be necessary to define ranges for wght, it probably shouldn't be necessary to define most named instances on the weight axis, because any of the standard weight class instances could be synthesised and named as a heuristic. As it is, named instances give font makers a choice about how many virtual static fonts to present to users in non-variable environments. Some, as in this case, might decide not to include all intermediate weights e.g. Medium between the named Regular and Semibold, but it seems to me that this could be entirely client-side, and perhaps up to the user which nominal weight variants to expose in font menus. Speaking of non-linear weight progression, linear mapping, and named instances, I can imagine that not all font makers approach this in the same way, and perhaps best practice recommendations should be documented. There are various tools available to calculate steps between weight design masters according to different equations as may be favoured by font makers. My approach when using such tools is to include all the steps implied by the CSS weight class, regardless of how many of those steps I intend to make named instances. So, if I have a Regular design master and a Black design master, I am going to calculate weight progression for four intermediate weights (Medium, Semibold, Bold, Extrabold) even if, for example, I only plan to define the Semibold and Bold as named instances. Does everyone do this, or do some people calculate only the number of intermediate steps for which they plan to have named instances? |
@tiroj: Your description of STAT Format 2 is interesting, and helps me understand how older apps can make best use of variable fonts, and also how static fonts such as Sitka can make best use of STAT. One clarification would be useful: are you saying that the process in Windows non-variable environments is to use STAT to compose the subfamily name (based on the point size, weight and style), then to look up that name in the fvar Named Instances? Or are you using the term “Named Instance” more loosely to include instances “named” by STAT?
My reading of the STAT table Format 2 spec leads to these two conclusions:
|
I mean Named Instance in the fvar sense; I'll try to remember to capitalise it like this to avoid ambiguity. A Named Instance has a specific axis location in the design space, but by specifying a range using a format 2 STAT axis record, one can associate a Named Instance with a larger area of the design space. But that seems to me primarily relevant to non-variable environments, because in a variable environment one generally doesn't want e.g. the Subhead Named Instance to be used for every point size between e.g. 16pt and 22pt, but rather to use interpolated locations of the design space specific to the actual size. It is possible, of course, that someone might want to use a variable font in a variable environment in a way that is compatible with use in a non-variable environment, or compatible with static fonts, and having format 2 range axis records for opsz would be relevant to that. But, again, that's because opsz Named Instances are not mapped to a standard scale, while wght Named Instances are. So I'm still not convinced there is ever a need to define range axis records for wght. I'm not saying it is wrong to do so, only that I wouldn't want font makers to look at something like Source Serif Pro and conclude from it that this is something they should be doing. |
cc. @PeterConstable who might be able to confirm or contradict my understanding, and provide insights into the design and intention of the format 2 axis record. |
I tested all the VF of this repo, here are the results:
Where is the script to reproduce the test? :)
|
Hi @davelab6 You're welcome! 😆 It was a very manual test (ttx the fonts, and I simply looked at the result with my very eyes), so, sorry, no script. But I can give the specifications of such a script:
|
IIRC, Adobe brought up the idea of an additional AxisValue format that defines both a range and a style-linked value. I forget now if it hasn't been pursued because they just didn't pursue it, or because there was an issue that never got resolved. (Possible issue: What would it mean to link a range to a point value?) Or would it make sense for the OT spec to explicitly sanction what Adobe has done, including both format 2 and format 3 entries for wght=400? (Explicit sanction could clue in app developers to anticipate this.) |
IIRC, format 3 was originally designed having in mind opsz in static-instance fonts, not in variable fonts. In a variable font with an opsz axis, opsz ranges shouldn't matter since there is an instance available for every text point size. (I suppose there could be an app that might support auto-selection of optical size variants but without support for arbitrary instances, so the opsz ranges in the variable font would allow it to identify the opsz name to use in filtering named instances. But hopefully apps wouldn't get designed that way.) Keep in mind that STAT was intended for use in variable or non-variable fonts; indeed, it was first conceived (at Adobe) before work on OT variations began. |
OK, read through the thread. I think it's fair to say that the original design intent for format 2 ranges was for non-variable scenarios. That first of all meant non-variable fonts, to supersede the OS/2 format 5 usLowerOpticalPointSize and usUpperOpticalPointSize fields and the 'size' feature. (I'm sure neither of those would have even been considered if a STAT table had existed.) But clearly the ranges can also be useful for a variable font in a non-variable app. Ranges may also be useful for variable fonts even in apps that support variations. For instance, consider a font fallback scenario: the content specifies weight=500 but the specified font family isn't available and fallback is being used: what instance from the fallback font family is selected? You could infer that algorithmically using a nearest numeric match. But designer-provided range values are another way that could be used. Generalizing that, consider what an API might need to do: an API might allow a client to request matches for some vector of axis values: that API could use nearest numeric matching, or it could use font-provided ranges. Or it could use font-provided ranges if available and use numeric matching if not—IIRC, that's what Dwyane Robinson did in Windows DirectWrite. So, is format 2 needed for wght? No, probably not: an app or API that pays attention to STAT axis value tables probably also implemented some behaviour when STAT isn't present. Is it useful? Maybe, if designer-provided values can give better results than a numeric algorithm. Btw, 'avar' was mentioned here. I would not expect any app or API that uses a numeric algorithm to evaluate what is happening in an 'avar' table to tune that algorithm: there's no easy way to know what the designer's intent was with the 'avar' table, and there's nothing to suggest it would be worth the investment to even try. |
I've been progressing through the many variable fonts in the library (both live and not) and wanted to give an update on the efforts. Categories:
|
Fantastic job! There is not much left after that. I see you don't consider a non elidable default value to be an error in the |
@thlinard For the "reviewed" fonts, I primarily looked at them in Mac Word to check if all of the STAT values are showing properly. Many didn't default to the "Regular" location, but I actually expected that to be the case. The problem in Mac Word is that it appears that if a font only has a master at either end of the designspace (and lacks one at the "Regular" location) that it will never be able to find the "Regular" location, regardless of the 'elidable' state. That said, you're right that I should make double-sure that they have 'elidable' for the wonderful day in the future when Mac Word works correctly ;) |
@thlinard I reviewed all the fonts that didn't default properly and only came up with "Spartan" as lacking the elidable flag on the Regular weight. Are there other fonts you found as problematic? |
@aaronbell To Spartan you could add:
|
Thanks! Interestingly those fonts did not exhibit any issues in Mac Word, but probably best to update. I’ll add them :) |
I’m going to keep this open for tracking |
@aaronbell 4 VFs are missing in your summary table:
|
I believe that all fonts that needed correction have been corrected, and PRs opened for each. Given that, I'm going to go ahead and close this issue :) |
Hi @aaronbell Same question as #3267: shoulddn't the issue be closed only when the fix is released, rather than just at the PR stage? And also, as #3267: many PRs missing (Archivo Narrow, Fraunces, all the Noto VFs — a lot !)? (or am I missing something?) Congratulations for the job done, anyway. 😃 |
Sure. I mistakenly thought all of the affected fonts were either merged, or soon to be merged, and I forgot that there's a number of other fonts that still need update! Whoops. On the various fonts:
|
|
|
It appears that the STAT tables in the Noto fonts still have not been fixed. Is there a timeline for that? |
Can anyone confirm that the InDesign issue reported here is still an active problem? I am trying to figure out if a behaviour I am experiencing in testing a new variable font is that same as discussed here, or something new. |
A user wrote in.
|
Since adding STAT table handling to Samsa, I’ve been finding apparent errors in several variable fonts including IBM Plex Sans and Work Sans. (These are the only two Google fonts I have tested, so I can only assume the problem is widespread.)
The issue is that the STAT in the Italic VF repeats the string “Italic” in all the weight entries. Here is a screengrab from Work Sans Italic (WorkSans-Italic-VariableFont_wght.ttf) in Samsa.
This leads to incorrect “composed names” such as Light Italic Italic.
In fact, each of these strings is supposed to refer to a single axis, so the list of strings in Work Sans Italic’s Weight STAT should be: Thin, ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold, Black. Only then can apps build menus where users select meaningful instance names from one axis at a time.
Work Sans Roman (WorkSans-VariableFont_wght.ttf) has a less important issue where the string “Roman” in the Italic axis should be marked elidable (flag = 2). When fixed, we would see composed names of the form “SemiBold” rather than “SemiBold Roman”. Finally, “Regular” should also be marked elidable in both Roman and Italic.
Try in Samsa
The text was updated successfully, but these errors were encountered: