2015-10-23 11:12:49 -07:00
|
|
|
# Copyright (c) 2009 Type Supply LLC
|
2015-10-30 10:32:04 -07:00
|
|
|
# Author: Tal Leming
|
2015-10-23 11:12:49 -07:00
|
|
|
|
|
|
|
from __future__ import print_function, division, absolute_import
|
2015-10-23 11:36:46 -07:00
|
|
|
from fontTools.misc.py23 import *
|
2015-10-23 11:12:49 -07:00
|
|
|
from fontTools.misc.psCharStrings import T2CharString
|
|
|
|
from fontTools.pens.basePen import BasePen
|
2017-05-06 04:50:24 -06:00
|
|
|
from fontTools.cffLib.specializer import specializeCommands, commandsToProgram
|
2015-10-23 11:12:49 -07:00
|
|
|
|
|
|
|
|
2017-01-12 22:38:28 +00:00
|
|
|
def makeRoundFunc(tolerance):
|
2017-01-13 22:32:10 +00:00
|
|
|
if tolerance < 0:
|
|
|
|
raise ValueError("Rounding tolerance must be positive")
|
2017-01-12 19:48:55 +00:00
|
|
|
|
|
|
|
def _round(number):
|
|
|
|
if tolerance == 0:
|
|
|
|
return number # no-op
|
|
|
|
rounded = round(number)
|
2017-01-13 22:32:10 +00:00
|
|
|
# return rounded integer if the tolerance >= 0.5, or if the absolute
|
2017-01-12 21:34:59 +00:00
|
|
|
# difference between the original float and the rounded integer is
|
|
|
|
# within the tolerance
|
2017-01-13 22:32:10 +00:00
|
|
|
if tolerance >= .5 or abs(rounded - number) <= tolerance:
|
2017-01-12 19:48:55 +00:00
|
|
|
return rounded
|
|
|
|
else:
|
|
|
|
# else return the value un-rounded
|
|
|
|
return number
|
|
|
|
|
2017-01-12 22:38:28 +00:00
|
|
|
def roundPoint(point):
|
2017-01-12 19:48:55 +00:00
|
|
|
x, y = point
|
|
|
|
return _round(x), _round(y)
|
|
|
|
|
2017-01-12 22:38:28 +00:00
|
|
|
return roundPoint
|
2017-01-12 19:48:55 +00:00
|
|
|
|
|
|
|
|
2017-05-06 04:50:24 -06:00
|
|
|
class T2CharStringPen(BasePen):
|
2017-01-14 12:11:21 +00:00
|
|
|
"""Pen to draw Type 2 CharStrings.
|
|
|
|
|
|
|
|
The 'roundTolerance' argument controls the rounding of point coordinates.
|
|
|
|
It is defined as the maximum absolute difference between the original
|
|
|
|
float and the rounded integer value.
|
|
|
|
The default tolerance of 0.5 means that all floats are rounded to integer;
|
|
|
|
a value of 0 disables rounding; values in between will only round floats
|
|
|
|
which are close to their integral part within the tolerated range.
|
|
|
|
"""
|
2015-10-23 11:12:49 -07:00
|
|
|
|
2017-05-06 04:54:07 -06:00
|
|
|
def __init__(self, width, glyphSet, roundTolerance=0.5, CFF2=False):
|
2017-05-17 17:06:00 -07:00
|
|
|
super(T2CharStringPen, self).__init__(glyphSet)
|
2017-01-12 22:38:28 +00:00
|
|
|
self.roundPoint = makeRoundFunc(roundTolerance)
|
2017-05-06 04:54:07 -06:00
|
|
|
self._CFF2 = CFF2
|
2017-05-05 21:21:30 -06:00
|
|
|
self._width = width
|
2017-05-06 04:50:24 -06:00
|
|
|
self._commands = []
|
|
|
|
self._p0 = (0,0)
|
2015-10-23 11:12:49 -07:00
|
|
|
|
2017-05-06 04:50:24 -06:00
|
|
|
def _p(self, pt):
|
|
|
|
p0 = self._p0
|
|
|
|
pt = self._p0 = self.roundPoint(pt)
|
2018-02-19 14:57:18 +00:00
|
|
|
return (pt[0]-p0[0], pt[1]-p0[1])
|
2015-10-23 11:12:49 -07:00
|
|
|
|
2017-05-06 04:50:24 -06:00
|
|
|
def _moveTo(self, pt):
|
|
|
|
self._commands.append(('rmoveto', self._p(pt)))
|
2015-10-23 11:12:49 -07:00
|
|
|
|
|
|
|
def _lineTo(self, pt):
|
2017-05-06 04:50:24 -06:00
|
|
|
self._commands.append(('rlineto', self._p(pt)))
|
2015-10-23 11:12:49 -07:00
|
|
|
|
|
|
|
def _curveToOne(self, pt1, pt2, pt3):
|
2017-05-06 04:50:24 -06:00
|
|
|
_p = self._p
|
|
|
|
self._commands.append(('rrcurveto', _p(pt1)+_p(pt2)+_p(pt3)))
|
2015-10-23 11:12:49 -07:00
|
|
|
|
|
|
|
def _closePath(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def _endPath(self):
|
|
|
|
pass
|
|
|
|
|
2017-05-05 21:21:30 -06:00
|
|
|
def getCharString(self, private=None, globalSubrs=None, optimize=True):
|
2017-05-06 04:50:24 -06:00
|
|
|
commands = self._commands
|
2017-05-05 21:21:30 -06:00
|
|
|
if optimize:
|
2017-05-06 13:14:25 -06:00
|
|
|
maxstack = 48 if not self._CFF2 else 513
|
2017-05-06 04:54:07 -06:00
|
|
|
commands = specializeCommands(commands,
|
|
|
|
generalizeFirst=False,
|
|
|
|
maxstack=maxstack)
|
2017-05-06 04:50:24 -06:00
|
|
|
program = commandsToProgram(commands)
|
2017-05-05 21:21:30 -06:00
|
|
|
if self._width is not None:
|
2017-05-06 13:16:07 -06:00
|
|
|
assert not self._CFF2, "CFF2 does not allow encoding glyph width in CharString."
|
2017-05-05 21:21:30 -06:00
|
|
|
program.insert(0, round(self._width))
|
2017-05-06 04:54:07 -06:00
|
|
|
if not self._CFF2:
|
|
|
|
program.append('endchar')
|
2017-01-12 19:48:55 +00:00
|
|
|
charString = T2CharString(
|
|
|
|
program=program, private=private, globalSubrs=globalSubrs)
|
2015-10-23 11:12:49 -07:00
|
|
|
return charString
|