| from __future__ import print_function, division, absolute_import |
| from fontTools.misc.py23 import * |
| 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) |