Fix syntax error reported by build system: can't mix string string types when doing literal concatenation Fix local import reference - doesn't work in Python3. Addressed issues raised by @msousa for PR 1345 yesterday. Will change cff2_merge_funcs.py and cff2mergePen.py from tab to space indentations after the current comments are resolved. Add various improvements from comments: - do not edit the post table under varLib.build(). Setting post table format 2 or 3 is now expected to be managed by whatever calls varLib.build(). - In the t2CharStringPen module, rename closure _round() nested in makeRoundFunc to an exportable function, and use it in cff2mergePen. - remove TypeSupply copyright from cff2mergePen. - use modulo function to convert float to int when it is meant to be 0 in cff2mergePen. cff2_merge_funcs.py:merge_PrivateDicts() should only be blending the hint related fields in the PrivateDict. This oversight that was surfaced by @madig reporting an error building his Cantrell font. The bug appeared when the font was subroutinized, as the pen draw method then has to interpret the Subr field in order to access T2Charstring subroutines. Fix expected ttx output file. When I removed the logic to add glyph names to the post table, glyph names in the ttx file changed. Miguel prefers a simple list for readability in cff2_merge_funs.py:138.
92 lines
3.1 KiB
Python
92 lines
3.1 KiB
Python
# Copyright (c) 2009 Type Supply LLC
|
|
# Author: Tal Leming
|
|
|
|
from __future__ import print_function, division, absolute_import
|
|
from fontTools.misc.py23 import *
|
|
from fontTools.misc.fixedTools import otRound
|
|
from fontTools.misc.psCharStrings import T2CharString
|
|
from fontTools.pens.basePen import BasePen
|
|
from fontTools.cffLib.specializer import specializeCommands, commandsToProgram
|
|
|
|
|
|
def t2c_round(number, tolerance=0.5):
|
|
if tolerance == 0:
|
|
return number # no-op
|
|
rounded = otRound(number)
|
|
# return rounded integer if the tolerance >= 0.5, or if the absolute
|
|
# difference between the original float and the rounded integer is
|
|
# within the tolerance
|
|
if tolerance >= .5 or abs(rounded - number) <= tolerance:
|
|
return rounded
|
|
else:
|
|
# else return the value un-rounded
|
|
return number
|
|
|
|
def makeRoundFunc(tolerance):
|
|
if tolerance < 0:
|
|
raise ValueError("Rounding tolerance must be positive")
|
|
|
|
def roundPoint(point):
|
|
x, y = point
|
|
return t2c_round(x, tolerance), t2c_round(y, tolerance)
|
|
|
|
return roundPoint
|
|
|
|
|
|
class T2CharStringPen(BasePen):
|
|
"""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.
|
|
"""
|
|
|
|
def __init__(self, width, glyphSet, roundTolerance=0.5, CFF2=False):
|
|
super(T2CharStringPen, self).__init__(glyphSet)
|
|
self.roundPoint = makeRoundFunc(roundTolerance)
|
|
self._CFF2 = CFF2
|
|
self._width = width
|
|
self._commands = []
|
|
self._p0 = (0,0)
|
|
|
|
def _p(self, pt):
|
|
p0 = self._p0
|
|
pt = self._p0 = self.roundPoint(pt)
|
|
return [pt[0]-p0[0], pt[1]-p0[1]]
|
|
|
|
def _moveTo(self, pt):
|
|
self._commands.append(('rmoveto', self._p(pt)))
|
|
|
|
def _lineTo(self, pt):
|
|
self._commands.append(('rlineto', self._p(pt)))
|
|
|
|
def _curveToOne(self, pt1, pt2, pt3):
|
|
_p = self._p
|
|
self._commands.append(('rrcurveto', _p(pt1)+_p(pt2)+_p(pt3)))
|
|
|
|
def _closePath(self):
|
|
pass
|
|
|
|
def _endPath(self):
|
|
pass
|
|
|
|
def getCharString(self, private=None, globalSubrs=None, optimize=True):
|
|
commands = self._commands
|
|
if optimize:
|
|
maxstack = 48 if not self._CFF2 else 513
|
|
commands = specializeCommands(commands,
|
|
generalizeFirst=False,
|
|
maxstack=maxstack)
|
|
program = commandsToProgram(commands)
|
|
if self._width is not None:
|
|
assert not self._CFF2, "CFF2 does not allow encoding glyph width in CharString."
|
|
program.insert(0, otRound(self._width))
|
|
if not self._CFF2:
|
|
program.append('endchar')
|
|
charString = T2CharString(
|
|
program=program, private=private, globalSubrs=globalSubrs)
|
|
return charString
|