[varLib.models] By default, assume OpenType-like normalized space
See: https://github.com/fonttools/fonttools/pull/2846#issuecomment-2267750076 I *think* this is an improvement, and no one should have been relying on the broken existing behavior. Docs need updating.
This commit is contained in:
parent
ead2a18d4b
commit
0c2652011e
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -16,7 +16,7 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.875"/>
|
||||
<EndCoord value="0.875"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
<VarRegionAxis index="1">
|
||||
<StartCoord value="0.0"/>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.875"/>
|
||||
<EndCoord value="0.875"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
<VarRegionAxis index="1">
|
||||
<StartCoord value="0.0"/>
|
||||
@ -24,12 +24,12 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.875"/>
|
||||
<EndCoord value="0.875"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
<VarRegionAxis index="1">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.5"/>
|
||||
<EndCoord value="0.5"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
</Region>
|
||||
</VarRegionList>
|
||||
|
@ -12,7 +12,7 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.875"/>
|
||||
<EndCoord value="0.875"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
<VarRegionAxis index="1">
|
||||
<StartCoord value="0.0"/>
|
||||
@ -24,12 +24,12 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.875"/>
|
||||
<EndCoord value="0.875"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
<VarRegionAxis index="1">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.5"/>
|
||||
<EndCoord value="0.5"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
</Region>
|
||||
</VarRegionList>
|
||||
|
@ -23,7 +23,7 @@
|
||||
<VarRegionAxis index="0">
|
||||
<StartCoord value="0.0"/>
|
||||
<PeakCoord value="0.38"/>
|
||||
<EndCoord value="0.38"/>
|
||||
<EndCoord value="1.0"/>
|
||||
</VarRegionAxis>
|
||||
</Region>
|
||||
</VarRegionList>
|
||||
|
Loading…
x
Reference in New Issue
Block a user