googlefonts / googlefonts/fontc
Glyphs v2 "Custom" (XXXX) point axis at non-default position
- Dominant language
- Rust
- Stars
- 193
- Forks
- 21
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 65
Description
There are a number of issues related to the funny implicit axes in glyphs v2 fonts. This issue is derived from a diff in [Charmonman](https://github.com/cadsondemak/Charmonman) @ 8590fc4aae.
I fed this diff to my dog, and got back the following. There was a proposed patched, but it didn't feel great, so I'm just opening an issue to track.
## Background
Glyphs v2 files implicitly define three axes when no explicit "Axes" custom parameter is present:
| Index | Tag | Name | Canonical default |
|-------|-----|------|-------------------|
| 0 | `wght` | Weight | 100.0 (design) |
| 1 | `wdth` | Width | 100.0 (design) |
| 2 | `XXXX` | Custom | **0.0** |
Charmonman has two masters (`wght` 400 and 700), both with `customValue = 10`. The XXXX axis is therefore a **point axis** — min = default = max = 10 — with no actual variation.
## What fontmake does
In [`glyphsLib/builder/axes.py`](https://github.com/googlefonts/glyphsLib/blob/f8c11742befe0a37aa6708be39a3c56da73cdc12/Lib/glyphsLib/builder/axes.py#L288-L299), an axis is added to the designspace if any of these conditions hold:
```python
if (
minimum < maximum # has a range
or minimum != axis_def.default_user_loc # point, but NOT at the canonical default
or not is_identity_map
or axis_wanted
):
self.designspace.addAxis(axis)
```
For XXXX: `minimum = 10`, `axis_def.default_user_loc = 0.0`. Because `10 != 0.0`, the axis is included even though it is a point. The result in fvar is `min = default = max = 10.0`.
For `wdth`: `minimum = 100`, `default_user_loc = 100.0`. Because `100 == 100` and it is a point, it is **not** included.
## What fontc does
`StaticMetadata::new` filters axes unconditionally on `is_point()`:
```rust
let variable_axes = axes.iter().filter(|a| !a.is_point()).cloned().collect();
```
`is_point()` returns `true` when `min == default == max`. XXXX has min = max = default = 10, so it is dropped. fontc never checks whether the value differs from the canonical default for that axis tag.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with fontc's StaticMetadata::new axis filtering and the is_point() behavior, then compare them with the referenced glyphsLib/builder/axes.py logic. Reproduce the Charmonman case using the linked commit and inspect the generated axis metadata; done means the intended handling of a non-default XXXX point axis is established and covered by an appropriate regression check.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100