pspicture.sty

D. P. Carlisle

16 June 1992

1 Introduction

pspicture is a re-implementation, and extension of, L^{A}TEX’s picture environment, using PostScript \special’s. This has several advantages, mainly that lines of arbitrary slope and thickness may be specified, and there is no limit on the size of the circles that may be drawn^{1}.

One disadvantage is that the picture can no longer be previewed on a dvi previewer, such as xdvi. To help with this problem, a companion style option, texpicture, may be used while developing a document, this uses the standard picture commands as much as possible, and silently omits any picture objects that can not be drawn with standard L^{A}TEX.

A second disadvantage, is that a dvi file produced with pspicture will contain embedded \special commands. These commands will only work with the driver program for which they were intended. This makes the dvi file less portable. pspicture will by default use \special’s set up for Rokicki’s dvips program, although it should be easy to modify the code to work with other PostScript drivers. A DocStrip option for a version of dvi2ps is included with this distribution.

1.1 Commands Available

“circle Use as described in the L^{A}TEX book but with no maximum diameter. The thickness “circle* of the circle is altered by the \linethickness command. The size of the circle

produced by \circle* is not affected by \linethickness, so it is not the same as ‘filling in’ the circle drawn by \circle.

“oval Use as described in the L^{A}TEX book, but as there is no maximum diameter for the circular arcs, the oval (in the absence of the optional [tr] etc) always consists of two semi-circular arcs joined by a pair of parallel lines. To obtain a ‘rectangle with rounded corners’ the oval command has a second optional argument (given first !).

1There is a certain amount of overlap between this style option and the widely available eepic option. However when I wrote the first version of this, in 1989, I was not aware of eepic, and pspicture has been reasonably popular in Manchester, even though epic and eepic have been installed.

\oval[20](100,200)[t]

Produces the top half of an oval with quarter circles of radius 20*unitlength. If unitlength = 1pt then this is equivalent to the standard oval command. In general \oval[R](x,y) uses circular arcs of radius min(R, x/2, y/2).

“line Use as described in the L^{A}TEX book but with no restriction on the available slopes. “vector The thickness of a sloping line is altered by the \linethickness command.

“Line New forms of the line and vector commands.

“Vector \put(x1,y1){\Line(x2,y2)}

produces a line from (x1,y1) to (x1+x2,y1+y2) and similarly for \Vector.

“Curve Like \Line except that it produce a curve!

\put(x1,y1){\Curve(x2,y2){m}}

produces a curve from (x1,y1) to (x1+x2,y1+y2). the amount of curvature is controlled by m but try 1 or −1 first. m does not have to be an integer. Negative numbers curve the opposite way to positive numbers.

“thinlines These commands alter the thickness of all lines including slanted lines and circular

“thicklines “linethickness

arcs.

“arrowlength A new command which specifies the size of the arrowhead drawn by the \vector and \Vector commands. Like \linethickness it does not get multiplied by \unitlength. At present the arrowhead is triangular. If a head with curved sides more like the standard L^{A}TEX head is required the definition of !A in pspicture.ps should be altered.

Other picture mode commands are not altered by this style, and so may be used, just as described in the L^{A}TEX book. These include: \put, \multiput, \makebox,

\framebox, dashbox and \shortstack.

2 Examples

A picture built with L^{A}TEX’s line and circle fonts.

[figure]

The same picture built with PostScript \special’s.

Some extra features not available using the standard picture mode.

3 pspicture.sty

1 ⟨∗pssty⟩

First we set up the code that is specific to the driver program that is being used. If the driver can incorporate a header file, define \PS@header appropriately, \PS@special should expand to the format for inline PostScript code. The driver should protect this code with a (g)save (g)restore pair. dvips is treated specially so that it will be the default driver if this file is used without being stripped. If you find definitions of these macros which work for the driver you use, email me, and I will include them in the next release.

“PS@header Code to include the PostScript header.

2 ⟨∗dvips⟩ 3 “def“PS@header#1–“special–header=#1˝ ˝ 4 ⟨/dvips⟩ 5 ⟨dvi2ps⟩“def“PS@header#1–“typeout–Print with the option -i #1˝ ˝ 6 “PS@header–pspicture.ps˝

“PS@special The format of the \special command for inline PostScript.

7 ⟨∗dvips⟩ 8 “def“PS@special#1–“special–”#1˝ ˝ 9 ⟨/dvips⟩ 10 ⟨dvi2ps⟩“def“PS@special#1–“special–pstext=”#1”˝ ˝

“strippt Strip the final ‘pt’ off the string returned by \the.

11 –“catcode‘t=12“catcode‘p=12“gdef“noPT#1pt–#1˝ ˝ 12 “def“strippt#1–“expandafter“noPT“the#1“space˝

“@circle Internal name for \circle.

13 “def“@circle#1–% 14 “@tempdimb #1“unitlength 15 “PS@special–% 16 “strippt“@wholewidth 17 “strippt“@tempdimb 18 !C˝ ˝

“@dot Internal name for \circle*.

19 “def“@dot#1–% 20 “@tempdimb #1“unitlength 21 “PS@special–% 22 “strippt“@tempdimb 23 !D˝ ˝

“line Line with a L^{A}TEX style slope specification.

24 “def“line(#1,#2)#3–% 25 “@linelen=#3“unitlength 26 “PS@special–% 27 “strippt“@wholewidth 28 #1 29 #2 30 “strippt“@linelen 31 !L˝ ˝

“vector Line and arrow head with a L^{A}TEX style slope specification.

32 “def“vector(#1,#2)#3–% 33 “@linelen=#3“unitlength 34 “PS@special–% 35 “strippt“@arrowlength 36 “strippt“@wholewidth 37 #1 38 #2 39 “strippt“@linelen 40 !V˝ ˝

“oval If no optional argument appears, use a default of maximum radius of TEX’s maximum length.

41 “def“oval–% 42 “@ifnextchar[% 43 –“@ov@l˝ % 44 –“count@=“maxdimen “divide“count@ by “unitlength “@ov@l[“count@]˝ ˝

“@ov@l Look for an optional tlbr argument.

45 “def“@ov@l[#1](#2,#3)–% 46 “@ifnextchar[–“@oval[#1](#2,#3)˝ –“@oval[#1](#2,#3)[]˝ ˝ %

“@oval The PostScript version of the \oval command will print each quarter of the oval separately, each quarter will only be printed if the appropriate argument is 1. An optional argument of t causes the arguments for the two bottom quarters to be set to 0, similarly, r causes the two left quarters to be set to 0. Thus an argument [tr] will set the bottom and left quarters to 0, resulting in only the top right quarter being printed.

47 “def“@oval[#1](#2,#3)[#4]–“begingroup 48 “@tempdimb #1“unitlength 49 “@ovxx #2“unitlength 50 “@ovyy #3“unitlength 51 “def“r–“def“TL–0 ˝ “def“BL–0 ˝ ˝ % 52 “def“l–“def“TR–0 ˝ “def“BR–0 ˝ ˝ % 53 “def“t–“def“BL–0 ˝ “def“BR–0 ˝ ˝ % 54 “def“b–“def“TL–0 ˝ “def“TR–0 ˝ ˝ % 55 “def“TL–1 ˝ “def“BL–1 ˝ “def“TR–1 ˝ “def“BR–1 ˝ % 56 “@tfor“@tempa :=#4“do–“csname“@tempa“endcsname˝ % 57 “PS@special–% 58 “BR“BL“TR“TL 59 “strippt“@wholewidth 60 “strippt“@tempdimb 61 “strippt“@ovxx 62 “strippt“@ovyy 63 !O˝ % 64 “endgroup˝

“Line New style \Line command.

65 “def“Line(#1,#2)–% 66 “@ovxx #1“unitlength 67 “@ovyy #2“unitlength 68 “PS@special–% 69 “strippt“@wholewidth 70 “strippt“@ovxx 71 “strippt“@ovyy 72 !L2˝ ˝

“Curve Not particularly good, but it will do for now.

73 “def“Curve(#1,#2)#3–% 74 “@ovxx #1“unitlength 75 “@ovyy #2“unitlength 76 “PS@special–% 77 “strippt“@wholewidth 78 “strippt“@ovxx 79 “strippt“@ovyy 80 #3 81 !C2˝ ˝

“Vector New style \Vector command.

82 “def“Vector(#1,#2)–% 83 “@ovxx #1“unitlength 84 “@ovyy #2“unitlength 85 “PS@special–% 86 “strippt“@arrowlength 87 “strippt“@wholewidth 88 “strippt“@ovxx 89 “strippt“@ovyy 90 !V2˝ ˝

“@arrowlength Length of an arrow head.

91 “newdimen“@arrowlength

“arrowlength Set the length of an arrow head.

92 “def“arrowlength#1–“@arrowlength #1˝ 93 “arrowlength–8pt˝

If this file is used as a .sty file without being stripped, we want to stop here. The \endinput must not be at the beginning of the line, or DocStrip will stop here as well!.

94 “endinput

95 ⟨/pssty⟩

4 texpicture.sty

A dummy style file so that documents using pspicture.sty can be previewed or printed (as much as possible) using a dvi (not PostScript) previewer or printer driver.

   Just change ‘pspicture’ to ‘texpicture’ in the \documentstyle options list.

96 ⟨∗texsty⟩

97 “@warning–texpicture.sty in operation:ˆ ˆ J“@spaces 98 LaTeX document with pspicture.sty before printing˝

“Line “Vector “arrowlength “Curve Define all these new commands to silently gobble their arguments.

99 “def“Line(#1,#2)–˝ 100 “def“Vector(#1,#2)–˝ 101 “def“arrowlength#1–˝ 102 “def“Curve(#1,#2)#3–˝

“@badlinearg If a vector or line is called with a slope specification that is not allowed by standard L^{A}TEX, \@badlinearg is called to produce the error message. We do not want to see these errors, so:

103 “def“@badlinearg–˝

“oval “@@v@l “@@vv@l Give the standard \oval command another optional argument (which will be ignored), to match the extra argument defined in pspicture.sty.

104 “let“@@v@l“oval 105 “def“@@@v@l[#1]–“@@v@l˝ 106 “def“oval–“@ifnextchar[–“@@@v@l˝ –“@@v@l˝ ˝

107 ⟨/texsty⟩

5 pspicture.ps

The PostScript header file for use with pspicture.sty. Probably this should use the PostScript dictionary mechanism, to keep identifiers local to this package, but for now, just give them names begining with !.

108 ⟨∗ps⟩

!BP PostScript uses TEX’s bp, that is 1/72 of an inch, not TEX’s pt, 1/72.27 of an inch, but it is inconvenient to get TEX to output in bp, so we need to scale the PostScript.

109 /!BP– 110 72 72.27 div dup scale 111 ˝ def

!A Arrow head:

⟨arrow length⟩ !A

112 /!A– 113 newpath 114 0 0 moveto 115 dup neg dup .4 mul rlineto 116 .8 mul 0 exch rlineto 117 closepath 118 fill 119 ˝ def

!V \vector(⟨x⟩,⟨y⟩)

⟨arrow length⟩ ⟨line width⟩ ⟨x⟩ ⟨y⟩ ⟨len*unitlength⟩ !V

120 /!V– 121 !BP 122 /!X exch def 123 /!y exch def 124 /!x exch def 125 newpath 126 0 0 moveto 127 !x 0 eq –0 !y 0 lt –!X neg˝ –!X˝ ifelse˝ 128 –!x 0 lt –!X neg˝ –!X˝ ifelse !X !y mul !x abs div˝ ifelse 129 lineto 130 setlinewidth % @wholewidth 131 currentpoint 132 stroke 133 translate 134 !y !x atan 135 rotate 136 !A % @arrowlength 137 ˝ def

!L \line(⟨x⟩,⟨y⟩)

⟨arrow length⟩ ⟨line width⟩ ⟨x⟩ ⟨y⟩ ⟨len*unitlength⟩ !L

138 /!L– 139 !BP 140 /!X exch def 141 /!y exch def 142 /!x exch def 143 newpath 144 0 0 moveto 145 !x 0 eq –0 !y 0 lt –!X neg˝ –!X˝ ifelse˝ 146 –!x 0 lt –!X neg˝ –!X˝ ifelse !X !y mul !x abs div˝ ifelse 147 lineto 148 setlinewidth % @wholewidth 149 stroke 150 ˝ def

!C \circle{⟨diam⟩}

⟨line width⟩ ⟨diam*unitlength⟩ !C

151 /!C– 152 !BP 153 0 0 3 2 roll 154 2 div 0 360 arc 155 setlinewidth % @wholewidth 156 stroke 157 ˝ def

!D \circle*{⟨diam⟩}

⟨diam*unitlength⟩ !D

158 /!D– 159 !BP 160 0 0 3 2 roll 161 2 div 0 360 arc fill 162 ˝ def

!O \oval[⟨max-radius⟩](⟨x⟩,⟨y⟩)[⟨tlbr⟩]

⟨br⟩⟨bl⟩⟨tr⟩⟨tl⟩

⟨line width⟩ ⟨max-radius*unitlength⟩ ⟨x*unitlength⟩ ⟨y*unitlength⟩ !O The first four arguments should be either 0, denoting that that quarter should not be drawn, or 1, to draw a quarter oval.

163 /!O– 164 !BP 165 /!y exch 2 div def 166 /!x exch 2 div def 167 /!r exch !x !y

Ghostscript appears to have a min operator, so the following 2 lines could be coded as min min, but it’s not in the Ref. Manual, and it doesn’t work on my printer!

168 2 copy gt –exch˝ if pop 169 2 copy gt –exch˝ if pop 170 def 171 setlinewidth % @wholewidth 172 1 eq 173 –newpath 174 !x neg 0 moveto 175 !x neg !y 0 !y !r arcto 4 –pop˝ repeat 176 0 !y lineto 177 stroke˝ if 178 1 eq 179 –newpath 180 !x 0 moveto 181 !x !y 0 !y !r arcto 4 –pop˝ repeat 182 0 !y lineto 183 stroke˝ if 184 1 eq 185 –newpath 186 !x neg 0 moveto 187 !x neg !y neg 0 !y neg !r arcto 4 –pop˝ repeat 188 0 !y neg lineto 189 stroke˝ if 190 1 eq 191 –newpath 192 !x 0 moveto 193 !x !y neg 0 !y neg !r arcto 4 –pop˝ repeat 194 0 !y neg lineto 195 stroke˝ if 196 ˝ def

!V2 \Vector(⟨x⟩,⟨y⟩)

⟨arrow length⟩ ⟨line width⟩ ⟨x*unitlength⟩ ⟨y*unitlength⟩ !V2

197 /!V2– 198 !BP 199 2 copy exch 200 atan 201 /a exch def 202 2 copy 203 newpath 204 0 0 moveto 205 lineto % ¡x*unitlength¿ ¡y*unitlength¿ 206 3 2 roll 207 setlinewidth % @wholewidth 208 stroke 209 translate % ¡x*unitlength¿ ¡y*unitlength¿ 210 a rotate 211 !A % @arrowlength 212 ˝ def

!L2 \Line(⟨x⟩,⟨y⟩) ⟨line width⟩ ⟨x*unitlength⟩ ⟨y*unitlength⟩ !L2

213 /!L2– 214 !BP 215 newpath 216 0 0 moveto 217 lineto % ¡x*unitlength¿ ¡y*unitlength¿ 218 setlinewidth % @wholewidth 219 stroke 220 ˝ def

!C2 \Curve(⟨x⟩,⟨y⟩){⟨±⟩} ⟨line width⟩ ⟨x*unitlength⟩ ⟨y*unitlength⟩ ⟨±⟩ !C2

221 /!C2– 222 !BP 223 /!s exch def 224 /!y exch def 225 /!x exch def 226 newpath 227 0 0 moveto 228 0 0 229 !x 2 div !y 10 div !s mul add 230 !y 2 div !x 10 div !s mul sub 231 !x !y 232 curveto 233 setlinewidth % @wholewidth 234 stroke 235 ˝ def

236 ⟨/ps⟩