From 6e156a7f13ad4f244ed61946d8ce6b1dd88e0d3e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 3 Nov 2022 12:51:59 -0600 Subject: [PATCH 1/6] [instancer] Split featureVars code into own module Towards fixing https://github.com/fonttools/fonttools/issues/2737 --- Lib/fontTools/varLib/instancer/__init__.py | 160 +---------------- Lib/fontTools/varLib/instancer/featureVars.py | 168 ++++++++++++++++++ Tests/varLib/instancer/instancer_test.py | 3 +- 3 files changed, 171 insertions(+), 160 deletions(-) create mode 100644 Lib/fontTools/varLib/instancer/featureVars.py diff --git a/Lib/fontTools/varLib/instancer/__init__.py b/Lib/fontTools/varLib/instancer/__init__.py index a8f0440f3..65ce2bbf0 100644 --- a/Lib/fontTools/varLib/instancer/__init__.py +++ b/Lib/fontTools/varLib/instancer/__init__.py @@ -100,6 +100,7 @@ from fontTools.varLib import builder from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib.merger import MutatorMerger from fontTools.varLib.instancer import names +from .featureVars import instantiateFeatureVariations from fontTools.misc.cliTools import makeOutputFileName from fontTools.varLib.instancer import solver import collections @@ -834,165 +835,6 @@ def instantiateOTL(varfont, axisLimits): del varfont["GDEF"] -def instantiateFeatureVariations(varfont, axisLimits): - for tableTag in ("GPOS", "GSUB"): - if tableTag not in varfont or not getattr( - varfont[tableTag].table, "FeatureVariations", None - ): - continue - log.info("Instantiating FeatureVariations of %s table", tableTag) - _instantiateFeatureVariations( - varfont[tableTag].table, varfont["fvar"].axes, axisLimits - ) - # remove unreferenced lookups - varfont[tableTag].prune_lookups() - - -def _featureVariationRecordIsUnique(rec, seen): - conditionSet = [] - for cond in rec.ConditionSet.ConditionTable: - if cond.Format != 1: - # can't tell whether this is duplicate, assume is unique - return True - conditionSet.append( - (cond.AxisIndex, cond.FilterRangeMinValue, cond.FilterRangeMaxValue) - ) - # besides the set of conditions, we also include the FeatureTableSubstitution - # version to identify unique FeatureVariationRecords, even though only one - # version is currently defined. It's theoretically possible that multiple - # records with same conditions but different substitution table version be - # present in the same font for backward compatibility. - recordKey = frozenset([rec.FeatureTableSubstitution.Version] + conditionSet) - if recordKey in seen: - return False - else: - seen.add(recordKey) # side effect - return True - - -def _limitFeatureVariationConditionRange(condition, axisLimit): - minValue = condition.FilterRangeMinValue - maxValue = condition.FilterRangeMaxValue - - if ( - minValue > maxValue - or minValue > axisLimit.maximum - or maxValue < axisLimit.minimum - ): - # condition invalid or out of range - return - - return tuple(normalizeValue(v, axisLimit) for v in (minValue, maxValue)) - - -def _instantiateFeatureVariationRecord( - record, recIdx, axisLimits, fvarAxes, axisIndexMap -): - applies = True - newConditions = [] - default_triple = NormalizedAxisTriple(-1, 0, +1) - for i, condition in enumerate(record.ConditionSet.ConditionTable): - if condition.Format == 1: - axisIdx = condition.AxisIndex - axisTag = fvarAxes[axisIdx].axisTag - - minValue = condition.FilterRangeMinValue - maxValue = condition.FilterRangeMaxValue - triple = axisLimits.get(axisTag, default_triple) - if not (minValue <= triple.default <= maxValue): - applies = False - # condition not met so remove entire record - if triple.minimum > maxValue or triple.maximum < minValue: - newConditions = None - break - - if axisTag in axisIndexMap: - # remap axis index - condition.AxisIndex = axisIndexMap[axisTag] - newConditions.append(condition) - else: - log.warning( - "Condition table {0} of FeatureVariationRecord {1} has " - "unsupported format ({2}); ignored".format(i, recIdx, condition.Format) - ) - applies = False - newConditions.append(condition) - - if newConditions: - record.ConditionSet.ConditionTable = newConditions - shouldKeep = True - else: - shouldKeep = False - - return applies, shouldKeep - - -def _limitFeatureVariationRecord(record, axisLimits, axisOrder): - newConditions = [] - for condition in record.ConditionSet.ConditionTable: - if condition.Format == 1: - axisIdx = condition.AxisIndex - axisTag = axisOrder[axisIdx] - if axisTag in axisLimits: - axisLimit = axisLimits[axisTag] - newRange = _limitFeatureVariationConditionRange(condition, axisLimit) - if newRange: - # keep condition with updated limits - minimum, maximum = newRange - condition.FilterRangeMinValue = minimum - condition.FilterRangeMaxValue = maximum - if minimum != -1 or maximum != +1: - newConditions.append(condition) - else: - # condition out of range, remove entire record - newConditions = None - break - else: - newConditions.append(condition) - else: - newConditions.append(condition) - - record.ConditionSet.ConditionTable = newConditions - return newConditions is not None - - -def _instantiateFeatureVariations(table, fvarAxes, axisLimits): - pinnedAxes = set(axisLimits.pinnedLocation()) - axisOrder = [axis.axisTag for axis in fvarAxes if axis.axisTag not in pinnedAxes] - axisIndexMap = {axisTag: axisOrder.index(axisTag) for axisTag in axisOrder} - - featureVariationApplied = False - uniqueRecords = set() - newRecords = [] - - for i, record in enumerate(table.FeatureVariations.FeatureVariationRecord): - applies, shouldKeep = _instantiateFeatureVariationRecord( - record, i, axisLimits, fvarAxes, axisIndexMap - ) - if shouldKeep: - shouldKeep = _limitFeatureVariationRecord(record, axisLimits, axisOrder) - - if shouldKeep and _featureVariationRecordIsUnique(record, uniqueRecords): - newRecords.append(record) - - if applies and not featureVariationApplied: - assert record.FeatureTableSubstitution.Version == 0x00010000 - for rec in record.FeatureTableSubstitution.SubstitutionRecord: - table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature = deepcopy( - rec.Feature - ) - # Set variations only once - featureVariationApplied = True - - if newRecords: - table.FeatureVariations.FeatureVariationRecord = newRecords - table.FeatureVariations.FeatureVariationCount = len(newRecords) - else: - del table.FeatureVariations - # downgrade table version if there are no FeatureVariations left - table.Version = 0x00010000 - - def _isValidAvarSegmentMap(axisTag, segmentMap): if not segmentMap: return True diff --git a/Lib/fontTools/varLib/instancer/featureVars.py b/Lib/fontTools/varLib/instancer/featureVars.py new file mode 100644 index 000000000..cdcfac659 --- /dev/null +++ b/Lib/fontTools/varLib/instancer/featureVars.py @@ -0,0 +1,168 @@ + +from fontTools.varLib.models import normalizeValue +from copy import deepcopy +import logging + + +log = logging.getLogger("fontTools.varLib.instancer.featureVars") + + +def _featureVariationRecordIsUnique(rec, seen): + conditionSet = [] + for cond in rec.ConditionSet.ConditionTable: + if cond.Format != 1: + # can't tell whether this is duplicate, assume is unique + return True + conditionSet.append( + (cond.AxisIndex, cond.FilterRangeMinValue, cond.FilterRangeMaxValue) + ) + # besides the set of conditions, we also include the FeatureTableSubstitution + # version to identify unique FeatureVariationRecords, even though only one + # version is currently defined. It's theoretically possible that multiple + # records with same conditions but different substitution table version be + # present in the same font for backward compatibility. + recordKey = frozenset([rec.FeatureTableSubstitution.Version] + conditionSet) + if recordKey in seen: + return False + else: + seen.add(recordKey) # side effect + return True + + +def _limitFeatureVariationConditionRange(condition, axisLimit): + minValue = condition.FilterRangeMinValue + maxValue = condition.FilterRangeMaxValue + + if ( + minValue > maxValue + or minValue > axisLimit.maximum + or maxValue < axisLimit.minimum + ): + # condition invalid or out of range + return + + return tuple(normalizeValue(v, axisLimit) for v in (minValue, maxValue)) + + +def _instantiateFeatureVariationRecord( + record, recIdx, axisLimits, fvarAxes, axisIndexMap +): + applies = True + newConditions = [] + from fontTools.varLib.instancer import NormalizedAxisTriple + default_triple = NormalizedAxisTriple(-1, 0, +1) + for i, condition in enumerate(record.ConditionSet.ConditionTable): + if condition.Format == 1: + axisIdx = condition.AxisIndex + axisTag = fvarAxes[axisIdx].axisTag + + minValue = condition.FilterRangeMinValue + maxValue = condition.FilterRangeMaxValue + triple = axisLimits.get(axisTag, default_triple) + if not (minValue <= triple.default <= maxValue): + applies = False + # condition not met so remove entire record + if triple.minimum > maxValue or triple.maximum < minValue: + newConditions = None + break + + if axisTag in axisIndexMap: + # remap axis index + condition.AxisIndex = axisIndexMap[axisTag] + newConditions.append(condition) + else: + log.warning( + "Condition table {0} of FeatureVariationRecord {1} has " + "unsupported format ({2}); ignored".format(i, recIdx, condition.Format) + ) + applies = False + newConditions.append(condition) + + if newConditions: + record.ConditionSet.ConditionTable = newConditions + shouldKeep = True + else: + shouldKeep = False + + return applies, shouldKeep + + +def _limitFeatureVariationRecord(record, axisLimits, axisOrder): + newConditions = [] + for condition in record.ConditionSet.ConditionTable: + if condition.Format == 1: + axisIdx = condition.AxisIndex + axisTag = axisOrder[axisIdx] + if axisTag in axisLimits: + axisLimit = axisLimits[axisTag] + newRange = _limitFeatureVariationConditionRange(condition, axisLimit) + if newRange: + # keep condition with updated limits + minimum, maximum = newRange + condition.FilterRangeMinValue = minimum + condition.FilterRangeMaxValue = maximum + if minimum != -1 or maximum != +1: + newConditions.append(condition) + else: + # condition out of range, remove entire record + newConditions = None + break + else: + newConditions.append(condition) + else: + newConditions.append(condition) + + record.ConditionSet.ConditionTable = newConditions + return newConditions is not None + + +def _instantiateFeatureVariations(table, fvarAxes, axisLimits): + pinnedAxes = set(axisLimits.pinnedLocation()) + axisOrder = [axis.axisTag for axis in fvarAxes if axis.axisTag not in pinnedAxes] + axisIndexMap = {axisTag: axisOrder.index(axisTag) for axisTag in axisOrder} + + featureVariationApplied = False + uniqueRecords = set() + newRecords = [] + + for i, record in enumerate(table.FeatureVariations.FeatureVariationRecord): + applies, shouldKeep = _instantiateFeatureVariationRecord( + record, i, axisLimits, fvarAxes, axisIndexMap + ) + if shouldKeep: + shouldKeep = _limitFeatureVariationRecord(record, axisLimits, axisOrder) + + if shouldKeep and _featureVariationRecordIsUnique(record, uniqueRecords): + newRecords.append(record) + + if applies and not featureVariationApplied: + assert record.FeatureTableSubstitution.Version == 0x00010000 + for rec in record.FeatureTableSubstitution.SubstitutionRecord: + table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature = deepcopy( + rec.Feature + ) + # Set variations only once + featureVariationApplied = True + + if newRecords: + table.FeatureVariations.FeatureVariationRecord = newRecords + table.FeatureVariations.FeatureVariationCount = len(newRecords) + else: + del table.FeatureVariations + # downgrade table version if there are no FeatureVariations left + table.Version = 0x00010000 + + +def instantiateFeatureVariations(varfont, axisLimits): + for tableTag in ("GPOS", "GSUB"): + if tableTag not in varfont or not getattr( + varfont[tableTag].table, "FeatureVariations", None + ): + continue + log.info("Instantiating FeatureVariations of %s table", tableTag) + _instantiateFeatureVariations( + varfont[tableTag].table, varfont["fvar"].axes, axisLimits + ) + # remove unreferenced lookups + varfont[tableTag].prune_lookups() + diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py index f4d266dd4..b3e40ebe7 100644 --- a/Tests/varLib/instancer/instancer_test.py +++ b/Tests/varLib/instancer/instancer_test.py @@ -9,6 +9,7 @@ from fontTools.ttLib.tables import otTables from fontTools.ttLib.tables.TupleVariation import TupleVariation from fontTools import varLib from fontTools.varLib import instancer +from fontTools.varLib.instancer import featureVars as instancer_featureVars from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib import builder from fontTools.varLib import featureVars @@ -1975,7 +1976,7 @@ class LimitTupleVariationAxisRangesTest: def test_limitFeatureVariationConditionRange(oldRange, newLimit, expected): condition = featureVars.buildConditionTable(0, *oldRange) - result = instancer._limitFeatureVariationConditionRange( + result = instancer_featureVars._limitFeatureVariationConditionRange( condition, instancer.NormalizedAxisTriple(*newLimit) ) From ecfcdffe9fff3e1cab06d86703242f2d5fa21401 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 3 Nov 2022 14:22:02 -0600 Subject: [PATCH 2/6] [instancer.featureVars] Combine two functions Fold _limitFeatureVariationRecord() into _instantiateFeatureVariationRecord(). --- Lib/fontTools/varLib/instancer/featureVars.py | 52 +++++++------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/featureVars.py b/Lib/fontTools/varLib/instancer/featureVars.py index cdcfac659..c2843266a 100644 --- a/Lib/fontTools/varLib/instancer/featureVars.py +++ b/Lib/fontTools/varLib/instancer/featureVars.py @@ -48,6 +48,7 @@ def _instantiateFeatureVariationRecord( record, recIdx, axisLimits, fvarAxes, axisIndexMap ): applies = True + shouldKeep = False newConditions = [] from fontTools.varLib.instancer import NormalizedAxisTriple default_triple = NormalizedAxisTriple(-1, 0, +1) @@ -69,7 +70,23 @@ def _instantiateFeatureVariationRecord( if axisTag in axisIndexMap: # remap axis index condition.AxisIndex = axisIndexMap[axisTag] - newConditions.append(condition) + + # remap condition limits + newRange = _limitFeatureVariationConditionRange(condition, triple) + if newRange: + # keep condition with updated limits + minimum, maximum = newRange + condition.FilterRangeMinValue = minimum + condition.FilterRangeMaxValue = maximum + shouldKeep = True + if minimum != -1 or maximum != +1: + newConditions.append(condition) + else: + # condition out of range, remove entire record + newConditions = None + break + + else: log.warning( "Condition table {0} of FeatureVariationRecord {1} has " @@ -78,7 +95,7 @@ def _instantiateFeatureVariationRecord( applies = False newConditions.append(condition) - if newConditions: + if newConditions is not None and shouldKeep: record.ConditionSet.ConditionTable = newConditions shouldKeep = True else: @@ -87,35 +104,6 @@ def _instantiateFeatureVariationRecord( return applies, shouldKeep -def _limitFeatureVariationRecord(record, axisLimits, axisOrder): - newConditions = [] - for condition in record.ConditionSet.ConditionTable: - if condition.Format == 1: - axisIdx = condition.AxisIndex - axisTag = axisOrder[axisIdx] - if axisTag in axisLimits: - axisLimit = axisLimits[axisTag] - newRange = _limitFeatureVariationConditionRange(condition, axisLimit) - if newRange: - # keep condition with updated limits - minimum, maximum = newRange - condition.FilterRangeMinValue = minimum - condition.FilterRangeMaxValue = maximum - if minimum != -1 or maximum != +1: - newConditions.append(condition) - else: - # condition out of range, remove entire record - newConditions = None - break - else: - newConditions.append(condition) - else: - newConditions.append(condition) - - record.ConditionSet.ConditionTable = newConditions - return newConditions is not None - - def _instantiateFeatureVariations(table, fvarAxes, axisLimits): pinnedAxes = set(axisLimits.pinnedLocation()) axisOrder = [axis.axisTag for axis in fvarAxes if axis.axisTag not in pinnedAxes] @@ -129,8 +117,6 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): applies, shouldKeep = _instantiateFeatureVariationRecord( record, i, axisLimits, fvarAxes, axisIndexMap ) - if shouldKeep: - shouldKeep = _limitFeatureVariationRecord(record, axisLimits, axisOrder) if shouldKeep and _featureVariationRecordIsUnique(record, uniqueRecords): newRecords.append(record) From 1b6f4fb8585464fa6f7fa9649a39c05e269577ae Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 3 Nov 2022 14:30:06 -0600 Subject: [PATCH 3/6] [instancer.featureVars] Minor adjustments --- Lib/fontTools/varLib/instancer/featureVars.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/featureVars.py b/Lib/fontTools/varLib/instancer/featureVars.py index c2843266a..5b5ddfd7b 100644 --- a/Lib/fontTools/varLib/instancer/featureVars.py +++ b/Lib/fontTools/varLib/instancer/featureVars.py @@ -60,12 +60,14 @@ def _instantiateFeatureVariationRecord( minValue = condition.FilterRangeMinValue maxValue = condition.FilterRangeMaxValue triple = axisLimits.get(axisTag, default_triple) + if not (minValue <= triple.default <= maxValue): applies = False - # condition not met so remove entire record - if triple.minimum > maxValue or triple.maximum < minValue: - newConditions = None - break + + # if condition not met, remove entire record + if triple.minimum > maxValue or triple.maximum < minValue: + newConditions = None + break if axisTag in axisIndexMap: # remap axis index @@ -101,7 +103,10 @@ def _instantiateFeatureVariationRecord( else: shouldKeep = False - return applies, shouldKeep + # Does this *always* apply? + universal = shouldKeep and not newConditions + + return applies, shouldKeep, universal def _instantiateFeatureVariations(table, fvarAxes, axisLimits): @@ -114,7 +119,7 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): newRecords = [] for i, record in enumerate(table.FeatureVariations.FeatureVariationRecord): - applies, shouldKeep = _instantiateFeatureVariationRecord( + applies, shouldKeep, universal = _instantiateFeatureVariationRecord( record, i, axisLimits, fvarAxes, axisIndexMap ) @@ -130,6 +135,10 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): # Set variations only once featureVariationApplied = True + # Further records don't have a chance to apply after a universal record + if universal: + break + if newRecords: table.FeatureVariations.FeatureVariationRecord = newRecords table.FeatureVariations.FeatureVariationCount = len(newRecords) From 392706949ce378f4b4061f349fd38bd99323ddc3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 3 Nov 2022 14:55:01 -0600 Subject: [PATCH 4/6] [instancer.featureVars] Fix deficiency in L4 instancing See discussion on the issue. I think I got this right. Fixes https://github.com/fonttools/fonttools/issues/2737 --- Lib/fontTools/varLib/instancer/featureVars.py | 17 ++++++++++++++++- Tests/varLib/instancer/instancer_test.py | 8 +++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/featureVars.py b/Lib/fontTools/varLib/instancer/featureVars.py index 5b5ddfd7b..12eefac24 100644 --- a/Lib/fontTools/varLib/instancer/featureVars.py +++ b/Lib/fontTools/varLib/instancer/featureVars.py @@ -1,4 +1,5 @@ +from fontTools.ttLib.tables import otTables as ot from fontTools.varLib.models import normalizeValue from copy import deepcopy import logging @@ -117,6 +118,7 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): featureVariationApplied = False uniqueRecords = set() newRecords = [] + defaultsSubsts = None for i, record in enumerate(table.FeatureVariations.FeatureVariationRecord): applies, shouldKeep, universal = _instantiateFeatureVariationRecord( @@ -128,7 +130,10 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): if applies and not featureVariationApplied: assert record.FeatureTableSubstitution.Version == 0x00010000 - for rec in record.FeatureTableSubstitution.SubstitutionRecord: + defaultsSubsts = deepcopy(record.FeatureTableSubstitution) + for default,rec in zip(defaultsSubsts.SubstitutionRecord, + record.FeatureTableSubstitution.SubstitutionRecord): + default.Feature = deepcopy(table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature) table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature = deepcopy( rec.Feature ) @@ -139,6 +144,16 @@ def _instantiateFeatureVariations(table, fvarAxes, axisLimits): if universal: break + # Insert a catch-all record to reinstate the old features if necessary + if featureVariationApplied and newRecords and not universal: + defaultRecord = ot.FeatureVariationRecord() + defaultRecord.ConditionSet = ot.ConditionSet() + defaultRecord.ConditionSet.ConditionTable = [] + defaultRecord.ConditionSet.ConditionCount = 0 + defaultRecord.FeatureTableSubstitution = defaultsSubsts + + newRecords.append(defaultRecord) + if newRecords: table.FeatureVariations.FeatureVariationRecord = newRecords table.FeatureVariations.FeatureVariationCount = len(newRecords) diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py index b3e40ebe7..9d77155a9 100644 --- a/Tests/varLib/instancer/instancer_test.py +++ b/Tests/varLib/instancer/instancer_test.py @@ -1588,13 +1588,13 @@ class InstantiateFeatureVariationsTest(object): "location, appliedSubs, expectedRecords", [ ({"wght": 0}, {}, [({"cntr": (0.75, 1.0)}, {"uni0041": "uni0061"})]), - # Buggy. See: https://github.com/fonttools/fonttools/issues/2737 ( {"wght": -1.0}, {"uni0061": "uni0041"}, [ ({"cntr": (0, 0.25)}, {"uni0061": "uni0041"}), ({"cntr": (0.75, 1.0)}, {"uni0041": "uni0061"}), + ({}, {}), ], ), ( @@ -1604,7 +1604,8 @@ class InstantiateFeatureVariationsTest(object): ( {"cntr": (0.75, 1.0)}, {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"}, - ) + ), + ({}, {}) ], ), ( @@ -1622,7 +1623,8 @@ class InstantiateFeatureVariationsTest(object): ( {"wght": (0.20886, 1.0)}, {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"}, - ) + ), + ({}, {}) ], ), ( From ea2ae7df86a363535ddbcb9d9234d0af2278a675 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 3 Nov 2022 17:15:40 -0600 Subject: [PATCH 5/6] [instancer.featureVars] Add one more test --- Tests/varLib/instancer/instancer_test.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py index 9d77155a9..aee53f751 100644 --- a/Tests/varLib/instancer/instancer_test.py +++ b/Tests/varLib/instancer/instancer_test.py @@ -1663,6 +1663,28 @@ class InstantiateFeatureVariationsTest(object): ), ], ), + ( + {"cntr": (0.7, 0.9, 1.0)}, + {"uni0041": "uni0061"}, + [ + ( + {'cntr': (-0.7499999999999999, 1.0), 'wght': (0.20886, 1.0)}, + {"uni0024": "uni0024.nostroke", "uni0041": "uni0061"}, + ), + ( + {'cntr': (-0.7499999999999999, 1.0)}, + {"uni0041": "uni0061"}, + ), + ( + {"wght": (0.20886, 1.0)}, + {"uni0024": "uni0024.nostroke"}, + ), + ( + {}, + {}, + ), + ], + ), ], ) def test_partial_instance(self, location, appliedSubs, expectedRecords): From 672c4bacddffacf0ef83f5c06196785b409e6719 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 4 Nov 2022 11:55:48 -0600 Subject: [PATCH 6/6] [instancer.featureVars] Address review comments --- Lib/fontTools/varLib/instancer/featureVars.py | 2 +- Tests/varLib/instancer/instancer_test.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/fontTools/varLib/instancer/featureVars.py b/Lib/fontTools/varLib/instancer/featureVars.py index 12eefac24..8d56eea60 100644 --- a/Lib/fontTools/varLib/instancer/featureVars.py +++ b/Lib/fontTools/varLib/instancer/featureVars.py @@ -5,7 +5,7 @@ from copy import deepcopy import logging -log = logging.getLogger("fontTools.varLib.instancer.featureVars") +log = logging.getLogger("fontTools.varLib.instancer") def _featureVariationRecordIsUnique(rec, seen): diff --git a/Tests/varLib/instancer/instancer_test.py b/Tests/varLib/instancer/instancer_test.py index aee53f751..b1807ab74 100644 --- a/Tests/varLib/instancer/instancer_test.py +++ b/Tests/varLib/instancer/instancer_test.py @@ -9,7 +9,6 @@ from fontTools.ttLib.tables import otTables from fontTools.ttLib.tables.TupleVariation import TupleVariation from fontTools import varLib from fontTools.varLib import instancer -from fontTools.varLib.instancer import featureVars as instancer_featureVars from fontTools.varLib.mvar import MVAR_ENTRIES from fontTools.varLib import builder from fontTools.varLib import featureVars @@ -2000,7 +1999,7 @@ class LimitTupleVariationAxisRangesTest: def test_limitFeatureVariationConditionRange(oldRange, newLimit, expected): condition = featureVars.buildConditionTable(0, *oldRange) - result = instancer_featureVars._limitFeatureVariationConditionRange( + result = instancer.featureVars._limitFeatureVariationConditionRange( condition, instancer.NormalizedAxisTriple(*newLimit) )