Back to index

radiance  4R0+20100331
x11plot.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: x11plot.c,v 1.4 2007/11/21 18:51:05 greg Exp $";
00003 #endif
00004 /*
00005  *   X window plotting functions
00006  *
00007  *      2/26/86
00008  */
00009 
00010 
00011 #include  "meta.h"
00012 
00013 #include  "plot.h"
00014 
00015 #include "string.h"
00016 
00017 #undef  TRUE
00018 
00019 #undef  FALSE
00020 
00021 #include  <X11/Xlib.h>
00022 
00023 extern void   replay(int xmin, int ymin, int xmax, int ymax);
00024 
00025 #define  BORWIDTH  5
00026 
00027 #define  BlackPix BlackPixel(dpy,0 )
00028 #define  WhitePix WhitePixel(dpy,0 )
00029 
00030 #define  mapx(x)  CONV(x,dxsize)
00031 #define  mapy(y)  CONV((XYSIZE-1)-(y),dysize)
00032 
00033 #define  MAXVERT  128
00034 
00035 #define  MAXCOLOR    65535
00036 
00037                             /* X window fonts */
00038 static struct {
00039        char  *name;         /* font name */
00040        Font  id;            /* font id */
00041 } font[] = {
00042        {"9x15", 0},
00043        {"8x13", 0},
00044        {"6x13", 0},
00045        {"vtdwidth", 0},
00046        {"accordbfx", 0}
00047 };
00048 
00049                                    /* map to our matrix string types */
00050 static int  fontmap[16] = {0,3,0,3,1,3,1,3,2,4,2,4,2,4,2,4};
00051 
00052 #define       LONG_DASHED_LIST_LENGTH            2
00053 #define       SHORT_DASHED_LIST_LENGTH    2
00054 #define       DOTTED_LIST_LENGTH          2
00055 
00056 int dash_list_length[] = {
00057        0,
00058        LONG_DASHED_LIST_LENGTH,
00059        SHORT_DASHED_LIST_LENGTH,
00060        DOTTED_LIST_LENGTH,
00061        };
00062 
00063 unsigned char long_dashed[LONG_DASHED_LIST_LENGTH] =    {4,7};
00064 unsigned char short_dashed[SHORT_DASHED_LIST_LENGTH] =  {4,3};
00065 unsigned char dotted[DOTTED_LIST_LENGTH] =              {5,2};
00066 
00067 unsigned char *Linetypes[] = {
00068        0,
00069        long_dashed,
00070        short_dashed,
00071        dotted,
00072        };
00073 
00074 Display       *dpy;
00075 Window wind;                /* our window */
00076 Colormap cmap;
00077 GC     gc;
00078 Font   curfont;             /* current font */
00079 int    curwidth;            /* current width of lines */
00080 int    curfill;             /* current fill style (FillTiled or FillSolid) */
00081 int    curcol;                     /* current color */
00082 int    curlinetype;         /* current line style */
00083 XGCValues gcval;
00084 int    pixel[4];
00085 int    dxsize, dysize;             /* window size */
00086 int    debug = False;              /* use XSynchronize if true */
00087 
00088 static void
00089 adjustsize()
00090 {
00091        if (dxsize > dysize)
00092               dxsize = dysize;
00093        else
00094               dysize = dxsize;
00095 }
00096 
00097 
00098 void
00099 init(name, geom)            /* initialize window */
00100 char  *name;
00101 char  *geom;
00102 {
00103     char  defgeom[32];
00104     XColor  cdef,dum;
00105     XEvent  evnt;
00106 
00107     curfont = curfill = curcol = -1;
00108     curlinetype = 0;
00109 
00110     if ((dpy=XOpenDisplay("")) == NULL)
00111        error(SYSTEM, "can't open display");
00112     
00113     /* for debugging so we don't have to flush always */
00114     if (debug) 
00115        (void) XSynchronize(dpy, True);
00116 
00117     dxsize = DisplayWidth(dpy,0) - 2*BORWIDTH-4;
00118     dysize = DisplayHeight(dpy,0) - 2*BORWIDTH-100;
00119     adjustsize();
00120 
00121     sprintf(defgeom, "=%dx%d+2+25", dxsize, dysize);
00122     /* XUseGeometry(dpy,0,geom,defgeom,BORWIDTH,100,100,100,100,
00123               &xoff,&yoff,&dxsize,&dysize); */
00124     gc = DefaultGC(dpy,0);                /* get default gc */
00125     cmap = DefaultColormap(dpy,0);        /* and colormap */
00126 
00127     wind = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,dxsize,dysize,
00128               BORWIDTH,BlackPix,WhitePix);
00129     if (wind == 0)
00130        error(SYSTEM, "can't create window");
00131     XStoreName(dpy, wind, name);
00132     XMapRaised(dpy, wind);
00133     XSelectInput(dpy, wind, StructureNotifyMask | ButtonPressMask | ExposureMask);
00134     if (DisplayPlanes(dpy,0) < 2) {       /* less than 2 color planes, use black */
00135            pixel[0] = pixel[1] = pixel[2] = pixel[3] = BlackPix;
00136     } else {
00137        if (XAllocNamedColor(dpy, cmap, "black", &dum, &cdef)==0)
00138               error(USER,"cannot allocate black!");
00139        pixel[0] = cdef.pixel;
00140        if (XAllocNamedColor(dpy, cmap, "red", &dum, &cdef)==0)
00141               {
00142               error(WARNING,"cannot allocate red");
00143               cdef.pixel = BlackPix;
00144               }
00145        pixel[1] = cdef.pixel;
00146        if (XAllocNamedColor(dpy, cmap, "green", &dum, &cdef)==0)
00147               {
00148               error(WARNING,"cannot allocate green");
00149               cdef.pixel = BlackPix;
00150               }
00151        pixel[2] = cdef.pixel;
00152        if (XAllocNamedColor(dpy, cmap, "blue", &dum, &cdef)==0)
00153               {
00154               error(WARNING,"cannot allocate blue");
00155               cdef.pixel = BlackPix;
00156               }
00157        pixel[3] = cdef.pixel;
00158     }
00159 
00160     while (1)
00161        {
00162        XNextEvent(dpy, &evnt);
00163        if (evnt.type == ConfigureNotify) /* wait for first ConfigureNotify */
00164               break;
00165        }
00166     dxsize = evnt.xconfigure.width;
00167     dysize = evnt.xconfigure.height;
00168     adjustsize();
00169     while (1)
00170        {
00171        XNextEvent(dpy, &evnt);
00172        if (evnt.type == Expose)    /* wait for first Expose */
00173               break;
00174        }
00175 }
00176 
00177 
00178 void
00179 endpage()            /* end of this graph */
00180 {
00181     XEvent  evnt;
00182     int    quit=False;
00183 
00184     XFlush(dpy);
00185     XBell(dpy, 0);
00186     while ( !quit ) {
00187        XNextEvent(dpy, &evnt);
00188        switch (evnt.type) {
00189          case ConfigureNotify:
00190               dxsize = evnt.xconfigure.width;
00191               dysize = evnt.xconfigure.height;
00192               adjustsize();
00193               break;
00194          case Expose:
00195               replay((int)((long)XYSIZE*evnt.xexpose.x/dxsize),
00196                  (int)((long)XYSIZE*(dysize-evnt.xexpose.y-evnt.xexpose.height)/dysize),
00197                  (int)((long)XYSIZE*(evnt.xexpose.x+evnt.xexpose.width)/dxsize),
00198                  (int)((long)XYSIZE*(dysize-evnt.xexpose.y)/dysize));
00199               break;
00200          case ButtonPress:
00201               quit = True;
00202               break;
00203        } /* switch */
00204     } /* for */
00205     XClearWindow(dpy, wind);
00206 
00207 }
00208 
00209 
00210 
00211 void
00212 printstr(p)          /* output a string */
00213 
00214 register PRIMITIVE  *p;
00215 
00216 {
00217     int  fn;
00218     int  col;
00219 
00220     fn = fontmap[(p->arg0 >> 2) & 017];          /* get font number */
00221                                           /* set font */
00222     if (font[fn].id == 0) 
00223        {
00224        font[fn].id = XLoadFont(dpy, font[fn].name);
00225        if (font[fn].id == 0) 
00226            {
00227            sprintf(errmsg, "can't open font \"%s\"", font[fn].name);
00228            error(SYSTEM, errmsg);
00229            }
00230        }
00231     col = p->arg0 & 03;
00232     if (curcol != col)
00233        {
00234        curcol = col;
00235        XSetForeground(dpy, gc, pixel[col]);
00236        }
00237     if (curfont != font[fn].id) 
00238        {
00239        curfont = font[fn].id;
00240        XSetFont(dpy, gc, curfont);
00241        }
00242 
00243     XDrawImageString(dpy, wind, gc, mapx(p->xy[XMN]), mapy(p->xy[YMN]),
00244               p->args, strlen(p->args));
00245 }
00246 
00247 
00248 
00249 
00250 
00251 void
00252 plotlseg(p)          /* plot a line segment */
00253 
00254 register PRIMITIVE  *p;
00255 
00256 {
00257     int  x1, y1, x2, y2;
00258     int  linetype, ps, pw;
00259     int col;
00260 
00261     linetype = (p->arg0 >> 4) & 03;       /* line style (solid, dashed, etc) */
00262 
00263     col = p->arg0 & 03;                   /* color */
00264 
00265     ps = WIDTH((p->arg0 >> 2) & 03);
00266     pw = CONV((ps)/2, dxsize);
00267 
00268     x1 = mapx(p->xy[XMN]);
00269     x2 = mapx(p->xy[XMX]);
00270     if (p->arg0 & 0100) {          /* reverse slope */
00271        y1 = mapy(p->xy[YMX]);
00272        y2 = mapy(p->xy[YMN]);
00273     } else {
00274        y1 = mapy(p->xy[YMN]);
00275        y2 = mapy(p->xy[YMX]);
00276     }
00277 
00278     if (curcol != col || curwidth != pw)
00279        {
00280        curcol = col;
00281        gcval.foreground = pixel[col];
00282        curwidth = pw;
00283        gcval.line_width = pw*2+1;  /* convert to thickness in pixels */
00284        gcval.join_style = JoinRound;
00285        XChangeGC(dpy, gc, GCJoinStyle|GCLineWidth|GCForeground, &gcval);
00286        }
00287     if (curlinetype != linetype)
00288        {
00289        curlinetype = linetype;
00290        if (linetype==0)
00291               gcval.line_style = LineSolid;
00292        else
00293               {
00294               gcval.line_style = LineOnOffDash;
00295               XSetDashes(dpy, gc, 0, Linetypes[linetype], dash_list_length[linetype]);
00296               }
00297        XChangeGC(dpy, gc, GCLineStyle, &gcval);
00298        }
00299     XDrawLine(dpy,wind,gc,x1,y1,x2,y2);
00300 }
00301 
00302 
00303 void
00304 pXFlush()
00305 {
00306        XFlush(dpy);
00307 }
00308 
00309 
00310 #ifdef  nyet
00311 
00312 static void
00313 fill(xmin,ymin,xmax,ymax,pm)
00314 int xmin,ymin,xmax,ymax;
00315 Pixmap pm;
00316 {
00317        if (pm != 0 && curpat != pm)
00318               {
00319               XSetTile(dpy, gc, pm);
00320               curpat = pm;
00321               }
00322        XFillRectangle(dpy, wind, gc, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
00323 }
00324 
00325 
00326 void
00327 fillrect(p)                 /* fill a rectangle */
00328 
00329 register PRIMITIVE  *p;
00330 
00331 {
00332     int  left, right, top, bottom;
00333 
00334     left = mapx(p->xy[XMN]);
00335     bottom = mapy(p->xy[YMN]);
00336     right = mapx(p->xy[XMX]);
00337     top = mapy(p->xy[YMX]);
00338 
00339     fill(left, top, right, bottom, pixpat(pati[(p->arg0>>2)&03],p->arg0&03));
00340 
00341 }
00342 
00343 
00344 
00345 
00346 void
00347 filltri(p)                  /* fill a triangle */
00348 
00349 register PRIMITIVE  *p;
00350 
00351 {
00352     Vertex  v[4];
00353     int  left, right, top, bottom;
00354 
00355     left = mapx(p->xy[XMN]);
00356     right = mapx(p->xy[XMX]);
00357     top = mapy(p->xy[YMX]);
00358     bottom = mapy(p->xy[YMN]);
00359 
00360     switch (p->arg0 & 060) {
00361     case 0:                 /* right (& down) */
00362        v[0].x = left; v[0].y = bottom;
00363        v[1].x = right; v[1].y = bottom;
00364        v[2].x = right; v[2].y = top;
00365        break;
00366     case 020:               /* up */
00367        v[0].x = right; v[0].y = bottom;
00368        v[1].x = right; v[1].y = top;
00369        v[2].x = left; v[2].y = top;
00370        break;
00371     case 040:               /* left */
00372        v[0].x = right; v[0].y = top;
00373        v[1].x = left; v[1].y = top;
00374        v[2].x = left; v[2].y = bottom;
00375        break;
00376     case 060:               /* down */
00377        v[0].x = left; v[0].y = top;
00378        v[1].x = left; v[1].y = bottom;
00379        v[2].x = right; v[2].y = bottom;
00380        break;
00381     }
00382     v[3].x = v[0].x; v[3].y = v[0].y;
00383     v[0].flags = v[1].flags = v[2].flags = v[3].flags = 0;
00384     if (curfill != FillTiled)
00385            {
00386            XSetFillStyle(dpy, gc, FillTiled);
00387            curfill = FillTiled;
00388            XSetTile(dpy, gc, pixpat(pati[(p->arg0>>2)&03],p->arg0&03));
00389            }
00390     XDrawFIlled(dpy, wind, gc, v, 4);
00391 }
00392 
00393 
00394 vpod
00395 xform(xp, yp, p)            /* transform a point according to p */
00396 
00397 register int  *xp, *yp;
00398 register PRIMITIVE  *p;
00399 
00400 {
00401     int  x, y;
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     
00422     *xp = CONV(x, p->xy[XMX] - p->xy[XMN]) + p->xy[XMN];
00423     *yp = CONV(y, p->xy[YMX] - p->xy[YMN]) + p->xy[YMN];
00424 
00425 }
00426 
00427 
00428 void
00429 fillpoly(p)                 /* fill a polygon */
00430 
00431 register PRIMITIVE  *p;
00432 
00433 {
00434     int  x0, y0, curx, cury;
00435     PolyHandle  polyh;
00436     char  *nextscan();
00437     register char  *s;
00438 
00439     polyh = OpenPoly();
00440 
00441     if ((s = nextscan(nextscan(p->args, "%d", &x0), "%d", &y0)) == NULL)
00442         error(USER, "illegal polygon spec in fillpoly");
00443     
00444     xform(&x0, &y0, p);
00445     x0 = mapx(x0); y0 = mapy(y0);
00446     MoveTo(x0, y0);
00447     
00448     while ((s = nextscan(nextscan(s, "%d", &curx), "%d", &cury)) != NULL) {
00449         xform(&curx, &cury, p);
00450         curx = mapx(curx); cury = mapy(cury);
00451         LineTo(curx, cury);
00452     }
00453     LineTo(x0, y0);
00454     
00455     ClosePoly();
00456 
00457     if (p->arg0 & 0100) {          /* draw border */
00458         if (curpat != 0) {
00459             PenPat(macpat[0]);
00460             curpat = 0;
00461         }
00462         if (curpsiz != 1) {
00463             PenSize(1, 1);
00464             curpsiz = 1;
00465         }
00466        if (curpmod != patOr) {
00467            PenMode(patOr);
00468            curpmod = patOr;
00469        }
00470        FramePoly(polyh);
00471     }
00472     
00473     setfill(p->arg0 & 077);
00474     PaintPoly(polyh);
00475     KillPoly(polyh);
00476     xpos = -1;
00477     ypos = -1;
00478 
00479 }
00480 
00481 #else
00482 
00483 void filltri(PRIMITIVE *p) {}
00484 void fillpoly(PRIMITIVE *p) {}
00485 void fillrect(PRIMITIVE *p) {}
00486 
00487 #endif