- added support for quadratic contours that have NO on-curve points.

- more doco and comments.


git-svn-id: svn://svn.code.sf.net/p/fonttools/code/trunk@438 4cde692c-a291-49d1-8350-778aa11640f8
This commit is contained in:
jvr 2003-08-28 19:30:46 +00:00
parent 53d7523c1c
commit 934fe5fb8f

View File

@ -37,7 +37,12 @@ class AbstractPen:
raise NotImplementedError raise NotImplementedError
def curveTo(self, *points): def curveTo(self, *points):
"""Draw a curve with an *arbitrary* number of control points. """Draw a cubic bezier with an arbitrary number of control points.
The last point specified is on-curve, all others are off-curve
(control) points. If the number of control points is > 2, the
segment is split into multiple bezier segments. This works
like this:
Let n be the number of control points (which is the number of Let n be the number of control points (which is the number of
arguments to this call minus 1). If n==2, a plain vanilla cubic arguments to this call minus 1). If n==2, a plain vanilla cubic
@ -55,13 +60,16 @@ class AbstractPen:
def qCurveTo(self, *points): def qCurveTo(self, *points):
"""Draw a whole string of quadratic curve segments. """Draw a whole string of quadratic curve segments.
This implements TrueType-style curves, breaking up curves using The last point specified is on-curve, all others are off-curve
implied points: between each two consequtive off-curve points, points.
there is one 'implied' point exactly in the middle between them.
'points' is a sequence of at least two points. Just like with This method implements TrueType-style curves, breaking up curves
any segment drawing function, the first and the last point are using 'implied points': between each two consequtive off-curve points,
treated as onCurve, the rest as offCurve. there is one implied point exactly in the middle between them.
The last argument (normally the on-curve point) may be None.
This is to support contours that have NO on-curve points (a rarely
seen feature of TrueType outlines).
""" """
raise NotImplementedError raise NotImplementedError
@ -70,7 +78,11 @@ class AbstractPen:
pass pass
def addComponent(self, glyphName, transformation): def addComponent(self, glyphName, transformation):
"""Add a sub glyph.""" """Add a sub glyph. The 'transformation' argument must be a 6-tuple
containing an affine transformation, or a Transform object from the
fontTools.misc.transform module. More precisely: it should be a
sequence containing 6 numbers.
"""
raise NotImplementedError raise NotImplementedError
@ -186,6 +198,19 @@ class BasePen(AbstractPen):
def qCurveTo(self, *points): def qCurveTo(self, *points):
n = len(points) - 1 # 'n' is the number of control points n = len(points) - 1 # 'n' is the number of control points
assert n >= 0 assert n >= 0
if points[-1] is None:
# Special case for TrueType quadratics: it is possible to
# define a contour with NO on-curve points. BasePen supports
# this by allowing the final argument (the expected on-curve
# point) to be None. We simulate the feature by making the implied
# on-curve point between the last and the first off-curve points
# explicit.
x, y = points[-2] # last off-curve point
nx, ny = points[0] # first off-curve point
impliedStartPoint = (0.5 * (x + nx), 0.5 * (y + ny))
self.__currentPoint = impliedStartPoint
self._moveTo(impliedStartPoint)
points = points[:-1] + (impliedStartPoint,)
if n > 0: if n > 0:
# Split the string of points into discrete quadratic curve # Split the string of points into discrete quadratic curve
# segments. Between any two consecutive off-curve points # segments. Between any two consecutive off-curve points
@ -210,7 +235,7 @@ class _TestPen(BasePen):
def _lineTo(self, pt): def _lineTo(self, pt):
print "%s %s lineto" % (pt[0], pt[1]) print "%s %s lineto" % (pt[0], pt[1])
def _curveToOne(self, bcp1, bcp2, pt): def _curveToOne(self, bcp1, bcp2, pt):
print "%s %s %s %s %s %s curveto" % (bcp1[0], bcp1[1], print "%s %s %s %s %s %s curveto" % (bcp1[0], bcp1[1],
bcp2[0], bcp2[1], pt[0], pt[1]) bcp2[0], bcp2[1], pt[0], pt[1])
def _closePath(self): def _closePath(self):
print "closepath" print "closepath"
@ -224,7 +249,6 @@ if __name__ == "__main__":
pen.closePath() pen.closePath()
pen = _TestPen(None) pen = _TestPen(None)
pen.moveTo((0, 0)) # testing the "no on-curve point" scenario
pen.lineTo((0, 100)) pen.qCurveTo((0, 0), (0, 100), (100, 100), (100, 0), None)
pen.curveTo((50, 75), (60, 50), (50, 25), (0, 0))
pen.closePath() pen.closePath()