[instancer/L4] Address review comments

This commit is contained in:
Behdad Esfahbod 2023-07-10 12:42:17 -06:00
parent 71cca00b05
commit 0893ba93f8
4 changed files with 37 additions and 18 deletions

View File

@ -234,9 +234,29 @@ class AxisTriple(Sequence):
@dataclasses.dataclass(frozen=True, order=True, repr=False)
class NormalizedAxisTripleAndDistances(AxisTriple):
class NormalizedAxisTriple(AxisTriple):
"""A triple of (min, default, max) normalized axis values."""
minimum: float
default: float
maximum: float
def __post_init__(self):
if self.default is None:
object.__setattr__(self, "default", max(self.minimum, min(self.maximum, 0)))
if not (-1.0 <= self.minimum <= self.default <= self.maximum <= 1.0):
raise ValueError(
"Normalized axis values not in -1..+1 range; got "
f"minimum={self.minimum:g}, default={self.default:g}, maximum={self.maximum:g})"
)
@dataclasses.dataclass(frozen=True, order=True, repr=False)
class NormalizedAxisTripleAndDistances(AxisTriple):
"""A triple of (min, default, max) normalized axis values,
with distances between min and default, and default and max,
in the *pre-normalized* space."""
minimum: float
default: float
maximum: float
@ -256,7 +276,11 @@ class NormalizedAxisTripleAndDistances(AxisTriple):
v = self
return self.__class__(-v[2], -v[1], -v[0], v[4], v[3])
def normalizeValue(self, v, extrapolate=True):
def renormalizeValue(self, v, extrapolate=True):
"""Renormalizes a normalized value v to the range of this axis,
considering the pre-normalized distances as well as the new
axis limits."""
lower, default, upper, distanceNegative, distancePositive = self
assert lower <= default <= upper
@ -267,7 +291,7 @@ class NormalizedAxisTripleAndDistances(AxisTriple):
return 0
if default < 0:
return -self.reverse_negate().normalizeValue(-v, extrapolate=extrapolate)
return -self.reverse_negate().renormalizeValue(-v, extrapolate=extrapolate)
# default >= 0 and v != default
@ -288,12 +312,6 @@ class NormalizedAxisTripleAndDistances(AxisTriple):
else:
vDistance = -v * distanceNegative + distancePositive * default
if totalDistance == 0:
# This happens
if default == 0:
return -v / lower
return 0 # Shouldn't happen
return -vDistance / totalDistance
@ -558,7 +576,7 @@ def _instantiateGvarGlyph(
"Instancing accross VarComposite axes with variation is not supported."
)
limits = axisLimits[tag]
loc = limits.normalizeValue(loc, extrapolate=False)
loc = limits.renormalizeValue(loc, extrapolate=False)
newLocation[tag] = loc
component.location = newLocation
@ -989,10 +1007,10 @@ def instantiateAvar(varfont, axisLimits):
for fromCoord, toCoord in mapping.items():
if fromCoord < axisRange.minimum or fromCoord > axisRange.maximum:
continue
fromCoord = axisRange.normalizeValue(fromCoord)
fromCoord = axisRange.renormalizeValue(fromCoord)
assert mappedMin <= toCoord <= mappedMax
toCoord = mappedAxisLimit.normalizeValue(toCoord)
toCoord = mappedAxisLimit.renormalizeValue(toCoord)
fromCoord = floatToFixedToFloat(fromCoord, 14)
toCoord = floatToFixedToFloat(toCoord, 14)

View File

@ -41,7 +41,7 @@ def _limitFeatureVariationConditionRange(condition, axisLimit):
return
return tuple(
axisLimit.normalizeValue(v, extrapolate=False) for v in (minValue, maxValue)
axisLimit.renormalizeValue(v, extrapolate=False) for v in (minValue, maxValue)
)
@ -53,7 +53,7 @@ def _instantiateFeatureVariationRecord(
newConditions = []
from fontTools.varLib.instancer import NormalizedAxisTripleAndDistances
default_triple = NormalizedAxisTripleAndDistances(-1, 0, +1, 0, 0)
default_triple = NormalizedAxisTripleAndDistances(-1, 0, +1)
for i, condition in enumerate(record.ConditionSet.ConditionTable):
if condition.Format == 1:
axisIdx = condition.AxisIndex

View File

@ -12,7 +12,7 @@ def _reverse_negate(v):
def _solve(tent, axisLimit, negative=False):
axisMin, axisDef, axisMax, distanceNegative, distancePositive = axisLimit
axisMin, axisDef, axisMax, _distanceNegative, _distancePositive = axisLimit
lower, peak, upper = tent
# Mirror the problem such that axisDef <= peak
@ -285,7 +285,7 @@ def rebaseTent(tent, axisLimit):
If tent value is None, that is a special deltaset that should
be always-enabled (called "gain")."""
axisMin, axisDef, axisMax, distanceNegative, distancePositive = axisLimit
axisMin, axisDef, axisMax, _distanceNegative, _distancePositive = axisLimit
assert -1 <= axisMin <= axisDef <= axisMax <= +1
lower, peak, upper = tent
@ -295,7 +295,7 @@ def rebaseTent(tent, axisLimit):
sols = _solve(tent, axisLimit)
n = lambda v: axisLimit.normalizeValue(v)
n = lambda v: axisLimit.renormalizeValue(v)
sols = [
(scalar, (n(v[0]), n(v[1]), n(v[2])) if v is not None else None)
for scalar, v in sols

View File

@ -1950,7 +1950,7 @@ class LimitTupleVariationAxisRangesTest:
],
)
def test_positive_var(self, var, axisTag, newMax, expected):
axisRange = instancer.NormalizedAxisTripleAndDistances(0, 0, newMax, 1, 1)
axisRange = instancer.NormalizedAxisTripleAndDistances(0, 0, newMax)
self.check_limit_single_var_axis_range(var, axisTag, axisRange, expected)
@pytest.mark.parametrize(
@ -2094,6 +2094,7 @@ def test_parseLimits_invalid(limits):
@pytest.mark.parametrize(
"limits, expected",
[
# 300, 500 come from the font having 100,400,900 fvar axis limits.
({"wght": (100, 400)}, {"wght": (-1.0, 0, 0, 300, 500)}),
({"wght": (100, 400, 400)}, {"wght": (-1.0, 0, 0, 300, 500)}),
({"wght": (100, 300, 400)}, {"wght": (-1.0, -0.5, 0, 300, 500)}),