Apply avar to variable locations
This commit is contained in:
parent
a993247e47
commit
cf43ff5d22
@ -1614,6 +1614,7 @@ class Builder(object):
|
||||
deviceX = otl.buildDevice(dict(anchor.xDeviceTable))
|
||||
if anchor.yDeviceTable is not None:
|
||||
deviceY = otl.buildDevice(dict(anchor.yDeviceTable))
|
||||
avar = self.font.get("avar")
|
||||
for dim in ("x", "y"):
|
||||
if not isinstance(getattr(anchor, dim), VariableScalar):
|
||||
continue
|
||||
@ -1627,7 +1628,9 @@ class Builder(object):
|
||||
)
|
||||
varscalar = getattr(anchor, dim)
|
||||
varscalar.axes = self.axes
|
||||
default, index = varscalar.add_to_variation_store(self.varstorebuilder)
|
||||
default, index = varscalar.add_to_variation_store(
|
||||
self.varstorebuilder, avar
|
||||
)
|
||||
setattr(anchor, dim, default)
|
||||
if index is not None and index != 0xFFFFFFFF:
|
||||
if dim == "x":
|
||||
@ -1654,6 +1657,7 @@ class Builder(object):
|
||||
if not v:
|
||||
return None
|
||||
|
||||
avar = self.font.get("avar")
|
||||
vr = {}
|
||||
for astName, (otName, isDevice) in self._VALUEREC_ATTRS.items():
|
||||
val = getattr(v, astName, None)
|
||||
@ -1674,7 +1678,7 @@ class Builder(object):
|
||||
location,
|
||||
)
|
||||
val.axes = self.axes
|
||||
default, index = val.add_to_variation_store(self.varstorebuilder)
|
||||
default, index = val.add_to_variation_store(self.varstorebuilder, avar)
|
||||
vr[otName] = default
|
||||
if index is not None and index != 0xFFFFFFFF:
|
||||
vr[otDeviceName] = buildVarDevTable(index)
|
||||
|
@ -1,4 +1,4 @@
|
||||
from fontTools.varLib.models import VariationModel, normalizeValue
|
||||
from fontTools.varLib.models import VariationModel, normalizeValue, piecewiseLinearMap
|
||||
|
||||
|
||||
def Location(loc):
|
||||
@ -83,29 +83,37 @@ class VariableScalar:
|
||||
# I *guess* we could interpolate one, but I don't know how.
|
||||
return self.values[key]
|
||||
|
||||
def value_at_location(self, location):
|
||||
def value_at_location(self, location, avar=None):
|
||||
loc = location
|
||||
if loc in self.values.keys():
|
||||
return self.values[loc]
|
||||
values = list(self.values.values())
|
||||
return self.model.interpolateFromMasters(loc, values)
|
||||
return self.model(avar).interpolateFromMasters(loc, values)
|
||||
|
||||
@property
|
||||
def model(self):
|
||||
def model(self, avar=None):
|
||||
key = tuple(self.values.keys())
|
||||
if key in self.model_pool:
|
||||
return self.model_pool[key]
|
||||
locations = [dict(self._normalized_location(k)) for k in self.values.keys()]
|
||||
if avar is not None:
|
||||
mapping = avar.segments
|
||||
locations = [
|
||||
{
|
||||
k: piecewiseLinearMap(v, mapping[k]) if k in mapping else v
|
||||
for k, v in location.items()
|
||||
}
|
||||
for location in locations
|
||||
]
|
||||
m = VariationModel(locations)
|
||||
self.model_pool[key] = m
|
||||
return m
|
||||
|
||||
def get_deltas_and_supports(self):
|
||||
def get_deltas_and_supports(self, avar=None):
|
||||
values = list(self.values.values())
|
||||
return self.model.getDeltasAndSupports(values)
|
||||
return self.model(avar).getDeltasAndSupports(values)
|
||||
|
||||
def add_to_variation_store(self, store_builder):
|
||||
deltas, supports = self.get_deltas_and_supports()
|
||||
def add_to_variation_store(self, store_builder, avar=None):
|
||||
deltas, supports = self.get_deltas_and_supports(avar)
|
||||
store_builder.setSupports(supports)
|
||||
index = store_builder.storeDeltas(deltas)
|
||||
return int(self.default), index
|
||||
|
@ -1034,6 +1034,64 @@ class BuilderTest(unittest.TestCase):
|
||||
assert condition_table[0].FilterRangeMinValue == 0.5
|
||||
assert condition_table[1].FilterRangeMinValue == 0.7
|
||||
|
||||
def test_variable_scalar_avar(self):
|
||||
"""Test that the `avar` table is consulted when normalizing user-space
|
||||
values."""
|
||||
|
||||
features = """
|
||||
languagesystem DFLT dflt;
|
||||
|
||||
feature kern {
|
||||
pos cursive one <anchor 0 (wght=200:12 wght=900:22 wdth=150,wght=900:42)> <anchor NULL>;
|
||||
pos two <0 (wght=200:12 wght=900:22 wdth=150,wght=900:42) 0 0>;
|
||||
} kern;
|
||||
"""
|
||||
|
||||
def make_mock_vf():
|
||||
font = makeTTFont()
|
||||
font["name"] = newTable("name")
|
||||
addFvar(font, self.VARFONT_AXES, [])
|
||||
del font["name"]
|
||||
return font
|
||||
|
||||
def get_region(var_region_axis):
|
||||
return (
|
||||
var_region_axis.StartCoord,
|
||||
var_region_axis.PeakCoord,
|
||||
var_region_axis.EndCoord,
|
||||
)
|
||||
|
||||
# Without `avar` (wght=200, wdth=100 is the default location):
|
||||
font = make_mock_vf()
|
||||
addOpenTypeFeaturesFromString(font, features)
|
||||
|
||||
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 get_region(var_region_axis_wght) == (0.0, 0.875, 0.875)
|
||||
assert 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 get_region(var_region_axis_wght) == (0.0, 0.875, 0.875)
|
||||
assert get_region(var_region_axis_wdth) == (0.0, 0.5, 0.5)
|
||||
|
||||
# With `avar`, shifting the wght axis' positive midpoint 0.5 a bit to
|
||||
# the right, but leaving the wdth axis alone:
|
||||
font = make_mock_vf()
|
||||
font["avar"] = newTable("avar")
|
||||
font["avar"].segments = {"wght": {-1.0: -1.0, 0.0: 0.0, 0.5: 0.625, 1.0: 1.0}}
|
||||
addOpenTypeFeaturesFromString(font, features)
|
||||
|
||||
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 get_region(var_region_axis_wght) == (0.0, 0.90625, 0.90625)
|
||||
assert 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 get_region(var_region_axis_wght) == (0.0, 0.90625, 0.90625)
|
||||
assert get_region(var_region_axis_wdth) == (0.0, 0.5, 0.5)
|
||||
|
||||
|
||||
def generate_feature_file_test(name):
|
||||
return lambda self: self.check_feature_file(name)
|
||||
|
Loading…
x
Reference in New Issue
Block a user