예제 #1
0
파일: tk3d.c 프로젝트: aosm/tcl
/*
 *--------------------------------------------------------------------
 *
 * 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;
}
예제 #2
0
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);
}
예제 #3
0
파일: tk3d.c 프로젝트: aosm/tcl
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++;
    }
}