• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.misc.roundTools import otRound
2from fontTools.misc.transform import Transform
3from fontTools.pens.filterPen import FilterPen, FilterPointPen
4
5
6__all__ = ["RoundingPen", "RoundingPointPen"]
7
8
9class RoundingPen(FilterPen):
10    """
11    Filter pen that rounds point coordinates and component XY offsets to integer.
12
13    >>> from fontTools.pens.recordingPen import RecordingPen
14    >>> recpen = RecordingPen()
15    >>> roundpen = RoundingPen(recpen)
16    >>> roundpen.moveTo((0.4, 0.6))
17    >>> roundpen.lineTo((1.6, 2.5))
18    >>> roundpen.qCurveTo((2.4, 4.6), (3.3, 5.7), (4.9, 6.1))
19    >>> roundpen.curveTo((6.4, 8.6), (7.3, 9.7), (8.9, 10.1))
20    >>> roundpen.addComponent("a", (1.5, 0, 0, 1.5, 10.5, -10.5))
21    >>> recpen.value == [
22    ...     ('moveTo', ((0, 1),)),
23    ...     ('lineTo', ((2, 3),)),
24    ...     ('qCurveTo', ((2, 5), (3, 6), (5, 6))),
25    ...     ('curveTo', ((6, 9), (7, 10), (9, 10))),
26    ...     ('addComponent', ('a', (1.5, 0, 0, 1.5, 11, -10))),
27    ... ]
28    True
29    """
30
31    def __init__(self, outPen, roundFunc=otRound):
32        super().__init__(outPen)
33        self.roundFunc = roundFunc
34
35    def moveTo(self, pt):
36        self._outPen.moveTo((self.roundFunc(pt[0]), self.roundFunc(pt[1])))
37
38    def lineTo(self, pt):
39        self._outPen.lineTo((self.roundFunc(pt[0]), self.roundFunc(pt[1])))
40
41    def curveTo(self, *points):
42        self._outPen.curveTo(
43            *((self.roundFunc(x), self.roundFunc(y)) for x, y in points)
44        )
45
46    def qCurveTo(self, *points):
47        self._outPen.qCurveTo(
48            *((self.roundFunc(x), self.roundFunc(y)) for x, y in points)
49        )
50
51    def addComponent(self, glyphName, transformation):
52        self._outPen.addComponent(
53            glyphName,
54            Transform(
55                *transformation[:4],
56                self.roundFunc(transformation[4]),
57                self.roundFunc(transformation[5]),
58            ),
59        )
60
61
62class RoundingPointPen(FilterPointPen):
63    """
64    Filter point pen that rounds point coordinates and component XY offsets to integer.
65
66    >>> from fontTools.pens.recordingPen import RecordingPointPen
67    >>> recpen = RecordingPointPen()
68    >>> roundpen = RoundingPointPen(recpen)
69    >>> roundpen.beginPath()
70    >>> roundpen.addPoint((0.4, 0.6), 'line')
71    >>> roundpen.addPoint((1.6, 2.5), 'line')
72    >>> roundpen.addPoint((2.4, 4.6))
73    >>> roundpen.addPoint((3.3, 5.7))
74    >>> roundpen.addPoint((4.9, 6.1), 'qcurve')
75    >>> roundpen.endPath()
76    >>> roundpen.addComponent("a", (1.5, 0, 0, 1.5, 10.5, -10.5))
77    >>> recpen.value == [
78    ...     ('beginPath', (), {}),
79    ...     ('addPoint', ((0, 1), 'line', False, None), {}),
80    ...     ('addPoint', ((2, 3), 'line', False, None), {}),
81    ...     ('addPoint', ((2, 5), None, False, None), {}),
82    ...     ('addPoint', ((3, 6), None, False, None), {}),
83    ...     ('addPoint', ((5, 6), 'qcurve', False, None), {}),
84    ...     ('endPath', (), {}),
85    ...     ('addComponent', ('a', (1.5, 0, 0, 1.5, 11, -10)), {}),
86    ... ]
87    True
88    """
89
90    def __init__(self, outPen, roundFunc=otRound):
91        super().__init__(outPen)
92        self.roundFunc = roundFunc
93
94    def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
95        self._outPen.addPoint(
96            (self.roundFunc(pt[0]), self.roundFunc(pt[1])),
97            segmentType=segmentType,
98            smooth=smooth,
99            name=name,
100            **kwargs,
101        )
102
103    def addComponent(self, baseGlyphName, transformation, **kwargs):
104        self._outPen.addComponent(
105            baseGlyphName,
106            Transform(
107                *transformation[:4],
108                self.roundFunc(transformation[4]),
109                self.roundFunc(transformation[5]),
110            ),
111            **kwargs,
112        )
113