Back to index

plt-scheme  4.2.1
xwTools3d.c
Go to the documentation of this file.
00001 /***********************************************************
00002 Copyright 2004-2009 PLT Scheme Inc.
00003 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
00004 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
00005 Copyright 1995 by Markus Holzem
00006 
00007                         All Rights Reserved
00008 
00009 Permission to use, copy, modify, and distribute this software and its 
00010 documentation for any purpose and without fee is hereby granted, 
00011 provided that the above copyright notice appear in all copies and that
00012 both that copyright notice and this permission notice appear in 
00013 supporting documentation, and that the names of Digital, MIT, or Kaleb 
00014 Keithley not be used in advertising or publicity pertaining to distribution 
00015 of the software without specific, written prior permission.  
00016 
00017 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00018 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00019 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00020 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00021 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00022 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00023 SOFTWARE.
00024 
00025 ******************************************************************/
00026 
00027 /*
00028  * For documeantation see headerfile
00029  */
00030 
00031 #include <X11/Xlib.h>
00032 #include <X11/IntrinsicP.h>
00033 
00034 #include <xwTools3d.h>
00035 
00036 #include "wxAllocColor.h"
00037 
00038 #define Xaw3dDisplay(w) (XtIsWidget(w) ? XtDisplay(w) : XtDisplayOfObject(w))
00039 #define Xaw3dScreen(w)  (XtIsWidget(w) ? XtScreen(w)  : XtScreenOfObject(w))
00040 
00041 Pixel Xaw3dAllocPixel(
00042     Widget w,               /* widget, that needs the new color value */
00043     Pixel  bg,                     /* background pixel of widget */
00044     float  contrast         /* contrast of new color to background */
00045 )
00046 {
00047     XColor   fg_color,
00048             bg_color;
00049     Display  *dpy = Xaw3dDisplay(w);
00050     Screen   *scn = Xaw3dScreen(w);
00051     Colormap cmap = wx_default_colormap;
00052 
00053     if (bg==BlackPixelOfScreen(scn) || bg==WhitePixelOfScreen(scn)) {
00054        if (contrast>=1.0) 
00055            contrast=2.0-contrast;
00056        fg_color.red = fg_color.green =    fg_color.blue 
00057            = (unsigned short)(contrast*65535.0);
00058     } else {
00059 #       define MIN(x,y) (unsigned short)(((x)<(y))?(x):(y))
00060        bg_color.pixel = bg;
00061        XQueryColor(dpy, cmap, &bg_color);
00062        fg_color.red   = MIN(65535, (int)(contrast*(float)bg_color.red));
00063        fg_color.green = MIN(65535, (int)(contrast*(float)bg_color.green));
00064        fg_color.blue  = MIN(65535, (int)(contrast*(float)bg_color.blue));
00065 #       undef MIN
00066     }
00067     (void)wxAllocColor(dpy, cmap, &fg_color);
00068     return (fg_color.pixel);
00069 }
00070 
00071 /* shadow pixmap data */
00072 #define dark_size 3
00073 static char dark_bits[] = { 0x05, 0x03, 0x06};
00074 #define light_size 3
00075 static char light_bits[] = { 0x02, 0x04, 0x01};
00076 #define gray_size 2
00077 static char gray_bits[] = { 0x02, 0x01};
00078 #ifdef USEGRAY
00079   static XColor Gray = { 0, 0, 0, 0, 0, 0 };
00080 #   define ALLOCGRAY { \
00081         if (!Gray.pixel) { XColor d;\
00082           XAllocNamedColor(dpy,wx_default_colormap,"gray",&Gray,&d);}}
00083 #   define WHITEGRAY (Gray.pixel ? Gray.pixel : WhitePixelOfScreen(scn))
00084 #   define BLACKGRAY (Gray.pixel ? Gray.pixel : BlackPixelOfScreen(scn))
00085 #   define GRAYMIX   {if (Gray.pixel) mix=GRAY;}
00086 #else
00087 #   define ALLOCGRAY {}
00088 #   define WHITEGRAY (WhitePixelOfScreen(scn))
00089 #   define BLACKGRAY (BlackPixelOfScreen(scn))
00090 #   define GRAYMIX   {}
00091 #endif
00092 
00093 Pixmap Xaw3dAllocPixmap(
00094     Widget w,               /* widget, that needs the new color value */
00095     Pixel  bg,                     /* background pixel of widget */
00096     MixType mix             /* how to mix fore- and background */
00097 )
00098 {
00099     Display       *dpy = Xaw3dDisplay(w);
00100     Screen        *scn = Xaw3dScreen(w);
00101     Pixel         fg;
00102     char          *bits;
00103     unsigned int  size;
00104  
00105     ALLOCGRAY;
00106     if (DefaultDepthOfScreen(scn) == 1) {
00107        fg = BlackPixelOfScreen(scn);
00108        bg = WhitePixelOfScreen(scn);
00109     } else if (bg == WhitePixelOfScreen(scn)) {
00110        switch (mix) {
00111        case LIGHTER:       fg = BLACKGRAY; break;
00112        case DARKER:        fg = WHITEGRAY; bg = BlackPixelOfScreen(scn);break;
00113        case GRAY: default: fg = WHITEGRAY; bg = BLACKGRAY;
00114        }
00115        GRAYMIX;
00116     } else if (bg == BlackPixelOfScreen(scn)) {
00117        switch (mix) {
00118        case LIGHTER:       fg = WhitePixelOfScreen(scn); break;
00119        case DARKER:        fg = WHITEGRAY; break;
00120        case GRAY: default: fg = WHITEGRAY; bg = BLACKGRAY;
00121        }
00122        GRAYMIX;
00123     } else {
00124        switch (mix) {
00125        case LIGHTER:
00126            fg = WhitePixelOfScreen(scn);
00127            break;
00128        case DARKER:
00129            fg = BlackPixelOfScreen(scn);
00130            break;
00131        case GRAY: default:
00132            fg = WHITEGRAY;
00133            bg = BLACKGRAY;
00134        }
00135        mix = GRAY;
00136     }
00137     switch (mix) {
00138     case LIGHTER:       bits = light_bits; size = light_size; break;
00139     case DARKER:        bits = dark_bits;  size = dark_size;  break;
00140     case GRAY: default: bits = gray_bits;  size = gray_size;  break;
00141     }
00142     return(XCreatePixmapFromBitmapData(dpy,
00143                                    RootWindowOfScreen (scn),
00144                                    bits, size, size, fg, bg,
00145                                    DefaultDepthOfScreen (scn)));
00146 }
00147 
00148 GC Xaw3dGetGC(
00149     Widget  w,                     /* widget, that needs the new color value */
00150     Boolean be_nice_to_cmap,       /* True: GC uses pxmap, False: GC uses pixel */
00151     Pixmap  pxmap,          /* Pixmap for GC */
00152     Pixel   pixel           /* Pixel for GC */
00153 )
00154 {
00155     XtGCMask  valuemask;
00156     XGCValues values;
00157        
00158     if ((be_nice_to_cmap || DefaultDepthOfScreen(Xaw3dScreen(w))==1) && pxmap) {
00159        valuemask         = GCTile | GCFillStyle;
00160        values.tile       = pxmap;
00161        values.fill_style = FillTiled;
00162     } else {
00163        valuemask         = GCForeground;
00164        values.foreground = pixel;
00165     }
00166     return (XtGetGC(w, valuemask, &values));
00167 }
00168 
00169 GC Xaw3dRecomputeGC(
00170     Widget  new,
00171     Boolean be_nice_to_cmap,
00172     Pixmap  new_pxmap,
00173     Pixel   new_pixel,
00174     Widget  old,
00175     Pixmap  old_pxmap,
00176     Pixel   old_pixel,
00177     GC      old_GC)
00178 {
00179     if (be_nice_to_cmap)
00180        Xaw3dFreePixmap(old, old_pxmap);
00181     Xaw3dReleaseGC(old, old_GC);
00182     return (Xaw3dGetGC(new, be_nice_to_cmap, new_pxmap, new_pixel));
00183 }
00184 
00185 void Xaw3dDrawRectangle(
00186 Display    *dpy,            /* Display for drawing */
00187 Window     win,                    /* Window for drawing */
00188 GC         lightGC,         /* GC for light color */
00189 GC         shadowGC,        /* GC for shadow color */
00190 GC         backgroundGC,    /* GC for background color */
00191 GC         fgGC,
00192 int        x, int y,        /* upper left corner of rectangle */
00193 unsigned   width, unsigned height, /* width and height of rectangle */
00194 int        thickness,              /* thickness of shadow */
00195 ShadowType shadow_type             /* type of shadow */
00196 )
00197 {
00198     GC       topGC, botGC, tempGC;
00199     unsigned inner_thickness = 0, orig_thickness;
00200     XPoint   pt[6];
00201 
00202     switch (shadow_type) {
00203     case XAW3D_BACKGROUND:
00204        topGC = botGC = backgroundGC;
00205        break;
00206     case XAW3D_ETCHED_IN:
00207        inner_thickness = thickness/2;
00208        thickness      -= inner_thickness;
00209     case XAW3D_IN:
00210     case XAW3D_IN_HARD:
00211     case XAW3D_XED:
00212        topGC = shadowGC;
00213        botGC = lightGC;
00214        break;
00215     case XAW3D_ETCHED_OUT:
00216        inner_thickness = thickness/2;
00217        thickness      -= inner_thickness;
00218     case XAW3D_OUT:
00219     default:
00220        topGC = lightGC;
00221        botGC = shadowGC;
00222     }
00223 
00224     orig_thickness = thickness;
00225 
00226     /*
00227      * 1 shadow:  thickness == thickness,
00228      *            inner_thickness == 0
00229      * 2 shadows: thickness == thickness-inner_thickness
00230      *            inner_thickness != 0
00231      */
00232     while (thickness) {
00233        /* Points for shadows are numbered as follows:
00234        *
00235        *  0-------------------------1
00236        *  |                        /|     there are only
00237        *  |  3                    / |     the points 0 and 3
00238        *  |  |-------------------/  |     to change
00239        *  |  |                  2|  |     from top to bottom shadow
00240        *  |  |                   |  |
00241        *  |  |4                  |  |
00242        *  |  /-------------------|  |
00243        *  | /                    3' |
00244        *  |/                        |
00245        *  5-------------------------0'
00246        */
00247        /* top-left shadow */
00248        pt[0].x = x;                 pt[0].y = y;
00249        pt[1].x = x+width;           pt[1].y = y;
00250        pt[2].x = x+width-thickness; pt[2].y = y+thickness;
00251        pt[3].x = x+thickness;       pt[3].y = y+thickness;
00252        pt[4].x = x+thickness;       pt[4].y = y+height-thickness ;
00253        pt[5].x = x;                 pt[5].y = y+height;
00254        XFillPolygon(dpy, win, topGC, pt, 6, Complex, CoordModeOrigin);
00255        /* bottom-right shadow */
00256        pt[0].x = x+width;           pt[0].y = y+height;
00257        pt[3].x = x+width-thickness; pt[3].y = y+height-thickness;
00258        XFillPolygon(dpy, win, botGC, pt, 6, Complex, CoordModeOrigin);
00259        /* an inner shadow to draw? */
00260        if (inner_thickness) {
00261            x += thickness; y += thickness;
00262            width -= 2*thickness; height -= 2*thickness;
00263            /* exchange top and bottom color */
00264            tempGC = topGC; topGC = botGC; botGC = tempGC;
00265            /* thickness of inner shadow and no further to draw */
00266            thickness=inner_thickness; inner_thickness = 0;
00267        } else {
00268            /* terminate loop, no further shadow to draw */
00269            thickness = 0;
00270        }
00271     }
00272     
00273 
00274     if ((shadow_type == XAW3D_OUT_HARD)
00275        || (shadow_type == XAW3D_IN_HARD)
00276        || (shadow_type == XAW3D_XED))
00277       XDrawRectangle(dpy, win, fgGC, x, y, width-1, height-1);
00278 }
00279 
00280 void Xaw3dDrawLine(
00281 Display    *dpy,            /* Display for drawing */
00282 Window     win,                    /* Window for drawing */
00283 GC         lightGC,         /* GC for light color */
00284 GC         shadowGC,        /* GC for shadow color */
00285 GC         foregroundGC,    /* GC for foreground color */
00286 int        x, int y,        /* upper left corner of line */
00287 unsigned   length,          /* length of line */
00288 int        thickness,              /* thickness of line */
00289 Boolean    vertical,        /* shall line be drawn vertical? */
00290 ShadowType shadow_type             /* type of shadow */
00291 )
00292 {
00293     GC       topGC, botGC;
00294     unsigned topThickness = 0;
00295     unsigned botThickness = 0;
00296     unsigned offset = 0;
00297     unsigned i;
00298     Boolean  dashed = FALSE;
00299 
00300     switch (shadow_type) {
00301     case XAW3D_NO_LINE: /* nothing to do */
00302        return; 
00303     case XAW3D_SINGLE_LINE_DASH:
00304        dashed = True;
00305     case XAW3D_SINGLE_LINE:
00306        topGC = botGC = foregroundGC;
00307        topThickness = 1;
00308        break;
00309     case XAW3D_DOUBLE_LINE_DASH:
00310        dashed = True;
00311     case XAW3D_DOUBLE_LINE:
00312        topGC = botGC = foregroundGC;
00313        topThickness = botThickness = 1;
00314        offset = 1;
00315        break;
00316     case XAW3D_ETCHED_OUT_DASH:
00317        dashed = True;
00318     case XAW3D_ETCHED_OUT:
00319        topGC = lightGC; botGC = shadowGC;
00320        topThickness = thickness/2; botThickness = thickness-topThickness;
00321        break;
00322     case XAW3D_ETCHED_IN_DASH:
00323        dashed = True;
00324     case XAW3D_ETCHED_IN:
00325     default:
00326        topGC = shadowGC; botGC = lightGC;
00327        topThickness = thickness/2; botThickness = thickness-topThickness;
00328     }
00329     if (dashed) { /* Change topGC and botGC to draw dashed lines  */
00330        XGCValues values;
00331        values.line_style = LineOnOffDash;
00332        if (topThickness > 0)
00333            XChangeGC(dpy, topGC, GCLineStyle, &values);
00334        if (botThickness > 0 && botGC != topGC)
00335            XChangeGC(dpy, botGC, GCLineStyle, &values);
00336     }
00337     for (i = 0; i < topThickness; i++) /* draw the line(s) */
00338        if (vertical) XDrawLine(dpy, win, topGC, x+i, y, x+i, y+length);
00339        else          XDrawLine(dpy, win, topGC, x, y+i, x+length, y+i);
00340     for (i = topThickness+offset; i < topThickness+botThickness+offset; i++)
00341        if (vertical) XDrawLine(dpy, win, botGC, x+i, y, x+i, y+length);
00342         else          XDrawLine(dpy, win, botGC, x, y+i, x+length, y+i);
00343     if (dashed) { /* changed GCs back to solid lines */
00344        XGCValues values;
00345        values.line_style = LineSolid;
00346        if (topThickness > 0)
00347            XChangeGC(dpy, topGC, GCLineStyle, &values);
00348        if (botThickness > 0 && botGC != topGC)
00349            XChangeGC(dpy, botGC, GCLineStyle, &values);
00350     }
00351 }
00352 
00353 void Xaw3dDrawToggle(
00354 Display    *dpy,            /* Display for drawing */
00355 Window     win,                    /* Window for drawing */
00356 GC         lightGC,         /* GC for light color */
00357 GC         shadowGC,        /* GC for shadow color */
00358 GC         inGC,            /* GC for pushed/set toggle */
00359 GC         outGC,           /* GC for released/unset toggle */
00360 GC         fgGC,                /* GC for checkmark */
00361 int        x, int y,        /* upper left corner */
00362 unsigned   width,           /* width of toggle button */
00363 int        thickness,              /* thickness of shadow */
00364 Boolean    pushed           /* is toggle pushed(in) or released(out) */
00365 )
00366 {
00367   if (outGC) {
00368     XFillRectangle(dpy, win, /* pushed ? inGC : */ outGC,
00369                  x+thickness, y+thickness,
00370                  width-(2*thickness), width-(2*thickness));
00371   }
00372   Xaw3dDrawRectangle(dpy, win, lightGC, shadowGC, (GC)0, inGC,
00373                    x, y, width, width, thickness,
00374                    XAW3D_IN_HARD);
00375 
00376   if (pushed) {
00377     XDrawLine(dpy, win, fgGC, x+thickness+1, y+thickness, 
00378              x+width-thickness-1, y+width-thickness-2);
00379     XDrawLine(dpy, win, fgGC, x+thickness, y+thickness+1, 
00380              x+width-thickness-2, y+width-thickness-1);
00381 
00382     XDrawLine(dpy, win, fgGC, x+thickness+1, y+width-thickness-1,
00383              x+width-thickness-1, y+thickness+1);
00384     XDrawLine(dpy, win, fgGC, x+thickness, y+width-thickness-2,
00385              x+width-thickness-2, y+thickness);
00386 
00387     XDrawLine(dpy, win, fgGC, x+thickness, y+thickness, 
00388              x+width-thickness-1, y+width-thickness-1);
00389     XDrawLine(dpy, win, fgGC, x+thickness, y+width-thickness-1,
00390              x+width-thickness-1, y+thickness);
00391   }
00392 }
00393 
00394 void Xaw3dDrawRadio(
00395 Display    *dpy,            /* Display for drawing */
00396 Window     win,                    /* Window for drawing */
00397 GC         lightGC,         /* GC for light color */
00398 GC         shadowGC,        /* GC for shadow color */
00399 GC         inGC,            /* GC for pushed/set radio */
00400 GC         outGC,           /* GC for released/unset radio */
00401 GC         fgGC,                /* GC for dont */
00402 int        x, int y,        /* upper left corner */
00403 unsigned   width,           /* width of radio button */
00404 int        thickness,              /* thickness of shadow */
00405 Boolean    pushed           /* is radio pushed(in) or released(out) */
00406 )
00407 {
00408     GC       topGC, botGC;
00409 
00410     topGC = shadowGC;
00411     botGC = lightGC;
00412        
00413     XFillArc(dpy, win, inGC, x, y, width, width, 0, 64*360);
00414     XFillArc(dpy, win, topGC, x+1, y+1, width-2, width-2, 0, 64*360);
00415     XDrawArc(dpy, win, topGC, x+1, y+1, width-2, width-2, 0, 64*360);
00416     XFillArc(dpy, win, botGC, x+1, y+1, width-2, width-2, 64*225, 64*180);
00417     XDrawArc(dpy, win, botGC, x+1, y+1, width-2, width-2, 64*225, 64*180);
00418     if (outGC) {
00419       XFillArc(dpy, win, outGC, x+thickness, y+thickness, width-2*thickness, width-2*thickness, 0, 64*360);
00420       XDrawArc(dpy, win, outGC, x+thickness, y+thickness, width-2*thickness, width-2*thickness, 0, 64*360);
00421     }
00422     if (pushed && fgGC) {
00423       XFillArc(dpy, win, fgGC, x+thickness+2, y+thickness+2, width-2*thickness-4, width-2*thickness-4, 0, 64*360);
00424       XDrawArc(dpy, win, fgGC, x+thickness+2, y+thickness+2, width-2*thickness-4, width-2*thickness-4, 0, 64*360);
00425     }
00426     XDrawArc(dpy, win, inGC, x, y, width, width, 0, 64*360);
00427 }
00428 
00429 void Xaw3dDrawArrow(
00430 Display    *dpy,            /* Display for drawing */
00431 Window     win,                    /* Window for drawing */
00432 GC         lightGC,         /* GC for light color */
00433 GC         shadowGC,        /* GC for shadow color */
00434 GC         inGC,            /* GC for pushed arrow */
00435 GC         outGC,           /* GC for released arrow */
00436 int        x, int y,        /* upper left corner */
00437 unsigned   width,           /* width of arrow */
00438 unsigned   height,          /* width of arrow */
00439 int        thickness,              /* thickness of shadow */
00440 ArrowType  arrow_type,             /* LEFT, RIGHT, UP or DOWN arrow */
00441 Boolean    pushed           /* is radio pushed(in) or released(out) */
00442 )
00443 {
00444   int x1, y1, x2, y2, dx1, dx2, dy1, dy2;
00445 
00446   switch (arrow_type) {
00447   case UP:
00448     y += (height - (width >> 1) + 1) >> 1;
00449     height = (width >> 1);
00450     break;
00451   case DOWN:
00452     y += (height - (width >> 1)) >> 1;
00453     height = (width >> 1);
00454     break;
00455   case LEFT:
00456     x += (width - (height >> 1) + 1) >> 1;
00457     width = (height >> 1);
00458     break;
00459   case RIGHT:
00460     x += (width - (height >> 1)) >> 1;
00461     width = (height >> 1);
00462     break;
00463   }
00464 
00465   switch (arrow_type) {
00466   case UP:
00467     x1 = x;
00468     x2 = x + width - 1;
00469     y1 = y2 = y + height;
00470     dx1 = 1;
00471     dx2 = -1;
00472     dy1 = dy2 = -1;
00473     break;
00474   case DOWN:
00475     x1 = x;
00476     x2 = x + width - 1;
00477     y1 = y2 = y;
00478     dx1 = 1;
00479     dx2 = -1;
00480     dy1 = dy2 = 1;
00481     break;
00482   case LEFT:
00483     y1 = y;
00484     y2 = y + height - 1;
00485     x1 = x2 = x + width;
00486     dy1 = 1;
00487     dy2 = -1;
00488     dx1 = dx2 = -1;
00489     break;
00490   default:
00491   case RIGHT:
00492     y1 = y;
00493     y2 = y + height - 1;
00494     x1 = x2 = x;
00495     dy1 = 1;
00496     dy2 = -1;
00497     dx1 = dx2 = 1;
00498     break;
00499   }
00500 
00501   while ((x2 >= x1) && (y2 >= y1)) {
00502     XDrawLine(dpy, win, pushed ? inGC : outGC, x1, y1, x2, y2);
00503     x1 += dx1;
00504     x2 += dx2;
00505     y1 += dy1;
00506     y2 += dy2;
00507   }
00508 }