ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/mplot.c
Revision: 1.1
Committed: Sat Feb 22 02:07:26 2003 UTC (21 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Plotting routines for meta-files to line-at-a-time printers
6 */
7
8
9 #include <fcntl.h>
10
11 #include "meta.h"
12
13 #include "plot.h"
14
15 #include "span.h"
16
17
18
19 int minwidth = 0;
20
21 static PLIST inqueue = {NULL, NULL};
22
23 static PRIMITIVE nextp;
24
25
26
27 plot(infp) /* plot meta-file */
28
29 FILE *infp;
30
31 {
32
33 do {
34 readp(&nextp, infp);
35 initplot();
36 while (inqueue.ptop != NULL || isprim(nextp.com))
37 plotspan(infp);
38 doglobal(&nextp);
39 fargs(&nextp);
40 } while (nextp.com != PEOF);
41
42 }
43
44
45
46
47
48 initplot() /* initialize this plot */
49
50 {
51
52 thispage();
53 outspan.xleft = 0;
54 outspan.xright = dxsize - 1;
55 outspan.ytop = dysize + linhite - 1;
56 outspan.ybot = dysize;
57
58 }
59
60
61
62
63
64 doglobal(g) /* execute a global command */
65
66 PRIMITIVE *g;
67
68 {
69 char c;
70 int tty;
71
72 switch (g->com) {
73
74 case PEOF:
75 break;
76
77 case PDRAW:
78 fflush(stdout);
79 break;
80
81 case PEOP:
82 if (g->arg0 & 0200) /* advance page */
83 nextpage();
84 else if (g->arg0 == 3) /* continue down */
85 contpage();
86 else
87 error(USER, "illegal continue direction in doglobal");
88 break;
89
90 case PPAUSE:
91 fflush(stdout);
92 tty = open(TTY, O_RDWR);
93 if (g->args != NULL) {
94 write(tty, g->args, strlen(g->args));
95 write(tty, " - (hit return to continue)", 27);
96 } else
97 write(tty, "\007", 1);
98 do {
99 c = '\n';
100 read(tty, &c, 1);
101 } while (c != '\n');
102 close(tty);
103 break;
104
105 case PSET:
106 set(g->arg0, g->args);
107 break;
108
109 case PUNSET:
110 unset(g->arg0);
111 break;
112
113 case PRESET:
114 reset(g->arg0);
115 break;
116
117 default:
118 sprintf(errmsg, "unknown command '%c' in doglobal", g->com);
119 error(WARNING, errmsg);
120 break;
121 }
122
123 }
124
125
126
127
128
129 plotspan(infp) /* plot next span */
130
131 FILE *infp;
132
133 {
134 PLIST lastinq;
135 register PRIMITIVE *p;
136
137 /* clear span */
138 nextspan();
139 /* plot from queue */
140 lastinq.ptop = inqueue.ptop;
141 lastinq.pbot = inqueue.pbot;
142 inqueue.ptop = inqueue.pbot = NULL;
143 while ((p = pop(&lastinq)) != NULL) {
144 doprim(p);
145 pfree(p);
146 }
147 /* plot from file */
148 while (isprim(nextp.com) && CONV(nextp.xy[YMX],dysize) >= outspan.ybot) {
149 doprim(&nextp);
150 fargs(&nextp);
151 readp(&nextp, infp);
152 }
153 /* print out span */
154 outputspan();
155
156 }
157
158
159
160
161
162 nextspan() /* prepare next span */
163
164 {
165 register int i;
166 register char *colp, *tcolp;
167
168 if (spanmin <= spanmax) { /* clear span */
169
170 i = nrows*dxsize;
171 colp = outspan.cols;
172 tcolp = outspan.tcols;
173 while (i--)
174 *colp++ = *tcolp++ = '\0';
175 }
176
177 outspan.ytop -= linhite; /* advance to next */
178 outspan.ybot -= linhite;
179 spanmin = dxsize;
180 spanmax = 0;
181
182 }
183
184
185
186 outputspan() /* output span to printer */
187 {
188 register int i;
189 register char *colp, *tcolp;
190
191 if (spanmin <= spanmax) { /* overlay spans */
192
193 i = nrows*dxsize;
194 colp = outspan.cols;
195 tcolp = outspan.tcols;
196 while (i--)
197 *colp++ |= *tcolp++;
198 }
199 printspan(); /* print span */
200 }
201
202
203
204 doprim(p) /* plot primitive */
205
206 register PRIMITIVE *p;
207
208 {
209 register PRIMITIVE *newp;
210
211 switch (p->com) {
212
213 case PLSEG:
214 plotlseg(p);
215 break;
216
217 case PRFILL:
218 fill((p->arg0&0103) | (pati[(p->arg0>>2)&03]<<2),
219 CONV(p->xy[XMN],dxsize),CONV(p->xy[YMN],dysize),
220 CONV(p->xy[XMX],dxsize)+(p->arg0&0100?-1:0),
221 CONV(p->xy[YMX],dysize)+(p->arg0&0100?-1:0));
222 break;
223
224 case PTFILL:
225 tfill(p);
226 break;
227
228 case PMSTR:
229 printstr(p);
230 break;
231
232 default:
233 sprintf(errmsg, "unknown command '%c' in doprim", p->com);
234 error(WARNING, errmsg);
235 return;
236 }
237
238 if (CONV(p->xy[YMN],dysize) < outspan.ybot) { /* save for next time */
239 if ((newp = palloc()) == NULL)
240 error(SYSTEM, "memory limit exceeded in doprim");
241 mcopy((char *)newp, (char *)p, sizeof(PRIMITIVE));
242 newp->args = savestr(p->args);
243 add(newp, &inqueue);
244 }
245
246 }
247
248
249
250
251
252 plotlseg(p) /* plot a line segment */
253
254 register PRIMITIVE *p;
255
256 {
257 register int ti;
258 long run2 = 0L, rise2 = 0L;
259 int x, y, run, rise, xstop, ystop, hrad, vrad, lpat, n;
260
261 /* compute line pattern */
262 lpat = (p->arg0 >> 2) & 014;
263 if (p->arg0 & 0100 && lpat != 0)
264 lpat += 014;
265 lpat |= p->arg0 & 03;
266
267 ti = (p->arg0 >> 2) & 03; /* compute line radius */
268 ti = WIDTH(ti) / 2;
269 hrad = CONV(ti, dxsize);
270 vrad = CONV(ti, dysize);
271 if (hrad < minwidth)
272 hrad = minwidth;
273 if (vrad < minwidth)
274 vrad = minwidth;
275
276 x = CONV(p->xy[XMX], dxsize); /* start at top */
277 y = CONV(p->xy[YMX], dysize);
278 run = CONV(p->xy[XMN], dxsize) - x;
279 rise = CONV(p->xy[YMN], dysize) - y;
280
281 if (p->arg0 & 0100) /* slope < 0; reverse x */
282 x -= (run = -run);
283
284 xstop = x + run; /* compute end point */
285 ystop = y + rise;
286
287 if ((ti = outspan.ytop+vrad+1-y) < 0) { /* adjust to top of span */
288 run2 = rise2 = (long)ti*run;
289 x += rise2/rise;
290 y += ti;
291 }
292
293 if ((ti = outspan.ybot-vrad-1-ystop) > 0) { /* adjust to bottom of span */
294 xstop += (long)ti*run/rise;
295 ystop += ti;
296 }
297
298 if (abs(run) > -rise)
299 n = abs(xstop - x);
300 else
301 n = y - ystop;
302
303 paintline(x, y, run, rise, hrad, vrad, lpat, run2, rise2, n);
304
305 }
306
307
308
309 /*
310 * This routine paints a line with calls to fill(). The line can
311 * start and end at arbitrary points on a longer line segment.
312 */
313
314 paintline(x, y, run, rise, hrad, vrad, lpat, run2, rise2, n)
315
316 register int x, y;
317 int run, rise;
318 int hrad, vrad;
319 int lpat;
320 long run2, rise2;
321 int n;
322
323 {
324 int xstep, ystep;
325
326 if (run >= 0)
327 xstep = 1;
328 else {
329 xstep = -1;
330 run = -run;
331 }
332 if (rise >= 0)
333 ystep = 1;
334 else {
335 ystep = -1;
336 rise = -rise;
337 }
338 if (n < 0)
339 n = max(run, rise);
340
341 if (run > rise)
342 while (n >= 0)
343 if (run2 >= rise2) {
344 fill(lpat, x-hrad, y-vrad, x+hrad, y+vrad);
345 n--;
346 x += xstep;
347 rise2 += rise;
348 } else {
349 y += ystep;
350 run2 += run;
351 }
352 else
353 while (n >= 0)
354 if (rise2 >= run2) {
355 fill(lpat, x-hrad, y-vrad, x+hrad, y+vrad);
356 n--;
357 y += ystep;
358 run2 += run;
359 } else {
360 x += xstep;
361 rise2 += rise;
362 }
363
364 }
365
366
367
368 tfill(p) /* fill a triangle */
369 register PRIMITIVE *p;
370 {
371 register int x, txmin, txmax;
372 int xmn, ymn, tpat;
373 long xsz, ysz;
374
375 xmn = CONV(p->xy[XMN], dxsize);
376 xsz = CONV(p->xy[XMX], dxsize) - xmn;
377 ymn = CONV(p->xy[YMN], dysize);
378 ysz = CONV(p->xy[YMX], dysize) - ymn;
379 if (xsz <= 0 || ysz <= 0)
380 return;
381 txmin = (outspan.ybot - ymn)*xsz/ysz;
382 txmax = (outspan.ytop - ymn)*xsz/ysz;
383 if (p->arg0 & 020) { /* up or down */
384 x = txmin;
385 txmin = xsz - txmax;
386 txmax = xsz - x;
387 }
388 txmin += xmn;
389 txmax += xmn;
390 txmin = max(txmin, xmn);
391 txmax = min(txmax, xmn + (int)xsz - 1);
392 tpat = (p->arg0&0103) | (pati[(p->arg0>>2)&03]<<2);
393
394 if (p->arg0 & 040) { /* left or down */
395 fill(tpat, xmn, ymn, txmin - 1, ymn + (int)ysz - 1);
396 for (x = txmin; x <= txmax; x++)
397 if (p->arg0 & 020) /* down */
398 fill(tpat, x, ymn, x, (int)(ysz-(x-xmn)*ysz/xsz) + ymn - 1);
399 else /* left */
400 fill(tpat, x, (int)((x-xmn)*ysz/xsz) + ymn, x, ymn + (int)ysz - 1);
401 } else { /* right or up */
402 for (x = txmin; x <= txmax; x++)
403 if (p->arg0 & 020) /* up */
404 fill(tpat, x, (int)(ysz-(x-xmn)*ysz/xsz) + ymn, x, ymn + (int)ysz - 1);
405 else /* right */
406 fill(tpat, x, ymn, x, (int)((x-xmn)*ysz/xsz) + ymn - 1);
407 fill(tpat, txmax + 1, ymn, xmn + (int)xsz - 1, ymn + (int)ysz - 1);
408 }
409 }
410
411
412
413
414 fill(attrib, xmin, ymin, xmax, ymax) /* fill rectangle with attribute */
415
416 int attrib;
417 int xmin, ymin, xmax, ymax;
418
419 {
420 int filpat;
421 int rpos;
422 unsigned char *pattr;
423 register char *colp;
424 register int i;
425
426 xmin = max(xmin, outspan.xleft) - outspan.xleft;
427 ymin = max(ymin, outspan.ybot) - outspan.ybot;
428 xmax = min(xmax, outspan.xright) - outspan.xleft;
429 ymax = min(ymax, outspan.ytop) - outspan.ybot;
430
431 for (rpos = 0; rpos < nrows; rpos++)
432
433 if (rpos >= ymin >> 3 && rpos <= ymax >> 3) {
434
435 filpat = 0377;
436 if (rpos == ymin >> 3) {
437 i = ymin & 07;
438 filpat = (filpat >> i) << i;
439 }
440 if (rpos == ymax >> 3) {
441 i = ~ymax & 07;
442 filpat = ((filpat << i) & 0377) >> i;
443 }
444
445 pattr = pattern[(attrib&074)>>2]
446 [((outspan.ybot>>3)+rpos)%(PATSIZE>>3)];
447
448 if (attrib & 0100) {
449 colp = &outspan.tcols[rpos*dxsize + xmin];
450 for (i = xmin; i <= xmax; i++)
451 *colp++ ^= filpat & pattr[i%PATSIZE];
452 } else {
453 colp = &outspan.cols[rpos*dxsize + xmin];
454 for (i = xmin; i <= xmax; i++)
455 *colp++ |= filpat & pattr[i%PATSIZE];
456 }
457
458 spanmin = min(xmin, spanmin);
459 spanmax = max(xmax, spanmax);
460 }
461
462 }