/* *-------------------------------------------------------------------- * * Tk_3DBorderGC -- * * Given a 3D border, returns one of the graphics contexts used to draw * the border. * * Results: * Returns the graphics context given by the "which" argument. * * Side effects: * None. * *-------------------------------------------------------------------- */ GC Tk_3DBorderGC( Tk_Window tkwin, /* Window for which border was allocated. */ Tk_3DBorder border, /* Border whose GC is wanted. */ int which) /* Selects one of the border's 3 GC's: * TK_3D_FLAT_GC, TK_3D_LIGHT_GC, or * TK_3D_DARK_GC. */ { TkBorder * borderPtr = (TkBorder *) border; if ((borderPtr->lightGC == None) && (which != TK_3D_FLAT_GC)) { TkpGetShadows(borderPtr, tkwin); } if (which == TK_3D_FLAT_GC) { return borderPtr->bgGC; } else if (which == TK_3D_LIGHT_GC) { return borderPtr->lightGC; } else if (which == TK_3D_DARK_GC){ return borderPtr->darkGC; } Tcl_Panic("bogus \"which\" value in Tk_3DBorderGC"); /* * The code below will never be executed, but it's needed to keep * compilers happy. */ return (GC) None; }
void TkpDrawCheckIndicator( Tk_Window tkwin, /* handle for resource alloc */ Display *display, Drawable d, /* what to draw on */ int x, int y, /* where to draw */ Tk_3DBorder bgBorder, /* colors of the border */ XColor *indicatorColor, /* color of the indicator */ XColor *selectColor, /* color when selected */ XColor *disableColor, /* color when disabled */ int on, /* are we on? */ int disabled, /* are we disabled? */ int mode) /* kind of indicator to draw */ { int ix, iy; int dim; int imgsel, imgstart; TkBorder *bg_brdr = (TkBorder*)bgBorder; XGCValues gcValues; GC copyGC; unsigned long imgColors[8]; XImage *img; Pixmap pixmap; int depth; /* * Sanity check. */ if (tkwin == NULL || display == None || d == None || bgBorder == NULL || indicatorColor == NULL) { return; } if (disableColor == NULL) { disableColor = bg_brdr->bgColorPtr; } if (selectColor == NULL) { selectColor = bg_brdr->bgColorPtr; } depth = Tk_Depth(tkwin); /* * Compute starting point and dimensions of image inside button_images to * be used. */ switch (mode) { default: case CHECK_BUTTON: imgsel = on == 2 ? CHECK_DISON_OFFSET : on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; imgstart = CHECK_START; dim = CHECK_BUTTON_DIM; break; case CHECK_MENU: imgsel = on == 2 ? CHECK_DISOFF_OFFSET : on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; imgstart = CHECK_START + 2; imgsel += 2; dim = CHECK_MENU_DIM; break; case RADIO_BUTTON: imgsel = on == 2 ? RADIO_DISON_OFFSET : on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; imgstart = RADIO_START; dim = RADIO_BUTTON_DIM; break; case RADIO_MENU: imgsel = on == 2 ? RADIO_DISOFF_OFFSET : on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; imgstart = RADIO_START + 3; imgsel += 3; dim = RADIO_MENU_DIM; break; } /* * Allocate the drawing areas to use. Note that we use double-buffering * here because not all code paths leading to this function do so. */ pixmap = Tk_GetPixmap(display, d, dim, dim, depth); if (pixmap == None) { return; } x -= dim/2; y -= dim/2; img = XGetImage(display, pixmap, 0, 0, (unsigned int)dim, (unsigned int)dim, AllPlanes, ZPixmap); if (img == NULL) { return; } /* * Set up the color mapping table. */ TkpGetShadows(bg_brdr, tkwin); imgColors[0 /*A*/] = Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; imgColors[1 /*B*/] = Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; imgColors[2 /*C*/] = (bg_brdr->lightColorPtr != NULL) ? Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr)->pixel : WhitePixelOfScreen(bg_brdr->screen); imgColors[3 /*D*/] = Tk_GetColorByValue(tkwin, selectColor)->pixel; imgColors[4 /*E*/] = (bg_brdr->darkColorPtr != NULL) ? Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr)->pixel : BlackPixelOfScreen(bg_brdr->screen); imgColors[5 /*F*/] = Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; imgColors[6 /*G*/] = Tk_GetColorByValue(tkwin, indicatorColor)->pixel; imgColors[7 /*H*/] = Tk_GetColorByValue(tkwin, disableColor)->pixel; /* * Create the image, painting it into an XImage one pixel at a time. */ for (iy=0 ; iy<dim ; iy++) { for (ix=0 ; ix<dim ; ix++) { XPutPixel(img, ix, iy, imgColors[button_images[imgstart+iy][imgsel+ix] - 'A'] ); } } /* * Copy onto our target drawable surface. */ memset(&gcValues, 0, sizeof(gcValues)); gcValues.background = bg_brdr->bgColorPtr->pixel; gcValues.graphics_exposures = False; copyGC = Tk_GetGC(tkwin, 0, &gcValues); XPutImage(display, pixmap, copyGC, img, 0, 0, 0, 0, (unsigned int)dim, (unsigned int)dim); XCopyArea(display, pixmap, d, copyGC, 0, 0, (unsigned int)dim, (unsigned int)dim, x, y); /* * Tidy up. */ Tk_FreeGC(display, copyGC); XDestroyImage(img); Tk_FreePixmap(display, pixmap); }
void Tk_Draw3DPolygon( Tk_Window tkwin, /* Window for which border was allocated. */ Drawable drawable, /* X window or pixmap in which to draw. */ Tk_3DBorder border, /* Token for border to draw. */ XPoint *pointPtr, /* Array of points describing polygon. All * points must be absolute * (CoordModeOrigin). */ int numPoints, /* Number of points at *pointPtr. */ int borderWidth, /* Width of border, measured in pixels to the * left of the polygon's trajectory. May be * negative. */ int leftRelief) /* TK_RELIEF_RAISED or TK_RELIEF_SUNKEN: * indicates how stuff to left of trajectory * looks relative to stuff on right. */ { XPoint poly[4], b1, b2, newB1, newB2; XPoint perp, c, shift1, shift2; /* Used for handling parallel lines. */ register XPoint *p1Ptr, *p2Ptr; TkBorder *borderPtr = (TkBorder *) border; GC gc; int i, lightOnLeft, dx, dy, parallel, pointsSeen; Display *display = Tk_Display(tkwin); if (borderPtr->lightGC == None) { TkpGetShadows(borderPtr, tkwin); } /* * Handle grooves and ridges with recursive calls. */ if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) { int halfWidth; halfWidth = borderWidth/2; Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED : TK_RELIEF_SUNKEN); Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, -halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED); return; } /* * If the polygon is already closed, drop the last point from it (we'll * close it automatically). */ p1Ptr = &pointPtr[numPoints-1]; p2Ptr = &pointPtr[0]; if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) { numPoints--; } /* * The loop below is executed once for each vertex in the polgon. At the * beginning of each iteration things look like this: * * poly[1] / * * / * | / * b1 * poly[0] (pointPtr[i-1]) * | | * | | * | | * | | * | | * | | *p1Ptr *p2Ptr * b2 *--------------------* * | * | * x------------------------- * * The job of this iteration is to do the following: * (a) Compute x (the border corner corresponding to pointPtr[i]) and put * it in poly[2]. As part of this, compute a new b1 and b2 value for * the next side of the polygon. * (b) Put pointPtr[i] into poly[3]. * (c) Draw the polygon given by poly[0..3]. * (d) Advance poly[0], poly[1], b1, and b2 for the next side of the * polygon. */ /* * The above situation doesn't first come into existence until two points * have been processed; the first two points are used to "prime the pump", * so some parts of the processing are ommitted for these points. The * variable "pointsSeen" keeps track of the priming process; it has to be * separate from i in order to be able to ignore duplicate points in the * polygon. */ pointsSeen = 0; for (i = -2, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1; i < numPoints; i++, p1Ptr = p2Ptr, p2Ptr++) { if ((i == -1) || (i == numPoints-1)) { p2Ptr = pointPtr; } if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) { /* * Ignore duplicate points (they'd cause core dumps in ShiftLine * calls below). */ continue; } ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1); newB2.x = newB1.x + (p2Ptr->x - p1Ptr->x); newB2.y = newB1.y + (p2Ptr->y - p1Ptr->y); poly[3] = *p1Ptr; parallel = 0; if (pointsSeen >= 1) { parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]); /* * If two consecutive segments of the polygon are parallel, then * things get more complex. Consider the following diagram: * * poly[1] * *----b1-----------b2------a * \ * \ * *---------*----------* b * poly[0] *p2Ptr *p1Ptr / * / * --*--------*----c * newB1 newB2 * * Instead of using x and *p1Ptr for poly[2] and poly[3], as in * the original diagram, use a and b as above. Then instead of * using x and *p1Ptr for the new poly[0] and poly[1], use b and c * as above. * * Do the computation in three stages: * 1. Compute a point "perp" such that the line p1Ptr-perp is * perpendicular to p1Ptr-p2Ptr. * 2. Compute the points a and c by intersecting the lines b1-b2 * and newB1-newB2 with p1Ptr-perp. * 3. Compute b by shifting p1Ptr-perp to the right and * intersecting it with p1Ptr-p2Ptr. */ if (parallel) { perp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y); perp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x); (void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]); (void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c); ShiftLine(p1Ptr, &perp, borderWidth, &shift1); shift2.x = shift1.x + (perp.x - p1Ptr->x); shift2.y = shift1.y + (perp.y - p1Ptr->y); (void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]); } } if (pointsSeen >= 2) { dx = poly[3].x - poly[0].x; dy = poly[3].y - poly[0].y; if (dx > 0) { lightOnLeft = (dy <= dx); } else { lightOnLeft = (dy < dx); } if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) { gc = borderPtr->lightGC; } else { gc = borderPtr->darkGC; } XFillPolygon(display, drawable, gc, poly, 4, Convex, CoordModeOrigin); } b1.x = newB1.x; b1.y = newB1.y; b2.x = newB2.x; b2.y = newB2.y; poly[0].x = poly[3].x; poly[0].y = poly[3].y; if (parallel) { poly[1].x = c.x; poly[1].y = c.y; } else if (pointsSeen >= 1) { poly[1].x = poly[2].x; poly[1].y = poly[2].y; } pointsSeen++; } }