xref: /aosp_15_r20/external/fonttools/Lib/fontTools/pens/t2CharStringPen.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1# Copyright (c) 2009 Type Supply LLC
2# Author: Tal Leming
3
4from fontTools.misc.roundTools import otRound, roundFunc
5from fontTools.misc.psCharStrings import T2CharString
6from fontTools.pens.basePen import BasePen
7from fontTools.cffLib.specializer import specializeCommands, commandsToProgram
8
9
10class T2CharStringPen(BasePen):
11    """Pen to draw Type 2 CharStrings.
12
13    The 'roundTolerance' argument controls the rounding of point coordinates.
14    It is defined as the maximum absolute difference between the original
15    float and the rounded integer value.
16    The default tolerance of 0.5 means that all floats are rounded to integer;
17    a value of 0 disables rounding; values in between will only round floats
18    which are close to their integral part within the tolerated range.
19    """
20
21    def __init__(self, width, glyphSet, roundTolerance=0.5, CFF2=False):
22        super(T2CharStringPen, self).__init__(glyphSet)
23        self.round = roundFunc(roundTolerance)
24        self._CFF2 = CFF2
25        self._width = width
26        self._commands = []
27        self._p0 = (0, 0)
28
29    def _p(self, pt):
30        p0 = self._p0
31        pt = self._p0 = (self.round(pt[0]), self.round(pt[1]))
32        return [pt[0] - p0[0], pt[1] - p0[1]]
33
34    def _moveTo(self, pt):
35        self._commands.append(("rmoveto", self._p(pt)))
36
37    def _lineTo(self, pt):
38        self._commands.append(("rlineto", self._p(pt)))
39
40    def _curveToOne(self, pt1, pt2, pt3):
41        _p = self._p
42        self._commands.append(("rrcurveto", _p(pt1) + _p(pt2) + _p(pt3)))
43
44    def _closePath(self):
45        pass
46
47    def _endPath(self):
48        pass
49
50    def getCharString(self, private=None, globalSubrs=None, optimize=True):
51        commands = self._commands
52        if optimize:
53            maxstack = 48 if not self._CFF2 else 513
54            commands = specializeCommands(
55                commands, generalizeFirst=False, maxstack=maxstack
56            )
57        program = commandsToProgram(commands)
58        if self._width is not None:
59            assert (
60                not self._CFF2
61            ), "CFF2 does not allow encoding glyph width in CharString."
62            program.insert(0, otRound(self._width))
63        if not self._CFF2:
64            program.append("endchar")
65        charString = T2CharString(
66            program=program, private=private, globalSubrs=globalSubrs
67        )
68        return charString
69