[varLib.avar] Test & fix _pruneLocations

This commit is contained in:
Behdad Esfahbod 2024-08-02 19:32:45 -06:00
parent 700b6a7b0e
commit 2742c6287c
2 changed files with 88 additions and 20 deletions

View File

@ -22,15 +22,16 @@ def _pruneLocations(locations, poles, axisTags):
model = VariationModel(locations, axisTags)
modelMapping = model.mapping
modelSupports = model.supports
pins = poles.copy()
for pole in poles.keys():
location = dict(pole)
pins = {tuple(k.items()): None for k in poles}
for location in poles:
i = locations.index(location)
i = modelMapping[i]
support = modelSupports[i]
supportAxes = set(support.keys())
for supportIndex, (axisTag, (minV, _, maxV)) in enumerate(support.items()):
for axisTag, (minV, _, maxV) in support.items():
for v in (minV, maxV):
if v in (-1, 0, 1):
continue
for pin in pins.keys():
pinLocation = dict(pin)
pinAxes = set(pinLocation.keys())
@ -40,21 +41,27 @@ def _pruneLocations(locations, poles, axisTags):
continue
if pinLocation[axisTag] == v:
break
else:
# No pin found. Go through the previous masters
# and find a suitable pin. Going backwards is
# better because it can find a pin that is close
# to the pole in more dimensions, and reducing
# the total number of pins needed.
for candidateIdx in range(supportIndex - 1, -1, -1):
candidate = modelSupports[candidateIdx]
candidateAxes = set(candidate.keys())
if candidateAxes != supportAxes:
continue
if axisTag not in candidateAxes:
continue
if candidateLocation[axisTag] == v:
pins[tuple(candidateLocation.items())] = None
else:
# No pin found. Go through the previous masters
# and find a suitable pin. Going backwards is
# better because it can find a pin that is close
# to the pole in more dimensions, and reducing
# the total number of pins needed.
for candidateIdx in range(i - 1, -1, -1):
candidate = modelSupports[candidateIdx]
candidateAxes = set(candidate.keys())
if candidateAxes != supportAxes:
continue
if axisTag not in candidateAxes:
continue
candidate = {
k: defaultV for k, (_, defaultV, _) in candidate.items()
}
if candidate[axisTag] == v:
pins[tuple(candidate.items())] = None
break
else:
assert False, "No pin found"
return [dict(t) for t in pins.keys()]
@ -115,7 +122,8 @@ def mappings_from_avar(font, denormalize=True):
key=lambda t: (len(t), tuple(axisIndexes[tag] for tag, _ in t)),
)
]
inputLocations = _pruneLocations(inputLocations, poles, axisTags)
poles = [dict(t) for t in poles.keys()]
inputLocations = _pruneLocations(inputLocations, list(poles), axisTags)
# Find the output locations, at input locations
varIdxMap = avar.table.VarIdxMap
@ -210,6 +218,7 @@ def main(args=None):
segments, mappings = mappings_from_avar(font)
pprint(segments)
pprint(mappings)
print(len(mappings), "mappings")
return
axisTags = [a.axisTag for a in font["fvar"].axes]

59
Tests/varLib/avar_test.py Normal file
View File

@ -0,0 +1,59 @@
from fontTools.varLib.avar import _pruneLocations
import unittest
import pytest
@pytest.mark.parametrize(
"locations, poles, expected",
[
(
[
{"wght": 1},
{"wght": 0.5},
],
[
{"wght": 0.5},
],
[
{"wght": 0.5},
],
),
(
[
{"wght": 1, "wdth": 1},
{"wght": 0.5, "wdth": 1},
],
[
{"wght": 1, "wdth": 1},
],
[
{"wght": 1, "wdth": 1},
{"wght": 0.5, "wdth": 1},
],
),
(
[
{"wght": 1},
{"wdth": 1},
{"wght": 0.5, "wdth": 0.5},
],
[
{"wght": 0.5, "wdth": 0.5},
],
[
{"wght": 0.5, "wdth": 0.5},
],
),
],
)
def test_pruneLocations(locations, poles, expected):
axisTags = set()
for location in locations:
axisTags.update(location.keys())
axisTags = sorted(axisTags)
locations = [{}] + locations
output = _pruneLocations(locations, poles, axisTags)
assert output == expected, (output, expected)