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) }
11 max-width: 50em; margin-left: auto
; margin-right: auto
;
12 font-family: sans-serif
;
14 background-color: white
;
15 padding: 0.25em 1em 0.25em 1em;
18 background-color: #f4eecf;
26 <h2>Vecto - Simple Vector Drawing with Common Lisp
</h2>
28 <blockquote class='abstract'
>
31 <p>Vecto is a simplified interface to the
32 powerful
<a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
33 vector rasterization library. It presents a function-oriented
34 interface similar to
<a href=
"http://www.cliki.net/CL-PDF">CL-PDF
</a>,
35 but the results can be saved to a PNG instead of a PDF file. Since
36 Vecto and all supporting libraries are written completely in Common
37 Lisp, without depending on external non-Lisp libraries, it should work
38 in any Common Lisp environment. Vecto is available under a BSD-like
41 The latest version is
1.4.10, released on October
15th,
2014.
44 by
<a href=
"http://wigflip.com/easystreet/">Easystreet
</a>
45 and
<a href='http://www.xach.com/moviecharts/'
>Movie Charts
</a>.
47 <p>The canonical location for Vecto
48 is
<a href=
"http://www.xach.com/lisp/vecto/">http://www.xach.com/lisp/vecto/
</a>.
50 <p class='download'
>Download shortcut:
</p>
52 <p><a href=
"http://www.xach.com/lisp/vecto.tgz">http://www.xach.com/lisp/vecto.tgz
</a>
59 <li> <a href='#sect-overview-and-limitations'
>Overview and Limitations
</a>
60 <li> <a href='#sect-examples'
>Examples
</a>
61 <li> <a href='#sect-dictionary'
>Dictionary
</a>
64 <li> <a href='#sect-canvases'
>Canvases
</a>
66 <li> <a href='#with-canvas'
><tt>with-canvas
</tt></a>
67 <li> <a href='#clear-canvas'
><tt>clear-canvas
</tt></a>
68 <li> <a href='#save-png'
><tt>save-png
</tt></a>
69 <li> <a href='#save-png-stream'
><tt>save-png-stream
</tt></a>
72 <li> <a href='#sect-graphics-state'
>Graphics State
</a>
74 <li> <a href='#with-graphics-state'
><tt>with-graphics-state
</tt></a>
75 <li> <a href='#set-rgba-fill'
><tt>set-rgba-fill
</tt></a>
76 <li> <a href='#set-rgba-fill'
><tt>set-rgb-fill
</tt></a>
77 <li> <a href='#set-gradient-fill'
><tt>set-gradient-fill
</tt></a>
78 <li> <a href='#set-rgba-stroke'
><tt>set-rgba-stroke
</tt></a>
79 <li> <a href='#set-rgba-stroke'
><tt>set-rgb-stroke
</tt></a>
80 <li> <a href='#set-line-cap'
><tt>set-line-cap
</tt></a>
81 <li> <a href='#set-line-join'
><tt>set-line-join
</tt></a>
82 <li> <a href='#set-line-width'
><tt>set-line-width
</tt></a>
83 <li> <a href='#set-dash-pattern'
><tt>set-dash-pattern
</tt></a>
84 <li> <a href='#translate'
><tt>translate
</tt></a>
85 <li> <a href='#rotate'
><tt>rotate
</tt></a>
86 <li> <a href='#scale'
><tt>scale
</tt></a>
87 <li> <a href='#skew'
><tt>skew
</tt></a>
88 <li> <a href='#clip-path'
><tt>clip-path
</tt></a>
89 <li> <a href='#even-odd-clip-path'
><tt>even-odd-clip-path
</tt></a>
92 <li> <a href='#sect-paths'
>Paths
</a>
94 <li> <a href='#move-to'
><tt>move-to
</tt></a>
95 <li> <a href='#line-to'
><tt>line-to
</tt></a>
96 <li> <a href='#curve-to'
><tt>curve-to
</tt></a>
97 <li> <a href='#quadratic-to'
><tt>quadratic-to
</tt></a>
98 <li> <a href='#arc'
><tt>arc
</tt></a>
99 <li> <a href='#arcn'
><tt>arcn
</tt></a>
100 <li> <a href='#ellipse-arc'
><tt>ellipse-arc
</tt></a>
101 <li> <a href='#ellipse-arcn'
><tt>ellipse-arcn
</tt></a>
102 <li> <a href='#close-subpath'
><tt>close-subpath
</tt></a>
103 <li> <a href='#stroke-to-paths'
><tt>stroke-to-paths
</tt></a>
104 <li> <a href='#rectangle'
><tt>rectangle
</tt></a>
105 <li> <a href='#rounded-rectangle'
><tt>rounded-rectangle
</tt></a>
106 <li> <a href='#centered-ellipse-path'
><tt>centered-ellipse-path
</tt></a>
107 <li> <a href='#centered-circle-path'
><tt>centered-circle-path
</tt></a>
110 <li> <a href='#sect-painting'
>Painting
</a>
112 <li> <a href='#fill-path'
><tt>fill-path
</tt></a>
113 <li> <a href='#even-odd-fill'
><tt>even-odd-fill
</tt></a>
114 <li> <a href='#stroke'
><tt>stroke
</tt></a>
115 <li> <a href='#fill-and-stroke'
><tt>fill-and-stroke
</tt></a>
116 <li> <a href='#even-odd-fill-and-stroke'
><tt>even-odd-fill-and-stroke
</tt></a>
117 <li> <a href='#end-path-no-op'
><tt>end-path-no-op
</tt></a>
120 <li> <a href='#sect-text'
>Text
</a>
122 <li> <a href='#get-font'
><tt>get-font
</tt></a>
123 <li> <a href='#set-font'
><tt>set-font
</tt></a>
124 <li> <a href='#set-character-spacing'
><tt>set-character-spacing
</tt></a>
125 <li> <a href='#*default-character-spacing*'
><tt>*default-character-spacing*
</tt></a>
126 <li> <a href='#draw-string'
><tt>draw-string
</tt></a>
127 <li> <a href='#string-paths'
><tt>string-paths
</tt></a>
128 <li> <a href='#draw-centered-string'
><tt>draw-centered-string
</tt></a>
129 <li> <a href='#centered-string-paths'
><tt>centered-string-paths
</tt></a>
130 <li> <a href='#string-bounding-box'
><tt>string-bounding-box
</tt></a>
133 <li> <a href='#sect-miscellaneous'
>Miscellaneous
</a>
135 <li> <a href='#const-kappa'
><tt>+kappa+
</tt></a>
140 <li> <a href='#sect-references'
>References
</a>
141 <li> <a href='#sect-acknowledgements'
>Acknowledgements
</a>
142 <li> <a href='#sect-feedback'
>Feedback
</a>
146 <a name='sect-overview-and-limitations'
><h3>Overview and Limitations
</h3></a>
148 <p>Vecto is a library that provides a simple interface to the
149 the
<a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
150 vector drawing library. It supports drawing on a canvas and saving the
151 results to a PNG file.
153 <p>Vecto depends on the following libraries:
156 <li> <a href=
"http://projects.tuxee.net/cl-vectors/">CL-VECTORS
</a>
157 <li> <a href=
"http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF
</a>
158 <li> <a href=
"http://www.xach.com/lisp/salza2/">Salza2
</a>
159 <li> <a href=
"http://www.xach.com/lisp/zpng/">ZPNG
</a>
162 <p>The easiest way to install Vecto and all its dependencies is
163 with
<a href=
"http://www.quicklisp.org/">Quicklisp
</a>.
165 <p>Vecto's function interface is similar to the
166 PDF vector description and painting interface: you create images by
167 describing vector paths, then using stroke or fill operations to paint
170 <p>Vecto's color system uses red, green, blue, and alpha color
171 components for drawing. The results can be be saved to a PNG with an
174 <p>Vecto's coordinate system starts at the lower-left corner of the
175 image, and increases rightwards along the X axis and upwards along the
178 <p>All measurements are in pixels.
180 <p>PDF is a feature-rich system. Vecto supports a small subset of
181 PDF-style operations. In particular, it does not support:
185 <li> pattern or functional fill
186 <li> complex layout of text
187 <li> PostScript fonts
188 <li> non-RGB color spaces
191 <p>Other limitations:
194 <li> No output formats other than
8-bit, truecolor-alpha PNGs
195 <li> No access to underlying pixel data
198 <p>Related libraries:
201 <li> <a href=
"http://common-lisp.net/project/imago/">Imago
</a>
203 <li> <a href=
"http://cyrusharmon.org/projects?project=ch-image">ch-image
</a>
205 <li> <a href=
"http://ygingras.net/poly-pen">Poly-pen
</a>
209 <a name='sect-examples'
><h3>Examples
</h3></a>
211 <p>All examples are available in
<tt>doc/examples.lisp
</tt> in the Vecto
212 distribution. That file starts with:
215 (defpackage #:vecto-examples
218 (in-package #:vecto-examples)
223 <img border=
0 align=right src='lambda-example.png'
224 >(defun radiant-lambda (file)
225 (
<a href='#with-canvas'
>with-canvas
</a> (:width
90 :height
90)
226 (let ((font (
<a href='#get-font'
>get-font
</a> "times.ttf"))
228 (
<a href='#set-font'
>set-font
</a> font
40)
229 (
<a href='#translate'
>translate
</a> 45 45)
230 (
<a href='#draw-centered-string'
>draw-centered-string
</a> 0 -
10 #(#x3BB))
231 (
<a href='#set-rgba-stroke'
>set-rgb-stroke
</a> 1 0 0)
232 (
<a href='#centered-circle-path'
>centered-circle-path
</a> 0 0 35)
233 (
<a href='#stroke'
>stroke
</a>)
234 (
<a href='#set-rgba-stroke'
>set-rgba-stroke
</a> 0 0 1.0 0.5)
235 (
<a href='#set-line-width'
>set-line-width
</a> 4)
237 (
<a href='#with-graphics-state'
>with-graphics-state
</a>
238 (
<a href='#rotate'
>rotate
</a> (* i step))
239 (
<a href='#move-to'
>move-to
</a> 30 0)
240 (
<a href='#line-to'
>line-to
</a> 40 0)
242 (
<a href='#save-png'
>save-png
</a> file))))
246 <img align=right src='feedlike-icon.png'
247 >(defun feedlike-icon (file)
248 (with-canvas (:width
100 :height
100)
249 (set-rgb-fill
1.0 0.65 0.3)
250 (
<a href='#rounded-rectangle'
>rounded-rectangle
</a> 0 0 100 100 10 10)
251 (
<a href='#fill-path'
>fill-path
</a>)
252 (set-rgb-fill
1.0 1.0 1.0)
253 (centered-circle-path
20 20 10)
255 (flet ((quarter-circle (x y radius)
256 (move-to (+ x radius) y)
257 (
<a href='#arc'
>arc
</a> x y radius
0 (/ pi
2))))
258 (set-rgb-stroke
1.0 1.0 1.0)
260 (quarter-circle
20 20 30)
262 (quarter-circle
20 20 60)
264 (rounded-rectangle
5 5 90 90 7 7)
265 (
<a href='#set-gradient-fill'
>set-gradient-fill
</a> 50 90
270 (set-rgba-stroke
1.0 1.0 1.0 0.1)
271 (
<a href='#fill-and-stroke'
>fill-and-stroke
</a>)
275 <pre><div style='float: right' class='transparent'
><img src='star-clipping.png'
276 ></div>(defun star-clipping (file)
277 (with-canvas (:width
200 :height
200)
280 (step (*
2 (/ (* pi
2)
5))))
281 (translate size size)
284 (setf angle (+ angle step))
285 (line-to (* (sin angle) size)
286 (* (cos angle) size)))
287 (
<a href='#even-odd-clip-path'
><tt>even-odd-clip-path
</tt></a>)
288 (
<a href='#end-path-no-op'
><tt>end-path-no-op
</tt></a>)
289 (flet ((circle (distance)
290 (
<a href='#set-rgba-fill'
><tt>set-rgba-fill
</tt></a> distance
0 0
292 (centered-circle-path
0 0 (* size distance))
294 (loop for i downfrom
1.0 by
0.05
300 <a name='sect-dictionary'
><h3>Dictionary
</h3></a>
302 <p>The following symbols are exported from the
<tt>VECTO
</tt> package.
304 <a name='sect-canvases'
><h4>Canvases
</h4></a>
306 <p><a name='with-canvas'
>[Macro]
</a><br>
307 <b>with-canvas
</b> (
<tt>&key
</tt> <i>width
</i> <i>height
</i>)
308 <tt>&body
</tt> <i>body
</i>
311 Evaluates
<i>body
</i> with a canvas established with the specified
312 dimensions as the target for drawing commands. The canvas is initially
313 completely clear (all pixels have
0 alpha).
317 <p><a name='clear-canvas'
>[Function]
</a><br>
318 <b>clear-canvas
</b> =
> |
321 Completely fills the canvas with the current fill color. Any marks on
322 the canvas are cleared.
326 <p><a name='save-png'
>[Function]
</a><br>
327 <b>save-png
</b> <i>file
</i> =
> <i>truename
</i>
330 Writes the contents of the canvas as the PNG
<i>file
</i>, and returns
331 the truename of
<i>file
</i>.
335 <p><a name='save-png-stream'
>[Function]
</a><br>
336 <b>save-png-stream
</b> <i>stream
</i> =
> |
339 Writes the contents of the canvas as a PNG to
<i>stream
</i>, which
340 must accept
<tt>(unsigned-byte
8)
</tt> data.
344 <a name='sect-graphics-state'
><h4>Graphics State
</h4></a>
346 <p>The graphics state stores several parameters used for graphic
349 <p><a name='with-graphics-state'
>[Macro]
</a><br>
350 <b>with-graphics-state
</b> <tt>&body
</tt> <i>body
</i>
353 Evaluates the forms of
<i>body
</i> with a copy of the current graphics
354 state. Any modifications to the state are undone at the end of the
359 <p><a name='set-rgba-fill'
>[Functions]
</a><br>
360 <b>set-rgba-fill
</b> <i>r
</i> <i>g
</i> <i>b
</i> <i>alpha
</i> =
> |
<br>
361 <b>set-rgb-fill
</b> <i>r
</i> <i>g
</i> <i>b
</i> =
> |
364 Sets the fill color.
<i>r
</i>,
<i>g
</i>,
<i>b
</i>, and
<i>alpha
</i>
365 should be in the range of
0.0 to
1.0.
367 <p><tt>set-rgb-fill
</tt> is the same as
<tt>set-rgba-fill
</tt> with an
368 implicit alpha value of
1.0.
370 <p>The fill color is used
372 href='#clear-canvas'
><tt>CLEAR-CANVAS
</tt></a>,
<a
373 href='#fill-path'
><tt>FILL-PATH
</tt></a>,
<a
374 href='#even-odd-fill'
><tt>EVEN-ODD-FILL
</tt></a>,
<a
375 href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
<a
376 href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>,
377 and
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a>.
381 <p><a name='set-gradient-fill'
>[Function]
</a><br>
382 <b>set-gradient-fill
</b>
383 <i>x0
</i> <i>y0
</i> <i>r0
</i> <i>g0
</i> <i>b0
</i> <i>a0
</i>
384 <i>x1
</i> <i>y1
</i> <i>r1
</i> <i>g1
</i> <i>b1
</i> <i>a1
</i>
385 <tt>&key
</tt> (
<i>extend-start
</i> <tt>t
</tt>)
386 (
<i>extend-end
</i> <tt>t
</tt>)
387 (
<i>domain-function
</i> <tt>'linear-domain
</tt>)
390 Set the fill color source to an axial gradient. The start point
391 is
<i>x0,y0
</i> and the start color is
<i>r0,g0,b0,a0
</i>. The end
392 point is
<i>x1, y1
</i> and the end color is
<i>r1,g1,b1,a1
</i>.
394 <p>Two domain functions are available:
398 <li> <tt>LINEAR-DOMAIN
</tt>, the default, makes a transition from the
399 start color to the end color along the axis between the start and end
402 <li> <tt>BILINEAR-DOMAIN
</tt> makes a transition from the start color
403 to the end color from the start point to the midpoint, then back to
404 the start color from the midpoint to the end point
407 <pre><img style='float: right' class='transparent'
408 src='linear-gradient.png'
>(defun gradient-example (file)
409 (with-canvas (:width
200 :height
50)
410 (set-gradient-fill
25 0
414 (rectangle
0 0 200 50)
419 <pre><img style='float: right' class='transparent'
420 src='bilinear-gradient.png'
>(defun gradient-bilinear-example (file)
421 (with-canvas (:width
200 :height
50)
422 (set-gradient-fill
25 0
426 :domain-function 'bilinear-domain)
427 (rectangle
0 0 200 50)
436 <p><a name='set-rgba-stroke'
>[Functions]
</a><br>
437 <b>set-rgba-stroke
</b> <i>r
</i> <i>g
</i> <i>b
</i> <i>alpha
</i> =
> |
<br>
438 <b>set-rgb-stroke
</b> <i>r
</i> <i>g
</i> <i>b
</i> =
> |
441 Sets the stroke color.
<i>r
</i>,
<i>g
</i>,
<i>b
</i>, and
<i>alpha
</i>
442 should be in the range of
0.0 to
1.0.
444 <p><tt>set-rgb-stroke
</tt> is the same as
<tt>set-rgba-stroke
</tt>
445 with an implicit alpha value of
1.0.
447 <p>The stroke color is used for
<a href='#stroke'
><tt>STROKE
</tt></a>,
448 <a href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
449 and
<a href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>.
453 <p><a name='set-line-cap'
>[Function]
</a><br>
454 <b>set-line-cap
</b> <i>style
</i> =
> |
457 Sets the line cap style to
<i>style
</i>, which must be one
458 of
<tt>:BUTT
</tt>,
<tt>:SQUARE
</tt>, or
<tt>:ROUND
</tt>. The initial
459 value is
<tt>:BUTT
</tt>.
461 <p><table cellspacing=
5 id=
"line-cap">
463 <td align=center
><img src=
"cap-style-butt.png"></td>
464 <td align=center
><img src=
"cap-style-square.png"></td>
465 <td align=center
><img src=
"cap-style-round.png"></td>
468 <td align=center
><tt>:BUTT
</tt></td>
469 <td align=center
><tt>:SQUARE
</tt></td>
470 <td align=center
><tt>:ROUND
</tt></td>
477 <p><a name='set-line-join'
>[Function]
</a><br>
478 <b>set-line-join
</b> <i>style
</i> =
> |
481 Sets the line join style to
<i>style
</i>, which must be one
482 of
<tt>:MITER
</tt>,
<tt>:BEVEL
</tt>, or
<tt>:ROUND
</tt>. The initial
483 value is
<tt>:MITER
</tt>.
485 <p><table cellspacing=
5 id=
"line-join">
487 <td align=center
><img src=
"join-style-miter.png"></td>
488 <td align=center
><img src=
"join-style-bevel.png"></td>
489 <td align=center
><img src=
"join-style-round.png"></td>
492 <td align=center
><tt>:MITER
</tt></td>
493 <td align=center
><tt>:BEVEL
</tt></td>
494 <td align=center
><tt>:ROUND
</tt></td>
501 <p><a name='set-line-width'
>[Function]
</a><br>
502 <b>set-line-width
</b> <i>width
</i> =
> |
505 Sets the line width for strokes to
<i>width
</i>.
510 <p><a name='set-dash-pattern'
>[Function]
</a><br>
511 <b>set-dash-pattern
</b> <i>dash-vector
</i> <i>phase
</i> =
> |
514 Sets the dash pattern according to
<i>dash-vector
</i> and
<i>phase
</i>.
516 <p><i>dash-vector
</i> should be a vector of numbers denoting on and
517 off patterns for a stroke. An empty
<i>dash-vector
</i> is the same as
518 having no dash pattern at all.
520 <p><i>phase
</i> is how far along the dash pattern to proceed before
521 applying the pattern to the current stroke.
527 <th>Dash Vector and Phase
</th>
530 <td align=center
><img src=
"dash-pattern-none.png"></td>
531 <td align=left
><tt>#()
0</tt></td>
534 <td align=center
><img src=
"dash-pattern-a.png"></td>
535 <td align=left
><tt>#(
30 30)
0</tt></td>
538 <td align=center
><img src=
"dash-pattern-b.png"></td>
539 <td align=left
><tt>#(
30 30)
15</tt></td>
542 <td align=center
><img src=
"dash-pattern-c.png"></td>
543 <td align=left
><tt>#(
10 20 10 40)
0</tt></td>
546 <td align=center
><img src=
"dash-pattern-d.png"></td>
547 <td align=left
><tt>#(
10 20 10 40)
13</tt></td>
550 <td align=center
><img src=
"dash-pattern-e.png"></td>
551 <td align=left
><tt>#(
30 30)
0</tt>,
<tt>:ROUND
</tt> line caps
</td>
557 <p><a name='translate'
>[Function]
</a><br>
558 <b>translate
</b> <i>x
</i> <i>y
</i> =
> |
561 Offsets the coordinate system by
<i>x
</i> units horizontally
562 and
<i>y
</i> units vertically.
566 <p><a name='rotate'
>[Function]
</a><br>
567 <b>rotate
</b> <i>radians
</i> =
> |
570 Rotates the coordinate system by
<i>radians
</i>.
574 <p><a name='scale'
>[Function]
</a><br>
575 <b>scale
</b> <i>sx
</i> <i>sy
</i> =
> |
578 Scales the coordinate system by
<i>sx
</i> horizontally
579 and
<i>sy
</i> vertically.
583 <p><a name='skew'
>[Function]
</a><br>
584 <b>skew
</b> <i>ax
</i> <i>ay
</i> =
> |
587 Skews the X axis of the coordinate system by
<i>ax
</i> radians and the
588 Y axis by
<i>ay
</i> radians.
592 <p><a name='clip-path'
>[Function]
</a><br>
593 <b>clip-path
</b> =
> |
596 Defines a clipping path based on the current path. It is not applied
597 immediately, but is created after after the painting is done in the
600 href='#fill-path'
><tt>FILL-PATH
</tt></a>,
<a
601 href='#even-odd-fill'
><tt>EVEN-ODD-FILL
</tt></a>,
<a
602 href='#fill-and-stroke'
><tt>FILL-AND-STROKE
</tt></a>,
<a
603 href='#even-odd-fill-and-stroke'
><tt>EVEN-ODD-FILL-AND-STROKE
</tt></a>,
604 or
<a href='#end-path-no-op'
><tt>END-PATH-NO-OP
</tt></a>.
606 <p>The clipping path initially covers the entire canvas; no clipping
607 is done. Subsequent calls to
<tt>CLIP-PATH
</tt> set the clipping path
608 to the intersection of the established clipping path and the new
609 clipping path, and all drawing will be done within the outline of the
612 <p>The outline of the clipping path is defined with the nonzero
613 winding rule, as with
<a href='#fill-path'
><tt>FILL-PATH
</tt></a>.
615 <p>There is no way to enlarge the clipping path. However, the clipping
616 path is part of the graphics state, so changes may be localized by
617 using
<a href='#with-graphics-state'
><tt>WITH-GRAPHICS-STATE
</tt></a>.
622 <td><img src=
"clip-unclipped.png"></td>
623 <td>A filled red rectangle, not clipped
</td>
626 <td><img src=
"clip-to-circle.png"></td>
627 <td>The same rectangle drawn with a circle clipping path in effect
</td>
630 <td><img src=
"clip-to-rectangle.png"></td>
631 <td>Clipped to a rounded rectangle clipping path
</td>
634 <td><img src=
"clip-to-both.png"></td>
635 <td>Clipped to the intersection of the circle and rounded rectangle clipping paths
</td>
644 <p><a name='even-odd-clip-path'
>[Function]
</a><br>
645 <b>even-odd-clip-path
</b> =
> |
648 Like
<a href='#clip-path'
><tt>CLIP-PATH
</tt></a>, but uses the
649 even/odd fill rule to determine the outline of the clipping path.
653 <a name='sect-paths'
><h4>Paths
</h4></a>
655 <p>Paths are used to create lines for stroking or outlines for
656 filling. Paths consist of straight lines and curves. Paths consist of
657 one or more subpaths.
659 <p><a name='move-to'
>[Function]
</a><br>
660 <b>move-to
</b> <i>x
</i> <i>y
</i> =
> |
663 Starts a new subpath at (
<i>x
</i>,
<i>y
</i>).
<tt>move-to
</tt> must be the
664 first step of constructing a subpath.
668 <p><a name='line-to'
>[Function]
</a><br>
669 <b>line-to
</b> <i>x
</i> <i>y
</i> =
> |
672 Appends a straight line ending at (
<i>x
</i>,
<i>y
</i>) to the
677 <p><a name='curve-to'
>[Function]
</a><br>
679 <i>cx1
</i> <i>cy1
</i>
680 <i>cx2
</i> <i>cy2
</i>
681 <i>x
</i> <i>y
</i> =
> |
685 cubic
<a href=
"http://en.wikipedia.org/wiki/B%C3%A9zier_curve">B
ézier
686 curve
</a> ending at (
<i>x
</i>,
<i>y
</i>) and with control
687 points (
<i>cx1
</i>,
<i>cy1
</i>) and (
<i>cx2
</i>,
<i>cy2
</i>) to the current
692 <p><a name='quadratic-to'
>[Function]
</a><br>
695 <i>x
</i> <i>y
</i> =
> |
698 Appends a quadratic B
ézier curve ending at (
<i>x
</i>,
<i>y
</i>)
699 and with the control point (
<i>cx
</i>,
<i>cy
</i>) to the current
704 <p><a name='arc'
>[Function]
</a><br>
705 <b>arc
</b> <i>x
</i> <i>y
</i> <i>radius
</i> <i>angle1
</i> <i>angle2
</i>
709 Appends an arc of a circle to the current path. The center of the arc is
710 at (
<i>x
</i>,
<i>y
</i>). The arc begins at point at a
711 distance
<i>radius
</i> from the center and with an angle
<i>angle1
</i>
712 radians from the positive x axis, and ends at the point
713 with
<i>angle2
</i> radians. If
<i>angle2
</i> is less
714 than
<i>angle1
</i>, it is increased by increasing multiples of
2π
715 until it is greater than or equal to
<i>angle1
</i>.
717 <p><table cellpadding=
5>
718 <tr><td align=center
><img src=
"arc.png"></td></tr>
719 <tr><td><span style='color: #
0f0'
><i>radius
</i></span>,
720 <span style='color: #f00'
><i>angle1
</i></span>,
721 <span style='color: #
00f'
><i>angle2
</i></span></td></tr>
724 <p>If there is a current point, a straight line is added from the
725 current point to the start point of the arc. Otherwise, a new path
728 <pre><img class='transparent' style='float: right' src='pie-wedge.png'
729 >(defun pie-wedge (file)
730 (with-canvas (:width
80 :height
60)
733 (angle1 (* (/ pi
180)
15))
734 (angle2 (* (/ pi
180)
45)))
738 (arc x y radius angle1 angle2)
746 <p><a name='arcn'
>[Function]
</a><br>
747 <b>arcn
</b> <i>x
</i> <i>y
</i> <i>radius
</i> <i>angle1
</i> <i>angle2
</i>
751 Like
<a href='#arc'
><tt>ARC
</tt></a>, but draws the arc clockwise
752 instead of counterclockwise. If
<i>angle2
</i> is greater
753 than
<i>angle1
</i>, it is decreased by increasing multiples of
2π
754 until it is less than or equal to
<i>angle1
</i>.
756 <pre><img class='transparent' style='float: right' src='wiper.png'
758 (with-canvas (:width
70 :height
70)
762 (angle2 (* (/ pi
180)
90)))
764 (set-rgba-fill
1 1 1 0.75)
765 (arc x y r1 angle1 angle2)
766 (arcn x y r2 angle2 angle1)
773 <p><a name='ellipse-arc'
>[Function]
</a><br>
774 <b>ellipse-arc
</b> <i>cx
</i> <i>cy
</i> <i>radius-x
</i> <i>radius-y
</i>
775 <i>rotation-angle
</i> <i>angle1
</i> <i>angle2
</i> =
> |
778 Like
<a href='#arc'
><tt>ARC
</TT></a>, but draws an arc from an
779 ellipse. The arc is drawn counterclockwise.
783 <p><a name='ellipse-arcn'
>[Function]
</a><br>
784 <b>ellipse-arcn
</b> <i>cx
</i> <i>cy
</i> <i>radius-x
</i> <i>radius-y
</i>
785 <i>rotation-angle
</i> <i>angle1
</i> <i>angle2
</i> =
> |
788 Like
<a href='#ellipse-arcn'
><tt>ELLIPSE-ARCN
</TT></a>, but draws the
793 <p><a name='close-subpath'
>[Function]
</a><br>
794 <b>close-subpath
</b> =
> |
797 Closes the current subpath. If the current point is not the same as the
798 starting point for the subpath, appends a straight line from the
799 current point to the starting point of the current subpath.
801 <p>Subpaths with start and end points that coincidentally overlap are
802 not the same as closed subpaths. The distinction is important when
805 <p><table cellpadding=
5>
807 <td align=center
><img src=
"open-subpath.png"></td>
808 <td align=center
><img src=
"closed-subpath.png"></td>
811 <td align=center
>Open subpath
</td>
812 <td align=center
>Closed subpath
</td>
816 <p>If the subpath is not closed, the start and points of the subpath
817 will be drawn with the current line cap style. If the path is
818 closed, the start and endpoints will be treated as joined and drawn
819 with the line join style.
823 <p><a name='stroke-to-paths'
>[Function]
</a><br>
824 <b>stroke-to-paths
</b> =
> |
827 Sets the current active paths to the paths that would result from
828 outlining a
<a href='#stroke'
><tt>STROKE
</tt></a> operation.
832 <p><a name='rectangle'
>[Function]
</a><br>
833 <b>rectangle
</b> <i>x
</i> <i>y
</i> <i>width
</i> <i>height
</i> =
> |
836 Creates a rectangular subpath with the given
<i>width
</i>
837 and
<i>height
</i> that has its lower-left corner at
838 (
<i>x
</i>,
<i>y
</i>). It is effectively the same as:
842 (line-to (+ x width) y)
843 (line-to (+ x width) (+ y height))
844 (line-to x (+ y height))
849 <p><a name='rounded-rectangle'
>[Function]
</a><br>
850 <b>rounded-rectangle
</b> <i>x
</i> <i>y
</i>
851 <i>width
</i> <i>height
</i> <i>rx
</i> <i>ry
</i> =
> |
854 Like
<a href='#rectangle'
><tt>RECTANGLE
</tt></a>, but rounds the
855 corners of the rectangle paths by the x radius
<i>rx
</i> and the y
859 <p><a name='centered-ellipse-path'
>[Function]
</a><br>
860 <b>centered-ellipse-path
</b>
865 Adds a closed subpath that outlines an ellipse centered at
866 (
<i>x
</i>,
<i>y
</i>) with an X radius of
<i>rx
</i> and a Y radius
870 <p><a name='centered-circle-path'
>[Function]
</a><br>
871 <b>centered-circle-path
</b> <i>x
</i> <i>y
</i> <i>radius
</i> =
> |
874 Adds a closed subpath that outlines a circle centered at
875 (
<i>x
</i>,
<i>y
</i>) with a radius of
<i>radius
</i>. It is effectively
879 (centered-ellipse-path x y radius radius)
885 <a name='sect-painting'
><h4>Painting
</h4></a>
887 <p>After a path is defined, filling, stroking, or both will use the
888 path to apply color to the canvas. After a path has been filled or
889 stroked, it is no longer active; it effectively disappears.
892 <p><a name='fill-path'
>[Function]
</a><br>
893 <b>fill-path
</b> =
> |
896 Fills the current path with the fill color or gradient. If the path
897 has not been explicitly closed
898 with
<a href='#close-subpath'
><tt>CLOSE-SUBPATH
</tt></a>, it is
899 implicitly closed before filling. The non-zero winding rule is used
900 to determine what areas are considered inside the path.
904 <p><a name='even-odd-fill'
>[Function]
</a><br>
905 <b>even-odd-fill
</b> =
> |
908 The same as
<a href='#fill-path'
><tt>FILL-PATH
</tt></a>, but uses the
909 even/odd rule to determine what areas are considered inside the path.
913 <p><a name='stroke'
>[Function]
</a><br>
917 Strokes the current path. The line width, stroke color, line join
918 style, line cap style, and dash pattern and phase determine how the
919 stroked path will appear on the canvas.
923 <p><a name='fill-and-stroke'
>[Function]
</a><br>
924 <b>fill-and-stroke
</b> =
> |
927 Fills the current path, then strokes it.
931 <p><a name='even-odd-fill-and-stroke'
>[Function]
</a><br>
932 <b>even-odd-fill-and-stroke
</b> =
> |
935 Fills the current path using the even/odd rule, then strokes it.
939 <p><a name='end-path-no-op'
>[Function]
</a><br>
940 <b>end-path-no-op
</b> =
> |
943 Ends the current path without painting anything. If a clipping path
944 has been specified with
<a href='#clip-path'
><tt>CLIP-PATH
</tt></a>
945 or
<a href='#even-odd-clip-path'
><tt>EVEN-ODD-CLIP-PATH
</tt></a>, it
946 will be created by
<tt>end-path-no-op
</tt>.
951 <a name='sect-text'
><h4>Text
</h4></a>
953 <p>Vecto can draw text to a canvas. It loads glyph shapes from
955 with
<a href=
"http://www.xach.com/lisp/zpb-ttf/">ZPB-TTF
</a>.
957 <p><a name='get-font'
>[Function]
</a><br>
958 <b>get-font
</b> <i>font-file
</i> =
> <i>font-loader
</i>
961 Creates and returns a ZPB-TTF font loader object
962 from
<i>font-file
</i>. Any font loader created this way will
963 automatically be closed at the end of its
964 enclosing
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a> form.
968 <p><a name='set-font'
>[Function]
</a><br>
969 <b>set-font
</b> <i>font-loader
</i> <i>size
</i> =
> |
972 Sets the active font to the font associated
973 with
<i>font-loader
</i>, scaled to
<i>size
</i> units per line.
975 <p>The first argument can be any ZPB-TTF font loader; it need not be
976 created via
<a href='#get-font'
><tt>GET-FONT
</tt></a>. However, only
977 font loaders created via
<tt>GET-FONT
</tt> will be automatically
978 closed at the end of
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a>.
982 <p><a name='set-character-spacing'
>[Function]
</a><br>
983 <b>set-character-spacing
</b> <i>spacing
</i> =
> |
986 Sets the scale of the spacing used between characters when drawing
987 text with
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a> and related
990 <p>Normally, the character spacing for drawing text is taken directly
991 from a font's advance-width and kerning
992 metrics.
<tt>SET-CHARACTER-SPACING
</tt> can be used to adjust this
993 spacing; for example, a character spacing of
2.0d0 would double the
994 normal space between characters, and
0.5d0 would halve it.
997 <p><a name='*default-character-spacing*'
>[Special variable]
</a><br>
998 <b>*default-character-spacing*
</b>
1001 The default scale for character spacing when drawing text
1002 with
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a> and related
1003 functions. Initial value is
1.0d0.
1005 <p>Changes to this variable affect the
1006 next
<a href='#with-canvas'
><tt>WITH-CANVAS
</tt></a> form. To affect
1007 the spacing within the current
<tt>WITH-CANVAS
</tt> form,
1008 use
<a href='#set-character-spacing'
><tt>SET-CHARACTER-SPACING
</tt></a>.
1012 <p><a name='draw-string'
>[Function]
</a><br>
1013 <b>draw-string
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1016 Draws
<i>string
</i> on the canvas with the active font. The glyph
1017 origin of the first character in the string is positioned at
<i>x
</i>
1018 and the baseline of the string is positioned at
<i>y
</i>. The text is
1019 filled with the current
<a href='#set-rgba-fill'
>fill color
</a>.
1021 <p>The string may be a specialized vector of characters (a true CL
1022 string) or a vector containing characters, Unicode code-points, or both. For
1023 example,
<tt>#(#\L #\a #\m #\b #\d #\a #\= #x3BB)
</tt> is a valid
1024 argument for
<tt>DRAW-STRING
</tt>.
1026 <p>The horizontal space between characters is determined by the
1027 advance-width and kerning metrics of the font, then multiplied by
1028 the current character spacing. At the default character spacing of
1029 1.0d0, the spacing is not adjusted at
1030 all.
<a href='#set-character-spacing'
><tt>SET-CHARACTER-SPACING
</tt></a>
1031 can be used to increase or decrease the character spacing.
1035 <p><a name='string-paths'
>[Function]
</a><br>
1036 <b>string-paths
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1039 Like
<a href='#draw-string'
><tt>DRAW-STRING
</tt></a>, but instead of
1040 drawing the text, adds the subpaths that make up the string glyphs to
1041 the graphics state. This can be used to stroke, fill, or clip based on
1042 the outlines of a string.
1046 <p><a name='draw-centered-string'
>[Function]
</a><br>
1047 <b>draw-centered-string
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1050 Draws
<i>string
</i> on the canvas with the active font. The horizontal
1051 center of the string is positioned at
<i>x
</i> and the baseline of the
1052 string is positioned at
<i>y
</i>.
1056 <p><a name='centered-string-paths'
>[Function]
</a><br>
1057 <b>centered-string-paths
</b> <i>x
</i> <i>y
</i> <i>string
</i> =
> |
1060 Like
<a href='#draw-centered-string'
><tt>DRAW-CENTERED-STRING
</tt></a>,
1061 but adds subpaths instead of painting. See
1062 also
<a href='#string-paths'
><tt>STRING-PATHS
</tt></a>.
1066 <p><a name='string-bounding-box'
>[Function]
</a><br>
1067 <b>string-bounding-box
</b> <i>string
</i> <i>size
</i> <i>loader
</i>
1068 =
> <i>#(xmin ymin xmax ymax)
</i>
1071 Calculates the bounding box of
<i>string
</i> for
<i>font-loader
</i>
1076 <a name='sect-miscellaneous'
><h3>Miscellaneous
</h3></a>
1078 <p><a name='const-kappa'
>[Constant]
</a><br>
1079 <b>+kappa+
</b> =
> 0.5522847498307936d0.
1082 This constant is useful to draw portions of a circle.
1086 <a name='sect-references'
><h2>References
</h2></a>
1089 <li> Adobe Systems Inc.,
<a href=
"http://www.adobe.com/devnet/pdf/pdf_reference.html">PDF Reference, Sixth Edition, Version
1.7</a>
1090 <li> Lawrence Kesteloot,
<a href=
"http://www.teamten.com/lawrence/graphics/premultiplication/">Alpha Premultiplication
</a>
1091 <li> Dr. Thomas Sederberg,
<a href=
"http://www.tsplines.com/resources/class_notes/Bezier_curves.pdf">B
ézier curves
</a>
1092 <li> Alvy Ray Smith,
<a href=
"http://alvyray.com/Memos/MemosMicrosoft.htm#ImageCompositing">Image Compositing Fundamentals
</a>
1093 <li> G. Adam Stanislav,
<a href=
"http://www.whizkidtech.redprince.net/bezier/circle/">Drawing a circle with B
ézier curves
</a>
1094 <li> Alexander Thomas,
<a href=
"http://www.dr-lex.be/random/matrix_inv.html">The Inverse and Determinants of
2x2 and
3x3 Matrices
</a>
1095 <li> Wikipedia,
<a href=
"http://en.wikipedia.org/wiki/B%C3%A9zier_curve">B
ézier curve
</a>
1100 <a name='sect-acknowledgements'
><h2>Acknowledgements
</h2></a>
1102 <p>Many thanks to
<a href=
"http://www.elbeno.com/">Ben Deane
</a> for
1103 permission to adapt code from his curve library for drawing arcs.
1105 <p>Ryan Davis helped fix my adaptation of the arc drawing.
1107 <a name='sect-feedback'
><h2>Feedback
</h2></a>
1109 <p>If you have any questions, comments, bug reports, or other feedback
1110 regarding Vecto, please email
<a href=
"mailto:xach@xach.com">Zach