-
Notifications
You must be signed in to change notification settings - Fork 52
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
User/design space mapping computation: Improve default generation? #483
Comments
Inferring master’s user location from the instances is the “old way”, for legacy compat, going forward we should encourage user to set explicitly the axis location master custom parameter |
after #451 was merged (glyphsLib >= 3.3.0), the old approach of building the DesignSpace axes mapping (from user-space to internal design locations) got an unexpected breaking change. The width axis is no longer assumed to be already in user-space coordinates (as in percentage of Normal width); but the instances' width classes are used as user-space locations, and the instances' width values as internal design locations. |
If one uses the new approach (i.e. Axes + Axis Location master custom parameters) to define the DesignSpace axes maps, one can only assign user-space locations to the masters, not to the intermediate locations corresponding to the interpolated instances in the previous method. |
According to the code, setting the Axis Location along the width axis should work (and override any other "inference" made by glyphsLib: https://github.com/googlefonts/glyphsLib/blob/master/Lib/glyphsLib/builder/axes.py#L354-L363 Is that an OK solution for you? Or do you mean that you want the old behaviour without switching your files to using Axis Location? As for having mapping entries corresponding to instances, we had something like that in glyphsLib before the introduction of Axis Location, but I think it's a bad idea in general because it often happens that designers define lots of instances in Glyphs for testing purposes, and that doesn't mean that they want mapping entries for all of them. On the other hand, designers could come up with a font with only two masters, no instances, and still want a precise mapping curve with many entries. That indicates to me that a better mapping generation in glyphsLib should rely on a specific "mapping description" in the Glyphs file format, that is NOT attached to instances. |
you mean, setting the Axis Location of, say, the NotoSans-MM.glyphs "Condensed" masters to be 70, i.e. the same as their internal design-space location? But then using Axis Location would opt in the new approach also for weight, where currently NotoSans has as many map elements as there are instances. But using Axis Location on the masters would mean having mappings only for the masters (which are at 100, 400, 700 and 900), and none for the intermediate steps |
it is extremely important that when for example one requests the wght=200 (and width=100) from NotoSans-VF.ttf, one gets exactly the same output as the ExtraLight static instance, and not something linearly interpolated between the Thin (100) and the Regular (400). That's why the DesignSpace axis maps (and coorespondingly the wght avar segementmap) needs to contain an entry for 200 |
nor attached to masters |
to stay with the example above, for NotoSans-VF and ExtraLight instance. If one requests an instance with wght=200, this value gets normalized using default coordinate normalization to -0.6667; but then the avar tables "warps" the default normalization and gives -0.7969. This is the final value used internally to compute scalars and deltas. <axis tag="wght" name="Weight" minimum="100" maximum="900" default="400">
<map input="100" output="26"/>
<!-- <map input="200" output="39"/>
<map input="300" output="58"/> -->
<map input="400" output="90"/>
<!-- <map input="500" output="108"/>
<map input="600" output="128"/>
<map input="700" output="151"/>
<map input="800" output="169"/> -->
<map input="900" output="190"/>
</axis> commenting out the intermediate mappings will produce the following avar table: <avar>
<segment axis="wght">
<mapping from="-1.0" to="-1.0"/>
<!-- <mapping from="-0.6667" to="-0.7969"/>
<mapping from="-0.3333" to="-0.5"/> -->
<mapping from="0.0" to="0.0"/>
<!-- <mapping from="0.2" to="0.18"/>
<mapping from="0.4" to="0.38"/>
<mapping from="0.6" to="0.61"/>
<mapping from="0.8" to="0.79"/> -->
<mapping from="1.0" to="1.0"/>
</segment>
</avar> |
I see your problem, I think there is no good solution currently. Either your mapping is not what you want for weight, or it's not what you want for width. The PR that you commented on improves slightly the situation for width because at least you don't have to stick to the design locations, but is still constrained by the limited list of options from the spec. I think a good way to fix that would be to have an "Axis Mapping" custom parameter on the GSFont, which would give exactly the same liberties for defining mappings as the Designspace format. I wonder how Glyphs users who produce variable fonts with Glyphs specify mappings? |
Good question. Maybe Georg knows? @schriftgestalt |
I think I will revert the change in #451 for now, until we find a decent solution. It's not good that users that install fontmake in a new environment will get glyphsLib 3.3.0 which produces a different designspace (hence different varfont's fvar/avar) than if they do not upgrade glyphsLib and stay with 3.2.0. |
this is to blacklist glyphsLib 3.3.0, which changed the way width axis coordinates are interpreted (and thus the generated fvar and avar tables in variable fonts). glyphsLib v3.3.1 restores the previous behavior until we reach agreement in googlefonts/glyphsLib#483. The change in question is googlefonts/glyphsLib#451
Maybe release v4 and do the right thing. There will be a lot more vf in the future than the past. |
Yeah, but it’s the definition of “the right thing” which is not only for me to decide. |
When I understand the problem correctly, the "Axis Location" CP is dealing with it. Glyphs doesn't properly handle the instance mapping at all as there is no support for |
the Axis Location applies to Masters only. We need a way to specify mappings (between user-space and internal design coordinate space) for arbitrary intermediate locations that may (or may) not correspond to the locations of the instances. Basically the equivalent of the designspace format's |
I convinced myself that we should use the instances' OS/2 widthClass to define the user-space locations for the wdth axis, the same way we do for wght (submitted #526 to re-revert the change from #451). Take NotoSans, for example, where the most condensed master has width coordinate 70; the "Extra Condensed" instance is also at the same width coordinate, and has OS/2 widthClass 2. According to both OS/2 and CSS specs, "extra-condensed" should correspond to 62.5 % percent of the normal width (not 70 %): If static instance is generated for such NotoSans-ExtraCondensed and it has OS/2.widthClass = 2, and it is selectable with Even with #526, we would still miss support for defining custom avar mappings for intermediate locations that don't correspond to neither masters nor instances, but that's less of an issue. |
another thing I am not quite at ease with is that, one the one hand we advertise using Axis Location custom parameter as the "new" approach to specifying the fvar's user-space locations, but on the other hand this only allows to specify user location of the masters and as soon as you have some instance in between them for which the OS/2 width class and the interpolation value do not exactly match, then the only solution is to not use the Axis Location parameter and revert back to the "old" approach where user-locations are inferred from the instances. |
I’m open to define something like the |
No it wouldn't; please do not tie the Axis Location to the instances, that would not solve the problem that is described here. The designspace mapping can have "Axis Locations" that are independent from masters and instances. ie. you can have 2 masters, no instances, and 5 mapping entries, or 3 masters, 2 instances, and 4 mapping entries, or any other combination. |
Right. Something in Font then. Can you suggest a data structure? I’ll think about a UI then? |
Thanks. I wrote above
|
I agree with Cosimo's suggestion, and just because usually people are confused about which side of the mapping is user location or design location, I would make it explicit on each tuple like so:
(but it's not necessarily a good idea because then people can write stuff like [{user: 100, design: 50}, {user: 100, design: 75}] which doesn't make sense) |
As for the UI I suggest something similar to the graph in the avar spec: With user-space coordinates on the horizontal axis, and the internal design locations on the vertical axis (the avar graph is using normalized coordinates but it’s the same). |
Also there must be mappings for at least the minimum, default and maximum location of each axis; the coordinates must be unique (no duplicates) and in increasing order. |
The Axis Location custom parameters provide mappings for the masters, so if those are present the Axis Mapping should be pre-populated with those values, and the user can add more intermediate mappings if needed but not modify the master’s axis location (otherwise the two pieces of data would get out of sync) |
Could the |
Supersede sgtm |
Should Glyphs.app auto-migrate master-level |
@schriftgestalt I was wondering if this new proposed "Axis Mapping" custom parameter has been implemented yet, perhaps in beta version? |
Didn’t have time for this, yet. It’s on my list. |
Random note to myself: look at if it's possible to get rid of the |
In the BraceTestFont.glyphs file, the generated axes mapping is
If one removes the "Axis Location" custom parameters from the masters, one gets
Looking at the instances, glyphsLib should be able to infer that we need to add a mapping that maps user 75 to design 50 and user 100 to design 100 ("Condensed" instances). Likewise, we have two weight masters and define weightClass 100 and 700 in the instances as min/max. Basically, glyphsLib should infer the first axes definition without the user setting the appropriate custom parameters.
The text was updated successfully, but these errors were encountered: