googlefonts / googlefonts/fontc
Nested composites with a per-master-varying 2×2 are decomposed differently from ufo2ft
- Dominant language
- Rust
- Stars
- 193
- Forks
- 21
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 60
Description
Opening this to track another place where operation order is producing different results than the python pipeline.
This affects certain composite glyphs whose component is itself a composite containing a component with a per-master-varying 2×2:
An example from NotoSans:
```
Omonocular-cy = [O, period(scale 1.034,1.004 → 0.833,0.98)] # both compilers decompose
Odoublemonocular-cy = [Omonocular-cy, Omonocular-cy] # fontc keeps, fontmake decomposes
u107B5 = [bilabialclick scale (0.65,0.6)] # bilabialclick = [O, periodcentered(varying)]
```
The source's filter list is `flattenComponents` with `pre = 1`. ufo2ft runs it *before* `check_for_nonmatching_components`, so the outer glyph is first flattened to `[O, period(varying), O, period(varying)]` and then decomposed because its 2×2s vary.
fontc does the opposite: `has_consistent_components` (`fontir/src/glyph.rs` ~878–905) runs on the unflattened glyph, whose two components have identity transforms, so it is kept; by the time `flatten_glyph` (~636–676) runs, the inner glyph is already simple and there is nothing to flatten. The log shows `Coalescing 'Omonocular-cy' into a simple glyph` with no corresponding line for `Odoublemonocular-cy`.
Both outputs are valid fonts. do we care?
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in fontir/src/glyph.rs around has_consistent_components (~878–905) and flatten_glyph (~636–676), then compare their order with the source filter list and ufo2ft behavior. Reproduce the NotoSans examples, decide whether matching ufo2ft is required, and document the agreed decomposition behavior with a regression check if the project has an appropriate location.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100