[VARC] More towards drawing

This commit is contained in:
Behdad Esfahbod 2023-12-16 00:37:55 -07:00
parent 68277fc0b5
commit 4b6c574d54
3 changed files with 69 additions and 21 deletions

View File

@ -17,6 +17,7 @@ from fontTools.misc.arrayTools import quantizeRect
from fontTools.misc.roundTools import otRound
from fontTools.misc.transform import Transform, Identity, DecomposedTransform
from fontTools.misc.textTools import bytesjoin, pad, safeEval
from fontTools.misc.vector import Vector
from fontTools.pens.boundsPen import ControlBoundsPen
from fontTools.pens.transformPen import TransformPen
from .otBase import (
@ -244,6 +245,7 @@ class VarComponent:
for attr_name, mapping_values in VAR_COMPONENT_TRANSFORM_MAPPING.items():
value = getattr(self.transform, attr_name)
# How to drop scaleX == scaleY here?
data.append(write_transform_component(value, mapping_values))
if flags & VarComponentFlags.TRANSFORM_HAS_VARIATION:
@ -323,6 +325,30 @@ class VarComponent:
result = self.__eq__(other)
return result if result is NotImplemented else not result
def getComponentValues(self):
flags = self.flags
if flags & VarComponentFlags.AXIS_VALUES_HAVE_VARIATION:
locationValues = [fl2fi(v, 14) for v in self.location.values()]
else:
locationValues = []
transformValues = []
def append_transform_component(value, values):
nonlocal transformValues
if flags & values.flag:
transformValues.append(
fl2fi(value / values.scale, values.fractionalBits)
)
if flags & VarComponentFlags.TRANSFORM_HAS_VARIATION:
for attr_name, mapping_values in VAR_COMPONENT_TRANSFORM_MAPPING.items():
value = getattr(self.transform, attr_name)
append_transform_component(value, mapping_values)
return Vector(locationValues), Vector(transformValues)
class CvarEncodedValues(BaseTable):
def __init__(self, values=None):

View File

@ -102,6 +102,7 @@ class _TTGlyphSetGlyf(_TTGlyphSet):
def __getitem__(self, glyphName):
return _TTGlyphGlyf(self, glyphName, recalcBounds=self.recalcBounds)
class _TTGlyphSetGlyf(_TTGlyphSet):
def __init__(self, font, location, recalcBounds=True):
self.glyfTable = font["glyf"]
@ -275,12 +276,15 @@ class _TTGlyphCFF(_TTGlyph):
class _TTGlyphVARC(_TTGlyph):
def _draw(self, pen, isPointPen):
"""Draw the glyph onto ``pen``. See fontTools.pens.basePen for details
how that works.
"""
from fontTools.ttLib.tables.otTables import VarComponentFlags
from fontTools.ttLib.tables.otTables import (
VarComponentFlags,
NO_VARIATION_INDEX,
)
glyphSet = self.glyphSet
varc = glyphSet.varcTable
idx = varc.Coverage.glyphs.index(self.name)
@ -288,27 +292,42 @@ class _TTGlyphVARC(_TTGlyph):
from fontTools.varLib.multiVarStore import MultiVarStoreInstancer
instancer = MultiVarStoreInstancer(varc.MultiVarStore, self.glyphSet.font["fvar"].axes, self.glyphSet.location)
instancer = MultiVarStoreInstancer(
varc.MultiVarStore, self.glyphSet.font["fvar"].axes, self.glyphSet.location
)
instancer.setLocation(self.glyphSet.location)
for comp in glyph.components:
comp = copy(comp) # Shallow copy
locationValues, transformValues = comp.getComponentValues()
comp = copy(comp) # Shallow copy
if comp.locationVarIndex != NO_VARIATION_INDEX:
assert locationValues
locationDeltas = instancer[comp.locationVarIndex]
locationValues = list(locationValues + locationDeltas)
if comp.transformVarIndex != NO_VARIATION_INDEX:
assert transformValues
transformDeltas = instancer[comp.transformVarIndex]
transformValues = list(transformValues + transformDeltas)
with self.glyphSet.glyphSet.pushLocation(
comp.location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES
):
try:
pen.addVarComponent(
comp.glyphName, comp.transform, self.glyphSet.rawLocation
)
except AttributeError:
t = comp.transform.toTransform()
if isPointPen:
tPen = TransformPointPen(pen, t)
self.glyphSet[comp.glyphName].drawPoints(tPen)
else:
tPen = TransformPen(pen, t)
self.glyphSet[comp.glyphName].draw(tPen)
with self.glyphSet.pushLocation(
comp.location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES
):
try:
pen.addVarComponent(
comp.glyphName, comp.transform, self.glyphSet.rawLocation
)
except AttributeError:
t = comp.transform.toTransform()
if isPointPen:
tPen = TransformPointPen(pen, t)
self.glyphSet[comp.glyphName].drawPoints(tPen)
else:
tPen = TransformPen(pen, t)
self.glyphSet[comp.glyphName].draw(tPen)
def draw(self, pen):
self._draw(pen, False)

View File

@ -166,19 +166,22 @@ class MultiVarStoreInstancer(object):
@staticmethod
def interpolateFromDeltasAndScalars(deltas, scalars):
assert len(deltas) % len(scalars) == 0
deltas = deltas.values
if not deltas:
return Vector([])
assert len(deltas) % len(scalars) == 0, (len(deltas), len(scalars))
m = len(deltas) // len(scalars)
delta = Vector([0] * m)
for d, s in zip((Vector(d) for d in batched(deltas, m)), scalars):
for d, s in zip(batched(deltas, m), scalars):
if not s:
continue
delta += d * s
return tuple(delta)
delta += Vector(d) * s
return delta
def __getitem__(self, varidx):
major, minor = varidx >> 16, varidx & 0xFFFF
if varidx == NO_VARIATION_INDEX:
return ()
return Vector([])
varData = self._varData
scalars = [self._getScalar(ri) for ri in varData[major].VarRegionIndex]
deltas = varData[major].Item[minor]