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