Spaces:
Runtime error
Runtime error
| """Pen recording operations that can be accessed or replayed.""" | |
| from fontTools.pens.basePen import AbstractPen, DecomposingPen | |
| from fontTools.pens.pointPen import AbstractPointPen | |
| __all__ = [ | |
| "replayRecording", | |
| "RecordingPen", | |
| "DecomposingRecordingPen", | |
| "RecordingPointPen", | |
| ] | |
| def replayRecording(recording, pen): | |
| """Replay a recording, as produced by RecordingPen or DecomposingRecordingPen, | |
| to a pen. | |
| Note that recording does not have to be produced by those pens. | |
| It can be any iterable of tuples of method name and tuple-of-arguments. | |
| Likewise, pen can be any objects receiving those method calls. | |
| """ | |
| for operator, operands in recording: | |
| getattr(pen, operator)(*operands) | |
| class RecordingPen(AbstractPen): | |
| """Pen recording operations that can be accessed or replayed. | |
| The recording can be accessed as pen.value; or replayed using | |
| pen.replay(otherPen). | |
| :Example: | |
| from fontTools.ttLib import TTFont | |
| from fontTools.pens.recordingPen import RecordingPen | |
| glyph_name = 'dollar' | |
| font_path = 'MyFont.otf' | |
| font = TTFont(font_path) | |
| glyphset = font.getGlyphSet() | |
| glyph = glyphset[glyph_name] | |
| pen = RecordingPen() | |
| glyph.draw(pen) | |
| print(pen.value) | |
| """ | |
| def __init__(self): | |
| self.value = [] | |
| def moveTo(self, p0): | |
| self.value.append(("moveTo", (p0,))) | |
| def lineTo(self, p1): | |
| self.value.append(("lineTo", (p1,))) | |
| def qCurveTo(self, *points): | |
| self.value.append(("qCurveTo", points)) | |
| def curveTo(self, *points): | |
| self.value.append(("curveTo", points)) | |
| def closePath(self): | |
| self.value.append(("closePath", ())) | |
| def endPath(self): | |
| self.value.append(("endPath", ())) | |
| def addComponent(self, glyphName, transformation): | |
| self.value.append(("addComponent", (glyphName, transformation))) | |
| def addVarComponent(self, glyphName, transformation, location): | |
| self.value.append(("addVarComponent", (glyphName, transformation, location))) | |
| def replay(self, pen): | |
| replayRecording(self.value, pen) | |
| class DecomposingRecordingPen(DecomposingPen, RecordingPen): | |
| """Same as RecordingPen, except that it doesn't keep components | |
| as references, but draws them decomposed as regular contours. | |
| The constructor takes a single 'glyphSet' positional argument, | |
| a dictionary of glyph objects (i.e. with a 'draw' method) keyed | |
| by thir name:: | |
| >>> class SimpleGlyph(object): | |
| ... def draw(self, pen): | |
| ... pen.moveTo((0, 0)) | |
| ... pen.curveTo((1, 1), (2, 2), (3, 3)) | |
| ... pen.closePath() | |
| >>> class CompositeGlyph(object): | |
| ... def draw(self, pen): | |
| ... pen.addComponent('a', (1, 0, 0, 1, -1, 1)) | |
| >>> glyphSet = {'a': SimpleGlyph(), 'b': CompositeGlyph()} | |
| >>> for name, glyph in sorted(glyphSet.items()): | |
| ... pen = DecomposingRecordingPen(glyphSet) | |
| ... glyph.draw(pen) | |
| ... print("{}: {}".format(name, pen.value)) | |
| a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())] | |
| b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())] | |
| """ | |
| # raises KeyError if base glyph is not found in glyphSet | |
| skipMissingComponents = False | |
| class RecordingPointPen(AbstractPointPen): | |
| """PointPen recording operations that can be accessed or replayed. | |
| The recording can be accessed as pen.value; or replayed using | |
| pointPen.replay(otherPointPen). | |
| :Example: | |
| from defcon import Font | |
| from fontTools.pens.recordingPen import RecordingPointPen | |
| glyph_name = 'a' | |
| font_path = 'MyFont.ufo' | |
| font = Font(font_path) | |
| glyph = font[glyph_name] | |
| pen = RecordingPointPen() | |
| glyph.drawPoints(pen) | |
| print(pen.value) | |
| new_glyph = font.newGlyph('b') | |
| pen.replay(new_glyph.getPointPen()) | |
| """ | |
| def __init__(self): | |
| self.value = [] | |
| def beginPath(self, identifier=None, **kwargs): | |
| if identifier is not None: | |
| kwargs["identifier"] = identifier | |
| self.value.append(("beginPath", (), kwargs)) | |
| def endPath(self): | |
| self.value.append(("endPath", (), {})) | |
| def addPoint( | |
| self, pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs | |
| ): | |
| if identifier is not None: | |
| kwargs["identifier"] = identifier | |
| self.value.append(("addPoint", (pt, segmentType, smooth, name), kwargs)) | |
| def addComponent(self, baseGlyphName, transformation, identifier=None, **kwargs): | |
| if identifier is not None: | |
| kwargs["identifier"] = identifier | |
| self.value.append(("addComponent", (baseGlyphName, transformation), kwargs)) | |
| def addVarComponent( | |
| self, baseGlyphName, transformation, location, identifier=None, **kwargs | |
| ): | |
| if identifier is not None: | |
| kwargs["identifier"] = identifier | |
| self.value.append( | |
| ("addVarComponent", (baseGlyphName, transformation, location), kwargs) | |
| ) | |
| def replay(self, pointPen): | |
| for operator, args, kwargs in self.value: | |
| getattr(pointPen, operator)(*args, **kwargs) | |
| if __name__ == "__main__": | |
| pen = RecordingPen() | |
| pen.moveTo((0, 0)) | |
| pen.lineTo((0, 100)) | |
| pen.curveTo((50, 75), (60, 50), (50, 25)) | |
| pen.closePath() | |
| from pprint import pprint | |
| pprint(pen.value) | |