googlefonts / glyphsLib

A bridge from Glyphs source files (.glyphs) to UFOs
Apache License 2.0
181 stars 51 forks source link

Using instance definitions for axes mappings is baseless #942

Open simoncozens opened 1 year ago

simoncozens commented 1 year ago

I recently tried building a large variable font in fontmake, and was confused about why the font didn't vary at all. When I dug further, only one master was being generated, and that's because all the others were out of the range of the minimum/maximum for the axis in the designspace. And that's because glyphsLib decides the range of an axis by looking at the instances. Only one instance was defined, so only one master got used.

I'm sure this made sense once, but it doesn't make sense now. If I have an eight master font, with masters at wght=400 wdth=100, wght=400 wdth=10, wght=800 wdth=100, wght=800 wdth=10, that's my designspace.

I tried adding a "Variable Font Setting" instance, but that still didn't work unless I removed all the static exports, at which point it was fine. We are currently working out what a variable font should look like based on the static instances, which I'm not sure makes any sense. And it causes fontmake exports to differ from the equivalent Glyphs exports - Glyphs does the right thing and uses the union location of the masters to make the variable font axis ranges.

anthrotype commented 1 year ago

have you defined Axis Mappings font custom parameter, or Axis Location master/instance custom parameters?

anthrotype commented 1 year ago

because I believe the inference from instance location is a legacy mode used for sources that don't define either of those

anthrotype commented 1 year ago

Glyphs does the right thing

I'm all for doing the right thing (tm), please send a PR if you find a way to fix it while keeping backward compat as much as possible

simoncozens commented 1 year ago

have you defined Axis Mappings font custom parameter, or Axis Location master/instance custom parameters?

This is just a regular Glyphs file that works in Glyphs. You don't need an Axis Location custom parameter in your master in Glyphs 3; that was a Glyphs 2 thing. These days, the axis coordinates are defined specifically, so you can just read them off the masters. So it's possible that font_uses_axis_locations needs to be updated for Glyphs 3.

But trying that, I get:

WARNING:glyphsLib.builder.axes:Axis wght: Master '...' redefines the mapping for user location 400 from 100 to 400
WARNING:glyphsLib.builder.axes:Axis wght: Master '...' redefines the mapping for user location 400 from 400 to 100
WARNING:glyphsLib.builder.axes:Axis wght: Master '...' redefines the mapping for user location 400 from 100 to 400

and so on. Why? Well, multiple problems. AxisDefinition.get_user_loc finds the user location by looking at master.weight and guessing based on the string (because that's what you had to do in Glyphs 2), and in this case, master.weight is being reported as "Regular" so it guesses that the user value of the weight axis should be 400. But the only reason master.weight is coming out as "Regular" is because that's the default and nothing seems to set it.

Argh, this is all largely my fault - I tried to add Glyphs 3 support on top of glyphsLib while keeping all the Glyphs 2 hacks working. I should have started again with the Glyphs 3 set-up as the primary data model, since it gets variable fonts right, and then upgraded any incoming Glyphs 2 files to the new model.

But that would have been a much bigger and more invasive change.

schriftgestalt commented 1 year ago

Yes, the axes ranges (for fvar) should be inferred from the masters. The master locations define the internal locations that can be amended with the "Axis Location" parameter. I just tried this and the master Axis Locations are "only" used to redefine the axis range, in between the proportions of the internal master positions are used (the tuple values in gvar use the internal values).

e.g.: master 1: inter: 100 extern:100 master 2: inter: 200 extern:250 (value is ignored) master 3: inter: 300 extern:1000

The master 2 will be effectively at external 555.

That is done to match the output of static fonts that do not care about the external values.

On top of this you can add Axis Locations to the instances to make avar.

anthrotype commented 1 year ago

You don't need an Axis Location custom parameter in your master in Glyphs 3; that was a Glyphs 2 thing. These days, the axis coordinates are defined specifically, so you can just read them off the masters.

masters' axis coordinates are in design-space, not user-space, by definition. That's why one may need Axis Mappings/Axis Location (or infer the user-space location from instances in absence of those), otherwise the only sane thing to do is assume nominal master coordinates are unmapped and as such design:user mapping is identity

anthrotype commented 1 year ago

Axis Locations are "only" used to redefine the axis range, in between the proportions of the internal master positions are used

well that's definitely not how fontmake/glyphsLib interpret those... Axis Location is the user-space coordinate that is mapped to the master (or instance, they can also get Axis Location!) internal design coordinate.

simoncozens commented 11 months ago

otherwise the only sane thing to do is assume nominal master coordinates are unmapped and as such design:user mapping is identity

That would be a sane thing to do, but glyphsLib is not sane.

The good news is that Georg's glyphs3 branch seems to get this right.

schriftgestalt commented 11 months ago

In my work on glyphsLib (in the Glyphs3 branch) I have removed the code that looks at the instances. I added internalAxesValues and externalAxesValues properties to the masters and instances. That internally uses the "Axis Location" parameter but frees up the builder and other code to deal with this.

I wonder how many projects rely on this. How to handle those? a) Add "Axis Location" parameters b) Add a custom parameter or fontmake flag to trigger the fallback?