From e2a875b26c8b25525928be983a5c29606b25bc70 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 9 Aug 2022 17:18:58 -0600 Subject: [PATCH] [instancer] Implement featureVariations L4 instancing I *think* this is all. --- Lib/fontTools/varLib/instancer/__init__.py | 18 ++++++------ Tests/varLib/instancer/instancer_test.py | 32 ++++++++++++---------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/__init__.py b/Lib/fontTools/varLib/instancer/__init__.py index 102166989..e3b50e283 100644 --- a/Lib/fontTools/varLib/instancer/__init__.py +++ b/Lib/fontTools/varLib/instancer/__init__.py @@ -678,21 +678,21 @@ def _featureVariationRecordIsUnique(rec, seen): return True -def _limitFeatureVariationConditionRange(condition, axisRange): +def _limitFeatureVariationConditionRange(condition, axisLimit): minValue = condition.FilterRangeMinValue maxValue = condition.FilterRangeMaxValue if ( minValue > maxValue - or minValue > axisRange.maximum - or maxValue < axisRange.minimum + or minValue > axisLimit.maximum + or maxValue < axisLimit.minimum ): # condition invalid or out of range return values = [minValue, maxValue] for i, value in enumerate(values): - values[i] = normalizeValue(value, (axisRange.minimum, 0, axisRange.maximum)) + values[i] = normalizeValue(value, axisLimit) return AxisRange(*values) @@ -737,15 +737,15 @@ def _instantiateFeatureVariationRecord( return applies, shouldKeep -def _limitFeatureVariationRecord(record, axisRanges, axisOrder): +def _limitFeatureVariationRecord(record, axisLimits, axisOrder): newConditions = [] for i, condition in enumerate(record.ConditionSet.ConditionTable): if condition.Format == 1: axisIdx = condition.AxisIndex axisTag = axisOrder[axisIdx] - if axisTag in axisRanges: - axisRange = axisRanges[axisTag] - newRange = _limitFeatureVariationConditionRange(condition, axisRange) + if axisTag in axisLimits: + axisLimit = axisLimits[axisTag] + newRange = _limitFeatureVariationConditionRange(condition, axisLimit) if newRange: # keep condition with updated limits and remapped axis index condition.FilterRangeMinValue = newRange.minimum @@ -786,7 +786,7 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): record, i, location, fvarAxes, axisIndexMap ) if shouldKeep: - shouldKeep = _limitFeatureVariationRecord(record, axisRanges, axisOrder) + shouldKeep = _limitFeatureVariationRecord(record, axisLimits, axisOrder) if shouldKeep and _featureVariationRecordIsUnique(record, uniqueRecords): newRecords.append(record) diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py index 1adb67313..93403daf4 100644 --- a/Tests/varLib/instancer/instancer_test.py +++ b/Tests/varLib/instancer/instancer_test.py @@ -1589,7 +1589,9 @@ class InstantiateFeatureVariationsTest(object): ] ) - instancer.instantiateFeatureVariations(font, location) + limits = {tag:instancer.NormalizedAxisTent(l, l, l) + for tag,l in location.items()} + instancer.instantiateFeatureVariations(font, limits) gsub = font["GSUB"].table featureVariations = gsub.FeatureVariations @@ -1668,7 +1670,7 @@ class InstantiateFeatureVariationsTest(object): rec1.ConditionSet.ConditionTable[0].Format = 2 with caplog.at_level(logging.WARNING, logger="fontTools.varLib.instancer"): - instancer.instantiateFeatureVariations(font, {"wdth": 0}) + instancer.instantiateFeatureVariations(font, {"wdth": instancer.NormalizedAxisTent(0,0,0)}) assert ( "Condition table 0 of FeatureVariationRecord 0 " @@ -1864,25 +1866,25 @@ class LimitTupleVariationAxisRangesTest: @pytest.mark.parametrize( - "oldRange, newRange, expected", + "oldRange, newLimit, expected", [ - ((1.0, -1.0), (-1.0, 1.0), None), # invalid oldRange min > max - ((0.6, 1.0), (0, 0.5), None), - ((-1.0, -0.6), (-0.5, 0), None), - ((0.4, 1.0), (0, 0.5), (0.8, 1.0)), - ((-1.0, -0.4), (-0.5, 0), (-1.0, -0.8)), - ((0.4, 1.0), (0, 0.4), (1.0, 1.0)), - ((-1.0, -0.4), (-0.4, 0), (-1.0, -1.0)), - ((-0.5, 0.5), (-0.4, 0.4), (-1.0, 1.0)), - ((0, 1.0), (-1.0, 0), (0, 0)), # or None? - ((-1.0, 0), (0, 1.0), (0, 0)), # or None? + ((1.0, -1.0), (-1.0, 0, 1.0), None), # invalid oldRange min > max + ((0.6, 1.0), (0, 0, 0.5), None), + ((-1.0, -0.6), (-0.5, 0, 0), None), + ((0.4, 1.0), (0, 0, 0.5), (0.8, 1.0)), + ((-1.0, -0.4), (-0.5, 0, 0), (-1.0, -0.8)), + ((0.4, 1.0), (0, 0, 0.4), (1.0, 1.0)), + ((-1.0, -0.4), (-0.4, 0, 0), (-1.0, -1.0)), + ((-0.5, 0.5), (-0.4, 0, 0.4), (-1.0, 1.0)), + ((0, 1.0), (-1.0, 0, 0), (0, 0)), # or None? + ((-1.0, 0), (0, 0, 1.0), (0, 0)), # or None? ], ) -def test_limitFeatureVariationConditionRange(oldRange, newRange, expected): +def test_limitFeatureVariationConditionRange(oldRange, newLimit, expected): condition = featureVars.buildConditionTable(0, *oldRange) result = instancer._limitFeatureVariationConditionRange( - condition, instancer.NormalizedAxisRange(*newRange) + condition, instancer.NormalizedAxisTent(*newLimit) ) assert result == expected