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