diff --git a/Lib/fontTools/varLib/models.py b/Lib/fontTools/varLib/models.py
index 819596991..fadfa242c 100644
--- a/Lib/fontTools/varLib/models.py
+++ b/Lib/fontTools/varLib/models.py
@@ -209,10 +209,14 @@ def supportScalar(location, support, ot=True, extrapolate=False, axisRanges=None
class VariationModel(object):
"""Locations must have the base master at the origin (ie. 0).
+ If axis-ranges are not provided, values are assumed to be normalized to
+ the range [-1, 1].
+
If the extrapolate argument is set to True, then values are extrapolated
outside the axis range.
>>> from pprint import pprint
+ >>> axisRanges = {'wght': (-180, +180), 'wdth': (-1, +1)}
>>> locations = [ \
{'wght':100}, \
{'wght':-100}, \
@@ -224,7 +228,7 @@ class VariationModel(object):
{'wght':+180,'wdth':.3}, \
{'wght':+180}, \
]
- >>> model = VariationModel(locations, axisOrder=['wght'])
+ >>> model = VariationModel(locations, axisOrder=['wght'], axisRanges=axisRanges)
>>> pprint(model.locations)
[{},
{'wght': -100},
@@ -252,14 +256,22 @@ class VariationModel(object):
7: 0.6666666666666667}]
"""
- def __init__(self, locations, axisOrder=None, extrapolate=False):
+ def __init__(
+ self, locations, axisOrder=None, extrapolate=False, *, axisRanges=None
+ ):
if len(set(tuple(sorted(l.items())) for l in locations)) != len(locations):
raise VariationModelError("Locations must be unique.")
self.origLocations = locations
self.axisOrder = axisOrder if axisOrder is not None else []
self.extrapolate = extrapolate
- self.axisRanges = self.computeAxisRanges(locations) if extrapolate else None
+ if axisRanges is None:
+ if extrapolate:
+ axisRanges = self.computeAxisRanges(locations)
+ else:
+ allAxes = {axis for loc in locations for axis in loc.keys()}
+ axisRanges = {axis: (-1, 1) for axis in allAxes}
+ self.axisRanges = axisRanges
locations = [{k: v for k, v in loc.items() if v != 0.0} for loc in locations]
keyFunc = self.getMasterLocationsSortKeyFunc(
@@ -425,23 +437,16 @@ class VariationModel(object):
def _locationsToRegions(self):
locations = self.locations
- # Compute min/max across each axis, use it as total range.
- # TODO Take this as input from outside?
- minV = {}
- maxV = {}
- for l in locations:
- for k, v in l.items():
- minV[k] = min(v, minV.get(k, v))
- maxV[k] = max(v, maxV.get(k, v))
+ axisRanges = self.axisRanges
regions = []
for loc in locations:
region = {}
for axis, locV in loc.items():
if locV > 0:
- region[axis] = (0, locV, maxV[axis])
+ region[axis] = (0, locV, axisRanges[axis][1])
else:
- region[axis] = (minV[axis], locV, 0)
+ region[axis] = (axisRanges[axis][0], locV, 0)
regions.append(region)
return regions
diff --git a/Tests/feaLib/builder_test.py b/Tests/feaLib/builder_test.py
index e2f6a1d4d..6c1fdab24 100644
--- a/Tests/feaLib/builder_test.py
+++ b/Tests/feaLib/builder_test.py
@@ -1112,12 +1112,12 @@ class BuilderTest(unittest.TestCase):
var_region_list = font.tables["GDEF"].table.VarStore.VarRegionList
var_region_axis_wght = var_region_list.Region[0].VarRegionAxis[0]
var_region_axis_wdth = var_region_list.Region[0].VarRegionAxis[1]
- assert self.get_region(var_region_axis_wght) == (0.0, 0.875, 0.875)
+ assert self.get_region(var_region_axis_wght) == (0.0, 0.875, 1.0)
assert self.get_region(var_region_axis_wdth) == (0.0, 0.0, 0.0)
var_region_axis_wght = var_region_list.Region[1].VarRegionAxis[0]
var_region_axis_wdth = var_region_list.Region[1].VarRegionAxis[1]
- assert self.get_region(var_region_axis_wght) == (0.0, 0.875, 0.875)
- assert self.get_region(var_region_axis_wdth) == (0.0, 0.5, 0.5)
+ assert self.get_region(var_region_axis_wght) == (0.0, 0.875, 1.0)
+ assert self.get_region(var_region_axis_wdth) == (0.0, 0.5, 1.0)
# With `avar`, shifting the wght axis' positive midpoint 0.5 a bit to
# the right, but leaving the wdth axis alone:
@@ -1129,12 +1129,12 @@ class BuilderTest(unittest.TestCase):
var_region_list = font.tables["GDEF"].table.VarStore.VarRegionList
var_region_axis_wght = var_region_list.Region[0].VarRegionAxis[0]
var_region_axis_wdth = var_region_list.Region[0].VarRegionAxis[1]
- assert self.get_region(var_region_axis_wght) == (0.0, 0.90625, 0.90625)
+ assert self.get_region(var_region_axis_wght) == (0.0, 0.90625, 1.0)
assert self.get_region(var_region_axis_wdth) == (0.0, 0.0, 0.0)
var_region_axis_wght = var_region_list.Region[1].VarRegionAxis[0]
var_region_axis_wdth = var_region_list.Region[1].VarRegionAxis[1]
- assert self.get_region(var_region_axis_wght) == (0.0, 0.90625, 0.90625)
- assert self.get_region(var_region_axis_wdth) == (0.0, 0.5, 0.5)
+ assert self.get_region(var_region_axis_wght) == (0.0, 0.90625, 1.0)
+ assert self.get_region(var_region_axis_wdth) == (0.0, 0.5, 1.0)
def test_ligatureCaretByPos_variable_scalar(self):
"""Test that the `avar` table is consulted when normalizing user-space
@@ -1158,7 +1158,7 @@ class BuilderTest(unittest.TestCase):
var_region_list = table.VarStore.VarRegionList
var_region_axis = var_region_list.Region[0].VarRegionAxis[0]
- assert self.get_region(var_region_axis) == (0.0, 0.875, 0.875)
+ assert self.get_region(var_region_axis) == (0.0, 0.875, 1.0)
def generate_feature_file_test(name):
diff --git a/Tests/feaLib/data/variable_mark_anchor.ttx b/Tests/feaLib/data/variable_mark_anchor.ttx
index 962cff741..d29fc43a1 100644
--- a/Tests/feaLib/data/variable_mark_anchor.ttx
+++ b/Tests/feaLib/data/variable_mark_anchor.ttx
@@ -16,7 +16,7 @@
-
+
diff --git a/Tests/feaLib/data/variable_scalar_anchor.ttx b/Tests/feaLib/data/variable_scalar_anchor.ttx
index 6bb55691f..92a456d3b 100644
--- a/Tests/feaLib/data/variable_scalar_anchor.ttx
+++ b/Tests/feaLib/data/variable_scalar_anchor.ttx
@@ -12,7 +12,7 @@
-
+
@@ -24,12 +24,12 @@
-
+
-
+
diff --git a/Tests/feaLib/data/variable_scalar_valuerecord.ttx b/Tests/feaLib/data/variable_scalar_valuerecord.ttx
index e3251f691..94bd3867d 100644
--- a/Tests/feaLib/data/variable_scalar_valuerecord.ttx
+++ b/Tests/feaLib/data/variable_scalar_valuerecord.ttx
@@ -12,7 +12,7 @@
-
+
@@ -24,12 +24,12 @@
-
+
-
+
diff --git a/Tests/varLib/data/test_results/BuildAvar2.ttx b/Tests/varLib/data/test_results/BuildAvar2.ttx
index 27a41bfbb..493d9bdbb 100644
--- a/Tests/varLib/data/test_results/BuildAvar2.ttx
+++ b/Tests/varLib/data/test_results/BuildAvar2.ttx
@@ -23,7 +23,7 @@
-
+