3 <title>Vecto - Simple Vector Drawing with Common Lisp
</title>
4 <style type=
"text/css">
5 a
, a:visited
{ text-decoration: none
}
6 a
[href
]:hover
{ text-decoration: underline
}
7 pre
{ background: #DDD; padding: 0.25em }
8 p
.download
{ color: red
}
9 .transparent { background-image: url
(background.gif) }
15 <h2>Vecto - Simple Vector Drawing with Common Lisp
</h2>
17 <blockquote class='abstract'
>
20 <p>Vecto is a simplified interface to the
21 powerful
<a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
22 vector rasterization library. It presents a function-oriented
23 interface similar to
<a href=
"http://www.cliki.net/CL-PDF">CL-PDF
</a>,
24 but the results can be saved to a PNG instead of a PDF file. Since
25 Vecto and all supporting libraries are written completely in Common
26 Lisp, without depending on external non-Lisp libraries, it should work
27 in any Common Lisp environment. Vecto is available under a BSD-like
30 The current version is
1.4.3, released on August
26,
2009.
33 by
<a href=
"http://wigflip.com/easystreet/">Easystreet
</a>
34 and
<a href='http://www.xach.com/moviecharts/'
>Movie Charts
</a>.
36 <p>The canonical location for Vecto
37 is
<a href=
"http://www.xach.com/lisp/vecto/">http://www.xach.com/lisp/vecto/
</a>.
39 <p class='download'
>Download shortcut:
</p>
41 <p><a href=
"http://www.xach.com/lisp/vecto.tgz">http://www.xach.com/lisp/vecto.tgz
</a>
48 <li> <a href='#sect-overview-and-limitations'
>Overview and Limitations
</a>
49 <li> <a href='#sect-examples'
>Examples
</a>
50 <li> <a href='#sect-dictionary'
>Dictionary
</a>
53 <li> <a href='#sect-canvases'
>Canvases
</a>
55 <li> <a href='#with-canvas'
><tt>with-canvas
</tt></a>
56 <li> <a href='#clear-canvas'
><tt>clear-canvas
</tt></a>
57 <li> <a href='#save-png'
><tt>save-png
</tt></a>
58 <li> <a href='#save-png-stream'
><tt>save-png-stream
</tt></a>
61 <li> <a href='#sect-graphics-state'
>Graphics State
</a>
63 <li> <a href='#with-graphics-state'
><tt>with-graphics-state
</tt></a>
64 <li> <a href='#set-rgba-fill'
><tt>set-rgba-fill
</tt></a>
65 <li> <a href='#set-rgba-fill'
><tt>set-rgb-fill
</tt></a>
66 <li> <a href='#set-gradient-fill'
><tt>set-gradient-fill
</tt></a>
67 <li> <a href='#set-rgba-stroke'
><tt>set-rgba-stroke
</tt></a>
68 <li> <a href='#set-rgba-stroke'
><tt>set-rgb-stroke
</tt></a>
69 <li> <a href='#set-line-cap'
><tt>set-line-cap
</tt></a>
70 <li> <a href='#set-line-join'
><tt>set-line-join
</tt></a>
71 <li> <a href='#set-line-width'
><tt>set-line-width
</tt></a>
72 <li> <a href='#set-dash-pattern'
><tt>set-dash-pattern
</tt></a>
73 <li> <a href='#translate'
><tt>translate
</tt></a>
74 <li> <a href='#rotate'
><tt>rotate
</tt></a>
75 <li> <a href='#scale'
><tt>scale
</tt></a>
76 <li> <a href='#skew'
><tt>skew
</tt></a>
77 <li> <a href='#clip-path'
><tt>clip-path
</tt></a>
78 <li> <a href='#even-odd-clip-path'
><tt>even-odd-clip-path
</tt></a>
81 <li> <a href='#sect-paths'
>Paths
</a>
83 <li> <a href='#move-to'
><tt>move-to
</tt></a>
84 <li> <a href='#line-to'
><tt>line-to
</tt></a>
85 <li> <a href='#curve-to'
><tt>curve-to
</tt></a>
86 <li> <a href='#quadratic-to'
><tt>quadratic-to
</tt></a>
87 <li> <a href='#arc'
><tt>arc
</tt></a>
88 <li> <a href='#arcn'
><tt>arcn
</tt></a>
89 <li> <a href='#close-subpath'
><tt>close-subpath
</tt></a>
90 <li> <a href='#stroke-to-paths'
><tt>stroke-to-paths
</tt></a>
91 <li> <a href='#rectangle'
><tt>rectangle
</tt></a>
92 <li> <a href='#rounded-rectangle'
><tt>rounded-rectangle
</tt></a>
93 <li> <a href='#centered-ellipse-path'
><tt>centered-ellipse-path
</tt></a>
94 <li> <a href='#centered-circle-path'
><tt>centered-circle-path
</tt></a>
97 <li> <a href='#sect-painting'
>Painting
</a>
99 <li> <a href='#fill-path'
><tt>fill-path
</tt></a>
100 <li> <a href='#even-odd-fill'
><tt>even-odd-fill
</tt></a>
101 <li> <a href='#stroke'
><tt>stroke
</tt></a>
102 <li> <a href='#fill-and-stroke'
><tt>fill-and-stroke
</tt></a>
103 <li> <a href='#even-odd-fill-and-stroke'
><tt>even-odd-fill-and-stroke
</tt></a>
104 <li> <a href='#end-path-no-op'
><tt>end-path-no-op
</tt></a>
107 <li> <a href='#sect-text'
>Text
</a>
109 <li> <a href='#get-font'
><tt>get-font
</tt></a>
110 <li> <a href='#set-font'
><tt>set-font
</tt></a>
111 <li> <a href='#set-character-spacing'
><tt>set-character-spacing
</tt></a>
112 <li> <a href='#*default-character-spacing*'
><tt>*default-character-spacing*
</tt></a>
113 <li> <a href='#draw-string'
><tt>draw-string
</tt></a>
114 <li> <a href='#string-paths'
><tt>string-paths
</tt></a>
115 <li> <a href='#draw-centered-string'
><tt>draw-centered-string
</tt></a>
116 <li> <a href='#centered-string-paths'
><tt>centered-string-paths
</tt></a>
117 <li> <a href='#string-bounding-box'
><tt>string-bounding-box
</tt></a>
120 <li> <a href='#sect-miscellaneous'
>Miscellaneous
</a>
122 <li> <a href='#const-kappa'
><tt>+kappa+
</tt></a>
127 <li> <a href='#sect-references'
>References
</a>
128 <li> <a href='#sect-acknowledgements'
>Acknowledgements
</a>
129 <li> <a href='#sect-feedback'
>Feedback
</a>
133 <a name='sect-overview-and-limitations'
><h3>Overview and Limitations
</h3></a>
135 <p>Vecto is a library that provides a simple interface to the
136 the
<a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
137 vector drawing library. It supports drawing on a canvas and saving the
138 results to a PNG file.
140 <p>Vecto depends on the following libraries:
143 <li> <a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
144 <li> <a href=
"http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF
</a>
145 <li> <a href=
"http://www.xach.com/lisp/salza2/">Salza2
</a>
146 <li> <a href=
"http://www.xach.com/lisp/zpng/">ZPNG
</a>
149 <p>The easiest way to install Vecto and all its dependencies is
150 with
<a href=
"http://www.cliki.net/asdf-install">ASDF-Install
</a>.
152 <p>Vecto's function interface is similar to the
153 PDF vector description and painting interface: you create images by
154 describing vector paths, then using stroke or fill operations to paint
157 <p>Vecto's color system uses red, green, blue, and alpha color
158 components for drawing. The results can be be saved to a PNG with an
161 <p>Vecto's coordinate system starts at the lower-left corner of the
162 image, and increases rightwards along the X axis and upwards along the
165 <p>All measurements are in pixels.
167 <p>PDF is a feature-rich system. Vecto supports a small subset of
168 PDF-style operations. In particular, it does not support:
172 <li> pattern or functional fill
173 <li> complex layout of text
174 <li> PostScript fonts
175 <li> non-RGB color spaces
178 <p>Other limitations:
181 <li> No output formats other than
8-bit, truecolor-alpha PNGs
182 <li> No access to underlying pixel data
185 <p>Related libraries:
188 <li> <a href=
"http://common-lisp.net/project/imago/">Imago
</a>
190 <li> <a href=
"http://cyrusharmon.org/projects?project=ch-image">ch-image
</a>
192 <li> <a href=
"http://ygingras.net/poly-pen">Poly-pen
</a>
196 <a name='sect-examples'
><h3>Examples
</h3></a>
198 <p>All examples are available in
<tt>doc/examples.lisp
</tt> in the Vecto
199 distribution. That file starts with:
202 (defpackage #:vecto-examples
205 (in-package #:vecto-examples)
210 <img border=
0 align=right src='lambda-example.png'
211 >(defun radiant-lambda (file)
212 (
<a href='#with-canvas'
>with-canvas
</a> (:width
90 :height
90)
213 (let ((font (
<a href='#get-font'
>get-font
</a> "times.ttf"))
215 (
<a href='#set-font'
>set-font
</a> font
40)
216 (
<a href='#translate'
>translate
</a> 45 45)
217 (
<a href='#draw-centered-string'
>draw-centered-string
</a> 0 -
10 #(#x3BB))
218 (
<a href='#set-rgba-stroke'
>set-rgb-stroke
</a> 1 0 0)
219 (
<a href='#centered-circle-path'
>centered-circle-path
</a> 0 0 35)
220 (
<a href='#stroke'
>stroke
</a>)
221 (
<a href='#set-rgba-stroke'
>set-rgba-stroke
</a> 0 0 1.0 0.5)
222 (
<a href='#set-line-width'
>set-line-width
</a> 4)
224 (
<a href='#with-graphics-state'
>with-graphics-state
</a>
225 (
<a href='#rotate'
>rotate
</a> (* i step))
226 (
<a href='#move-to'
>move-to
</a> 30 0)
227 (
<a href='#line-to'
>line-to
</a> 40 0)
229 (
<a href='#save-png'
>save-png
</a> file))))
233 <img align=right src='feedlike-icon.png'
234 >(defun feedlike-icon (file)
235 (with-canvas (:width
100 :height
100)
236 (set-rgb-fill
1.0 0.65 0.3)
237 (
<a href='#rounded-rectangle'
>rounded-rectangle
</a> 0 0 100 100 10 10)
238 (
<a href='#fill-path'
>fill-path
</a>)
239 (set-rgb-fill
1.0 1.0 1.0)
240 (centered-circle-path
20 20 10)
242 (flet ((quarter-circle (x y radius)
243 (move-to (+ x radius) y)
244 (
<a href='#arc'
>arc
</a> x y radius
0 (/ pi
2))))
245 (set-rgb-stroke
1.0 1.0 1.0)
247 (quarter-circle
20 20 30)
249 (quarter-circle
20 20 60)
251 (rounded-rectangle
5 5 90 90 7 7)
252 (
<a href='#set-gradient-fill'
>set-gradient-fill
</a> 50 90
257 (set-rgba-stroke
1.0 1.0 1.0 0.1)
258 (
<a href='#fill-and-stroke'
>fill-and-stroke
</a>)
262 <pre><div style='float: right' class='transparent'
><img src='star-clipping.png'
263 ></div>(defun star-clipping (file)
264 (with-canvas (:width
200 :height
200)
267 (step (*
2 (/ (* pi
2)
5))))
268 (translate size size)
271 (setf angle (+ angle step))
272 (line-to (* (sin angle) size)
273 (* (cos angle) size)))
274 (
<a href='#even-odd-clip-path'
><tt>even-odd-clip-path
</tt></a>)
275 (
<a href='#end-path-no-op'
><tt>end-path-no-op
</tt></a>)
276 (flet ((circle (distance)
277 (
<a href='#set-rgba-fill'
><tt>set-rgba-fill
</tt></a> distance
0 0
279 (centered-circle-path
0 0 (* size distance))
281 (loop for i downfrom
1.0 by
0.05
287 <a name='sect-dictionary'
><h3>Dictionary
</h3></a>
289 <p>The following symbols are exported from the
<tt>VECTO
</tt> package.
291 <a name='sect-canvases'
><h4>Canvases
</h4></a>
293 <p><a name='with-canvas'
>[Macro]
</a><br>
294 <b>with-canvas
</b> (
<tt>&key
</tt> <i>width
</i> <i>height
</i>)
295 <tt>&body
</tt> <i>body
</i>
298 Evaluates
<i>body
</i> with a canvas established with the specified
299 dimensions as the target for drawing commands. The canvas is initially
300 completely clear (all pixels have
0 alpha).
304 <p><a name='clear-canvas'
>[Function]
</a><br>
305 <b>clear-canvas
</b> =
> |
308 Completely fills the canvas with the current fill color. Any marks on
309 the canvas are cleared.
313 <p><a name='save-png'
>[Function]
</a><br>
314 <b>save-png
</b> <i>file
</i> =
> <i>truename
</i>
317 Writes the contents of the canvas as the PNG
<i>file
</i>, and returns
318 the truename of
<i>file
</i>.
322 <p><a name='save-png-stream'
>[Function]
</a><br>
323 <b>save-png-stream
</b> <i>stream
</i> =
> |
326 Writes the contents of the canvas as a PNG to
<i>stream
</i>, which
327 must accept
<tt>(unsigned-byte
8)
</tt> data.
331 <a name='sect-graphics-state'
><h4>Graphics State
</h4></a>
333 <p>The graphics state stores several parameters used for graphic
336 <p><a name='with-graphics-state'
>[Macro]
</a><br>
337 <b>with-graphics-state
</b> <tt>&body
</tt> <i>body
</i>
340 Evaluates the forms of
<i>body
</i> with a copy of the current graphics
341 state. Any modifications to the state are undone at the end of the
346 <p><a name='set-rgba-fill'
>[Functions]
</a><br>
347 <b>set-rgba-fill
</b> <i>r
</i> <i>g
</i> <i>b
</i> <i>alpha
</i> =
> |
<br>
348 <b>set-rgb-fill
</b> <i>r
</i> <i>g
</i> <i>b
</i> =
> |
351 Sets the fill color.
<i>r
</i>,
<i>g
</i>,
<i>b
</i>, and
<i>alpha
</i>
352 should be in the range of
0.0 to
1.0.
354 <p><tt>set-rgb-fill
</tt> is the same as
<tt>set-rgba-fill
</tt> with an
355 implicit alpha value of
1.0.
357 <p>The fill color is used
359 href='#clear-canvas'
><tt>CLEAR-CANVAS
</tt></a>,
<a
360 href='#fill-path'
><tt>FILL-PATH
</tt></a>,
<a
361 href='#even-odd-fill'
><tt>EVEN-ODD-FILL
</tt></a>,
<a
362 href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
<a
363 href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>,
364 and
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a>.
368 <p><a name='set-gradient-fill'
>[Function]
</a><br>
369 <b>set-gradient-fill
</b>
370 <i>x0
</i> <i>y0
</i> <i>r0
</i> <i>g0
</i> <i>b0
</i> <i>a0
</i>
371 <i>x1
</i> <i>y1
</i> <i>r1
</i> <i>g1
</i> <i>b1
</i> <i>a1
</i>
372 <tt>&key
</tt> (
<i>extend-start
</i> <tt>t
</tt>)
373 (
<i>extend-end
</i> <tt>t
</tt>)
374 (
<i>domain-function
</i> <tt>'linear-domain
</tt>)
377 Set the fill color source to an axial gradient. The start point
378 is
<i>x0,y0
</i> and the start color is
<i>r0,g0,b0,a0
</i>. The end
379 point is
<i>x1, y1
</i> and the end color is
<i>r1,g1,b1,a1
</i>.
381 <p>Two domain functions are available:
385 <li> <tt>LINEAR-DOMAIN
</tt>, the default, makes a transition from the
386 start color to the end color along the axis between the start and end
389 <li> <tt>BILINEAR-DOMAIN
</tt> makes a transition from the start color
390 to the end color from the start point to the midpoint, then back to
391 the start color from the midpoint to the end point
394 <pre><img style='float: right' class='transparent'
395 src='linear-gradient.png'
>(defun gradient-example (file)
396 (with-canvas (:width
200 :height
50)
397 (set-gradient-fill
25 0
401 (rectangle
0 0 200 50)
406 <pre><img style='float: right' class='transparent'
407 src='bilinear-gradient.png'
>(defun gradient-bilinear-example (file)
408 (with-canvas (:width
200 :height
50)
409 (set-gradient-fill
25 0
413 :domain-function 'bilinear-domain)
414 (rectangle
0 0 200 50)
423 <p><a name='set-rgba-stroke'
>[Functions]
</a><br>
424 <b>set-rgba-stroke
</b> <i>r
</i> <i>g
</i> <i>b
</i> <i>alpha
</i> =
> |
<br>
425 <b>set-rgb-stroke
</b> <i>r
</i> <i>g
</i> <i>b
</i> =
> |
428 Sets the stroke color.
<i>r
</i>,
<i>g
</i>,
<i>b
</i>, and
<i>alpha
</i>
429 should be in the range of
0.0 to
1.0.
431 <p><tt>set-rgb-stroke
</tt> is the same as
<tt>set-rgba-stroke
</tt>
432 with an implicit alpha value of
1.0.
434 <p>The stroke color is used for
<a href='#stroke'
><tt>STROKE
</tt></a>,
435 <a href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
436 and
<a href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>.
440 <p><a name='set-line-cap'
>[Function]
</a><br>
441 <b>set-line-cap
</b> <i>style
</i> =
> |
444 Sets the line cap style to
<i>style
</i>, which must be one
445 of
<tt>:BUTT
</tt>,
<tt>:SQUARE
</tt>, or
<tt>:ROUND
</tt>. The initial
446 value is
<tt>:BUTT
</tt>.
448 <p><table cellspacing=
5 id=
"line-cap">
450 <td align=center
><img src=
"cap-style-butt.png"></td>
451 <td align=center
><img src=
"cap-style-square.png"></td>
452 <td align=center
><img src=
"cap-style-round.png"></td>
455 <td align=center
><tt>:BUTT
</tt></td>
456 <td align=center
><tt>:SQUARE
</tt></td>
457 <td align=center
><tt>:ROUND
</tt></td>
464 <p><a name='set-line-join'
>[Function]
</a><br>
465 <b>set-line-join
</b> <i>style
</i> =
> |
468 Sets the line join style to
<i>style
</i>, which must be one
469 of
<tt>:MITER
</tt>,
<tt>:BEVEL
</tt>, or
<tt>:ROUND
</tt>. The initial
470 value is
<tt>:MITER
</tt>.
472 <p><table cellspacing=
5 id=
"line-join">
474 <td align=center
><img src=
"join-style-miter.png"></td>
475 <td align=center
><img src=
"join-style-bevel.png"></td>
476 <td align=center
><img src=
"join-style-round.png"></td>
479 <td align=center
><tt>:MITER
</tt></td>
480 <td align=center
><tt>:BEVEL
</tt></td>
481 <td align=center
><tt>:ROUND
</tt></td>
488 <p><a name='set-line-width'
>[Function]
</a><br>
489 <b>set-line-width
</b> <i>width
</i> =
> |
492 Sets the line width for strokes to
<i>width
</i>.
497 <p><a name='set-dash-pattern'
>[Function]
</a><br>
498 <b>set-dash-pattern
</b> <i>dash-vector
</i> <i>phase
</i> =
> |
501 Sets the dash pattern according to
<i>dash-vector
</i> and
<i>phase
</i>.
503 <p><i>dash-vector
</i> should be a vector of numbers denoting on and
504 off patterns for a stroke. An empty
<i>dash-vector
</i> is the same as
505 having no dash pattern at all.
507 <p><i>phase
</i> is how far along the dash pattern to proceed before
508 applying the pattern to the current stroke.
514 <th>Dash Vector and Phase
</th>
517 <td align=center
><img src=
"dash-pattern-none.png"></td>
518 <td align=left
><tt>#()
0</tt></td>
521 <td align=center
><img src=
"dash-pattern-a.png"></td>
522 <td align=left
><tt>#(
30 30)
0</tt></td>
525 <td align=center
><img src=
"dash-pattern-b.png"></td>
526 <td align=left
><tt>#(
30 30)
15</tt></td>
529 <td align=center
><img src=
"dash-pattern-c.png"></td>
530 <td align=left
><tt>#(
10 20 10 40)
0</tt></td>
533 <td align=center
><img src=
"dash-pattern-d.png"></td>
534 <td align=left
><tt>#(
10 20 10 40)
13</tt></td>
537 <td align=center
><img src=
"dash-pattern-e.png"></td>
538 <td align=left
><tt>#(
30 30)
0</tt>,
<tt>:ROUND
</tt> line caps
</td>
544 <p><a name='translate'
>[Function]
</a><br>
545 <b>translate
</b> <i>x
</i> <i>y
</i> =
> |
548 Offsets the coordinate system by
<i>x
</i> units horizontally
549 and
<i>y
</i> units vertically.
553 <p><a name='rotate'
>[Function]
</a><br>
554 <b>rotate
</b> <i>radians
</i> =
> |
557 Rotates the coordinate system by
<i>radians
</i>.
561 <p><a name='scale'
>[Function]
</a><br>
562 <b>scale
</b> <i>sx
</i> <i>sy
</i> =
> |
565 Scales the coordinate system by
<i>sx
</i> horizontally
566 and
<i>sy
</i> vertically.
570 <p><a name='skew'
>[Function]
</a><br>
571 <b>skew
</b> <i>ax
</i> <i>ay
</i> =
> |
574 Skews the X axis of the coordinate system by
<i>ax
</i> radians and the
575 Y axis by
<i>ay
</i> radians.
579 <p><a name='clip-path'
>[Function]
</a><br>
580 <b>clip-path
</b> =
> |
583 Defines a clipping path based on the current path. It is not applied
584 immediately, but is created after after the painting is done in the
587 href='#fill-path'
><tt>FILL-PATH
</tt></a>,
<a
588 href='#even-odd-fill'
><tt>EVEN-ODD-FILL
</tt></a>,
<a
589 href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
<a
590 href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>,
591 or
<a href='#end-path-no-op'
><tt>END-PATH-NO-OP
</tt></a>.
593 <p>The clipping path initially covers the entire canvas; no clipping
594 is done. Subsequent calls to
<tt>CLIP-PATH
</tt> set the clipping path
595 to the intersection of the established clipping path and the new
596 clipping path, and all drawing will be done within the outline of the
599 <p>The outline of the clipping path is defined with the nonzero
600 winding rule, as with
<a href='#fill-path'
><tt>FILL-PATH
</tt></a>.
602 <p>There is no way to enlarge the clipping path. However, the clipping
603 path is part of the graphics state, so changes may be localized by
604 using
<a href='#with-graphics-state'
><tt>WITH-GRAPHICS-STATE
</tt></a>.
609 <td><img src=
"clip-unclipped.png"></td>
610 <td>A filled red rectangle, not clipped
</td>
613 <td><img src=
"clip-to-circle.png"></td>
614 <td>The same rectangle drawn with a circle clipping path in effect
</td>
617 <td><img src=
"clip-to-rectangle.png"></td>
618 <td>Clipped to a rounded rectangle clipping path
</td>
621 <td><img src=
"clip-to-both.png"></td>
622 <td>Clipped to the intersection of the circle and rounded rectangle clipping paths
</td>
631 <p><a name='even-odd-clip-path'
>[Function]
</a><br>
632 <b>even-odd-clip-path
</b> =
> |
635 Like
<a href='#clip-path'
><tt>CLIP-PATH
</tt></a>, but uses the
636 even/odd fill rule to determine the outline of the clipping path.
640 <a name='sect-paths'
><h4>Paths
</h4></a>
642 <p>Paths are used to create lines for stroking or outlines for
643 filling. Paths consist of straight lines and curves. Paths consist of
644 one or more subpaths.
646 <p><a name='move-to'
>[Function]
</a><br>
647 <b>move-to
</b> <i>x
</i> <i>y
</i> =
> |
650 Starts a new subpath at (
<i>x
</i>,
<i>y
</i>).
<tt>move-to
</tt> must be the
651 first step of constructing a subpath.
655 <p><a name='line-to'
>[Function]
</a><br>
656 <b>line-to
</b> <i>x
</i> <i>y
</i> =
> |
659 Appends a straight line ending at (
<i>x
</i>,
<i>y
</i>) to the
664 <p><a name='curve-to'
>[Function]
</a><br>
666 <i>cx1
</i> <i>cy1
</i>
667 <i>cx2
</i> <i>cy2
</i>
668 <i>x
</i> <i>y
</i> =
> |
672 cubic
<a href=
"http://en.wikipedia.org/wiki/B%C3%A9zier_curve">B
ézier
673 curve
</a> ending at (
<i>x
</i>,
<i>y
</i>) and with control
674 points (
<i>cx1
</i>,
<i>cy1
</i>) and (
<i>cx2
</i>,
<i>cy2
</i>) to the current
679 <p><a name='quadratic-to'
>[Function]
</a><br>
682 <i>x
</i> <i>y
</i> =
> |
685 Appends a quadratic B
ézier curve ending at (
<i>x
</i>,
<i>y
</i>)
686 and with the control point (
<i>cx
</i>,
<i>cy
</i>) to the current
691 <p><a name='arc'
>[Function]
</a><br>
692 <b>arc
</b> <i>x
</i> <i>y
</i> <i>radius
</i> <i>angle1
</i> <i>angle2
</i>
696 Appends an arc of a circle to the current path. The center of the arc is
697 at (
<i>x
</i>,
<i>y
</i>). The arc begins at point at a
698 distance
<i>radius
</i> from the center and with an angle
<i>angle1
</i>
699 radians from the positive x axis, and ends at the point
700 with
<i>angle2
</i> radians. If
<i>angle2
</i> is less
701 than
<i>angle1
</i>, it is increased by increasing multiples of
2π
702 until it is greater than or equal to
<i>angle1
</i>.
704 <p><table cellpadding=
5>
705 <tr><td align=center
><img src=
"arc.png"></td></tr>
706 <tr><td><span style='color: #
0f0'
><i>radius
</i></span>,
707 <span style='color: #f00'
><i>angle1
</i></span>,
708 <span style='color: #
00f'
><i>angle2
</i></span></td></tr>
711 <p>If there is a current point, a straight line is added from the
712 current point to the start point of the arc. Otherwise, a new path
715 <pre><img class='transparent' style='float: right' src='pie-wedge.png'
716 >(defun pie-wedge (file)
717 (with-canvas (:width
80 :height
60)
720 (angle1 (* (/ pi
180)
15))
721 (angle2 (* (/ pi
180)
45)))
725 (arc x y radius angle1 angle2)
733 <p><a name='arcn'
>[Function]
</a><br>
734 <b>arcn
</b> <i>x
</i> <i>y
</i> <i>radius
</i> <i>angle1
</i> <i>angle2
</i>
738 Like
<a href='#arc'
><tt>ARC
</tt></a>, but draws the arc clockwise
739 instead of counterclockwise. If
<i>angle2
</i> is greater
740 than
<i>angle1
</i>, it is decreased by increasing multiples of
2π
741 until it is less than or equal to
<i>angle1
</i>.
743 <pre><img class='transparent' style='float: right' src='wiper.png'
745 (with-canvas (:width
70 :height
70)
749 (angle2 (* (/ pi
180)
90)))
751 (set-rgba-fill
1 1 1 0.75)
752 (arc x y r1 angle1 angle2)
753 (arcn x y r2 angle2 angle1)
761 <p><a name='close-subpath'
>[Function]
</a><br>
762 <b>close-subpath
</b> =
> |
765 Closes the current subpath. If the current point is not the same as the
766 starting point for the subpath, appends a straight line from the
767 current point to the starting point of the current subpath.
769 <p>Subpaths with start and end points that coincidentally overlap are
770 not the same as closed subpaths. The distinction is important when
773 <p><table cellpadding=
5>
775 <td align=center
><img src=
"open-subpath.png"></td>
776 <td align=center
><img src=
"closed-subpath.png"></td>
779 <td align=center
>Open subpath
</td>
780 <td align=center
>Closed subpath
</td>
784 <p>If the subpath is not closed, the start and points of the subpath
785 will be drawn with the current line cap style. If the path is
786 closed, the start and endpoints will be treated as joined and drawn
787 with the line join style.
791 <p><a name='stroke-to-paths'
>[Function]
</a><br>
792 <b>stroke-to-paths
</b> =
> |
795 Sets the current active paths to the paths that would result from
796 outlining a
<a href='#stroke'
><tt>STROKE
</tt></a> operation.
800 <p><a name='rectangle'
>[Function]
</a><br>
801 <b>rectangle
</b> <i>x
</i> <i>y
</i> <i>width
</i> <i>height
</i> =
> |
804 Creates a rectangular subpath with the given
<i>width
</i>
805 and
<i>height
</i> that has its lower-left corner at
806 (
<i>x
</i>,
<i>y
</i>). It is effectively the same as:
810 (line-to (+ x width) y)
811 (line-to (+ x width) (+ y height))
812 (line-to x (+ y height))
817 <p><a name='rounded-rectangle'
>[Function]
</a><br>
818 <b>rounded-rectangle
</b> <i>x
</i> <i>y
</i>
819 <i>width
</i> <i>height
</i> <i>rx
</i> <i>ry
</i> =
> |
822 Like
<a href='#rectangle'
><tt>RECTANGLE
</tt></a>, but rounds the
823 corners of the rectangle paths by the x radius
<i>rx
</i> and the y
827 <p><a name='centered-ellipse-path'
>[Function]
</a><br>
828 <b>centered-ellipse-path
</b>
833 Adds a closed subpath that outlines an ellipse centered at
834 (
<i>x
</i>,
<i>y
</i>) with an X radius of
<i>rx
</i> and a Y radius
838 <p><a name='centered-circle-path'
>[Function]
</a><br>
839 <b>centered-circle-path
</b> <i>x
</i> <i>y
</i> <i>radius
</i> =
> |
842 Adds a closed subpath that outlines a circle centered at
843 (
<i>x
</i>,
<i>y
</i>) with a radius of
<i>radius
</i>. It is effectively
847 (centered-ellipse-path x y radius radius)
853 <a name='sect-painting'
><h4>Painting
</h4></a>
855 <p>After a path is defined, filling, stroking, or both will use the
856 path to apply color to the canvas. After a path has been filled or
857 stroked, it is no longer active; it effectively disappears.
860 <p><a name='fill-path'
>[Function]
</a><br>
861 <b>fill-path
</b> =
> |
864 Fills the current path with the fill color or gradient. If the path
865 has not been explicitly closed
866 with
<a href='#close-subpath'
><tt>CLOSE-SUBPATH
</tt></a>, it is
867 implicitly closed before filling. The non-zero winding rule is used
868 to determine what areas are considered inside the path.
872 <p><a name='even-odd-fill'
>[Function]
</a><br>
873 <b>even-odd-fill
</b> =
> |
876 The same as
<a href='#fill-path'
><tt>FILL-PATH
</tt></a>, but uses the
877 even/odd rule to determine what areas are considered inside the path.
881 <p><a name='stroke'
>[Function]
</a><br>
885 Strokes the current path. The line width, stroke color, line join
886 style, line cap style, and dash pattern and phase determine how the
887 stroked path will appear on the canvas.
891 <p><a name='fill-and-stroke'
>[Function]
</a><br>
892 <b>fill-and-stroke
</b> =
> |
895 Fills the current path, then strokes it.
899 <p><a name='even-odd-fill-and-stroke'
>[Function]
</a><br>
900 <b>even-odd-fill-and-stroke
</b> =
> |
903 Fills the current path using the even/odd rule, then strokes it.
907 <p><a name='end-path-no-op'
>[Function]
</a><br>
908 <b>end-path-no-op
</b> =
> |
911 Ends the current path without painting anything. If a clipping path
912 has been specified with
<a href='#clip-path'
><tt>CLIP-PATH
</tt></a>
913 or
<a href='#even-odd-clip-path'
><tt>EVEN-ODD-CLIP-PATH
</tt></a>, it
914 will be created by
<tt>end-path-no-op
</tt>.
919 <a name='sect-text'
><h4>Text
</h4></a>
921 <p>Vecto can draw text to a canvas. It loads glyph shapes from
923 with
<a href=
"http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF
</a>.
925 <p><a name='get-font'
>[Function]
</a><br>
926 <b>get-font
</b> <i>font-file
</i> =
> <i>font-loader
</i>
929 Creates and returns a ZPB-TTF font loader object
930 from
<i>font-file
</i>. Any font loader created this way will
931 automatically be closed at the end of its
932 enclosing
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a> form.
936 <p><a name='set-font'
>[Function]
</a><br>
937 <b>set-font
</b> <i>font-loader
</i> <i>size
</i> =
> |
940 Sets the active font to the font associated
941 with
<i>font-loader
</i>, scaled to
<i>size
</i> units per line.
943 <p>The first argument can be any ZPB-TTF font loader; it need not be
944 created via
<a href='#get-font'
><tt>GET-FONT
</tt></a>. However, only
945 font loaders created via
<tt>GET-FONT
</tt> will be automatically
946 closed at the end of
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a>.
950 <p><a name='set-character-spacing'
>[Function]
</a><br>
951 <b>set-character-spacing
</b> <i>spacing
</i> =
> |
954 Sets the scale of the spacing used between characters when drawing
955 text with
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a> and related
958 <p>Normally, the character spacing for drawing text is taken directly
959 from a font's advance-width and kerning
960 metrics.
<tt>SET-CHARACTER-SPACING
</tt> can be used to adjust this
961 spacing; for example, a character spacing of
2.0d0 would double the
962 normal space between characters, and
0.5d0 would halve it.
965 <p><a name='*default-character-spacing*'
>[Special variable]
</a><br>
966 <b>*default-character-spacing*
</b>
969 The default scale for character spacing when drawing text
970 with
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a> and related
971 functions. Initial value is
1.0d0.
973 <p>Changes to this variable affect the
974 next
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a> form. To affect
975 the spacing within the current
<tt>WITH-CANVAS
</tt> form,
976 use
<a href='#set-character-spacing'
><tt>SET-CHARACTER-SPACING
</tt></a>.
980 <p><a name='draw-string'
>[Function]
</a><br>
981 <b>draw-string
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
984 Draws
<i>string
</i> on the canvas with the active font. The glyph
985 origin of the first character in the string is positioned at
<i>x
</i>
986 and the baseline of the string is positioned at
<i>y
</i>. The text is
987 filled with the current
<a href='#set-rgba-fill'
>fill color
</a>.
989 <p>The string may be a specialized vector of characters (a true CL
990 string) or a vector containing characters, Unicode code-points, or both. For
991 example,
<tt>#(#\L #\a #\m #\b #\d #\a #\= #x3BB)
</tt> is a valid
992 argument for
<tt>DRAW-STRING
</tt>.
994 <p>The horizontal space between characters is determined by the
995 advance-width and kerning metrics of the font, then multiplied by
996 the current character spacing. At the default character spacing of
997 1.0d0, the spacing is not adjusted at
998 all.
<a href='#set-character-spacing'
><tt>SET-CHARACTER-SPACING
</tt></a>
999 can be used to increase or decrease the character spacing.
1003 <p><a name='string-paths'
>[Function]
</a><br>
1004 <b>string-paths
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1007 Like
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a>, but instead of
1008 drawing the text, adds the subpaths that make up the string glyphs to
1009 the graphics state. This can be used to stroke, fill, or clip based on
1010 the outlines of a string.
1014 <p><a name='draw-centered-string'
>[Function]
</a><br>
1015 <b>draw-centered-string
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1018 Draws
<i>string
</i> on the canvas with the active font. The horizontal
1019 center of the string is positioned at
<i>x
</i> and the baseline of the
1020 string is positioned at
<i>y
</i>.
1024 <p><a name='centered-string-paths'
>[Function]
</a><br>
1025 <b>centered-string-paths
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1028 Like
<a href='#draw-centered-string'
><tt>DRAW-CENTERED-STRING
</tt></a>,
1029 but adds subpaths instead of painting. See
1030 also
<a href='#string-paths'
><tt>STRING-PATHS
</tt></a>.
1034 <p><a name='string-bounding-box'
>[Function]
</a><br>
1035 <b>string-bounding-box
</b> <i>string
</i> <i>size
</i> <i>loader
</i>
1036 =
> <i>#(xmin ymin xmax ymax)
</i>
1039 Calculates the bounding box of
<i>string
</i> for
<i>font-loader
</i>
1044 <a name='sect-miscellaneous'
><h3>Miscellaneous
</h3></a>
1046 <p><a name='const-kappa'
>[Constant]
</a><br>
1047 <b>+kappa+
</b> =
> 0.5522847498307936d0.
1050 This constant is useful to draw portions of a circle.
1054 <a name='sect-references'
><h2>References
</h2></a>
1057 <li> Adobe Systems Inc.,
<a href=
"http://www.adobe.com/devnet/pdf/pdf_reference.html">PDF Reference, Sixth Edition, Version
1.7</a>
1058 <li> Lawrence Kesteloot,
<a href=
"http://www.teamten.com/lawrence/graphics/premultiplication/">Alpha Premultiplication
</a>
1059 <li> Dr. Thomas Sederberg,
<a href=
"http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf">B
ézier curves
</a>
1060 <li> Alvy Ray Smith,
<a href=
"http://alvyray.com/Memos/MemosMicrosoft.htm#ImageCompositing">Image Compositing Fundamentals
</a>
1061 <li> G. Adam Stanislav,
<a href=
"http://www.whizkidtech.redprince.net/bezier/circle/">Drawing a circle with B
ézier curves
</a>
1062 <li> Alexander Thomas,
<a href=
"http://www.dr-lex.be/random/matrix_inv.html">The Inverse and Determinants of
2x2 and
3x3 Matrices
</a>
1063 <li> Wikipedia,
<a href=
"http://en.wikipedia.org/wiki/B%C3%A9zier_curve">B
ézier curve
</a>
1068 <a name='sect-acknowledgements'
><h2>Acknowledgements
</h2></a>
1070 <p>Many thanks to
<a href=
"http://www.elbeno.com/">Ben Deane
</a> for
1071 permission to adapt code from his curve library for drawing arcs.
1073 <p>Ryan Davis helped fix my adaptation of the arc drawing.
1075 <a name='sect-feedback'
><h2>Feedback
</h2></a>
1077 <p>If you have any questions, comments, bug reports, or other feedback
1078 regarding Vecto, please email
<a href=
"mailto:xach@xach.com">Zach