diff --git a/Lib/fontTools/fontBuilder.py b/Lib/fontTools/fontBuilder.py index dd57a0507..16b7ee167 100644 --- a/Lib/fontTools/fontBuilder.py +++ b/Lib/fontTools/fontBuilder.py @@ -656,11 +656,7 @@ class FontBuilder(object): if validateGlyphFormat and self.font["head"].glyphDataFormat == 0: for name, g in glyphs.items(): - if g.isVarComposite(): - raise ValueError( - f"Glyph {name!r} is a variable composite, but glyphDataFormat=0" - ) - elif g.numberOfContours > 0 and any(f & flagCubic for f in g.flags): + if g.numberOfContours > 0 and any(f & flagCubic for f in g.flags): raise ValueError( f"Glyph {name!r} has cubic Bezier outlines, but glyphDataFormat=0; " "either convert to quadratics with cu2qu or set glyphDataFormat=1." diff --git a/Lib/fontTools/merge/tables.py b/Lib/fontTools/merge/tables.py index d132cb2a0..208a5099f 100644 --- a/Lib/fontTools/merge/tables.py +++ b/Lib/fontTools/merge/tables.py @@ -225,7 +225,7 @@ def merge(self, m, tables): g.removeHinting() # Expand composite glyphs to load their # composite glyph names. - if g.isComposite() or g.isVarComposite(): + if g.isComposite(): g.expand(table) return DefaultTable.merge(self, m, tables) diff --git a/Lib/fontTools/ttLib/scaleUpem.py b/Lib/fontTools/ttLib/scaleUpem.py index 2909bfcb2..0df563f27 100644 --- a/Lib/fontTools/ttLib/scaleUpem.py +++ b/Lib/fontTools/ttLib/scaleUpem.py @@ -11,7 +11,6 @@ from fontTools.cffLib import VarStoreData import fontTools.cffLib.specializer as cffSpecializer from fontTools.varLib import builder # for VarData.calculateNumShorts from fontTools.misc.fixedTools import otRound -from fontTools.ttLib.tables._g_l_y_f import VarComponentFlags __all__ = ["scale_upem", "ScalerVisitor"] @@ -123,13 +122,6 @@ def visit(visitor, obj, attr, glyphs): component.y = visitor.scale(component.y) continue - if g.isVarComposite(): - for component in g.components: - for attr in ("translateX", "translateY", "tCenterX", "tCenterY"): - v = getattr(component.transform, attr) - setattr(component.transform, attr, visitor.scale(v)) - continue - if hasattr(g, "coordinates"): coordinates = g.coordinates for i, (x, y) in enumerate(coordinates): @@ -138,56 +130,15 @@ def visit(visitor, obj, attr, glyphs): @ScalerVisitor.register_attr(ttLib.getTableClass("gvar"), "variations") def visit(visitor, obj, attr, variations): - # VarComposites are a pain to handle :-( glyfTable = visitor.font["glyf"] for glyphName, varlist in variations.items(): glyph = glyfTable[glyphName] - isVarComposite = glyph.isVarComposite() for var in varlist: coordinates = var.coordinates - - if not isVarComposite: - for i, xy in enumerate(coordinates): - if xy is None: - continue - coordinates[i] = visitor.scale(xy[0]), visitor.scale(xy[1]) - continue - - # VarComposite glyph - - i = 0 - for component in glyph.components: - if component.flags & VarComponentFlags.AXES_HAVE_VARIATION: - i += len(component.location) - if component.flags & ( - VarComponentFlags.HAVE_TRANSLATE_X - | VarComponentFlags.HAVE_TRANSLATE_Y - ): - xy = coordinates[i] - coordinates[i] = visitor.scale(xy[0]), visitor.scale(xy[1]) - i += 1 - if component.flags & VarComponentFlags.HAVE_ROTATION: - i += 1 - if component.flags & ( - VarComponentFlags.HAVE_SCALE_X | VarComponentFlags.HAVE_SCALE_Y - ): - i += 1 - if component.flags & ( - VarComponentFlags.HAVE_SKEW_X | VarComponentFlags.HAVE_SKEW_Y - ): - i += 1 - if component.flags & ( - VarComponentFlags.HAVE_TCENTER_X | VarComponentFlags.HAVE_TCENTER_Y - ): - xy = coordinates[i] - coordinates[i] = visitor.scale(xy[0]), visitor.scale(xy[1]) - i += 1 - - # Phantom points - assert i + 4 == len(coordinates) - for i in range(i, len(coordinates)): - xy = coordinates[i] + for i, xy in enumerate(coordinates): + if xy is None: + continue coordinates[i] = visitor.scale(xy[0]), visitor.scale(xy[1]) diff --git a/Lib/fontTools/ttLib/tables/_g_l_y_f.py b/Lib/fontTools/ttLib/tables/_g_l_y_f.py index 683912be9..fa11cf8f4 100644 --- a/Lib/fontTools/ttLib/tables/_g_l_y_f.py +++ b/Lib/fontTools/ttLib/tables/_g_l_y_f.py @@ -424,29 +424,6 @@ class table__g_l_y_f(DefaultTable.DefaultTable): for c in glyph.components ], ) - elif glyph.isVarComposite(): - coords = [] - controls = [] - - for component in glyph.components: - ( - componentCoords, - componentControls, - ) = component.getCoordinatesAndControls() - coords.extend(componentCoords) - controls.extend(componentControls) - - coords = GlyphCoordinates(coords) - - controls = _GlyphControls( - numberOfContours=glyph.numberOfContours, - endPts=list(range(len(coords))), - flags=None, - components=[ - (c.glyphName, getattr(c, "flags", None)) for c in glyph.components - ], - ) - else: coords, endPts, flags = glyph.getCoordinates(self) coords = coords.copy() @@ -492,10 +469,6 @@ class table__g_l_y_f(DefaultTable.DefaultTable): for p, comp in zip(coord, glyph.components): if hasattr(comp, "x"): comp.x, comp.y = p - elif glyph.isVarComposite(): - for comp in glyph.components: - coord = comp.setCoordinates(coord) - assert not coord elif glyph.numberOfContours == 0: assert len(coord) == 0 else: @@ -737,8 +710,6 @@ class Glyph(object): return if self.isComposite(): self.decompileComponents(data, glyfTable) - elif self.isVarComposite(): - self.decompileVarComponents(data, glyfTable) else: self.decompileCoordinates(data) @@ -758,8 +729,6 @@ class Glyph(object): data = sstruct.pack(glyphHeaderFormat, self) if self.isComposite(): data = data + self.compileComponents(glyfTable) - elif self.isVarComposite(): - data = data + self.compileVarComponents(glyfTable) else: data = data + self.compileCoordinates() return data @@ -769,10 +738,6 @@ class Glyph(object): for compo in self.components: compo.toXML(writer, ttFont) haveInstructions = hasattr(self, "program") - elif self.isVarComposite(): - for compo in self.components: - compo.toXML(writer, ttFont) - haveInstructions = False else: last = 0 for i in range(self.numberOfContours): @@ -842,15 +807,6 @@ class Glyph(object): component = GlyphComponent() self.components.append(component) component.fromXML(name, attrs, content, ttFont) - elif name == "varComponent": - if self.numberOfContours > 0: - raise ttLib.TTLibError("can't mix composites and contours in glyph") - self.numberOfContours = -2 - if not hasattr(self, "components"): - self.components = [] - component = GlyphVarComponent() - self.components.append(component) - component.fromXML(name, attrs, content, ttFont) elif name == "instructions": self.program = ttProgram.Program() for element in content: @@ -860,7 +816,7 @@ class Glyph(object): self.program.fromXML(name, attrs, content, ttFont) def getCompositeMaxpValues(self, glyfTable, maxComponentDepth=1): - assert self.isComposite() or self.isVarComposite() + assert self.isComposite() nContours = 0 nPoints = 0 initialMaxComponentDepth = maxComponentDepth @@ -904,13 +860,6 @@ class Glyph(object): len(data), ) - def decompileVarComponents(self, data, glyfTable): - self.components = [] - while len(data) >= GlyphVarComponent.MIN_SIZE: - component = GlyphVarComponent() - data = component.decompile(data, glyfTable) - self.components.append(component) - def decompileCoordinates(self, data): endPtsOfContours = array.array("H") endPtsOfContours.frombytes(data[: 2 * self.numberOfContours]) @@ -1027,9 +976,6 @@ class Glyph(object): data = data + struct.pack(">h", len(instructions)) + instructions return data - def compileVarComponents(self, glyfTable): - return b"".join(c.compile(glyfTable) for c in self.components) - def compileCoordinates(self): assert len(self.coordinates) == len(self.flags) data = [] @@ -1231,13 +1177,6 @@ class Glyph(object): else: return self.numberOfContours == -1 - def isVarComposite(self): - """Test whether a glyph has variable components""" - if hasattr(self, "data"): - return struct.unpack(">h", self.data[:2])[0] == -2 if self.data else False - else: - return self.numberOfContours == -2 - def getCoordinates(self, glyfTable): """Return the coordinates, end points and flags @@ -1308,8 +1247,6 @@ class Glyph(object): allCoords.extend(coordinates) allFlags.extend(flags) return allCoords, allEndPts, allFlags - elif self.isVarComposite(): - raise NotImplementedError("use TTGlyphSet to draw VarComposite glyphs") else: return GlyphCoordinates(), [], bytearray() @@ -1319,12 +1256,8 @@ class Glyph(object): This method can be used on simple glyphs (in which case it returns an empty list) or composite glyphs. """ - if hasattr(self, "data") and self.isVarComposite(): - # TODO(VarComposite) Add implementation without expanding glyph - self.expand(glyfTable) - if not hasattr(self, "data"): - if self.isComposite() or self.isVarComposite(): + if self.isComposite(): return [c.glyphName for c in self.components] else: return [] @@ -1367,8 +1300,6 @@ class Glyph(object): if self.isComposite(): if hasattr(self, "program"): del self.program - elif self.isVarComposite(): - pass # Doesn't have hinting else: self.program = ttProgram.Program() self.program.fromBytecode([]) @@ -1450,13 +1381,6 @@ class Glyph(object): i += 2 + instructionLen # Remove padding data = data[:i] - elif self.isVarComposite(): - i = 0 - MIN_SIZE = GlyphVarComponent.MIN_SIZE - while len(data[i : i + MIN_SIZE]) >= MIN_SIZE: - size = GlyphVarComponent.getSize(data[i : i + MIN_SIZE]) - i += size - data = data[:i] self.data = data @@ -1942,391 +1866,6 @@ class GlyphComponent(object): return result if result is NotImplemented else not result -# -# Variable Composite glyphs -# https://github.com/harfbuzz/boring-expansion-spec/blob/main/glyf1.md -# - - -class VarComponentFlags(IntFlag): - USE_MY_METRICS = 0x0001 - AXIS_INDICES_ARE_SHORT = 0x0002 - UNIFORM_SCALE = 0x0004 - HAVE_TRANSLATE_X = 0x0008 - HAVE_TRANSLATE_Y = 0x0010 - HAVE_ROTATION = 0x0020 - HAVE_SCALE_X = 0x0040 - HAVE_SCALE_Y = 0x0080 - HAVE_SKEW_X = 0x0100 - HAVE_SKEW_Y = 0x0200 - HAVE_TCENTER_X = 0x0400 - HAVE_TCENTER_Y = 0x0800 - GID_IS_24BIT = 0x1000 - AXES_HAVE_VARIATION = 0x2000 - RESET_UNSPECIFIED_AXES = 0x4000 - - -VarComponentTransformMappingValues = namedtuple( - "VarComponentTransformMappingValues", - ["flag", "fractionalBits", "scale", "defaultValue"], -) - -VAR_COMPONENT_TRANSFORM_MAPPING = { - "translateX": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_TRANSLATE_X, 0, 1, 0 - ), - "translateY": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_TRANSLATE_Y, 0, 1, 0 - ), - "rotation": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_ROTATION, 12, 180, 0 - ), - "scaleX": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_SCALE_X, 10, 1, 1 - ), - "scaleY": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_SCALE_Y, 10, 1, 1 - ), - "skewX": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_SKEW_X, 12, -180, 0 - ), - "skewY": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_SKEW_Y, 12, 180, 0 - ), - "tCenterX": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_TCENTER_X, 0, 1, 0 - ), - "tCenterY": VarComponentTransformMappingValues( - VarComponentFlags.HAVE_TCENTER_Y, 0, 1, 0 - ), -} - - -class GlyphVarComponent(object): - MIN_SIZE = 5 - - def __init__(self): - self.location = {} - self.transform = DecomposedTransform() - - @staticmethod - def getSize(data): - size = 5 - flags = struct.unpack(">H", data[:2])[0] - numAxes = int(data[2]) - - if flags & VarComponentFlags.GID_IS_24BIT: - size += 1 - - size += numAxes - if flags & VarComponentFlags.AXIS_INDICES_ARE_SHORT: - size += 2 * numAxes - else: - axisIndices = array.array("B", data[:numAxes]) - size += numAxes - - for attr_name, mapping_values in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - if flags & mapping_values.flag: - size += 2 - - return size - - def decompile(self, data, glyfTable): - flags = struct.unpack(">H", data[:2])[0] - self.flags = int(flags) - data = data[2:] - - numAxes = int(data[0]) - data = data[1:] - - if flags & VarComponentFlags.GID_IS_24BIT: - glyphID = int(struct.unpack(">L", b"\0" + data[:3])[0]) - data = data[3:] - flags ^= VarComponentFlags.GID_IS_24BIT - else: - glyphID = int(struct.unpack(">H", data[:2])[0]) - data = data[2:] - self.glyphName = glyfTable.getGlyphName(int(glyphID)) - - if flags & VarComponentFlags.AXIS_INDICES_ARE_SHORT: - axisIndices = array.array("H", data[: 2 * numAxes]) - if sys.byteorder != "big": - axisIndices.byteswap() - data = data[2 * numAxes :] - flags ^= VarComponentFlags.AXIS_INDICES_ARE_SHORT - else: - axisIndices = array.array("B", data[:numAxes]) - data = data[numAxes:] - assert len(axisIndices) == numAxes - axisIndices = list(axisIndices) - - axisValues = array.array("h", data[: 2 * numAxes]) - if sys.byteorder != "big": - axisValues.byteswap() - data = data[2 * numAxes :] - assert len(axisValues) == numAxes - axisValues = [fi2fl(v, 14) for v in axisValues] - - self.location = { - glyfTable.axisTags[i]: v for i, v in zip(axisIndices, axisValues) - } - - def read_transform_component(data, values): - if flags & values.flag: - return ( - data[2:], - fi2fl(struct.unpack(">h", data[:2])[0], values.fractionalBits) - * values.scale, - ) - else: - return data, values.defaultValue - - for attr_name, mapping_values in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - data, value = read_transform_component(data, mapping_values) - setattr(self.transform, attr_name, value) - - if flags & VarComponentFlags.UNIFORM_SCALE: - if flags & VarComponentFlags.HAVE_SCALE_X and not ( - flags & VarComponentFlags.HAVE_SCALE_Y - ): - self.transform.scaleY = self.transform.scaleX - flags |= VarComponentFlags.HAVE_SCALE_Y - flags ^= VarComponentFlags.UNIFORM_SCALE - - return data - - def compile(self, glyfTable): - data = b"" - - if not hasattr(self, "flags"): - flags = 0 - # Calculate optimal transform component flags - for attr_name, mapping in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - value = getattr(self.transform, attr_name) - if fl2fi(value / mapping.scale, mapping.fractionalBits) != fl2fi( - mapping.defaultValue / mapping.scale, mapping.fractionalBits - ): - flags |= mapping.flag - else: - flags = self.flags - - if ( - flags & VarComponentFlags.HAVE_SCALE_X - and flags & VarComponentFlags.HAVE_SCALE_Y - and fl2fi(self.transform.scaleX, 10) == fl2fi(self.transform.scaleY, 10) - ): - flags |= VarComponentFlags.UNIFORM_SCALE - flags ^= VarComponentFlags.HAVE_SCALE_Y - - numAxes = len(self.location) - - data = data + struct.pack(">B", numAxes) - - glyphID = glyfTable.getGlyphID(self.glyphName) - if glyphID > 65535: - flags |= VarComponentFlags.GID_IS_24BIT - data = data + struct.pack(">L", glyphID)[1:] - else: - data = data + struct.pack(">H", glyphID) - - axisIndices = [glyfTable.axisTags.index(tag) for tag in self.location.keys()] - if all(a <= 255 for a in axisIndices): - axisIndices = array.array("B", axisIndices) - else: - axisIndices = array.array("H", axisIndices) - if sys.byteorder != "big": - axisIndices.byteswap() - flags |= VarComponentFlags.AXIS_INDICES_ARE_SHORT - data = data + bytes(axisIndices) - - axisValues = self.location.values() - axisValues = array.array("h", (fl2fi(v, 14) for v in axisValues)) - if sys.byteorder != "big": - axisValues.byteswap() - data = data + bytes(axisValues) - - def write_transform_component(data, value, values): - if flags & values.flag: - return data + struct.pack( - ">h", fl2fi(value / values.scale, values.fractionalBits) - ) - else: - return data - - for attr_name, mapping_values in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - value = getattr(self.transform, attr_name) - data = write_transform_component(data, value, mapping_values) - - return struct.pack(">H", flags) + data - - def toXML(self, writer, ttFont): - attrs = [("glyphName", self.glyphName)] - - if hasattr(self, "flags"): - attrs = attrs + [("flags", hex(self.flags))] - - for attr_name, mapping in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - v = getattr(self.transform, attr_name) - if v != mapping.defaultValue: - attrs.append((attr_name, fl2str(v, mapping.fractionalBits))) - - writer.begintag("varComponent", attrs) - writer.newline() - - writer.begintag("location") - writer.newline() - for tag, v in self.location.items(): - writer.simpletag("axis", [("tag", tag), ("value", fl2str(v, 14))]) - writer.newline() - writer.endtag("location") - writer.newline() - - writer.endtag("varComponent") - writer.newline() - - def fromXML(self, name, attrs, content, ttFont): - self.glyphName = attrs["glyphName"] - - if "flags" in attrs: - self.flags = safeEval(attrs["flags"]) - - for attr_name, mapping in VAR_COMPONENT_TRANSFORM_MAPPING.items(): - if attr_name not in attrs: - continue - v = str2fl(safeEval(attrs[attr_name]), mapping.fractionalBits) - setattr(self.transform, attr_name, v) - - for c in content: - if not isinstance(c, tuple): - continue - name, attrs, content = c - if name != "location": - continue - for c in content: - if not isinstance(c, tuple): - continue - name, attrs, content = c - assert name == "axis" - assert not content - self.location[attrs["tag"]] = str2fl(safeEval(attrs["value"]), 14) - - def getPointCount(self): - assert hasattr(self, "flags"), "VarComponent with variations must have flags" - - count = 0 - - if self.flags & VarComponentFlags.AXES_HAVE_VARIATION: - count += len(self.location) - - if self.flags & ( - VarComponentFlags.HAVE_TRANSLATE_X | VarComponentFlags.HAVE_TRANSLATE_Y - ): - count += 1 - if self.flags & VarComponentFlags.HAVE_ROTATION: - count += 1 - if self.flags & ( - VarComponentFlags.HAVE_SCALE_X | VarComponentFlags.HAVE_SCALE_Y - ): - count += 1 - if self.flags & (VarComponentFlags.HAVE_SKEW_X | VarComponentFlags.HAVE_SKEW_Y): - count += 1 - if self.flags & ( - VarComponentFlags.HAVE_TCENTER_X | VarComponentFlags.HAVE_TCENTER_Y - ): - count += 1 - - return count - - def getCoordinatesAndControls(self): - coords = [] - controls = [] - - if self.flags & VarComponentFlags.AXES_HAVE_VARIATION: - for tag, v in self.location.items(): - controls.append(tag) - coords.append((fl2fi(v, 14), 0)) - - if self.flags & ( - VarComponentFlags.HAVE_TRANSLATE_X | VarComponentFlags.HAVE_TRANSLATE_Y - ): - controls.append("translate") - coords.append((self.transform.translateX, self.transform.translateY)) - if self.flags & VarComponentFlags.HAVE_ROTATION: - controls.append("rotation") - coords.append((fl2fi(self.transform.rotation / 180, 12), 0)) - if self.flags & ( - VarComponentFlags.HAVE_SCALE_X | VarComponentFlags.HAVE_SCALE_Y - ): - controls.append("scale") - coords.append( - (fl2fi(self.transform.scaleX, 10), fl2fi(self.transform.scaleY, 10)) - ) - if self.flags & (VarComponentFlags.HAVE_SKEW_X | VarComponentFlags.HAVE_SKEW_Y): - controls.append("skew") - coords.append( - ( - fl2fi(self.transform.skewX / -180, 12), - fl2fi(self.transform.skewY / 180, 12), - ) - ) - if self.flags & ( - VarComponentFlags.HAVE_TCENTER_X | VarComponentFlags.HAVE_TCENTER_Y - ): - controls.append("tCenter") - coords.append((self.transform.tCenterX, self.transform.tCenterY)) - - return coords, controls - - def setCoordinates(self, coords): - i = 0 - - if self.flags & VarComponentFlags.AXES_HAVE_VARIATION: - newLocation = {} - for tag in self.location: - newLocation[tag] = fi2fl(coords[i][0], 14) - i += 1 - self.location = newLocation - - self.transform = DecomposedTransform() - if self.flags & ( - VarComponentFlags.HAVE_TRANSLATE_X | VarComponentFlags.HAVE_TRANSLATE_Y - ): - self.transform.translateX, self.transform.translateY = coords[i] - i += 1 - if self.flags & VarComponentFlags.HAVE_ROTATION: - self.transform.rotation = fi2fl(coords[i][0], 12) * 180 - i += 1 - if self.flags & ( - VarComponentFlags.HAVE_SCALE_X | VarComponentFlags.HAVE_SCALE_Y - ): - self.transform.scaleX, self.transform.scaleY = fi2fl( - coords[i][0], 10 - ), fi2fl(coords[i][1], 10) - i += 1 - if self.flags & (VarComponentFlags.HAVE_SKEW_X | VarComponentFlags.HAVE_SKEW_Y): - self.transform.skewX, self.transform.skewY = ( - fi2fl(coords[i][0], 12) * -180, - fi2fl(coords[i][1], 12) * 180, - ) - i += 1 - if self.flags & ( - VarComponentFlags.HAVE_TCENTER_X | VarComponentFlags.HAVE_TCENTER_Y - ): - self.transform.tCenterX, self.transform.tCenterY = coords[i] - i += 1 - - return coords[i:] - - def __eq__(self, other): - if type(self) != type(other): - return NotImplemented - return self.__dict__ == other.__dict__ - - def __ne__(self, other): - result = self.__eq__(other) - return result if result is NotImplemented else not result - - class GlyphCoordinates(object): """A list of glyph coordinates. diff --git a/Lib/fontTools/ttLib/tables/_g_v_a_r.py b/Lib/fontTools/ttLib/tables/_g_v_a_r.py index 11485bf09..e6b7ee8d6 100644 --- a/Lib/fontTools/ttLib/tables/_g_v_a_r.py +++ b/Lib/fontTools/ttLib/tables/_g_v_a_r.py @@ -245,11 +245,6 @@ class table__g_v_a_r(DefaultTable.DefaultTable): if glyph.isComposite(): return len(glyph.components) + NUM_PHANTOM_POINTS - elif glyph.isVarComposite(): - count = 0 - for component in glyph.components: - count += component.getPointCount() - return count + NUM_PHANTOM_POINTS else: # Empty glyphs (eg. space, nonmarkingreturn) have no "coordinates" attribute. return len(getattr(glyph, "coordinates", [])) + NUM_PHANTOM_POINTS diff --git a/Lib/fontTools/ttLib/ttGlyphSet.py b/Lib/fontTools/ttLib/ttGlyphSet.py index b4beb3e76..7cfdfd75f 100644 --- a/Lib/fontTools/ttLib/ttGlyphSet.py +++ b/Lib/fontTools/ttLib/ttGlyphSet.py @@ -178,10 +178,6 @@ class _TTGlyphGlyf(_TTGlyph): if depth: offset = 0 # Offset should only apply at top-level - if glyph.isVarComposite(): - self._drawVarComposite(glyph, pen, False) - return - glyph.draw(pen, self.glyphSet.glyfTable, offset) def drawPoints(self, pen): @@ -194,35 +190,8 @@ class _TTGlyphGlyf(_TTGlyph): if depth: offset = 0 # Offset should only apply at top-level - if glyph.isVarComposite(): - self._drawVarComposite(glyph, pen, True) - return - glyph.drawPoints(pen, self.glyphSet.glyfTable, offset) - def _drawVarComposite(self, glyph, pen, isPointPen): - from fontTools.ttLib.tables._g_l_y_f import ( - VarComponentFlags, - VAR_COMPONENT_TRANSFORM_MAPPING, - ) - - for comp in glyph.components: - 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 _getGlyphAndOffset(self): if self.glyphSet.location and self.glyphSet.gvarTable is not None: glyph = self._getGlyphInstance() @@ -300,11 +269,6 @@ def _setCoordinates(glyph, coord, glyfTable, *, recalcBounds=True): for p, comp in zip(coord, glyph.components): if hasattr(comp, "x"): comp.x, comp.y = p - elif glyph.isVarComposite(): - glyph.components = [copy(comp) for comp in glyph.components] # Shallow copy - for comp in glyph.components: - coord = comp.setCoordinates(coord) - assert not coord elif glyph.numberOfContours == 0: assert len(coord) == 0 else: diff --git a/Lib/fontTools/ttLib/woff2.py b/Lib/fontTools/ttLib/woff2.py index 9da2f7e6d..03667e834 100644 --- a/Lib/fontTools/ttLib/woff2.py +++ b/Lib/fontTools/ttLib/woff2.py @@ -1017,8 +1017,6 @@ class WOFF2GlyfTable(getTableClass("glyf")): return elif glyph.isComposite(): self._encodeComponents(glyph) - elif glyph.isVarComposite(): - raise NotImplementedError else: self._encodeCoordinates(glyph) self._encodeOverlapSimpleFlag(glyph, glyphID) diff --git a/Lib/fontTools/varLib/instancer/__init__.py b/Lib/fontTools/varLib/instancer/__init__.py index 7120b0831..78b608ef2 100644 --- a/Lib/fontTools/varLib/instancer/__init__.py +++ b/Lib/fontTools/varLib/instancer/__init__.py @@ -843,23 +843,6 @@ def _instantiateGvarGlyph( if defaultDeltas: coordinates += _g_l_y_f.GlyphCoordinates(defaultDeltas) - glyph = glyf[glyphname] - if glyph.isVarComposite(): - for component in glyph.components: - newLocation = {} - for tag, loc in component.location.items(): - if tag not in axisLimits: - newLocation[tag] = loc - continue - if component.flags & _g_l_y_f.VarComponentFlags.AXES_HAVE_VARIATION: - raise NotImplementedError( - "Instancing accross VarComposite axes with variation is not supported." - ) - limits = axisLimits[tag] - loc = limits.renormalizeValue(loc, extrapolate=False) - newLocation[tag] = loc - component.location = newLocation - # _setCoordinates also sets the hmtx/vmtx advance widths and sidebearings from # the four phantom points and glyph bounding boxes. # We call it unconditionally even if a glyph has no variations or no deltas are @@ -908,11 +891,9 @@ def instantiateGvar(varfont, axisLimits, optimize=True): glyphnames = sorted( glyf.glyphOrder, key=lambda name: ( - ( - glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth - if glyf[name].isComposite() or glyf[name].isVarComposite() - else 0 - ), + glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth + if glyf[name].isComposite() + else 0, name, ), ) diff --git a/Lib/fontTools/varLib/mutator.py b/Lib/fontTools/varLib/mutator.py index c7c37dabc..ae848cc4e 100644 --- a/Lib/fontTools/varLib/mutator.py +++ b/Lib/fontTools/varLib/mutator.py @@ -199,11 +199,9 @@ def instantiateVariableFont(varfont, location, inplace=False, overlap=True): glyphnames = sorted( gvar.variations.keys(), key=lambda name: ( - ( - glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth - if glyf[name].isComposite() or glyf[name].isVarComposite() - else 0 - ), + glyf[name].getCompositeMaxpValues(glyf).maxComponentDepth + if glyf[name].isComposite() + else 0, name, ), ) @@ -307,9 +305,9 @@ def instantiateVariableFont(varfont, location, inplace=False, overlap=True): if applies: assert record.FeatureTableSubstitution.Version == 0x00010000 for rec in record.FeatureTableSubstitution.SubstitutionRecord: - table.FeatureList.FeatureRecord[rec.FeatureIndex].Feature = ( - rec.Feature - ) + table.FeatureList.FeatureRecord[ + rec.FeatureIndex + ].Feature = rec.Feature break del table.FeatureVariations