diff options
Diffstat (limited to 'Lib/fontTools/pens/ttGlyphPen.py')
-rw-r--r-- | Lib/fontTools/pens/ttGlyphPen.py | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/Lib/fontTools/pens/ttGlyphPen.py b/Lib/fontTools/pens/ttGlyphPen.py index 6e2f0d31..e7841efc 100644 --- a/Lib/fontTools/pens/ttGlyphPen.py +++ b/Lib/fontTools/pens/ttGlyphPen.py @@ -1,6 +1,6 @@ -from __future__ import print_function, division, absolute_import -from fontTools.misc.py23 import * from array import array +from fontTools.misc.fixedTools import MAX_F2DOT14, otRound, floatToFixedToFloat +from fontTools.misc.roundTools import otRound from fontTools.pens.basePen import LoggingPen from fontTools.pens.transformPen import TransformPen from fontTools.ttLib.tables import ttProgram @@ -12,30 +12,37 @@ from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates __all__ = ["TTGlyphPen"] -# the max value that can still fit in an F2Dot14: -# 1.99993896484375 -MAX_F2DOT14 = 0x7FFF / (1 << 14) - - class TTGlyphPen(LoggingPen): """Pen used for drawing to a TrueType glyph. - If `handleOverflowingTransforms` is True, the components' transform values - are checked that they don't overflow the limits of a F2Dot14 number: - -2.0 <= v < +2.0. If any transform value exceeds these, the composite - glyph is decomposed. - An exception to this rule is done for values that are very close to +2.0 - (both for consistency with the -2.0 case, and for the relative frequency - these occur in real fonts). When almost +2.0 values occur (and all other - values are within the range -2.0 <= x <= +2.0), they are clamped to the - maximum positive value that can still be encoded as an F2Dot14: i.e. - 1.99993896484375. - If False, no check is done and all components are translated unmodified - into the glyf table, followed by an inevitable `struct.error` once an - attempt is made to compile them. + This pen can be used to construct or modify glyphs in a TrueType format + font. After using the pen to draw, use the ``.glyph()`` method to retrieve + a :py:class:`~._g_l_y_f.Glyph` object representing the glyph. """ def __init__(self, glyphSet, handleOverflowingTransforms=True): + """Construct a new pen. + + Args: + glyphSet (ttLib._TTGlyphSet): A glyphset object, used to resolve components. + handleOverflowingTransforms (bool): See below. + + If ``handleOverflowingTransforms`` is True, the components' transform values + are checked that they don't overflow the limits of a F2Dot14 number: + -2.0 <= v < +2.0. If any transform value exceeds these, the composite + glyph is decomposed. + + An exception to this rule is done for values that are very close to +2.0 + (both for consistency with the -2.0 case, and for the relative frequency + these occur in real fonts). When almost +2.0 values occur (and all other + values are within the range -2.0 <= x <= +2.0), they are clamped to the + maximum positive value that can still be encoded as an F2Dot14: i.e. + 1.99993896484375. + + If False, no check is done and all components are translated unmodified + into the glyf table, followed by an inevitable ``struct.error`` once an + attempt is made to compile them. + """ self.glyphSet = glyphSet self.handleOverflowingTransforms = handleOverflowingTransforms self.init() @@ -66,6 +73,9 @@ class TTGlyphPen(LoggingPen): assert self._isClosed(), '"move"-type point must begin a new contour.' self._addPoint(pt, 1) + def curveTo(self, *points): + raise NotImplementedError + def qCurveTo(self, *points): assert len(points) >= 1 for pt in points[:-1]: @@ -123,8 +133,12 @@ class TTGlyphPen(LoggingPen): component = GlyphComponent() component.glyphName = glyphName - component.x, component.y = transformation[4:] - transformation = transformation[:4] + component.x, component.y = (otRound(v) for v in transformation[4:]) + # quantize floats to F2Dot14 so we get same values as when decompiled + # from a binary glyf table + transformation = tuple( + floatToFixedToFloat(v, 14) for v in transformation[:4] + ) if transformation != (1, 0, 0, 1): if (self.handleOverflowingTransforms and any(MAX_F2DOT14 < s <= 2 for s in transformation)): @@ -137,12 +151,14 @@ class TTGlyphPen(LoggingPen): return components def glyph(self, componentFlags=0x4): + """Returns a :py:class:`~._g_l_y_f.Glyph` object representing the glyph.""" assert self._isClosed(), "Didn't close last contour." components = self._buildComponents(componentFlags) glyph = Glyph() glyph.coordinates = GlyphCoordinates(self.points) + glyph.coordinates.toInt() glyph.endPtsOfContours = self.endPts glyph.flags = array("B", self.types) self.init() |