fonttools/Lib/robofab/pens/mathPens.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

186 lines
5.5 KiB
Python
Executable File

"""Some pens that are needed during glyph math"""
from robofab.pens.pointPen import BasePointToSegmentPen, AbstractPointPen
class GetMathDataPointPen(AbstractPointPen):
"""
Point pen that converts all "line" segments into
curve segments containing two off curve points.
"""
def __init__(self):
self.contours = []
self.components = []
self.anchors = []
self._points = []
def _flushContour(self):
points = self._points
if len(points) == 1:
segmentType, pt, smooth, name = points[0]
self.anchors.append((pt, name))
else:
self.contours.append([])
prevOnCurve = None
offCurves = []
# deal with the first point
segmentType, pt, smooth, name = points[0]
# if it is an offcurve, add it to the offcurve list
if segmentType is None:
offCurves.append((segmentType, pt, smooth, name))
# if it is a line, change the type to curve and add it to the contour
# create offcurves corresponding with the last oncurve and
# this point and add them to the points list
elif segmentType == "line":
prevOnCurve = pt
self.contours[-1].append(("curve", pt, False, name))
lastPoint = points[-1][1]
points.append((None, lastPoint, False, None))
points.append((None, pt, False, None))
# a move, curve or qcurve. simple append the data.
else:
self.contours[-1].append((segmentType, pt, smooth, name))
prevOnCurve = pt
# now go through the rest of the points
for segmentType, pt, smooth, name in points[1:]:
# store the off curves
if segmentType is None:
offCurves.append((segmentType, pt, smooth, name))
continue
# make off curve corresponding the the previous
# on curve an dthis point
if segmentType == "line":
segmentType = "curve"
offCurves.append((None, prevOnCurve, False, None))
offCurves.append((None, pt, False, None))
# add the offcurves to the contour
for offCurve in offCurves:
self.contours[-1].append(offCurve)
# add the oncurve to the contour
self.contours[-1].append((segmentType, pt, smooth, name))
# reset the stored data
prevOnCurve = pt
offCurves = []
# catch offcurves that belong to the first
if len(offCurves) != 0:
self.contours[-1].extend(offCurves)
def beginPath(self):
self._points = []
def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
self._points.append((segmentType, pt, smooth, name))
def endPath(self):
self._flushContour()
def addComponent(self, baseGlyphName, transformation):
self.components.append((baseGlyphName, transformation))
def getData(self):
return {
'contours':list(self.contours),
'components':list(self.components),
'anchors':list(self.anchors)
}
class CurveSegmentFilterPointPen(AbstractPointPen):
"""
Point pen that turns curve segments that contain
unnecessary anchor points into line segments.
"""
# XXX it would be great if this also checked to see if the
# off curves are on the segment and therefre unneeded
def __init__(self, anotherPointPen):
self._pen = anotherPointPen
self._points = []
def _flushContour(self):
points = self._points
# an anchor
if len(points) == 1:
pt, segmentType, smooth, name = points[0]
self._pen.addPoint(pt, segmentType, smooth, name)
else:
prevOnCurve = None
offCurves = []
pointsToDraw = []
# deal with the first point
pt, segmentType, smooth, name = points[0]
# if it is an offcurve, add it to the offcurve list
if segmentType is None:
offCurves.append((pt, segmentType, smooth, name))
else:
# potential redundancy
if segmentType == "curve":
# gather preceding off curves
testOffCurves = []
lastPoint = None
for i in xrange(len(points)):
i = -i - 1
testPoint = points[i]
testSegmentType = testPoint[1]
if testSegmentType is not None:
lastPoint = testPoint[0]
break
testOffCurves.append(testPoint[0])
# if two offcurves exist we can test for redundancy
if len(testOffCurves) == 2:
if testOffCurves[1] == lastPoint and testOffCurves[0] == pt:
segmentType = "line"
# remove the last two points
points = points[:-2]
# add the point to the contour
pointsToDraw.append((pt, segmentType, smooth, name))
prevOnCurve = pt
for pt, segmentType, smooth, name in points[1:]:
# store offcurves
if segmentType is None:
offCurves.append((pt, segmentType, smooth, name))
continue
# curves are a potential redundancy
elif segmentType == "curve":
if len(offCurves) == 2:
# test for redundancy
if offCurves[0][0] == prevOnCurve and offCurves[1][0] == pt:
offCurves = []
segmentType = "line"
# add all offcurves
for offCurve in offCurves:
pointsToDraw.append(offCurve)
# add the on curve
pointsToDraw.append((pt, segmentType, smooth, name))
# reset the stored data
prevOnCurve = pt
offCurves = []
# catch any remaining offcurves
if len(offCurves) != 0:
for offCurve in offCurves:
pointsToDraw.append(offCurve)
# draw to the pen
for pt, segmentType, smooth, name in pointsToDraw:
self._pen.addPoint(pt, segmentType, smooth, name)
def beginPath(self):
self._points = []
self._pen.beginPath()
def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs):
self._points.append((pt, segmentType, smooth, name))
def endPath(self):
self._flushContour()
self._pen.endPath()
def addComponent(self, baseGlyphName, transformation):
self._pen.addComponent(baseGlyphName, transformation)