-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSVG.html
More file actions
206 lines (181 loc) · 8.38 KB
/
Copy pathSVG.html
File metadata and controls
206 lines (181 loc) · 8.38 KB
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title></title>
</head><body>
<div class="article">
<h2>Description</h2>
<p>The SVG library gives control over vector work imported into PlotDevice. Rectangles, circles
and paths from an SVG file are imported as native PlotDevice paths, so their individual points and
colors can be manipulated (see the tutorial on <a href="../tut/Bezier_Paths.html">Paths</a>).</p>
<p>’SVG’ means Scalable Vector Graphics and is an XML format. You can save SVG files from
<a href="http://www.inkscape.org/">Inkscape</a> and Illustrator. Hand-draw your shapes there
and then manipulate them further in PlotDevice.</p>
<p>The SVG library has been tested for the following Illustrator functionalities: rectangles,
ellipses, polygons, lines, curves constructed with the pen-tool, fill colors, stroke colors,
stroke widths and transparency. Complicated things like gradient fills are ignored.</p>
<h2>Download</h2>
<table border="0">
<tbody>
<tr>
<td><a href="http://plotdevice.io/extras/svg.zip"><img alt="download" height="20" src="../etc/lib/download.gif" width="20"/></a>
</td><td><a href="http://plotdevice.io/extras/svg.zip">svg.zip</a> (400KB)<br/>
<i>Last updated for NodeBox 1.9.4.5<br/></i><i>Licensed under GPL</i><br/>
<i>Author: Tom De Smedt</i><br/>
</td></tr></tbody></table>
<h2>Documentation</h2>
<ul>
<li><a href="#library">How to get the library up and running</a>
</li><li><a href="#export">Preparing SVG files</a>
</li><li><a href="#parse">Importing SVG files</a>
</li><li><a href="#furry">A simple path filter</a>
</li><li><a href="#group_transform">Transforming a group of paths</a><br/>
</li></ul>
<p> </p>
<hr/>
<h2><a id="library" name="library" title="library"></a>How to get the library up and
running</h2>
<p>Put the <i>svg</i> library folder in the same folder as your script so PlotDevice can find the
library. You can also put it in ~/Library/Application Support/PlotDevice/.</p>
<pre>svg = ximport("svg")
</pre>
<hr/>
<h2><a id="export" name="export" title="export"></a>Preparing SVG files</h2>
<p>To export files as SVG from Adobe Illustrator do the following:</p>
<ul>
<li>Choose File > Save As...
</li><li>In the file dialog, select ‘SVG (svg)’ (not ‘SVG Compressed’ - we can’t read compressed
files)
</li><li>In the next window, choose ‘SVG Tiny 1.2’ as the SVG Profile.<br/>
The regular SVG format saves all swatches and patterns, which is useless outside of
Illustrator. Leave the rest of the settings as-is.
</li></ul>
<p><span class="media"><img height="414" src="../etc/lib/svg-export.jpg" width="500"/></span></p>
<hr/>
<h2><a id="parse" name="parse" title="parse"></a>Importing SVG files</h2>
<pre>parse(str, cached=False)
</pre>
<p>The <i>parse()</i> command reads SVG source and returns a list of <a href="../tut/Bezier_Paths.html">paths</a> that are drawable with <a href="../ref/Drawing.html#drawpath()">drawpath()</a>. The command has an optional <i>cached</i>
parameter. When set to <i>True</i>, the SVG source is analyzed only once and the parsed paths
stored in memory so they load faster.</p>
<p>Each returned path in the list has the following properties:</p>
<ul>
<li><i>path</i>.closed: is set to True when the path is closed
</li><li><i>path</i>.fill: the fill color of the path in the SVG file
</li><li><i>path</i>.stroke: the stroke color of the path in the SVG file
</li><li><i>path</i>.strokewidth: the stroke width of the path in the SVG file.<br/>
</li></ul>
<p>These can be used to copy color information from the original vector drawing. Read the
<a href="../tut/Bezier_Paths.html">tutorial on paths</a> to see what you can do with the points of a
path.</p>
<p>For example, here’s one of Ludivine Lechat’s Illustrator drawings. We can import the paths
into PlotDevice. Those that have a fill color will retain their original fill.</p>
<p> </p>
<p><span class="media"><img height="668" src="../etc/lib/svg-illustrator.jpg" width="634"/></span></p>
<pre>data = open("flower.svg").read()
paths = svg.parse(data)
for path in paths:
try:
fill(path.fill)
except:
fill(random(), 0, 0)
drawpath(path)
</pre>
<p><span class="media">In the following example we override the colors in the original
document. We only fill paths that are closed, in shades of the same color:</span></p>
<p> </p>
<p><span class="media"><img height="647" src="../etc/lib/svg-plotdevice.jpg" width="739"/></span></p>
<p> </p>
<hr/>
<h2><a id="furry" name="furry" title="furry"></a>A simple path filter</h2>
<p>Since all of the imported artwork are standard PlotDevice paths, I can also manipulate them
with <a href="../tut/Bezier_Paths.html#Path_Mathematics">path mathematics</a>, transform them like the
<a href="../tut/LetterKnitter.html">LetterKnitter</a>. After some fumbling with paths and a
nice gradient background, here is a hairy version of our flower. The bottom paths are darker to
create a sense of depth.</p>
<p> </p>
<p><span class="media"><img height="647" src="../etc/lib/svg-pathfilter.jpg" width="739"/></span></p>
<p>Below is some example code used to alter the path.<br/>
You can see it in use in the <a href="http://nodebox.net/code/index.php/Superfolia">Superfolia</a> project in the gallery.</p>
<pre>def draw_furry(path):
prev = None
autoclosepath(False)
nofill()
for pt in path.points(100):
stroke(1, 0.5)
strokewidth(random(0.5))
if prev != None:
beginpath(prev.x, prev.y)
curveto(
pt.ctrl1.x - random(30),
pt.ctrl1.y,
pt.ctrl2.x,
pt.ctrl2.y + random(30),
pt.x,
pt.y
)
curveto(
pt.ctrl1.x + random(10),
pt.ctrl1.y,
pt.ctrl2.x,
pt.ctrl2.y - random(10),
pt.x + random(-20, 20),
pt.y + random(-20, 20)
)
endpath()
prev = pt
</pre>
<p>More path filters can be found <a href="../tut/Path_Filters.html">here</a>.</p>
<p> </p>
<hr size="2" width="100%"/>
<h2><a id="group_transform" name="group_transform" title="group_transform"></a>Transforming a
group of paths</h2>
<p>When you import an SVG file a list of paths is returned. All of these paths may make up a
single drawing and you may encounter difficulties when <b>rotating and scaling the drawing a
whole</b>. Below are two commands to help you along.</p>
<p>The first command, <i>bounds()</i>, calculates the position and total size of a list of
paths. The second command, <i>drawpaths()</i>, draws all of the paths rotating and scaling from
the given origin. By default origin is (0.5, 0.5) which means the center of the group.</p>
<pre>def bounds(paths=[]):
""" Returns (x, y), (width, height) bounds for a group of paths.
"""
if len(paths) == 0:
return (0,0), (0,0)
l = t = float("inf")
r = b = float("-inf")
for path in paths:
(x, y), (w, h) = path.bounds
l = min(l, x)
t = min(t, y)
r = max(r, x+w)
b = max(b, y+h)
return (l, t), (r-l, b-t)
</pre>
<pre>def drawpaths(paths=[], x=0, y=0, rotate=0, scale=1.0, origin=(0.5,0.5)):
""" Draws a group of paths that rotate and scale from the given origin.
"""
_ctx.transform(CORNER)
_ctx.push()
_ctx.translate(x, y)
_ctx.rotate(rotate)
_ctx.scale(scale)
(x, y), (w, h) = bounds(paths)
_ctx.translate((-x-w)*origin[0], (-y-h)*origin[1])
for path in paths:
#_ctx.fill(path.fill)
#_ctx.stroke(path.stroke)
#_ctx.strokewidth(path.strokewidth)
# Use copies of the paths that adhere to the transformations.
_ctx.drawpath(path.copy())
_ctx.pop()
</pre>
<hr/>
<p>Finally, remember that when you want to supply one path multiple times to drawpath(), each
with its own translation and rotation, you need to <b>feed copies of the path to drawpath</b>:</p>
<pre>path = svg.parse(data)[0]
for i in range(5):
rotate(i*10)
drawpath(path.copy())
</pre>
<p> </p>
</div>
</body></html>