static void DiamondIndicatorElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { IndicatorElement *indicator = elementRecord; Tk_3DBorder border = 0, interior = 0; int borderWidth = 2; int relief = TK_RELIEF_RAISED; int diameter, radius; XPoint points[4]; Ttk_Padding padding; interior = Tk_Get3DBorderFromObj(tkwin, indicator->colorObj); border = Tk_Get3DBorderFromObj(tkwin, indicator->backgroundObj); Tcl_GetIntFromObj(NULL,indicator->borderWidthObj,&borderWidth); Tk_GetReliefFromObj(NULL,indicator->reliefObj,&relief); Ttk_GetPaddingFromObj(NULL,tkwin,indicator->marginObj,&padding); b = Ttk_PadBox(b, padding); diameter = b.width < b.height ? b.width : b.height; radius = diameter / 2; points[0].x = b.x; points[0].y = b.y + radius; points[1].x = b.x + radius; points[1].y = b.y + 2*radius; points[2].x = b.x + 2*radius; points[2].y = b.y + radius; points[3].x = b.x + radius; points[3].y = b.y; Tk_Fill3DPolygon(tkwin,d,interior,points,4,borderWidth,TK_RELIEF_FLAT); Tk_Draw3DPolygon(tkwin,d,border,points,4,borderWidth,relief); }
static void DrawMenuSeparator( TkMenu *menuPtr, /* The menu we are drawing */ TkMenuEntry *mePtr, /* The entry we are drawing */ Drawable d, /* The drawable we are using */ GC gc, /* The gc to draw into */ Tk_Font tkfont, /* The font to draw with */ const Tk_FontMetrics *fmPtr,/* The font metrics from the font */ int x, int y, int width, int height) { XPoint points[2]; Tk_3DBorder border; if (menuPtr->menuType == MENUBAR) { return; } points[0].x = x; points[0].y = y + height/2; points[1].x = width - 1; points[1].y = points[0].y; border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, TK_RELIEF_RAISED); }
void Tk_Fill3DPolygon( 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) /* Indicates 3D effect of left side of * trajectory relative to right: * TK_RELIEF_FLAT, TK_RELIEF_RAISED, or * TK_RELIEF_SUNKEN. */ { register TkBorder *borderPtr = (TkBorder *) border; XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC, pointPtr, numPoints, Complex, CoordModeOrigin); if (leftRelief != TK_RELIEF_FLAT) { Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints, borderWidth, leftRelief); } }
static void DrawTearoffEntry( TkMenu *menuPtr, /* The menu we are drawing */ TkMenuEntry *mePtr, /* The entry we are drawing */ Drawable d, /* The drawable we are drawing into */ GC gc, /* The gc we are drawing with */ Tk_Font tkfont, /* The font we are drawing with */ const Tk_FontMetrics *fmPtr,/* The metrics we are drawing with */ int x, int y, int width, int height) { XPoint points[2]; int segmentWidth, maxX; Tk_3DBorder border; if (menuPtr->menuType != MASTER_MENU) { return; } points[0].x = x; points[0].y = y + height/2; points[1].y = points[0].y; segmentWidth = 6; maxX = width - 1; border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); while (points[0].x < maxX) { points[1].x = points[0].x + segmentWidth; if (points[1].x > maxX) { points[1].x = maxX; } Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, TK_RELIEF_RAISED); points[0].x += 2 * segmentWidth; } }
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++; } }