Annotation of micropolis/src/tk/tkrectov.c, revision 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.