Annotation of micropolis/src/tk/tkrectov.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tkRectOval.c --
                      3:  *
                      4:  *     This file implements rectangle and oval items for canvas
                      5:  *     widgets.
                      6:  *
                      7:  * Copyright 1991-1992 Regents of the University of California.
                      8:  * Permission to use, copy, modify, and distribute this
                      9:  * software and its documentation for any purpose and without
                     10:  * fee is hereby granted, provided that the above copyright
                     11:  * notice appear in all copies.  The University of California
                     12:  * makes no representations about the suitability of this
                     13:  * software for any purpose.  It is provided "as is" without
                     14:  * express or implied warranty.
                     15:  */
                     16: 
                     17: #ifndef lint
                     18: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkRectOval.c,v 1.15 92/08/24 09:23:58 ouster Exp $ SPRITE (Berkeley)";
                     19: #endif
                     20: 
                     21: #include <stdio.h>
                     22: #include <math.h>
                     23: #include "tkconfig.h"
                     24: #include "tkint.h"
                     25: #include "tkcanvas.h"
                     26: 
                     27: /*
                     28:  * The structure below defines the record for each rectangle/oval item.
                     29:  */
                     30: 
                     31: typedef struct RectOvalItem  {
                     32:     Tk_Item header;            /* Generic stuff that's the same for all
                     33:                                 * types.  MUST BE FIRST IN STRUCTURE. */
                     34:     double bbox[4];            /* Coordinates of bounding box for rectangle
                     35:                                 * or oval (x1, y1, x2, y2).  Item includes
                     36:                                 * x1 and x2 but not y1 and y2. */
                     37:     int width;                 /* Width of outline. */
                     38:     XColor *outlineColor;      /* Color for outline. */
                     39:     XColor *fillColor;         /* Color for filling rectangle/oval. */
                     40:     Pixmap fillStipple;                /* Stipple bitmap for filling item. */
                     41:     GC outlineGC;              /* Graphics context for outline. */
                     42:     GC fillGC;                 /* Graphics context for filling item. */
                     43: } RectOvalItem;
                     44: 
                     45: /*
                     46:  * Information used for parsing configuration specs:
                     47:  */
                     48: 
                     49: static Tk_ConfigSpec configSpecs[] = {
                     50:     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
                     51:        (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
                     52:     {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
                     53:        "black", Tk_Offset(RectOvalItem, outlineColor), TK_CONFIG_NULL_OK},
                     54:     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
                     55:        (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
                     56:     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
                     57:        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tkCanvasTagsOption},
                     58:     {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
                     59:        "1", Tk_Offset(RectOvalItem, width), TK_CONFIG_DONT_SET_DEFAULT},
                     60:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
                     61:        (char *) NULL, 0, 0}
                     62: };
                     63: 
                     64: /*
                     65:  * Prototypes for procedures defined in this file:
                     66:  */
                     67: 
                     68: static void            ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     69:                            RectOvalItem *rectOvalPtr));
                     70: static int             ConfigureRectOval _ANSI_ARGS_((
                     71:                            Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int argc,
                     72:                            char **argv, int flags));
                     73: static int             CreateRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     74:                            struct Tk_Item *itemPtr, int argc, char **argv));
                     75: static void            DeleteRectOval _ANSI_ARGS_((Tk_Item *itemPtr));
                     76: static void            DisplayRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     77:                            Tk_Item *itemPtr, Drawable dst));
                     78: static int             OvalToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     79:                            Tk_Item *itemPtr, double *areaPtr));
                     80: static double          OvalToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     81:                            Tk_Item *itemPtr, double *pointPtr));
                     82: static int             RectOvalCoords _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     83:                            Tk_Item *itemPtr, int argc, char **argv));
                     84: static int             RectToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     85:                            Tk_Item *itemPtr, double *areaPtr));
                     86: static double          RectToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     87:                            Tk_Item *itemPtr, double *pointPtr));
                     88: static void            ScaleRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     89:                            Tk_Item *itemPtr, double originX, double originY,
                     90:                            double scaleX, double scaleY));
                     91: static void            TranslateRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
                     92:                            Tk_Item *itemPtr, double deltaX, double deltaY));
                     93: 
                     94: /*
                     95:  * The structures below defines the rectangle and oval item types
                     96:  * by means of procedures that can be invoked by generic item code.
                     97:  */
                     98: 
                     99: Tk_ItemType TkRectangleType = {
                    100:     "rectangle",                       /* name */
                    101:     sizeof(RectOvalItem),              /* itemSize */
                    102:     CreateRectOval,                    /* createProc */
                    103:     configSpecs,                       /* configSpecs */
                    104:     ConfigureRectOval,                 /* configureProc */
                    105:     RectOvalCoords,                    /* coordProc */
                    106:     DeleteRectOval,                    /* deleteProc */
                    107:     DisplayRectOval,                   /* displayProc */
                    108:     0,                                 /* alwaysRedraw */
                    109:     RectToPoint,                       /* pointProc */
                    110:     RectToArea,                                /* areaProc */
                    111:     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
                    112:     ScaleRectOval,                     /* scaleProc */
                    113:     TranslateRectOval,                 /* translateProc */
                    114:     (Tk_ItemIndexProc *) NULL,         /* indexProc */
                    115:     (Tk_ItemCursorProc *) NULL,                /* cursorProc */
                    116:     (Tk_ItemSelectionProc *) NULL,     /* selectionProc */
                    117:     (Tk_ItemInsertProc *) NULL,                /* insertProc */
                    118:     (Tk_ItemDCharsProc *) NULL,                /* dTextProc */
                    119:     (Tk_ItemType *) NULL               /* nextPtr */
                    120: };
                    121: 
                    122: Tk_ItemType TkOvalType = {
                    123:     "oval",                            /* name */
                    124:     sizeof(RectOvalItem),              /* itemSize */
                    125:     CreateRectOval,                    /* createProc */
                    126:     configSpecs,                       /* configSpecs */
                    127:     ConfigureRectOval,                 /* configureProc */
                    128:     RectOvalCoords,                    /* coordProc */
                    129:     DeleteRectOval,                    /* deleteProc */
                    130:     DisplayRectOval,                   /* displayProc */
                    131:     0,                                 /* alwaysRedraw */
                    132:     OvalToPoint,                       /* pointProc */
                    133:     OvalToArea,                                /* areaProc */
                    134:     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
                    135:     ScaleRectOval,                     /* scaleProc */
                    136:     TranslateRectOval,                 /* translateProc */
                    137:     (Tk_ItemIndexProc *) NULL,         /* indexProc */
                    138:     (Tk_ItemCursorProc *) NULL,                /* cursorProc */
                    139:     (Tk_ItemSelectionProc *) NULL,     /* selectionProc */
                    140:     (Tk_ItemInsertProc *) NULL,                /* insertProc */
                    141:     (Tk_ItemDCharsProc *) NULL,                /* dTextProc */
                    142:     (Tk_ItemType *) NULL               /* nextPtr */
                    143: };
                    144: 
                    145: /*
                    146:  *--------------------------------------------------------------
                    147:  *
                    148:  * CreateRectOval --
                    149:  *
                    150:  *     This procedure is invoked to create a new rectangle
                    151:  *     or oval item in a canvas.
                    152:  *
                    153:  * Results:
                    154:  *     A standard Tcl return value.  If an error occurred in
                    155:  *     creating the item, then an error message is left in
                    156:  *     canvasPtr->interp->result;  in this case itemPtr is
                    157:  *     left uninitialized, so it can be safely freed by the
                    158:  *     caller.
                    159:  *
                    160:  * Side effects:
                    161:  *     A new rectangle or oval item is created.
                    162:  *
                    163:  *--------------------------------------------------------------
                    164:  */
                    165: 
                    166: static int
                    167: CreateRectOval(canvasPtr, itemPtr, argc, argv)
                    168:     register Tk_Canvas *canvasPtr;     /* Canvas to hold new item. */
                    169:     Tk_Item *itemPtr;                  /* Record to hold new item;  header
                    170:                                         * has been initialized by caller. */
                    171:     int argc;                          /* Number of arguments in argv. */
                    172:     char **argv;                       /* Arguments describing rectangle. */
                    173: {
                    174:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    175: 
                    176:     if (argc < 4) {
                    177:        Tcl_AppendResult(canvasPtr->interp, "wrong # args:  should be \"",
                    178:                Tk_PathName(canvasPtr->tkwin), "\" create ",
                    179:                itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?",
                    180:                (char *) NULL);
                    181:        return TCL_ERROR;
                    182:     }
                    183: 
                    184:     /*
                    185:      * Carry out initialization that is needed in order to clean
                    186:      * up after errors during the the remainder of this procedure.
                    187:      */
                    188: 
                    189:     rectOvalPtr->width = 1;
                    190:     rectOvalPtr->outlineColor = NULL;
                    191:     rectOvalPtr->fillColor = NULL;
                    192:     rectOvalPtr->fillStipple = None;
                    193:     rectOvalPtr->outlineGC = None;
                    194:     rectOvalPtr->fillGC = None;
                    195: 
                    196:     /*
                    197:      * Process the arguments to fill in the item record.
                    198:      */
                    199: 
                    200:     if ((TkGetCanvasCoord(canvasPtr, argv[0], &rectOvalPtr->bbox[0]) != TCL_OK)
                    201:            || (TkGetCanvasCoord(canvasPtr, argv[1],
                    202:                &rectOvalPtr->bbox[1]) != TCL_OK)
                    203:            || (TkGetCanvasCoord(canvasPtr, argv[2],
                    204:                    &rectOvalPtr->bbox[2]) != TCL_OK)
                    205:            || (TkGetCanvasCoord(canvasPtr, argv[3],
                    206:                    &rectOvalPtr->bbox[3]) != TCL_OK)) {
                    207:        return TCL_ERROR;
                    208:     }
                    209: 
                    210:     if (ConfigureRectOval(canvasPtr, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
                    211:        DeleteRectOval(itemPtr);
                    212:        return TCL_ERROR;
                    213:     }
                    214:     return TCL_OK;
                    215: }
                    216: 
                    217: /*
                    218:  *--------------------------------------------------------------
                    219:  *
                    220:  * RectOvalCoords --
                    221:  *
                    222:  *     This procedure is invoked to process the "coords" widget
                    223:  *     command on rectangles and ovals.  See the user documentation
                    224:  *     for details on what it does.
                    225:  *
                    226:  * Results:
                    227:  *     Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
                    228:  *
                    229:  * Side effects:
                    230:  *     The coordinates for the given item may be changed.
                    231:  *
                    232:  *--------------------------------------------------------------
                    233:  */
                    234: 
                    235: static int
                    236: RectOvalCoords(canvasPtr, itemPtr, argc, argv)
                    237:     register Tk_Canvas *canvasPtr;     /* Canvas containing item. */
                    238:     Tk_Item *itemPtr;                  /* Item whose coordinates are to be
                    239:                                         * read or modified. */
                    240:     int argc;                          /* Number of coordinates supplied in
                    241:                                         * argv. */
                    242:     char **argv;                       /* Array of coordinates: x1, y1,
                    243:                                         * x2, y2, ... */
                    244: {
                    245:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    246:     char buffer[500];
                    247: 
                    248:     if (argc == 0) {
                    249:        sprintf(buffer, "%g %g %g %g", rectOvalPtr->bbox[0],
                    250:                rectOvalPtr->bbox[1], rectOvalPtr->bbox[2],
                    251:                rectOvalPtr->bbox[3]);
                    252:        Tcl_SetResult(canvasPtr->interp, buffer, TCL_VOLATILE);
                    253:     } else if (argc == 4) {
                    254:        if ((TkGetCanvasCoord(canvasPtr, argv[0],
                    255:                    &rectOvalPtr->bbox[0]) != TCL_OK)
                    256:                || (TkGetCanvasCoord(canvasPtr, argv[1],
                    257:                    &rectOvalPtr->bbox[1]) != TCL_OK)
                    258:                || (TkGetCanvasCoord(canvasPtr, argv[2],
                    259:                        &rectOvalPtr->bbox[2]) != TCL_OK)
                    260:                || (TkGetCanvasCoord(canvasPtr, argv[3],
                    261:                        &rectOvalPtr->bbox[3]) != TCL_OK)) {
                    262:            return TCL_ERROR;
                    263:        }
                    264:        ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
                    265:     } else {
                    266:        sprintf(canvasPtr->interp->result,
                    267:                "wrong # coordinates:  expected 0 or 4, got %d",
                    268:                argc);
                    269:        return TCL_ERROR;
                    270:     }
                    271:     return TCL_OK;
                    272: }
                    273: 
                    274: /*
                    275:  *--------------------------------------------------------------
                    276:  *
                    277:  * ConfigureRectOval --
                    278:  *
                    279:  *     This procedure is invoked to configure various aspects
                    280:  *     of a rectangle or oval item, such as its border and
                    281:  *     background colors.
                    282:  *
                    283:  * Results:
                    284:  *     A standard Tcl result code.  If an error occurs, then
                    285:  *     an error message is left in canvasPtr->interp->result.
                    286:  *
                    287:  * Side effects:
                    288:  *     Configuration information, such as colors and stipple
                    289:  *     patterns, may be set for itemPtr.
                    290:  *
                    291:  *--------------------------------------------------------------
                    292:  */
                    293: 
                    294: static int
                    295: ConfigureRectOval(canvasPtr, itemPtr, argc, argv, flags)
                    296:     Tk_Canvas *canvasPtr;      /* Canvas containing itemPtr. */
                    297:     Tk_Item *itemPtr;          /* Rectangle item to reconfigure. */
                    298:     int argc;                  /* Number of elements in argv.  */
                    299:     char **argv;               /* Arguments describing things to configure. */
                    300:     int flags;                 /* Flags to pass to Tk_ConfigureWidget. */
                    301: {
                    302:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    303:     XGCValues gcValues;
                    304:     GC newGC;
                    305:     unsigned long mask;
                    306: 
                    307:     if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
                    308:            configSpecs, argc, argv, (char *) rectOvalPtr, flags) != TCL_OK) {
                    309:        return TCL_ERROR;
                    310:     }
                    311: 
                    312:     /*
                    313:      * A few of the options require additional processing, such as
                    314:      * graphics contexts.
                    315:      */
                    316: 
                    317:     if (rectOvalPtr->outlineColor == NULL) {
                    318:        newGC = None;
                    319:     } else {
                    320:        gcValues.foreground = rectOvalPtr->outlineColor->pixel;
                    321:        gcValues.cap_style = CapProjecting;
                    322:        if (rectOvalPtr->width < 0) {
                    323:            rectOvalPtr->width = 1;
                    324:        }
                    325:        gcValues.line_width = rectOvalPtr->width;
                    326:        mask = GCForeground|GCCapStyle|GCLineWidth;
                    327:        newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
                    328:     }
                    329:     if (rectOvalPtr->outlineGC != None) {
                    330:        Tk_FreeGC(rectOvalPtr->outlineGC);
                    331:     }
                    332:     rectOvalPtr->outlineGC = newGC;
                    333: 
                    334:     if (rectOvalPtr->fillColor == NULL) {
                    335:        newGC = None;
                    336:     } else {
                    337:        gcValues.foreground = rectOvalPtr->fillColor->pixel;
                    338:        if (rectOvalPtr->fillStipple != None) {
                    339:            gcValues.stipple = rectOvalPtr->fillStipple;
                    340:            gcValues.fill_style = FillStippled;
                    341:            mask = GCForeground|GCStipple|GCFillStyle;
                    342:        } else {
                    343:            mask = GCForeground;
                    344:        }
                    345:        newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
                    346:     }
                    347:     if (rectOvalPtr->fillGC != None) {
                    348:        Tk_FreeGC(rectOvalPtr->fillGC);
                    349:     }
                    350:     rectOvalPtr->fillGC = newGC;
                    351:     ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
                    352: 
                    353:     return TCL_OK;
                    354: }
                    355: 
                    356: /*
                    357:  *--------------------------------------------------------------
                    358:  *
                    359:  * DeleteRectOval --
                    360:  *
                    361:  *     This procedure is called to clean up the data structure
                    362:  *     associated with a rectangle or oval item.
                    363:  *
                    364:  * Results:
                    365:  *     None.
                    366:  *
                    367:  * Side effects:
                    368:  *     Resources associated with itemPtr are released.
                    369:  *
                    370:  *--------------------------------------------------------------
                    371:  */
                    372: 
                    373: static void
                    374: DeleteRectOval(itemPtr)
                    375:     Tk_Item *itemPtr;                  /* Item that is being deleted. */
                    376: {
                    377:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    378: 
                    379:     if (rectOvalPtr->outlineColor != NULL) {
                    380:        Tk_FreeColor(rectOvalPtr->outlineColor);
                    381:     }
                    382:     if (rectOvalPtr->fillColor != NULL) {
                    383:        Tk_FreeColor(rectOvalPtr->fillColor);
                    384:     }
                    385:     if (rectOvalPtr->fillStipple != None) {
                    386:        Tk_FreeBitmap(rectOvalPtr->fillStipple);
                    387:     }
                    388:     if (rectOvalPtr->outlineGC != None) {
                    389:        Tk_FreeGC(rectOvalPtr->outlineGC);
                    390:     }
                    391:     if (rectOvalPtr->fillGC != None) {
                    392:        Tk_FreeGC(rectOvalPtr->fillGC);
                    393:     }
                    394: }
                    395: 
                    396: /*
                    397:  *--------------------------------------------------------------
                    398:  *
                    399:  * ComputeRectOvalBbox --
                    400:  *
                    401:  *     This procedure is invoked to compute the bounding box of
                    402:  *     all the pixels that may be drawn as part of a rectangle
                    403:  *     or oval.
                    404:  *
                    405:  * Results:
                    406:  *     None.
                    407:  *
                    408:  * Side effects:
                    409:  *     The fields x1, y1, x2, and y2 are updated in the header
                    410:  *     for itemPtr.
                    411:  *
                    412:  *--------------------------------------------------------------
                    413:  */
                    414: 
                    415:        /* ARGSUSED */
                    416: static void
                    417: ComputeRectOvalBbox(canvasPtr, rectOvalPtr)
                    418:     Tk_Canvas *canvasPtr;              /* Canvas that contains item. */
                    419:     register RectOvalItem *rectOvalPtr;        /* Item whose bbox is to be
                    420:                                         * recomputed. */
                    421: {
                    422:     int bloat;
                    423: 
                    424:     /*
                    425:      * Make sure that the first coordinates are the lowest ones.
                    426:      */
                    427: 
                    428:     if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
                    429:        double tmp;
                    430:        tmp = rectOvalPtr->bbox[3];
                    431:        rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
                    432:        rectOvalPtr->bbox[1] = tmp;
                    433:     }
                    434:     if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
                    435:        double tmp;
                    436:        tmp = rectOvalPtr->bbox[2];
                    437:        rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
                    438:        rectOvalPtr->bbox[0] = tmp;
                    439:     }
                    440: 
                    441:     bloat = (rectOvalPtr->width+1)/2 + 1;
                    442:     rectOvalPtr->header.x1 = rectOvalPtr->bbox[0] - bloat;
                    443:     rectOvalPtr->header.y1 = rectOvalPtr->bbox[1] - bloat;
                    444:     rectOvalPtr->header.x2 = rectOvalPtr->bbox[2] + bloat;
                    445:     rectOvalPtr->header.y2 = rectOvalPtr->bbox[3] + bloat;
                    446: }
                    447: 
                    448: /*
                    449:  *--------------------------------------------------------------
                    450:  *
                    451:  * DisplayRectOval --
                    452:  *
                    453:  *     This procedure is invoked to draw a rectangle or oval
                    454:  *     item in a given drawable.
                    455:  *
                    456:  * Results:
                    457:  *     None.
                    458:  *
                    459:  * Side effects:
                    460:  *     ItemPtr is drawn in drawable using the transformation
                    461:  *     information in canvasPtr.
                    462:  *
                    463:  *--------------------------------------------------------------
                    464:  */
                    465: 
                    466: static void
                    467: DisplayRectOval(canvasPtr, itemPtr, drawable)
                    468:     register Tk_Canvas *canvasPtr;     /* Canvas that contains item. */
                    469:     Tk_Item *itemPtr;                  /* Item to be displayed. */
                    470:     Drawable drawable;                 /* Pixmap or window in which to draw
                    471:                                         * item. */
                    472: {
                    473:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    474:     Display *display = Tk_Display(canvasPtr->tkwin);
                    475:     int x1, y1, x2, y2;
                    476: 
                    477:     /*
                    478:      * Compute the screen coordinates of the bounding box for the item.
                    479:      * Make sure that the bbox is at least one pixel large, since some
                    480:      * X servers will die if it isn't.
                    481:      */
                    482: 
                    483:     x1 = SCREEN_X(canvasPtr, rectOvalPtr->bbox[0]);
                    484:     y1 = SCREEN_Y(canvasPtr, rectOvalPtr->bbox[1]);
                    485:     x2 = SCREEN_X(canvasPtr, rectOvalPtr->bbox[2]);
                    486:     y2 = SCREEN_Y(canvasPtr, rectOvalPtr->bbox[3]);
                    487:     if (x2 <= x1) {
                    488:        x2 = x1+1;
                    489:     }
                    490:     if (y2 <= y1) {
                    491:        y2 = y1+1;
                    492:     }
                    493: 
                    494:     /*
                    495:      * Display filled box first (if wanted), then outline.
                    496:      */
                    497: 
                    498:     if (rectOvalPtr->fillGC != None) {
                    499:        if (rectOvalPtr->header.typePtr == &TkRectangleType) {
                    500:            XFillRectangle(display, drawable, rectOvalPtr->fillGC,
                    501:                    x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
                    502:        } else {
                    503:            XFillArc(display, drawable, rectOvalPtr->fillGC,
                    504:                    x1, y1, (x2-x1), (y2-y1), 0, 360*64);
                    505:        }
                    506:     }
                    507:     if (rectOvalPtr->outlineGC != None) {
                    508:        if (rectOvalPtr->header.typePtr == &TkRectangleType) {
                    509:            XDrawRectangle(display, drawable, rectOvalPtr->outlineGC,
                    510:                    x1, y1, (x2-x1-1), (y2-y1-1));
                    511:        } else {
                    512:            XDrawArc(display, drawable, rectOvalPtr->outlineGC,
                    513:                    x1, y1, (x2-x1-1), (y2-y1-1), 0, 360*64);
                    514:        }
                    515:     }
                    516: }
                    517: 
                    518: /*
                    519:  *--------------------------------------------------------------
                    520:  *
                    521:  * RectToPoint --
                    522:  *
                    523:  *     Computes the distance from a given point to a given
                    524:  *     rectangle, in canvas units.
                    525:  *
                    526:  * Results:
                    527:  *     The return value is 0 if the point whose x and y coordinates
                    528:  *     are coordPtr[0] and coordPtr[1] is inside the rectangle.  If the
                    529:  *     point isn't inside the rectangle then the return value is the
                    530:  *     distance from the point to the rectangle.  If itemPtr is filled,
                    531:  *     then anywhere in the interior is considered "inside"; if
                    532:  *     itemPtr isn't filled, then "inside" means only the area
                    533:  *     occupied by the outline.
                    534:  *
                    535:  * Side effects:
                    536:  *     None.
                    537:  *
                    538:  *--------------------------------------------------------------
                    539:  */
                    540: 
                    541:        /* ARGSUSED */
                    542: static double
                    543: RectToPoint(canvasPtr, itemPtr, pointPtr)
                    544:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
                    545:     Tk_Item *itemPtr;          /* Item to check against point. */
                    546:     double *pointPtr;          /* Pointer to x and y coordinates. */
                    547: {
                    548:     register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
                    549:     double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
                    550: 
                    551:     /*
                    552:      * Generate a new larger rectangle that includes the border
                    553:      * width, if there is one.
                    554:      */
                    555: 
                    556:     x1 = rectPtr->bbox[0];
                    557:     y1 = rectPtr->bbox[1];
                    558:     x2 = rectPtr->bbox[2];
                    559:     y2 = rectPtr->bbox[3];
                    560:     if (rectPtr->outlineGC != None) {
                    561:        inc = rectPtr->width/2.0;
                    562:        x1 -= inc;
                    563:        y1 -= inc;
                    564:        x2 += inc;
                    565:        y2 += inc;
                    566:     }
                    567: 
                    568:     /*
                    569:      * If the point is inside the rectangle, handle specially:
                    570:      * distance is 0 if rectangle is filled, otherwise compute
                    571:      * distance to nearest edge of rectangle and subtract width
                    572:      * of edge.
                    573:      */
                    574: 
                    575:     if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
                    576:                && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
                    577:        if ((rectPtr->fillGC != None) || (rectPtr->outlineGC == None)) {
                    578:            return 0.0;
                    579:        }
                    580:        xDiff = pointPtr[0] - x1;
                    581:        tmp = x2 - pointPtr[0];
                    582:        if (tmp < xDiff) {
                    583:            xDiff = tmp;
                    584:        }
                    585:        yDiff = pointPtr[1] - y1;
                    586:        tmp = y2 - pointPtr[1];
                    587:        if (tmp < yDiff) {
                    588:            yDiff = tmp;
                    589:        }
                    590:        if (yDiff < xDiff) {
                    591:            xDiff = yDiff;
                    592:        }
                    593:        xDiff -= rectPtr->width;
                    594:        if (xDiff < 0.0) {
                    595:            return 0.0;
                    596:        }
                    597:        return xDiff;
                    598:     }
                    599: 
                    600:     /*
                    601:      * Point is outside rectangle.
                    602:      */
                    603: 
                    604:     if (pointPtr[0] < x1) {
                    605:        xDiff = x1 - pointPtr[0];
                    606:     } else if (pointPtr[0] > x2)  {
                    607:        xDiff = pointPtr[0] - x2;
                    608:     } else {
                    609:        xDiff = 0;
                    610:     }
                    611: 
                    612:     if (pointPtr[1] < y1) {
                    613:        yDiff = y1 - pointPtr[1];
                    614:     } else if (pointPtr[1] > y2)  {
                    615:        yDiff = pointPtr[1] - y2;
                    616:     } else {
                    617:        yDiff = 0;
                    618:     }
                    619: 
                    620:     return hypot(xDiff, yDiff);
                    621: }
                    622: 
                    623: /*
                    624:  *--------------------------------------------------------------
                    625:  *
                    626:  * OvalToPoint --
                    627:  *
                    628:  *     Computes the distance from a given point to a given
                    629:  *     oval, in canvas units.
                    630:  *
                    631:  * Results:
                    632:  *     The return value is 0 if the point whose x and y coordinates
                    633:  *     are coordPtr[0] and coordPtr[1] is inside the oval.  If the
                    634:  *     point isn't inside the oval then the return value is the
                    635:  *     distance from the point to the oval.  If itemPtr is filled,
                    636:  *     then anywhere in the interior is considered "inside"; if
                    637:  *     itemPtr isn't filled, then "inside" means only the area
                    638:  *     occupied by the outline.
                    639:  *
                    640:  * Side effects:
                    641:  *     None.
                    642:  *
                    643:  *--------------------------------------------------------------
                    644:  */
                    645: 
                    646:        /* ARGSUSED */
                    647: static double
                    648: OvalToPoint(canvasPtr, itemPtr, pointPtr)
                    649:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
                    650:     Tk_Item *itemPtr;          /* Item to check against point. */
                    651:     double *pointPtr;          /* Pointer to x and y coordinates. */
                    652: {
                    653:     register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
                    654:     double width;
                    655:     int filled;
                    656: 
                    657:     width = ovalPtr->width;
                    658:     filled = ovalPtr->fillGC != None;
                    659:     if (ovalPtr->outlineGC == None) {
                    660:        width = 0.0;
                    661:        filled = 1;
                    662:     }
                    663:     return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
                    664: }
                    665: 
                    666: /*
                    667:  *--------------------------------------------------------------
                    668:  *
                    669:  * RectToArea --
                    670:  *
                    671:  *     This procedure is called to determine whether an item
                    672:  *     lies entirely inside, entirely outside, or overlapping
                    673:  *     a given rectangle.
                    674:  *
                    675:  * Results:
                    676:  *     -1 is returned if the item is entirely outside the area
                    677:  *     given by rectPtr, 0 if it overlaps, and 1 if it is entirely
                    678:  *     inside the given area.
                    679:  *
                    680:  * Side effects:
                    681:  *     None.
                    682:  *
                    683:  *--------------------------------------------------------------
                    684:  */
                    685: 
                    686:        /* ARGSUSED */
                    687: static int
                    688: RectToArea(canvasPtr, itemPtr, areaPtr)
                    689:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
                    690:     Tk_Item *itemPtr;          /* Item to check against rectangle. */
                    691:     double *areaPtr;           /* Pointer to array of four coordinates
                    692:                                 * (x1, y1, x2, y2) describing rectangular
                    693:                                 * area.  */
                    694: {
                    695:     register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
                    696:     double halfWidth;
                    697: 
                    698:     halfWidth = rectPtr->width/2.0;
                    699:     if (rectPtr->outlineGC == None) {
                    700:        halfWidth = 0.0;
                    701:     }
                    702: 
                    703:     if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
                    704:            || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
                    705:            || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
                    706:            || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
                    707:        return -1;
                    708:     }
                    709:     if ((rectPtr->fillGC == None) && (rectPtr->outlineGC != None)
                    710:            && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
                    711:            && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
                    712:            && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
                    713:            && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
                    714:        return -1;
                    715:     }
                    716:     if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
                    717:            && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
                    718:            && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
                    719:            && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
                    720:        return 1;
                    721:     }
                    722:     return 0;
                    723: }
                    724: 
                    725: /*
                    726:  *--------------------------------------------------------------
                    727:  *
                    728:  * OvalToArea --
                    729:  *
                    730:  *     This procedure is called to determine whether an item
                    731:  *     lies entirely inside, entirely outside, or overlapping
                    732:  *     a given rectangular area.
                    733:  *
                    734:  * Results:
                    735:  *     -1 is returned if the item is entirely outside the area
                    736:  *     given by rectPtr, 0 if it overlaps, and 1 if it is entirely
                    737:  *     inside the given area.
                    738:  *
                    739:  * Side effects:
                    740:  *     None.
                    741:  *
                    742:  *--------------------------------------------------------------
                    743:  */
                    744: 
                    745:        /* ARGSUSED */
                    746: static int
                    747: OvalToArea(canvasPtr, itemPtr, areaPtr)
                    748:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
                    749:     Tk_Item *itemPtr;          /* Item to check against oval. */
                    750:     double *areaPtr;           /* Pointer to array of four coordinates
                    751:                                 * (x1, y1, x2, y2) describing rectangular
                    752:                                 * area.  */
                    753: {
                    754:     register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
                    755:     double oval[4], halfWidth;
                    756:     int result;
                    757: 
                    758:     /*
                    759:      * Expand the oval to include the width of the outline, if any.
                    760:      */
                    761: 
                    762:     halfWidth = ovalPtr->width/2.0;
                    763:     if (ovalPtr->outlineGC == None) {
                    764:        halfWidth = 0.0;
                    765:     }
                    766:     oval[0] = ovalPtr->bbox[0] - halfWidth;
                    767:     oval[1] = ovalPtr->bbox[1] - halfWidth;
                    768:     oval[2] = ovalPtr->bbox[2] + halfWidth;
                    769:     oval[3] = ovalPtr->bbox[3] + halfWidth;
                    770: 
                    771:     result = TkOvalToArea(oval, areaPtr);
                    772: 
                    773:     /*
                    774:      * If the rectangle appears to overlap the oval and the oval
                    775:      * isn't filled, do one more check to see if perhaps all four
                    776:      * of the rectangle's corners are totally inside the oval's
                    777:      * unfilled center, in which case we should return "outside".
                    778:      */
                    779: 
                    780:     if ((result == 0) && (ovalPtr->outlineGC != NULL)
                    781:            && (ovalPtr->fillGC == NULL)) {
                    782:        double centerX, centerY, width, height;
                    783:        double xDelta1, yDelta1, xDelta2, yDelta2;
                    784: 
                    785:        centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
                    786:        centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
                    787:        width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
                    788:        height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
                    789:        xDelta1 = (areaPtr[0] - centerX)/width;
                    790:        xDelta1 *= xDelta1;
                    791:        yDelta1 = (areaPtr[1] - centerY)/height;
                    792:        yDelta1 *= yDelta1;
                    793:        xDelta2 = (areaPtr[2] - centerX)/width;
                    794:        xDelta2 *= xDelta2;
                    795:        yDelta2 = (areaPtr[3] - centerY)/height;
                    796:        yDelta2 *= yDelta2;
                    797:        if (((xDelta1 + yDelta1) < 1.0)
                    798:                && ((xDelta1 + yDelta2) < 1.0)
                    799:                && ((xDelta2 + yDelta1) < 1.0)
                    800:                && ((xDelta2 + yDelta2) < 1.0)) {
                    801:            return -1;
                    802:        }
                    803:     }
                    804:     return result;
                    805: }
                    806: 
                    807: /*
                    808:  *--------------------------------------------------------------
                    809:  *
                    810:  * ScaleRectOval --
                    811:  *
                    812:  *     This procedure is invoked to rescale a rectangle or oval
                    813:  *     item.
                    814:  *
                    815:  * Results:
                    816:  *     None.
                    817:  *
                    818:  * Side effects:
                    819:  *     The rectangle or oval referred to by itemPtr is rescaled
                    820:  *     so that the following transformation is applied to all
                    821:  *     point coordinates:
                    822:  *             x' = originX + scaleX*(x-originX)
                    823:  *             y' = originY + scaleY*(y-originY)
                    824:  *
                    825:  *--------------------------------------------------------------
                    826:  */
                    827: 
                    828: static void
                    829: ScaleRectOval(canvasPtr, itemPtr, originX, originY, scaleX, scaleY)
                    830:     Tk_Canvas *canvasPtr;              /* Canvas containing rectangle. */
                    831:     Tk_Item *itemPtr;                  /* Rectangle to be scaled. */
                    832:     double originX, originY;           /* Origin about which to scale rect. */
                    833:     double scaleX;                     /* Amount to scale in X direction. */
                    834:     double scaleY;                     /* Amount to scale in Y direction. */
                    835: {
                    836:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    837: 
                    838:     rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
                    839:     rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
                    840:     rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
                    841:     rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
                    842:     ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
                    843: }
                    844: 
                    845: /*
                    846:  *--------------------------------------------------------------
                    847:  *
                    848:  * TranslateRectOval --
                    849:  *
                    850:  *     This procedure is called to move a rectangle or oval by a
                    851:  *     given amount.
                    852:  *
                    853:  * Results:
                    854:  *     None.
                    855:  *
                    856:  * Side effects:
                    857:  *     The position of the rectangle or oval is offset by
                    858:  *     (xDelta, yDelta), and the bounding box is updated in the
                    859:  *     generic part of the item structure.
                    860:  *
                    861:  *--------------------------------------------------------------
                    862:  */
                    863: 
                    864: static void
                    865: TranslateRectOval(canvasPtr, itemPtr, deltaX, deltaY)
                    866:     Tk_Canvas *canvasPtr;              /* Canvas containing item. */
                    867:     Tk_Item *itemPtr;                  /* Item that is being moved. */
                    868:     double deltaX, deltaY;             /* Amount by which item is to be
                    869:                                         * moved. */
                    870: {
                    871:     register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
                    872: 
                    873:     rectOvalPtr->bbox[0] += deltaX;
                    874:     rectOvalPtr->bbox[1] += deltaY;
                    875:     rectOvalPtr->bbox[2] += deltaX;
                    876:     rectOvalPtr->bbox[3] += deltaY;
                    877:     ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
                    878: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.