[fonttools/fonttools] d28b40: Fix interpolation, and allow for common operations...

0 views
Skip to first unread message

Cosimo Lupo

unread,
Mar 5, 2026, 7:09:58 AM (6 days ago) Mar 5
to fontto...@googlegroups.com
Branch: refs/heads/varsca-interpolation
Home: https://github.com/fonttools/fonttools
Commit: d28b407429fed86e85354237e57f6ca9e6778f78
https://github.com/fonttools/fonttools/commit/d28b407429fed86e85354237e57f6ca9e6778f78
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/feaLib/builder.py
M Lib/fontTools/feaLib/variableScalar.py

Log Message:
-----------
Fix interpolation, and allow for common operations on pre-compiled fonts

(aims to facilitate googlefonts/ufo2ft#945)

Previously, calculating an individual interpolated value did not account
for avar mapping. This commit fixes this, as well as allowing for
interpolation and other common operations to be performed on fonts prior
to compilation by decoupling from the exact ttLib representations of
axes.

Some refactoring has been undergone to assist with this, including
adding some more types and docs, and splitting the builder into a
separate class to limit the amount of state in the VariableScalar class
itself.

The fonttools and ufo2ft test suites pass with these changes, although
there is no coverage for the designspace-based interpolation yet. This
should be introduced before merging.


Commit: 41ebf1f1fe3ee9858778737c3250baf17c21b9e0
https://github.com/fonttools/fonttools/commit/41ebf1f1fe3ee9858778737c3250baf17c21b9e0
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/designspaceLib/__init__.py

Log Message:
-----------
Add partial AxisDescriptor typing


Commit: 888d7fbea41778153c3d221bdce2956ebbe3b222
https://github.com/fonttools/fonttools/commit/888d7fbea41778153c3d221bdce2956ebbe3b222
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/varLib/models.py

Log Message:
-----------
Type linear mapping function


Commit: 3ce01a02a83d3b6a9e4b1ea9368a6dfebdfa6d29
https://github.com/fonttools/fonttools/commit/3ce01a02a83d3b6a9e4b1ea9368a6dfebdfa6d29
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py

Log Message:
-----------
Fix type checking related crash for pre-`Self` Python


Commit: 3b9dcdfe06961c02ab10d771753a8fae2e264d49
https://github.com/fonttools/fonttools/commit/3b9dcdfe06961c02ab10d771753a8fae2e264d49
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/feaLib/builder.py

Log Message:
-----------
Allow for modern type annotations


Commit: 78b71a5e038426550aa5f5fcbaf5ceb5f0ce33e8
https://github.com/fonttools/fonttools/commit/78b71a5e038426550aa5f5fcbaf5ceb5f0ce33e8
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/designspaceLib/__init__.py

Log Message:
-----------
Fix and improve partial axis descriptor typing


Commit: 7d31b1cfccc0aaa17812230517fa48e21e80e1c0
https://github.com/fonttools/fonttools/commit/7d31b1cfccc0aaa17812230517fa48e21e80e1c0
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py

Log Message:
-----------
Iterate over mapping as guaranteed list instead of optional dict


Commit: e02295b6eb25b5c60890f729be1fece42b500f60
https://github.com/fonttools/fonttools/commit/e02295b6eb25b5c60890f729be1fece42b500f60
Author: Harry Dalton <harry....@daltonmaag.com>
Date: 2025-09-19 (Fri, 19 Sep 2025)

Changed paths:
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
Test interpolation of single variable scalar value from designspace


Commit: 1c385c6154ec0b9dbd08169a8bab33299b7663af
https://github.com/fonttools/fonttools/commit/1c385c6154ec0b9dbd08169a8bab33299b7663af
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M .github/workflows/test.yml
M .github/workflows/wheels.yml
M Doc/source/designspaceLib/xml.rst
M Doc/source/misc/index.rst
A Doc/source/misc/visitor.rst
M Doc/source/ttLib/index.rst
M Doc/source/ttLib/tables.rst
R Doc/source/ttLib/tables/G_M_A_P_.rst
R Doc/source/ttLib/tables/G_P_K_G_.rst
R Doc/source/ttLib/tables/M_E_T_A_.rst
R Doc/source/ttLib/tables/S_I_N_G_.rst
A Doc/source/ttLib/ttVisitor.rst
M Lib/fontTools/__init__.py
M Lib/fontTools/cffLib/CFF2ToCFF.py
M Lib/fontTools/cffLib/__init__.py
M Lib/fontTools/cu2qu/cu2qu.py
M Lib/fontTools/cu2qu/ufo.py
M Lib/fontTools/designspaceLib/__init__.py
A Lib/fontTools/diff/__init__.py
A Lib/fontTools/diff/__main__.py
A Lib/fontTools/diff/color.py
A Lib/fontTools/diff/diff.py
A Lib/fontTools/diff/utils.py
M Lib/fontTools/feaLib/builder.py
M Lib/fontTools/feaLib/parser.py
M Lib/fontTools/feaLib/variableScalar.py
M Lib/fontTools/fontBuilder.py
M Lib/fontTools/misc/bezierTools.py
M Lib/fontTools/misc/configTools.py
M Lib/fontTools/misc/fixedTools.py
M Lib/fontTools/misc/visitor.py
M Lib/fontTools/misc/xmlWriter.py
M Lib/fontTools/otlLib/builder.py
M Lib/fontTools/pens/pointPen.py
M Lib/fontTools/qu2cu/cli.py
M Lib/fontTools/qu2cu/qu2cu.py
M Lib/fontTools/subset/__init__.py
M Lib/fontTools/subset/svg.py
M Lib/fontTools/svgLib/path/shapes.py
M Lib/fontTools/ttLib/removeOverlaps.py
M Lib/fontTools/ttLib/sfnt.py
M Lib/fontTools/ttLib/tables/D_S_I_G_.py
M Lib/fontTools/ttLib/tables/DefaultTable.py
R Lib/fontTools/ttLib/tables/G_M_A_P_.py
R Lib/fontTools/ttLib/tables/G_P_K_G_.py
R Lib/fontTools/ttLib/tables/M_E_T_A_.py
R Lib/fontTools/ttLib/tables/S_I_N_G_.py
M Lib/fontTools/ttLib/tables/TupleVariation.py
M Lib/fontTools/ttLib/tables/__init__.py
M Lib/fontTools/ttLib/tables/_a_v_a_r.py
M Lib/fontTools/ttLib/tables/_f_v_a_r.py
M Lib/fontTools/ttLib/tables/_g_l_y_f.py
M Lib/fontTools/ttLib/tables/_t_r_a_k.py
M Lib/fontTools/ttLib/tables/otBase.py
M Lib/fontTools/ttLib/tables/otConverters.py
M Lib/fontTools/ttLib/tables/ttProgram.py
M Lib/fontTools/ttLib/ttFont.py
M Lib/fontTools/ufoLib/__init__.py
M Lib/fontTools/ufoLib/glifLib.py
M Lib/fontTools/ufoLib/validators.py
M Lib/fontTools/unicodedata/Blocks.py
M Lib/fontTools/unicodedata/ScriptExtensions.py
M Lib/fontTools/unicodedata/Scripts.py
M Lib/fontTools/unicodedata/__init__.py
M Lib/fontTools/varLib/__init__.py
M Lib/fontTools/varLib/avar/build.py
M Lib/fontTools/varLib/avar/map.py
M Lib/fontTools/varLib/avar/unbuild.py
M Lib/fontTools/varLib/instancer/__init__.py
M Lib/fontTools/varLib/interpolatable.py
M Lib/fontTools/varLib/interpolatableHelpers.py
M Lib/fontTools/varLib/interpolatablePlot.py
M Lib/fontTools/varLib/interpolatableTestContourOrder.py
M Lib/fontTools/varLib/interpolatableTestStartingPoint.py
M Lib/fontTools/varLib/models.py
M NEWS.rst
M README.rst
M Tests/cu2qu/cu2qu_test.py
M Tests/cu2qu/ufo_test.py
M Tests/designspaceLib/data/convert5to4_output/AktivGroteskVF_Italics_Wght.designspace
M Tests/designspaceLib/data/convert5to4_output/AktivGroteskVF_Italics_WghtWdth.designspace
M Tests/designspaceLib/data/split_output/AktivGroteskVF_Italics_Wght.designspace
M Tests/designspaceLib/data/split_output/AktivGroteskVF_Italics_WghtWdth.designspace
M Tests/designspaceLib/data/split_output/MutatorSansVariable_Weight.designspace
M Tests/designspaceLib/data/split_output/MutatorSansVariable_Width.designspace
M Tests/designspaceLib/designspace_test.py
M Tests/feaLib/builder_test.py
A Tests/feaLib/data/cvparam_null.fea
A Tests/feaLib/data/cvparam_null.ttx
M Tests/feaLib/data/empty_filter_sets_and_mark_classes.ttx
M Tests/feaLib/data/spec9a2.fea
M Tests/feaLib/data/spec9a2.ttx
M Tests/feaLib/parser_test.py
M Tests/feaLib/variableScalar_test.py
M Tests/misc/bezierTools_test.py
M Tests/otlLib/builder_test.py
M Tests/pens/pointPen_test.py
M Tests/qu2cu/qu2cu_cli_test.py
M Tests/qu2cu/qu2cu_test.py
A Tests/subset/data/TestBASE.ttx
A Tests/subset/data/expect_BASE.ttx
M Tests/subset/subset_test.py
M Tests/svgLib/path/path_test.py
M Tests/ttLib/tables/TupleVariation_test.py
M Tests/ufoLib/GLIF2_test.py
M Tests/ufoLib/UFOConversion_test.py
M Tests/ufoLib/glifLib_test.py
M Tests/varLib/avar_test.py
M Tests/varLib/models_test.py
M Tests/varLib/varLib_test.py
M pyproject.toml
M requirements.txt
M setup.cfg
M setup.py
M tox.ini

Log Message:
-----------
Merge origin/main into varsca-interpolation

Resolve conflicts incorporating two main-branch bugfixes into the
refactored VariableScalarBuilder:
- Pass axisOrder to VariationModel (from axis_triples key order)
- Round deltas iteratively via getDeltasAndSupports(round=round)
and storeDeltas(round=noRound)


Compare: https://github.com/fonttools/fonttools/compare/d28b407429fe%5E...1c385c6154ec

To unsubscribe from these emails, change your notification settings at https://github.com/fonttools/fonttools/settings/notifications

Cosimo Lupo

unread,
Mar 6, 2026, 7:05:46 AM (5 days ago) Mar 6
to fontto...@googlegroups.com
Branch: refs/heads/main
Commit: 76942525acbc87a23d5a05948574ad03350e9365
https://github.com/fonttools/fonttools/commit/76942525acbc87a23d5a05948574ad03350e9365
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py
M Tests/feaLib/builder_test.py

Log Message:
-----------
[feaLib] Raise clear error for duplicate normalized locations in VariableScalar

When two user-locations normalise to the same location (e.g. one omitting
an axis that defaults to 0, another specifying it explicitly), raise a
VariationModelError instead of hitting an AssertionError from mismatched
location/value counts in VariationModel.getDeltasAndSupports().

The error flows through makeVariablePos's existing VarLibError handler,
producing a FeatureLibError with a helpful message.


Commit: 73c3e56932e0ce487679c37bd2f26351a93bbaeb
https://github.com/fonttools/fonttools/commit/73c3e56932e0ce487679c37bd2f26351a93bbaeb
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py

Log Message:
-----------
[feaLib] Fix mutable default argument in VariableScalar.__init__


Commit: 8299652ed2bbee2c08fcacd7fddcefa27472d672
https://github.com/fonttools/fonttools/commit/8299652ed2bbee2c08fcacd7fddcefa27472d672
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
[feaLib] Add backwards-compat shim for VariableScalar.add_to_variation_store()

Downstream consumers (babelfont, fontFeatures) set .axes on VariableScalar
and call .add_to_variation_store() directly, bypassing feaLib's builder.
Add a thin deprecation shim that delegates to VariableScalarBuilder so
these callers continue working while they migrate to the new API.


Commit: 23f2a2fcd0da05ec75f483a1f751e201900545c3
https://github.com/fonttools/fonttools/commit/23f2a2fcd0da05ec75f483a1f751e201900545c3
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
black + add link to issue in test comment


Commit: 65181e0c27046b4841b2751341f5e5e03cbbf448
https://github.com/fonttools/fonttools/commit/65181e0c27046b4841b2751341f5e5e03cbbf448
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
[feaLib] Replace VariableScalar interpolation test with one that exercises avar

The previous test used an avar map that collapsed to identity in normalized
space, making the result identical with or without avar mapping. Replace
with a test that uses a non-trivial avar (user 250 maps to design default)
and verifies the interpolated value differs from the no-avar case.


Commit: b3a2f752df90b3aaaaf40c5545af8549adc31e06
https://github.com/fonttools/fonttools/commit/b3a2f752df90b3aaaaf40c5545af8549adc31e06
Author: Cosimo Lupo <cl...@google.com>
Date: 2026-03-05 (Thu, 05 Mar 2026)

Changed paths:
M Lib/fontTools/feaLib/variableScalar.py
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
[feaLib] Refactor VariableScalarBuilder to work in user-space

Address review feedback from PR #4054:

- Rename normalise -> normalize (American spelling)
- Remove intermediate "normalized user-space" representation; locations
are now kept in user-space until the point of normalization+avar
mapping, which happen together in _normalize_location()
- Drop custom duplicate location detection; VariationModel raises its
own error for duplicate locations
- Add comment explaining exact-match shortcut in value_at_location()
- Keep typing.Self (only used under TYPE_CHECKING, fine for Python 3.10)
- Add test for from_ttf constructor with avar
- Add TODO for avar2 support


Commit: d0d007bea8b5697624d95a74d644e9da1987e482
https://github.com/fonttools/fonttools/commit/d0d007bea8b5697624d95a74d644e9da1987e482
Author: Cosimo Lupo <cos...@anthrotype.com>
Date: 2026-03-06 (Fri, 06 Mar 2026)

Changed paths:
M Lib/fontTools/designspaceLib/__init__.py
M Lib/fontTools/feaLib/builder.py
M Lib/fontTools/feaLib/variableScalar.py
M Lib/fontTools/varLib/models.py
M Tests/feaLib/builder_test.py
M Tests/feaLib/variableScalar_test.py

Log Message:
-----------
Merge pull request #4054 from fonttools/varsca-interpolation

Fix interpolation of variable scalars, and allow on pre-compiled fonts (2)


Compare: https://github.com/fonttools/fonttools/compare/614863e321ad...d0d007bea8b5
Reply all
Reply to author
Forward
0 new messages