aboutsummaryrefslogtreecommitdiff
path: root/Tests/pens/reverseContourPen_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/pens/reverseContourPen_test.py')
-rw-r--r--Tests/pens/reverseContourPen_test.py589
1 files changed, 385 insertions, 204 deletions
diff --git a/Tests/pens/reverseContourPen_test.py b/Tests/pens/reverseContourPen_test.py
index 9c715404..c250847e 100644
--- a/Tests/pens/reverseContourPen_test.py
+++ b/Tests/pens/reverseContourPen_test.py
@@ -6,331 +6,512 @@ import pytest
TEST_DATA = [
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('lineTo', ((2, 2),)),
- ('lineTo', ((3, 3),)), # last not on move, line is implied
- ('closePath', ()),
- ],
- [
- ('moveTo', ((0, 0),)),
- ('lineTo', ((3, 3),)),
- ('lineTo', ((2, 2),)),
- ('lineTo', ((1, 1),)),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((3, 3),)), # last not on move, line is implied
+ ("closePath", ()),
+ ],
+ False, # outputImpliedClosingLine
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((3, 3),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('lineTo', ((2, 2),)),
- ('lineTo', ((0, 0),)), # last on move, no implied line
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((3, 3),)), # last line does not overlap move...
+ ("closePath", ()),
],
+ True, # outputImpliedClosingLine
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((3, 3),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((0, 0),)), # ... but closing line is NOT implied
+ ("closePath", ()),
+ ],
+ ),
+ (
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((0, 0),)), # last line overlaps move, explicit line
+ ("closePath", ()),
+ ],
+ False,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((2, 2),)),
- ('lineTo', ((1, 1),)),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("closePath", ()), # closing line implied
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('lineTo', ((2, 2),)),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((0, 0),)), # last line overlaps move...
+ ("closePath", ()),
],
+ True,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((2, 2),)),
- ('lineTo', ((1, 1),)),
- ('lineTo', ((0, 0),)),
- ('lineTo', ((0, 0),)),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((0, 0),)), # ... but line is NOT implied
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((0, 0),)), # duplicate lineTo following moveTo
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("closePath", ()),
+ ],
+ False,
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((0, 0),)), # extra explicit lineTo is always emitted to
+ ("lineTo", ((0, 0),)), # disambiguate from an implicit closing line
+ ("closePath", ()),
],
+ ),
+ (
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((0, 0),)), # duplicate lineTo following moveTo
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((2, 2),)),
+ ("closePath", ()),
+ ],
+ True,
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((2, 2),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((0, 0),)), # duplicate lineTo is retained also in this case,
+ ("lineTo", ((0, 0),)), # same result as with outputImpliedClosingLine=False
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('curveTo', ((1, 1), (2, 2), (3, 3))),
- ('curveTo', ((4, 4), (5, 5), (0, 0))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((0, 0),)),
- ('curveTo', ((5, 5), (4, 4), (3, 3))),
- ('curveTo', ((2, 2), (1, 1), (0, 0))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('curveTo', ((1, 1), (2, 2), (3, 3))),
- ('curveTo', ((4, 4), (5, 5), (6, 6))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("closePath", ()),
],
+ True,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((6, 6),)), # implied line
- ('curveTo', ((5, 5), (4, 4), (3, 3))),
- ('curveTo', ((2, 2), (1, 1), (0, 0))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("lineTo", ((0, 0),)),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)), # this line becomes implied
- ('curveTo', ((2, 2), (3, 3), (4, 4))),
- ('curveTo', ((5, 5), (6, 6), (7, 7))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((1, 1), (2, 2), (3, 3))),
+ ("curveTo", ((4, 4), (5, 5), (0, 0))), # closed curveTo overlaps moveTo
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((7, 7),)),
- ('curveTo', ((6, 6), (5, 5), (4, 4))),
- ('curveTo', ((3, 3), (2, 2), (1, 1))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)), # no extra lineTo added here
+ ("curveTo", ((5, 5), (4, 4), (3, 3))),
+ ("curveTo", ((2, 2), (1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('qCurveTo', ((1, 1), (2, 2))),
- ('qCurveTo', ((3, 3), (0, 0))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((1, 1), (2, 2), (3, 3))),
+ ("curveTo", ((4, 4), (5, 5), (0, 0))), # closed curveTo overlaps moveTo
+ ("closePath", ()),
],
+ True,
[
- ('moveTo', ((0, 0),)),
- ('qCurveTo', ((3, 3), (2, 2))),
- ('qCurveTo', ((1, 1), (0, 0))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)), # no extra lineTo added here, same as preceding
+ ("curveTo", ((5, 5), (4, 4), (3, 3))),
+ ("curveTo", ((2, 2), (1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('qCurveTo', ((1, 1), (2, 2))),
- ('qCurveTo', ((3, 3), (4, 4))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((1, 1), (2, 2), (3, 3))),
+ ("curveTo", ((4, 4), (5, 5), (6, 6))), # closed curve not overlapping move
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((4, 4),)),
- ('qCurveTo', ((3, 3), (2, 2))),
- ('qCurveTo', ((1, 1), (0, 0))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((6, 6),)), # the previously implied line
+ ("curveTo", ((5, 5), (4, 4), (3, 3))),
+ ("curveTo", ((2, 2), (1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('qCurveTo', ((2, 2), (3, 3))),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((1, 1), (2, 2), (3, 3))),
+ ("curveTo", ((4, 4), (5, 5), (6, 6))), # closed curve not overlapping move
+ ("closePath", ()),
],
+ True,
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((3, 3),)),
- ('qCurveTo', ((2, 2), (1, 1))),
- ('closePath', ()),
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((6, 6),)), # the previously implied line (same as above)
+ ("curveTo", ((5, 5), (4, 4), (3, 3))),
+ ("curveTo", ((2, 2), (1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
),
(
[
- ('addComponent', ('a', (1, 0, 0, 1, 0, 0)))
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)), # this line becomes implied
+ ("curveTo", ((2, 2), (3, 3), (4, 4))),
+ ("curveTo", ((5, 5), (6, 6), (7, 7))),
+ ("closePath", ()),
],
+ False,
[
- ('addComponent', ('a', (1, 0, 0, 1, 0, 0)))
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((7, 7),)),
+ ("curveTo", ((6, 6), (5, 5), (4, 4))),
+ ("curveTo", ((3, 3), (2, 2), (1, 1))),
+ ("closePath", ()),
+ ],
),
(
- [], []
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)), # this line...
+ ("curveTo", ((2, 2), (3, 3), (4, 4))),
+ ("curveTo", ((5, 5), (6, 6), (7, 7))),
+ ("closePath", ()),
+ ],
+ True,
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((7, 7),)),
+ ("curveTo", ((6, 6), (5, 5), (4, 4))),
+ ("curveTo", ((3, 3), (2, 2), (1, 1))),
+ ("lineTo", ((0, 0),)), # ... does NOT become implied
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('endPath', ()),
+ ("moveTo", ((0, 0),)),
+ ("qCurveTo", ((1, 1), (2, 2))),
+ ("qCurveTo", ((3, 3), (0, 0))), # closed qCurve overlaps move
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((0, 0),)),
- ('endPath', ()),
+ ("moveTo", ((0, 0),)), # no extra lineTo added here
+ ("qCurveTo", ((3, 3), (2, 2))),
+ ("qCurveTo", ((1, 1), (0, 0))),
+ ("closePath", ()),
],
),
(
[
- ('moveTo', ((0, 0),)),
- ('closePath', ()),
+ ("moveTo", ((0, 0),)),
+ ("qCurveTo", ((1, 1), (2, 2))),
+ ("qCurveTo", ((3, 3), (0, 0))), # closed qCurve overlaps move
+ ("closePath", ()),
],
+ True, # <--
[
- ('moveTo', ((0, 0),)),
- ('endPath', ()), # single-point paths is always open
+ ("moveTo", ((0, 0),)), # no extra lineTo added here, same as above
+ ("qCurveTo", ((3, 3), (2, 2))),
+ ("qCurveTo", ((1, 1), (0, 0))),
+ ("closePath", ()),
],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('endPath', ())
+ ("moveTo", ((0, 0),)),
+ ("qCurveTo", ((1, 1), (2, 2))),
+ ("qCurveTo", ((3, 3), (4, 4))), # closed qCurve not overlapping move
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((1, 1),)),
- ('lineTo', ((0, 0),)),
- ('endPath', ())
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((4, 4),)), # the previously implied line
+ ("qCurveTo", ((3, 3), (2, 2))),
+ ("qCurveTo", ((1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('curveTo', ((1, 1), (2, 2), (3, 3))),
- ('endPath', ())
+ ("moveTo", ((0, 0),)),
+ ("qCurveTo", ((1, 1), (2, 2))),
+ ("qCurveTo", ((3, 3), (4, 4))), # closed qCurve not overlapping move
+ ("closePath", ()),
],
+ True,
[
- ('moveTo', ((3, 3),)),
- ('curveTo', ((2, 2), (1, 1), (0, 0))),
- ('endPath', ())
- ]
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((4, 4),)), # the previously implied line (same as above)
+ ("qCurveTo", ((3, 3), (2, 2))),
+ ("qCurveTo", ((1, 1), (0, 0))),
+ ("closePath", ()),
+ ],
+ ),
+ (
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("qCurveTo", ((2, 2), (3, 3))),
+ ("closePath", ()),
+ ],
+ False,
+ [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((3, 3),)),
+ ("qCurveTo", ((2, 2), (1, 1))),
+ ("closePath", ()),
+ ],
+ ),
+ (
+ [("addComponent", ("a", (1, 0, 0, 1, 0, 0)))],
+ False,
+ [("addComponent", ("a", (1, 0, 0, 1, 0, 0)))],
),
+ ([], False, []),
(
[
- ('moveTo', ((0, 0),)),
- ('curveTo', ((1, 1), (2, 2), (3, 3))),
- ('lineTo', ((4, 4),)),
- ('endPath', ())
+ ("moveTo", ((0, 0),)),
+ ("endPath", ()),
],
+ False,
[
- ('moveTo', ((4, 4),)),
- ('lineTo', ((3, 3),)),
- ('curveTo', ((2, 2), (1, 1), (0, 0))),
- ('endPath', ())
- ]
+ ("moveTo", ((0, 0),)),
+ ("endPath", ()),
+ ],
),
(
[
- ('moveTo', ((0, 0),)),
- ('lineTo', ((1, 1),)),
- ('curveTo', ((2, 2), (3, 3), (4, 4))),
- ('endPath', ())
+ ("moveTo", ((0, 0),)),
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((4, 4),)),
- ('curveTo', ((3, 3), (2, 2), (1, 1))),
- ('lineTo', ((0, 0),)),
- ('endPath', ())
- ]
+ ("moveTo", ((0, 0),)),
+ ("endPath", ()), # single-point paths is always open
+ ],
+ ),
+ (
+ [("moveTo", ((0, 0),)), ("lineTo", ((1, 1),)), ("endPath", ())],
+ False,
+ [("moveTo", ((1, 1),)), ("lineTo", ((0, 0),)), ("endPath", ())],
+ ),
+ (
+ [("moveTo", ((0, 0),)), ("curveTo", ((1, 1), (2, 2), (3, 3))), ("endPath", ())],
+ False,
+ [("moveTo", ((3, 3),)), ("curveTo", ((2, 2), (1, 1), (0, 0))), ("endPath", ())],
),
(
[
- ('qCurveTo', ((0, 0), (1, 1), (2, 2), None)),
- ('closePath', ())
+ ("moveTo", ((0, 0),)),
+ ("curveTo", ((1, 1), (2, 2), (3, 3))),
+ ("lineTo", ((4, 4),)),
+ ("endPath", ()),
],
+ False,
[
- ('qCurveTo', ((0, 0), (2, 2), (1, 1), None)),
- ('closePath', ())
- ]
+ ("moveTo", ((4, 4),)),
+ ("lineTo", ((3, 3),)),
+ ("curveTo", ((2, 2), (1, 1), (0, 0))),
+ ("endPath", ()),
+ ],
),
(
[
- ('qCurveTo', ((0, 0), (1, 1), (2, 2), None)),
- ('endPath', ())
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((1, 1),)),
+ ("curveTo", ((2, 2), (3, 3), (4, 4))),
+ ("endPath", ()),
],
+ False,
[
- ('qCurveTo', ((0, 0), (2, 2), (1, 1), None)),
- ('closePath', ()) # this is always "closed"
- ]
+ ("moveTo", ((4, 4),)),
+ ("curveTo", ((3, 3), (2, 2), (1, 1))),
+ ("lineTo", ((0, 0),)),
+ ("endPath", ()),
+ ],
+ ),
+ (
+ [("qCurveTo", ((0, 0), (1, 1), (2, 2), None)), ("closePath", ())],
+ False,
+ [("qCurveTo", ((0, 0), (2, 2), (1, 1), None)), ("closePath", ())],
+ ),
+ (
+ [("qCurveTo", ((0, 0), (1, 1), (2, 2), None)), ("endPath", ())],
+ False,
+ [
+ ("qCurveTo", ((0, 0), (2, 2), (1, 1), None)),
+ ("closePath", ()), # this is always "closed"
+ ],
),
# Test case from:
# https://github.com/googlei18n/cu2qu/issues/51#issue-179370514
(
[
- ('moveTo', ((848, 348),)),
- ('lineTo', ((848, 348),)), # duplicate lineTo point after moveTo
- ('qCurveTo', ((848, 526), (649, 704), (449, 704))),
- ('qCurveTo', ((449, 704), (248, 704), (50, 526), (50, 348))),
- ('lineTo', ((50, 348),)),
- ('qCurveTo', ((50, 348), (50, 171), (248, -3), (449, -3))),
- ('qCurveTo', ((449, -3), (649, -3), (848, 171), (848, 348))),
- ('closePath', ())
- ],
- [
- ('moveTo', ((848, 348),)),
- ('qCurveTo', ((848, 171), (649, -3), (449, -3), (449, -3))),
- ('qCurveTo', ((248, -3), (50, 171), (50, 348), (50, 348))),
- ('lineTo', ((50, 348),)),
- ('qCurveTo', ((50, 526), (248, 704), (449, 704), (449, 704))),
- ('qCurveTo', ((649, 704), (848, 526), (848, 348))),
- ('lineTo', ((848, 348),)), # the duplicate point is kept
- ('closePath', ())
- ]
+ ("moveTo", ((848, 348),)),
+ ("lineTo", ((848, 348),)), # duplicate lineTo point after moveTo
+ ("qCurveTo", ((848, 526), (649, 704), (449, 704))),
+ ("qCurveTo", ((449, 704), (248, 704), (50, 526), (50, 348))),
+ ("lineTo", ((50, 348),)),
+ ("qCurveTo", ((50, 348), (50, 171), (248, -3), (449, -3))),
+ ("qCurveTo", ((449, -3), (649, -3), (848, 171), (848, 348))),
+ ("closePath", ()),
+ ],
+ False,
+ [
+ ("moveTo", ((848, 348),)),
+ ("qCurveTo", ((848, 171), (649, -3), (449, -3), (449, -3))),
+ ("qCurveTo", ((248, -3), (50, 171), (50, 348), (50, 348))),
+ ("lineTo", ((50, 348),)),
+ ("qCurveTo", ((50, 526), (248, 704), (449, 704), (449, 704))),
+ ("qCurveTo", ((649, 704), (848, 526), (848, 348))),
+ ("lineTo", ((848, 348),)), # the duplicate point is kept
+ ("closePath", ()),
+ ],
),
# Test case from https://github.com/googlefonts/fontmake/issues/572
# An additional closing lineTo is required to disambiguate a duplicate
# point at the end of a contour from the implied closing line.
(
[
- ('moveTo', ((0, 651),)),
- ('lineTo', ((0, 101),)),
- ('lineTo', ((0, 101),)),
- ('lineTo', ((0, 651),)),
- ('lineTo', ((0, 651),)),
- ('closePath', ())
+ ("moveTo", ((0, 651),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 651),)),
+ ("lineTo", ((0, 651),)),
+ ("closePath", ()),
],
+ False,
[
- ('moveTo', ((0, 651),)),
- ('lineTo', ((0, 651),)),
- ('lineTo', ((0, 101),)),
- ('lineTo', ((0, 101),)),
- ('closePath', ())
- ]
- )
+ ("moveTo", ((0, 651),)),
+ ("lineTo", ((0, 651),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 101),)),
+ ("closePath", ()),
+ ],
+ ),
+ (
+ [
+ ("moveTo", ((0, 651),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 651),)),
+ ("lineTo", ((0, 651),)),
+ ("closePath", ()),
+ ],
+ True,
+ [
+ ("moveTo", ((0, 651),)),
+ ("lineTo", ((0, 651),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 101),)),
+ ("lineTo", ((0, 651),)), # closing line not implied
+ ("closePath", ()),
+ ],
+ ),
]
-@pytest.mark.parametrize("contour, expected", TEST_DATA)
-def test_reverse_pen(contour, expected):
+@pytest.mark.parametrize("contour, outputImpliedClosingLine, expected", TEST_DATA)
+def test_reverse_pen(contour, outputImpliedClosingLine, expected):
recpen = RecordingPen()
- revpen = ReverseContourPen(recpen)
+ revpen = ReverseContourPen(recpen, outputImpliedClosingLine)
for operator, operands in contour:
getattr(revpen, operator)(*operands)
assert recpen.value == expected
-@pytest.mark.parametrize("contour, expected", TEST_DATA)
-def test_reverse_point_pen(contour, expected):
- from fontTools.ufoLib.pointPen import (
- ReverseContourPointPen, PointToSegmentPen, SegmentToPointPen)
+def test_reverse_pen_outputImpliedClosingLine():
+ recpen = RecordingPen()
+ revpen = ReverseContourPen(recpen)
+ revpen.moveTo((0, 0))
+ revpen.lineTo((10, 0))
+ revpen.lineTo((0, 10))
+ revpen.lineTo((0, 0))
+ revpen.closePath()
+ assert recpen.value == [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((0, 10),)),
+ ("lineTo", ((10, 0),)),
+ # ("lineTo", ((0, 0),)), # implied
+ ("closePath", ()),
+ ]
+
+ recpen = RecordingPen()
+ revpen = ReverseContourPen(recpen, outputImpliedClosingLine=True)
+ revpen.moveTo((0, 0))
+ revpen.lineTo((10, 0))
+ revpen.lineTo((0, 10))
+ revpen.lineTo((0, 0))
+ revpen.closePath()
+ assert recpen.value == [
+ ("moveTo", ((0, 0),)),
+ ("lineTo", ((0, 10),)),
+ ("lineTo", ((10, 0),)),
+ ("lineTo", ((0, 0),)), # not implied
+ ("closePath", ()),
+ ]
+
+
+@pytest.mark.parametrize("contour, outputImpliedClosingLine, expected", TEST_DATA)
+def test_reverse_point_pen(contour, outputImpliedClosingLine, expected):
+ from fontTools.pens.pointPen import (
+ ReverseContourPointPen,
+ PointToSegmentPen,
+ SegmentToPointPen,
+ )
recpen = RecordingPen()
- pt2seg = PointToSegmentPen(recpen, outputImpliedClosingLine=True)
+ pt2seg = PointToSegmentPen(recpen, outputImpliedClosingLine)
revpen = ReverseContourPointPen(pt2seg)
seg2pt = SegmentToPointPen(revpen)
for operator, operands in contour:
getattr(seg2pt, operator)(*operands)
- # for closed contours that have a lineTo following the moveTo,
- # and whose points don't overlap, our current implementation diverges
- # from the ReverseContourPointPen as wrapped by ufoLib's pen converters.
- # In the latter case, an extra lineTo is added because of
- # outputImpliedClosingLine=True. This is redundant but not incorrect,
- # as the number of points is the same in both.
- if (contour and contour[-1][0] == "closePath" and
- contour[1][0] == "lineTo" and contour[1][1] != contour[0][1]):
- expected = expected[:-1] + [("lineTo", contour[0][1])] + expected[-1:]
-
assert recpen.value == expected