Back to index

radiance  4R0+20100331
rplot.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rplot.c,v 1.3 2003/11/15 02:13:37 schorsch Exp $";
00003 #endif
00004 /*
00005  *   Plotting routines for meta-files to raster files
00006  */
00007 
00008 
00009 #include  "meta.h"
00010 #include  "plot.h"
00011 #include  "rast.h"
00012 
00013 
00014 int  minwidth = 0;
00015 
00016 static PLIST  inqueue = {NULL, NULL};
00017 
00018 static PRIMITIVE  nextp;
00019 
00020 static void initplot(void);
00021 static void doglobal(PRIMITIVE  *g);
00022 static void plotblock(FILE  *infp);
00023 static void doprim(PRIMITIVE  *p);
00024 static void doprim(PRIMITIVE  *p);
00025 static void paintline(int  x, int  y, int  run, int  rise, int  hrad, int  vrad,
00026        int  lpat, long  run2, long  rise2, int  n);
00027 static void tfill(PRIMITIVE  *p);
00028 static void fill(int  attrib, int  xmin, int ymin, int xmax, int ymax);
00029 
00030 
00031 void
00032 plot(         /* plot meta-file */
00033        FILE  *infp
00034 )
00035 {
00036     do {
00037        readp(&nextp, infp);
00038        initplot();
00039        while (inqueue.ptop != NULL || isprim(nextp.com))
00040            plotblock(infp);
00041        doglobal(&nextp);
00042        fargs(&nextp);
00043     } while (nextp.com != PEOF);
00044 }
00045 
00046 
00047 void
00048 initplot(void)                     /* initialize this plot */
00049 {
00050     int  i;
00051 
00052     thispage();
00053                                    /* allocate block */
00054     if (outblock.xright <= 0) {
00055        for (i = 0; i < NUMSCANS; i++)
00056            if ((outblock.cols[i] = (unsigned char *)malloc(dxsize)) == NULL)
00057               error(SYSTEM, "out of memory in initplot");
00058     }
00059     outblock.xleft = 0;
00060     outblock.xright = dxsize-1;
00061     if (ydown) {
00062        outblock.ytop = dysize+NUMSCANS-1;
00063        outblock.ybot = dysize;
00064     } else {
00065        outblock.ytop = -1;
00066        outblock.ybot = -NUMSCANS;
00067     }
00068 
00069 }
00070 
00071 
00072 void
00073 doglobal(                   /* execute a global command */
00074        PRIMITIVE  *g
00075 )
00076 {
00077     switch (g->com) {
00078 
00079        case PEOF:
00080            break;
00081 
00082        case PEOP:
00083            if (g->arg0 & 0200)            /* advance page */
00084               nextpage();
00085            else
00086                error(USER, "illegal continue direction in doglobal");
00087            break;
00088 
00089        case PSET:
00090            set(g->arg0, g->args);
00091            break;
00092 
00093        case PUNSET:
00094            unset(g->arg0);
00095            break;
00096 
00097        case PRESET:
00098            reset(g->arg0);
00099            break;
00100 
00101        default:
00102            sprintf(errmsg, "unknown command '%c' in doglobal", g->com);
00103            error(WARNING, errmsg);
00104            break;
00105        }
00106 }
00107 
00108 
00109 
00110 void
00111 plotblock(                  /* plot next block */
00112        FILE  *infp
00113 )
00114 {
00115     PLIST  lastinq;
00116     register PRIMITIVE  *p;
00117 
00118                                    /* clear block */
00119     nextblock();
00120                                    /* plot from queue */
00121     lastinq.ptop = inqueue.ptop;
00122     lastinq.pbot = inqueue.pbot;
00123     inqueue.ptop = inqueue.pbot = NULL;
00124     while ((p = pop(&lastinq)) != NULL) {
00125        doprim(p);
00126        pfree(p);
00127     }
00128                                    /* plot from file */
00129     while (isprim(nextp.com) && inthis(&nextp)) {
00130         doprim(&nextp);
00131        fargs(&nextp);
00132        readp(&nextp, infp);
00133     }
00134                                    /* print out block */
00135     outputblock();
00136 
00137 }
00138 
00139 
00140 
00141 extern void
00142 nextblock(void)             /* prepare next block */
00143 {
00144     register int  i, n;
00145     register unsigned char  *colp;
00146                                           /* clear block */
00147     for (i = 0; i < NUMSCANS; i++) {
00148        colp = outblock.cols[i];
00149        n = dxsize;
00150        while (n--)
00151            *colp++ = IWHT<<3 | IWHT;
00152     }
00153                                           /* advance */
00154     if (ydown) {
00155        outblock.ytop -= NUMSCANS;
00156        outblock.ybot -= NUMSCANS;
00157     } else {
00158        outblock.ytop += NUMSCANS;
00159        outblock.ybot += NUMSCANS;
00160     }
00161     return;
00162 }
00163 
00164 
00165 void
00166 outputblock(void)           /* output block to printer */
00167 {
00168     register int  i, n;
00169     register unsigned char  *colp;
00170 
00171     for (i = 0; i < NUMSCANS; i++) {             /* overlay blocks */
00172 
00173        n = outblock.xright - outblock.xleft + 1;
00174        colp = outblock.cols[i] + outblock.xleft;
00175        while (n--) {
00176            *colp = *colp>>3 & *colp;
00177            colp++;
00178        }
00179     }
00180     printblock();                  /* print block */
00181 }
00182 
00183 
00184 void
00185 doprim(              /* plot primitive */
00186        register PRIMITIVE  *p
00187 )
00188 {
00189     register PRIMITIVE  *newp;
00190     
00191     switch (p->com) {
00192 
00193        case PLSEG:
00194            plotlseg(p);
00195            break;
00196 
00197        case PRFILL:
00198            fill((p->arg0&0103) | (pati[(p->arg0>>2)&03]<<2),
00199                      CONV(p->xy[XMN],dxsize),CONV(p->xy[YMN],dysize),
00200                      CONV(p->xy[XMX],dxsize)+(p->arg0&0100?-1:0),
00201                      CONV(p->xy[YMX],dysize)+(p->arg0&0100?-1:0));
00202            break;
00203 
00204        case PTFILL:
00205            tfill(p);
00206            break;
00207               
00208        default:
00209            sprintf(errmsg, "unknown command '%c' in doprim", p->com);
00210            error(WARNING, errmsg);
00211            return;
00212     }
00213 
00214     if (innext(p)) {               /* save for next time */
00215         if ((newp = palloc()) == NULL)
00216             error(SYSTEM, "memory limit exceeded in doprim");
00217        mcopy((char *)newp, (char *)p, sizeof(PRIMITIVE));
00218        newp->args = savestr(p->args);
00219         add(newp, &inqueue);
00220     }
00221 }
00222 
00223 
00224 void
00225 plotlseg(            /* plot a line segment */
00226        register PRIMITIVE  *p
00227 )
00228 {
00229     register int  ti;
00230     long  run2 = 0L, rise2 = 0L;
00231     int  x, y, run, rise, xstop, ystop, hrad, vrad, lpat, n;
00232 
00233                                           /* compute line pattern */
00234     lpat = (p->arg0 >> 2) & 014;
00235     if (p->arg0 & 0100 && lpat != 0)
00236        lpat += 014;
00237     lpat |= p->arg0 & 03;
00238 
00239     ti = (p->arg0 >> 2) & 03;                    /* compute line radius */
00240     ti = WIDTH(ti) / 2;
00241     hrad = CONV(ti, dxsize);
00242     vrad = CONV(ti, dysize);
00243     if (hrad < minwidth)
00244        hrad = minwidth;
00245     if (vrad < minwidth)
00246        vrad = minwidth;
00247 
00248     x = CONV(p->xy[XMX], dxsize);         /* start at top */
00249     y = CONV(p->xy[YMX], dysize);
00250     run = CONV(p->xy[XMN], dxsize) - x;
00251     rise = CONV(p->xy[YMN], dysize) - y;
00252 
00253     if (p->arg0 & 0100)                          /* slope < 0; reverse x */
00254        x -= (run = -run);
00255 
00256     xstop = x + run;                      /* compute end point */
00257     ystop = y + rise;
00258 
00259     if ((ti = outblock.ytop+vrad+1-y) < 0) {     /* adjust to top of block */
00260        run2 = rise2 = (long)ti*run;
00261        x += rise2/rise;
00262        y += ti;
00263     }
00264 
00265     if ((ti = outblock.ybot-vrad-1-ystop) > 0) { /* adjust to bottom of block */
00266         xstop += (long)ti*run/rise;
00267        ystop += ti;
00268     }
00269 
00270     if (abs(run) > -rise)
00271        n = abs(xstop - x);
00272     else
00273        n = y - ystop;
00274     
00275     paintline(x, y, run, rise, hrad, vrad, lpat, run2, rise2, n);
00276 
00277 }
00278 
00279 
00280 
00281 /*
00282  *  This routine paints a line with calls to fill().  The line can
00283  *    start and end at arbitrary points on a longer line segment.
00284  */
00285 void
00286 paintline(
00287        register int  x,
00288        register int  y,
00289        int  run,
00290        int  rise,
00291        int  hrad,
00292        int  vrad,
00293        int  lpat,
00294        long  run2,
00295        long  rise2,
00296        int  n
00297 )
00298 {
00299     int  xstep, ystep;
00300 
00301     if (run >= 0)
00302        xstep = 1;
00303     else {
00304        xstep = -1;
00305        run = -run;
00306     }
00307     if (rise >= 0)
00308        ystep = 1;
00309     else {
00310        ystep = -1;
00311        rise = -rise;
00312     }
00313     if (n < 0)
00314        n = max(run, rise);
00315 
00316     if (run > rise)
00317        while (n >= 0)
00318            if (run2 >= rise2) {
00319               fill(lpat, x-hrad, y-vrad, x+hrad, y+vrad);
00320               n--;
00321               x += xstep;
00322               rise2 += rise;
00323            } else {
00324               y += ystep;
00325               run2 += run;
00326            }
00327     else
00328        while (n >= 0)
00329            if (rise2 >= run2) {
00330               fill(lpat, x-hrad, y-vrad, x+hrad, y+vrad);
00331               n--;
00332               y += ystep;
00333               run2 += run;
00334            } else {
00335               x += xstep;
00336               rise2 += rise;
00337            }
00338 
00339 }
00340 
00341 
00342 void
00343 tfill(               /* fill a triangle */
00344        register PRIMITIVE  *p
00345 )
00346 {
00347     register int  x, txmin, txmax; 
00348     int  xmn, ymn, tpat;
00349     long  xsz, ysz;
00350 
00351     xmn = CONV(p->xy[XMN], dxsize);
00352     xsz = CONV(p->xy[XMX], dxsize) - xmn;
00353     ymn = CONV(p->xy[YMN], dysize);
00354     ysz = CONV(p->xy[YMX], dysize) - ymn;
00355     if (xsz <= 0 || ysz <= 0)
00356        return;       
00357     txmin = (outblock.ybot - ymn)*xsz/ysz;
00358     txmax = (outblock.ytop - ymn)*xsz/ysz;
00359     if (p->arg0 & 020) {                         /* up or down */
00360        x = txmin;
00361        txmin = xsz - txmax;
00362        txmax = xsz - x;
00363     }
00364     txmin += xmn;
00365     txmax += xmn;
00366     txmin = max(txmin, xmn);
00367     txmax = min(txmax, xmn + (int)xsz - 1);
00368     tpat = (p->arg0&0103) | (pati[(p->arg0>>2)&03]<<2);
00369 
00370     if (p->arg0 & 040) {                         /* left or down */
00371        fill(tpat, xmn, ymn, txmin - 1, ymn + (int)ysz - 1);
00372        for (x = txmin; x <= txmax; x++)
00373            if (p->arg0 & 020)                    /* down */
00374               fill(tpat, x, ymn, x, (int)(ysz-(x-xmn)*ysz/xsz) + ymn - 1);
00375            else                           /* left */
00376               fill(tpat, x, (int)((x-xmn)*ysz/xsz) + ymn, x, ymn + (int)ysz - 1);
00377     } else {                                     /* right or up */
00378        for (x = txmin; x <= txmax; x++)
00379            if (p->arg0 & 020)                    /* up */
00380               fill(tpat, x, (int)(ysz-(x-xmn)*ysz/xsz) + ymn, x, ymn + (int)ysz - 1);
00381            else                           /* right */
00382               fill(tpat, x, ymn, x, (int)((x-xmn)*ysz/xsz) + ymn - 1);
00383        fill(tpat, txmax + 1, ymn, xmn + (int)xsz - 1, ymn + (int)ysz - 1);
00384     }
00385 }
00386 
00387 
00388 
00389 void
00390 fill(  /* fill rectangle with attribute */
00391        register int  attrib,
00392        int  xmin,
00393        int ymin,
00394        int xmax,
00395        int ymax
00396 )
00397 {
00398     register int  i, j;
00399 
00400     xmin = max(xmin, outblock.xleft);
00401     ymin = max(ymin, outblock.ybot);
00402     xmax = min(xmax, outblock.xright);
00403     ymax = min(ymax, outblock.ytop);
00404 
00405     for (j = ymin; j <= ymax; j++)
00406        for (i = xmin; i <= xmax; i++)
00407            if (pattern[(attrib&074)>>2]
00408                      [(j>>3)%(PATSIZE>>3)][i%PATSIZE] & 1<<(j&07)) {
00409 
00410               if (attrib & 0100) {
00411                   pixtog(i,j,attrib&03);
00412               } else {
00413                   pixmix(i,j,attrib&03);
00414               }
00415            }
00416 
00417 }