From 16782604a861d173a5bf8abbb8a8b298a2641550 Mon Sep 17 00:00:00 2001 From: James Clark Date: Fri, 15 Aug 1997 07:55:45 -0500 Subject: [PATCH] groff before CVS: release 1.11 The tarball from which this was unpacked was labeled "1.11a". --- ChangeLog | 7 + INSTALL | 2 +- NEWS | 17 + PROJECTS | 9 +- README | 7 +- VERSION | 2 +- doc/Makefile | 11 +- doc/pic.ms | 2433 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ groff/groff.man | 3 + 9 files changed, 2479 insertions(+), 12 deletions(-) create mode 100644 doc/pic.ms diff --git a/ChangeLog b/ChangeLog index 872c759a..9d91424e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Fri Aug 15 08:51:47 1997 Eric S. Raymond + + * README, PROJECTS, NEWS, INSTALL, VERSION, + doc/Makefile. doc/pic.ms, groff/groff.man: + Prepare for 1.11 release. No code changes. + Documentation for pic added (doc/pic.ms). + Sun Nov 26 11:45:13 1995 James Clark * Version 1.10 released. diff --git a/INSTALL b/INSTALL index 639b9134..ceb3e6a7 100644 --- a/INSTALL +++ b/INSTALL @@ -16,7 +16,7 @@ usual malloc, it is good idea to include it in LIBS. For example, using the malloc that comes with GNU Emacs version 18 can give a worthwhile (and sometimes spectacular) performance improvement. -When you have build groff, you can use the test-groff script to try +When you have built groff, you can use the test-groff script to try groff out on one of the man pages. (Use the .n files not the .man files.) The test-groff script sets up environment variables to allow groff to run without being installed. The current directory must be diff --git a/NEWS b/NEWS index 0e0e1fca..e1df82e1 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,23 @@ This file describes recent user-visible changes in groff. Bug fixes are not described. There are more details in the man pages. +VERSION 1.11 +============ + +James Clark has written (11 Aug 1997): +>Frankly I don't known when I'm going to be able to do another groff +>release. At the moment, I have no time, no Unix machine, and not a lot +>of interest in doing it. If anybody else wants to take over groff +>maintenance, that would be fine with me. Last time I asked in +>gnu.groff.bug, nobody volunteered. + +This means groff is an orphan. It is looking for a maintainer. + +Complete documentation for pic is now in the file doc/pic.ms. It was +contributed by Eric S. Raymond, , who is emphatically +*not* volunteering to take over groff as he is way overworked with +half a dozen other projects. + VERSION 1.10 ============ diff --git a/PROJECTS b/PROJECTS index 1691e032..535d8b46 100644 --- a/PROJECTS +++ b/PROJECTS @@ -11,7 +11,10 @@ Here are some things that would be useful additions to groff: a complete, self-contained manual (trent@cs.pdx.edu is working on this) -If you want to work on one of these, I suggest you contact me first. +If you want to work on one of these, you should probably post to +gnu.groff.bug to see if anyone else has gotten there first. + +As of August 1997 groff lacks a maintainer. If you are seriously interested +in these projects, perhaps you should volunteer. + -James Clark -jjc@jclark.com diff --git a/README b/README index bd288421..5ea82bc4 100644 --- a/README +++ b/README @@ -26,11 +26,10 @@ The most recent released version of groff is always available by anonymous ftp from prep.ai.mit.edu in the directory pub/gnu. Please report bugs using the form in the file BUG-REPORT; the idea of -this is to make sure that I have all the information I need to fix the +this is to make sure that FSF has all the information it needs to fix the bug. At the very least, read the BUG-REPORT form and make sure that you supply all the information that it asks for. Even if you are not sure that something is a bug, report it using BUG-REPORT: this will -enable me to determine whether it really is a bug or not. +enable us to determine whether it really is a bug or not. -James Clark -jjc@jclark.com +GNU groff was written by James Clark . diff --git a/VERSION b/VERSION index c044b1a3..09601587 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.10 +1.11 diff --git a/doc/Makefile b/doc/Makefile index 563f0be7..4c56aa38 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -20,13 +20,13 @@ FFLAG=-F.. TROFF=../troff/troff -M../tmac $(FFLAG) GROPS=../grops/grops $(FFLAG) -DOCS=meref.PS meintro.PS +DOCS=meref.PS meintro.PS pic.PS MEMACROS=../macros/tmac.e SOELIM=../soelim/soelim all: $(DOCS) -.SUFFIXES: .tr .me .PS .dit +.SUFFIXES: .tr .me .ms .PS .dit .dit.PS: $(GROPS) $< >$@ @@ -42,8 +42,13 @@ all: $(DOCS) meref.PS: meref.dit meintro.PS: meintro.dit +# This production must use -p -e -t so pic/eqn processing is done +pic.PS: pic.ms + sed $< -e "s;@VERSION@;`cat ../VERSION`;" \ + | ../groff/groff -p -e -t -Tps $(FFLAG) -ms >$@ + install: - + clean: -rm -f *.PS *.dit core diff --git a/doc/pic.ms b/doc/pic.ms new file mode 100644 index 00000000..59dcc08c --- /dev/null +++ b/doc/pic.ms @@ -0,0 +1,2433 @@ +.\" For tolerably obvious reason, this needs to be processed through PIC. +.\" It also needs to be processed through TBL and EQN. Use "groff -p -e -t". +.\" There is no hope that this will ever look right under nroff. +.\" +.\" Comments beginning with %% are cut lines so portions of this + \" document can be automatically extracted. %%TUTORIAL%% begins the +.\" tutorial part; %%REFERENCE%% the reference part. %%POSTLUDE%% the + \" bibliography and end matter after the reference part. +.\" +.\" This document was written for free use and redistribution by +.\" Eric S. Raymond in August 1995. +.\" +.\" $Id: pic.ms,v 1.27 1997/07/03 17:35:39 esr Exp $ +.\" +.\" Set a proper TeX +.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X +.el .ds tx TeX +.\" +.de CE\" Centered caption for figure. Assumes previous .KS +.ce 1 +Figure \\n(H1-\\$1 +.sp 1 +.KE +.. +.\" Definitions end here +.TL +Making Pictures With GNU PIC +.AU +Eric S. Raymond +.AI + +.AB +The \fBpic\fP language is a \fBtroff\fP extension that makes it easy +to create and alter box-and-arrow diagrams of the kind frequently used +in technical papers and textbooks. This paper is both an introduction +to and reference for \fIgpic\fP(1), the implementation distributed by +the Free Software Foundation for use with \fIgroff\fP(1). +.AE +.\"%%TUTORIAL%% +.NH 1 +Introduction to PIC +.NH 2 +Why PIC? +.PP +The \fBpic\fP language provides an easy way to write procedural +box-and-arrow diagrams to be included in \fBtroff\fP documents. The +language is sufficiently flexible to be quite useful for state charts, +Petri-net diagrams, flow charts, simple circuit schematics, jumper +layouts, and other kinds of illustration involving repetitive uses of +simple geometric forms and splines. Because these descriptions are +procedural and object-based, they are both compact and easy to modify. +.PP +The \fIgpic\fP(1) implementation of \fBpic\fP is distributed by the +Free Software Foundation for use with their \fIgroff\fP(1) +implementation of \fBtroff\fP. Because both implementations are +widely available in source form for free, they are good bets for +writing very portable documentation. +.NH 2 +PIC Versions +.PP +The original 1984 pre-\fIditroff\fP(1) version of \fBpic\fP is long +obsolete. The rewritten 1991 version is still available as part of +the Documenter's Work Bench module of System V. +.PP +Where differences between Documenter's Work Bench (1991) \fBpic\fP and GNU +\fBpic\fP need to be described, original \fBpic\fP is referred to as +"DWB pic". Details on the history of the program are given at the end +of this document. +.PP +In this document, the \fIgpic\fP(1) extensions will be marked as such. +.NH 1 +Invoking PIC +.PP +Every \fBpic\fP description is a little program, which gets compiled +by \fIpic\fP(1) into \fIgtroff\fP(1) macros. Programs that process or +display \fIgtroff\fP(1) output need not know or care that parts of the +image began life as \fBpic\fP descriptions. +.PP +The \fIpic\fP(1) program tries to translate anything between \fB.PS\fP +and \fB.PE\fP markers, and passes through everything else. The normal +definitions of \fB.PS\fP and \fB.PE\fP in the \fIms\fP macro package +and elsewhere have also the side-effect of centering the \fBpic\fP output +on the page. +.PP +Other details of the \fI[gt]roff\fP(1) interface +.NH 2 +PIC Error Messages +.PP +If you make a \fBpic\fP syntax error, \fIgpic\fP(1) will issue an +error message in the standard \fIgcc\fP(1)-like syntax. A typical +error message looks like this, +.KS +.DS +.CW +pic:pic.ms:: parse error before `' +pic:pic.ms:: giving up on this picture +.DE +.R +.KE +.LP +where is a line number, and is a token near (usually +just after) the error location. +.NH 1 +Basic PIC Concepts +.PP +Pictures are described procedurally, as collections of objects +connected by motions. Normally, \fBpic\fP tries to string together +objects left-to-right in the sequence they are described, joining them +at visually natural points. Here is an example illustrating the +flow of data in \fBpic\fP processing: +.KS +.PS +ellipse "document"; +arrow; +box "\fIgpic\fP(1)" +arrow; +box width 1.2 "\fIgtbl\fP(1) or \fIgeqn\fP(1)" "(optional)" dashed; +arrow; +box "\fIgtroff\fP(1)"; +arrow; +ellipse "PostScript" +.PE +.CE "1: Flow of \fBpic\fP data" +.PP +This was produced from the following \fBpic\fP program: +.KS +.DS +.CW +\&.PS +\&ellipse "document"; +\&arrow; +\&box "\\fIpic\\fP(1)" +\&arrow; +\&box width 1.2 "\\fIgtbl\\fP(1) or \\fIgeqn\\fP(1)" "(optional)" dashed; +\&arrow; +\&box "\\fIgtroff\\fP(1)"; +\&arrow; +\&ellipse "PostScript" +\&.PE +.DE +.R +.KE +.LP +This little program illustrates several \fBpic\fP basics. Firstly, we +see how to invoke three object types; ellipses, arrows, and boxes. We +see how to declare text lines to go within an object (and that text +can have font changes in it). We see how to change the line style of +an object from solid to dashed. And we see that a box can be made +wider than its default size to accommodate more text (we'll discuss +this facility in detail in the next section). +.PP +We also get to see \fBpic\fP's simple syntax. Statements are ended by +newlines or semicolons. String quotes are required around all text +arguments, whether or not they contain spaces. In general, the order +of command arguments and modifiers like "width 1.2" or "dashed" doesn't +matter, except that the order of text arguments is significant. +.PP +Here are all but one of the basic \fBpic\fP objects at their default sizes: +.KS +.PS +box "box"; +move; +line "line" ""; +move; +arrow "arrow" ""; +move; +circle "circle"; +move; +ellipse "ellipse"; +move; +arc; down; move; "arc" +.PE +.CE "2: Basic \fBpic\fP objects" +.PP +The missing simple object type is a \fIspline\fP. There is also a way +to collect objects into \fIblock composites\fP which allows you to +treat the whole group as a single object (resembling a box) for many +purposes. We'll describe both of these later on. +.PP +The box, ellipse, circle, and block composite objects are \fIclosed\fR; +lines, arrows, arcs and splines are \fIopen\fP. This distinction +will often be important in explaining command modifiers. +.PP +Figure \n[H1]-2 was produced by the following \fBpic\fP program, +which introduces some more basic concepts: +.KS +.DS +.CW +\&.PS +\&box "box"; +\&move; +\&line "line" ""; +\&move; +\&arrow "arrow" ""; +\&move; +\&circle "circle"; +\&move; +\&ellipse "ellipse"; +\&move; +\&arc; down; move; "arc" +\&.PE +.DE +.ft R +.KE +.PP +The first thing to notice is the \fImove\fP command, which moves a +default distance (1/2 inch) in the current movement direction. +.PP +Secondly, see how we can also decorate lines and arrows with text. +The line and arrow commands each take two arguments here, specifying +text to go above and below the object. If you wonder why one argument +would not do, contemplate the output of \fBarrow "ow!"\fP: +.KS +.PS +arrow "ow!" +.PE +.CE "3: Text centered on an arrow" +.PP +When a command takes one text string, \fBpic\fP tries to place it at +the object's geometric center. As you add more strings, \fBpic\fP +treats them as a vertical block to be centered. The program +.KS +.DS +.CW +line "1"; +line "1" "2"; +line "1" "2" "3"; +line "1" "2" "3" "4"; +line "1" "2" "3" "4" "5"; +.DE +.ft R +.KE +.LP +for example, gives you this: +.KS +.sp 2 +.PS +line "1"; +line "1" "2"; +line "1" "2" "3"; +line "1" "2" "3" "4"; +line "1" "2" "3" "4" "5"; +.PE +.sp 2 +.CE "4: Effects of multiple text arguments" +.PP +The last line of Figure 3.2's program, `\fBarc; down; move; +"arc"\fP', describing the captioned arc, introduces several new ideas. +Firstly, we see how to change the direction in which objects are +joined. Had we written \fBarc; move; "arc"\fP, +omitting \fBdown\fP the caption would have been joined to the top +of the arc, like this: +.KS +.PS +arc; move; "arc"; +.PE +.CE "5: Result of \fBarc; move; \"arc\"\fP" +.PP +This is because drawing an arc changes the default direction to the +one its exit end points at. To reinforce this point, consider: +.KS +.PS +arc cw; move; "arc"; +.PE +.CE "6: Result of \fBarc cw; move; \"arc\"\fP" +.PP +All we've done differently here is specify "cw" for a clockwise arc. +Observe how it changes the default direction to down, rather than up. +.PP +Another good way to see this via with the following program: +.KS +.DS +.CW +line; arc; arc cw; line +.DE +.ft R +.KE +.LP +which yields: +.KS +.PS +line; arc; arc cw; line; +.PE +.CE "7: Result of \fBline; arc; arc cw; line\fP" +.LP +Notice that we did not have to specify "up" for the second arc to be +joined to the end of the first. +.PP +Finally, observe that a string, alone, is treated as text to be +surrounded by an invisible box of a size either specified by width +and height attributes or by the defaults \fBtextwid\fR and +\fBtextht\fR. Both are initially zero (because we don't know the +default font size). +.NH 1 +Sizes and Spacing +.PP +Sizes are specified in inches. If you don't like inches, it's +possible to set a global style variable \fBscale\fP that changes the +unit. Setting \fBscale = 2.54\fP will effectively change the internal +unit to centimeters (all other size variable valuess will be scaled +correspondingly). +.NH 2 Default Sizes of Objects +.PP +Here are the default sizes for \fBpic\fP objects: +.RS +.KS +.TS +tab(@), linesize(2); +lb | lb +l | l. +.sp 2p +Object@Default Size +.sp 2p +_ +.sp 2p +box@0.75" wide by 0.5" high +circle@0.5" diameter +ellipse@0.75" wide by 0.5" high +arc@0.5" radius +line@0.5" long +arrow@0.5" long +.sp 5p +_ +.TE +.KE +.RE +.PP +The simplest way to think about these defaults is that they make the +other basic objects fit snugly into a default-sized box. +.NH 2 +Objects Do Not Stretch! +.PP +Text is rendered in the current font with normal troff line spacing. +Boxes, circles, and ellipses do \fInot\fP automatically resize to fit +enclosed text. Thus, if you say \fBbox "text far too long"\fP +you'll get this: +.KS +.PS +box "this text is far too long for a default box" +.PE +.CE "1: Boxes do not automatically resize" +.PP +which is probably not the effect you want. +.NH 2 +Resizing Boxes +.PP +To change the box size, you can specify a box width with the "width" +modifier: +.KS +.PS +box width 3 "this text is far too long for a default box" +.PE +.CE "2: Result of \fBbox width 3 \"text far too long\"\fP" +.PP +This modifier takes a dimension in inches. There is also a "height" +modifier that will change a box's height. The \fBwidth\fP keyword may +be abbreviated to \fBewid\fP; the \fBheight\fP keyword to +\fBheight\fP. +.NH 2 +Resizing Other Object Types +.PP +To change the size of a circle, give it a \fBrad\fP or \fBdiam\fP +modifier; this changes the radius or diameter of the circle, according +to the numeric argument that follows. +.KS +.PS +{circle rad 0.1; move down 0.2 from last circle .s; "0.1"}; +move; circle rad 0.2 "0.2"; move; circle rad 0.3 "0.3"; +.PE +.CE "3: Circles with increasing radii" +.PP +The \fBmove\fP command can also take a dimension, which just tells +it how many inches to move in the current direction. +.PP +Ellipses are sized to fit in the rectangular box defined by their +axes, and can be resized with \fBwidth\fP and \fBheight\fP like boxes. +.PP +You can also change the radius of curvature of an arc with \fBrad\fP +(which specifies the radius of the circle of which the arc is a segnmment). +Larger values yield flatter arcs. +.KS +.PS +{arc rad 0.1; move down 0.3 from last arc .center; "0.1"}; +move; +{arc rad 0.2; move down 0.4 from last arc .center; "0.2"}; +move; +{arc rad 0.3; move down 0.5 from last arc .center; "0.3"}; +.PE +.CE "4: \fBarc rad\fP with increasing radii" +.PP +Observe that because an arc is defined as a quarter circle, increasing +the radius also increases the size of the arc's bounding box. +.NH 2 +The `same' Keyword +.PP +In place of a dimension specification, you can use the keyword +\fBsame\fR. This gives the object the same size as the previous one +of its type. As an example, the program +.KS +.DS +.CW +\&.PS +\&box; box wid 1 ht 1; box same; box +\&.PE +.R +.DE +.KE +.LP +gives you +.KS +.PS +box; box wid 1 ht 1; box same; box +.PE +.CE "5: The \fBsame\fP keyword" + +.NH 1 +Generalized Lines and Splines +.NH 2 +Diagonal Lines +.PP +It is possible to specify diagonal lines or arrows by adding multiple \fBup\fP, +\fBdown\fP, \fBleft\fP, and \fBright\fP modifiers to the line object. +Any of these can have a multiplier. To understand the effects, think +of the drawing area as being gridded with standard-sized boxes. +.KS +.PS +# Draw a demonstration up left arrow with grid box overlay +define gridarrow +{ + [ + {arrow up left $1;} + box wid 0.5 ht 0.5 dotted with .nw at last arrow .end; + for i = 2 to ($1 / 0.5) do + { + box wid 0.5 ht 0.5 dotted with .sw at last box .se; + } + move down from last arrow .center; + [ + if ( $1 == boxht ) then { "\fBline up left\fP" } else { sprintf("\fBarrow up left %g\fP", $1) }; + ] + ] + move right from last [] .e; +} +gridarrow(0.5); +gridarrow(1); +gridarrow(1.5); +gridarrow(2); +undef gridarrow +.PE +.CE "1: Diagonal arrows (dotted boxes show the implied 0.5-inch grid)" +.NH 2 +Multi-Segment Line Objects +.PP +A "line" or "arrow" object may actually be a path consisting of any number of +segments of varying lengths and directions. To describe a path, +connect several line or arrow commands with the keyword \fBthen\fP. +.KS +.PS +define zigzag { $1 right 1 then down .5 left 1 then right 1 } +zigzag(line); +.PE +.CE "2: \fBline right 1 then down .5 left 1 then right 1\fP" +.NH 2 +Spline Objects +.PP +If you start a path with the \fBspline\fP keyword, the path vertices +are treated as control points for a spline curve fit. +.KS +.PS +[zigzag(spline);] +move down 0.2 from last [] .s; +"The spline curve..." +move right from last [] .e; +[ + zigzag(line dashed); + spline from start of last line right 1 then down .5 left 1 then right 1; + "1" at last spline .start + (-0.1, 0); + "2" at last spline .start + (1.1, 0); + "3" at last spline .end + (-1.1, 0); + "4" at last spline .end + (0.1, 0); +] +move down 0.2 from last [] .s; +"...with tangents displayed" +undef zigzag; +.PE +.CE "3: \fBspline right 1 then down .5 left 1 then right 1\fP" +.PP +You can describe many natural-looking but irregular curves this +way. For example: +.KS +.PS +[spline right then up then left then down ->;] +move down 0.2 from last [] .s; +["\fBspline right then up then left then down ->;\fP"] +move right 3 from last [] .se; +"\fBspline left then up right then down right ->;\fP" +move up 0.2; +[spline left then up right then down right ->;] +.PE +.CE "4: Two more spline examples" +.PP +Note the arrow decorations. Arrowheads can be applied naturally to +any path-based object, line or spline. We'll see how in the next +section. +.NH 1 +Decorating Objects. +.NH 2 +Dashed Objects +.PP +We've already seen that the modifier \fBdashed\fP can change the line +style of an object from solid to dashed. GNU \fBgpic\fP permits you to +dot or dash ellipses, circles, and arcs (and splines in \(*tx mode +only); some versions of DWB may only permit dashing of lines and +boxes. It's possible to change the dash interval by specifying a +number after the modifier. +.PP +.KS +.PS +box dashed "default"; +move; +box dashed 0.05 "0.05"; +move; +box dashed 0.1 "0.1"; +move; +box dashed 0.15 "0.15"; +move; +box dashed 0.2 "0.2"; +.PE +.CE "1: Dashed objects" +.NH 2 +Dotted Objects +.PP +Another available qualifier is \fBdotted\fP. GNU \fBgpic\fP permits +you to dot or dash ellipses, circles, and arcs (and splines in \(*tx +mode only); some versions of DWB may only permit dashing of lines and +boxes. It too can be suffixed with a number to specify the interval +between dots: +.KS +.PS +box dotted "default"; +move; +box dotted 0.05 "0.05"; +move; +box dotted 0.1 "0.1"; +move; +box dotted 0.15 "0.15"; +move; +box dotted 0.2 "0.2"; +.PE +.CE "2: Dotted objects" +.NH 2 +Rounding Box Corners +.PP +It is also possible, in GNU \fBgpic\fP only, to modify a box so it has +rounded corners +.KS +.PS +box rad 0.05 "rad 0.05"; +move; +box rad 0.1 "rad 0.1"; +move; +box rad 0.15 "rad=0.15"; +move; +box rad 0.2 "rad=0.2"; +move; +box rad 0.25 "rad=0.25"; +.PE +.CE "3: \fBbox rad\fP with increasing radius values;" +.PP +Radius values higher than half the minimum box dimension are silently +truncated to that value. +.NH 2 +Arrowheads +.PP +Lines and arcs can be decorated as well. Any line or arc (and any +spline as well) can be decorated with arrowheads by adding one or more +as modifiers: +.KS +.PS +line <- -> +.PE +.CE "4: Double-headed line made with \fBline <- ->\fP" +.PP +In fact, the \fBarrow\fP command is just shorthand for \fBline ->\fP. And +there is a double-head modifier <->, so the figure above could have been made +with \fCWline <->\fP. +.PP +Arrowheads have a \fBwidth\fP attribute, the distance across the rear; +and a \fBheight\fP attribute, the length of the arrowhead along the shaft. +.PP +Arrowhead style is controlled by the style variable \fBarrowhead\fP. +The DWB and GNU versions interpret it differently. DWB defaults to +open arrowheads and an \fBarrowhead\fP value of 2; the Kernighan +paper says a value of 7 will make solid arrowheads. GNU \fBgpic\fP +defaults to solid arrowheads and an \fBarrowhead\fP value of 1; a +value of 0 will produce open arrowheads. +.NH 2 +Line Thickness +.PP +It's also possible to change the line thickness of an object (this is +a GNU extension, DWB \fBpic\fP doesn't support it.). +The default thickness of the lines used to draw objects is controlled by the +.B linethick +variable. +This gives the thickness of lines in points. +A negative value means use the default thickness: +in \(*tx output mode, this means use a thickness of 8 milliinches; +in \(*tx output mode with the +.B -c +option, this means use the line thickness specified by +.B .ps +lines; in troff output mode, this means use a thickness proportional +to the pointsize. A zero value means draw the thinnest possible line +supported by the output device. Initially it has a value of -1. +There is also a \fBthickness\fP attribute (which can be abbreviated to +\fBthick\fP). For example, \fBcircle thickness 1.5\fP would draw a +circle using a line with a thickness of 1.5 points. The thickness of +lines is not affected by the value of the +.B scale +variable, nor by any width or height given in the +.B .PS +line. +.NH 2 +Invisible Objects +.PP +The modifier \fBinvis\fP makes an object entirely invisible. This +used to be useful for positioning text in an invisible object that is +properly joined to neighboring ones. Newer DWB versions and GNU +\fBpic\fP treat standalone text in exactly this way. +.NH 2 +Filled Objects +.PP +It is possible to fill boxes, circles, and ellipses. The +modifier \fBfill[ed]\fP accomplishes this. You can suffix it with a fill +value; the default is given by the stule variable \fBfillval\fP. +.PP +DWB \fBpic\fP and \fBgpic\fP have opposite conventions for fill values +and different defaults. DWB \fBfillval\fP defaults to 0.3 and smaller +values are darker; GNU \fBfillval\fP uses 0 for white and 1 for black. +.KS +.PS +circle fill; move; circle fill 0.4; move; circle fill 0.2; +.PE +.CE "5: \fBcircle fill; move; circle fill 0.4; move; circle fill 0.9;\fB" +.PP +GNU \fBgpic\fP makes some additional guarantees. A fill value greater +than 1 can also be used: this means fill with the shade of gray that +is currently being used for text and lines. Normally this will be +black, but output devices may provide a mechanism for changing this. +The invisible attribute does not affect the filling of objects. Any +text associated with a filled object will be added after the object +has been filled, so that the text will not be obscured by the filling. +.PP +The closed-object modifier \fBsolid\fR is equivalent to \fBfill\fR +with the darkest fill value (DWB \fBpic\fR had this capability but +mentioned it only in a reference opinion). +.NH 1 +More About Text Placement +.PP +By default, text is centered at the geometric center of the object it is +associated with. The modifier \fBljust\fR causes the left end to be +at the specified point (which means that the text lies to the right of +the specified place!), The modifier \fBrjust\fP puts the right end at +the place. The modifiers \fBabove\fP and \fBbelow\fP center the text +one half line space in the given direction. +.PP +Text attributes can be combined: +.KS +.PS +[line up "ljust text" ljust;] +move 1.5; +[line up "rjust text" rjust;] +move; +[arrow 1 "ljust above" ljust above;] +move; +[arrow 1 "rjust below" rjust below;] +.PE +.CE "1: Text attributes" +.PP +What actually happens is that n text strings are centered in a box +that is \fBtextwid\fP wide by \fBtextht\fP high. Both these variables +are initially zero (that is \fBpic\fR's way of not making assumptions +about \fI[tg]roff\fP(1)'s default point size). +.PP +In GNU \fBgpic\fR, objects can have an +.B aligned +attribute. +This will only work when the postprocessor is +\fBgrops\fP. +Any text associated with an object having the +.B aligned +attribute will be rotated about the center of the object +so that it is aligned in the direction from the start point +to the end point of the object. +Note that this attribute will have no effect for objects whose start and +end points are coincident. +.NH 1 +More About Direction Changes +.PP +We've already seen how to change the direction in which objects are +composed from rightwards to downwards. Here are some more +illustrative examples: +.KS +.PS +down; +[ + "\fBright; box; arrow; circle; arrow; ellipse\fP"; + move 0.2; + [right; box; arrow; circle; arrow; ellipse;] +] +move down 0.3 from last [] .s; +[ + "\fBleft; box; arrow; circle; arrow; ellipse\fP" + move 0.2; + [left; box; arrow; circle; arrow; ellipse;] +] +# move down 0.3 from last [] .sw; +# To re-join this illustrations, delete everything from here down to +# the next #-comment, and uncomment the move line above +.PE +.CE "1: Effects of different motion directions (right and left)" +.KS +.PS +# To re-join this illustrations, delete everything down to here, then +# comment out the next `down' line. +# Don't forget to re-number the figures following! +down; +[ + "\fBdown; box; arrow; circle; arrow; ellipse;\fP" + move 0.2; + box; arrow; circle; arrow; ellipse; +] +move right 2 from last [] .e; +[ + up; box; arrow; circle; arrow; ellipse; + move 0.2; + "\fBup; box; arrow; circle; arrow; ellipse;\fP" +] +.PE +.CE "2: Effects of different motion directions (up and down)" +.PP +Something that may appear surprising happens if you change directions +in the obvious way: +.KS +.PS +box; arrow; circle; down; arrow; ellipse +.PE +.CE "3: \fBbox; arrow; circle; down; arrow; ellipse\fP +.LP +You might have expected that program to yield this: +.KS +.PS +box; arrow; circle; move to last circle .s; down; arrow; ellipse +.PE +.CE "4: More intuitive? +.LP +But, in fact, to get Figure \*[SN]3 you have to do this: +.KS +.DS +.CW +\&.PS +box; +arrow; +circle; +move to last circle .s; +down; +arrow; +ellipse +\&.PE +.R +.DE +.KE +Why is this? Because the exit point for the current direction is +already set when you draw the object. The second arrow in Figure +\*[SN]2 dropped downwards from the circle's attachment point for an +object to be joined to the right. +.PP +The meaning of the command \fBmove to last circle .s\fP should be obvious. +In order to see how it generalizes, we'll need to go into detail on two +important topics; locations and object names. +.NH 1 +Naming Objects +.PP +The most natural way to name locations in \fBpic\fP is relative to +objects. In order to do this, you have to be able you have to be able +to name objects. The \fBpic\fP language has rich facilities for this +that try to emulate the syntax of English. +.NH 2 +Naming Objects By Order Of Drawing +.PP +The simplest (and generally the most useful) way to name an object is +with a \fBlast\fP clause. It needs to be followed by an object type +name; \fBbox\fP, \fBcircle\fP, \fBellipse\fP, \fBline\fP, \fBarrow\fP, +\fBspline\fP or \fB[]\fP (the last type refers to a \fIcomposite +object\fP which we'll discuss later). So, for example, the \fBlast +circle\fP clause in the program attached to Figure \*[SN]3 refers to the +last circle drawn. +.PP +More generally, objects of a given type are implicitly numbered +(starting from 1). You can refer to (say) the third ellipse in the +current picture with \fB3rd ellipse\fP, or to the first box as \fB1st +box\fP, or to the fifth line as \fB5th line\fP. +.PP +Objects are also numbered backwards by type from the last one of +You can say \fB2nd last box\fP to get the second-to-last box, or +\fB3rd last ellipse\fP to get the third-to-last box. +.PP +In places where \fIn\fBth\fP is allowed, \fB`\fIexpr\fB'th\fP is also allowed. +Note that +.B 'th +is a single token: no space is allowed between the +.B ' +and the \fBth\fP. +For example, +.IP +.KS +.R +.DS +for i = 1 to 4 do { + line from `i'th box.nw to `i+1'th box.se +} +.R +.DE +.KE +.NH 2 +Naming Objects With Labels +.PP +You can also specify an object by referring to a label. A label is a +word (which must begin with a capital letter) followed by a colon; +you declare it by placing it immediately before the object drawing command. +For example, the program +.KS +.DS +.CW +\&.PS +A: box "first" "object" +move; +B: ellipse "second" "object" +move; +arrow left at A; +\&.PE +.R +.DE +.KE +.LP +declares labels \fBA\fP and \fBB\fP for its first and second objects. +Here's what that looks like: +.KS +.PS +A: box "first" "object" +move; +B: ellipse "second" "object" +move; +arrow left at A .l; +.PE +.CE "1: Example of label use" +The \fBat\fP statement in the fourth line uses the label \fBA\fP (the +behavior of \fBat\fP will be explained in the next section). We'll +see later on that labels are most useful for referring to block composite +objects. +.PP +Labels are not constants but variables (you can view colon as a sort +of assignment). You can say something like \fBA: A + (1,0);\fP +and the effect will be to reassign the label \fBA\fR to designate a +position one inch to the right of its old value. +.NH 1 +Describing locations +.PP +The location of points can be described in many different ways. All these +forms are interchangeable as for as the \fBpic\fP language syntax is +concerned; where you can use one, any of the others that would make +semantic sense are allowed. +.PP +The special label \fBHere\fR always refers to the current position. +.NH 2 +Absolute Coordinates +.PP +The simplest is absolute coordinates in inches; \fBpic\fP uses a +Cartesian system with (0, 0) at the lower left corner of the virtual +drawing surface for each picture (that is, X increases to the right +and Y increases upwards). An absolute location may always be written in the +conventional form as two comma-separated numbers surrounded by +parentheses (and this is recommended for clarity). In contexts where +it creates no ambiguity, the pair of X and Y coordinates suffices +without punctuation. +.PP +It is a good idea to avoid absolute coordinates, however. They tend +to make picture descriptions difficult to understand and modify. +Instead, there are quite a number of ways to specify locations +relative to \fBpic\fP objects and previous locations. +.PP +.NH 2 +Locations Relative to Objects +.PP +The symbol \fBhere\fP always refers to the position of the last object +drawn or the destination of the last \fBmove\fP. +.PP +Alone and unqualified, a \fBlast circle\fP or any other way of +specifying a closed-object or arc location refers as a position to the +geometric center of the object. Unqualified, the name of a line or +spline object refers to the position of the object start. +.PP +Also, \fBpic\fP objects have quite a few named locations +associated with them. One of these is the object center, which can be +indicated (redundantly) with the suffix \fB.center\fP (or just \fB.c\fP). +Thus, \fBlast circle \&.center\fP is equivalent to \fBlast +circle\fP. +.NH 3 +Locations Relative to Closed Objects +.PP +Every closed object (box, circle, ellipse, or block composite) also +has eight compass points associated with it; +.KS +.PS +define dot {circle fill rad 0.02 at $1} + +define compass { [ + ME: $1; + dot(ME.c); "\fB .c\fP" at ME .c ljust; + dot(ME.n); "\fB.n\fP" at ME .n above + dot(ME.ne); "\fB .ne\fP" at ME .ne above + dot(ME.e); "\fB .e\fP" at ME .e ljust + dot(ME.se); "\fB .se\fP" at ME .se below + dot(ME.s); "\fB.s\fP" at ME .s below + dot(ME.sw); "\fB.sw \fP" at ME .sw below + dot(ME.w); "\fB.w \fP" at ME .w rjust + dot(ME.nw); "\fB.nw \fP" at ME .nw above +] } +compass(box wid 1.5 ht 1); +move right from last [] .e; +compass(circle diam 1); +move right from last [] .e; +compass(ellipse wid 1.5 ht 1); +.PE +.CE "1: Compass points" +.LP +these are the locations where eight compass rays from the geometric center +would intersect the figure. So when we say \fBlast circle .s\fP we are +referring to the south compass point of the last circle drawn. The +explanation of Figure 7.3's program is now complete. +.PP +(In case you dislike compass points, the names \fB.top\fP, +\&\fB.bottom\fP, \fB.left\fP and \fB.right\fP are synonyms for \fB.n\fP, +\&\fB.s\fP, \fB.e\fP, and \fB.w\fP respectively; they can even be +abbreviated to \fB.t\fP, \fB.b\fP, \fB.l\fP and \fB.r\fP). +.PP +The names \fBcenter\fP, \fBtop\fP, \fBbottom\fP, \fBleft\fP and +\fBright\fP can also be used (without the leading dot) in a prefix +form marked by \fBof\fP; thus, \fPcenter of last circle\fB and +\fBtop of 2nd last ellipse\fP are both valid object references. +.PP +Arc objects also have compass point; they are the compass points of +the implied circle. +.NH 3 +Locations Relative to Open Objects +.PP +Every open object (line, arrow, arc, or spline) has three named +points; \fB.start\fP, \fB.center\fP, and \fB.end\fP. They can +also be used without leading dots in the \fBof\fP prefix form. +The center of an arc is the center of its circle, but the center of +a line, path, or spline is halfway between its endpoints. +.KS +.PS +define critical { + [ ME: $1; + dot(ME.c); ".center" rjust at ME.center + (-0.1, 0.1) + dot(ME.start); ".start" rjust at ME.start + (-0.1, 0.1) + dot(ME.end); ".end" rjust at ME.end + (-0.1, 0.1) + ] + move down 0.2 from last [] .s; +} +critical(line up right 1); +move right from last [] .e; +critical(arc rad 0.5 cw); +move right from last [] .e; +critical(line right 1 then down .5 left 1 then right 1); +move right from last [] .e; +critical(spline right 1 then up right then left then left 1); +.PE +.CE "2: Special points on open objects" +.PP +.NH 2 +Ways of Composing Positions +.PP +Once you have two positions to work with, there are several ways to +combine them to specify new positions. +.NH 3 +Vector Sums and Displacements +.PP +Any two positions may be added or subtracted to yield a new position. +The result is the conventional vector sum or difference of coordinates. +For example, \fBlast box .ne + (0.1, 0)\fP is a valid position. This +example illustrates a common use, to define a position slightly offset +from a named one (say, for captioning purposes). +.NH 3 +Interpolation Between Positions +.PP +A position may be interpolated between any two positions. The syntax +is `\fIfraction\fP \fBof the way between\fP \fIposition1\fP \fBand\fP +\fIposition2\fP.' For example, you can say \fB1/3 of the way between +here and last ellipse .ne\fP. The fraction may be in +numerator/denominator form or may be an ordinary number (values are +\&\fInot\fP restricted to [0,1]). As an alternative to this verbose +syntax, you can say `\fIfraction\fP \fB<\fP\fIposition1\fP \fB,\fP +\fIposition2\fP\fB>\fP.'; thus, the example could also be written +\fB1/3\fP \fP. +.KS +.PS +arrow up right; +P: 1/3 of the way between last arrow .start and last arrow .end; +dot(P); move right 0.1; "P"; +.PE +.CE "3: \fBP: 1/3 of the way between last arrow .start and last arrow .end\fP" +.PP +This facility can be used, for example, to double connections. +.KS +.PS +A: box "yin"; move; B: box "yang"; +arrow right at 1/4 ; +arrow left at 1/4 ; +.PE +.CE "4: Doubled arrows" +.LP +You can get Figure \n[H1]-4 from the following program: +.KS +.DS +.CW +\&.PS +A: box "yin"; move; +B: box "yang"; +arrow right at 1/4 ; +arrow left at 1/4 ; +\&.PE +.R +.DE +.KE +.LP +Note the use of the short form for interpolating points. +.NH 3 +Projections of Points +.PP +Given two positions \fIp\fP and \fIq\fP, the position +\fB(\fP\fIp\fP\fB,\fP \fIq\fP\fB)\fP has the X coordinate of \fIp\fP +and the Y coordinate of \fIq\fP. This can be helpful in placing an +object at one of the corners of the virtual box defined by two other +objects. +.KS +.PS +box invis wid 2 height 1; +dot(last box .ne); "\fB(B,A)\fB is here" ljust at last circle + (0.1, 0.1); +dot(last box .se); "B" ljust at last circle + (0.1, -0.1) +dot(last box .sw); "\fB(A,B)\fB is here" rjust at last circle + (-0.1, -0.1); +dot(last box .nw); "A" ljust at last circle + (-0.1, 0.1) +.PE +.CE "5: Using (\fIx\fP, \fIy\fP) composition" +.NH 2 +Using Locations +.PP +There are four ways to use locations; \fBat\fP, \fBfrom\fP, \fBto\fP, +and \fBwith\fP. All three are object modifiers; that is, you use them +as suffixes to a drawing command. +.PP +The \fBat\fP modifier says to draw a closed object or arc with its +center at the following location, or to draw a line/spline/arrow +starting at the following location. +.PP +The \fBto\fP modifier can be used alone to specify a move destination. +The \fBfrom\fP modifier can be used alone in the same way as \fBat\fP. +.PP +The \fBfrom\fP and \fBto\fP modifiers can be used with a \fBline\fR or +\fBarc\fR command to specify start and end points of the object. In +conjunction with named locations, this offers a very flexible +mechanism for connecting objects. For example, the following program +.KS +.DS +.CW +\&.PS +box "from" +move 0.75; +ellipse "to" +arc cw from 1/3 of the way \\ + between last box .n and last box .ne to last ellipse .n; +\&.PE +.R +.DE +.KE +.LP +yields: +.KS +.PS +box "from" +move 0.75; +ellipse "to" +arc cw from 1/3 of the way between last box .n and last box .ne to last ellipse .n; +.PE +.CE "6: A tricky connection specified with English-like syntax" +.PP +The \fBwith\fP modifier allows you to identify a named attachment +point of an object with another point. This is very useful for connecting +objects in a natural way. For an example, consider these two programs: +.KS +.PS +[ + box wid 0.5 ht 0.5; box wid 0.75 ht 0.75; + move down from last box .s 0.1; + "\fBbox wid 0.5 ht 0.5; box wid 0.75 ht 0.75\fP" +] +move from last [].e 2 +[ + box wid 0.5 ht 0.5; box wid 0.75 ht 0.75 with .sw at last box .se; + move down from last box .s 0.1; + "\fBbox wid 0.5 ht 0.5; box wid 0.75 ht 0.75 with .sw at last box .se;\fP" +] +.PE +.CE "7: Using the \fBwith\fP modifier for attachments" +.NH 2 +The chop modifier +.PP +When drawing lines between circles that don't intersect them at a +compass point, it is useful to be able to shorten a line by the radius +of the circle at either or both ends. Consider the following program: +.KS +.DS +\&.PS +circle "x" +circle "y" at 1st circle - (0.4, 0.6) +circle "z" at 1st circle + (0.4, -0.6) +arrow from 1st circle to 2nd circle chop +arrow from 2nd circle to 3rd circle chop +arrow from 3rd circle to 1st circle chop +\&.PE +.DE +.KE +.LP +It yields the following: +.KS +.PS +circle "x" +circle "y" at 1st circle - (0.4, 0.6) +circle "z" at 1st circle + (0.4, -0.6) +arrow from 1st circle to 2nd circle chop +arrow from 2nd circle to 3rd circle chop +arrow from 3rd circle to 1st circle chop +.PE +.CE "8: The \fBchop\fR modifier" +.LP +Notice that the \fBchop\fR attribute moves arrowheads rather than +stepping on them. By default, the \fBchop\fR modifier shortens both +ends of the line by \fBcirclerad\fR. By suffixing it with a number +you can change the amount of chopping. +.PP +If you say \fBline ... chop \fIr1\fP chop \fIr2\fP\fR with \fIr1\fP +and \fIr2\fP both numbers, you can vary the amount of chopping at both +ends. You can use this in combination with trigonometric functions +to write code that will deal with more complex intersections. +.NH 1 +Object Groups +.PP +There are two different ways to group objects in \fBpic\fP; \fIbrace +grouping\fP and \fIblock composites\fP. +.NH 2 +Brace Grouping +.PP +The simpler method is simply to group a set of objects within curly +bracket or brace characters. On exit from this grouping, the current +position and direction are restored to their value when the opening +brace was encountered. +.NH 2 +Block Composites +.PP +A block composite object is created a series of commands enclosed by +square brackets. The composite can be treated for most purposes like +a single closed object, with the size and shape of its bounding box. +Here is an example. The program fragment +.KS +.DS +.CW +\&A: [ +\& circle; +\& line up 1 at last circle .n; +\& line down 1 at last circle .s; +\& line right 1 at last circle .e; +\& line left 1 at last circle .w; +\& box dashed with .nw at last circle .se + (0.2, -0.2); +\& Caption: center of last box; +\&] +.R +.DE +.KE +.LP +yields the block in figure \n[H1]-1, which we show both with and +without its attachment points. The block's location becomes the +value of \fBA\fP. +.KS +.PS +define junction { + circle; + line up 1 at last circle .n; + line down 1 at last circle .s; + line right 1 at last circle .e; + line left 1 at last circle .w; + box dashed with .nw at last circle .se + (0.2, -0.2); + Caption: center of last box; +} +[junction();] +move; +compass([junction()]); +.PE +.CE "1: A sample composite object" +.LP +To refer to one of the composite's attachment points, you can say +(for example) \fBA .s\fP. For purposes of object naming, composites +are a class. You could write \fBlast [] .s\fP as an equivalent +refrence, usable anywhere a location is needed. This construction is +very important for putting together large, multi-part diagrams. +.PP +Blocks are also a variable-scoping mechanism, like a \fIgroff\fP(1) +environment. All variable assignments done inside a block are undone +at the end of it. To get at values within a block, write a name of +the block followed by a dot, followed by the variable or label you +want. For example, we could refer the the center of the box in the +above composite as \fBlast [] .Caption\fP or \fBA.Caption\fP. +.PP +This kind of reference to a label can be used in any way any other +location can be. For example, if we added \fB"Hi!" at A.Caption\fP +the result would look like this: +.KS +.PS +A: [junction();] +"Hi!" at A.Caption; +.PE +.CE "2: Adding a caption using interior labeling" +.PP +You can also use interior labels in either part of a \fBwith\fR +modifier. This means that the example composite could be placed +relative to its caption box by a command containing \fBwith A.Caption +at\fP. +.PP +Blocks may be nested. This means you can use block attachment points +to build up complex diagrams hierarchically, from the inside out. +Note that \fBlast\fP and the other sequential naming mechanisms +don't look inside blocks, so if you have a program that looks +like +.KS +.DS +.CW +\&.PS +P: [box "foo"; ellipse "bar"]; +Q: [ + [box "baz"; ellipse "quxx"] + "random text"; + ] +arrow from 2nd last []; +\&.PE +.R +.DE +.KE +.LP +the arrow in the last line will be attached to object \fBP\fP, not +object \fBQ\fP. +.PP +In DWB \fBpic\fP, only references one level deep into enclosed blocks +were permitted. GNU \fBgpic\fP removes this restriction. +.PP +The combination of block variable scoping, assignability of labels and +the macro facility that we'll describe later on can be used to +simulate functions with local variables (just wrap the macro body in +block braces). +.NH 1 +Style Variables +.PP +There are a number of global style variables in \fBpic\fR that can be used to +change its overall behavior. We've mentioned several of them in +previous sections. They're all described here. For each variable, +the default is given. +.TS H +tab(@), linesize(2); +lb | lb | lb +l | n | l. +.sp 2p +Style Variable@Default@What It Does +.sp 2p +_ +.sp 2p +.TH +boxht@0.5@Default height of a box +boxwid@0.75@Default height of a box +lineht@0.5@Default length of vertical line +linewid@0.75@Default length of horizontal line +arcrad @0.25@Default radius of an arc +circlerad@0.25@Default radius of a circle +ellipseht@0.5@Default height of an ellipse +ellipsewid@0.75@Default width of an ellipse +moveht@0.5@Default length of vertical move +movewid@0.75@Default length of horizontal move +textht@0@Default height of box enclosing a text object +textwid@0@Default width of box enclosing a text object +arrowht@0.1@Length of arrowhead along shaft +arrowwid@0.05@Width of rear of arrowhead +arrowhead@1@Enable/disable arrowhead filling +dashwid@0.05@Interval for dashed lines +maxpswid@11@Maximum width of picture +maxpsht@8.5@Maximum height of picture +scale@1@Unit scale factor +fillval@0.5@Default fill value +.sp 5p +_ +.TE +Any of these variables can be set with a simple assignment statement. +For example: +.KS +.PS +[boxht=1; boxwid=0.3; movewid=0.2; box; move; box; move; box; move; box;] +.PE +.CE "1: \fBboxht=1; boxwid=0.3; movewid=0.2; box; move; box; move; box; move; box;\fP" +.PP +In GNU \fBpic\fR, setting the \fBscale\fR variable re-scales all +size-related state variables so that their values remain equivalent in +the new units. +.PP +The command \fBreset\fP resets all style variables to their defaults. +You can give it a comma-separated list of variable names as arguments, +in which case it resets only those. +.PP +State variables retain their values across pictures until reset. +.NH 1 +Expressions, Variables, and Assignment +.PP +A number is a valid expression, of course (all numbers are stored +internally as floating-point). Decimal-point notation is acceptable; +in GNU \fBgpic\fR, scientific notation in C's `e' format (like +\f(CW5e-2\fP) is accepted. +.PP +Anywhere a number is expected, the language will also accept a +variable. Variables may be the built-in style variable described in +the last section, or new variables created by assignment. +.PP +DWB \fBpic\fP supports only the ordinary assignment via =, defines the +variable in the current block if it is not already defined there, and +then changes the value in the current block. +GNU \fBgpic\fP supports an alternate form of assignment using :=. The +.I variable +(right side) must already be defined, +and the value of +.I variable +will be changed only in the innermost block in which it is defined. +.PP +You can use the height, width, radius, and x and y coordinates of any +object or corner in expressions If \fBA\fP is an object label or name, +all the following are valid: +.KS +.DS +.CW +A.x # x coordinate of the center of A +A.ne.y # y coordinate of the northeast corner of A +A.wid # the width of A +A.ht # and its height +2nd last circle.rad # the radius of the 2nd last circle +.R +.DE +.KE +Note the second expression, showing how to extract a corner coordinate. +.PP +Basic arithmetic resembling those of C operators are available; +, *, +-, /, and %. So is ^ for exponentiation. Grouping is permitted in +the usual way using parentheses. GNU \fBgpic\fP allows logical +operators to appear in expressions; ! (logical negation, not +factorial), &&, ||, ==, !=, >=, <=, <, >. +.PP +Various built-in functions are supported: \fBsin(\fIx\fP)\fP, +\fBcos(\fIx\fP)\fP, \fBlog(\fIx\fP)\fP, \fBexp(\fIx\fP)\fP, +\fBsqrt(\fIx\fP)\fP, \fBmax(\fIx\fP,\fIy\fP)\fP, +\fBatan2(\fIx\fP,\fIy\fP)\fP, \fBmin(\fIx\fP,\fIy\fP)\fP, +\fBint(\fIx\fP\fB)\fP, and \fBrand()\fP, Both \fBexp\fP and \fBlog\fP are +base 10; \fBint\fP does integer truncation; and \fBrand()\fP returns a +random number in [0-1). +.PP +GNU \fBgpic\fP also documents a one-argument form or rand, +\fBrand(\fIx\fP\fB)\fP, which returns a random number between 1 and +\fIx\fP, but this is deprecated and may be removed in a future +version. +.PP +The function \fBsprintf()\fP behaves like a C \fIsprintf\fP(3) that +only takes %, %e, %f, and %g format strings. +.NH 1 +Macros +.PP +You can define macros in \fBpic\fP. This is useful for diagrams with +repetitive parts. In conjunction with the scope rules for block +composites, it effectively gives you the ability to write functions. +.PP +The syntax is +.DS +.CW +\fBdefine\fP \fIname\fP \fB{\fP \fIreplacement text \fB}\fP +.R +.DE +.LP +This defines \fIname\fR as a macro to be replaced by the replacement +text (not including the braces). The macro may be called as +.DS +.CW +\fIname\fB(\fIarg1, arg2, ... argn\fB)\fR +.R +.DE +.LP +The arguments (if any) will be substituted for tokens $1, $2 ... $n +appearing in the replacement text. +.PP +As an example of macro use, consider the following: +.KS +.DS +.CW +\&.PS +\&# Plot a single jumper in a $1 by $2 box, $3 is the on-off state +\&define jumper { [ +\& shrinkfactor = 0.8; +\& Outer: box invis wid 0.5 ht 1; +\& +\& # Count on end ] to reset these +\& boxwid = Outer.wid * shrinkfactor / 2; +\& boxht = Outer.ht * shrinkfactor / 2; +\& +\& box fill (!$1) with .s at center of Outer; +\& box fill ($1) with .n at center of Outer; +\&] } +\& +\&# Plot a block of six jumpers +\&define jumperblock { +\& jumper($1); +\& jumper($2); +\& jumper($3); +\& jumper($4); +\& jumper($5); +\& jumper($6); +\& +\& jwidth = last [].Outer.wid; +\& jheight = last [].Outer.ht; +\& +\& box with .nw at 6th last [].nw wid 6*jwidth ht jheight; +\& +\& # Use {} to avoid changing position from last box draw. +\& # This is necessary so move in any direction will work as expected +\& {"Jumpers in state $1$2$2$3$4$5$6" at last box .s + (0, -0.2);} +\&} +\& +\&# Sample macro invocations +\&jumperblock(1,1,0,0,1,0); +\&move; +\&jumperblock(1,0,1,0,1,1); +.PE +.R +.DE +.KE +It yields the following: +.KS +.PS +# Plot a single jumper in a $1 by $2 box, $3 is the on-off state +define jumper { [ + shrinkfactor = 0.8; + Outer: box invis wid 0.5 ht 1; + + # Count on end ] to reset these + boxwid = Outer.wid * shrinkfactor / 2; + boxht = Outer.ht * shrinkfactor / 2; + + box fill (!$1) with .s at center of Outer; + box fill ($1) with .n at center of Outer; +] } + +# Plot a block of six jumpers +define jumperblock { + jumper($1); + jumper($2); + jumper($3); + jumper($4); + jumper($5); + jumper($6); + + jwidth = last [].Outer.wid; + jheight = last [].Outer.ht; + + box with .nw at 6th last [].nw wid 6*jwidth ht jheight; + + # Use {} to avoid changing position from last box draw. + # This is necessary so move in any direction will work as expected + {"Jumpers in state $1$2$2$3$4$5$6" at last box .s + (0, -0.2);} +} + +# Sample macro invocations +jumperblock(1,1,0,0,1,0); +move; +jumperblock(1,0,1,0,1,1); +.PE +.CE "1: Sample use of a macro" +.LP +This macro example illustrates how you can combine [], brace grouping, +and variable assignment to write true functions. +.PP +One detail the example above does not illustrate is the fact that +macro argument parsing is not token-oriented. If you call \fBjumper( +1 )\fP, the value of $1 will be \fB" 1 "\fP. You could even call +\fBjumper(big string)\fP to give $1 the value \fB"big string"\fP. +.PP +If you want to pass in a coordinate pair, you can avoid getting +tripped up by the comma by wrapping the pair in parentheses. +.PP +Macros persist through pictures. To undefine a mcro, say \fBundef\fP +\fIname\fR; for example, +.DS +\f(CWundef jumper\fP +\f(CWundef jumperblock\fP +.DE +.LP +would undefine the two macros in the jumper block example. +.NH 1 +Import/Export Commands +.PP +Commands that import or export data between \fBpic\fR and its +environment are described here. +.NH 2 +File and Table Insertion +.PP +The statement +.DS +\f(CWcopy\fP \fIfilename\fR +.DE +inserts the contents of \fIfilename\fR in the \fBpic\fP input stream. +Any .PS/.PE pair in the file will be ignored. This, you can use this +to include pre-generated images. +.PP +A variant of this statement replicates the \fBcopy thru\fP feature of +\fIgrap\fP(1). If you say +.DS +\f(CWcopy\fP \fIfilename\fR \f(CWthru\fP \fImacro\fP +.DE +.LP +calls the \fImacro\fP (which may be either a name or replacement text) +on the arguments obtained by breaking each line of the file into +blank-separated fields. The macro may have up to 9 arguments. The +replacement text may be delimited by braces or by a pair of instances +of any character not appearing in the rest of the text. +.PP +If you write +.DS +\f(CWcopy thru\fP \fImacro\fP +.DE +.LP +omitting the filename, lines to be parsed are taken from the input +source up to the next .PE. +.PP +In either of the \fBcopy\fP commands, GNU \fBgpic\fP permits a +trailing `\fBuntil\fP \fIword\fP' clause to be added which terminates +the copy when the first word matches the argument (the default +behavior is therefore equivalent to \fBuntil .PE\fP, +.PP +Accordingly, the command +.RS +.IP +.ft CW +.nf +\&.PS +copy thru % circle at ($1,$2) % until "END" +1 2 +3 4 +5 6 +END +box +\&.PE +.R +.fi +.RE +.LP +is equivalent to +.RS +.IP +.ft CW +.nf +\&.PS +circle at (1,2) +circle at (3,4) +circle at (5,6) +box +\&.PE +.R +.fi +.RE +.NH 2 +Debug Messages +.PP +The command \fBprint\fR accepts any number of comma-separated +arguments, concatenates their output forms, and writes the result to +standard error. Each argument must be an expression, a position, or +a text string. +.NH 2 +Escape to Post-Processor +.PP +If you write +.DS +\fBcommand\fR \fIarg\fR\|.\|.\|. +.DE +.LP +\fBpic\fP concatenates the arguments and pass them through as a line +to troff or \*(tx. Each +.I arg +must be an expression, a position, or text. +This has a similar effect to a line beginning with +.B . +or +\fB\e\fR, +but allows the values of variables to be passed through. +.NH 2 +Executing Shell Commands +.PP +The command +.DS +\f(CWsh { \fIanything...\fP }\fP +.DE +.LP +macroexpands the text in braces, then executes it as a shell command. +This could be used to generate images or data tables for later +inclusion. The delimiters shown as {} here may also be two copies of +any one character not present in the shell command text. In either +case, the body may contain balanced {} pairs. Strings in the body +may contain balanced or unbalanced braces in any case. +.NH 1 +Control-flow constructs +.PP +The \fBpic\fP language provides conditionals and looping. For +example, +.KS +.DS +.CW +pi = atan2(0, -1); +for i = 0 to 2 * pi by 0.1 do { + "-" at (i/2, 0); + "." at (i/2, sin(i)/2); + ":" at (i/2, cos(i)/2); +} +.R +.DE +.KE +.LP +which yields this: +.KS +.PS +pi = atan2(0, -1); +for i = 0 to 2 * pi by 0.1 do { + "-" at (i/2, 0); + "." at (i/2, sin(i)/2); + ":" at (i/2, cos(i)/2); +} +.PE +.CE "1: Plotting with a \fBfor\fP loop" +.LP +The syntax of the \fBfor\fP statement is: +.DS +\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \ +[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR +.DE +The semantics are as follows: Set +.I variable +to \fIexpr\fR1 . +While the value of +.I variable +is less than or equal to +\fIexpr2\fR, +do +.I body +and increment +.I variable +by +\fIexpr3\fR; +if +.B by +is not given, increment +.I variable +by 1. +If +.I expr3 +is prefixed by +.B * +then +.I variable +will instead be multiplied by +\fIexpr3\fR. +.I X +can be any character not occurring in +\fIbody\fR; or the two Xs may be paired braces (as in the \fBsh\fR command). +.PP +The syntax of the \fBif\fP statement is as follows: +.DS +\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \ +[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR] +.DE +Its semantics are as follows: Evaluate +\fIexpr\fR; +if it is non-zero then do +\fIif-true\fR, +otherwise do +\fIif-false\fR. +.I X +can be any character not occurring in +\fIif-true\fR. +.I Y +can be any character not occurring in +\fIif-false\fR. +.PP +Eithe or both of the X or Y pairs may instead be balanced pairs of +braces ({ and }) as in the \fBsh\fR command. In either case, the +\fIif-true\fR may contain balanced pairs of braces. None of these +delimiters will be seen inside strings. +.PP +All the usual relational operators my be used in conditional expressions; +! (logical negation, not factorial), &&, ||, ==, !=, >=, <=, <, >. +.PP +String comparison is also supported using == and !=. String +comparisons may need to be parenthesized to avoid syntactic +ambiguities. +.NH 1 +Interface To [gt]roff +.PP +The output of \fBpic\fP is \fB[gt]roff\fP drawing commands. The GNU +\fIgpic\fP(1) command warns that it relies on drawing extensions +present in \fIgroff\fP(1) that are not present in \fItroff\fP(1). +.NH 2 +Scaling Arguments +.PP +The DWB \fIpic\fP(1) program will accept one or two arguments to +\&\fB.PS\fP, which is interpreted as a width and height in inches to +which the results of \fIpic\fP(1) should be scaled (width and height +scale independently). If there is only one argument, it is +interpreted as a width to scale the picture to, and height will be +scaled by the same proportion. +.PP +GNU \fBgpic\fP is less general; it will accept a single width to scale +to, or a zero width and a maximum height to scale to. With +two nonzero arguments, it will scale to the maximum height. +.NH 2 +How Scaling is Handled +.PP +When \fBpic\fP processes a picture description on input, it passes .PS +and .PE through to the postprocessor. The .PS gets decorated with two +numeric arguments which are the X and Y dimensions of the picture in +inches. The post-processor can use these to reserve space for the +picture and center it. +.PP +The \fBmgs\fP macros, for example, include the following definitions: +.KS +.DS +.CW +\&.de PS +\&.br +\&.sp \\n[DD]u +\&.ie \\n[.$]<2 .@error bad arguments to PS (not preprocessed with pic?) +\&.el \{\ +\&. ds@need (u;\\$1)+1v +\&. in +(u;\\n[.l]-\\n[.i]-\\$2/2>?0) +\&.\} +\&.. +\&.de PE +\&.par@reset +\&.sp \\n[DD]u+.5m +\&.. +.R +.DE +.KE +.LP +Equivalent definition will be supplied by GNU \fIpic\fP(1) if you use +the -mpic option; this should make it usable with macro pages other +than \fIms\fR(1). +.PP +if .PF is used instead of .PE, the \fBtroff\fP position is restored to +what it was at the picture start (Kernighan notes that the F stands +for "flyback"). +.PP +The invocation +.DS +\&\fB.PS <\fP\fIfile\fP +.DE +.LP +causes the contents of \fIfile\fP to replace the .PS line. This +feature is deprecated; use \fBcopy file\fR instead). +.PP +By default, input lines that begin with a period are passed to the +postprocessor, embedded at the corresponding point in the output. +Messing with horizontal or vertical spacing is an obvious recipe for +bugs, but point size and font changes will usually be safe. +.PP +Point sizes and font changes are also safe within text strings, as +long as they are undone before the end of string. +.PP +The state of \fB[gt]roff\fP's fill mode is preserved across pictures. +.PP +The Kernighan paper notes that there is a subtle problem with +complicated equations inside \fBpic\fR pictures; they come out wrong if +\fIeqn\fP(1) has to leave extra vertical space for the equation. +If your equation involves more than subscripts and superscripts, you +must add to the beginning of each equation the extra information +\f(CWspace 0\fP. He gives the following example: +.KS +.DS +.CW +arrow +box "$space 0 {H( omega )} over {1 - H( omega )}$" +arrow +.R +.DE +.KE +.EQ +delim @@ +.EN +.KS +.PS +arrow +box "@space 0 {H( omega )} over {1 - H( omega )}@" +arrow +.PE +.CE "1: Equations within pictures" +.NH 1 +Interface to TeX +.PP +.PP +\*(tx mode is enabled by the +.B \-t +option. +In \*(tx mode, pic will define a vbox called +.B \egraph +for each picture. +You must yourself print that vbox using, for example, the command +.RS +.LP +.B +\ecenterline{\ebox\egraph} +.RE +.LP +Actually, since the vbox has a height of zero this will produce +slightly more vertical space above the picture than below it; +.RS +.LP +.B +\ecenterline{\eraise 1em\ebox\egraph} +.RE +.LP +would avoid this. +.PP +You must use a \*(tx driver that supports the +.B tpic +specials, version 2. +.PP +Lines beginning with +.B \e +are passed through transparently; a +.B % +is added to the end of the line to avoid unwanted spaces. +You can safely use this feature to change fonts or to +change the value of \fI\ebaselineskip\fR. +Anything else may well produce undesirable results; use at your own risk. +Lines beginning with a period are not given any special treatment. +.PP +The \(*tx mode of \fIpic\fP(1) will \fInot\fP translate \fBtroff\fP +font and size changes included in text strings! +.NH 1 +Obsolete Commands +.PP +GNU \fIgpic\fP(1) has a command +.DS +\fBplot\fR \fIexpr\fR [\fB"\fItext\fB"\fR] +.DE +This is a text object which is constructed by using +.I text +as a format string for sprintf +with an argument of +\fIexpr\fP. +If +.I text +is omitted a format string of "%g" is used. +Attributes can be specified in the same way as for a normal text +object. +Be very careful that you specify an appropriate format string; +\fBpic\fP does only very limited checking of the string. +This is deprecated in favour of +\fBsprintf\fP. +.NH 1 +Some Larger Examples +.PP +Here are a few larger examples, with complete source code. +.PP +One of our earlier examples is generated in an instructive way using a +for loop: +.KS +.DS +.CW +\&.PS +\&# Draw a demonstration up left arrow with grid box overlay +\&define gridarrow +\&{ +\& [ +\& {arrow up left $1;} +\& box wid 0.5 ht 0.5 dotted with .nw at last arrow .end; +\& for i = 2 to ($1 / 0.5) do +\& { +\& box wid 0.5 ht 0.5 dotted with .sw at last box .se; +\& } +\& move down from last arrow .center; +\& [ +\& if ( $1 == boxht ) then { "\\fBline up left\\fP" } else { sprintf("\\fBarrow up left %g\\fP", $1) }; +\& ] +\& ] +\& move right from last [] .e; +\&} +\&gridarrow(0.5); +\&gridarrow(1); +\&gridarrow(1.5); +\&gridarrow(2); +\&undef gridarrow +\&.PE +.R +.DE +.KE +.KS +.PS +# Draw a demonstration up left arrow with grid box overlay +define gridarrow +{ + [ + {arrow up left $1;} + box wid 0.5 ht 0.5 dotted with .nw at last arrow .end; + for i = 2 to ($1 / 0.5) do + { + box wid 0.5 ht 0.5 dotted with .sw at last box .se; + } + move down from last arrow .center; + [ + if ( $1 == boxht ) then { "\fBline up left\fP" } else { sprintf("\fBarrow up left %g\fP", $1) }; + ] + ] + move right from last [] .e; +} +gridarrow(0.5); +gridarrow(1); +gridarrow(1.5); +gridarrow(2); +undef gridarrow +.PE +.CE "1: Diagonal arrows (dotted boxes show the implied 0.5-inch grid)" +.PP +Here's an example concocted to demonstrate layout of a large, +multiple-part pattern: +.KS +.DS +.CW +\&.PS +\&define filter {box ht 0.25 rad 0.125} +\&lineht = 0.25; +\&Top: [ +\& right; +\& box "\\fBms\\fR" "sources"; +\& move; +\& box "\\fBHTML\\fR" "sources"; +\& move; +\& box "\\fBlinuxdoc-sgml\\fP" "sources" wid 1.5; +\& move; +\& box "\\fBTexinfo\\fP" "sources"; +\& +\& line down from 1st box .s lineht; +\& A: line down; +\& line down from 2nd box .s; filter "\\fBhtml2ms"; +\& B: line down; +\& line down from 3rd box .s; filter "\\fBformat\\fP"; +\& C: line down; +\& line down from 4th box .s; filter "\\fBtexi2roff\\fP"; +\& D: line down; +\&] +\&move down 1 from last [] .s; +\&Anchor: box wid 1 ht 0.75 "\\fBms\\fR" "intermediate" "form"; +\&arrow from Top.A.end to Anchor.nw; +\&arrow from Top.B.end to 1/3 of the way between Anchor.nw and Anchor.ne; +\&arrow from Top.C.end to 2/3 of the way between Anchor.nw and Anchor.ne; +\&arrow from Top.D.end to Anchor.ne +\&{ +\& # PostScript column +\& move to Anchor .sw; +\& line down left then down ->; +\& filter "\\fBpic\\fP"; +\& arrow; +\& filter "\\fBeqn\\fP"; +\& arrow; +\& filter "\\fBtbl\\fP"; +\& arrow; +\& filter "\\fBgroff\\fP"; +\& arrow; +\& box "PostScript"; +\& +\& # HTML column +\& move to Anchor .se; +\& line down right then down ->; +\& A: filter dotted "\\fBpic2img\\fP"; +\& arrow; +\& B: filter dotted "\\fBeqn2html\\fP"; +\& arrow; +\& C: filter dotted "\\fBtbl2html\\fP"; +\& arrow; +\& filter "\\fBms2html\\fP"; +\& arrow; +\& box "HTML"; +\& +\& # Nonexistence caption +\& box dashed wid 1 at B + (2, 0) "These tools" "don't yet exist"; +\& line chop 0 chop 0.1 dashed from last box .nw to A.e ->; +\& line chop 0 chop 0.1 dashed from last box .w to B.e ->; +\& line chop 0 chop 0.1 dashed from last box .sw to C.e ->; +\&} +\&.PE +.R +.DE +.KE +.KS +.PS +define filter {box ht 0.25 rad 0.125} +lineht = 0.25; +Top: [ + right; + box "\fBms\fR" "sources"; + move; + box "\fBHTML\fR" "sources"; + move; + box "\fBlinuxdoc-sgml\fP" "sources" wid 1.5; + move; + box "\fBTexinfo\fP" "sources"; + + line down from 1st box .s lineht; + A: line down; + line down from 2nd box .s; filter "\fBhtml2ms"; + B: line down; + line down from 3rd box .s; filter "\fBformat\fP"; + C: line down; + line down from 4th box .s; filter "\fBtexi2roff\fP"; + D: line down; +] +move down 1 from last [] .s; +Anchor: box wid 1 ht 0.75 "\fBms\fR" "intermediate" "form"; +arrow from Top.A.end to Anchor.nw; +arrow from Top.B.end to 1/3 of the way between Anchor.nw and Anchor.ne; +arrow from Top.C.end to 2/3 of the way between Anchor.nw and Anchor.ne; +arrow from Top.D.end to Anchor.ne +{ + # PostScript column + move to Anchor .sw; + line down left then down ->; + filter "\fBpic\fP"; + arrow; + filter "\fBeqn\fP"; + arrow; + filter "\fBtbl\fP"; + arrow; + filter "\fBgroff\fP"; + arrow; + box "PostScript"; + + # HTML column + move to Anchor .se; + line down right then down ->; + A: filter dotted "\fBpic2img\fP"; + arrow; + B: filter dotted "\fBeqn2html\fP"; + arrow; + C: filter dotted "\fBtbl2html\fP"; + arrow; + filter "\fBms2html\fP"; + arrow; + box "HTML"; + + # Nonexistence caption + box dashed wid 1 at B + (2, 0) "These tools" "don't yet exist"; + line chop 0 chop 0.1 dashed from last box .nw to A.e ->; + line chop 0 chop 0.1 dashed from last box .w to B.e ->; + line chop 0 chop 0.1 dashed from last box .sw to C.e ->; +} +.PE +.CE "2: Hypothetical production flow for dual-mode publishing" +.LP +.\"%%REFERENCE%% +.NH 1 +PIC Reference +.PP +This is an annotated grammar of PIC. +.NH 2 +Lexical Items +.PP +In general, \fBpic\fP is a free-format, token-oriented language that +ignores whitespace outside strings. But certain lines and contructs +are specially interpreted at the lexical level: +.PP +A comment begins with # and continues to \en (comments may also follow +text in a line). A line beginning with a period or backslash may be +interpreted as text to be passed through to the post-processor, +depending on command-line options. An end-of-line backslash is +interpreted as a request to continue the line; the backslash and +following newline are ignored. +.LP +Here are the grammar terminals: +.IP +A decimal numeric constant. May contain a decimal point or be +expressed in scientific notation in the style of \fIprintf\fP(3)'s %e +escape. (All variables are represented internally in floating-point.) +.IP +Any ASCII characters surrounded by a pair of double quotes. May +contain a double quote if preceded by a backslash. +.IP +A lower-case alphabetic character, followed by any number of +alphanumerics. (Values of variables are preserved across pictures.) +.IP