fonttools/Lib/robofab/pens/reverseContourPointPen.py
Just van Rossum feb0046176 Moved Data, Lib and install.py one level down the tree
git-svn-id: http://svn.robofab.com/trunk@67 b5fa9d6c-a76f-4ffd-b3cb-f825fc41095c
2008-03-11 09:18:32 +00:00

126 lines
3.5 KiB
Python
Executable File

"""PointPen for reversing the winding direction of contours."""
__all__ = ["ReverseContourPointPen"]
from robofab.pens.pointPen import AbstractPointPen
class ReverseContourPointPen(AbstractPointPen):
"""This is a PointPen that passes outline data to another PointPen, but
reversing the winding direction of all contours. Components are simply
passed through unchanged.
Closed contours are reversed in such a way that the first point remains
the first point.
"""
def __init__(self, outputPointPen):
self.pen = outputPointPen
self.currentContour = None # a place to store the points for the current sub path
def _flushContour(self):
pen = self.pen
contour = self.currentContour
if not contour:
pen.beginPath()
pen.endPath()
return
closed = contour[0][1] != "move"
if not closed:
lastSegmentType = "move"
else:
# Remove the first point and insert it at the end. When
# the list of points gets reversed, this point will then
# again be at the start. In other words, the following
# will hold:
# for N in range(len(originalContour)):
# originalContour[N] == reversedContour[-N]
contour.append(contour.pop(0))
# Find the first on-curve point.
firstOnCurve = None
for i in range(len(contour)):
if contour[i][1] is not None:
firstOnCurve = i
break
if firstOnCurve is None:
# There are no on-curve points, be basically have to
# do nothing but contour.reverse().
lastSegmentType = None
else:
lastSegmentType = contour[firstOnCurve][1]
contour.reverse()
if not closed:
# Open paths must start with a move, so we simply dump
# all off-curve points leading up to the first on-curve.
while contour[0][1] is None:
contour.pop(0)
pen.beginPath()
for pt, nextSegmentType, smooth, name in contour:
if nextSegmentType is not None:
segmentType = lastSegmentType
lastSegmentType = nextSegmentType
else:
segmentType = None
pen.addPoint(pt, segmentType=segmentType, smooth=smooth, name=name)
pen.endPath()
def beginPath(self):
assert self.currentContour is None
self.currentContour = []
self.onCurve = []
def endPath(self):
assert self.currentContour is not None
self._flushContour()
self.currentContour = None
def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
self.currentContour.append((pt, segmentType, smooth, name))
def addComponent(self, glyphName, transform):
assert self.currentContour is None
self.pen.addComponent(glyphName, transform)
if __name__ == "__main__":
from robofab.pens.pointPen import PrintingPointPen
pP = PrintingPointPen()
rP = ReverseContourPointPen(pP)
rP.beginPath()
rP.addPoint((339, -8), "curve")
rP.addPoint((502, -8))
rP.addPoint((635, 65))
rP.addPoint((635, 305), "curve")
rP.addPoint((635, 545))
rP.addPoint((504, 623))
rP.addPoint((340, 623), "curve")
rP.addPoint((177, 623))
rP.addPoint((43, 545))
rP.addPoint((43, 305), "curve")
rP.addPoint((43, 65))
rP.addPoint((176, -8))
rP.endPath()
rP.beginPath()
rP.addPoint((100, 100), "move", smooth=False, name='a')
rP.addPoint((150, 150))
rP.addPoint((200, 200))
rP.addPoint((250, 250), "curve", smooth=True, name='b')
rP.addPoint((300, 300), "line", smooth=False, name='c')
rP.addPoint((350, 350))
rP.addPoint((400, 400))
rP.addPoint((450, 450))
rP.addPoint((500, 500), "curve", smooth=True, name='d')
rP.addPoint((550, 550))
rP.addPoint((600, 600))
rP.addPoint((650, 650))
rP.addPoint((700, 700))
rP.addPoint((750, 750), "qcurve", smooth=False, name='e')
rP.endPath()