/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkrectoval.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkrectoval.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

projs/trunk/shared_source/tk_base/tkrectoval.c revision 42 by dashley, Fri Oct 14 01:50:00 2016 UTC projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkrectoval.c revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkrectoval.c,v 1.1.1.1 2001/06/13 05:07:29 dtashley Exp $ */  
   
 /*  
  * tkRectOval.c --  
  *  
  *      This file implements rectangle and oval items for canvas  
  *      widgets.  
  *  
  * Copyright (c) 1991-1994 The Regents of the University of California.  
  * Copyright (c) 1994-1997 Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkrectoval.c,v 1.1.1.1 2001/06/13 05:07:29 dtashley Exp $  
  */  
   
 #include <stdio.h>  
 #include "tk.h"  
 #include "tkInt.h"  
 #include "tkPort.h"  
 #include "tkCanvas.h"  
   
 /*  
  * The structure below defines the record for each rectangle/oval item.  
  */  
   
 typedef struct RectOvalItem  {  
     Tk_Item header;             /* Generic stuff that's the same for all  
                                  * types.  MUST BE FIRST IN STRUCTURE. */  
     Tk_Outline outline;         /* Outline structure */  
     double bbox[4];             /* Coordinates of bounding box for rectangle  
                                  * or oval (x1, y1, x2, y2).  Item includes  
                                  * x1 and x2 but not y1 and y2. */  
     Tk_TSOffset tsoffset;  
     XColor *fillColor;          /* Color for filling rectangle/oval. */  
     XColor *activeFillColor;    /* Color for filling rectangle/oval if state is active. */  
     XColor *disabledFillColor;  /* Color for filling rectangle/oval if state is disabled. */  
     Pixmap fillStipple;         /* Stipple bitmap for filling item. */  
     Pixmap activeFillStipple;   /* Stipple bitmap for filling item if state is active. */  
     Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is disabled. */  
     GC fillGC;                  /* Graphics context for filling item. */  
 } RectOvalItem;  
   
 /*  
  * Information used for parsing configuration specs:  
  */  
   
 static Tk_CustomOption stateOption = {  
     (Tk_OptionParseProc *) TkStateParseProc,  
     TkStatePrintProc, (ClientData) 2  
 };  
 static Tk_CustomOption tagsOption = {  
     (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,  
     Tk_CanvasTagsPrintProc, (ClientData) NULL  
 };  
 static Tk_CustomOption dashOption = {  
     (Tk_OptionParseProc *) TkCanvasDashParseProc,  
     TkCanvasDashPrintProc, (ClientData) NULL  
 };  
 static Tk_CustomOption offsetOption = {  
     (Tk_OptionParseProc *) TkOffsetParseProc,  
     TkOffsetPrintProc, (ClientData) TK_OFFSET_RELATIVE  
 };  
 static Tk_CustomOption pixelOption = {  
     (Tk_OptionParseProc *) TkPixelParseProc,  
     TkPixelPrintProc, (ClientData) NULL  
 };  
   
 static Tk_ConfigSpec configSpecs[] = {  
     {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.activeDash),  
         TK_CONFIG_NULL_OK, &dashOption},  
     {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, activeFillColor),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.activeColor),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.activeStipple),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, activeFillStipple),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,  
         "0.0", Tk_Offset(RectOvalItem, outline.activeWidth),  
         TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},  
     {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.dash),  
         TK_CONFIG_NULL_OK, &dashOption},  
     {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,  
         "0", Tk_Offset(RectOvalItem, outline.offset),  
         TK_CONFIG_DONT_SET_DEFAULT},  
     {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledDash),  
         TK_CONFIG_NULL_OK, &dashOption},  
     {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, disabledFillColor),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledColor),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, disabledFillStipple),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_PIXELS, "-disabledwidth", (char *) NULL, (char *) NULL,  
         "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),  
         TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},  
     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},  
     {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,  
         "0,0", Tk_Offset(RectOvalItem, tsoffset),  
         TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},  
     {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,  
         "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK},  
     {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,  
         "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),  
         TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},  
     {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, outline.stipple),  
         TK_CONFIG_NULL_OK},  
     {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK,  
         &stateOption},  
     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,  
         (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},  
     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},  
     {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,  
         "1.0", Tk_Offset(RectOvalItem, outline.width),  
         TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},  
     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,  
         (char *) NULL, 0, 0}  
 };  
   
 /*  
  * Prototypes for procedures defined in this file:  
  */  
   
 static void             ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas,  
                             RectOvalItem *rectOvalPtr));  
 static int              ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tk_Canvas canvas, Tk_Item *itemPtr, int argc,  
                             Tcl_Obj *CONST argv[], int flags));  
 static int              CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tk_Canvas canvas, struct Tk_Item *itemPtr,  
                             int argc, Tcl_Obj *CONST argv[]));  
 static void             DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, Display *display));  
 static void             DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, Display *display, Drawable dst,  
                             int x, int y, int width, int height));  
 static int              OvalToArea _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double *areaPtr));  
 static double           OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double *pointPtr));  
 static int              RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tk_Canvas canvas, Tk_Item *itemPtr, int argc,  
                             Tcl_Obj *CONST argv[]));  
 static int              RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp,  
                             Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));  
 static int              RectToArea _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double *areaPtr));  
 static double           RectToPoint _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double *pointPtr));  
 static void             ScaleRectOval _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double originX, double originY,  
                             double scaleX, double scaleY));  
 static void             TranslateRectOval _ANSI_ARGS_((Tk_Canvas canvas,  
                             Tk_Item *itemPtr, double deltaX, double deltaY));  
   
 /*  
  * The structures below defines the rectangle and oval item types  
  * by means of procedures that can be invoked by generic item code.  
  */  
   
 Tk_ItemType tkRectangleType = {  
     "rectangle",                        /* name */  
     sizeof(RectOvalItem),               /* itemSize */  
     CreateRectOval,                     /* createProc */  
     configSpecs,                        /* configSpecs */  
     ConfigureRectOval,                  /* configureProc */  
     RectOvalCoords,                     /* coordProc */  
     DeleteRectOval,                     /* deleteProc */  
     DisplayRectOval,                    /* displayProc */  
     TK_CONFIG_OBJS,                     /* flags */  
     RectToPoint,                        /* pointProc */  
     RectToArea,                         /* areaProc */  
     RectOvalToPostscript,               /* postscriptProc */  
     ScaleRectOval,                      /* scaleProc */  
     TranslateRectOval,                  /* translateProc */  
     (Tk_ItemIndexProc *) NULL,          /* indexProc */  
     (Tk_ItemCursorProc *) NULL,         /* icursorProc */  
     (Tk_ItemSelectionProc *) NULL,      /* selectionProc */  
     (Tk_ItemInsertProc *) NULL,         /* insertProc */  
     (Tk_ItemDCharsProc *) NULL,         /* dTextProc */  
     (Tk_ItemType *) NULL,               /* nextPtr */  
 };  
   
 Tk_ItemType tkOvalType = {  
     "oval",                             /* name */  
     sizeof(RectOvalItem),               /* itemSize */  
     CreateRectOval,                     /* createProc */  
     configSpecs,                        /* configSpecs */  
     ConfigureRectOval,                  /* configureProc */  
     RectOvalCoords,                     /* coordProc */  
     DeleteRectOval,                     /* deleteProc */  
     DisplayRectOval,                    /* displayProc */  
     TK_CONFIG_OBJS,                     /* flags */  
     OvalToPoint,                        /* pointProc */  
     OvalToArea,                         /* areaProc */  
     RectOvalToPostscript,               /* postscriptProc */  
     ScaleRectOval,                      /* scaleProc */  
     TranslateRectOval,                  /* translateProc */  
     (Tk_ItemIndexProc *) NULL,          /* indexProc */  
     (Tk_ItemCursorProc *) NULL,         /* cursorProc */  
     (Tk_ItemSelectionProc *) NULL,      /* selectionProc */  
     (Tk_ItemInsertProc *) NULL,         /* insertProc */  
     (Tk_ItemDCharsProc *) NULL,         /* dTextProc */  
     (Tk_ItemType *) NULL,               /* nextPtr */  
 };  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * CreateRectOval --  
  *  
  *      This procedure is invoked to create a new rectangle  
  *      or oval item in a canvas.  
  *  
  * Results:  
  *      A standard Tcl return value.  If an error occurred in  
  *      creating the item, then an error message is left in  
  *      the interp's result;  in this case itemPtr is left uninitialized,  
  *      so it can be safely freed by the caller.  
  *  
  * Side effects:  
  *      A new rectangle or oval item is created.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 CreateRectOval(interp, canvas, itemPtr, argc, argv)  
     Tcl_Interp *interp;                 /* For error reporting. */  
     Tk_Canvas canvas;                   /* Canvas to hold new item. */  
     Tk_Item *itemPtr;                   /* Record to hold new item;  header  
                                          * has been initialized by caller. */  
     int argc;                           /* Number of arguments in argv. */  
     Tcl_Obj *CONST argv[];              /* Arguments describing rectangle. */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
     int i;  
   
   
     if (argc==1) {  
         i = 1;  
     } else {  
         char *arg = Tcl_GetStringFromObj(argv[1], NULL);  
         if ((argc>1) && (arg[0] == '-')  
                 && (arg[1] >= 'a') && (arg[1] <= 'z')) {  
             i = 1;  
         } else {  
             i = 4;  
         }  
     }  
   
     if (argc < i) {  
         Tcl_AppendResult(interp, "wrong # args: should be \"",  
                 Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",  
                 itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",  
                 (char *) NULL);  
         return TCL_ERROR;  
     }  
   
     /*  
      * Carry out initialization that is needed in order to clean  
      * up after errors during the the remainder of this procedure.  
      */  
   
     Tk_CreateOutline(&(rectOvalPtr->outline));  
     rectOvalPtr->tsoffset.flags = 0;  
     rectOvalPtr->tsoffset.xoffset = 0;  
     rectOvalPtr->tsoffset.yoffset = 0;  
     rectOvalPtr->fillColor = NULL;  
     rectOvalPtr->activeFillColor = NULL;  
     rectOvalPtr->disabledFillColor = NULL;  
     rectOvalPtr->fillStipple = None;  
     rectOvalPtr->activeFillStipple = None;  
     rectOvalPtr->disabledFillStipple = None;  
     rectOvalPtr->fillGC = None;  
   
     /*  
      * Process the arguments to fill in the item record.  
      */  
   
     if ((RectOvalCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {  
         goto error;  
     }  
     if (ConfigureRectOval(interp, canvas, itemPtr, argc-i, argv+i, 0)  
             == TCL_OK) {  
         return TCL_OK;  
     }  
   
     error:  
     DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));  
     return TCL_ERROR;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * RectOvalCoords --  
  *  
  *      This procedure is invoked to process the "coords" widget  
  *      command on rectangles and ovals.  See the user documentation  
  *      for details on what it does.  
  *  
  * Results:  
  *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.  
  *  
  * Side effects:  
  *      The coordinates for the given item may be changed.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 RectOvalCoords(interp, canvas, itemPtr, argc, argv)  
     Tcl_Interp *interp;                 /* Used for error reporting. */  
     Tk_Canvas canvas;                   /* Canvas containing item. */  
     Tk_Item *itemPtr;                   /* Item whose coordinates are to be  
                                          * read or modified. */  
     int argc;                           /* Number of coordinates supplied in  
                                          * argv. */  
     Tcl_Obj *CONST argv[];              /* Array of coordinates: x1, y1,  
                                          * x2, y2, ... */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
   
     if (argc == 0) {  
         Tcl_Obj *obj = Tcl_NewObj();  
         Tcl_Obj *subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);  
         Tcl_ListObjAppendElement(interp, obj, subobj);  
         subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);  
         Tcl_ListObjAppendElement(interp, obj, subobj);  
         subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);  
         Tcl_ListObjAppendElement(interp, obj, subobj);  
         subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);  
         Tcl_ListObjAppendElement(interp, obj, subobj);  
         Tcl_SetObjResult(interp, obj);  
     } else if ((argc == 1)||(argc == 4)) {  
         if (argc==1) {  
             if (Tcl_ListObjGetElements(interp, argv[0], &argc,  
                     (Tcl_Obj ***) &argv) != TCL_OK) {  
                 return TCL_ERROR;  
             } else if (argc != 4) {  
                 char buf[64 + TCL_INTEGER_SPACE];  
   
                 sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);  
                 Tcl_SetResult(interp, buf, TCL_VOLATILE);  
                 return TCL_ERROR;  
             }  
         }  
         if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],  
                     &rectOvalPtr->bbox[0]) != TCL_OK)  
                 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],  
                     &rectOvalPtr->bbox[1]) != TCL_OK)  
                 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[2],  
                         &rectOvalPtr->bbox[2]) != TCL_OK)  
                 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[3],  
                         &rectOvalPtr->bbox[3]) != TCL_OK)) {  
             return TCL_ERROR;  
         }  
         ComputeRectOvalBbox(canvas, rectOvalPtr);  
     } else {  
         char buf[64 + TCL_INTEGER_SPACE];  
           
         sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);  
         Tcl_SetResult(interp, buf, TCL_VOLATILE);  
         return TCL_ERROR;  
     }  
     return TCL_OK;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ConfigureRectOval --  
  *  
  *      This procedure is invoked to configure various aspects  
  *      of a rectangle or oval item, such as its border and  
  *      background colors.  
  *  
  * Results:  
  *      A standard Tcl result code.  If an error occurs, then  
  *      an error message is left in the interp's result.  
  *  
  * Side effects:  
  *      Configuration information, such as colors and stipple  
  *      patterns, may be set for itemPtr.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)  
     Tcl_Interp *interp;         /* Used for error reporting. */  
     Tk_Canvas canvas;           /* Canvas containing itemPtr. */  
     Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */  
     int argc;                   /* Number of elements in argv.  */  
     Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */  
     int flags;                  /* Flags to pass to Tk_ConfigureWidget. */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
     XGCValues gcValues;  
     GC newGC;  
     unsigned long mask;  
     Tk_Window tkwin;  
     Tk_TSOffset *tsoffset;  
     XColor *color;  
     Pixmap stipple;  
     Tk_State state;  
   
     tkwin = Tk_CanvasTkwin(canvas);  
   
     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,  
             (char *) rectOvalPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {  
         return TCL_ERROR;  
     }  
     state = itemPtr->state;  
   
     /*  
      * A few of the options require additional processing, such as  
      * graphics contexts.  
      */  
   
     if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||  
             rectOvalPtr->outline.activeDash.number != 0 ||  
             rectOvalPtr->outline.activeColor != NULL ||  
             rectOvalPtr->outline.activeStipple != None ||  
             rectOvalPtr->activeFillColor != NULL ||  
             rectOvalPtr->activeFillStipple != None) {  
         itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;  
     } else {  
         itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;  
     }  
   
     tsoffset = &rectOvalPtr->outline.tsoffset;  
     flags = tsoffset->flags;  
     if (flags & TK_OFFSET_LEFT) {  
         tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);  
     } else if (flags & TK_OFFSET_CENTER) {  
         tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);  
     } else if (flags & TK_OFFSET_RIGHT) {  
         tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);  
     }  
     if (flags & TK_OFFSET_TOP) {  
         tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);  
     } else if (flags & TK_OFFSET_MIDDLE) {  
         tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);  
     } else if (flags & TK_OFFSET_BOTTOM) {  
         tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);  
     }  
   
     /*  
      * Configure the outline graphics context.  If mask is non-zero,  
      * the gc has changed and must be reallocated, provided that the  
      * new settings specify a valid outline (non-zero width and non-NULL  
      * color)  
      */  
   
     mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,  
              &(rectOvalPtr->outline));  
     if (mask && \  
             rectOvalPtr->outline.width != 0 && \  
             rectOvalPtr->outline.color != NULL) {  
         gcValues.cap_style = CapProjecting;  
         mask |= GCCapStyle;  
         newGC = Tk_GetGC(tkwin, mask, &gcValues);  
     } else {  
         newGC = None;  
     }  
     if (rectOvalPtr->outline.gc != None) {  
         Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);  
     }  
     rectOvalPtr->outline.gc = newGC;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
     if (state==TK_STATE_HIDDEN) {  
         ComputeRectOvalBbox(canvas, rectOvalPtr);  
         return TCL_OK;  
     }  
   
     color = rectOvalPtr->fillColor;  
     stipple = rectOvalPtr->fillStipple;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (rectOvalPtr->activeFillColor!=NULL) {  
             color = rectOvalPtr->activeFillColor;  
         }  
         if (rectOvalPtr->activeFillStipple!=None) {  
             stipple = rectOvalPtr->activeFillStipple;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectOvalPtr->disabledFillColor!=NULL) {  
             color = rectOvalPtr->disabledFillColor;  
         }  
         if (rectOvalPtr->disabledFillStipple!=None) {  
             stipple = rectOvalPtr->disabledFillStipple;  
         }  
     }  
   
     if (color == NULL) {  
         newGC = None;  
     } else {  
         gcValues.foreground = color->pixel;  
         if (stipple != None) {  
             gcValues.stipple = stipple;  
             gcValues.fill_style = FillStippled;  
             mask = GCForeground|GCStipple|GCFillStyle;  
         } else {  
             mask = GCForeground;  
         }  
         newGC = Tk_GetGC(tkwin, mask, &gcValues);  
     }  
     if (rectOvalPtr->fillGC != None) {  
         Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);  
     }  
     rectOvalPtr->fillGC = newGC;  
   
     tsoffset = &rectOvalPtr->tsoffset;  
     flags = tsoffset->flags;  
     if (flags & TK_OFFSET_LEFT) {  
         tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);  
     } else if (flags & TK_OFFSET_CENTER) {  
         tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);  
     } else if (flags & TK_OFFSET_RIGHT) {  
         tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);  
     }  
     if (flags & TK_OFFSET_TOP) {  
         tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);  
     } else if (flags & TK_OFFSET_MIDDLE) {  
         tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);  
     } else if (flags & TK_OFFSET_BOTTOM) {  
         tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);  
     }  
   
     ComputeRectOvalBbox(canvas, rectOvalPtr);  
   
     return TCL_OK;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * DeleteRectOval --  
  *  
  *      This procedure is called to clean up the data structure  
  *      associated with a rectangle or oval item.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      Resources associated with itemPtr are released.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static void  
 DeleteRectOval(canvas, itemPtr, display)  
     Tk_Canvas canvas;                   /* Info about overall widget. */  
     Tk_Item *itemPtr;                   /* Item that is being deleted. */  
     Display *display;                   /* Display containing window for  
                                          * canvas. */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
   
     Tk_DeleteOutline(display, &(rectOvalPtr->outline));  
     if (rectOvalPtr->fillColor != NULL) {  
         Tk_FreeColor(rectOvalPtr->fillColor);  
     }  
     if (rectOvalPtr->activeFillColor != NULL) {  
         Tk_FreeColor(rectOvalPtr->activeFillColor);  
     }  
     if (rectOvalPtr->disabledFillColor != NULL) {  
         Tk_FreeColor(rectOvalPtr->disabledFillColor);  
     }  
     if (rectOvalPtr->fillStipple != None) {  
         Tk_FreeBitmap(display, rectOvalPtr->fillStipple);  
     }  
     if (rectOvalPtr->activeFillStipple != None) {  
         Tk_FreeBitmap(display, rectOvalPtr->activeFillStipple);  
     }  
     if (rectOvalPtr->disabledFillStipple != None) {  
         Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);  
     }  
     if (rectOvalPtr->fillGC != None) {  
         Tk_FreeGC(display, rectOvalPtr->fillGC);  
     }  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ComputeRectOvalBbox --  
  *  
  *      This procedure is invoked to compute the bounding box of  
  *      all the pixels that may be drawn as part of a rectangle  
  *      or oval.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The fields x1, y1, x2, and y2 are updated in the header  
  *      for itemPtr.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static void  
 ComputeRectOvalBbox(canvas, rectOvalPtr)  
     Tk_Canvas canvas;                   /* Canvas that contains item. */  
     RectOvalItem *rectOvalPtr;          /* Item whose bbox is to be  
                                          * recomputed. */  
 {  
     int bloat, tmp;  
     double dtmp, width;  
     Tk_State state = rectOvalPtr->header.state;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
   
     width = rectOvalPtr->outline.width;  
     if (state==TK_STATE_HIDDEN) {  
         rectOvalPtr->header.x1 = rectOvalPtr->header.y1 =  
         rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;  
         return;  
     }  
     if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {  
         if (rectOvalPtr->outline.activeWidth>width) {  
             width = rectOvalPtr->outline.activeWidth;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectOvalPtr->outline.disabledWidth>0) {  
             width = rectOvalPtr->outline.disabledWidth;  
         }  
     }  
   
     /*  
      * Make sure that the first coordinates are the lowest ones.  
      */  
   
     if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {  
         double tmp;  
         tmp = rectOvalPtr->bbox[3];  
         rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];  
         rectOvalPtr->bbox[1] = tmp;  
     }  
     if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {  
         double tmp;  
         tmp = rectOvalPtr->bbox[2];  
         rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];  
         rectOvalPtr->bbox[0] = tmp;  
     }  
   
     if (rectOvalPtr->outline.gc == None) {  
         /*  
          * The Win32 switch was added for 8.3 to solve a problem  
          * with ovals leaving traces on bottom and right of 1 pixel.  
          * This may not be the correct place to solve it, but it works.  
          */  
 #ifdef __WIN32__  
         bloat = 1;  
 #else  
         bloat = 0;  
 #endif  
     } else {  
         bloat = (int) (width+1)/2;  
     }  
   
     /*  
      * Special note:  the rectangle is always drawn at least 1x1 in  
      * size, so round up the upper coordinates to be at least 1 unit  
      * greater than the lower ones.  
      */  
   
     tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5  
             : rectOvalPtr->bbox[0] - .5);  
     rectOvalPtr->header.x1 = tmp - bloat;  
     tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5  
             : rectOvalPtr->bbox[1] - .5);  
     rectOvalPtr->header.y1 = tmp - bloat;  
     dtmp = rectOvalPtr->bbox[2];  
     if (dtmp < (rectOvalPtr->bbox[0] + 1)) {  
         dtmp = rectOvalPtr->bbox[0] + 1;  
     }  
     tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);  
     rectOvalPtr->header.x2 = tmp + bloat;  
     dtmp = rectOvalPtr->bbox[3];  
     if (dtmp < (rectOvalPtr->bbox[1] + 1)) {  
         dtmp = rectOvalPtr->bbox[1] + 1;  
     }  
     tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);  
     rectOvalPtr->header.y2 = tmp + bloat;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * DisplayRectOval --  
  *  
  *      This procedure is invoked to draw a rectangle or oval  
  *      item in a given drawable.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      ItemPtr is drawn in drawable using the transformation  
  *      information in canvas.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static void  
 DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)  
     Tk_Canvas canvas;                   /* Canvas that contains item. */  
     Tk_Item *itemPtr;                   /* Item to be displayed. */  
     Display *display;                   /* Display on which to draw item. */  
     Drawable drawable;                  /* Pixmap or window in which to draw  
                                          * item. */  
     int x, y, width, height;            /* Describes region of canvas that  
                                          * must be redisplayed (not used). */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
     short x1, y1, x2, y2;  
     Pixmap fillStipple;  
     Tk_State state = itemPtr->state;  
   
     /*  
      * Compute the screen coordinates of the bounding box for the item.  
      * Make sure that the bbox is at least one pixel large, since some  
      * X servers will die if it isn't.  
      */  
   
     Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0], rectOvalPtr->bbox[1],  
             &x1, &y1);  
     Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2], rectOvalPtr->bbox[3],  
             &x2, &y2);  
     if (x2 <= x1) {  
         x2 = x1+1;  
     }  
     if (y2 <= y1) {  
         y2 = y1+1;  
     }  
   
     /*  
      * Display filled part first (if wanted), then outline.  If we're  
      * stippling, then modify the stipple offset in the GC.  Be sure to  
      * reset the offset when done, since the GC is supposed to be  
      * read-only.  
      */  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
     fillStipple = rectOvalPtr->fillStipple;  
     if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {  
         if (rectOvalPtr->activeFillStipple!=None) {  
             fillStipple = rectOvalPtr->activeFillStipple;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectOvalPtr->disabledFillStipple!=None) {  
             fillStipple = rectOvalPtr->disabledFillStipple;  
         }  
     }  
   
     if (rectOvalPtr->fillGC != None) {  
         if (fillStipple != None) {  
             Tk_TSOffset *tsoffset;  
             int w=0; int h=0;  
             tsoffset = &rectOvalPtr->tsoffset;  
             if (tsoffset) {  
                 int flags = tsoffset->flags;  
                 if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {  
                     Tk_SizeOfBitmap(display, fillStipple, &w, &h);  
                     if (flags & TK_OFFSET_CENTER) {  
                         w /= 2;  
                     } else {  
                         w = 0;  
                     }  
                     if (flags & TK_OFFSET_MIDDLE) {  
                         h /= 2;  
                     } else {  
                         h = 0;  
                     }  
                 }  
                 tsoffset->xoffset -= w;  
                 tsoffset->yoffset -= h;  
             }  
             Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);  
             if (tsoffset) {  
                 tsoffset->xoffset += w;  
                 tsoffset->yoffset += h;  
             }  
         }  
         if (rectOvalPtr->header.typePtr == &tkRectangleType) {  
             XFillRectangle(display, drawable, rectOvalPtr->fillGC,  
                     x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));  
         } else {  
             XFillArc(display, drawable, rectOvalPtr->fillGC,  
                     x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),  
                     0, 360*64);  
         }  
         if (fillStipple != None) {  
             XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);  
         }  
     }  
     if (rectOvalPtr->outline.gc != None) {  
         Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));  
         if (rectOvalPtr->header.typePtr == &tkRectangleType) {  
             XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,  
                     x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));  
         } else {  
             XDrawArc(display, drawable, rectOvalPtr->outline.gc,  
                     x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);  
         }  
         Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));  
     }  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * RectToPoint --  
  *  
  *      Computes the distance from a given point to a given  
  *      rectangle, in canvas units.  
  *  
  * Results:  
  *      The return value is 0 if the point whose x and y coordinates  
  *      are coordPtr[0] and coordPtr[1] is inside the rectangle.  If the  
  *      point isn't inside the rectangle then the return value is the  
  *      distance from the point to the rectangle.  If itemPtr is filled,  
  *      then anywhere in the interior is considered "inside"; if  
  *      itemPtr isn't filled, then "inside" means only the area  
  *      occupied by the outline.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static double  
 RectToPoint(canvas, itemPtr, pointPtr)  
     Tk_Canvas canvas;           /* Canvas containing item. */  
     Tk_Item *itemPtr;           /* Item to check against point. */  
     double *pointPtr;           /* Pointer to x and y coordinates. */  
 {  
     RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;  
     double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;  
     double width;  
     Tk_State state = itemPtr->state;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
   
     width = rectPtr->outline.width;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (rectPtr->outline.activeWidth>width) {  
             width = rectPtr->outline.activeWidth;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectPtr->outline.disabledWidth>0) {  
             width = rectPtr->outline.disabledWidth;  
         }  
     }  
   
     /*  
      * Generate a new larger rectangle that includes the border  
      * width, if there is one.  
      */  
   
     x1 = rectPtr->bbox[0];  
     y1 = rectPtr->bbox[1];  
     x2 = rectPtr->bbox[2];  
     y2 = rectPtr->bbox[3];  
     if (rectPtr->outline.gc != None) {  
         inc = width/2.0;  
         x1 -= inc;  
         y1 -= inc;  
         x2 += inc;  
         y2 += inc;  
     }  
   
     /*  
      * If the point is inside the rectangle, handle specially:  
      * distance is 0 if rectangle is filled, otherwise compute  
      * distance to nearest edge of rectangle and subtract width  
      * of edge.  
      */  
   
     if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)  
                 && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {  
         if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) {  
             return 0.0;  
         }  
         xDiff = pointPtr[0] - x1;  
         tmp = x2 - pointPtr[0];  
         if (tmp < xDiff) {  
             xDiff = tmp;  
         }  
         yDiff = pointPtr[1] - y1;  
         tmp = y2 - pointPtr[1];  
         if (tmp < yDiff) {  
             yDiff = tmp;  
         }  
         if (yDiff < xDiff) {  
             xDiff = yDiff;  
         }  
         xDiff -= width;  
         if (xDiff < 0.0) {  
             return 0.0;  
         }  
         return xDiff;  
     }  
   
     /*  
      * Point is outside rectangle.  
      */  
   
     if (pointPtr[0] < x1) {  
         xDiff = x1 - pointPtr[0];  
     } else if (pointPtr[0] > x2)  {  
         xDiff = pointPtr[0] - x2;  
     } else {  
         xDiff = 0;  
     }  
   
     if (pointPtr[1] < y1) {  
         yDiff = y1 - pointPtr[1];  
     } else if (pointPtr[1] > y2)  {  
         yDiff = pointPtr[1] - y2;  
     } else {  
         yDiff = 0;  
     }  
   
     return hypot(xDiff, yDiff);  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * OvalToPoint --  
  *  
  *      Computes the distance from a given point to a given  
  *      oval, in canvas units.  
  *  
  * Results:  
  *      The return value is 0 if the point whose x and y coordinates  
  *      are coordPtr[0] and coordPtr[1] is inside the oval.  If the  
  *      point isn't inside the oval then the return value is the  
  *      distance from the point to the oval.  If itemPtr is filled,  
  *      then anywhere in the interior is considered "inside"; if  
  *      itemPtr isn't filled, then "inside" means only the area  
  *      occupied by the outline.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static double  
 OvalToPoint(canvas, itemPtr, pointPtr)  
     Tk_Canvas canvas;           /* Canvas containing item. */  
     Tk_Item *itemPtr;           /* Item to check against point. */  
     double *pointPtr;           /* Pointer to x and y coordinates. */  
 {  
     RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;  
     double width;  
     int filled;  
     Tk_State state = itemPtr->state;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
   
     width = (double) ovalPtr->outline.width;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (ovalPtr->outline.activeWidth>width) {  
             width = (double) ovalPtr->outline.activeWidth;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (ovalPtr->outline.disabledWidth>0) {  
             width = (double) ovalPtr->outline.disabledWidth;  
         }  
     }  
   
   
     filled = ovalPtr->fillGC != None;  
     if (ovalPtr->outline.gc == None) {  
         width = 0.0;  
         filled = 1;  
     }  
     return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * RectToArea --  
  *  
  *      This procedure is called to determine whether an item  
  *      lies entirely inside, entirely outside, or overlapping  
  *      a given rectangle.  
  *  
  * Results:  
  *      -1 is returned if the item is entirely outside the area  
  *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely  
  *      inside the given area.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static int  
 RectToArea(canvas, itemPtr, areaPtr)  
     Tk_Canvas canvas;           /* Canvas containing item. */  
     Tk_Item *itemPtr;           /* Item to check against rectangle. */  
     double *areaPtr;            /* Pointer to array of four coordinates  
                                  * (x1, y1, x2, y2) describing rectangular  
                                  * area.  */  
 {  
     RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;  
     double halfWidth;  
     double width;  
     Tk_State state = itemPtr->state;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
   
     width = rectPtr->outline.width;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (rectPtr->outline.activeWidth>width) {  
             width = rectPtr->outline.activeWidth;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectPtr->outline.disabledWidth>0) {  
             width = rectPtr->outline.disabledWidth;  
         }  
     }  
   
     halfWidth = width/2.0;  
     if (rectPtr->outline.gc == None) {  
         halfWidth = 0.0;  
     }  
   
     if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))  
             || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))  
             || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))  
             || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {  
         return -1;  
     }  
     if ((rectPtr->fillGC == None) && (rectPtr->outline.gc != None)  
             && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))  
             && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))  
             && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))  
             && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {  
         return -1;  
     }  
     if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))  
             && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))  
             && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))  
             && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {  
         return 1;  
     }  
     return 0;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * OvalToArea --  
  *  
  *      This procedure is called to determine whether an item  
  *      lies entirely inside, entirely outside, or overlapping  
  *      a given rectangular area.  
  *  
  * Results:  
  *      -1 is returned if the item is entirely outside the area  
  *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely  
  *      inside the given area.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
         /* ARGSUSED */  
 static int  
 OvalToArea(canvas, itemPtr, areaPtr)  
     Tk_Canvas canvas;           /* Canvas containing item. */  
     Tk_Item *itemPtr;           /* Item to check against oval. */  
     double *areaPtr;            /* Pointer to array of four coordinates  
                                  * (x1, y1, x2, y2) describing rectangular  
                                  * area.  */  
 {  
     RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;  
     double oval[4], halfWidth;  
     int result;  
     double width;  
     Tk_State state = itemPtr->state;  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
   
     width = ovalPtr->outline.width;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (ovalPtr->outline.activeWidth>width) {  
             width = ovalPtr->outline.activeWidth;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (ovalPtr->outline.disabledWidth>0) {  
             width = ovalPtr->outline.disabledWidth;  
         }  
     }  
   
     /*  
      * Expand the oval to include the width of the outline, if any.  
      */  
   
     halfWidth = width/2.0;  
     if (ovalPtr->outline.gc == None) {  
         halfWidth = 0.0;  
     }  
     oval[0] = ovalPtr->bbox[0] - halfWidth;  
     oval[1] = ovalPtr->bbox[1] - halfWidth;  
     oval[2] = ovalPtr->bbox[2] + halfWidth;  
     oval[3] = ovalPtr->bbox[3] + halfWidth;  
   
     result = TkOvalToArea(oval, areaPtr);  
   
     /*  
      * If the rectangle appears to overlap the oval and the oval  
      * isn't filled, do one more check to see if perhaps all four  
      * of the rectangle's corners are totally inside the oval's  
      * unfilled center, in which case we should return "outside".  
      */  
   
     if ((result == 0) && (ovalPtr->outline.gc != None)  
             && (ovalPtr->fillGC == None)) {  
         double centerX, centerY, height;  
         double xDelta1, yDelta1, xDelta2, yDelta2;  
   
         centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;  
         centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;  
         width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;  
         height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;  
         xDelta1 = (areaPtr[0] - centerX)/width;  
         xDelta1 *= xDelta1;  
         yDelta1 = (areaPtr[1] - centerY)/height;  
         yDelta1 *= yDelta1;  
         xDelta2 = (areaPtr[2] - centerX)/width;  
         xDelta2 *= xDelta2;  
         yDelta2 = (areaPtr[3] - centerY)/height;  
         yDelta2 *= yDelta2;  
         if (((xDelta1 + yDelta1) < 1.0)  
                 && ((xDelta1 + yDelta2) < 1.0)  
                 && ((xDelta2 + yDelta1) < 1.0)  
                 && ((xDelta2 + yDelta2) < 1.0)) {  
             return -1;  
         }  
     }  
     return result;  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * ScaleRectOval --  
  *  
  *      This procedure is invoked to rescale a rectangle or oval  
  *      item.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The rectangle or oval referred to by itemPtr is rescaled  
  *      so that the following transformation is applied to all  
  *      point coordinates:  
  *              x' = originX + scaleX*(x-originX)  
  *              y' = originY + scaleY*(y-originY)  
  *  
  *--------------------------------------------------------------  
  */  
   
 static void  
 ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY)  
     Tk_Canvas canvas;                   /* Canvas containing rectangle. */  
     Tk_Item *itemPtr;                   /* Rectangle to be scaled. */  
     double originX, originY;            /* Origin about which to scale rect. */  
     double scaleX;                      /* Amount to scale in X direction. */  
     double scaleY;                      /* Amount to scale in Y direction. */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
   
     rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);  
     rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);  
     rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);  
     rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);  
     ComputeRectOvalBbox(canvas, rectOvalPtr);  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * TranslateRectOval --  
  *  
  *      This procedure is called to move a rectangle or oval by a  
  *      given amount.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The position of the rectangle or oval is offset by  
  *      (xDelta, yDelta), and the bounding box is updated in the  
  *      generic part of the item structure.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static void  
 TranslateRectOval(canvas, itemPtr, deltaX, deltaY)  
     Tk_Canvas canvas;                   /* Canvas containing item. */  
     Tk_Item *itemPtr;                   /* Item that is being moved. */  
     double deltaX, deltaY;              /* Amount by which item is to be  
                                          * moved. */  
 {  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
   
     rectOvalPtr->bbox[0] += deltaX;  
     rectOvalPtr->bbox[1] += deltaY;  
     rectOvalPtr->bbox[2] += deltaX;  
     rectOvalPtr->bbox[3] += deltaY;  
     ComputeRectOvalBbox(canvas, rectOvalPtr);  
 }  
   
 /*  
  *--------------------------------------------------------------  
  *  
  * RectOvalToPostscript --  
  *  
  *      This procedure is called to generate Postscript for  
  *      rectangle and oval items.  
  *  
  * Results:  
  *      The return value is a standard Tcl result.  If an error  
  *      occurs in generating Postscript then an error message is  
  *      left in the interp's result, replacing whatever used to be there.  
  *      If no error occurs, then Postscript for the rectangle is  
  *      appended to the result.  
  *  
  * Side effects:  
  *      None.  
  *  
  *--------------------------------------------------------------  
  */  
   
 static int  
 RectOvalToPostscript(interp, canvas, itemPtr, prepass)  
     Tcl_Interp *interp;                 /* Interpreter for error reporting. */  
     Tk_Canvas canvas;                   /* Information about overall canvas. */  
     Tk_Item *itemPtr;                   /* Item for which Postscript is  
                                          * wanted. */  
     int prepass;                        /* 1 means this is a prepass to  
                                          * collect font information;  0 means  
                                          * final Postscript is being created. */  
 {  
     char pathCmd[500];  
     RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;  
     double y1, y2;  
     XColor *color;  
     XColor *fillColor;  
     Pixmap fillStipple;  
     Tk_State state = itemPtr->state;  
   
     y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);  
     y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);  
   
     /*  
      * Generate a string that creates a path for the rectangle or oval.  
      * This is the only part of the procedure's code that is type-  
      * specific.  
      */  
   
   
     if (rectOvalPtr->header.typePtr == &tkRectangleType) {  
         sprintf(pathCmd, "%.15g %.15g moveto %.15g 0 rlineto 0 %.15g rlineto %.15g 0 rlineto closepath\n",  
                 rectOvalPtr->bbox[0], y1,  
                 rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0], y2-y1,  
                 rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);  
     } else {  
         sprintf(pathCmd, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",  
                 (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,  
                 (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);  
     }  
   
     if(state == TK_STATE_NULL) {  
         state = ((TkCanvas *)canvas)->canvas_state;  
     }  
     color = rectOvalPtr->outline.color;  
     fillColor = rectOvalPtr->fillColor;  
     fillStipple = rectOvalPtr->fillStipple;  
     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {  
         if (rectOvalPtr->outline.activeColor!=NULL) {  
             color = rectOvalPtr->outline.activeColor;  
         }  
         if (rectOvalPtr->activeFillColor!=NULL) {  
             fillColor = rectOvalPtr->activeFillColor;  
         }  
         if (rectOvalPtr->activeFillStipple!=None) {  
             fillStipple = rectOvalPtr->activeFillStipple;  
         }  
     } else if (state==TK_STATE_DISABLED) {  
         if (rectOvalPtr->outline.disabledColor!=NULL) {  
             color = rectOvalPtr->outline.disabledColor;  
         }  
         if (rectOvalPtr->disabledFillColor!=NULL) {  
             fillColor = rectOvalPtr->disabledFillColor;  
         }  
         if (rectOvalPtr->disabledFillStipple!=None) {  
             fillStipple = rectOvalPtr->disabledFillStipple;  
         }  
     }  
   
     /*  
      * First draw the filled area of the rectangle.  
      */  
   
     if (fillColor != NULL) {  
         Tcl_AppendResult(interp, pathCmd, (char *) NULL);  
         if (Tk_CanvasPsColor(interp, canvas, fillColor)  
                 != TCL_OK) {  
             return TCL_ERROR;  
         }  
         if (fillStipple != None) {  
             Tcl_AppendResult(interp, "clip ", (char *) NULL);  
             if (Tk_CanvasPsStipple(interp, canvas, fillStipple)  
                     != TCL_OK) {  
                 return TCL_ERROR;  
             }  
             if (color != NULL) {  
                 Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);  
             }  
         } else {  
             Tcl_AppendResult(interp, "fill\n", (char *) NULL);  
         }  
     }  
   
     /*  
      * Now draw the outline, if there is one.  
      */  
   
     if (color != NULL) {  
         Tcl_AppendResult(interp, pathCmd, "0 setlinejoin 2 setlinecap\n",  
                 (char *) NULL);  
         if (Tk_CanvasPsOutline(canvas, itemPtr,  
                 &(rectOvalPtr->outline))!= TCL_OK) {  
             return TCL_ERROR;  
         }  
     }  
     return TCL_OK;  
 }  
   
   
 /* $History: tkRectOval.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 3:03a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKRECTOVAL.C */  
1    /* $Header$ */
2    
3    /*
4     * tkRectOval.c --
5     *
6     *      This file implements rectangle and oval items for canvas
7     *      widgets.
8     *
9     * Copyright (c) 1991-1994 The Regents of the University of California.
10     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11     *
12     * See the file "license.terms" for information on usage and redistribution
13     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14     *
15     * RCS: @(#) $Id: tkrectoval.c,v 1.1.1.1 2001/06/13 05:07:29 dtashley Exp $
16     */
17    
18    #include <stdio.h>
19    #include "tk.h"
20    #include "tkInt.h"
21    #include "tkPort.h"
22    #include "tkCanvas.h"
23    
24    /*
25     * The structure below defines the record for each rectangle/oval item.
26     */
27    
28    typedef struct RectOvalItem  {
29        Tk_Item header;             /* Generic stuff that's the same for all
30                                     * types.  MUST BE FIRST IN STRUCTURE. */
31        Tk_Outline outline;         /* Outline structure */
32        double bbox[4];             /* Coordinates of bounding box for rectangle
33                                     * or oval (x1, y1, x2, y2).  Item includes
34                                     * x1 and x2 but not y1 and y2. */
35        Tk_TSOffset tsoffset;
36        XColor *fillColor;          /* Color for filling rectangle/oval. */
37        XColor *activeFillColor;    /* Color for filling rectangle/oval if state is active. */
38        XColor *disabledFillColor;  /* Color for filling rectangle/oval if state is disabled. */
39        Pixmap fillStipple;         /* Stipple bitmap for filling item. */
40        Pixmap activeFillStipple;   /* Stipple bitmap for filling item if state is active. */
41        Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is disabled. */
42        GC fillGC;                  /* Graphics context for filling item. */
43    } RectOvalItem;
44    
45    /*
46     * Information used for parsing configuration specs:
47     */
48    
49    static Tk_CustomOption stateOption = {
50        (Tk_OptionParseProc *) TkStateParseProc,
51        TkStatePrintProc, (ClientData) 2
52    };
53    static Tk_CustomOption tagsOption = {
54        (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
55        Tk_CanvasTagsPrintProc, (ClientData) NULL
56    };
57    static Tk_CustomOption dashOption = {
58        (Tk_OptionParseProc *) TkCanvasDashParseProc,
59        TkCanvasDashPrintProc, (ClientData) NULL
60    };
61    static Tk_CustomOption offsetOption = {
62        (Tk_OptionParseProc *) TkOffsetParseProc,
63        TkOffsetPrintProc, (ClientData) TK_OFFSET_RELATIVE
64    };
65    static Tk_CustomOption pixelOption = {
66        (Tk_OptionParseProc *) TkPixelParseProc,
67        TkPixelPrintProc, (ClientData) NULL
68    };
69    
70    static Tk_ConfigSpec configSpecs[] = {
71        {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
72            (char *) NULL, Tk_Offset(RectOvalItem, outline.activeDash),
73            TK_CONFIG_NULL_OK, &dashOption},
74        {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
75            (char *) NULL, Tk_Offset(RectOvalItem, activeFillColor),
76            TK_CONFIG_NULL_OK},
77        {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
78            (char *) NULL, Tk_Offset(RectOvalItem, outline.activeColor),
79            TK_CONFIG_NULL_OK},
80        {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
81            (char *) NULL, Tk_Offset(RectOvalItem, outline.activeStipple),
82            TK_CONFIG_NULL_OK},
83        {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
84            (char *) NULL, Tk_Offset(RectOvalItem, activeFillStipple),
85            TK_CONFIG_NULL_OK},
86        {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
87            "0.0", Tk_Offset(RectOvalItem, outline.activeWidth),
88            TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
89        {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
90            (char *) NULL, Tk_Offset(RectOvalItem, outline.dash),
91            TK_CONFIG_NULL_OK, &dashOption},
92        {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
93            "0", Tk_Offset(RectOvalItem, outline.offset),
94            TK_CONFIG_DONT_SET_DEFAULT},
95        {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
96            (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledDash),
97            TK_CONFIG_NULL_OK, &dashOption},
98        {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
99            (char *) NULL, Tk_Offset(RectOvalItem, disabledFillColor),
100            TK_CONFIG_NULL_OK},
101        {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
102            (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledColor),
103            TK_CONFIG_NULL_OK},
104        {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
105            (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),
106            TK_CONFIG_NULL_OK},
107        {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
108            (char *) NULL, Tk_Offset(RectOvalItem, disabledFillStipple),
109            TK_CONFIG_NULL_OK},
110        {TK_CONFIG_PIXELS, "-disabledwidth", (char *) NULL, (char *) NULL,
111            "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),
112            TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
113        {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
114            (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
115        {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
116            "0,0", Tk_Offset(RectOvalItem, tsoffset),
117            TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
118        {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
119            "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK},
120        {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
121            "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
122            TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
123        {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
124            (char *) NULL, Tk_Offset(RectOvalItem, outline.stipple),
125            TK_CONFIG_NULL_OK},
126        {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
127            (char *) NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK,
128            &stateOption},
129        {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
130            (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
131        {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
132            (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
133        {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
134            "1.0", Tk_Offset(RectOvalItem, outline.width),
135            TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
136        {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
137            (char *) NULL, 0, 0}
138    };
139    
140    /*
141     * Prototypes for procedures defined in this file:
142     */
143    
144    static void             ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas,
145                                RectOvalItem *rectOvalPtr));
146    static int              ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp,
147                                Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
148                                Tcl_Obj *CONST argv[], int flags));
149    static int              CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp,
150                                Tk_Canvas canvas, struct Tk_Item *itemPtr,
151                                int argc, Tcl_Obj *CONST argv[]));
152    static void             DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas,
153                                Tk_Item *itemPtr, Display *display));
154    static void             DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas,
155                                Tk_Item *itemPtr, Display *display, Drawable dst,
156                                int x, int y, int width, int height));
157    static int              OvalToArea _ANSI_ARGS_((Tk_Canvas canvas,
158                                Tk_Item *itemPtr, double *areaPtr));
159    static double           OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas,
160                                Tk_Item *itemPtr, double *pointPtr));
161    static int              RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp,
162                                Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
163                                Tcl_Obj *CONST argv[]));
164    static int              RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
165                                Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
166    static int              RectToArea _ANSI_ARGS_((Tk_Canvas canvas,
167                                Tk_Item *itemPtr, double *areaPtr));
168    static double           RectToPoint _ANSI_ARGS_((Tk_Canvas canvas,
169                                Tk_Item *itemPtr, double *pointPtr));
170    static void             ScaleRectOval _ANSI_ARGS_((Tk_Canvas canvas,
171                                Tk_Item *itemPtr, double originX, double originY,
172                                double scaleX, double scaleY));
173    static void             TranslateRectOval _ANSI_ARGS_((Tk_Canvas canvas,
174                                Tk_Item *itemPtr, double deltaX, double deltaY));
175    
176    /*
177     * The structures below defines the rectangle and oval item types
178     * by means of procedures that can be invoked by generic item code.
179     */
180    
181    Tk_ItemType tkRectangleType = {
182        "rectangle",                        /* name */
183        sizeof(RectOvalItem),               /* itemSize */
184        CreateRectOval,                     /* createProc */
185        configSpecs,                        /* configSpecs */
186        ConfigureRectOval,                  /* configureProc */
187        RectOvalCoords,                     /* coordProc */
188        DeleteRectOval,                     /* deleteProc */
189        DisplayRectOval,                    /* displayProc */
190        TK_CONFIG_OBJS,                     /* flags */
191        RectToPoint,                        /* pointProc */
192        RectToArea,                         /* areaProc */
193        RectOvalToPostscript,               /* postscriptProc */
194        ScaleRectOval,                      /* scaleProc */
195        TranslateRectOval,                  /* translateProc */
196        (Tk_ItemIndexProc *) NULL,          /* indexProc */
197        (Tk_ItemCursorProc *) NULL,         /* icursorProc */
198        (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
199        (Tk_ItemInsertProc *) NULL,         /* insertProc */
200        (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
201        (Tk_ItemType *) NULL,               /* nextPtr */
202    };
203    
204    Tk_ItemType tkOvalType = {
205        "oval",                             /* name */
206        sizeof(RectOvalItem),               /* itemSize */
207        CreateRectOval,                     /* createProc */
208        configSpecs,                        /* configSpecs */
209        ConfigureRectOval,                  /* configureProc */
210        RectOvalCoords,                     /* coordProc */
211        DeleteRectOval,                     /* deleteProc */
212        DisplayRectOval,                    /* displayProc */
213        TK_CONFIG_OBJS,                     /* flags */
214        OvalToPoint,                        /* pointProc */
215        OvalToArea,                         /* areaProc */
216        RectOvalToPostscript,               /* postscriptProc */
217        ScaleRectOval,                      /* scaleProc */
218        TranslateRectOval,                  /* translateProc */
219        (Tk_ItemIndexProc *) NULL,          /* indexProc */
220        (Tk_ItemCursorProc *) NULL,         /* cursorProc */
221        (Tk_ItemSelectionProc *) NULL,      /* selectionProc */
222        (Tk_ItemInsertProc *) NULL,         /* insertProc */
223        (Tk_ItemDCharsProc *) NULL,         /* dTextProc */
224        (Tk_ItemType *) NULL,               /* nextPtr */
225    };
226    
227    /*
228     *--------------------------------------------------------------
229     *
230     * CreateRectOval --
231     *
232     *      This procedure is invoked to create a new rectangle
233     *      or oval item in a canvas.
234     *
235     * Results:
236     *      A standard Tcl return value.  If an error occurred in
237     *      creating the item, then an error message is left in
238     *      the interp's result;  in this case itemPtr is left uninitialized,
239     *      so it can be safely freed by the caller.
240     *
241     * Side effects:
242     *      A new rectangle or oval item is created.
243     *
244     *--------------------------------------------------------------
245     */
246    
247    static int
248    CreateRectOval(interp, canvas, itemPtr, argc, argv)
249        Tcl_Interp *interp;                 /* For error reporting. */
250        Tk_Canvas canvas;                   /* Canvas to hold new item. */
251        Tk_Item *itemPtr;                   /* Record to hold new item;  header
252                                             * has been initialized by caller. */
253        int argc;                           /* Number of arguments in argv. */
254        Tcl_Obj *CONST argv[];              /* Arguments describing rectangle. */
255    {
256        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
257        int i;
258    
259    
260        if (argc==1) {
261            i = 1;
262        } else {
263            char *arg = Tcl_GetStringFromObj(argv[1], NULL);
264            if ((argc>1) && (arg[0] == '-')
265                    && (arg[1] >= 'a') && (arg[1] <= 'z')) {
266                i = 1;
267            } else {
268                i = 4;
269            }
270        }
271    
272        if (argc < i) {
273            Tcl_AppendResult(interp, "wrong # args: should be \"",
274                    Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
275                    itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
276                    (char *) NULL);
277            return TCL_ERROR;
278        }
279    
280        /*
281         * Carry out initialization that is needed in order to clean
282         * up after errors during the the remainder of this procedure.
283         */
284    
285        Tk_CreateOutline(&(rectOvalPtr->outline));
286        rectOvalPtr->tsoffset.flags = 0;
287        rectOvalPtr->tsoffset.xoffset = 0;
288        rectOvalPtr->tsoffset.yoffset = 0;
289        rectOvalPtr->fillColor = NULL;
290        rectOvalPtr->activeFillColor = NULL;
291        rectOvalPtr->disabledFillColor = NULL;
292        rectOvalPtr->fillStipple = None;
293        rectOvalPtr->activeFillStipple = None;
294        rectOvalPtr->disabledFillStipple = None;
295        rectOvalPtr->fillGC = None;
296    
297        /*
298         * Process the arguments to fill in the item record.
299         */
300    
301        if ((RectOvalCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
302            goto error;
303        }
304        if (ConfigureRectOval(interp, canvas, itemPtr, argc-i, argv+i, 0)
305                == TCL_OK) {
306            return TCL_OK;
307        }
308    
309        error:
310        DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
311        return TCL_ERROR;
312    }
313    
314    /*
315     *--------------------------------------------------------------
316     *
317     * RectOvalCoords --
318     *
319     *      This procedure is invoked to process the "coords" widget
320     *      command on rectangles and ovals.  See the user documentation
321     *      for details on what it does.
322     *
323     * Results:
324     *      Returns TCL_OK or TCL_ERROR, and sets the interp's result.
325     *
326     * Side effects:
327     *      The coordinates for the given item may be changed.
328     *
329     *--------------------------------------------------------------
330     */
331    
332    static int
333    RectOvalCoords(interp, canvas, itemPtr, argc, argv)
334        Tcl_Interp *interp;                 /* Used for error reporting. */
335        Tk_Canvas canvas;                   /* Canvas containing item. */
336        Tk_Item *itemPtr;                   /* Item whose coordinates are to be
337                                             * read or modified. */
338        int argc;                           /* Number of coordinates supplied in
339                                             * argv. */
340        Tcl_Obj *CONST argv[];              /* Array of coordinates: x1, y1,
341                                             * x2, y2, ... */
342    {
343        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
344    
345        if (argc == 0) {
346            Tcl_Obj *obj = Tcl_NewObj();
347            Tcl_Obj *subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);
348            Tcl_ListObjAppendElement(interp, obj, subobj);
349            subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);
350            Tcl_ListObjAppendElement(interp, obj, subobj);
351            subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);
352            Tcl_ListObjAppendElement(interp, obj, subobj);
353            subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);
354            Tcl_ListObjAppendElement(interp, obj, subobj);
355            Tcl_SetObjResult(interp, obj);
356        } else if ((argc == 1)||(argc == 4)) {
357            if (argc==1) {
358                if (Tcl_ListObjGetElements(interp, argv[0], &argc,
359                        (Tcl_Obj ***) &argv) != TCL_OK) {
360                    return TCL_ERROR;
361                } else if (argc != 4) {
362                    char buf[64 + TCL_INTEGER_SPACE];
363    
364                    sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
365                    Tcl_SetResult(interp, buf, TCL_VOLATILE);
366                    return TCL_ERROR;
367                }
368            }
369            if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],
370                        &rectOvalPtr->bbox[0]) != TCL_OK)
371                    || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
372                        &rectOvalPtr->bbox[1]) != TCL_OK)
373                    || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[2],
374                            &rectOvalPtr->bbox[2]) != TCL_OK)
375                    || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[3],
376                            &rectOvalPtr->bbox[3]) != TCL_OK)) {
377                return TCL_ERROR;
378            }
379            ComputeRectOvalBbox(canvas, rectOvalPtr);
380        } else {
381            char buf[64 + TCL_INTEGER_SPACE];
382            
383            sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
384            Tcl_SetResult(interp, buf, TCL_VOLATILE);
385            return TCL_ERROR;
386        }
387        return TCL_OK;
388    }
389    
390    /*
391     *--------------------------------------------------------------
392     *
393     * ConfigureRectOval --
394     *
395     *      This procedure is invoked to configure various aspects
396     *      of a rectangle or oval item, such as its border and
397     *      background colors.
398     *
399     * Results:
400     *      A standard Tcl result code.  If an error occurs, then
401     *      an error message is left in the interp's result.
402     *
403     * Side effects:
404     *      Configuration information, such as colors and stipple
405     *      patterns, may be set for itemPtr.
406     *
407     *--------------------------------------------------------------
408     */
409    
410    static int
411    ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
412        Tcl_Interp *interp;         /* Used for error reporting. */
413        Tk_Canvas canvas;           /* Canvas containing itemPtr. */
414        Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */
415        int argc;                   /* Number of elements in argv.  */
416        Tcl_Obj *CONST argv[];      /* Arguments describing things to configure. */
417        int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
418    {
419        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
420        XGCValues gcValues;
421        GC newGC;
422        unsigned long mask;
423        Tk_Window tkwin;
424        Tk_TSOffset *tsoffset;
425        XColor *color;
426        Pixmap stipple;
427        Tk_State state;
428    
429        tkwin = Tk_CanvasTkwin(canvas);
430    
431        if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
432                (char *) rectOvalPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
433            return TCL_ERROR;
434        }
435        state = itemPtr->state;
436    
437        /*
438         * A few of the options require additional processing, such as
439         * graphics contexts.
440         */
441    
442        if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||
443                rectOvalPtr->outline.activeDash.number != 0 ||
444                rectOvalPtr->outline.activeColor != NULL ||
445                rectOvalPtr->outline.activeStipple != None ||
446                rectOvalPtr->activeFillColor != NULL ||
447                rectOvalPtr->activeFillStipple != None) {
448            itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
449        } else {
450            itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
451        }
452    
453        tsoffset = &rectOvalPtr->outline.tsoffset;
454        flags = tsoffset->flags;
455        if (flags & TK_OFFSET_LEFT) {
456            tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
457        } else if (flags & TK_OFFSET_CENTER) {
458            tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
459        } else if (flags & TK_OFFSET_RIGHT) {
460            tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
461        }
462        if (flags & TK_OFFSET_TOP) {
463            tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
464        } else if (flags & TK_OFFSET_MIDDLE) {
465            tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
466        } else if (flags & TK_OFFSET_BOTTOM) {
467            tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
468        }
469    
470        /*
471         * Configure the outline graphics context.  If mask is non-zero,
472         * the gc has changed and must be reallocated, provided that the
473         * new settings specify a valid outline (non-zero width and non-NULL
474         * color)
475         */
476    
477        mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
478                 &(rectOvalPtr->outline));
479        if (mask && \
480                rectOvalPtr->outline.width != 0 && \
481                rectOvalPtr->outline.color != NULL) {
482            gcValues.cap_style = CapProjecting;
483            mask |= GCCapStyle;
484            newGC = Tk_GetGC(tkwin, mask, &gcValues);
485        } else {
486            newGC = None;
487        }
488        if (rectOvalPtr->outline.gc != None) {
489            Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);
490        }
491        rectOvalPtr->outline.gc = newGC;
492    
493        if(state == TK_STATE_NULL) {
494            state = ((TkCanvas *)canvas)->canvas_state;
495        }
496        if (state==TK_STATE_HIDDEN) {
497            ComputeRectOvalBbox(canvas, rectOvalPtr);
498            return TCL_OK;
499        }
500    
501        color = rectOvalPtr->fillColor;
502        stipple = rectOvalPtr->fillStipple;
503        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
504            if (rectOvalPtr->activeFillColor!=NULL) {
505                color = rectOvalPtr->activeFillColor;
506            }
507            if (rectOvalPtr->activeFillStipple!=None) {
508                stipple = rectOvalPtr->activeFillStipple;
509            }
510        } else if (state==TK_STATE_DISABLED) {
511            if (rectOvalPtr->disabledFillColor!=NULL) {
512                color = rectOvalPtr->disabledFillColor;
513            }
514            if (rectOvalPtr->disabledFillStipple!=None) {
515                stipple = rectOvalPtr->disabledFillStipple;
516            }
517        }
518    
519        if (color == NULL) {
520            newGC = None;
521        } else {
522            gcValues.foreground = color->pixel;
523            if (stipple != None) {
524                gcValues.stipple = stipple;
525                gcValues.fill_style = FillStippled;
526                mask = GCForeground|GCStipple|GCFillStyle;
527            } else {
528                mask = GCForeground;
529            }
530            newGC = Tk_GetGC(tkwin, mask, &gcValues);
531        }
532        if (rectOvalPtr->fillGC != None) {
533            Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
534        }
535        rectOvalPtr->fillGC = newGC;
536    
537        tsoffset = &rectOvalPtr->tsoffset;
538        flags = tsoffset->flags;
539        if (flags & TK_OFFSET_LEFT) {
540            tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
541        } else if (flags & TK_OFFSET_CENTER) {
542            tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
543        } else if (flags & TK_OFFSET_RIGHT) {
544            tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
545        }
546        if (flags & TK_OFFSET_TOP) {
547            tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
548        } else if (flags & TK_OFFSET_MIDDLE) {
549            tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
550        } else if (flags & TK_OFFSET_BOTTOM) {
551            tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);
552        }
553    
554        ComputeRectOvalBbox(canvas, rectOvalPtr);
555    
556        return TCL_OK;
557    }
558    
559    /*
560     *--------------------------------------------------------------
561     *
562     * DeleteRectOval --
563     *
564     *      This procedure is called to clean up the data structure
565     *      associated with a rectangle or oval item.
566     *
567     * Results:
568     *      None.
569     *
570     * Side effects:
571     *      Resources associated with itemPtr are released.
572     *
573     *--------------------------------------------------------------
574     */
575    
576    static void
577    DeleteRectOval(canvas, itemPtr, display)
578        Tk_Canvas canvas;                   /* Info about overall widget. */
579        Tk_Item *itemPtr;                   /* Item that is being deleted. */
580        Display *display;                   /* Display containing window for
581                                             * canvas. */
582    {
583        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
584    
585        Tk_DeleteOutline(display, &(rectOvalPtr->outline));
586        if (rectOvalPtr->fillColor != NULL) {
587            Tk_FreeColor(rectOvalPtr->fillColor);
588        }
589        if (rectOvalPtr->activeFillColor != NULL) {
590            Tk_FreeColor(rectOvalPtr->activeFillColor);
591        }
592        if (rectOvalPtr->disabledFillColor != NULL) {
593            Tk_FreeColor(rectOvalPtr->disabledFillColor);
594        }
595        if (rectOvalPtr->fillStipple != None) {
596            Tk_FreeBitmap(display, rectOvalPtr->fillStipple);
597        }
598        if (rectOvalPtr->activeFillStipple != None) {
599            Tk_FreeBitmap(display, rectOvalPtr->activeFillStipple);
600        }
601        if (rectOvalPtr->disabledFillStipple != None) {
602            Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);
603        }
604        if (rectOvalPtr->fillGC != None) {
605            Tk_FreeGC(display, rectOvalPtr->fillGC);
606        }
607    }
608    
609    /*
610     *--------------------------------------------------------------
611     *
612     * ComputeRectOvalBbox --
613     *
614     *      This procedure is invoked to compute the bounding box of
615     *      all the pixels that may be drawn as part of a rectangle
616     *      or oval.
617     *
618     * Results:
619     *      None.
620     *
621     * Side effects:
622     *      The fields x1, y1, x2, and y2 are updated in the header
623     *      for itemPtr.
624     *
625     *--------------------------------------------------------------
626     */
627    
628            /* ARGSUSED */
629    static void
630    ComputeRectOvalBbox(canvas, rectOvalPtr)
631        Tk_Canvas canvas;                   /* Canvas that contains item. */
632        RectOvalItem *rectOvalPtr;          /* Item whose bbox is to be
633                                             * recomputed. */
634    {
635        int bloat, tmp;
636        double dtmp, width;
637        Tk_State state = rectOvalPtr->header.state;
638    
639        if(state == TK_STATE_NULL) {
640            state = ((TkCanvas *)canvas)->canvas_state;
641        }
642    
643        width = rectOvalPtr->outline.width;
644        if (state==TK_STATE_HIDDEN) {
645            rectOvalPtr->header.x1 = rectOvalPtr->header.y1 =
646            rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;
647            return;
648        }
649        if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
650            if (rectOvalPtr->outline.activeWidth>width) {
651                width = rectOvalPtr->outline.activeWidth;
652            }
653        } else if (state==TK_STATE_DISABLED) {
654            if (rectOvalPtr->outline.disabledWidth>0) {
655                width = rectOvalPtr->outline.disabledWidth;
656            }
657        }
658    
659        /*
660         * Make sure that the first coordinates are the lowest ones.
661         */
662    
663        if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
664            double tmp;
665            tmp = rectOvalPtr->bbox[3];
666            rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
667            rectOvalPtr->bbox[1] = tmp;
668        }
669        if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
670            double tmp;
671            tmp = rectOvalPtr->bbox[2];
672            rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
673            rectOvalPtr->bbox[0] = tmp;
674        }
675    
676        if (rectOvalPtr->outline.gc == None) {
677            /*
678             * The Win32 switch was added for 8.3 to solve a problem
679             * with ovals leaving traces on bottom and right of 1 pixel.
680             * This may not be the correct place to solve it, but it works.
681             */
682    #ifdef __WIN32__
683            bloat = 1;
684    #else
685            bloat = 0;
686    #endif
687        } else {
688            bloat = (int) (width+1)/2;
689        }
690    
691        /*
692         * Special note:  the rectangle is always drawn at least 1x1 in
693         * size, so round up the upper coordinates to be at least 1 unit
694         * greater than the lower ones.
695         */
696    
697        tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5
698                : rectOvalPtr->bbox[0] - .5);
699        rectOvalPtr->header.x1 = tmp - bloat;
700        tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5
701                : rectOvalPtr->bbox[1] - .5);
702        rectOvalPtr->header.y1 = tmp - bloat;
703        dtmp = rectOvalPtr->bbox[2];
704        if (dtmp < (rectOvalPtr->bbox[0] + 1)) {
705            dtmp = rectOvalPtr->bbox[0] + 1;
706        }
707        tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
708        rectOvalPtr->header.x2 = tmp + bloat;
709        dtmp = rectOvalPtr->bbox[3];
710        if (dtmp < (rectOvalPtr->bbox[1] + 1)) {
711            dtmp = rectOvalPtr->bbox[1] + 1;
712        }
713        tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
714        rectOvalPtr->header.y2 = tmp + bloat;
715    }
716    
717    /*
718     *--------------------------------------------------------------
719     *
720     * DisplayRectOval --
721     *
722     *      This procedure is invoked to draw a rectangle or oval
723     *      item in a given drawable.
724     *
725     * Results:
726     *      None.
727     *
728     * Side effects:
729     *      ItemPtr is drawn in drawable using the transformation
730     *      information in canvas.
731     *
732     *--------------------------------------------------------------
733     */
734    
735    static void
736    DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
737        Tk_Canvas canvas;                   /* Canvas that contains item. */
738        Tk_Item *itemPtr;                   /* Item to be displayed. */
739        Display *display;                   /* Display on which to draw item. */
740        Drawable drawable;                  /* Pixmap or window in which to draw
741                                             * item. */
742        int x, y, width, height;            /* Describes region of canvas that
743                                             * must be redisplayed (not used). */
744    {
745        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
746        short x1, y1, x2, y2;
747        Pixmap fillStipple;
748        Tk_State state = itemPtr->state;
749    
750        /*
751         * Compute the screen coordinates of the bounding box for the item.
752         * Make sure that the bbox is at least one pixel large, since some
753         * X servers will die if it isn't.
754         */
755    
756        Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0], rectOvalPtr->bbox[1],
757                &x1, &y1);
758        Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2], rectOvalPtr->bbox[3],
759                &x2, &y2);
760        if (x2 <= x1) {
761            x2 = x1+1;
762        }
763        if (y2 <= y1) {
764            y2 = y1+1;
765        }
766    
767        /*
768         * Display filled part first (if wanted), then outline.  If we're
769         * stippling, then modify the stipple offset in the GC.  Be sure to
770         * reset the offset when done, since the GC is supposed to be
771         * read-only.
772         */
773    
774        if(state == TK_STATE_NULL) {
775            state = ((TkCanvas *)canvas)->canvas_state;
776        }
777        fillStipple = rectOvalPtr->fillStipple;
778        if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
779            if (rectOvalPtr->activeFillStipple!=None) {
780                fillStipple = rectOvalPtr->activeFillStipple;
781            }
782        } else if (state==TK_STATE_DISABLED) {
783            if (rectOvalPtr->disabledFillStipple!=None) {
784                fillStipple = rectOvalPtr->disabledFillStipple;
785            }
786        }
787    
788        if (rectOvalPtr->fillGC != None) {
789            if (fillStipple != None) {
790                Tk_TSOffset *tsoffset;
791                int w=0; int h=0;
792                tsoffset = &rectOvalPtr->tsoffset;
793                if (tsoffset) {
794                    int flags = tsoffset->flags;
795                    if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
796                        Tk_SizeOfBitmap(display, fillStipple, &w, &h);
797                        if (flags & TK_OFFSET_CENTER) {
798                            w /= 2;
799                        } else {
800                            w = 0;
801                        }
802                        if (flags & TK_OFFSET_MIDDLE) {
803                            h /= 2;
804                        } else {
805                            h = 0;
806                        }
807                    }
808                    tsoffset->xoffset -= w;
809                    tsoffset->yoffset -= h;
810                }
811                Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);
812                if (tsoffset) {
813                    tsoffset->xoffset += w;
814                    tsoffset->yoffset += h;
815                }
816            }
817            if (rectOvalPtr->header.typePtr == &tkRectangleType) {
818                XFillRectangle(display, drawable, rectOvalPtr->fillGC,
819                        x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
820            } else {
821                XFillArc(display, drawable, rectOvalPtr->fillGC,
822                        x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
823                        0, 360*64);
824            }
825            if (fillStipple != None) {
826                XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
827            }
828        }
829        if (rectOvalPtr->outline.gc != None) {
830            Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
831            if (rectOvalPtr->header.typePtr == &tkRectangleType) {
832                XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
833                        x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
834            } else {
835                XDrawArc(display, drawable, rectOvalPtr->outline.gc,
836                        x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
837            }
838            Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
839        }
840    }
841    
842    /*
843     *--------------------------------------------------------------
844     *
845     * RectToPoint --
846     *
847     *      Computes the distance from a given point to a given
848     *      rectangle, in canvas units.
849     *
850     * Results:
851     *      The return value is 0 if the point whose x and y coordinates
852     *      are coordPtr[0] and coordPtr[1] is inside the rectangle.  If the
853     *      point isn't inside the rectangle then the return value is the
854     *      distance from the point to the rectangle.  If itemPtr is filled,
855     *      then anywhere in the interior is considered "inside"; if
856     *      itemPtr isn't filled, then "inside" means only the area
857     *      occupied by the outline.
858     *
859     * Side effects:
860     *      None.
861     *
862     *--------------------------------------------------------------
863     */
864    
865            /* ARGSUSED */
866    static double
867    RectToPoint(canvas, itemPtr, pointPtr)
868        Tk_Canvas canvas;           /* Canvas containing item. */
869        Tk_Item *itemPtr;           /* Item to check against point. */
870        double *pointPtr;           /* Pointer to x and y coordinates. */
871    {
872        RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
873        double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
874        double width;
875        Tk_State state = itemPtr->state;
876    
877        if(state == TK_STATE_NULL) {
878            state = ((TkCanvas *)canvas)->canvas_state;
879        }
880    
881        width = rectPtr->outline.width;
882        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
883            if (rectPtr->outline.activeWidth>width) {
884                width = rectPtr->outline.activeWidth;
885            }
886        } else if (state==TK_STATE_DISABLED) {
887            if (rectPtr->outline.disabledWidth>0) {
888                width = rectPtr->outline.disabledWidth;
889            }
890        }
891    
892        /*
893         * Generate a new larger rectangle that includes the border
894         * width, if there is one.
895         */
896    
897        x1 = rectPtr->bbox[0];
898        y1 = rectPtr->bbox[1];
899        x2 = rectPtr->bbox[2];
900        y2 = rectPtr->bbox[3];
901        if (rectPtr->outline.gc != None) {
902            inc = width/2.0;
903            x1 -= inc;
904            y1 -= inc;
905            x2 += inc;
906            y2 += inc;
907        }
908    
909        /*
910         * If the point is inside the rectangle, handle specially:
911         * distance is 0 if rectangle is filled, otherwise compute
912         * distance to nearest edge of rectangle and subtract width
913         * of edge.
914         */
915    
916        if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
917                    && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
918            if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) {
919                return 0.0;
920            }
921            xDiff = pointPtr[0] - x1;
922            tmp = x2 - pointPtr[0];
923            if (tmp < xDiff) {
924                xDiff = tmp;
925            }
926            yDiff = pointPtr[1] - y1;
927            tmp = y2 - pointPtr[1];
928            if (tmp < yDiff) {
929                yDiff = tmp;
930            }
931            if (yDiff < xDiff) {
932                xDiff = yDiff;
933            }
934            xDiff -= width;
935            if (xDiff < 0.0) {
936                return 0.0;
937            }
938            return xDiff;
939        }
940    
941        /*
942         * Point is outside rectangle.
943         */
944    
945        if (pointPtr[0] < x1) {
946            xDiff = x1 - pointPtr[0];
947        } else if (pointPtr[0] > x2)  {
948            xDiff = pointPtr[0] - x2;
949        } else {
950            xDiff = 0;
951        }
952    
953        if (pointPtr[1] < y1) {
954            yDiff = y1 - pointPtr[1];
955        } else if (pointPtr[1] > y2)  {
956            yDiff = pointPtr[1] - y2;
957        } else {
958            yDiff = 0;
959        }
960    
961        return hypot(xDiff, yDiff);
962    }
963    
964    /*
965     *--------------------------------------------------------------
966     *
967     * OvalToPoint --
968     *
969     *      Computes the distance from a given point to a given
970     *      oval, in canvas units.
971     *
972     * Results:
973     *      The return value is 0 if the point whose x and y coordinates
974     *      are coordPtr[0] and coordPtr[1] is inside the oval.  If the
975     *      point isn't inside the oval then the return value is the
976     *      distance from the point to the oval.  If itemPtr is filled,
977     *      then anywhere in the interior is considered "inside"; if
978     *      itemPtr isn't filled, then "inside" means only the area
979     *      occupied by the outline.
980     *
981     * Side effects:
982     *      None.
983     *
984     *--------------------------------------------------------------
985     */
986    
987            /* ARGSUSED */
988    static double
989    OvalToPoint(canvas, itemPtr, pointPtr)
990        Tk_Canvas canvas;           /* Canvas containing item. */
991        Tk_Item *itemPtr;           /* Item to check against point. */
992        double *pointPtr;           /* Pointer to x and y coordinates. */
993    {
994        RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
995        double width;
996        int filled;
997        Tk_State state = itemPtr->state;
998    
999        if(state == TK_STATE_NULL) {
1000            state = ((TkCanvas *)canvas)->canvas_state;
1001        }
1002    
1003        width = (double) ovalPtr->outline.width;
1004        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1005            if (ovalPtr->outline.activeWidth>width) {
1006                width = (double) ovalPtr->outline.activeWidth;
1007            }
1008        } else if (state==TK_STATE_DISABLED) {
1009            if (ovalPtr->outline.disabledWidth>0) {
1010                width = (double) ovalPtr->outline.disabledWidth;
1011            }
1012        }
1013    
1014    
1015        filled = ovalPtr->fillGC != None;
1016        if (ovalPtr->outline.gc == None) {
1017            width = 0.0;
1018            filled = 1;
1019        }
1020        return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
1021    }
1022    
1023    /*
1024     *--------------------------------------------------------------
1025     *
1026     * RectToArea --
1027     *
1028     *      This procedure is called to determine whether an item
1029     *      lies entirely inside, entirely outside, or overlapping
1030     *      a given rectangle.
1031     *
1032     * Results:
1033     *      -1 is returned if the item is entirely outside the area
1034     *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1035     *      inside the given area.
1036     *
1037     * Side effects:
1038     *      None.
1039     *
1040     *--------------------------------------------------------------
1041     */
1042    
1043            /* ARGSUSED */
1044    static int
1045    RectToArea(canvas, itemPtr, areaPtr)
1046        Tk_Canvas canvas;           /* Canvas containing item. */
1047        Tk_Item *itemPtr;           /* Item to check against rectangle. */
1048        double *areaPtr;            /* Pointer to array of four coordinates
1049                                     * (x1, y1, x2, y2) describing rectangular
1050                                     * area.  */
1051    {
1052        RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
1053        double halfWidth;
1054        double width;
1055        Tk_State state = itemPtr->state;
1056    
1057        if(state == TK_STATE_NULL) {
1058            state = ((TkCanvas *)canvas)->canvas_state;
1059        }
1060    
1061        width = rectPtr->outline.width;
1062        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1063            if (rectPtr->outline.activeWidth>width) {
1064                width = rectPtr->outline.activeWidth;
1065            }
1066        } else if (state==TK_STATE_DISABLED) {
1067            if (rectPtr->outline.disabledWidth>0) {
1068                width = rectPtr->outline.disabledWidth;
1069            }
1070        }
1071    
1072        halfWidth = width/2.0;
1073        if (rectPtr->outline.gc == None) {
1074            halfWidth = 0.0;
1075        }
1076    
1077        if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
1078                || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
1079                || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
1080                || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
1081            return -1;
1082        }
1083        if ((rectPtr->fillGC == None) && (rectPtr->outline.gc != None)
1084                && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
1085                && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
1086                && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
1087                && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
1088            return -1;
1089        }
1090        if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
1091                && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
1092                && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
1093                && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
1094            return 1;
1095        }
1096        return 0;
1097    }
1098    
1099    /*
1100     *--------------------------------------------------------------
1101     *
1102     * OvalToArea --
1103     *
1104     *      This procedure is called to determine whether an item
1105     *      lies entirely inside, entirely outside, or overlapping
1106     *      a given rectangular area.
1107     *
1108     * Results:
1109     *      -1 is returned if the item is entirely outside the area
1110     *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1111     *      inside the given area.
1112     *
1113     * Side effects:
1114     *      None.
1115     *
1116     *--------------------------------------------------------------
1117     */
1118    
1119            /* ARGSUSED */
1120    static int
1121    OvalToArea(canvas, itemPtr, areaPtr)
1122        Tk_Canvas canvas;           /* Canvas containing item. */
1123        Tk_Item *itemPtr;           /* Item to check against oval. */
1124        double *areaPtr;            /* Pointer to array of four coordinates
1125                                     * (x1, y1, x2, y2) describing rectangular
1126                                     * area.  */
1127    {
1128        RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
1129        double oval[4], halfWidth;
1130        int result;
1131        double width;
1132        Tk_State state = itemPtr->state;
1133    
1134        if(state == TK_STATE_NULL) {
1135            state = ((TkCanvas *)canvas)->canvas_state;
1136        }
1137    
1138        width = ovalPtr->outline.width;
1139        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1140            if (ovalPtr->outline.activeWidth>width) {
1141                width = ovalPtr->outline.activeWidth;
1142            }
1143        } else if (state==TK_STATE_DISABLED) {
1144            if (ovalPtr->outline.disabledWidth>0) {
1145                width = ovalPtr->outline.disabledWidth;
1146            }
1147        }
1148    
1149        /*
1150         * Expand the oval to include the width of the outline, if any.
1151         */
1152    
1153        halfWidth = width/2.0;
1154        if (ovalPtr->outline.gc == None) {
1155            halfWidth = 0.0;
1156        }
1157        oval[0] = ovalPtr->bbox[0] - halfWidth;
1158        oval[1] = ovalPtr->bbox[1] - halfWidth;
1159        oval[2] = ovalPtr->bbox[2] + halfWidth;
1160        oval[3] = ovalPtr->bbox[3] + halfWidth;
1161    
1162        result = TkOvalToArea(oval, areaPtr);
1163    
1164        /*
1165         * If the rectangle appears to overlap the oval and the oval
1166         * isn't filled, do one more check to see if perhaps all four
1167         * of the rectangle's corners are totally inside the oval's
1168         * unfilled center, in which case we should return "outside".
1169         */
1170    
1171        if ((result == 0) && (ovalPtr->outline.gc != None)
1172                && (ovalPtr->fillGC == None)) {
1173            double centerX, centerY, height;
1174            double xDelta1, yDelta1, xDelta2, yDelta2;
1175    
1176            centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
1177            centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
1178            width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
1179            height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
1180            xDelta1 = (areaPtr[0] - centerX)/width;
1181            xDelta1 *= xDelta1;
1182            yDelta1 = (areaPtr[1] - centerY)/height;
1183            yDelta1 *= yDelta1;
1184            xDelta2 = (areaPtr[2] - centerX)/width;
1185            xDelta2 *= xDelta2;
1186            yDelta2 = (areaPtr[3] - centerY)/height;
1187            yDelta2 *= yDelta2;
1188            if (((xDelta1 + yDelta1) < 1.0)
1189                    && ((xDelta1 + yDelta2) < 1.0)
1190                    && ((xDelta2 + yDelta1) < 1.0)
1191                    && ((xDelta2 + yDelta2) < 1.0)) {
1192                return -1;
1193            }
1194        }
1195        return result;
1196    }
1197    
1198    /*
1199     *--------------------------------------------------------------
1200     *
1201     * ScaleRectOval --
1202     *
1203     *      This procedure is invoked to rescale a rectangle or oval
1204     *      item.
1205     *
1206     * Results:
1207     *      None.
1208     *
1209     * Side effects:
1210     *      The rectangle or oval referred to by itemPtr is rescaled
1211     *      so that the following transformation is applied to all
1212     *      point coordinates:
1213     *              x' = originX + scaleX*(x-originX)
1214     *              y' = originY + scaleY*(y-originY)
1215     *
1216     *--------------------------------------------------------------
1217     */
1218    
1219    static void
1220    ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY)
1221        Tk_Canvas canvas;                   /* Canvas containing rectangle. */
1222        Tk_Item *itemPtr;                   /* Rectangle to be scaled. */
1223        double originX, originY;            /* Origin about which to scale rect. */
1224        double scaleX;                      /* Amount to scale in X direction. */
1225        double scaleY;                      /* Amount to scale in Y direction. */
1226    {
1227        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1228    
1229        rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
1230        rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
1231        rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
1232        rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
1233        ComputeRectOvalBbox(canvas, rectOvalPtr);
1234    }
1235    
1236    /*
1237     *--------------------------------------------------------------
1238     *
1239     * TranslateRectOval --
1240     *
1241     *      This procedure is called to move a rectangle or oval by a
1242     *      given amount.
1243     *
1244     * Results:
1245     *      None.
1246     *
1247     * Side effects:
1248     *      The position of the rectangle or oval is offset by
1249     *      (xDelta, yDelta), and the bounding box is updated in the
1250     *      generic part of the item structure.
1251     *
1252     *--------------------------------------------------------------
1253     */
1254    
1255    static void
1256    TranslateRectOval(canvas, itemPtr, deltaX, deltaY)
1257        Tk_Canvas canvas;                   /* Canvas containing item. */
1258        Tk_Item *itemPtr;                   /* Item that is being moved. */
1259        double deltaX, deltaY;              /* Amount by which item is to be
1260                                             * moved. */
1261    {
1262        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1263    
1264        rectOvalPtr->bbox[0] += deltaX;
1265        rectOvalPtr->bbox[1] += deltaY;
1266        rectOvalPtr->bbox[2] += deltaX;
1267        rectOvalPtr->bbox[3] += deltaY;
1268        ComputeRectOvalBbox(canvas, rectOvalPtr);
1269    }
1270    
1271    /*
1272     *--------------------------------------------------------------
1273     *
1274     * RectOvalToPostscript --
1275     *
1276     *      This procedure is called to generate Postscript for
1277     *      rectangle and oval items.
1278     *
1279     * Results:
1280     *      The return value is a standard Tcl result.  If an error
1281     *      occurs in generating Postscript then an error message is
1282     *      left in the interp's result, replacing whatever used to be there.
1283     *      If no error occurs, then Postscript for the rectangle is
1284     *      appended to the result.
1285     *
1286     * Side effects:
1287     *      None.
1288     *
1289     *--------------------------------------------------------------
1290     */
1291    
1292    static int
1293    RectOvalToPostscript(interp, canvas, itemPtr, prepass)
1294        Tcl_Interp *interp;                 /* Interpreter for error reporting. */
1295        Tk_Canvas canvas;                   /* Information about overall canvas. */
1296        Tk_Item *itemPtr;                   /* Item for which Postscript is
1297                                             * wanted. */
1298        int prepass;                        /* 1 means this is a prepass to
1299                                             * collect font information;  0 means
1300                                             * final Postscript is being created. */
1301    {
1302        char pathCmd[500];
1303        RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1304        double y1, y2;
1305        XColor *color;
1306        XColor *fillColor;
1307        Pixmap fillStipple;
1308        Tk_State state = itemPtr->state;
1309    
1310        y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
1311        y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);
1312    
1313        /*
1314         * Generate a string that creates a path for the rectangle or oval.
1315         * This is the only part of the procedure's code that is type-
1316         * specific.
1317         */
1318    
1319    
1320        if (rectOvalPtr->header.typePtr == &tkRectangleType) {
1321            sprintf(pathCmd, "%.15g %.15g moveto %.15g 0 rlineto 0 %.15g rlineto %.15g 0 rlineto closepath\n",
1322                    rectOvalPtr->bbox[0], y1,
1323                    rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0], y2-y1,
1324                    rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);
1325        } else {
1326            sprintf(pathCmd, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
1327                    (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,
1328                    (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);
1329        }
1330    
1331        if(state == TK_STATE_NULL) {
1332            state = ((TkCanvas *)canvas)->canvas_state;
1333        }
1334        color = rectOvalPtr->outline.color;
1335        fillColor = rectOvalPtr->fillColor;
1336        fillStipple = rectOvalPtr->fillStipple;
1337        if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1338            if (rectOvalPtr->outline.activeColor!=NULL) {
1339                color = rectOvalPtr->outline.activeColor;
1340            }
1341            if (rectOvalPtr->activeFillColor!=NULL) {
1342                fillColor = rectOvalPtr->activeFillColor;
1343            }
1344            if (rectOvalPtr->activeFillStipple!=None) {
1345                fillStipple = rectOvalPtr->activeFillStipple;
1346            }
1347        } else if (state==TK_STATE_DISABLED) {
1348            if (rectOvalPtr->outline.disabledColor!=NULL) {
1349                color = rectOvalPtr->outline.disabledColor;
1350            }
1351            if (rectOvalPtr->disabledFillColor!=NULL) {
1352                fillColor = rectOvalPtr->disabledFillColor;
1353            }
1354            if (rectOvalPtr->disabledFillStipple!=None) {
1355                fillStipple = rectOvalPtr->disabledFillStipple;
1356            }
1357        }
1358    
1359        /*
1360         * First draw the filled area of the rectangle.
1361         */
1362    
1363        if (fillColor != NULL) {
1364            Tcl_AppendResult(interp, pathCmd, (char *) NULL);
1365            if (Tk_CanvasPsColor(interp, canvas, fillColor)
1366                    != TCL_OK) {
1367                return TCL_ERROR;
1368            }
1369            if (fillStipple != None) {
1370                Tcl_AppendResult(interp, "clip ", (char *) NULL);
1371                if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
1372                        != TCL_OK) {
1373                    return TCL_ERROR;
1374                }
1375                if (color != NULL) {
1376                    Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1377                }
1378            } else {
1379                Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1380            }
1381        }
1382    
1383        /*
1384         * Now draw the outline, if there is one.
1385         */
1386    
1387        if (color != NULL) {
1388            Tcl_AppendResult(interp, pathCmd, "0 setlinejoin 2 setlinecap\n",
1389                    (char *) NULL);
1390            if (Tk_CanvasPsOutline(canvas, itemPtr,
1391                    &(rectOvalPtr->outline))!= TCL_OK) {
1392                return TCL_ERROR;
1393            }
1394        }
1395        return TCL_OK;
1396    }
1397    
1398    /* End of tkrectoval.c */

Legend:
Removed from v.42  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25