[reverseContourPen] Add outputImpliedClosingLine

Fixes https://github.com/fonttools/fonttools/issues/2914
This commit is contained in:
Behdad Esfahbod 2022-12-09 15:27:07 -07:00
parent 6aca5be9b7
commit ddbbef2257
2 changed files with 36 additions and 12 deletions

View File

@ -14,11 +14,15 @@ class ReverseContourPen(ContourFilterPen):
the first point.
"""
def __init__(self, outPen, outputImpliedClosingLine=False):
super().__init__(outPen)
self.outputImpliedClosingLine = outputImpliedClosingLine
def filterContour(self, contour):
return reversedContour(contour)
return reversedContour(contour, self.outputImpliedClosingLine)
def reversedContour(contour):
def reversedContour(contour, outputImpliedClosingLine=False):
""" Generator that takes a list of pen's (operator, operands) tuples,
and yields them with the winding direction reversed.
"""
@ -60,7 +64,7 @@ def reversedContour(contour):
if closed:
# for closed paths, we keep the starting point
yield firstType, firstPts
if firstOnCurve != lastOnCurve:
if outputImpliedClosingLine or firstOnCurve != lastOnCurve:
# emit an implied line between the last and first points
yield "lineTo", (lastOnCurve,)
contour[-1] = (lastType,
@ -71,6 +75,8 @@ def reversedContour(contour):
else:
# contour has only two points, the second and last are the same
secondType, secondPts = lastType, lastPts
if not outputImpliedClosingLine:
# if a lineTo follows the initial moveTo, after reversing it
# will be implied by the closePath, so we don't emit one;
# unless the lineTo and moveTo overlap, in which case we keep the

View File

@ -310,6 +310,24 @@ def test_reverse_pen(contour, expected):
getattr(revpen, operator)(*operands)
assert recpen.value == expected
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 len(recpen.value) == 4
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 len(recpen.value) == 6
@pytest.mark.parametrize("contour, expected", TEST_DATA)
def test_reverse_point_pen(contour, expected):