[reverseContourPen] Add outputImpliedClosingLine
Fixes https://github.com/fonttools/fonttools/issues/2914
This commit is contained in:
parent
6aca5be9b7
commit
ddbbef2257
@ -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,15 +75,17 @@ def reversedContour(contour):
|
||||
else:
|
||||
# contour has only two points, the second and last are the same
|
||||
secondType, secondPts = lastType, lastPts
|
||||
# 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
|
||||
# duplicate points
|
||||
if secondType == "lineTo" and firstPts != secondPts:
|
||||
del contour[0]
|
||||
if contour:
|
||||
contour[-1] = (lastType,
|
||||
tuple(lastPts[:-1]) + secondPts)
|
||||
|
||||
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
|
||||
# duplicate points
|
||||
if secondType == "lineTo" and firstPts != secondPts:
|
||||
del contour[0]
|
||||
if contour:
|
||||
contour[-1] = (lastType,
|
||||
tuple(lastPts[:-1]) + secondPts)
|
||||
else:
|
||||
# for open paths, the last point will become the first
|
||||
yield firstType, (lastOnCurve,)
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user