ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/rplot.c
Revision: 1.3
Committed: Sat Nov 15 02:13:37 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad4R2P2, rad5R0, rad5R1, rad3R7P2, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9, rad4R2P1
Changes since 1.2: +61 -70 lines
Log Message:
Continued ANSIfication, and reduced other compile warnings.

File Contents

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