From 9cc3689fb16504921075666861dccee5a9dcefaa Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 19 Dec 2023 16:07:27 -0700 Subject: [PATCH] [VARC] Towards drawing new design --- Lib/fontTools/ttLib/tables/otTables.py | 24 +++++++++++- Lib/fontTools/ttLib/ttGlyphSet.py | 53 ++++++++++++++++---------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Lib/fontTools/ttLib/tables/otTables.py b/Lib/fontTools/ttLib/tables/otTables.py index 5dd52cd2c..4e073bac7 100644 --- a/Lib/fontTools/ttLib/tables/otTables.py +++ b/Lib/fontTools/ttLib/tables/otTables.py @@ -143,6 +143,8 @@ class VarTransform: else: flags = self.flags + data.append(struct.pack(">H", flags)) + if flags & VarTransformFlags.HAVE_VARIATIONS: data.append(struct.pack(">L", self.varIndex)) @@ -158,7 +160,7 @@ class VarTransform: value = getattr(self.transform, attr_name) data.append(write_transform_component(value, mapping_values)) - return struct.pack(">H", flags) + bytesjoin(data) + return bytesjoin(data) def toXML(self, writer, ttFont, attrs, name): if self.varIndex != NO_VARIATION_INDEX: @@ -184,6 +186,26 @@ class VarTransform: v = str2fl(safeEval(attrs[attr_name]), mapping.fractionalBits) setattr(self.transform, attr_name, v) + def applyDeltas(deltas): + i = 0 + + def read_transform_component_delta(data, values): + nonlocal i + if self.flags & values.flag: + v = fi2fl(data[i], values.fractionalBits) * values.scale + i += 1 + return v + else: + return 0 + + for attr_name, mapping_values in VAR_TRANSFORM_MAPPING.items(): + value = read_transform_component_delta(data, mapping_values) + setattr( + self.transform, attr_name, getattr(self.transform, attr_name) + value + ) + + assert i == len(deltas) + def __eq__(self, other): if type(self) != type(other): return NotImplemented diff --git a/Lib/fontTools/ttLib/ttGlyphSet.py b/Lib/fontTools/ttLib/ttGlyphSet.py index d848c8670..d5107236b 100644 --- a/Lib/fontTools/ttLib/ttGlyphSet.py +++ b/Lib/fontTools/ttLib/ttGlyphSet.py @@ -5,9 +5,10 @@ from collections.abc import Mapping from contextlib import contextmanager from copy import copy from types import SimpleNamespace +from fontTools.misc.vector import Vector from fontTools.misc.fixedTools import otRound from fontTools.misc.loggingTools import deprecateFunction -from fontTools.misc.transform import Transform +from fontTools.misc.transform import Transform, DecomposedTransform from fontTools.pens.transformPen import TransformPen, TransformPointPen from fontTools.pens.recordingPen import ( DecomposingRecordingPen, @@ -288,42 +289,54 @@ class _TTGlyphVARC(_TTGlyph): glyphSet = self.glyphSet varc = glyphSet.varcTable idx = varc.Coverage.glyphs.index(self.name) - glyph = varc.VarCompositeGlyphs.glyphs[idx] + glyph = varc.VarCompositeGlyphs.VarCompositeGlyph[idx] from fontTools.varLib.multiVarStore import MultiVarStoreInstancer + fvarAxes = glyphSet.font["fvar"].axes instancer = MultiVarStoreInstancer( - varc.MultiVarStore, self.glyphSet.font["fvar"].axes, self.glyphSet.location + varc.MultiVarStore, fvarAxes, self.glyphSet.location ) - instancer.setLocation(self.glyphSet.location) for comp in glyph.components: - comp = copy(comp) # Shallow copy - locationValues, transformValues = comp.getComponentValues() + location = {} + assert (comp.AxisIndicesIndex is None) == (comp.AxisValuesIndex is None) + if comp.AxisIndicesIndex is not None: + axisIndices = varc.AxisIndicesList.Item[comp.AxisIndicesIndex] + axisValues = Vector(varc.AxisValuesList.Item[comp.AxisValuesIndex]) + # Apply variations + varIdx = NO_VARIATION_INDEX + if comp.AxisValuesIndex < varc.AxisValuesList.VarIndicesCount: + varIdx = varc.AxisValuesList.VarIndices[comp.AxisValuesIndex] + if varIdx != NO_VARIATION_INDEX: + axisValues = ( + axisValues + instancer[varIdx] + ) # TODO Implement __iadd__ for Vector + location = { + fvarAxes[i].axisTag: v for i, v in zip(axisIndices, axisValues) + } - if comp.locationVarIndex != NO_VARIATION_INDEX: - assert len(locationValues) - locationDeltas = instancer[comp.locationVarIndex] - locationValues = list(locationValues + locationDeltas) - if comp.transformVarIndex != NO_VARIATION_INDEX: - assert len(transformValues) - transformDeltas = instancer[comp.transformVarIndex] - transformValues = list(transformValues + transformDeltas) - - comp.setComponentValues(locationValues, transformValues) + transform = DecomposedTransform() + if comp.TransformIndex is not None: + varTransform = varc.TransformList.VarTransform[comp.TransformIndex] + varIdx = varTransform.varIndex + if varIdx != NO_VARIATION_INDEX: + deltas = instancer[varIdx] + varTransform.applyDeltas(deltas) + transform = varTransform.transform with self.glyphSet.glyphSet.pushLocation( - comp.location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES + location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES ): with self.glyphSet.pushLocation( - comp.location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES + location, comp.flags & VarComponentFlags.RESET_UNSPECIFIED_AXES ): try: pen.addVarComponent( - comp.glyphName, comp.transform, self.glyphSet.rawLocation + comp.glyphName, transform, self.glyphSet.rawLocation ) except AttributeError: - t = comp.transform.toTransform() + t = transform.toTransform() compGlyphSet = ( self.glyphSet if comp.glyphName != self.name