1*e1fe3e4aSElliott Hughesfrom fontTools.pens.filterPen import FilterPen, FilterPointPen 2*e1fe3e4aSElliott Hughes 3*e1fe3e4aSElliott Hughes 4*e1fe3e4aSElliott Hughes__all__ = ["TransformPen", "TransformPointPen"] 5*e1fe3e4aSElliott Hughes 6*e1fe3e4aSElliott Hughes 7*e1fe3e4aSElliott Hughesclass TransformPen(FilterPen): 8*e1fe3e4aSElliott Hughes """Pen that transforms all coordinates using a Affine transformation, 9*e1fe3e4aSElliott Hughes and passes them to another pen. 10*e1fe3e4aSElliott Hughes """ 11*e1fe3e4aSElliott Hughes 12*e1fe3e4aSElliott Hughes def __init__(self, outPen, transformation): 13*e1fe3e4aSElliott Hughes """The 'outPen' argument is another pen object. It will receive the 14*e1fe3e4aSElliott Hughes transformed coordinates. The 'transformation' argument can either 15*e1fe3e4aSElliott Hughes be a six-tuple, or a fontTools.misc.transform.Transform object. 16*e1fe3e4aSElliott Hughes """ 17*e1fe3e4aSElliott Hughes super(TransformPen, self).__init__(outPen) 18*e1fe3e4aSElliott Hughes if not hasattr(transformation, "transformPoint"): 19*e1fe3e4aSElliott Hughes from fontTools.misc.transform import Transform 20*e1fe3e4aSElliott Hughes 21*e1fe3e4aSElliott Hughes transformation = Transform(*transformation) 22*e1fe3e4aSElliott Hughes self._transformation = transformation 23*e1fe3e4aSElliott Hughes self._transformPoint = transformation.transformPoint 24*e1fe3e4aSElliott Hughes self._stack = [] 25*e1fe3e4aSElliott Hughes 26*e1fe3e4aSElliott Hughes def moveTo(self, pt): 27*e1fe3e4aSElliott Hughes self._outPen.moveTo(self._transformPoint(pt)) 28*e1fe3e4aSElliott Hughes 29*e1fe3e4aSElliott Hughes def lineTo(self, pt): 30*e1fe3e4aSElliott Hughes self._outPen.lineTo(self._transformPoint(pt)) 31*e1fe3e4aSElliott Hughes 32*e1fe3e4aSElliott Hughes def curveTo(self, *points): 33*e1fe3e4aSElliott Hughes self._outPen.curveTo(*self._transformPoints(points)) 34*e1fe3e4aSElliott Hughes 35*e1fe3e4aSElliott Hughes def qCurveTo(self, *points): 36*e1fe3e4aSElliott Hughes if points[-1] is None: 37*e1fe3e4aSElliott Hughes points = self._transformPoints(points[:-1]) + [None] 38*e1fe3e4aSElliott Hughes else: 39*e1fe3e4aSElliott Hughes points = self._transformPoints(points) 40*e1fe3e4aSElliott Hughes self._outPen.qCurveTo(*points) 41*e1fe3e4aSElliott Hughes 42*e1fe3e4aSElliott Hughes def _transformPoints(self, points): 43*e1fe3e4aSElliott Hughes transformPoint = self._transformPoint 44*e1fe3e4aSElliott Hughes return [transformPoint(pt) for pt in points] 45*e1fe3e4aSElliott Hughes 46*e1fe3e4aSElliott Hughes def closePath(self): 47*e1fe3e4aSElliott Hughes self._outPen.closePath() 48*e1fe3e4aSElliott Hughes 49*e1fe3e4aSElliott Hughes def endPath(self): 50*e1fe3e4aSElliott Hughes self._outPen.endPath() 51*e1fe3e4aSElliott Hughes 52*e1fe3e4aSElliott Hughes def addComponent(self, glyphName, transformation): 53*e1fe3e4aSElliott Hughes transformation = self._transformation.transform(transformation) 54*e1fe3e4aSElliott Hughes self._outPen.addComponent(glyphName, transformation) 55*e1fe3e4aSElliott Hughes 56*e1fe3e4aSElliott Hughes 57*e1fe3e4aSElliott Hughesclass TransformPointPen(FilterPointPen): 58*e1fe3e4aSElliott Hughes """PointPen that transforms all coordinates using a Affine transformation, 59*e1fe3e4aSElliott Hughes and passes them to another PointPen. 60*e1fe3e4aSElliott Hughes 61*e1fe3e4aSElliott Hughes >>> from fontTools.pens.recordingPen import RecordingPointPen 62*e1fe3e4aSElliott Hughes >>> rec = RecordingPointPen() 63*e1fe3e4aSElliott Hughes >>> pen = TransformPointPen(rec, (2, 0, 0, 2, -10, 5)) 64*e1fe3e4aSElliott Hughes >>> v = iter(rec.value) 65*e1fe3e4aSElliott Hughes >>> pen.beginPath(identifier="contour-0") 66*e1fe3e4aSElliott Hughes >>> next(v) 67*e1fe3e4aSElliott Hughes ('beginPath', (), {'identifier': 'contour-0'}) 68*e1fe3e4aSElliott Hughes >>> pen.addPoint((100, 100), "line") 69*e1fe3e4aSElliott Hughes >>> next(v) 70*e1fe3e4aSElliott Hughes ('addPoint', ((190, 205), 'line', False, None), {}) 71*e1fe3e4aSElliott Hughes >>> pen.endPath() 72*e1fe3e4aSElliott Hughes >>> next(v) 73*e1fe3e4aSElliott Hughes ('endPath', (), {}) 74*e1fe3e4aSElliott Hughes >>> pen.addComponent("a", (1, 0, 0, 1, -10, 5), identifier="component-0") 75*e1fe3e4aSElliott Hughes >>> next(v) 76*e1fe3e4aSElliott Hughes ('addComponent', ('a', <Transform [2 0 0 2 -30 15]>), {'identifier': 'component-0'}) 77*e1fe3e4aSElliott Hughes """ 78*e1fe3e4aSElliott Hughes 79*e1fe3e4aSElliott Hughes def __init__(self, outPointPen, transformation): 80*e1fe3e4aSElliott Hughes """The 'outPointPen' argument is another point pen object. 81*e1fe3e4aSElliott Hughes It will receive the transformed coordinates. 82*e1fe3e4aSElliott Hughes The 'transformation' argument can either be a six-tuple, or a 83*e1fe3e4aSElliott Hughes fontTools.misc.transform.Transform object. 84*e1fe3e4aSElliott Hughes """ 85*e1fe3e4aSElliott Hughes super().__init__(outPointPen) 86*e1fe3e4aSElliott Hughes if not hasattr(transformation, "transformPoint"): 87*e1fe3e4aSElliott Hughes from fontTools.misc.transform import Transform 88*e1fe3e4aSElliott Hughes 89*e1fe3e4aSElliott Hughes transformation = Transform(*transformation) 90*e1fe3e4aSElliott Hughes self._transformation = transformation 91*e1fe3e4aSElliott Hughes self._transformPoint = transformation.transformPoint 92*e1fe3e4aSElliott Hughes 93*e1fe3e4aSElliott Hughes def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs): 94*e1fe3e4aSElliott Hughes self._outPen.addPoint( 95*e1fe3e4aSElliott Hughes self._transformPoint(pt), segmentType, smooth, name, **kwargs 96*e1fe3e4aSElliott Hughes ) 97*e1fe3e4aSElliott Hughes 98*e1fe3e4aSElliott Hughes def addComponent(self, baseGlyphName, transformation, **kwargs): 99*e1fe3e4aSElliott Hughes transformation = self._transformation.transform(transformation) 100*e1fe3e4aSElliott Hughes self._outPen.addComponent(baseGlyphName, transformation, **kwargs) 101*e1fe3e4aSElliott Hughes 102*e1fe3e4aSElliott Hughes 103*e1fe3e4aSElliott Hughesif __name__ == "__main__": 104*e1fe3e4aSElliott Hughes from fontTools.pens.basePen import _TestPen 105*e1fe3e4aSElliott Hughes 106*e1fe3e4aSElliott Hughes pen = TransformPen(_TestPen(None), (2, 0, 0.5, 2, -10, 0)) 107*e1fe3e4aSElliott Hughes pen.moveTo((0, 0)) 108*e1fe3e4aSElliott Hughes pen.lineTo((0, 100)) 109*e1fe3e4aSElliott Hughes pen.curveTo((50, 75), (60, 50), (50, 25), (0, 0)) 110*e1fe3e4aSElliott Hughes pen.closePath() 111