/* * MwGcs.c - Utility functions to allocate GCs. * * Author: Edward A. Falk * falk@falconer.vip.best.com * * Date: Sept 29, 1998 * * * Revision 1.3 1998/12/15 04:55:05 falk * now uses Xmu library for stippled bitmap * now includes font in foreground & grey GC * * Revision 1.2 1998/10/12 16:29:32 falk * Now exports the allocPixel and GetGrey50 functions * * Revision 1.1 1998/10/12 01:38:14 falk * Initial revision * * */ /* Functions: * * GC AllocFgGC(w, fg, font) * Return a GC with foreground set as specified. * If font is None, then the returned GC is allocated with font specified * as a "don't care" value. * * GC * AllocBackgroundGC(w, font) * Return a GC with the foreground set to the widget's background color. * * GC * AllocGreyGC(w, fg, font, contrast, gp, be_nice_to_cmap) * Widget w ; * Pixel fg ; * Font font ; * int contrast ; * Pixmap *gp ; * int be_nice_to_cmap ; * * Return a GC suitable for rendering a widget in its "inactive" color. * Normally returns a GC with a color somewhere between the widget's * background color and the specified foreground. If font is None, then * the returned GC is allocated with font specified as "don't care". * If be_nice_to_cmap is True, the returned GC is created using a 50% * dither instead of a new color. * * The 'gp' argument is a pointer to a Pixmap value, used to cache the * 50% dither pattern. If *gp points to a Pixmap value, it will be used * as the source of the 50% dither pattern. If *gp is None, then a * dither pattern will be created and stored in gp. If gp is NULL, then * a dither pattern will be created but not returned. * * GC * AllocTopShadowGC(w, contrast, be_nice_to_cmap) * Return a GC suitable for rendering the "top shadow" decorations of * a widget. Returns a GC with foreground computed from widget's * background color and contrast. If be_nice_to_cmap is True, the * returned GC will use a foreground color of white. If widget depth * is 1, this function will use a foreground color of black. * * GC * AllocBotShadowGC(w, contrast, be_nice_to_cmap) * Return a GC suitable for rendering the "bottom shadow" decorations * of a widget. Returns a GC with foreground computed from widget's * background color and contrast. If be_nice_to_cmap is True, the * returned GC will use a foreground color of black. * * GC * AllocArmGC(w, contrast, gp, be_nice_to_cmap) * Return a GC suitable for rendering the "armed" decorations of a * widget. This GC would typically be used to fill in the widget's * background. Returns a GC with foreground computed from widget's * background color and contrast. If be_nice_to_cmap is True, the * returned GC will use a foreground color of black and a 50% dither. * * The 'gp' argument is as described above. * * void * Draw3dBox(w, x,y,wid,hgt,s, topgc, botgc) * Utility function. Draws a raised shadow box with outside dimensions * as specified by x,y,wid,hgt and shadow width specified by s. * A lowered shadow box may be generated by swapping topgc and botgc. * */ #include #include #include #include #include #include #include "MwGcs.h" #include /* Color & GC allocation. * * Frame widgets use the following graphics contexts: * * Foreground tab label text drawn this way * Insensitive Fg foreground color greyed out. * Background frame background color * Top shadow upper-left highlight around widget * Bottom shadow lower-right highlight around widget * Arm shadow button pressed and ready to be released * * * GC's are defined as follows, depending on attributes and * window depth: * * Monochrome: * Foreground = foreground color attribute or BlackPixel() * Grey = Foreground color + 50% dither * Background = background color attribute or WhitePixel() * top shadow = foreground * bottom shadow = foreground * arm shadow = (what?) * * Color, beNiceToColormap=true: * Foreground = foreground color attribute or BlackPixel() * Grey = Foreground color + 50% dither * Background = background color attribute or WhitePixel() * top shadow = white * bottom shadow = black * arm shadow = (what?) * * Color, beNiceToColormap=false: * Foreground = foreground color attribute or BlackPixel() * Grey = (foreground color + background color)/2 * Background = background color attribute or WhitePixel() * top shadow = background * 1.2 * bottom shadow = background * .6 * arm shadow = background * .8 * * Special cases: * If background is white, ?? * if background is black, ?? * * * If the widget's background is solid white or solid black, * this code just picks some numbers. (The choice is designed * to be compatibile with ThreeD interface.) */ #if XtSpecificationRelease < 5 static GC XtAllocateGC(Widget, int, u_long, XGCValues *, u_long, u_long) ; #endif /* shadowpm_bits put back by Ulric: needed by GetGrey50 */ static char shadowpm_bits[] = {0x02, 0x01}; /* return a GC with the specified foreground and optional font */ GC AllocFgGC(w, fg, font) Widget w; Pixel fg ; Font font ; { XGCValues values ; u_long vmask, dcmask ; values.foreground = fg ; values.font = font ; if( font != None ) { vmask = GCForeground|GCFont ; dcmask = GCSubwindowMode|GCGraphicsExposures|GCDashOffset| GCDashList|GCArcMode|GCBackground ; } else { vmask = GCForeground ; dcmask = GCFont|GCSubwindowMode|GCGraphicsExposures|GCDashOffset| GCDashList|GCArcMode|GCBackground ; } return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ; } /* return gc with widget background color as the foreground */ GC AllocBackgroundGC(w, font) Widget w; Font font ; { return AllocFgGC(w, w->core.background_pixel, font) ; } /* Allocate an "inactive" GC. Color is grey (possibly via * dither pattern). This function optionally returns the * grey pixmap so the caller may cache it. */ GC AllocGreyGC(w, fg, font, contrast, be_nice_to_cmap) Widget w ; Pixel fg ; Font font ; int contrast ; int be_nice_to_cmap ; { XGCValues values ; u_long vmask, dcmask ; values.foreground = fg ; values.background = w->core.background_pixel ; values.font = font ; if( font != None ) { vmask = GCForeground|GCFont ; dcmask = GCSubwindowMode|GCGraphicsExposures|GCDashOffset| GCDashList|GCArcMode ; } else { vmask = GCForeground ; dcmask = GCFont|GCSubwindowMode|GCGraphicsExposures|GCDashOffset| GCDashList|GCArcMode ; } if( be_nice_to_cmap || w->core.depth == 1) { values.fill_style = FillStippled ; values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ; vmask |= GCBackground|GCStipple|GCFillStyle ; return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ; } else { values.foreground = AllocGreyPixel(w, fg, values.background, contrast) ; dcmask |= GCBackground ; return XtAllocateGC(w, w->core.depth, vmask, &values, 0L, dcmask) ; } } /* return top-shadow gc. */ GC AllocTopShadowGC(w, contrast, be_nice_to_cmap) Widget w; int contrast ; int be_nice_to_cmap ; { Screen *scr = XtScreen (w); XGCValues values ; if( w->core.depth == 1 ) values.foreground = BlackPixelOfScreen(scr) ; else if( be_nice_to_cmap ) values.foreground = WhitePixelOfScreen(scr) ; else values.foreground = AllocShadowPixel(w, 100+contrast) ; return XtAllocateGC(w, w->core.depth, GCForeground, &values, 0L, GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures| GCDashOffset|GCDashList|GCArcMode) ; } /* return bottom-shadow gc. */ GC AllocBotShadowGC(w, contrast, be_nice_to_cmap) Widget w ; int contrast ; int be_nice_to_cmap ; { Screen *scr = XtScreen (w); XGCValues values ; if( w->core.depth == 1 || be_nice_to_cmap ) values.foreground = BlackPixelOfScreen(scr) ; else values.foreground = AllocShadowPixel(w, 100-contrast) ; return XtAllocateGC(w, w->core.depth, GCForeground, &values, 0L, GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures| GCDashOffset|GCDashList|GCArcMode) ; } /* return arm-shadow gc. */ GC AllocArmGC(w, contrast, be_nice_to_cmap) Widget w; int contrast ; int be_nice_to_cmap ; { Screen *scr = XtScreen (w); XGCValues values ; /* Not clear exactly what we should do here. Take a look at * Xaw3d to see what they do. */ if( w->core.depth == 1 || be_nice_to_cmap ) { values.background = w->core.background_pixel ; if( values.background == BlackPixelOfScreen(scr) ) values.foreground = WhitePixelOfScreen(scr) ; else values.foreground = BlackPixelOfScreen(scr) ; values.fill_style = FillStippled ; values.stipple = XmuCreateStippledPixmap(XtScreen(w), 1L, 0L, 1) ; return XtAllocateGC(w, w->core.depth, GCForeground|GCBackground|GCStipple|GCFillStyle, &values, 0L, GCFont|GCSubwindowMode|GCGraphicsExposures| GCDashOffset|GCDashList|GCArcMode) ; } else { values.foreground = AllocShadowPixel(w, 100-contrast) ; return XtAllocateGC(w, w->core.depth, GCForeground, &values, 0L, GCBackground|GCFont|GCSubwindowMode|GCGraphicsExposures| GCDashOffset|GCDashList|GCArcMode) ; } } Pixel AllocShadowPixel(w, scale) Widget w; int scale ; { XColor get_c, set_c ; Display *dpy = XtDisplay(w) ; Screen *scr = XtScreen(w) ; Colormap cmap ; Pixel maxColor ; cmap = w->core.colormap ; get_c.pixel = w->core.background_pixel ; if( get_c.pixel == WhitePixelOfScreen(scr) || get_c.pixel == BlackPixelOfScreen(scr) ) { /* what we *ought* to do is choose gray75 as the base color, * or perhaps gray83. Instead, we choose colors that are * the same as ThreeD would choose. */ if( scale > 100 ) scale = 200 - scale ; set_c.red = set_c.green = set_c.blue = 65535*scale/100 ; } else { XQueryColor(dpy, cmap, &get_c) ; /* adjust scale so that brightest component does not * exceed 65535; otherwise hue would change. */ if( scale > 100 ) { maxColor = Max(get_c.red, Max(get_c.green, get_c.blue)) ; if( scale*maxColor > 65535*100 ) scale = 65535*100/maxColor ; } set_c.red = scale * get_c.red / 100 ; set_c.green = scale * get_c.green / 100 ; set_c.blue = scale * get_c.blue / 100 ; } MwAllocColor(dpy, None, &set_c); return set_c.pixel; } /* Allocate a pixel halfway between foreground and background */ Pixel AllocGreyPixel(w, fg, bg, cnt) Widget w ; Pixel fg, bg ; int cnt ; { XColor get_cf, get_cb, set_c ; Display *dpy = XtDisplay(w) ; Colormap cmap ; cmap = w->core.colormap ; get_cf.pixel = fg ; get_cb.pixel = bg ; XQueryColor(dpy, cmap, &get_cf) ; XQueryColor(dpy, cmap, &get_cb) ; set_c.red = (get_cf.red * cnt + get_cb.red * (100-cnt)) / 100 ; set_c.green = (get_cf.green * cnt + get_cb.green * (100-cnt)) / 100 ; set_c.blue = (get_cf.blue * cnt + get_cb.blue * (100-cnt)) / 100 ; MwAllocColor(dpy, None, &set_c) ; return set_c.pixel ; } /* GetGrey50 put back by Ulric: needed by Gridbox. */ Pixmap GetGrey50(w, gp) Widget w; Pixmap *gp ; { Pixmap pm = gp != NULL ? *gp : None ; if( pm == None ) { pm = XCreateBitmapFromData( XtDisplay(w), XtWindow(w), shadowpm_bits, 2, 2) ; if( gp != NULL ) *gp = pm ; } return pm ; } /* draw a 3-d box */ void Draw3dBox(w, x,y,wid,hgt,s, topgc, botgc) Widget w ; int x,y ; /* position */ int wid,hgt,s ; /* outside dimensions, shadow wid */ GC topgc ; GC botgc ; { Display *dpy = XtDisplay(w) ; Window win = XtWindow(w) ; if( s == 0 ) return ; if( s == 1 ) { XDrawLine(dpy,win,botgc, x,y+hgt-1, x+wid-1,y+hgt-1) ; XDrawLine(dpy,win,botgc, x+wid-1,y, x+wid-1,y+hgt-1) ; XDrawLine(dpy,win,topgc, x,y, x,y+hgt-1) ; XDrawLine(dpy,win,topgc, x,y, x+wid-1,y) ; } else { XPoint pts[6] ; /* bottom-right shadow */ pts[0].x = x ; pts[0].y = y + hgt ; pts[1].x = s ; pts[1].y = -s ; pts[2].x = wid-2*s ; pts[2].y = 0 ; pts[3].x = 0 ; pts[3].y = -(hgt-2*s) ; pts[4].x = s ; pts[4].y = -s ; pts[5].x = 0 ; pts[5].y = hgt ; XFillPolygon(dpy,win,botgc, pts,6, Nonconvex,CoordModePrevious) ; /* top-left shadow */ pts[0].x = x ; pts[0].y = y ; pts[1].x = wid ; pts[1].y = 0 ; pts[2].x = -s ; pts[2].y = s ; pts[3].x = -wid+2*s ; pts[3].y = 0 ; pts[4].x = 0 ; pts[4].y = hgt-2*s ; pts[5].x = -s ; pts[5].y = s ; XFillPolygon(dpy,win,topgc, pts,6, Nonconvex,CoordModePrevious) ; } } #if XtSpecificationRelease < 5 static GC XtAllocateGC(w, depth, mask, values, dynamic, dontcare) Widget w ; int depth ; unsigned long mask, dynamic, dontcare ; XGCValues *values ; { return XtGetGC(w, mask, values) ; } #endif