Written because the author confused themselves and wanted to be sure they now understand.
There are three main classes of variation axis coordinates in variable fonts:
- Design coordinates
- User, aka External, coordinates
- The values in fvar, for example Weight 400
- What you would expose to an end user in a document editor or manipulate via CSS
- Internal, or normalized, coordinates
- Values in [-1, 1], used internally by the font
- The default must be at 0 in these terms
Any unit can be converted to any other unit using a piecewise linear function.
Given that we have at least one design coordinate, and we know what the design coordinate for the default outline is:
Design coord | Internal coord | Notes |
---|---|---|
min design value | -1 | If min < default master location |
default master location | 0 | Mandatory |
max design value | 1 | If max > default master location |
User coordinates run through a piecewise linear function, to get internal coordinates. avar captures this in the font binary, derived from the User:Design mapping typically captured in the sources.
Both Glyphs and .designspace files capture mappings from user to design coordinates:
-
The set of elements for an axis capture it in .designspace sources, for example (from Noto Sans Thai):
<axes> <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> <axis tag="wdth" name="Width" minimum="62.500000" maximum="100" default="100"> <map input="62.500000" output="70"/> <map input="75" output="79"/> <map input="87.500000" output="89"/> <map input="100" output="100"/> </axis> </axes>
-
The custom key "Axis Mappings" captures it in .glyphs sources, for example (from Lexend)
{ name = "Axis Mappings"; value = { HEXP = { 0 = 0; 100 = 100; }; wght = { 100 = 22; 200 = 50; 300 = 78; 400 = 108; 500 = 130; 600 = 150; 700 = 170; 800 = 198; 900 = 216; }; }; }
Since design trivially maps to internal coordinates this readily yields the mapping needed for the avar table, as is the intent.
See also @anthrotype's writeup in googlefonts/glyphsLib#568 (comment).