You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.3 KiB

from fontTools.pens.basePen import BasePen
def pointToString(pt):
return " ".join([str(i) for i in pt])
class SVGPathPen(BasePen):
def __init__(self, glyphSet):
BasePen.__init__(self, glyphSet)
self._commands = []
self._lastCommand = None
self._lastX = None
self._lastY = None
def _handleAnchor(self):
"""
>>> pen = SVGPathPen(None)
>>> pen.moveTo((0, 0))
>>> pen.moveTo((10, 10))
>>> pen._commands
['M10 10']
"""
if self._lastCommand == "M":
self._commands.pop(-1)
def _moveTo(self, pt):
"""
>>> pen = SVGPathPen(None)
>>> pen.moveTo((0, 0))
>>> pen._commands
['M0 0']
>>> pen = SVGPathPen(None)
>>> pen.moveTo((10, 0))
>>> pen._commands
['M10 0']
>>> pen = SVGPathPen(None)
>>> pen.moveTo((0, 10))
>>> pen._commands
['M0 10']
"""
self._handleAnchor()
t = "M%s" % (pointToString(pt))
self._commands.append(t)
self._lastCommand = "M"
self._lastX, self._lastY = pt
def _lineTo(self, pt):
"""
# duplicate point
>>> pen = SVGPathPen(None)
>>> pen.moveTo((10, 10))
>>> pen.lineTo((10, 10))
>>> pen._commands
['M10 10']
# vertical line
>>> pen = SVGPathPen(None)
>>> pen.moveTo((10, 10))
>>> pen.lineTo((10, 0))
>>> pen._commands
['M10 10', 'V0']
# horizontal line
>>> pen = SVGPathPen(None)
>>> pen.moveTo((10, 10))
>>> pen.lineTo((0, 10))
>>> pen._commands
['M10 10', 'H0']
# basic
>>> pen = SVGPathPen(None)
>>> pen.lineTo((70, 80))
>>> pen._commands
['L70 80']
# basic following a moveto
>>> pen = SVGPathPen(None)
>>> pen.moveTo((0, 0))
>>> pen.lineTo((10, 10))
>>> pen._commands
['M0 0', ' 10 10']
"""
x, y = pt
# duplicate point
if x == self._lastX and y == self._lastY:
return
# vertical line
elif x == self._lastX:
cmd = "V"
pts = str(y)
# horizontal line
elif y == self._lastY:
cmd = "H"
pts = str(x)
# previous was a moveto
elif self._lastCommand == "M":
cmd = None
pts = " " + pointToString(pt)
# basic
else:
cmd = "L"
pts = pointToString(pt)
# write the string
t = ""
if cmd:
t += cmd
self._lastCommand = cmd
t += pts
self._commands.append(t)
# store for future reference
self._lastX, self._lastY = pt
def _curveToOne(self, pt1, pt2, pt3):
"""
>>> pen = SVGPathPen(None)
>>> pen.curveTo((10, 20), (30, 40), (50, 60))
>>> pen._commands
['C10 20 30 40 50 60']
"""
t = "C"
t += pointToString(pt1) + " "
t += pointToString(pt2) + " "
t += pointToString(pt3)
self._commands.append(t)
self._lastCommand = "C"
self._lastX, self._lastY = pt3
def _qCurveToOne(self, pt1, pt2):
"""
>>> pen = SVGPathPen(None)
>>> pen.qCurveTo((10, 20), (30, 40))
>>> pen._commands
['Q10 20 30 40']
"""
assert pt2 is not None
t = "Q"
t += pointToString(pt1) + " "
t += pointToString(pt2)
self._commands.append(t)
self._lastCommand = "Q"
self._lastX, self._lastY = pt2
def _closePath(self):
"""
>>> pen = SVGPathPen(None)
>>> pen.closePath()
>>> pen._commands
['Z']
"""
self._commands.append("Z")
self._lastCommand = "Z"
self._lastX = self._lastY = None
def _endPath(self):
"""
>>> pen = SVGPathPen(None)
>>> pen.endPath()
>>> pen._commands
['Z']
"""
self._closePath()
self._lastCommand = None
self._lastX = self._lastY = None
def getCommands(self):
return "".join(self._commands)
if __name__ == "__main__":
import sys
import doctest
sys.exit(doctest.testmod().failed)