[varLib.mutator] Implement IUP
This commit is contained in:
parent
10ff112e6a
commit
997c073e26
@ -11,6 +11,94 @@ from fontTools.varLib import _GetCoordinates, _SetCoordinates
|
||||
from fontTools.varLib.models import VariationModel, supportScalar, normalizeLocation
|
||||
import os.path
|
||||
|
||||
|
||||
def _iup_segment(coords, rc1, rd1, rc2, rd2):
|
||||
# rc1 = reference coord 1
|
||||
# rd1 = reference delta 1
|
||||
out_arrays = [None, None]
|
||||
for j in 0,1:
|
||||
out_arrays[j] = out = []
|
||||
x1, x2, d1, d2 = rc1[j], rc2[j], rd1[j], rd2[j]
|
||||
|
||||
|
||||
if x1 == x2:
|
||||
n = len(coords)
|
||||
if d1 == d2:
|
||||
out.extend([d1]*n)
|
||||
else:
|
||||
out.extend([0]*n)
|
||||
continue
|
||||
|
||||
if x1 > x2:
|
||||
x1, x2 = x2, x1
|
||||
d1, d2 = d2, d1
|
||||
|
||||
# x1 < x2
|
||||
scale = (d2 - d1) / (x2 - x1)
|
||||
for pair in coords:
|
||||
x = pair[j]
|
||||
|
||||
if x <= x1:
|
||||
d = d1
|
||||
elif x >= x2:
|
||||
d = d2
|
||||
else:
|
||||
# Interpolate
|
||||
d = d1 + (x - x1) * scale
|
||||
|
||||
out.append(d)
|
||||
|
||||
return zip(*out_arrays)
|
||||
|
||||
def _iup_contour(delta, coords):
|
||||
assert len(delta) == len(coords)
|
||||
if None not in delta:
|
||||
return delta
|
||||
|
||||
n = len(delta)
|
||||
# indices of points with explicit deltas
|
||||
indices = [i for i,v in enumerate(delta) if v is not None]
|
||||
if not indices:
|
||||
# All deltas are None. Return 0,0 for all.
|
||||
return [(0,0)]*n
|
||||
|
||||
out = []
|
||||
it = iter(indices)
|
||||
start = next(it)
|
||||
if start != 0:
|
||||
# Initial segment that wraps around
|
||||
i1, i2, ri1, ri2 = 0, start, start, indices[-1]
|
||||
out.extend(_iup_segment(coords[i1:i2], coords[ri1], delta[ri1], coords[ri2], delta[ri2]))
|
||||
out.append(delta[start])
|
||||
for end in it:
|
||||
if end - start > 1:
|
||||
i1, i2, ri1, ri2 = start+1, end, start, end
|
||||
out.extend(_iup_segment(coords[i1:i2], coords[ri1], delta[ri1], coords[ri2], delta[ri2]))
|
||||
out.append(delta[end])
|
||||
start = end
|
||||
if start != n-1:
|
||||
# Final segment that wraps around
|
||||
i1, i2, ri1, ri2 = start+1, n, start, indices[0]
|
||||
out.extend(_iup_segment(coords[i1:i2], coords[ri1], delta[ri1], coords[ri2], delta[ri2]))
|
||||
|
||||
assert len(delta) == len(out), (len(delta), len(out))
|
||||
return out
|
||||
|
||||
def _iup_delta(delta, coords, ends):
|
||||
assert sorted(ends) == ends and len(coords) == (ends[-1]+1 if ends else 0) + 4
|
||||
n = len(coords)
|
||||
ends = ends + [n-4, n-3, n-2, n-1]
|
||||
out = []
|
||||
start = 0
|
||||
for end in ends:
|
||||
end += 1
|
||||
contour = _iup_contour(delta[start:end], coords[start:end])
|
||||
out.extend(contour)
|
||||
start = end
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def main(args=None):
|
||||
|
||||
if args is None:
|
||||
@ -59,6 +147,7 @@ def main(args=None):
|
||||
if origCoords is None:
|
||||
origCoords,control = _GetCoordinates(varfont, glyphname)
|
||||
endPts = control[1] if control[0] >= 1 else list(range(len(control[1])))
|
||||
delta = _iup_delta(delta, origCoords, endPts)
|
||||
# TODO Do IUP / handle None items
|
||||
coordinates += GlyphCoordinates(delta) * scalar
|
||||
_SetCoordinates(varfont, glyphname, coordinates)
|
||||
|
Loading…
x
Reference in New Issue
Block a user