aboutsummaryrefslogtreecommitdiff
path: root/Tests/pens/ttGlyphPen_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/pens/ttGlyphPen_test.py')
-rw-r--r--Tests/pens/ttGlyphPen_test.py256
1 files changed, 243 insertions, 13 deletions
diff --git a/Tests/pens/ttGlyphPen_test.py b/Tests/pens/ttGlyphPen_test.py
index 96d75a19..6a74cb25 100644
--- a/Tests/pens/ttGlyphPen_test.py
+++ b/Tests/pens/ttGlyphPen_test.py
@@ -4,6 +4,7 @@ import struct
from fontTools import ttLib
from fontTools.pens.basePen import PenError
+from fontTools.pens.recordingPen import RecordingPen, RecordingPointPen
from fontTools.pens.ttGlyphPen import TTGlyphPen, TTGlyphPointPen, MAX_F2DOT14
@@ -21,12 +22,11 @@ class TTGlyphPenTestBase:
glyphSet = font.getGlyphSet()
glyfTable = font["glyf"]
- pen = self.penClass(font.getGlyphSet())
+ pen = self.penClass(glyphSet)
for name in font.getGlyphOrder():
- oldGlyph = glyphSet[name]
- getattr(oldGlyph, self.drawMethod)(pen)
- oldGlyph = oldGlyph._glyph
+ getattr(glyphSet[name], self.drawMethod)(pen)
+ oldGlyph = glyfTable[name]
newGlyph = pen.glyph()
if hasattr(oldGlyph, "program"):
@@ -295,6 +295,27 @@ class TTGlyphPenTest(TTGlyphPenTestBase):
uni0302_uni0300.recalcBounds(glyphSet)
self.assertGlyphBoundsEqual(uni0302_uni0300, (-278, 745, 148, 1025))
+ def test_outputImpliedClosingLine(self):
+ glyphSet = {}
+
+ pen = TTGlyphPen(glyphSet)
+ pen.moveTo((0, 0))
+ pen.lineTo((10, 0))
+ pen.lineTo((0, 10))
+ pen.lineTo((0, 0))
+ pen.closePath()
+ glyph = pen.glyph()
+ assert len(glyph.coordinates) == 3
+
+ pen = TTGlyphPen(glyphSet, outputImpliedClosingLine=True)
+ pen.moveTo((0, 0))
+ pen.lineTo((10, 0))
+ pen.lineTo((0, 10))
+ pen.lineTo((0, 0))
+ pen.closePath()
+ glyph = pen.glyph()
+ assert len(glyph.coordinates) == 4
+
class TTGlyphPointPenTest(TTGlyphPenTestBase):
penClass = TTGlyphPointPen
@@ -312,11 +333,11 @@ class TTGlyphPointPenTest(TTGlyphPenTestBase):
assert glyph.numberOfContours == 1
assert glyph.endPtsOfContours == [3]
- def test_addPoint_errorOnCurve(self):
+ def test_addPoint_noErrorOnCurve(self):
pen = TTGlyphPointPen(None)
pen.beginPath()
- with pytest.raises(NotImplementedError):
- pen.addPoint((0, 0), "curve")
+ pen.addPoint((0, 0), "curve")
+ pen.endPath()
def test_beginPath_beginPathOnOpenPath(self):
pen = TTGlyphPointPen(None)
@@ -332,12 +353,6 @@ class TTGlyphPointPenTest(TTGlyphPenTestBase):
with pytest.raises(PenError):
pen.glyph()
- def test_glyph_errorOnEmptyContour(self):
- pen = TTGlyphPointPen(None)
- pen.beginPath()
- with pytest.raises(PenError):
- pen.endPath()
-
def test_glyph_decomposes(self):
componentName = "a"
glyphSet = {}
@@ -574,6 +589,221 @@ class TTGlyphPointPenTest(TTGlyphPenTestBase):
assert pen1.points == pen2.points == [(0, 0), (10, 10), (20, 20), (20, 0)]
assert pen1.types == pen2.types == [1, 1, 0, 1]
+ def test_skip_empty_contours(self):
+ pen = TTGlyphPointPen(None)
+ pen.beginPath()
+ pen.endPath()
+ pen.beginPath()
+ pen.endPath()
+ glyph = pen.glyph()
+ assert glyph.numberOfContours == 0
+
+
+class CubicGlyfTest:
+ def test_cubic_simple(self):
+ spen = TTGlyphPen(None)
+ spen.moveTo((0, 0))
+ spen.curveTo((0, 1), (1, 1), (1, 0))
+ spen.closePath()
+
+ ppen = TTGlyphPointPen(None)
+ ppen.beginPath()
+ ppen.addPoint((0, 0), "line")
+ ppen.addPoint((0, 1))
+ ppen.addPoint((1, 1))
+ ppen.addPoint((1, 0), "curve")
+ ppen.endPath()
+
+ for pen in (spen, ppen):
+ glyph = pen.glyph()
+
+ for i in range(2):
+ if i == 1:
+ glyph.compile(None)
+
+ assert list(glyph.coordinates) == [(0, 0), (0, 1), (1, 1), (1, 0)]
+ assert list(glyph.flags) == [0x01, 0x80, 0x80, 0x01]
+
+ rpen = RecordingPen()
+ glyph.draw(rpen, None)
+ assert rpen.value == [
+ ("moveTo", ((0, 0),)),
+ (
+ "curveTo",
+ (
+ (0, 1),
+ (1, 1),
+ (1, 0),
+ ),
+ ),
+ ("closePath", ()),
+ ]
+
+ @pytest.mark.parametrize(
+ "dropImpliedOnCurves, segment_pen_commands, point_pen_commands, expected_coordinates, expected_flags, expected_endPts",
+ [
+ ( # Two curves that do NOT merge; request merging
+ True,
+ [
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((0, 1), (1, 2), (2, 2))),
+ ("curveTo", ((3, 3), (4, 1), (4, 0))),
+ ("closePath", ()),
+ ],
+ [
+ ("beginPath", (), {}),
+ ("addPoint", ((0, 0), "line", None, None), {}),
+ ("addPoint", ((0, 1), None, None, None), {}),
+ ("addPoint", ((1, 2), None, None, None), {}),
+ ("addPoint", ((2, 2), "curve", None, None), {}),
+ ("addPoint", ((3, 3), None, None, None), {}),
+ ("addPoint", ((4, 1), None, None, None), {}),
+ ("addPoint", ((4, 0), "curve", None, None), {}),
+ ("endPath", (), {}),
+ ],
+ [(0, 0), (0, 1), (1, 2), (2, 2), (3, 3), (4, 1), (4, 0)],
+ [0x01, 0x80, 0x80, 0x01, 0x80, 0x80, 0x01],
+ [6],
+ ),
+ ( # Two curves that merge; request merging
+ True,
+ [
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((0, 1), (1, 2), (2, 2))),
+ ("curveTo", ((3, 2), (4, 1), (4, 0))),
+ ("closePath", ()),
+ ],
+ [
+ ("beginPath", (), {}),
+ ("addPoint", ((0, 0), "line", None, None), {}),
+ ("addPoint", ((0, 1), None, None, None), {}),
+ ("addPoint", ((1, 2), None, None, None), {}),
+ ("addPoint", ((2, 2), "curve", None, None), {}),
+ ("addPoint", ((3, 2), None, None, None), {}),
+ ("addPoint", ((4, 1), None, None, None), {}),
+ ("addPoint", ((4, 0), "curve", None, None), {}),
+ ("endPath", (), {}),
+ ],
+ [(0, 0), (0, 1), (1, 2), (3, 2), (4, 1), (4, 0)],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x01],
+ [5],
+ ),
+ ( # Two curves that merge; request NOT merging
+ False,
+ [
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((0, 1), (1, 2), (2, 2))),
+ ("curveTo", ((3, 2), (4, 1), (4, 0))),
+ ("closePath", ()),
+ ],
+ [
+ ("beginPath", (), {}),
+ ("addPoint", ((0, 0), "line", None, None), {}),
+ ("addPoint", ((0, 1), None, None, None), {}),
+ ("addPoint", ((1, 2), None, None, None), {}),
+ ("addPoint", ((2, 2), "curve", None, None), {}),
+ ("addPoint", ((3, 2), None, None, None), {}),
+ ("addPoint", ((4, 1), None, None, None), {}),
+ ("addPoint", ((4, 0), "curve", None, None), {}),
+ ("endPath", (), {}),
+ ],
+ [(0, 0), (0, 1), (1, 2), (2, 2), (3, 2), (4, 1), (4, 0)],
+ [0x01, 0x80, 0x80, 0x01, 0x80, 0x80, 0x01],
+ [6],
+ ),
+ ( # Two (duplicate) contours
+ True,
+ [
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((0, 1), (1, 2), (2, 2))),
+ ("curveTo", ((3, 2), (4, 1), (4, 0))),
+ ("closePath", ()),
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((0, 1), (1, 2), (2, 2))),
+ ("curveTo", ((3, 2), (4, 1), (4, 0))),
+ ("closePath", ()),
+ ],
+ [
+ ("beginPath", (), {}),
+ ("addPoint", ((0, 0), "line", None, None), {}),
+ ("addPoint", ((0, 1), None, None, None), {}),
+ ("addPoint", ((1, 2), None, None, None), {}),
+ ("addPoint", ((2, 2), "curve", None, None), {}),
+ ("addPoint", ((3, 2), None, None, None), {}),
+ ("addPoint", ((4, 1), None, None, None), {}),
+ ("addPoint", ((4, 0), "curve", None, None), {}),
+ ("endPath", (), {}),
+ ("beginPath", (), {}),
+ ("addPoint", ((0, 0), "line", None, None), {}),
+ ("addPoint", ((0, 1), None, None, None), {}),
+ ("addPoint", ((1, 2), None, None, None), {}),
+ ("addPoint", ((2, 2), "curve", None, None), {}),
+ ("addPoint", ((3, 2), None, None, None), {}),
+ ("addPoint", ((4, 1), None, None, None), {}),
+ ("addPoint", ((4, 0), "curve", None, None), {}),
+ ("endPath", (), {}),
+ ],
+ [
+ (0, 0),
+ (0, 1),
+ (1, 2),
+ (3, 2),
+ (4, 1),
+ (4, 0),
+ (0, 0),
+ (0, 1),
+ (1, 2),
+ (3, 2),
+ (4, 1),
+ (4, 0),
+ ],
+ [
+ 0x01,
+ 0x80,
+ 0x80,
+ 0x80,
+ 0x80,
+ 0x01,
+ 0x01,
+ 0x80,
+ 0x80,
+ 0x80,
+ 0x80,
+ 0x01,
+ ],
+ [5, 11],
+ ),
+ ],
+ )
+ def test_cubic_topology(
+ self,
+ dropImpliedOnCurves,
+ segment_pen_commands,
+ point_pen_commands,
+ expected_coordinates,
+ expected_flags,
+ expected_endPts,
+ ):
+ spen = TTGlyphPen(None)
+ rpen = RecordingPen()
+ rpen.value = segment_pen_commands
+ rpen.replay(spen)
+
+ ppen = TTGlyphPointPen(None)
+ rpen = RecordingPointPen()
+ rpen.value = point_pen_commands
+ rpen.replay(ppen)
+
+ for pen in (spen, ppen):
+ glyph = pen.glyph(dropImpliedOnCurves=dropImpliedOnCurves)
+
+ assert list(glyph.coordinates) == expected_coordinates
+ assert list(glyph.flags) == expected_flags
+ assert list(glyph.endPtsOfContours) == expected_endPts
+
+ rpen = RecordingPen()
+ glyph.draw(rpen, None)
+ assert rpen.value == segment_pen_commands
class _TestGlyph(object):