Back to index

radiance  4R0+20100331
psplot.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: psplot.c,v 1.3 2003/11/15 02:13:37 schorsch Exp $";
00003 #endif
00004 /*
00005  *  psplot.c - routines for generating PostScript output.
00006  *
00007  *     9/23/88
00008  */
00009 
00010 #include <ctype.h>
00011 
00012 #include "meta.h"
00013 #include "plot.h"
00014 #include "psplot.h"
00015 
00016 #ifdef SMALLAREA
00017 #define HMARGIN             (0.2*72)             /* horizontal margin */
00018 #define VMARGIN             (0.2*72)             /* vertical margin */
00019 #define PWIDTH              (6*72-2*HMARGIN)     /* width of device */
00020 #define PHEIGHT             (6*72-2*VMARGIN)     /* height of device */
00021 #else
00022 #define HMARGIN             (.6*72)                     /* horizontal margin */
00023 #define VMARGIN             (.6*72)                     /* vertical margin */
00024 #define PWIDTH              (8.5*72-2*HMARGIN)   /* width of device */
00025 #define PHEIGHT             (11*72-2*VMARGIN)    /* height of device */
00026 #endif
00027 
00028 #define PSQUARE             PWIDTH               /* maximal square */
00029 
00030 #define MAXPATHL     700                  /* maximum path length */
00031 
00032 #define PREFIX              "seg_"        /* name prefix */
00033 #define ESCCHAR             '#'           /* to introduce hex in name */
00034 
00035 #define checkline()  if (inaline) endline()
00036 
00037 
00038 static int    savelvl = 0;
00039 
00040 static int    inaline = 0;
00041 
00042 static char   hexdigit[] = "0123456789ABCDEF";
00043 
00044 static char   buf[512];
00045 
00046 static void endline(void);
00047 
00048 
00049 static char *
00050 convertname(s)                            /* convert to segment name */
00051 char   *s;
00052 {
00053        register char *cp, *cp0;
00054 
00055        for (cp = buf, cp0 = PREFIX; *cp0; )
00056               *cp++ = *cp0++;
00057        for (cp0 = s; *cp0; cp0++) {
00058               if (isalnum(*cp0))
00059                      *cp++ = *cp0;
00060               else {
00061                      *cp++ = ESCCHAR;
00062                      *cp++ = hexdigit[*cp0 >> 4];
00063                      *cp++ = hexdigit[*cp0 & 0xf];
00064               }
00065        }
00066        *cp = '\0';
00067        return(buf);
00068 }
00069 
00070 
00071 static char *
00072 convertstring(              /* convert to acceptable string */
00073        register char *s
00074 )
00075 {
00076        register char *cp;
00077        
00078        for (cp = buf; *s; s++) {
00079               if (*s == '(' || *s == ')')
00080                      *cp++ = '\\';
00081               if (isprint(*s))
00082                      *cp++ = *s;
00083               else {
00084                      *cp++ = '\\';
00085                      *cp++ = (*s>>6) + '0';
00086                      *cp++ = (*s>>3 & 07) + '0';
00087                      *cp++ = (*s & 07) + '0';
00088               }
00089        }
00090        *cp = '\0';
00091        return(buf);
00092 }
00093 
00094 
00095 void
00096 init(                /* initialize */
00097        char   *id
00098 )
00099 {
00100        printf("%%!PS-Adobe-2.0 EPSF-2.0\n");
00101        printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
00102                      HMARGIN+(PWIDTH-PSQUARE)/2.,
00103                      VMARGIN+(PHEIGHT-PSQUARE)/2.,
00104                      HMARGIN+(PWIDTH-PSQUARE)/2.+PSQUARE,
00105                      VMARGIN+(PHEIGHT-PSQUARE)/2.+PSQUARE);
00106        printf("%%%%DocumentFonts: Helvetica Courier\n");
00107        if (id != NULL)
00108               printf("%%%%Creator: %s\n", id);
00109        printf("gsave\n");
00110        printf("save\n");
00111        printf("256 dict begin\n");
00112        printf("%f %f translate\n", HMARGIN+(PWIDTH-PSQUARE)/2.,
00113                      VMARGIN+(PHEIGHT-PSQUARE)/2.);
00114        printf("%f %f scale\n", (double)PSQUARE/XYSIZE,
00115                      (double)PSQUARE/XYSIZE);
00116        printf("/mapping matrix currentmatrix def\n");
00117        printf("/segment {\t\t%% name lth pat col dir xmn ymn xmx ymx\n");
00118        printf("\t/startstate save def\n");
00119        printf("\t128 dict begin\t\t%% get parameters\n");
00120        printf("\t/ymax exch def /xmax exch def\n");
00121        printf("\t/ymin exch def /xmin exch def\n");
00122        printf("\t/orient exch def\n");
00123        printf("\t/colndx exch def /patndx exch def /lthick exch def\n");
00124        printf("\t%% segment name left on stack\n");
00125        printf("\txmax xmin add 2 div ymax ymin add 2 div translate\n");
00126        printf("\txmax xmin sub %d div ymax ymin sub %d div scale\n",
00127                      XYSIZE, XYSIZE);
00128        printf("\torient 90 mul rotate\n");
00129        printf("\t%d %d translate\n", -XYSIZE/2, -XYSIZE/2);
00130        printf("\tcvx exec\t\t\t%% execute segment\n");
00131        printf("\tend\n");
00132        printf("\tstartstate restore\n");
00133        printf("} def\n");
00134        printf("/vstr {\t\t\t%% string\n");
00135        printf("\t0 setcolor\n");
00136        printf("\t/Helvetica findfont setfont\n");
00137        printf("\tdup stringwidth pop %d exch div %d scale\n", XYSIZE, XYSIZE);
00138        printf("\tcurrentfont charorigin translate\n");
00139        printf("\t0 0 moveto show\n");
00140        printf("} def\n");
00141        printf("/charorigin {\t\t\t%% font charorigin xorg yorg\n");
00142        printf("\tdup /FontBBox get aload pop pop pop\n");
00143        printf("\t3 2 roll /FontMatrix get transform\n");
00144        printf("\texch neg exch neg\n");
00145        printf("} def\n");
00146        printf("/newline {\t\t\t%% lpat lthick col x0 y0\n");
00147        printf("\tnewpath moveto\n");
00148        printf("\tsetcolor setlthick setlpat\n");
00149        printf("} def\n");
00150        printf("/rfilldict 4 dict def\n");
00151        printf("/rfill {\t\t\t%% pat col xmn ymn xmx ymx\n");
00152        printf("\trfilldict begin\n");
00153        printf("\t/ymax exch def /xmax exch def\n");
00154        printf("\t/ymin exch def /xmin exch def\n");
00155        printf("\tsetcolor setpattern\n");
00156        printf("\tnewpath\n");
00157        printf("\txmin ymin moveto\n");
00158        printf("\txmax ymin lineto\n");
00159        printf("\txmax ymax lineto\n");
00160        printf("\txmin ymax lineto\n");
00161        printf("\tclosepath patfill\n");
00162        printf("\tend\n");
00163        printf("} def\n");
00164        printf("/fillpoly {\t\t\t%% pat col mark x1 y1 .. xn yn\n");
00165        printf("\tnewpath moveto\n");
00166        printf("\tcounttomark 2 idiv { lineto } repeat cleartomark\n");
00167        printf("\tclosepath\n");
00168        printf("\tsetcolor setpattern\n");
00169        printf("\t{ gsave 0 setlinewidth stroke grestore } if\n");
00170        printf("\tpatfill\n");
00171        printf("} def\n");
00172        printf("/mstr {\t\t\t%% fnt col x y\n");
00173        printf("\t100 add moveto setcolor setmfont show\n");
00174        printf("} def\n");
00175        printf("/patfill {\n");
00176        printf("\tfill\t\t\t\t%% unimplemented\n");
00177        printf("} def\n");
00178        printf("/setmfont {\t\t\t%% fontndx\n");
00179        printf("\tmfontab exch get setfont\n");
00180        printf("} def\n");
00181        printf("/setcolor {\t\t\t%% colndx\n");
00182        printf("\tcolndx 0 ne { pop colndx } if\n");
00183        printf("\trgbcoltab exch get aload pop setrgbcolor\n");
00184        printf("} def\n");
00185        printf("/setlthick {\t\t\t%% lthick\n");
00186        printf("\tlthick 0 ne { pop lthick } if\n");
00187        printf("\tsetlinewidth\n");
00188        printf("} def\n");
00189        printf("/setlpat {\t\t\t%% lpatndx\n");
00190        printf("\tdashtab exch get 0 setdash\n");
00191        printf("} def\n");
00192        printf("/setpattern {\t\t\t%% patndx\n");
00193        printf("\tpop\t\t\t\t%% unimplemented\n");
00194        printf("} def\n");
00195        printf("/canonfont\t\t\t%% canonical matrix string font\n");
00196        printf("\t/Courier findfont\n");
00197        printf("\tdup charorigin matrix translate\n");
00198        printf("\tmakefont\n");
00199        printf("def\n");
00200        printf("/mfontab [\t\t\t%% hardware font table\n");
00201        printf("\t[\n");
00202        printf("\t\t[ 340 0 0 340 0 -340 ]\n");
00203        printf("\t\t[ 681 0 0 340 0 -340 ]\n");
00204        printf("\t\t[ 340 0 0 681 0 -681 ]\n");
00205        printf("\t\t[ 681 0 0 681 0 -681 ]\n");
00206        printf("\t\t[ 282 0 0 282 0 -282 ]\n");
00207        printf("\t\t[ 564 0 0 282 0 -282 ]\n");
00208        printf("\t\t[ 282 0 0 564 0 -564 ]\n");
00209        printf("\t\t[ 564 0 0 564 0 -564 ]\n");
00210        printf("\t\t[ 199 0 0 199 0 -199 ]\n");
00211        printf("\t\t[ 398 0 0 199 0 -199 ]\n");
00212        printf("\t\t[ 199 0 0 398 0 -398 ]\n");
00213        printf("\t\t[ 398 0 0 398 0 -398 ]\n");
00214        printf("\t\t[ 169 0 0 169 0 -169 ]\n");
00215        printf("\t\t[ 339 0 0 169 0 -169 ]\n");
00216        printf("\t\t[ 169 0 0 339 0 -339 ]\n");
00217        printf("\t\t[ 339 0 0 339 0 -339 ]\n");
00218        printf("\t]\n");
00219        printf("\t{ canonfont exch makefont }\n");
00220        printf("\tforall\n");
00221        printf("] def\n");
00222        printf("/dashtab [ [ ] [ 200 80 ] [ 80 80 ] [ 200 80 80 80 ] ] def\n");
00223        printf("/rgbcoltab [ [ 0 0 0 ] [ 1 0 0 ] [ 0 1 0 ] [ 0 0 1 ] ] def\n");
00224        printf("/colndx 0 def /patndx 0 def /lthick 0 def\n");
00225        printf("%%%%EndProlog\n");
00226 }
00227 
00228 
00229 void
00230 done(void)                         /* done with graphics */
00231 {
00232        printf("end\nrestore\ngrestore\n");
00233 }
00234 
00235 
00236 void
00237 endpage(void)               /* done with page */
00238 {
00239        checkline();
00240 
00241        printf("showpage\nmapping setmatrix\n");
00242 }
00243 
00244 
00245 void
00246 segopen(                    /* open a segment */
00247        char   *s
00248 )
00249 {
00250        checkline();
00251 
00252        printf("/%s {\n", convertname(s));
00253 }
00254 
00255 
00256 void
00257 segclose(void)                     /* close a segment */
00258 {
00259        checkline();
00260 
00261        printf("} def\n");
00262 }
00263 
00264 
00265 void
00266 doseg(               /* instance of a segment */
00267        register PRIMITIVE   *p
00268 )
00269 {
00270        checkline();
00271 
00272        printf("/%s %d %d %d ", convertname(p->args),
00273                      WIDTH(p->arg0>>2 & 03),
00274                      p->arg0>>2 & 03, p->arg0 & 03);
00275        printf("%d %d %d %d %d segment\n", p->arg0>>4,
00276                      p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]);
00277 }
00278 
00279 
00280 extern void
00281 printstr(                   /* print a string */
00282        register PRIMITIVE   *p
00283 )
00284 {
00285        checkline();
00286        printf("(%s) %d %d %d %d mstr\n", convertstring(p->args),
00287                      p->arg0>>2 & 017, p->arg0 & 03,
00288                      p->xy[XMN], p->xy[YMX]);
00289 }
00290 
00291 
00292 void
00293 plotvstr(                   /* print a vector string */
00294        register PRIMITIVE   *p
00295 )
00296 {
00297        checkline();
00298 
00299        printf("(%s) /vstr %d 0 %d ", convertstring(p->args),
00300                      WIDTH(p->arg0>>2 & 03), p->arg0 & 03);
00301        printf("%d %d %d %d %d segment\n", p->arg0>>4,
00302                      p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]);
00303 }
00304 
00305 
00306 void
00307 plotlseg(                   /* plot a line segment */
00308        register PRIMITIVE   *p
00309 )
00310 {
00311        static int    right = FALSE;
00312        static int    curx, cury;
00313        static int    curlpat, curlthick, curlcol;
00314        int    y1, y2;
00315        int    lpat, lthick, lcol;
00316 
00317        if (p->arg0 & 0100) {
00318               y1 = p->xy[YMX];
00319               y2 = p->xy[YMN];
00320        } else {
00321               y1 = p->xy[YMN];
00322               y2 = p->xy[YMX];
00323        }
00324        lpat = p->arg0>>4 & 03;
00325        lthick = WIDTH(p->arg0>>2 & 03);
00326        lcol = p->arg0 & 03;
00327        if (!inaline || lpat != curlpat ||
00328                      lthick != curlthick || lcol != curlcol) {
00329               checkline();
00330               printf("%d %d %d %d %d newline\n",
00331                             curlpat = lpat,
00332                             curlthick = lthick,
00333                             curlcol = lcol,
00334                             curx = p->xy[XMN],
00335                             cury = y1);
00336        }
00337        if (curx == p->xy[XMN] && cury == y1) {
00338               printf("%d %d lineto\n", curx = p->xy[XMX], cury = y2);
00339        } else if (curx == p->xy[XMX] && cury == y2) {
00340               printf("%d %d lineto\n", curx = p->xy[XMN], cury = y1);
00341        } else if ( (right = !right) ) {
00342               printf("%d %d moveto ", p->xy[XMN], y1);
00343               printf("%d %d lineto\n", curx = p->xy[XMX], cury = y2);
00344        } else {
00345               printf("%d %d moveto ", p->xy[XMX], y2);
00346               printf("%d %d lineto\n", curx = p->xy[XMN], cury = y1);
00347        }
00348        if (++inaline >= MAXPATHL)
00349               endline();
00350 }
00351 
00352 
00353 void
00354 endline(void)               /* close current line */
00355 {
00356        printf("stroke\n");
00357        inaline = 0;
00358 }
00359 
00360 
00361 extern void
00362 fillrect(                   /* fill a rectangle */
00363        register PRIMITIVE   *p
00364 )
00365 {
00366        checkline();
00367 
00368        printf("%d %d %d %d %d %d rfill\n", p->arg0>>2 & 03, p->arg0 & 03,
00369                      p->xy[XMN], p->xy[YMN], p->xy[XMX], p->xy[YMX]);
00370 }
00371 
00372 
00373 extern void
00374 filltri(                    /* fill a triangle */
00375        register PRIMITIVE   *p
00376 )
00377 {
00378        static short  corn[4][2] = {{XMN,YMX},{XMN,YMN},{XMX,YMN},{XMX,YMX}};
00379        int           orient;
00380        register int  i;
00381        
00382        checkline();
00383 
00384        printf("false %d %d mark\n", p->arg0>>2 & 03, p->arg0 & 03);
00385        orient = p->arg0>>4 & 03;
00386        for (i = 0; i < 4; i++)
00387               if (i != orient)
00388                      printf("%d %d ", p->xy[corn[i][0]],
00389                                    p->xy[corn[i][1]]);
00390        printf("fillpoly\n");
00391 }
00392 
00393 
00394 void
00395 xform(        /* transform a point according to p */
00396        register int  *xp,
00397        register int  *yp,
00398        register PRIMITIVE  *p
00399 )
00400 {
00401     int  x = 0, y = 0;
00402 
00403     switch (p->arg0 & 060) {
00404        case 0:                     /* right */
00405            x = *xp;
00406            y = *yp;
00407            break;
00408        case 020:            /* up */
00409            x = (XYSIZE-1) - *yp;
00410            y = *xp;
00411            break;
00412        case 040:            /* left */
00413            x = (XYSIZE-1) - *xp;
00414            y = (XYSIZE-1) - *yp;
00415            break;
00416        case 060:            /* down */
00417            x = *yp;
00418            y = (XYSIZE-1) - *xp;
00419            break;
00420     }
00421     *xp = CONV(x, p->xy[XMX] - p->xy[XMN]) + p->xy[XMN];
00422     *yp = CONV(y, p->xy[YMX] - p->xy[YMN]) + p->xy[YMN];
00423 }
00424 
00425 
00426 extern void
00427 fillpoly(p)                 /* fill a polygon */
00428 register PRIMITIVE   *p;
00429 {
00430        register char *s;
00431        int    curx, cury;
00432 
00433        checkline();
00434 
00435        printf("%s %d %d mark\n", p->arg0 & 0100 ? "false" : "true",
00436                      p->arg0>>2 & 03, p->arg0 & 03);
00437        s = p->args;
00438        while ((s = nextscan(nextscan(s, "%d", (char*)&curx), "%d", (char*)&cury)) != NULL) {
00439               xform(&curx, &cury, p);
00440               printf("%d %d ", curx, cury);
00441        }
00442        printf("fillpoly\n");
00443 }
00444 
00445 
00446 void
00447 set(          /* set an attribute or context */
00448        int    attrib,
00449        char   *val
00450 )
00451 {
00452        checkline();
00453 
00454        switch (attrib) {
00455        case SALL:
00456               printf("save\n");
00457               savelvl++;
00458               break;
00459        case SPAT0:
00460        case SPAT1:
00461        case SPAT2:
00462        case SPAT3:
00463               break;
00464        default:
00465               error(WARNING, "illegal set command");
00466               break;
00467        }
00468 }
00469 
00470 
00471 void
00472 unset(               /* unset an attribute or context */
00473        int    attrib
00474 )
00475 {
00476        checkline();
00477 
00478        switch (attrib) {
00479        case SALL:
00480               if (savelvl > 0) {
00481                      printf("restore\n");
00482                      savelvl--;
00483               }
00484               break;
00485        case SPAT0:
00486        case SPAT1:
00487        case SPAT2:
00488        case SPAT3:
00489               break;
00490        default:
00491               error(WARNING, "illegal unset command");
00492               break;
00493        }
00494 }
00495 
00496 
00497 void
00498 reset(               /* reset an attribute or context */
00499        int    attrib
00500 )
00501 {
00502        checkline();
00503 
00504        switch (attrib) {
00505        case SALL:
00506               while (savelvl > 0) {
00507                      printf("restore\n");
00508                      savelvl--;
00509               }
00510               printf("restore save\n");
00511               break;
00512        case SPAT0:
00513        case SPAT1:
00514        case SPAT2:
00515        case SPAT3:
00516               break;
00517        default:
00518               error(WARNING, "illegal reset command");
00519               break;
00520        }
00521 }