     [file version.texi not included]

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''.

Guile Picture Language
**********************

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

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 see 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.

Installation
************

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

     guix install guile-picture-language

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:

     ./configure
     make
     make install

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

Once installed you should make sure that the GUILE_LOAD_PATH includes the directory containing this library.  Start a Guile REPL with Geiser and load up the module with ,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 guile-user@gnu.org, or ask for help on the #guile IRC channel on the Freenode network.

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 in an we use the digits 0 to 9.  Similarly, strings of text compose 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.

Simple shapes
=============

 -- Scheme Procedure: line
     X1 Y1 X2 Y2
     [MAXW MAXH
     #:color "BLACK" #:stroke-width 1]

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

          [file line.svg.scm not included]
     A straight line.

 -- Scheme Procedure: hline
     W H
     [#:color "BLACK" #:stroke-width 1]

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

          [file hline.svg.scm not included]
     A horizontal line.

 -- Scheme Procedure: vline
     W H
     [#:color "BLACK" #:stroke-width 1]

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

          [file vline.svg.scm not included]
     A vertical line.

 -- Scheme Procedure: polyline
     POINTS
     [#:color "BLACK" #:stroke-width 1]

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

Here is a simple zig zag line:

          [file polyline.svg.scm not included]
     A zig zag polyline.

Of course, you could also compute the points.  Here we use iota and list-tabulate of the (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 map and cons:

          [file polyline2.svg.scm not included]
     A longer zig zag polyline.

 -- Scheme Procedure: polygon
     POINTS
     [#:border-color "BLACK" #:border-width 1]

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

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

Here is a simple polygon:

          [file polygon.svg.scm not included]
     A polygon.

 -- Scheme Procedure: triangle
     W H
     [#:border-color "BLACK" #:border-width 1]

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

Here is a simple triangle:

          [file triangle.svg.scm not included]
     A triangle.

 -- Scheme Procedure: filled-triangle
     W H
     [#:color "BLACK"]

     This procedure draws a triangle just like the triangle procedure, except that it does not have an outline and is filled with the provided COLOR.

 -- Scheme Procedure: octagon
     SIZE
     [#:border-color "BLACK" #:border-width 1]

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

Here is a simple octagon:

          [file octagon.svg.scm not included]
     An octagon.

 -- Scheme Procedure: filled-octagon
     SIZE
     [#:color "BLACK"]

     This procedure draws an octagon just like the octagon procedure, except that it does not have an outline and is filled with the provided COLOR.

 -- Scheme Procedure: circle
     SIZE
     [#:border-color "BLACK" #:border-width 1]

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

Here is a simple circle:

          [file circle.svg.scm not included]
     A circle.

 -- Scheme Procedure: disk
     SIZE
     [#:color "BLACK"]

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

 -- Scheme Procedure: ellipse
     W H
     [#:border-color "BLACK" #:border-width 1]

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

Here is a simple ellipse:

          [file ellipse.svg.scm not included]
     An ellipse.

 -- Scheme Procedure: filled-ellipse
     W H
     [#:color "BLACK"]

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

 -- Scheme Procedure: rectangle
     W H
     [#:border-color "BLACK" #:border-width 1 #:rx 0 #:ry 0]

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

Here is a simple rectangle with rounded corners:

          [file rectangle.svg.scm not included]
     A rectangle with rounded corners.

 -- Scheme Procedure: filled-rectangle
     W H
     [#:color "BLACK" #:border-color "NONE" #:border-width 1 #:rx 0 #:ry 0]

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

 -- Scheme Procedure: text
     TXT
     [#:color "BLACK" #:font-family "SANS-SERIF" #:font-size 32
     #:font-style "NORMAL" #:font-weight "NORMAL"]

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

Here are a few snippets of text, combined horizontally (see below).

          [file text.svg.scm not included]
     A few snippets of text.

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:

          [file boring-triangles.svg.scm not included]
     A boring list of triangles.

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.

Here's a preview of what we can do to the boring triangles:

          [file modifiers.svg.scm not included]
     A less boring list of triangles.

Much better!

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

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: append-align, ht-append, hc-append, hb-append, vl-append, vc-append, vr-append, lt-superimpose, lc-superimpose, lb-superimpose, ct-superimpose, cc-superimpose, cb-superimpose, rt-superimpose, rc-superimpose, rb-superimpose, pin-over, and pin-under.

Acknowledgments
***************

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

  * Ludovic Courtès ludo@gnu.org

  * Christopher Lemmer Webber cwebber@dustycloud.org

Thank you.

GNU Free Documentation License
******************************

     [file fdl-1.3.texi not included]