summaryrefslogtreecommitdiff
path: root/doc/picture-language.texi
blob: da697bf8066cfa13dda3468abfc35489f966f5eb (about) (plain)
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
\input texinfo
@c -*-texinfo-*-

@c %**start of header
@setfilename picture-language.info
@documentencoding UTF-8
@settitle Guile Picture Language Reference Manual
@c %**end of header

@include version.texi

@copying
Copyright @copyright{} 2019 Ricardo Wurmus@*

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
copy of the license is included in the section entitled ``GNU Free
Documentation License''.
@end copying

@dircategory The Algorithmic Language Scheme
@direntry
* Guile Picture Language: (picture-language).   Compose pictures with Guile.
@end direntry

@titlepage
@title Guile Picture Language Reference Manual
@subtitle Composing pictures with Guile
@author Ricardo Wurmus

@page
@vskip 0pt plus 1filll
Edition @value{EDITION} @*
@value{UPDATED} @*

@insertcopying
@end titlepage

@contents

@c *********************************************************************
@node Top
@top Guile Picture Language

This document describes the Guile Picture Language version
@value{VERSION}, a simple language to compose shapes and pictures using
vector graphics.

@menu
* Introduction::                What is this all about?
* Installation::                Installing the picture language.
* A Picture Vocabulary::        Learning to speak the language.

* Acknowledgments::             Thanks!
* GNU Free Documentation License::  The license of this manual.
* Concept Index::               Concepts.
* Programming Index::           Data types, functions, and variables.
@end menu

@c *********************************************************************
@node Introduction
@chapter Introduction

This package provides a Guile library containing simple procedures to
generate primitive shapes, to manipulate them, and to compose them to
build complex pictures.  While this library could be used to
procedurally generate images, it is really meant to be used
interactively.

Pictures in this language are first class values like numbers or
strings, so they are displayed as actual pictures, not as text.  We
suggest using Guile Studio to play with the picture language, as it
comes with everything you need to play with the picture language
interactively.  You can jump straight to @xref{A Picture Vocabulary} and
follow along.

If you aren't using Guile Studio you will probably want to use a
graphical instance of Emacs and set up Geiser for use with Guile.


@c *********************************************************************
@node Installation
@chapter Installation

The easiest way to install the Picture Language is through GNU Guix.

@example
guix install guile-picture-language
@end example

If you cannot use Guix or want to build it manually from a release
tarball, just unpack it and run the usual GNU build system commands:

@example
./configure
make
make install
@end example

If you want to build the sources from the source repository you need to
bootstrap the build system first.  Run the @code{bootstrap.sh} script
first and then perform the above steps.

Once installed you should make sure that the @code{GUILE_LOAD_PATH}
includes the directory containing this library.  Start a Guile REPL with
Geiser and load up the module with @code{,use(pict)}.  If everything
went well read on to learn how to use the picture language.

If you're getting errors feel free to write email to the Guile user
mailing list @email{guile-user@@gnu.org}, or ask for help on the
@code{#guile} IRC channel on the Freenode network.

@c *********************************************************************
@node A Picture Vocabulary
@chapter A Picture Vocabulary

The goal of the picture language is to allow you to interactively work
with pictures as you would with any other seemingly primitive data
type, such as numbers or strings of text.  To compose numbers we
combine the digits 0 to 9.  Similarly, strings of text are composed of
a wide range of characters enclosed in double quotes.  What, then, are
the building blocks of pictures?

One approach is to think of a picture as an arrangement of little
colored dots or pixels.  Building pictures from dots, however, would be
rather tedious and dull.  It would not be a very expressive language.
Another approach is to start with a small set of simple shapes that can
be modified and combined.  Let's first take a look at the different
kinds of simple shapes that make up the ``nouns'' of our picture
language vocabulary.

@menu
* Simple shapes::  The ``nouns'' of our picture language.
* Modifiers::      Procedures for modifying pictures.
* Combinators::    Build large pictures from smaller pictures.
@end menu

@c *********************************************************************
@node Simple shapes
@section Simple shapes

@cindex line, simple shape
@deffn {Scheme Procedure} line @
  @var{x1} @var{y1} @var{x2} @var{y2} @
  [@var{maxw} @var{maxh} @
  #:color @var{"black"} #:stroke-width @var{1}]

Return a straight line connecting the start point described by the
numbers @var{X1} and @var{Y1} and the end point described by the numbers
@var{X2} and @var{Y2}.  Optionally, the numbers @var{MAXW} and
@var{MAXH} can be provided to limit the width or height, respectively,
of the resulting picture.  The keys @var{COLOR} (a string) and
@var{STROKE-WIDTH} (a number) are accepted to override the line color
and line thickness, respectively.
@end deffn

@cindex line, example
@lisp
@verbatiminclude images/line.svg.scm
@end lisp
@indentedblock
@image{images/line.svg.scm,,,A straight line.}
@end indentedblock

@cindex hline, simple shape
@deffn {Scheme Procedure} hline @
  @var{w} @var{h} @
  [#:color @var{"black"} #:stroke-width @var{1}]
  
Return a horizontal line segment of width @var{W}.  The bounding box
height is @var{H} and the line is drawn in the vertical center of the
bounding box.  The keys @var{COLOR} (a string) and @var{STROKE-WIDTH} (a
number) are accepted to override the line color and line thickness.
@end deffn

@cindex hline, example
@lisp
@verbatiminclude images/hline.svg.scm
@end lisp
@indentedblock
@image{images/hline.svg.scm,,,A horizontal line.}
@end indentedblock

@cindex vline, simple shape
@deffn {Scheme Procedure} vline @
  @var{w} @var{h} @
  [#:color @var{"black"} #:stroke-width @var{1}]

Return a vertical line segment of height @var{H}.  The bounding box
width is @var{W} and the line is drawn in the horizontal center of the
bounding box.  The keys @var{COLOR} (a string) and @var{STROKE-WIDTH} (a
number) are accepted to override the line color and line thickness.
@end deffn

@cindex vline, example
@lisp
@verbatiminclude images/vline.svg.scm
@end lisp
@indentedblock
@image{images/vline.svg.scm,,,A vertical line.}
@end indentedblock

@cindex polyline, simple shape
@deffn {Scheme Procedure} polyline @
  @var{points} @
  [#:color @var{"black"} #:stroke-width @var{1}]

A polyline is a multi-segment line that is drawn through any number of
points.  This procedure draws a polyline from @var{POINTS}, a list of x
and y coordinate pairs.  The keys @var{COLOR} (a string) and
@var{STROKE-WIDTH} (a number) are accepted to override the line color
and line thickness.
@end deffn

@cindex polyline, example
Here is a simple zig zag line:
@lisp
@verbatiminclude images/polyline.svg.scm
@end lisp
@indentedblock
@image{images/polyline.svg.scm,,,A zig zag polyline.}
@end indentedblock

Of course, you could also compute the points.  Here we use @code{iota}
and @code{list-tabulate} of the @code{(srfi srfi-1)} module to generate
a list for increasing X coordinates and a list for alternating Y
coordinates before merging them to a single list of coordinate pairs
with @code{map} and @code{cons}:

@lisp
@verbatiminclude images/polyline2.svg.scm
@end lisp
@indentedblock
@image{images/polyline2.svg.scm,,,A longer zig zag polyline.}
@end indentedblock

@cindex polygon, simple shape
@deffn {Scheme Procedure} polygon @
  @var{points} @
  [#:border-color @var{"black"} #:border-width @var{1}]

The @code{polygon} procedure has almost the exact same behavior as
@code{polyline}, except that it connects the first point and the last
point with a line segment.  @code{polyline}, on the other hand, leaves
the two points unconnected.

This procedure draws a line through @var{POINTS}, a list of x and y
coordinate pairs, connecting the first and last points.  The keys
@var{BORDER-COLOR} (a string) and @var{BORDER-WIDTH} (a number) are
accepted to override the line color and line thickness.
@end deffn

@cindex polygon, example
Here is a simple polygon:
@lisp
@verbatiminclude images/polygon.svg.scm
@end lisp
@indentedblock
@image{images/polygon.svg.scm,,,A polygon.}
@end indentedblock

@cindex triangle, simple shape
@deffn {Scheme Procedure} triangle @
  @var{W} @var{H} @
  [#:border-color @var{"black"} #:border-width @var{1}]

This procedure draws an isosceles triangle with width @var{W} and
height @var{H}.  The keys @var{BORDER-COLOR} (a string) and
@var{BORDER-WIDTH} (a number) are accepted to override the line color
and line thickness.
@end deffn

@cindex triangle, example
Here is a simple triangle:
@lisp
@verbatiminclude images/triangle.svg.scm
@end lisp
@indentedblock
@image{images/triangle.svg.scm,,,A triangle.}
@end indentedblock

@cindex filled-triangle, simple shape
@deffn {Scheme Procedure} filled-triangle @
  @var{W} @var{H} @
  [#:color @var{"black"}]

This procedure draws a triangle just like the @code{triangle}
procedure, except that it does not have an outline and is filled with
the provided @var{COLOR}.
@end deffn


@cindex octagon, simple shape
@deffn {Scheme Procedure} octagon @
  @var{SIZE} @
  [#:border-color @var{"black"} #:border-width @var{1}]

This procedure draws a p8 symmetric isogonal octagon with a maximum
width of @var{SIZE}.  The keys @var{BORDER-COLOR} (a string) and
@var{BORDER-WIDTH} (a number) are accepted to override the line color
and line thickness.
@end deffn

@cindex octagon, example
Here is a simple octagon:
@lisp
@verbatiminclude images/octagon.svg.scm
@end lisp
@indentedblock
@image{images/octagon.svg.scm,,,An octagon.}
@end indentedblock

@cindex filled-octagon, simple shape
@deffn {Scheme Procedure} filled-octagon @
  @var{SIZE} @
  [#:color @var{"black"}]

This procedure draws an octagon just like the @code{octagon}
procedure, except that it does not have an outline and is filled with
the provided @var{COLOR}.
@end deffn


@cindex circle, simple shape
@deffn {Scheme Procedure} circle @
  @var{SIZE} @
  [#:border-color @var{"black"} #:border-width @var{1}]

This procedure draws a circle with an outer diameter of @var{SIZE}.
The keys @var{BORDER-COLOR} (a string) and @var{BORDER-WIDTH} (a
number) are accepted to override the line color and line thickness.
@end deffn

@cindex circle, example
Here is a simple circle:
@lisp
@verbatiminclude images/circle.svg.scm
@end lisp
@indentedblock
@image{images/circle.svg.scm,,,A circle.}
@end indentedblock

@cindex disk, simple shape
@deffn {Scheme Procedure} disk @
  @var{SIZE} @
  [#:color @var{"black"}]

A disk is a filled circle.  This procedure draws a disk with the outer
diameter @var{SIZE}.  It's just like the output of the @code{circle}
procedure, except that it does not have an outline and is filled with
the provided @var{COLOR}.
@end deffn


@cindex ellipse, simple shape
@deffn {Scheme Procedure} ellipse @
  @var{W} @var{H} @
  [#:border-color @var{"black"} #:border-width @var{1}]

This procedure draws an ellipse with width @var{W} and height @var{H}.
The keys @var{BORDER-COLOR} (a string) and @var{BORDER-WIDTH} (a
number) are accepted to override the line color and line thickness.
@end deffn

@cindex ellipse, example
Here is a simple ellipse:
@lisp
@verbatiminclude images/ellipse.svg.scm
@end lisp
@indentedblock
@image{images/ellipse.svg.scm,,,An ellipse.}
@end indentedblock

@cindex filled-ellipse, simple shape
@deffn {Scheme Procedure} filled-ellipse @
  @var{W} @var{H} @
  [#:color @var{"black"}]

This procedure draws a filled ellipse.  It's just like the ellipse
drawn by the @code{ellipse} procedure, except that it does not have an
outline and is filled with the provided @var{COLOR}.
@end deffn


@cindex rectangle, simple shape
@deffn {Scheme Procedure} rectangle @
  @var{W} @var{H} @
  [#:border-color @var{"black"} #:border-width @var{1} #:rx @var{0} #:ry @var{0}]

This procedure draws a rectangle with width @var{W} and height
@var{H}.  The keys @var{BORDER-COLOR} (a string) and
@var{BORDER-WIDTH} (a number) are accepted to override the line color
and line thickness.  The keys @var{RX} and @var{RY} (both numbers) can
be provided to round off the corners.
@end deffn

@cindex rectangle, example
Here is a simple rectangle with rounded corners:
@lisp
@verbatiminclude images/rectangle.svg.scm
@end lisp
@indentedblock
@image{images/rectangle.svg.scm,,,A rectangle with rounded corners.}
@end indentedblock

@cindex filled-rectangle, simple shape
@deffn {Scheme Procedure} filled-rectangle @
  @var{W} @var{H} @
  [#:color @var{"black"} #:border-color @var{"none"} #:border-width @var{1} #:rx @var{0} #:ry @var{0}]

This procedure draws a filled rectangle.  It's just like the rectangle
drawn by the @code{rectangle} procedure, except that it does not have
an outline and is filled with the provided @var{COLOR}.
@end deffn


@cindex text, simple shape
@deffn {Scheme Procedure} text @
  @var{TXT} @
  [#:color @var{"black"} #:font-family @var{"sans-serif"} #:font-size @var{32} @
  #:font-style @var{"normal"} #:font-weight @var{"normal"}]

This procedure renders the text @var{TXT}.  The height of the text is
always a full line height, which depends on the selected
@var{FONT-FAMILY} and is generally larger than the provided
@var{FONT-SIZE}.  The keys @var{FONT-STYLE} (a string),
@var{FONT-WEIGHT} (a string), and @var{COLOR} (also a string) are
also accepted.
@end deffn

@cindex text, example
Here are a few snippets of text, combined horizontally (see below).
@lisp
@verbatiminclude images/text.svg.scm
@end lisp
@indentedblock
@image{images/text.svg.scm,,,A few snippets of text.}
@end indentedblock

@c *********************************************************************
@node Modifiers
@section Modifiers

Imagine you have a list of ten identical triangles: all with the same
size and the same color.  Boring, isn't it?  Perhaps it was easier to
produce them all alike.  Perhaps it was done like this:

@lisp
@verbatiminclude images/boring-triangles.svg.scm
@end lisp
@indentedblock
@image{images/boring-triangles.svg.scm,,,A boring list of triangles.}
@end indentedblock

Luckily, we have a wide range of modifiers to change the properties of
existing pictures, including the fill color, the border color, the
orientation, the transparency, and even the properties of the bounding
box.

@cindex modifiers, example
Here's a preview of what we can do to the boring triangles:

@lisp
@verbatiminclude images/modifiers.svg.scm
@end lisp
@indentedblock
@image{images/modifiers.svg.scm,,,A less boring list of triangles.}
@end indentedblock

Much better!

The following modifiers exist and still need to be documented:
@code{fill}, @code{colorize}, @code{remove-outline}, @code{rotate},
@code{scale}, @code{expand}, @code{grow}, @code{shrink}, @code{blur},
@code{cellophane}, @code{frame}, and @code{ghost}.

@c *********************************************************************
@node Combinators
@section Combinators

Now that we have learned about simple shapes we can generate lines and
shapes with different colors and dimensions, and with modifiers we can
scale them up or rotate them, but we still cannot compose complex
pictures that consist of more than just one shape.  To compose and
arrange shapes we need combinators: procedures that operate on pictures
and return new pictures.

Combinators cannot only be used on simple shapes but also on complex
pictures.  This is what makes them very powerful.  For example, we can
combine circles, lines, and ellipses to build a picture of a flower.  We
can then take this picture of a flower, duplicate and scale it a hundred
times, and then combine these pictures to a new picture of a meadow.
This picture of a meadow can be duplicated, the duplicates tinted and
arranged as a pop art print.  The picture of a pop art print can be
duplicated and arranged as a wall in an art gallery...

The following combinators exist and still need to be documented:
@code{append-align}, @code{ht-append}, @code{hc-append},
@code{hb-append}, @code{vl-append}, @code{vc-append}, @code{vr-append},
@code{lt-superimpose}, @code{lc-superimpose}, @code{lb-superimpose},
@code{ct-superimpose}, @code{cc-superimpose}, @code{cb-superimpose},
@code{rt-superimpose}, @code{rc-superimpose}, @code{rb-superimpose},
@code{pin-over}, and @code{pin-under}.

@c *********************************************************************
@node Acknowledgments
@chapter Acknowledgments

Thanks to the following people who contributed to the Picture Language
through bug reports, patches, ideas, encouragement, or suggestions:

@itemize @bullet
@item Ludovic Courtès @email{ludo@@gnu.org}
@item Christine Lemmer-Webber @email{cwebber@@dustycloud.org}
@end itemize

Thank you.

@c *********************************************************************
@node GNU Free Documentation License
@appendix GNU Free Documentation License

@include fdl-1.3.texi

@page

@c *********************************************************************
@node Concept Index
@unnumbered Concept Index

@printindex cp

@node Programming Index
@unnumbered Programming Index
@syncodeindex tp fn
@syncodeindex vr fn
@printindex fn

@bye