[instancer.solver] Implement no-gain in the general solution
This can replace the DefaultUnmoved
This commit is contained in:
parent
e94f564149
commit
bf55b28c50
@ -75,7 +75,6 @@ from fontTools.misc.fixedTools import (
|
||||
floatToFixedToFloat,
|
||||
strToFixedToFloat,
|
||||
otRound,
|
||||
MAX_F2DOT14,
|
||||
)
|
||||
from fontTools.varLib.models import supportScalar, normalizeValue, piecewiseLinearMap
|
||||
from fontTools.ttLib import TTFont
|
||||
|
@ -1,4 +1,5 @@
|
||||
from fontTools.varLib.models import supportScalar
|
||||
from fontTools.varLib.models import supportScalar, normalizeValue
|
||||
from fontTools.misc.fixedTools import MAX_F2DOT14
|
||||
|
||||
def _negate(*values):
|
||||
yield from (-1 * v for v in values)
|
||||
@ -105,14 +106,43 @@ def _solveDefaultUnmoved(tent, axisLimit):
|
||||
|
||||
|
||||
|
||||
def _solveNoGain(tent, axisLimit):
|
||||
axisMin, axisDef, axisMax = axisLimit
|
||||
lower, peak, upper = tent
|
||||
|
||||
# axisMin <= axisDef <= lower < peak <= axisMax
|
||||
|
||||
# case 3: outermost limit still fits within F2Dot14 bounds;
|
||||
# we keep deltas as is and only scale the axes bounds. Deltas beyond -1.0
|
||||
# or +1.0 will never be applied as implementations must clamp to that range.
|
||||
if axisDef + (axisMax - axisDef) * 2 >= upper:
|
||||
|
||||
if axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper:
|
||||
# we clamp +2.0 to the max F2Dot14 (~1.99994) for convenience
|
||||
upper = axisDef + (axisMax - axisDef) * MAX_F2DOT14
|
||||
|
||||
return [(1, (lower, peak, upper))]
|
||||
|
||||
# case 4: new limit doesn't fit; we need to chop the deltaset into two 'tents',
|
||||
# because the shape of a triangle with part of one side cut off cannot be
|
||||
# represented as a triangle itself. It can be represented as sum of two triangles.
|
||||
# NOTE: This increases the file size!
|
||||
else:
|
||||
|
||||
loc1 = (lower, peak, axisMax)
|
||||
scalar1 = 1
|
||||
|
||||
loc2 = (peak, axisMax, axisMax)
|
||||
scalar2 = supportScalar({tag: axisMax}, {tag: tent})
|
||||
|
||||
return [(scalar1, loc1), (scalar2, loc2)]
|
||||
|
||||
|
||||
def _solveGeneral(tent, axisLimit):
|
||||
axisMin, axisDef, axisMax = axisLimit
|
||||
lower, peak, upper = tent
|
||||
|
||||
# Mirror the problem such that axisDef is always <= peak
|
||||
if axisDef > peak:
|
||||
return [(scalar, _revnegate(t))
|
||||
for scalar,t
|
||||
@ -120,16 +150,24 @@ def _solveGeneral(tent, axisLimit):
|
||||
_revnegate(axisLimit))]
|
||||
# axisDef <= peak
|
||||
|
||||
# case 1: the whole deltaset falls outside the new limit; we can drop it
|
||||
if axisMax <= lower and axisMax < peak:
|
||||
return [] # No overlap
|
||||
|
||||
# case 2: only the peak and outermost bound fall outside the new limit;
|
||||
# we keep the deltaset, update peak and outermost bound and and scale deltas
|
||||
# by the scalar value for the restricted axis at the new limit.
|
||||
if axisMax < peak:
|
||||
mult = supportScalar({'tag': peak}, {'tag': axisLimit})
|
||||
mult = supportScalar({'tag': axisMax}, {'tag': tent})
|
||||
tent = (lower, axisMax, axisMax)
|
||||
return [(scalar*mult, t) for scalar,t in _solveGeneral(tent, axisLimit)]
|
||||
|
||||
# axisDef <= peak <= axisMax
|
||||
|
||||
if axisDef <= lower and axisDef < peak:
|
||||
# No gain to carry
|
||||
return _solveNoGain(tent, axisLimit)
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@ -148,7 +186,12 @@ def rebaseTent(tent, axisLimit):
|
||||
return _solvePinned(tent, axisLimit)
|
||||
|
||||
# If default isn't moving, get that out of the way as well
|
||||
if axisDef == 0:
|
||||
return _solveDefaultUnmoved(tent, axisLimit)
|
||||
if False and axisDef == 0:
|
||||
sols = _solveDefaultUnmoved(tent, axisLimit)
|
||||
print(sols)
|
||||
return sols
|
||||
|
||||
return _solveGeneral(tent, axisLimit)
|
||||
sols = _solveGeneral(tent, axisLimit)
|
||||
n = lambda v: normalizeValue(v, axisLimit, extrapolate=True)
|
||||
sols = [(scalar, (n(v[0]), n(v[1]), n(v[2]))) for scalar,v in sols if scalar != 0]
|
||||
return sols
|
||||
|
Loading…
x
Reference in New Issue
Block a user