1 |
#ifndef lint |
2 |
static const char RCSid[] = "$Id: psplot.c,v 1.1 2003/02/22 02:07:26 greg Exp $"; |
3 |
#endif |
4 |
/* |
5 |
* psplot.c - routines for generating PostScript output. |
6 |
* |
7 |
* 9/23/88 |
8 |
*/ |
9 |
|
10 |
#include "meta.h" |
11 |
|
12 |
#include <ctype.h> |
13 |
|
14 |
#ifdef SMALLAREA |
15 |
#define HMARGIN (0.2*72) /* horizontal margin */ |
16 |
#define VMARGIN (0.2*72) /* vertical margin */ |
17 |
#define PWIDTH (6*72-2*HMARGIN) /* width of device */ |
18 |
#define PHEIGHT (6*72-2*VMARGIN) /* height of device */ |
19 |
#else |
20 |
#define HMARGIN (.6*72) /* horizontal margin */ |
21 |
#define VMARGIN (.6*72) /* vertical margin */ |
22 |
#define PWIDTH (8.5*72-2*HMARGIN) /* width of device */ |
23 |
#define PHEIGHT (11*72-2*VMARGIN) /* height of device */ |
24 |
#endif |
25 |
|
26 |
#define PSQUARE PWIDTH /* maximal square */ |
27 |
|
28 |
#define MAXPATHL 700 /* maximum path length */ |
29 |
|
30 |
#define PREFIX "seg_" /* name prefix */ |
31 |
#define ESCCHAR '#' /* to introduce hex in name */ |
32 |
|
33 |
#define checkline() if (inaline) endline() |
34 |
|
35 |
|
36 |
static int savelvl = 0; |
37 |
|
38 |
static int inaline = 0; |
39 |
|
40 |
static char hexdigit[] = "0123456789ABCDEF"; |
41 |
|
42 |
static char buf[512]; |
43 |
|
44 |
|
45 |
static char * |
46 |
convertname(s) /* convert to segment name */ |
47 |
char *s; |
48 |
{ |
49 |
register char *cp, *cp0; |
50 |
|
51 |
for (cp = buf, cp0 = PREFIX; *cp0; ) |
52 |
*cp++ = *cp0++; |
53 |
for (cp0 = s; *cp0; cp0++) { |
54 |
if (isalnum(*cp0)) |
55 |
*cp++ = *cp0; |
56 |
else { |
57 |
*cp++ = ESCCHAR; |
58 |
*cp++ = hexdigit[*cp0 >> 4]; |
59 |
*cp++ = hexdigit[*cp0 & 0xf]; |
60 |
} |
61 |
} |
62 |
*cp = '\0'; |
63 |
return(buf); |
64 |
} |
65 |
|
66 |
|
67 |
static char * |
68 |
convertstring(s) /* convert to acceptable string */ |
69 |
register char *s; |
70 |
{ |
71 |
register char *cp; |
72 |
|
73 |
for (cp = buf; *s; s++) { |
74 |
if (*s == '(' || *s == ')') |
75 |
*cp++ = '\\'; |
76 |
if (isprint(*s)) |
77 |
*cp++ = *s; |
78 |
else { |
79 |
*cp++ = '\\'; |
80 |
*cp++ = (*s>>6) + '0'; |
81 |
*cp++ = (*s>>3 & 07) + '0'; |
82 |
*cp++ = (*s & 07) + '0'; |
83 |
} |
84 |
} |
85 |
*cp = '\0'; |
86 |
return(buf); |
87 |
} |
88 |
|
89 |
|
90 |
init(id) /* initialize */ |
91 |
char *id; |
92 |
{ |
93 |
printf("%%!PS-Adobe-2.0 EPSF-2.0\n"); |
94 |
printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", |
95 |
HMARGIN+(PWIDTH-PSQUARE)/2., |
96 |
VMARGIN+(PHEIGHT-PSQUARE)/2., |
97 |
HMARGIN+(PWIDTH-PSQUARE)/2.+PSQUARE, |
98 |
VMARGIN+(PHEIGHT-PSQUARE)/2.+PSQUARE); |
99 |
printf("%%%%DocumentFonts: Helvetica Courier\n"); |
100 |
if (id != NULL) |
101 |
printf("%%%%Creator: %s\n", id); |
102 |
printf("gsave\n"); |
103 |
printf("save\n"); |
104 |
printf("256 dict begin\n"); |
105 |
printf("%f %f translate\n", HMARGIN+(PWIDTH-PSQUARE)/2., |
106 |
VMARGIN+(PHEIGHT-PSQUARE)/2.); |
107 |
printf("%f %f scale\n", (double)PSQUARE/XYSIZE, |
108 |
(double)PSQUARE/XYSIZE); |
109 |
printf("/mapping matrix currentmatrix def\n"); |
110 |
printf("/segment {\t\t%% name lth pat col dir xmn ymn xmx ymx\n"); |
111 |
printf("\t/startstate save def\n"); |
112 |
printf("\t128 dict begin\t\t%% get parameters\n"); |
113 |
printf("\t/ymax exch def /xmax exch def\n"); |
114 |
printf("\t/ymin exch def /xmin exch def\n"); |
115 |
printf("\t/orient exch def\n"); |
116 |
printf("\t/colndx exch def /patndx exch def /lthick exch def\n"); |
117 |
printf("\t%% segment name left on stack\n"); |
118 |
printf("\txmax xmin add 2 div ymax ymin add 2 div translate\n"); |
119 |
printf("\txmax xmin sub %d div ymax ymin sub %d div scale\n", |
120 |
XYSIZE, XYSIZE); |
121 |
printf("\torient 90 mul rotate\n"); |
122 |
printf("\t%d %d translate\n", -XYSIZE/2, -XYSIZE/2); |
123 |
printf("\tcvx exec\t\t\t%% execute segment\n"); |
124 |
printf("\tend\n"); |
125 |
printf("\tstartstate restore\n"); |
126 |
printf("} def\n"); |
127 |
printf("/vstr {\t\t\t%% string\n"); |
128 |
printf("\t0 setcolor\n"); |
129 |
printf("\t/Helvetica findfont setfont\n"); |
130 |
printf("\tdup stringwidth pop %d exch div %d scale\n", XYSIZE, XYSIZE); |
131 |
printf("\tcurrentfont charorigin translate\n"); |
132 |
printf("\t0 0 moveto show\n"); |
133 |
printf("} def\n"); |
134 |
printf("/charorigin {\t\t\t%% font charorigin xorg yorg\n"); |
135 |
printf("\tdup /FontBBox get aload pop pop pop\n"); |
136 |
printf("\t3 2 roll /FontMatrix get transform\n"); |
137 |
printf("\texch neg exch neg\n"); |
138 |
printf("} def\n"); |
139 |
printf("/newline {\t\t\t%% lpat lthick col x0 y0\n"); |
140 |
printf("\tnewpath moveto\n"); |
141 |
printf("\tsetcolor setlthick setlpat\n"); |
142 |
printf("} def\n"); |
143 |
printf("/rfilldict 4 dict def\n"); |
144 |
printf("/rfill {\t\t\t%% pat col xmn ymn xmx ymx\n"); |
145 |
printf("\trfilldict begin\n"); |
146 |
printf("\t/ymax exch def /xmax exch def\n"); |
147 |
printf("\t/ymin exch def /xmin exch def\n"); |
148 |
printf("\tsetcolor setpattern\n"); |
149 |
printf("\tnewpath\n"); |
150 |
printf("\txmin ymin moveto\n"); |
151 |
printf("\txmax ymin lineto\n"); |
152 |
printf("\txmax ymax lineto\n"); |
153 |
printf("\txmin ymax lineto\n"); |
154 |
printf("\tclosepath patfill\n"); |
155 |
printf("\tend\n"); |
156 |
printf("} def\n"); |
157 |
printf("/fillpoly {\t\t\t%% pat col mark x1 y1 .. xn yn\n"); |
158 |
printf("\tnewpath moveto\n"); |
159 |
printf("\tcounttomark 2 idiv { lineto } repeat cleartomark\n"); |
160 |
printf("\tclosepath\n"); |
161 |
printf("\tsetcolor setpattern\n"); |
162 |
printf("\t{ gsave 0 setlinewidth stroke grestore } if\n"); |
163 |
printf("\tpatfill\n"); |
164 |
printf("} def\n"); |
165 |
printf("/mstr {\t\t\t%% fnt col x y\n"); |
166 |
printf("\t100 add moveto setcolor setmfont show\n"); |
167 |
printf("} def\n"); |
168 |
printf("/patfill {\n"); |
169 |
printf("\tfill\t\t\t\t%% unimplemented\n"); |
170 |
printf("} def\n"); |
171 |
printf("/setmfont {\t\t\t%% fontndx\n"); |
172 |
printf("\tmfontab exch get setfont\n"); |
173 |
printf("} def\n"); |
174 |
printf("/setcolor {\t\t\t%% colndx\n"); |
175 |
printf("\tcolndx 0 ne { pop colndx } if\n"); |
176 |
printf("\trgbcoltab exch get aload pop setrgbcolor\n"); |
177 |
printf("} def\n"); |
178 |
printf("/setlthick {\t\t\t%% lthick\n"); |
179 |
printf("\tlthick 0 ne { pop lthick } if\n"); |
180 |
printf("\tsetlinewidth\n"); |
181 |
printf("} def\n"); |
182 |
printf("/setlpat {\t\t\t%% lpatndx\n"); |
183 |
printf("\tdashtab exch get 0 setdash\n"); |
184 |
printf("} def\n"); |
185 |
printf("/setpattern {\t\t\t%% patndx\n"); |
186 |
printf("\tpop\t\t\t\t%% unimplemented\n"); |
187 |
printf("} def\n"); |
188 |
printf("/canonfont\t\t\t%% canonical matrix string font\n"); |
189 |
printf("\t/Courier findfont\n"); |
190 |
printf("\tdup charorigin matrix translate\n"); |
191 |
printf("\tmakefont\n"); |
192 |
printf("def\n"); |
193 |
printf("/mfontab [\t\t\t%% hardware font table\n"); |
194 |
printf("\t[\n"); |
195 |
printf("\t\t[ 340 0 0 340 0 -340 ]\n"); |
196 |
printf("\t\t[ 681 0 0 340 0 -340 ]\n"); |
197 |
printf("\t\t[ 340 0 0 681 0 -681 ]\n"); |
198 |
printf("\t\t[ 681 0 0 681 0 -681 ]\n"); |
199 |
printf("\t\t[ 282 0 0 282 0 -282 ]\n"); |
200 |
printf("\t\t[ 564 0 0 282 0 -282 ]\n"); |
201 |
printf("\t\t[ 282 0 0 564 0 -564 ]\n"); |
202 |
printf("\t\t[ 564 0 0 564 0 -564 ]\n"); |
203 |
printf("\t\t[ 199 0 0 199 0 -199 ]\n"); |
204 |
printf("\t\t[ 398 0 0 199 0 -199 ]\n"); |
205 |
printf("\t\t[ 199 0 0 398 0 -398 ]\n"); |
206 |
printf("\t\t[ 398 0 0 398 0 -398 ]\n"); |
207 |
printf("\t\t[ 169 0 0 169 0 -169 ]\n"); |
208 |
printf("\t\t[ 339 0 0 169 0 -169 ]\n"); |
209 |
printf("\t\t[ 169 0 0 339 0 -339 ]\n"); |
210 |
printf("\t\t[ 339 0 0 339 0 -339 ]\n"); |
211 |
printf("\t]\n"); |
212 |
printf("\t{ canonfont exch makefont }\n"); |
213 |
printf("\tforall\n"); |
214 |
printf("] def\n"); |
215 |
printf("/dashtab [ [ ] [ 200 80 ] [ 80 80 ] [ 200 80 80 80 ] ] def\n"); |
216 |
printf("/rgbcoltab [ [ 0 0 0 ] [ 1 0 0 ] [ 0 1 0 ] [ 0 0 1 ] ] def\n"); |
217 |
printf("/colndx 0 def /patndx 0 def /lthick 0 def\n"); |
218 |
printf("%%%%EndProlog\n"); |
219 |
} |
220 |
|
221 |
|
222 |
done() /* done with graphics */ |
223 |
{ |
224 |
printf("end\nrestore\ngrestore\n"); |
225 |
} |
226 |
|
227 |
|
228 |
endpage() /* done with page */ |
229 |
{ |
230 |
checkline(); |
231 |
|
232 |
printf("showpage\nmapping setmatrix\n"); |
233 |
} |
234 |
|
235 |
|
236 |
segopen(s) /* open a segment */ |
237 |
char *s; |
238 |
{ |
239 |
checkline(); |
240 |
|
241 |
printf("/%s {\n", convertname(s)); |
242 |
} |
243 |
|
244 |
|
245 |
segclose() /* close a segment */ |
246 |
{ |
247 |
checkline(); |
248 |
|
249 |
printf("} def\n"); |
250 |
} |
251 |
|
252 |
|
253 |
doseg(p) /* instance of a segment */ |
254 |
register PRIMITIVE *p; |
255 |
{ |
256 |
checkline(); |
257 |
|
258 |
printf("/%s %d %d %d ", convertname(p->args), |
259 |
WIDTH(p->arg0>>2 & 03), |
260 |
p->arg0>>2 & 03, p->arg0 & 03); |
261 |
printf("%d %d %d %d %d segment\n", p->arg0>>4, |
262 |
p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]); |
263 |
} |
264 |
|
265 |
|
266 |
printstr(p) /* print a string */ |
267 |
register PRIMITIVE *p; |
268 |
{ |
269 |
checkline(); |
270 |
printf("(%s) %d %d %d %d mstr\n", convertstring(p->args), |
271 |
p->arg0>>2 & 017, p->arg0 & 03, |
272 |
p->xy[XMN], p->xy[YMX]); |
273 |
} |
274 |
|
275 |
|
276 |
plotvstr(p) /* print a vector string */ |
277 |
register PRIMITIVE *p; |
278 |
{ |
279 |
checkline(); |
280 |
|
281 |
printf("(%s) /vstr %d 0 %d ", convertstring(p->args), |
282 |
WIDTH(p->arg0>>2 & 03), p->arg0 & 03); |
283 |
printf("%d %d %d %d %d segment\n", p->arg0>>4, |
284 |
p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]); |
285 |
} |
286 |
|
287 |
|
288 |
plotlseg(p) /* plot a line segment */ |
289 |
register PRIMITIVE *p; |
290 |
{ |
291 |
static int right = FALSE; |
292 |
static int curx, cury; |
293 |
static int curlpat, curlthick, curlcol; |
294 |
int y1, y2; |
295 |
int lpat, lthick, lcol; |
296 |
|
297 |
if (p->arg0 & 0100) { |
298 |
y1 = p->xy[YMX]; |
299 |
y2 = p->xy[YMN]; |
300 |
} else { |
301 |
y1 = p->xy[YMN]; |
302 |
y2 = p->xy[YMX]; |
303 |
} |
304 |
lpat = p->arg0>>4 & 03; |
305 |
lthick = WIDTH(p->arg0>>2 & 03); |
306 |
lcol = p->arg0 & 03; |
307 |
if (!inaline || lpat != curlpat || |
308 |
lthick != curlthick || lcol != curlcol) { |
309 |
checkline(); |
310 |
printf("%d %d %d %d %d newline\n", |
311 |
curlpat = lpat, |
312 |
curlthick = lthick, |
313 |
curlcol = lcol, |
314 |
curx = p->xy[XMN], |
315 |
cury = y1); |
316 |
} |
317 |
if (curx == p->xy[XMN] && cury == y1) { |
318 |
printf("%d %d lineto\n", curx = p->xy[XMX], cury = y2); |
319 |
} else if (curx == p->xy[XMX] && cury == y2) { |
320 |
printf("%d %d lineto\n", curx = p->xy[XMN], cury = y1); |
321 |
} else if ( (right = !right) ) { |
322 |
printf("%d %d moveto ", p->xy[XMN], y1); |
323 |
printf("%d %d lineto\n", curx = p->xy[XMX], cury = y2); |
324 |
} else { |
325 |
printf("%d %d moveto ", p->xy[XMX], y2); |
326 |
printf("%d %d lineto\n", curx = p->xy[XMN], cury = y1); |
327 |
} |
328 |
if (++inaline >= MAXPATHL) |
329 |
endline(); |
330 |
} |
331 |
|
332 |
|
333 |
endline() /* close current line */ |
334 |
{ |
335 |
printf("stroke\n"); |
336 |
inaline = 0; |
337 |
} |
338 |
|
339 |
|
340 |
fillrect(p) /* fill a rectangle */ |
341 |
register PRIMITIVE *p; |
342 |
{ |
343 |
checkline(); |
344 |
|
345 |
printf("%d %d %d %d %d %d rfill\n", p->arg0>>2 & 03, p->arg0 & 03, |
346 |
p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]); |
347 |
} |
348 |
|
349 |
|
350 |
filltri(p) /* fill a triangle */ |
351 |
register PRIMITIVE *p; |
352 |
{ |
353 |
static short corn[4][2] = {XMN,YMX,XMN,YMN,XMX,YMN,XMX,YMX}; |
354 |
int orient; |
355 |
register int i; |
356 |
|
357 |
checkline(); |
358 |
|
359 |
printf("false %d %d mark\n", p->arg0>>2 & 03, p->arg0 & 03); |
360 |
orient = p->arg0>>4 & 03; |
361 |
for (i = 0; i < 4; i++) |
362 |
if (i != orient) |
363 |
printf("%d %d ", p->xy[corn[i][0]], |
364 |
p->xy[corn[i][1]]); |
365 |
printf("fillpoly\n"); |
366 |
} |
367 |
|
368 |
|
369 |
xform(xp, yp, p) /* transform a point according to p */ |
370 |
register int *xp, *yp; |
371 |
register PRIMITIVE *p; |
372 |
{ |
373 |
int x, y; |
374 |
|
375 |
switch (p->arg0 & 060) { |
376 |
case 0: /* right */ |
377 |
x = *xp; |
378 |
y = *yp; |
379 |
break; |
380 |
case 020: /* up */ |
381 |
x = (XYSIZE-1) - *yp; |
382 |
y = *xp; |
383 |
break; |
384 |
case 040: /* left */ |
385 |
x = (XYSIZE-1) - *xp; |
386 |
y = (XYSIZE-1) - *yp; |
387 |
break; |
388 |
case 060: /* down */ |
389 |
x = *yp; |
390 |
y = (XYSIZE-1) - *xp; |
391 |
break; |
392 |
} |
393 |
*xp = CONV(x, p->xy[XMX] - p->xy[XMN]) + p->xy[XMN]; |
394 |
*yp = CONV(y, p->xy[YMX] - p->xy[YMN]) + p->xy[YMN]; |
395 |
} |
396 |
|
397 |
|
398 |
fillpoly(p) /* fill a polygon */ |
399 |
register PRIMITIVE *p; |
400 |
{ |
401 |
extern char *nextscan(); |
402 |
register char *s; |
403 |
int curx, cury; |
404 |
|
405 |
checkline(); |
406 |
|
407 |
printf("%s %d %d mark\n", p->arg0 & 0100 ? "false" : "true", |
408 |
p->arg0>>2 & 03, p->arg0 & 03); |
409 |
s = p->args; |
410 |
while ((s = nextscan(nextscan(s, "%d", &curx), "%d", &cury)) != NULL) { |
411 |
xform(&curx, &cury, p); |
412 |
printf("%d %d ", curx, cury); |
413 |
} |
414 |
printf("fillpoly\n"); |
415 |
} |
416 |
|
417 |
|
418 |
set(attrib, val) /* set an attribute or context */ |
419 |
int attrib; |
420 |
char *val; |
421 |
{ |
422 |
checkline(); |
423 |
|
424 |
switch (attrib) { |
425 |
case SALL: |
426 |
printf("save\n"); |
427 |
savelvl++; |
428 |
break; |
429 |
case SPAT0: |
430 |
case SPAT1: |
431 |
case SPAT2: |
432 |
case SPAT3: |
433 |
break; |
434 |
default: |
435 |
error(WARNING, "illegal set command"); |
436 |
break; |
437 |
} |
438 |
} |
439 |
|
440 |
|
441 |
unset(attrib) /* unset an attribute or context */ |
442 |
int attrib; |
443 |
{ |
444 |
checkline(); |
445 |
|
446 |
switch (attrib) { |
447 |
case SALL: |
448 |
if (savelvl > 0) { |
449 |
printf("restore\n"); |
450 |
savelvl--; |
451 |
} |
452 |
break; |
453 |
case SPAT0: |
454 |
case SPAT1: |
455 |
case SPAT2: |
456 |
case SPAT3: |
457 |
break; |
458 |
default: |
459 |
error(WARNING, "illegal unset command"); |
460 |
break; |
461 |
} |
462 |
} |
463 |
|
464 |
|
465 |
reset(attrib) /* reset an attribute or context */ |
466 |
int attrib; |
467 |
{ |
468 |
checkline(); |
469 |
|
470 |
switch (attrib) { |
471 |
case SALL: |
472 |
while (savelvl > 0) { |
473 |
printf("restore\n"); |
474 |
savelvl--; |
475 |
} |
476 |
printf("restore save\n"); |
477 |
break; |
478 |
case SPAT0: |
479 |
case SPAT1: |
480 |
case SPAT2: |
481 |
case SPAT3: |
482 |
break; |
483 |
default: |
484 |
error(WARNING, "illegal reset command"); |
485 |
break; |
486 |
} |
487 |
} |