instancer: always calculate inferred deltas upfront to simplify code

and instead of sumDeltas method, use in-place add operator.
This commit is contained in:
Cosimo Lupo 2019-04-04 17:21:01 +01:00
parent 82085f5ea8
commit dc99925bee
No known key found for this signature in database
GPG Key ID: 20D4A261E4A0E642
3 changed files with 48 additions and 78 deletions

View File

@ -530,41 +530,32 @@ class TupleVariation(object):
if optimizedLength < unoptimizedLength:
self.coordinates = varOpt.coordinates
def sumDeltas(self, variations, origCoords=None, endPts=None):
# to sum the gvar deltas we need to first interpolate any inferred deltas
if origCoords is not None:
self.calcInferredDeltas(origCoords, endPts)
def __iadd__(self, other):
if not isinstance(other, TupleVariation):
return NotImplemented
deltas1 = self.coordinates
axes = self.axes
length = len(deltas1)
deltaRange = range(length)
deltaType = self.checkDeltaType()
for other in variations:
if other.axes != axes:
raise ValueError(
"cannot merge TupleVariations with different axes"
)
if origCoords is not None:
other.calcInferredDeltas(origCoords, endPts)
deltas2 = other.coordinates
if len(deltas2) != length:
raise ValueError(
"cannot merge TupleVariations with different lengths"
)
for i, d2 in zip(deltaRange, deltas2):
d1 = deltas1[i]
if d1 is not None and d2 is not None:
if deltaType == "gvar":
deltas1[i] = (d1[0] + d2[0], d1[1] + d2[1])
else:
deltas1[i] = d1 + d2
deltas2 = other.coordinates
if len(deltas2) != length:
raise ValueError(
"cannot sum TupleVariation deltas with different lengths"
)
for i, d2 in zip(range(length), deltas2):
d1 = deltas1[i]
if d1 is not None and d2 is not None:
if deltaType == "gvar":
deltas1[i] = (d1[0] + d2[0], d1[1] + d2[1])
else:
if deltaType == "gvar":
raise ValueError(
"cannot merge gvar deltas with inferred points"
)
if d1 is None and d2 is not None:
deltas1[i] = d2
deltas1[i] = d1 + d2
else:
if deltaType == "gvar":
raise ValueError(
"cannot sum gvar deltas with inferred points"
)
if d1 is None and d2 is not None:
deltas1[i] = d2
return self
def decompileSharedTuples(axisTags, sharedTupleCount, data, offset):

View File

@ -28,7 +28,7 @@ log = logging.getLogger("fontTools.varlib.instancer")
def instantiateTupleVariationStore(variations, location, origCoords=None, endPts=None):
varGroups = collections.OrderedDict()
newVariations = collections.OrderedDict()
for var in variations:
# Compute the scalar support of the axes to be pinned at the desired location,
# excluding any axes that we are not pinning.
@ -40,44 +40,28 @@ def instantiateTupleVariationStore(variations, location, origCoords=None, endPts
# no influence, drop the TupleVariation
continue
if origCoords is not None:
var.calcInferredDeltas(origCoords, endPts)
var.scaleDeltas(scalar)
# group TupleVariations by overlapping "tents" (can be empty if all the axes
# were instanced)
# merge TupleVariations with overlapping "tents"
axes = tuple(var.axes.items())
if axes in varGroups:
varGroups[axes].append(var)
if axes in newVariations:
newVariations[axes] += var
else:
varGroups[axes] = [var]
newVariations[axes] = var
# TupleVariations in which all axes have been pinned are dropped from gvar/cvar,
# their deltas summed up, rounded and subsequently added to the default instance
emptyAxes = ()
if emptyAxes in varGroups:
defaultVars = varGroups.pop(emptyAxes)
var = defaultVars.pop(0)
var.sumDeltas(defaultVars, origCoords, endPts)
for var in newVariations.values():
var.roundDeltas()
defaultDeltas = var.coordinates
else:
defaultDeltas = []
# merge remaining TupleVariations having the same axes
newVariations = []
for varGroup in varGroups.values():
var = varGroup.pop(0)
if varGroup:
var.sumDeltas(varGroup, origCoords, endPts)
elif origCoords is not None and defaultDeltas:
# if the default instance coordinates will be modified, all the inferred
# deltas that still remains need to be calculated using the original
# coordinates (can later be re-optimized using the modified ones)
var.calcInferredDeltas(origCoords, endPts)
var.roundDeltas()
newVariations.append(var)
variations[:] = newVariations
# drop TupleVariation if all axes have been pinned (var.axes.items() is empty);
# its deltas will be added to the default instance's coordinates
defaultVar = newVariations.pop(tuple(), None)
return defaultDeltas
variations[:] = list(newVariations.values())
return defaultVar.coordinates if defaultVar is not None else []
def instantiateGvarGlyph(varfont, glyphname, location, optimize=True):

View File

@ -788,29 +788,23 @@ class TupleVariationTest(unittest.TestCase):
var.optimize([(0, 0)]*129, list(range(129-4)), isComposite=True)
self.assertEqual(var.coordinates, [(0, 0)] + [None]*128)
def test_sumDeltas_gvar(self):
coordinates = [
(0, 0), (0, 100), (100, 100), (100, 0),
(0, 0), (100, 0), (0, 0), (0, 0),
]
endPts = [3]
axes = {"wght": (0.0, 1.0, 1.0)}
def test_sum_deltas_gvar(self):
var1 = TupleVariation(
axes,
{},
[
(-20, 0), None, None, (20, 0),
None, None, None, None,
(-20, 0), (-20, 0), (20, 0), (20, 0),
(0, 0), (0, 0), (0, 0), (0, 0),
]
)
var2 = TupleVariation(
axes,
{},
[
(-10, 0), None, None, (10, 0),
None, (20, 0), None, None,
(-10, 0), (-10, 0), (10, 0), (10, 0),
(0, 0), (20, 0), (0, 0), (0, 0),
]
)
var1.sumDeltas([var2], coordinates, endPts)
var1 += var2
self.assertEqual(
var1.coordinates,
@ -820,13 +814,14 @@ class TupleVariationTest(unittest.TestCase):
]
)
def test_sumDeltas_cvar(self):
def test_sum_deltas_cvar(self):
axes = {"wght": (0.0, 1.0, 1.0)}
var1 = TupleVariation(axes, [0, 1, None, None])
var2 = TupleVariation(axes, [None, 2, None, 3])
var3 = TupleVariation(axes, [None, None, None, 4])
var1.sumDeltas([var2, var3])
var1 += var2
var1 += var3
self.assertEqual(var1.coordinates, [0, 3, None, 7])