Repository navigation
Conversation
black7375
force-pushed
the
fix/glyphs-conversion-edge-cases
branch
2 times, most recently
from
September 8, 2026 16:12
0686366 to
1ade42d
Compare
black7375
force-pushed
the
fix/glyphs-conversion-edge-cases
branch
from
October 10, 2026 15:42
1ade42d to
c325c84
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix axis-mapping and glyph-swap edge cases encountered when converting Glyphs sources through glyphsLib and fontmake.
This PR now builds on the instance-mapping fixes in #1197. It retains upstream's mapping selection, endpoint extrapolation, trimming, and 16.16 rounding instead of adding a second implementation.
Changes
Axis Mappingscustom parameter, without extending the declared mapping bounds.AxisDescriptor.map_backward()for axis-default lookup and upstream's new interpolation helper, preserving both endpoints of flat segments.Design rationale
Preserve explicit defaults without reinterpreting the source
Designspace axis defaults use user coordinates, while source locations use design coordinates. The mapped default must therefore match the default source's location. See the Designspace axis documentation and fontTools default-source lookup.
An interpolated user-space default can be rounded during XML serialization and then map back to a slightly different design coordinate. Adding an explicit knot preserves its correspondence to the master through serialization. fontTools also requires mapping knots for the axis minimum, maximum, and default when building
avar; this is a fontTools build requirement, not a UFO constraint.Upstream already inserts inferred default knots. The additional handling here covers explicit
Axis Mappingsand only inserts a missing default strictly inside the existing user-coordinate range. Existing knots and bounds remain unchanged. In particular, it does not flip mappings, infer their direction from the Glyphs file version, or extend explicit bounds to conceal the out-of-range sources discussed in #993.Preserve flat segments throughout upstream's new mapping pipeline
The OpenType
avarspecification permits equal consecutive output coordinates: flat segments are valid. Its output coordinates must not decrease. This PR applies nondecreasing validation as a conversion policy before trimming or fallback; it does not claim that UFO defines axis-mapping constraints.Inverting a mapping into a dictionary loses one endpoint when multiple user coordinates share a design coordinate. This also affects upstream's new helper used for default interpolation and trimming. For example, with
100→100, 300→400, 400→400, 900→900, design coordinate350corresponds to user coordinate approximately266.666667, not350.fontTools 4.63.0 includes fonttools/fonttools#4085, which preserves both endpoints during reverse mapping. The dependency bump makes that corrected implementation available everywhere this PR uses it, while retaining upstream's 16.16 rounding. Output such as
400.0instead of400is numerically equivalent and is not a new formatting requirement.Preserve component relationships during glyph swaps
UFO GLIF components reference base glyphs by name within the same layer and must not create circular references. Swapping only glyph contents can turn an existing reference into a self-reference: for example, when
a.altcontains a component referencinga.Swapping the corresponding component references along with the contents preserves the existing component relationships. Unicode assignments remain attached to the original names. This is the rationale for the component-reference update, not a claim that the UFO specification defines Glyphs.app's complete
Rename Glyphssemantics.