diff -2rcP groff-1.10/ChangeLog groff-1.11/ChangeLog *** groff-1.10/ChangeLog Sun Nov 26 06:45:18 1995 --- groff-1.11/ChangeLog Fri Aug 15 08:55:45 1997 *************** *** 1,2 **** --- 1,9 ---- + 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 diff -2rcP groff-1.10/INSTALL groff-1.11/INSTALL *** groff-1.10/INSTALL Sun Nov 26 06:46:52 1995 --- groff-1.11/INSTALL Mon Aug 11 03:02:59 1997 *************** *** 17,21 **** worthwhile (and sometimes spectacular) performance improvement. ! When you have build 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 --- 17,21 ---- worthwhile (and sometimes spectacular) performance improvement. ! 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 diff -2rcP groff-1.10/NEWS groff-1.11/NEWS *** groff-1.10/NEWS Tue Jun 27 11:07:13 1995 --- groff-1.11/NEWS Mon Aug 11 03:27:42 1997 *************** *** 2,5 **** --- 2,22 ---- 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 -2rcP groff-1.10/PROJECTS groff-1.11/PROJECTS *** groff-1.10/PROJECTS Sun Jul 10 09:25:50 1994 --- groff-1.11/PROJECTS Mon Aug 11 03:09:49 1997 *************** *** 12,17 **** 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. - James Clark - jjc@jclark.com --- 12,20 ---- a complete, self-contained manual (trent@cs.pdx.edu is working on this) ! 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. ! diff -2rcP groff-1.10/README groff-1.11/README *** groff-1.10/README Sun Nov 26 06:50:32 1995 --- groff-1.11/README Mon Aug 11 03:11:41 1997 *************** *** 27,36 **** 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 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. ! James Clark ! jjc@jclark.com --- 27,35 ---- Please report bugs using the form in the file BUG-REPORT; the idea of ! 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 us to determine whether it really is a bug or not. ! GNU groff was written by James Clark . diff -2rcP groff-1.10/VERSION groff-1.11/VERSION *** groff-1.10/VERSION Sun Nov 26 06:44:50 1995 --- groff-1.11/VERSION Fri Aug 15 08:52:14 1997 *************** *** 1 **** ! 1.10 --- 1 ---- ! 1.11 diff -2rcP groff-1.10/doc/Makefile groff-1.11/doc/Makefile *** groff-1.10/doc/Makefile Thu Jun 22 03:42:50 1995 --- groff-1.11/doc/Makefile Fri Aug 15 08:44:06 1997 *************** *** 21,25 **** TROFF=../troff/troff -M../tmac $(FFLAG) GROPS=../grops/grops $(FFLAG) ! DOCS=meref.PS meintro.PS MEMACROS=../macros/tmac.e SOELIM=../soelim/soelim --- 21,25 ---- TROFF=../troff/troff -M../tmac $(FFLAG) GROPS=../grops/grops $(FFLAG) ! DOCS=meref.PS meintro.PS pic.PS MEMACROS=../macros/tmac.e SOELIM=../soelim/soelim *************** *** 27,31 **** all: $(DOCS) ! .SUFFIXES: .tr .me .PS .dit .dit.PS: --- 27,31 ---- all: $(DOCS) ! .SUFFIXES: .tr .me .ms .PS .dit .dit.PS: *************** *** 43,48 **** meintro.PS: meintro.dit install: ! clean: -rm -f *.PS *.dit core --- 43,53 ---- 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 -2rcP groff-1.10/doc/pic.ms groff-1.11/doc/pic.ms *** groff-1.10/doc/pic.ms Wed Dec 31 19:00:00 1969 --- groff-1.11/doc/pic.ms Fri Aug 15 08:20:10 1997 *************** *** 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