1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
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)
|