Merge pull request #2164 from fonttools/pen-maintenance
Pen maintenance
This commit is contained in:
commit
f6a62e0db1
@ -1,3 +1 @@
|
||||
"""Empty __init__.py file to signal Python this directory is a package."""
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""Calculate the area of a glyph."""
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -36,26 +36,52 @@ Coordinates are usually expressed as (x, y) tuples, but generally any
|
||||
sequence of length 2 will do.
|
||||
"""
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
import abc
|
||||
from typing import Any, Tuple
|
||||
|
||||
from fontTools.misc.loggingTools import LogMixin
|
||||
|
||||
__all__ = ["AbstractPen", "NullPen", "BasePen",
|
||||
"decomposeSuperBezierSegment", "decomposeQuadraticSegment"]
|
||||
|
||||
|
||||
class AbstractPen(object):
|
||||
class AbstractPen(abc.ABC):
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass: Any) -> bool:
|
||||
if cls is not AbstractPen:
|
||||
return NotImplemented
|
||||
return (
|
||||
hasattr(subclass, "moveTo")
|
||||
and callable(subclass.moveTo)
|
||||
and hasattr(subclass, "lineTo")
|
||||
and callable(subclass.lineTo)
|
||||
and hasattr(subclass, "curveTo")
|
||||
and callable(subclass.curveTo)
|
||||
and hasattr(subclass, "qCurveTo")
|
||||
and callable(subclass.qCurveTo)
|
||||
and hasattr(subclass, "closePath")
|
||||
and callable(subclass.closePath)
|
||||
and hasattr(subclass, "endPath")
|
||||
and callable(subclass.endPath)
|
||||
and hasattr(subclass, "addComponent")
|
||||
and callable(subclass.addComponent)
|
||||
or NotImplemented
|
||||
)
|
||||
|
||||
def moveTo(self, pt):
|
||||
@abc.abstractmethod
|
||||
def moveTo(self, pt: Tuple[float, float]) -> None:
|
||||
"""Begin a new sub path, set the current point to 'pt'. You must
|
||||
end each sub path with a call to pen.closePath() or pen.endPath().
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def lineTo(self, pt):
|
||||
@abc.abstractmethod
|
||||
def lineTo(self, pt: Tuple[float, float]) -> None:
|
||||
"""Draw a straight line from the current point to 'pt'."""
|
||||
raise NotImplementedError
|
||||
|
||||
def curveTo(self, *points):
|
||||
@abc.abstractmethod
|
||||
def curveTo(self, *points: Tuple[float, float]) -> None:
|
||||
"""Draw a cubic bezier with an arbitrary number of control points.
|
||||
|
||||
The last point specified is on-curve, all others are off-curve
|
||||
@ -76,7 +102,8 @@ class AbstractPen(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def qCurveTo(self, *points):
|
||||
@abc.abstractmethod
|
||||
def qCurveTo(self, *points: Tuple[float, float]) -> None:
|
||||
"""Draw a whole string of quadratic curve segments.
|
||||
|
||||
The last point specified is on-curve, all others are off-curve
|
||||
@ -93,19 +120,26 @@ class AbstractPen(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def closePath(self):
|
||||
@abc.abstractmethod
|
||||
def closePath(self) -> None:
|
||||
"""Close the current sub path. You must call either pen.closePath()
|
||||
or pen.endPath() after each sub path.
|
||||
"""
|
||||
pass
|
||||
|
||||
def endPath(self):
|
||||
@abc.abstractmethod
|
||||
def endPath(self) -> None:
|
||||
"""End the current sub path, but don't close it. You must call
|
||||
either pen.closePath() or pen.endPath() after each sub path.
|
||||
"""
|
||||
pass
|
||||
|
||||
def addComponent(self, glyphName, transformation):
|
||||
@abc.abstractmethod
|
||||
def addComponent(
|
||||
self,
|
||||
glyphName: str,
|
||||
transformation: Tuple[float, float, float, float, float, float]
|
||||
) -> None:
|
||||
"""Add a sub glyph. The 'transformation' argument must be a 6-tuple
|
||||
containing an affine transformation, or a Transform object from the
|
||||
fontTools.misc.transform module. More precisely: it should be a
|
||||
@ -114,7 +148,7 @@ class AbstractPen(object):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class NullPen(object):
|
||||
class NullPen(AbstractPen):
|
||||
|
||||
"""A pen that does nothing.
|
||||
"""
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
|
||||
from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
from fontTools.pens.pointPen import AbstractPointPen
|
||||
from fontTools.pens.recordingPen import RecordingPen
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""Pen calculating 0th, 1st, and 2nd moments of area of glyph shapes.
|
||||
This is low-level, autogenerated pen. Use statisticsPen instead."""
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Calculate the perimeter of a glyph."""
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
from fontTools.misc.bezierTools import approximateQuadraticArcLengthC, calcQuadraticArcLengthC, approximateCubicArcLengthC, calcCubicArcLengthC
|
||||
import math
|
||||
|
@ -2,7 +2,6 @@
|
||||
for shapes.
|
||||
"""
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
from fontTools.misc.bezierTools import solveQuadratic, solveCubic
|
||||
|
||||
|
@ -11,8 +11,12 @@ steps through all the points in a call from glyph.drawPoints().
|
||||
This allows the caller to provide more data for each point.
|
||||
For instance, whether or not a point is smooth, and its name.
|
||||
"""
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
|
||||
import abc
|
||||
import math
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
|
||||
__all__ = [
|
||||
"AbstractPointPen",
|
||||
@ -24,26 +28,56 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
class AbstractPointPen(object):
|
||||
"""
|
||||
Baseclass for all PointPens.
|
||||
"""
|
||||
class AbstractPointPen(abc.ABC):
|
||||
"""Baseclass for all PointPens."""
|
||||
|
||||
def beginPath(self, identifier=None, **kwargs):
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass: Any) -> bool:
|
||||
if cls is not AbstractPointPen:
|
||||
return NotImplemented
|
||||
return (
|
||||
hasattr(subclass, "beginPath")
|
||||
and callable(subclass.beginPath)
|
||||
and hasattr(subclass, "endPath")
|
||||
and callable(subclass.endPath)
|
||||
and hasattr(subclass, "addPoint")
|
||||
and callable(subclass.addPoint)
|
||||
and hasattr(subclass, "addComponent")
|
||||
and callable(subclass.addComponent)
|
||||
or NotImplemented
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
def beginPath(self, identifier: Optional[str] = None, **kwargs: Any) -> None:
|
||||
"""Start a new sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def endPath(self):
|
||||
@abc.abstractmethod
|
||||
def endPath(self) -> None:
|
||||
"""End the current sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def addPoint(self, pt, segmentType=None, smooth=False, name=None,
|
||||
identifier=None, **kwargs):
|
||||
@abc.abstractmethod
|
||||
def addPoint(
|
||||
self,
|
||||
pt: Tuple[float, float],
|
||||
segmentType: Optional[str] = None,
|
||||
smooth: bool = False,
|
||||
name: Optional[str] = None,
|
||||
identifier: Optional[str] = None,
|
||||
**kwargs: Any
|
||||
) -> None:
|
||||
"""Add a point to the current sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def addComponent(self, baseGlyphName, transformation, identifier=None,
|
||||
**kwargs):
|
||||
@abc.abstractmethod
|
||||
def addComponent(
|
||||
self,
|
||||
baseGlyphName: str,
|
||||
transformation: Tuple[float, float, float, float, float, float],
|
||||
identifier: Optional[str] = None,
|
||||
**kwargs: Any
|
||||
) -> None:
|
||||
"""Add a sub glyph."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
from Quartz.CoreGraphics import CGPathCreateMutable, CGPathMoveToPoint
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Pen recording operations that can be accessed or replayed."""
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import AbstractPen, DecomposingPen
|
||||
from fontTools.pens.pointPen import AbstractPointPen
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
from reportlab.graphics.shapes import Path
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.misc.arrayTools import pairwise
|
||||
from fontTools.pens.filterPen import ContourFilterPen
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""Pen calculating area, center of mass, variance and standard-deviation,
|
||||
covariance and correlation, and slant, of glyph shapes."""
|
||||
from fontTools.misc.py23 import *
|
||||
import math
|
||||
from fontTools.pens.momentsPen import MomentsPen
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
# Copyright (c) 2009 Type Supply LLC
|
||||
# Author: Tal Leming
|
||||
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.misc.fixedTools import otRound
|
||||
from fontTools.misc.psCharStrings import T2CharString
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""Pen multiplexing drawing to one or more pens."""
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.filterPen import FilterPen, FilterPointPen
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from array import array
|
||||
from fontTools.misc.fixedTools import MAX_F2DOT14, otRound, floatToFixedToFloat
|
||||
from fontTools.pens.basePen import LoggingPen
|
||||
@ -73,6 +72,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]:
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import BasePen
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.areaPen import AreaPen
|
||||
import unittest
|
||||
|
||||
|
@ -1,10 +1,33 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import \
|
||||
BasePen, decomposeSuperBezierSegment, decomposeQuadraticSegment
|
||||
AbstractPen, BasePen, decomposeSuperBezierSegment, decomposeQuadraticSegment
|
||||
from fontTools.pens.pointPen import AbstractPointPen
|
||||
from fontTools.misc.loggingTools import CapturingLogHandler
|
||||
import unittest
|
||||
|
||||
|
||||
def test_subclasshook():
|
||||
class NullPen:
|
||||
def moveTo(self, pt):
|
||||
pass
|
||||
def lineTo(self, pt):
|
||||
pass
|
||||
def curveTo(self, *points):
|
||||
pass
|
||||
def qCurveTo(self, *points):
|
||||
pass
|
||||
def closePath(self):
|
||||
pass
|
||||
def endPath(self):
|
||||
pass
|
||||
def addComponent(self, glyphName, transformation):
|
||||
pass
|
||||
|
||||
assert issubclass(NullPen, AbstractPen)
|
||||
assert isinstance(NullPen(), AbstractPen)
|
||||
assert not issubclass(NullPen, AbstractPointPen)
|
||||
assert not isinstance(NullPen(), AbstractPointPen)
|
||||
|
||||
|
||||
class _TestPen(BasePen):
|
||||
def __init__(self):
|
||||
BasePen.__init__(self, glyphSet={})
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.boundsPen import BoundsPen, ControlBoundsPen
|
||||
import unittest
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
import unittest
|
||||
|
||||
try:
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.perimeterPen import PerimeterPen
|
||||
import unittest
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from io import StringIO
|
||||
from fontTools.pens.pointInsidePen import PointInsidePen
|
||||
import unittest
|
||||
|
||||
@ -72,16 +72,16 @@ class PointInsidePenTest(unittest.TestCase):
|
||||
|
||||
@staticmethod
|
||||
def render(draw_function, even_odd):
|
||||
result = BytesIO()
|
||||
result = StringIO()
|
||||
for y in range(5):
|
||||
for x in range(10):
|
||||
pen = PointInsidePen(None, (x + 0.5, y + 0.5), even_odd)
|
||||
draw_function(pen)
|
||||
if pen.getResult():
|
||||
result.write(b"*")
|
||||
result.write("*")
|
||||
else:
|
||||
result.write(b" ")
|
||||
return tounicode(result.getvalue())
|
||||
result.write(" ")
|
||||
return result.getvalue()
|
||||
|
||||
|
||||
def test_contour_no_solutions(self):
|
||||
|
@ -1,5 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.misc.loggingTools import CapturingLogHandler
|
||||
import unittest
|
||||
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
@ -7,6 +5,23 @@ from fontTools.pens.pointPen import AbstractPointPen, PointToSegmentPen, \
|
||||
SegmentToPointPen, GuessSmoothPointPen, ReverseContourPointPen
|
||||
|
||||
|
||||
def test_subclasshook():
|
||||
class NullPen:
|
||||
def beginPath(self, identifier, **kwargs) -> None:
|
||||
pass
|
||||
def endPath(self) -> None:
|
||||
pass
|
||||
def addPoint(self, pt, segmentType, smooth, name, identifier, **kwargs) -> None:
|
||||
pass
|
||||
def addComponent(self, baseGlyphName, transformation, identifier, **kwargs) -> None:
|
||||
pass
|
||||
|
||||
assert issubclass(NullPen, AbstractPointPen)
|
||||
assert isinstance(NullPen(), AbstractPointPen)
|
||||
assert not issubclass(NullPen, AbstractPen)
|
||||
assert not isinstance(NullPen(), AbstractPen)
|
||||
|
||||
|
||||
class _TestSegmentPen(AbstractPen):
|
||||
|
||||
def __init__(self):
|
||||
@ -43,7 +58,7 @@ def _reprKwargs(kwargs):
|
||||
items = []
|
||||
for key in sorted(kwargs):
|
||||
value = kwargs[key]
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, str):
|
||||
items.append("%s='%s'" % (key, value))
|
||||
else:
|
||||
items.append("%s=%s" % (key, value))
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
import unittest
|
||||
|
||||
try:
|
||||
|
@ -1,4 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.t2CharStringPen import T2CharStringPen
|
||||
import unittest
|
||||
|
||||
@ -7,16 +6,12 @@ class T2CharStringPenTest(unittest.TestCase):
|
||||
|
||||
def __init__(self, methodName):
|
||||
unittest.TestCase.__init__(self, methodName)
|
||||
# Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
|
||||
# and fires deprecation warnings if a program uses the old name.
|
||||
if not hasattr(self, "assertRaisesRegex"):
|
||||
self.assertRaisesRegex = self.assertRaisesRegexp
|
||||
|
||||
def assertAlmostEqualProgram(self, expected, actual):
|
||||
self.assertEqual(len(expected), len(actual))
|
||||
for i1, i2 in zip(expected, actual):
|
||||
if isinstance(i1, basestring):
|
||||
self.assertIsInstance(i2, basestring)
|
||||
if isinstance(i1, str):
|
||||
self.assertIsInstance(i2, str)
|
||||
self.assertEqual(i1, i2)
|
||||
else:
|
||||
self.assertAlmostEqual(i1, i2)
|
||||
|
@ -1,5 +1,3 @@
|
||||
from fontTools.misc.py23 import *
|
||||
|
||||
import os
|
||||
import unittest
|
||||
import struct
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
from . import CUBIC_GLYPHS
|
||||
from fontTools.pens.pointPen import PointToSegmentPen, SegmentToPointPen
|
||||
from fontTools.misc.py23 import isclose
|
||||
from math import isclose
|
||||
import unittest
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user