Annotation of micropolis/src/tk/tkcvarc.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * tkCanvArc.c --
        !             3:  *
        !             4:  *     This file implements arc items for canvas widgets.
        !             5:  *
        !             6:  * Copyright 1992 Regents of the University of California.
        !             7:  * Permission to use, copy, modify, and distribute this
        !             8:  * software and its documentation for any purpose and without
        !             9:  * fee is hereby granted, provided that the above copyright
        !            10:  * notice appear in all copies.  The University of California
        !            11:  * makes no representations about the suitability of this
        !            12:  * software for any purpose.  It is provided "as is" without
        !            13:  * express or implied warranty.
        !            14:  */
        !            15: 
        !            16: #ifndef lint
        !            17: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkCanvArc.c,v 1.5 92/08/16 15:42:20 ouster Exp $ SPRITE (Berkeley)";
        !            18: #endif
        !            19: 
        !            20: #include <stdio.h>
        !            21: #include <math.h>
        !            22: #include "tkint.h"
        !            23: #include "tkcanvas.h"
        !            24: 
        !            25: /*
        !            26:  * The structure below defines the record for each arc item.
        !            27:  */
        !            28: 
        !            29: typedef struct ArcItem  {
        !            30:     Tk_Item header;            /* Generic stuff that's the same for all
        !            31:                                 * types.  MUST BE FIRST IN STRUCTURE. */
        !            32:     double bbox[4];            /* Coordinates (x1, y1, x2, y2) of bounding
        !            33:                                 * box for oval of which arc is a piece. */
        !            34:     double start;              /* Angle at which arc begins, in degrees
        !            35:                                 * between 0 and 360. */
        !            36:     double extent;             /* Extent of arc (angular distance from
        !            37:                                 * start to end of arc) in degrees between
        !            38:                                 * -360 and 360. */
        !            39:     double *outlinePtr;                /* Points to (x,y) coordinates for points
        !            40:                                 * that define one or two closed polygons
        !            41:                                 * representing the portion of the outline
        !            42:                                 * that isn't part of the arc (the V-shape
        !            43:                                 * for a pie slice or a line-like segment
        !            44:                                 * for a chord).  Malloc'ed. */
        !            45:     int numOutlinePoints;      /* Number of points at outlinePtr.  Zero
        !            46:                                 * means no space allocated. */
        !            47:     int width;                 /* Width of outline (in pixels). */
        !            48:     XColor *outlineColor;      /* Color for outline.  NULL means don't
        !            49:                                 * draw outline. */
        !            50:     XColor *fillColor;         /* Color for filling arc (used for drawing
        !            51:                                 * outline too when style is "arc").  NULL
        !            52:                                 * means don't fill arc. */
        !            53:     Pixmap fillStipple;                /* Stipple bitmap for filling item. */
        !            54:     Tk_Uid style;              /* How to draw arc: arc, chord, or pieslice. */
        !            55:     GC outlineGC;              /* Graphics context for outline. */
        !            56:     GC fillGC;                 /* Graphics context for filling item. */
        !            57:     double center1[2];         /* Coordinates of center of arc outline at
        !            58:                                 * start (see ComputeArcOutline). */
        !            59:     double center2[2];         /* Coordinates of center of arc outline at
        !            60:                                 * start+extent (see ComputeArcOutline). */
        !            61: } ArcItem;
        !            62: 
        !            63: /*
        !            64:  * The definitions below define the sizes of the polygons used to
        !            65:  * display outline information for various styles of arcs:
        !            66:  */
        !            67: 
        !            68: #define CHORD_OUTLINE_PTS      7
        !            69: #define PIE_OUTLINE1_PTS       6
        !            70: #define PIE_OUTLINE2_PTS       7
        !            71: 
        !            72: /*
        !            73:  * Information used for parsing configuration specs:
        !            74:  */
        !            75: 
        !            76: static Tk_ConfigSpec configSpecs[] = {
        !            77:     {TK_CONFIG_DOUBLE, "-extent", (char *) NULL, (char *) NULL,
        !            78:        "90", Tk_Offset(ArcItem, extent), TK_CONFIG_DONT_SET_DEFAULT},
        !            79:     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
        !            80:        (char *) NULL, Tk_Offset(ArcItem, fillColor), TK_CONFIG_NULL_OK},
        !            81:     {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
        !            82:        "black", Tk_Offset(ArcItem, outlineColor), TK_CONFIG_NULL_OK},
        !            83:     {TK_CONFIG_DOUBLE, "-start", (char *) NULL, (char *) NULL,
        !            84:        "0", Tk_Offset(ArcItem, start), TK_CONFIG_DONT_SET_DEFAULT},
        !            85:     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
        !            86:        (char *) NULL, Tk_Offset(ArcItem, fillStipple), TK_CONFIG_NULL_OK},
        !            87:     {TK_CONFIG_UID, "-style", (char *) NULL, (char *) NULL,
        !            88:        "pieslice", Tk_Offset(ArcItem, style), TK_CONFIG_DONT_SET_DEFAULT},
        !            89:     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
        !            90:        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tkCanvasTagsOption},
        !            91:     {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
        !            92:        "1", Tk_Offset(ArcItem, width), TK_CONFIG_DONT_SET_DEFAULT},
        !            93:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
        !            94:        (char *) NULL, 0, 0}
        !            95: };
        !            96: 
        !            97: /*
        !            98:  * Prototypes for procedures defined in this file:
        !            99:  */
        !           100: 
        !           101: static int             ArcCoords _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           102:                            Tk_Item *itemPtr, int argc, char **argv));
        !           103: static int             AngleInRange _ANSI_ARGS_((double x, double y,
        !           104:                            double start, double extent));
        !           105: static int             ArcToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           106:                            Tk_Item *itemPtr, double *rectPtr));
        !           107: static double          ArcToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           108:                            Tk_Item *itemPtr, double *coordPtr));
        !           109: static void            ComputeArcBbox _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           110:                            ArcItem *arcPtr));
        !           111: static void            ComputeArcOutline _ANSI_ARGS_((ArcItem *arcPtr));
        !           112: static int             ConfigureArc _ANSI_ARGS_((
        !           113:                            Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int argc,
        !           114:                            char **argv, int flags));
        !           115: static int             CreateArc _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           116:                            struct Tk_Item *itemPtr, int argc, char **argv));
        !           117: static void            DeleteArc _ANSI_ARGS_((Tk_Item *itemPtr));
        !           118: static void            DisplayArc _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           119:                            Tk_Item *itemPtr, Drawable dst));
        !           120: static int             HorizLineToArc _ANSI_ARGS_((double x1, double x2,
        !           121:                            double y, double rx, double ry,
        !           122:                            double start, double extent));
        !           123: static void            ScaleArc _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           124:                            Tk_Item *itemPtr, double originX, double originY,
        !           125:                            double scaleX, double scaleY));
        !           126: static void            TranslateArc _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !           127:                            Tk_Item *itemPtr, double deltaX, double deltaY));
        !           128: static int             VertLineToArc _ANSI_ARGS_((double x, double y1,
        !           129:                            double y2, double rx, double ry,
        !           130:                            double start, double extent));
        !           131: 
        !           132: /*
        !           133:  * The structures below defines the arc item types by means of procedures
        !           134:  * that can be invoked by generic item code.
        !           135:  */
        !           136: 
        !           137: Tk_ItemType TkArcType = {
        !           138:     "arc",                             /* name */
        !           139:     sizeof(ArcItem),                   /* itemSize */
        !           140:     CreateArc,                         /* createProc */
        !           141:     configSpecs,                       /* configSpecs */
        !           142:     ConfigureArc,                      /* configureProc */
        !           143:     ArcCoords,                         /* coordProc */
        !           144:     DeleteArc,                         /* deleteProc */
        !           145:     DisplayArc,                                /* displayProc */
        !           146:     0,                                 /* alwaysRedraw */
        !           147:     ArcToPoint,                                /* pointProc */
        !           148:     ArcToArea,                         /* areaProc */
        !           149:     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
        !           150:     ScaleArc,                          /* scaleProc */
        !           151:     TranslateArc,                      /* translateProc */
        !           152:     (Tk_ItemIndexProc *) NULL,         /* indexProc */
        !           153:     (Tk_ItemCursorProc *) NULL,                /* cursorProc */
        !           154:     (Tk_ItemSelectionProc *) NULL,     /* selectionProc */
        !           155:     (Tk_ItemInsertProc *) NULL,                /* insertProc */
        !           156:     (Tk_ItemDCharsProc *) NULL,                /* dTextProc */
        !           157:     (Tk_ItemType *) NULL               /* nextPtr */
        !           158: };
        !           159: 
        !           160: #define PI 3.14159265358979323846
        !           161: 
        !           162: /*
        !           163:  * The uid's below comprise the legal values for the "-style"
        !           164:  * option for arcs.
        !           165:  */
        !           166: 
        !           167: static Tk_Uid arcUid =  NULL;
        !           168: static Tk_Uid chordUid =  NULL;
        !           169: static Tk_Uid pieSliceUid = NULL;
        !           170: 
        !           171: /*
        !           172:  *--------------------------------------------------------------
        !           173:  *
        !           174:  * CreateArc --
        !           175:  *
        !           176:  *     This procedure is invoked to create a new arc item in
        !           177:  *     a canvas.
        !           178:  *
        !           179:  * Results:
        !           180:  *     A standard Tcl return value.  If an error occurred in
        !           181:  *     creating the item, then an error message is left in
        !           182:  *     canvasPtr->interp->result;  in this case itemPtr is
        !           183:  *     left uninitialized, so it can be safely freed by the
        !           184:  *     caller.
        !           185:  *
        !           186:  * Side effects:
        !           187:  *     A new arc item is created.
        !           188:  *
        !           189:  *--------------------------------------------------------------
        !           190:  */
        !           191: 
        !           192: static int
        !           193: CreateArc(canvasPtr, itemPtr, argc, argv)
        !           194:     register Tk_Canvas *canvasPtr;     /* Canvas to hold new item. */
        !           195:     Tk_Item *itemPtr;                  /* Record to hold new item;  header
        !           196:                                         * has been initialized by caller. */
        !           197:     int argc;                          /* Number of arguments in argv. */
        !           198:     char **argv;                       /* Arguments describing arc. */
        !           199: {
        !           200:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           201: 
        !           202:     if (argc < 4) {
        !           203:        Tcl_AppendResult(canvasPtr->interp, "wrong # args:  should be \"",
        !           204:                Tk_PathName(canvasPtr->tkwin), "\" create ",
        !           205:                itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?",
        !           206:                (char *) NULL);
        !           207:        return TCL_ERROR;
        !           208:     }
        !           209: 
        !           210:     /*
        !           211:      * Carry out once-only initialization.
        !           212:      */
        !           213: 
        !           214:     if (arcUid == NULL) {
        !           215:        arcUid = Tk_GetUid("arc");
        !           216:        chordUid = Tk_GetUid("chord");
        !           217:        pieSliceUid = Tk_GetUid("pieslice");
        !           218:     }
        !           219: 
        !           220:     /*
        !           221:      * Carry out initialization that is needed in order to clean
        !           222:      * up after errors during the the remainder of this procedure.
        !           223:      */
        !           224: 
        !           225:     arcPtr->start = 0;
        !           226:     arcPtr->extent = 90;
        !           227:     arcPtr->outlinePtr = NULL;
        !           228:     arcPtr->numOutlinePoints = 0;
        !           229:     arcPtr->width = 1;
        !           230:     arcPtr->outlineColor = NULL;
        !           231:     arcPtr->fillColor = NULL;
        !           232:     arcPtr->fillStipple = None;
        !           233:     arcPtr->style = pieSliceUid;
        !           234:     arcPtr->outlineGC = None;
        !           235:     arcPtr->fillGC = None;
        !           236: 
        !           237:     /*
        !           238:      * Process the arguments to fill in the item record.
        !           239:      */
        !           240: 
        !           241:     if ((TkGetCanvasCoord(canvasPtr, argv[0], &arcPtr->bbox[0]) != TCL_OK)
        !           242:            || (TkGetCanvasCoord(canvasPtr, argv[1],
        !           243:                &arcPtr->bbox[1]) != TCL_OK)
        !           244:            || (TkGetCanvasCoord(canvasPtr, argv[2],
        !           245:                    &arcPtr->bbox[2]) != TCL_OK)
        !           246:            || (TkGetCanvasCoord(canvasPtr, argv[3],
        !           247:                    &arcPtr->bbox[3]) != TCL_OK)) {
        !           248:        return TCL_ERROR;
        !           249:     }
        !           250: 
        !           251:     if (ConfigureArc(canvasPtr, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
        !           252:        DeleteArc(itemPtr);
        !           253:        return TCL_ERROR;
        !           254:     }
        !           255:     return TCL_OK;
        !           256: }
        !           257: 
        !           258: /*
        !           259:  *--------------------------------------------------------------
        !           260:  *
        !           261:  * ArcCoords --
        !           262:  *
        !           263:  *     This procedure is invoked to process the "coords" widget
        !           264:  *     command on arcs.  See the user documentation for details
        !           265:  *     on what it does.
        !           266:  *
        !           267:  * Results:
        !           268:  *     Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
        !           269:  *
        !           270:  * Side effects:
        !           271:  *     The coordinates for the given item may be changed.
        !           272:  *
        !           273:  *--------------------------------------------------------------
        !           274:  */
        !           275: 
        !           276: static int
        !           277: ArcCoords(canvasPtr, itemPtr, argc, argv)
        !           278:     register Tk_Canvas *canvasPtr;     /* Canvas containing item. */
        !           279:     Tk_Item *itemPtr;                  /* Item whose coordinates are to be
        !           280:                                         * read or modified. */
        !           281:     int argc;                          /* Number of coordinates supplied in
        !           282:                                         * argv. */
        !           283:     char **argv;                       /* Array of coordinates: x1, y1,
        !           284:                                         * x2, y2, ... */
        !           285: {
        !           286:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           287:     char buffer[500];
        !           288: 
        !           289:     if (argc == 0) {
        !           290:        sprintf(buffer, "%g %g %g %g", arcPtr->bbox[0],
        !           291:                arcPtr->bbox[1], arcPtr->bbox[2],
        !           292:                arcPtr->bbox[3]);
        !           293:        Tcl_SetResult(canvasPtr->interp, buffer, TCL_VOLATILE);
        !           294:     } else if (argc == 4) {
        !           295:        if ((TkGetCanvasCoord(canvasPtr, argv[0],
        !           296:                    &arcPtr->bbox[0]) != TCL_OK)
        !           297:                || (TkGetCanvasCoord(canvasPtr, argv[1],
        !           298:                    &arcPtr->bbox[1]) != TCL_OK)
        !           299:                || (TkGetCanvasCoord(canvasPtr, argv[2],
        !           300:                        &arcPtr->bbox[2]) != TCL_OK)
        !           301:                || (TkGetCanvasCoord(canvasPtr, argv[3],
        !           302:                        &arcPtr->bbox[3]) != TCL_OK)) {
        !           303:            return TCL_ERROR;
        !           304:        }
        !           305:        ComputeArcBbox(canvasPtr, arcPtr);
        !           306:     } else {
        !           307:        sprintf(canvasPtr->interp->result,
        !           308:                "wrong # coordinates:  expected 0 or 4, got %d",
        !           309:                argc);
        !           310:        return TCL_ERROR;
        !           311:     }
        !           312:     return TCL_OK;
        !           313: }
        !           314: 
        !           315: /*
        !           316:  *--------------------------------------------------------------
        !           317:  *
        !           318:  * ConfigureArc --
        !           319:  *
        !           320:  *     This procedure is invoked to configure various aspects
        !           321:  *     of a arc item, such as its outline and fill colors.
        !           322:  *
        !           323:  * Results:
        !           324:  *     A standard Tcl result code.  If an error occurs, then
        !           325:  *     an error message is left in canvasPtr->interp->result.
        !           326:  *
        !           327:  * Side effects:
        !           328:  *     Configuration information, such as colors and stipple
        !           329:  *     patterns, may be set for itemPtr.
        !           330:  *
        !           331:  *--------------------------------------------------------------
        !           332:  */
        !           333: 
        !           334: static int
        !           335: ConfigureArc(canvasPtr, itemPtr, argc, argv, flags)
        !           336:     Tk_Canvas *canvasPtr;      /* Canvas containing itemPtr. */
        !           337:     Tk_Item *itemPtr;          /* Arc item to reconfigure. */
        !           338:     int argc;                  /* Number of elements in argv.  */
        !           339:     char **argv;               /* Arguments describing things to configure. */
        !           340:     int flags;                 /* Flags to pass to Tk_ConfigureWidget. */
        !           341: {
        !           342:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           343:     XGCValues gcValues;
        !           344:     GC newGC;
        !           345:     unsigned long mask;
        !           346:     int i;
        !           347: 
        !           348:     if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
        !           349:            configSpecs, argc, argv, (char *) arcPtr, flags) != TCL_OK) {
        !           350:        return TCL_ERROR;
        !           351:     }
        !           352: 
        !           353:     /*
        !           354:      * A few of the options require additional processing, such as
        !           355:      * style and graphics contexts.
        !           356:      */
        !           357: 
        !           358:     i = arcPtr->start/360.0;
        !           359:     arcPtr->start -= i*360.0;
        !           360:     if (arcPtr->start < 0) {
        !           361:        arcPtr->start += 360.0;
        !           362:     }
        !           363:     i = arcPtr->extent/360.0;
        !           364:     arcPtr->extent -= i*360.0;
        !           365: 
        !           366:     if ((arcPtr->style != arcUid) && (arcPtr->style != chordUid)
        !           367:            && (arcPtr->style != pieSliceUid)) {
        !           368:        Tcl_AppendResult(canvasPtr->interp, "bad -style option \"",
        !           369:                arcPtr->style, "\": must be arc, chord, or pieslice",
        !           370:                (char *) NULL);
        !           371:        arcPtr->style = pieSliceUid;
        !           372:        return TCL_ERROR;
        !           373:     }
        !           374: 
        !           375:     if (arcPtr->width < 0) {
        !           376:        arcPtr->width = 1;
        !           377:     }
        !           378:     if (arcPtr->style == arcUid) {
        !           379:        if (arcPtr->fillColor == NULL) {
        !           380:            newGC = None;
        !           381:        } else {
        !           382:            gcValues.foreground = arcPtr->fillColor->pixel;
        !           383:            gcValues.cap_style = CapButt;
        !           384:            gcValues.line_width = arcPtr->width;
        !           385:            mask = GCForeground|GCCapStyle|GCLineWidth;
        !           386:            if (arcPtr->fillStipple != None) {
        !           387:                gcValues.stipple = arcPtr->fillStipple;
        !           388:                gcValues.fill_style = FillStippled;
        !           389:                mask |= GCStipple|GCFillStyle;
        !           390:            }
        !           391:            newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
        !           392:        }
        !           393:     } else if (arcPtr->outlineColor == NULL) {
        !           394:        newGC = None;
        !           395:     } else {
        !           396:        gcValues.foreground = arcPtr->outlineColor->pixel;
        !           397:        gcValues.cap_style = CapButt;
        !           398:        gcValues.line_width = arcPtr->width;
        !           399:        mask = GCForeground|GCCapStyle|GCLineWidth;
        !           400:        newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
        !           401:     }
        !           402:     if (arcPtr->outlineGC != None) {
        !           403:        Tk_FreeGC(arcPtr->outlineGC);
        !           404:     }
        !           405:     arcPtr->outlineGC = newGC;
        !           406: 
        !           407:     if ((arcPtr->fillColor == NULL) || (arcPtr->style == arcUid)) {
        !           408:        newGC = None;
        !           409:     } else {
        !           410:        gcValues.foreground = arcPtr->fillColor->pixel;
        !           411:        if (arcPtr->style == chordUid) {
        !           412:            gcValues.arc_mode = ArcChord;
        !           413:        } else {
        !           414:            gcValues.arc_mode = ArcPieSlice;
        !           415:        }
        !           416:        mask = GCForeground|GCArcMode;
        !           417:        if (arcPtr->fillStipple != None) {
        !           418:            gcValues.stipple = arcPtr->fillStipple;
        !           419:            gcValues.fill_style = FillStippled;
        !           420:            mask |= GCStipple|GCFillStyle;
        !           421:        }
        !           422:        newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
        !           423:     }
        !           424:     if (arcPtr->fillGC != None) {
        !           425:        Tk_FreeGC(arcPtr->fillGC);
        !           426:     }
        !           427:     arcPtr->fillGC = newGC;
        !           428: 
        !           429:     ComputeArcBbox(canvasPtr, arcPtr);
        !           430:     return TCL_OK;
        !           431: }
        !           432: 
        !           433: /*
        !           434:  *--------------------------------------------------------------
        !           435:  *
        !           436:  * DeleteArc --
        !           437:  *
        !           438:  *     This procedure is called to clean up the data structure
        !           439:  *     associated with a arc item.
        !           440:  *
        !           441:  * Results:
        !           442:  *     None.
        !           443:  *
        !           444:  * Side effects:
        !           445:  *     Resources associated with itemPtr are released.
        !           446:  *
        !           447:  *--------------------------------------------------------------
        !           448:  */
        !           449: 
        !           450: static void
        !           451: DeleteArc(itemPtr)
        !           452:     Tk_Item *itemPtr;                  /* Item that is being deleted. */
        !           453: {
        !           454:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           455: 
        !           456:     if (arcPtr->numOutlinePoints != 0) {
        !           457:        ckfree((char *) arcPtr->outlinePtr);
        !           458:     }
        !           459:     if (arcPtr->outlineColor != NULL) {
        !           460:        Tk_FreeColor(arcPtr->outlineColor);
        !           461:     }
        !           462:     if (arcPtr->fillColor != NULL) {
        !           463:        Tk_FreeColor(arcPtr->fillColor);
        !           464:     }
        !           465:     if (arcPtr->fillStipple != None) {
        !           466:        Tk_FreeBitmap(arcPtr->fillStipple);
        !           467:     }
        !           468:     if (arcPtr->outlineGC != None) {
        !           469:        Tk_FreeGC(arcPtr->outlineGC);
        !           470:     }
        !           471:     if (arcPtr->fillGC != None) {
        !           472:        Tk_FreeGC(arcPtr->fillGC);
        !           473:     }
        !           474: }
        !           475: 
        !           476: /*
        !           477:  *--------------------------------------------------------------
        !           478:  *
        !           479:  * ComputeArcBbox --
        !           480:  *
        !           481:  *     This procedure is invoked to compute the bounding box of
        !           482:  *     all the pixels that may be drawn as part of an arc.
        !           483:  *
        !           484:  * Results:
        !           485:  *     None.
        !           486:  *
        !           487:  * Side effects:
        !           488:  *     The fields x1, y1, x2, and y2 are updated in the header
        !           489:  *     for itemPtr.
        !           490:  *
        !           491:  *--------------------------------------------------------------
        !           492:  */
        !           493: 
        !           494:        /* ARGSUSED */
        !           495: static void
        !           496: ComputeArcBbox(canvasPtr, arcPtr)
        !           497:     register Tk_Canvas *canvasPtr;     /* Canvas that contains item. */
        !           498:     register ArcItem *arcPtr;          /* Item whose bbox is to be
        !           499:                                         * recomputed. */
        !           500: {
        !           501:     double tmp, center[2], point[2];
        !           502: 
        !           503:     /*
        !           504:      * Make sure that the first coordinates are the lowest ones.
        !           505:      */
        !           506: 
        !           507:     if (arcPtr->bbox[1] > arcPtr->bbox[3]) {
        !           508:        double tmp;
        !           509:        tmp = arcPtr->bbox[3];
        !           510:        arcPtr->bbox[3] = arcPtr->bbox[1];
        !           511:        arcPtr->bbox[1] = tmp;
        !           512:     }
        !           513:     if (arcPtr->bbox[0] > arcPtr->bbox[2]) {
        !           514:        double tmp;
        !           515:        tmp = arcPtr->bbox[2];
        !           516:        arcPtr->bbox[2] = arcPtr->bbox[0];
        !           517:        arcPtr->bbox[0] = tmp;
        !           518:     }
        !           519: 
        !           520:     ComputeArcOutline(arcPtr);
        !           521: 
        !           522:     /*
        !           523:      * To compute the bounding box, start with the the bbox formed
        !           524:      * by the two endpoints of the arc.  Then add in the center of
        !           525:      * the arc's oval (if relevant) and the 3-o'clock, 6-o'clock,
        !           526:      * 9-o'clock, and 12-o'clock positions, if they are relevant.
        !           527:      */
        !           528: 
        !           529:     arcPtr->header.x1 = arcPtr->header.x2 = arcPtr->center1[0];
        !           530:     arcPtr->header.y1 = arcPtr->header.y2 = arcPtr->center1[1];
        !           531:     TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, arcPtr->center2);
        !           532:     center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2;
        !           533:     center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2;
        !           534:     if (arcPtr->style != arcUid) {
        !           535:        TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, center);
        !           536:     }
        !           537: 
        !           538:     tmp = -arcPtr->start;
        !           539:     if (tmp < 0) {
        !           540:        tmp += 360.0;
        !           541:     }
        !           542:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           543:        point[0] = arcPtr->bbox[2];
        !           544:        point[1] = center[1];
        !           545:        TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, point);
        !           546:     }
        !           547:     tmp = 90.0 - arcPtr->start;
        !           548:     if (tmp < 0) {
        !           549:        tmp += 360.0;
        !           550:     }
        !           551:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           552:        point[0] = center[0];
        !           553:        point[1] = arcPtr->bbox[1];
        !           554:        TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, point);
        !           555:     }
        !           556:     tmp = 180.0 - arcPtr->start;
        !           557:     if (tmp < 0) {
        !           558:        tmp += 360.0;
        !           559:     }
        !           560:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           561:        point[0] = arcPtr->bbox[0];
        !           562:        point[1] = center[1];
        !           563:        TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, point);
        !           564:     }
        !           565:     tmp = 270.0 - arcPtr->start;
        !           566:     if (tmp < 0) {
        !           567:        tmp += 360.0;
        !           568:     }
        !           569:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           570:        point[0] = center[0];
        !           571:        point[1] = arcPtr->bbox[3];
        !           572:        TkIncludePoint(canvasPtr, (Tk_Item *) arcPtr, point);
        !           573:     }
        !           574: 
        !           575:     /*
        !           576:      * Lastly, expand by the width of the arc (if the arc's outline is
        !           577:      * being drawn) and add one extra pixel just for safety.
        !           578:      */
        !           579: 
        !           580:     if (arcPtr->outlineColor == NULL) {
        !           581:        tmp = 1;
        !           582:     } else {
        !           583:        tmp = (arcPtr->width + 1)/2 + 1;
        !           584:     }
        !           585:     arcPtr->header.x1 -= tmp;
        !           586:     arcPtr->header.y1 -= tmp;
        !           587:     arcPtr->header.x2 += tmp;
        !           588:     arcPtr->header.y2 += tmp;
        !           589: }
        !           590: 
        !           591: /*
        !           592:  *--------------------------------------------------------------
        !           593:  *
        !           594:  * DisplayArc --
        !           595:  *
        !           596:  *     This procedure is invoked to draw an arc item in a given
        !           597:  *     drawable.
        !           598:  *
        !           599:  * Results:
        !           600:  *     None.
        !           601:  *
        !           602:  * Side effects:
        !           603:  *     ItemPtr is drawn in drawable using the transformation
        !           604:  *     information in canvasPtr.
        !           605:  *
        !           606:  *--------------------------------------------------------------
        !           607:  */
        !           608: 
        !           609: static void
        !           610: DisplayArc(canvasPtr, itemPtr, drawable)
        !           611:     register Tk_Canvas *canvasPtr;     /* Canvas that contains item. */
        !           612:     Tk_Item *itemPtr;                  /* Item to be displayed. */
        !           613:     Drawable drawable;                 /* Pixmap or window in which to draw
        !           614:                                         * item. */
        !           615: {
        !           616:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           617:     Display *display = Tk_Display(canvasPtr->tkwin);
        !           618:     int x1, y1, x2, y2, start, extent;
        !           619: 
        !           620:     /*
        !           621:      * Compute the screen coordinates of the bounding box for the item,
        !           622:      * plus integer values for the angles.
        !           623:      */
        !           624: 
        !           625:     x1 = SCREEN_X(canvasPtr, arcPtr->bbox[0]);
        !           626:     y1 = SCREEN_Y(canvasPtr, arcPtr->bbox[1]);
        !           627:     x2 = SCREEN_X(canvasPtr, arcPtr->bbox[2]);
        !           628:     y2 = SCREEN_Y(canvasPtr, arcPtr->bbox[3]);
        !           629:     if (x2 <= x1) {
        !           630:        x2 = x1+1;
        !           631:     }
        !           632:     if (y2 <= y1) {
        !           633:        y2 = y1+1;
        !           634:     }
        !           635:     start = (64*arcPtr->start) + 0.5;
        !           636:     extent = (64*arcPtr->extent) + 0.5;
        !           637: 
        !           638:     /*
        !           639:      * Display filled arc first (if wanted), then outline.
        !           640:      */
        !           641: 
        !           642:     if (arcPtr->fillGC != None) {
        !           643:        XFillArc(display, drawable, arcPtr->fillGC, x1, y1, (x2-x1),
        !           644:                (y2-y1), start, extent);
        !           645:     }
        !           646:     if (arcPtr->outlineGC != None) {
        !           647:        XDrawArc(display, drawable, arcPtr->outlineGC, x1, y1, (x2-x1),
        !           648:                (y2-y1), start, extent);
        !           649: 
        !           650:        /*
        !           651:         * If the outline width is very thin, don't use polygons to draw
        !           652:         * the linear parts of the outline (this often results in nothing
        !           653:         * being displayed); just draw lines instead.
        !           654:         */
        !           655: 
        !           656:        if (arcPtr->width <= 2) {
        !           657:            x1 = SCREEN_X(canvasPtr, arcPtr->center1[0]);
        !           658:            y1 = SCREEN_Y(canvasPtr, arcPtr->center1[1]);
        !           659:            x2 = SCREEN_X(canvasPtr, arcPtr->center2[0]);
        !           660:            y2 = SCREEN_Y(canvasPtr, arcPtr->center2[1]);
        !           661: 
        !           662:            if (arcPtr->style == chordUid) {
        !           663:                XDrawLine(display, drawable, arcPtr->outlineGC,
        !           664:                        x1, y1, x2, y2);
        !           665:            } else if (arcPtr->style == pieSliceUid) {
        !           666:                int cx, cy;
        !           667:     
        !           668:                cx = SCREEN_X(canvasPtr, (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0);
        !           669:                cy = SCREEN_Y(canvasPtr, (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0);
        !           670:                XDrawLine(display, drawable, arcPtr->outlineGC,
        !           671:                        cx, cy, x1, y1);
        !           672:                XDrawLine(display, drawable, arcPtr->outlineGC,
        !           673:                        cx, cy, x2, y2);
        !           674:            }
        !           675:        } else {
        !           676:            if (arcPtr->style == chordUid) {
        !           677:                TkFillPolygon(canvasPtr, arcPtr->outlinePtr,
        !           678:                        CHORD_OUTLINE_PTS, drawable, arcPtr->outlineGC);
        !           679:            } else if (arcPtr->style == pieSliceUid) {
        !           680:                TkFillPolygon(canvasPtr, arcPtr->outlinePtr,
        !           681:                        PIE_OUTLINE1_PTS, drawable, arcPtr->outlineGC);
        !           682:                TkFillPolygon(canvasPtr,
        !           683:                        arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
        !           684:                        PIE_OUTLINE2_PTS, drawable, arcPtr->outlineGC);
        !           685:            }
        !           686:        }
        !           687:     }
        !           688: }
        !           689: 
        !           690: /*
        !           691:  *--------------------------------------------------------------
        !           692:  *
        !           693:  * ArcToPoint --
        !           694:  *
        !           695:  *     Computes the distance from a given point to a given
        !           696:  *     arc, in canvas units.
        !           697:  *
        !           698:  * Results:
        !           699:  *     The return value is 0 if the point whose x and y coordinates
        !           700:  *     are coordPtr[0] and coordPtr[1] is inside the arc.  If the
        !           701:  *     point isn't inside the arc then the return value is the
        !           702:  *     distance from the point to the arc.  If itemPtr is filled,
        !           703:  *     then anywhere in the interior is considered "inside"; if
        !           704:  *     itemPtr isn't filled, then "inside" means only the area
        !           705:  *     occupied by the outline.
        !           706:  *
        !           707:  * Side effects:
        !           708:  *     None.
        !           709:  *
        !           710:  *--------------------------------------------------------------
        !           711:  */
        !           712: 
        !           713:        /* ARGSUSED */
        !           714: static double
        !           715: ArcToPoint(canvasPtr, itemPtr, pointPtr)
        !           716:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
        !           717:     Tk_Item *itemPtr;          /* Item to check against point. */
        !           718:     double *pointPtr;          /* Pointer to x and y coordinates. */
        !           719: {
        !           720:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           721:     double vertex[2], pointAngle, diff, dist, newDist;
        !           722:     double poly[8], polyDist, width;
        !           723:     int filled, angleInRange;
        !           724: 
        !           725:     if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
        !           726:        filled = 1;
        !           727:     } else {
        !           728:        filled = 0;
        !           729:     }
        !           730: 
        !           731:     /*
        !           732:      * See if the point is within the angular range of the arc.
        !           733:      * Remember, X angles are backwards from the way we'd normally
        !           734:      * think of them.  Also, compensate for any eccentricity of
        !           735:      * the oval.
        !           736:      */
        !           737: 
        !           738:     vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
        !           739:     vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
        !           740:     pointAngle = -atan2((pointPtr[1] - vertex[1])
        !           741:            /(arcPtr->bbox[3] - arcPtr->bbox[1]),
        !           742:            (pointPtr[0] - vertex[0])/(arcPtr->bbox[2] - arcPtr->bbox[0]));
        !           743:     pointAngle *= 180/PI;
        !           744:     diff = pointAngle - arcPtr->start;
        !           745:     diff -= ((int) (diff/360.0) * 360.0);
        !           746:     if (diff < 0) {
        !           747:        diff += 360.0;
        !           748:     }
        !           749:     angleInRange = (diff <= arcPtr->extent) ||
        !           750:            ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent));
        !           751: 
        !           752:     /*
        !           753:      * Now perform different tests depending on what kind of arc
        !           754:      * we're dealing with.
        !           755:      */
        !           756: 
        !           757:     if (arcPtr->style == arcUid) {
        !           758:        if (angleInRange) {
        !           759:            return TkOvalToPoint(arcPtr->bbox, (double) arcPtr->width,
        !           760:                    0, pointPtr);
        !           761:        }
        !           762:        dist = hypot(pointPtr[0] - arcPtr->center1[0],
        !           763:                pointPtr[1] - arcPtr->center1[1]);
        !           764:        newDist = hypot(pointPtr[0] - arcPtr->center2[0],
        !           765:                pointPtr[1] - arcPtr->center2[1]);
        !           766:        if (newDist < dist) {
        !           767:            return newDist;
        !           768:        }
        !           769:        return dist;
        !           770:     }
        !           771: 
        !           772:     if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
        !           773:        filled = 1;
        !           774:     } else {
        !           775:        filled = 0;
        !           776:     }
        !           777:     if (arcPtr->outlineGC == None) {
        !           778:        width = 0.0;
        !           779:     } else {
        !           780:        width = arcPtr->width;
        !           781:     }
        !           782: 
        !           783:     if (arcPtr->style == pieSliceUid) {
        !           784:        if (width > 1.0) {
        !           785:            dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
        !           786:                    pointPtr);
        !           787:            newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
        !           788:                        PIE_OUTLINE2_PTS, pointPtr);
        !           789:        } else {
        !           790:            dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr);
        !           791:            newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr);
        !           792:        }
        !           793:        if (newDist < dist) {
        !           794:            dist = newDist;
        !           795:        }
        !           796:        if (angleInRange) {
        !           797:            newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
        !           798:            if (newDist < dist) {
        !           799:                dist = newDist;
        !           800:            }
        !           801:        }
        !           802:        return dist;
        !           803:     }
        !           804: 
        !           805:     /*
        !           806:      * This is a chord-style arc.  We have to deal specially with the
        !           807:      * triangular piece that represents the difference between a
        !           808:      * chord-style arc and a pie-slice arc (for small angles this piece
        !           809:      * is excluded here where it would be included for pie slices;
        !           810:      * for large angles the piece is included here but would be
        !           811:      * excluded for pie slices).
        !           812:      */
        !           813: 
        !           814:     if (width > 1.0) {
        !           815:        dist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
        !           816:                    pointPtr);
        !           817:     } else {
        !           818:        dist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr);
        !           819:     }
        !           820:     poly[0] = poly[6] = vertex[0];
        !           821:     poly[1] = poly[7] = vertex[1];
        !           822:     poly[2] = arcPtr->center1[0];
        !           823:     poly[3] = arcPtr->center1[1];
        !           824:     poly[4] = arcPtr->center2[0];
        !           825:     poly[5] = arcPtr->center2[1];
        !           826:     polyDist = TkPolygonToPoint(poly, 4, pointPtr);
        !           827:     if (angleInRange) {
        !           828:        if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)
        !           829:                || (polyDist > 0.0)) {
        !           830:            newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr);
        !           831:            if (newDist < dist) {
        !           832:                dist = newDist;
        !           833:            }
        !           834:        }
        !           835:     } else {
        !           836:        if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0)) {
        !           837:            if (filled && (polyDist < dist)) {
        !           838:                dist = polyDist;
        !           839:            }
        !           840:        }
        !           841:     }
        !           842:     return dist;
        !           843: }
        !           844: 
        !           845: /*
        !           846:  *--------------------------------------------------------------
        !           847:  *
        !           848:  * ArcToArea --
        !           849:  *
        !           850:  *     This procedure is called to determine whether an item
        !           851:  *     lies entirely inside, entirely outside, or overlapping
        !           852:  *     a given area.
        !           853:  *
        !           854:  * Results:
        !           855:  *     -1 is returned if the item is entirely outside the area
        !           856:  *     given by rectPtr, 0 if it overlaps, and 1 if it is entirely
        !           857:  *     inside the given area.
        !           858:  *
        !           859:  * Side effects:
        !           860:  *     None.
        !           861:  *
        !           862:  *--------------------------------------------------------------
        !           863:  */
        !           864: 
        !           865:        /* ARGSUSED */
        !           866: static int
        !           867: ArcToArea(canvasPtr, itemPtr, rectPtr)
        !           868:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
        !           869:     Tk_Item *itemPtr;          /* Item to check against arc. */
        !           870:     double *rectPtr;           /* Pointer to array of four coordinates
        !           871:                                 * (x1, y1, x2, y2) describing rectangular
        !           872:                                 * area.  */
        !           873: {
        !           874:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !           875:     double rx, ry;             /* Radii for transformed oval:  these define
        !           876:                                 * an oval centered at the origin. */
        !           877:     double tRect[4];           /* Transformed version of x1, y1, x2, y2,
        !           878:                                 * for coord. system where arc is centered
        !           879:                                 * on the origin. */
        !           880:     double center[2], width, angle, tmp;
        !           881:     double points[20], *pointPtr;
        !           882:     int numPoints, filled;
        !           883:     int inside;                        /* Non-zero means every test so far suggests
        !           884:                                 * that arc is inside rectangle.  0 means
        !           885:                                 * every test so far shows arc to be outside
        !           886:                                 * of rectangle. */
        !           887:     int newInside;
        !           888: 
        !           889:     if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) {
        !           890:        filled = 1;
        !           891:     } else {
        !           892:        filled = 0;
        !           893:     }
        !           894:     if (arcPtr->outlineGC == None) {
        !           895:        width = 0.0;
        !           896:     } else {
        !           897:        width = arcPtr->width;
        !           898:     }
        !           899: 
        !           900:     /*
        !           901:      * Transform both the arc and the rectangle so that the arc's oval
        !           902:      * is centered on the origin.
        !           903:      */
        !           904: 
        !           905:     center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
        !           906:     center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
        !           907:     tRect[0] = rectPtr[0] - center[0];
        !           908:     tRect[1] = rectPtr[1] - center[1];
        !           909:     tRect[2] = rectPtr[2] - center[0];
        !           910:     tRect[3] = rectPtr[3] - center[1];
        !           911:     rx = arcPtr->bbox[2] - center[0] + width/2.0;
        !           912:     ry = arcPtr->bbox[3] - center[1] + width/2.0;
        !           913: 
        !           914:     /*
        !           915:      * Find the extreme points of the arc and see whether these are all
        !           916:      * inside the rectangle (in which case we're done), partly in and
        !           917:      * partly out (in which case we're done), or all outside (in which
        !           918:      * case we have more work to do).  The extreme points include the
        !           919:      * following, which are checked in order:
        !           920:      *
        !           921:      * 1. The outside points of the arc, corresponding to start and
        !           922:      *   extent.
        !           923:      * 2. The center of the arc (but only in pie-slice mode).
        !           924:      * 3. The 12, 3, 6, and 9-o'clock positions (but only if the arc
        !           925:      *    includes those angles).
        !           926:      */
        !           927: 
        !           928:     pointPtr = points;
        !           929:     numPoints = 0;
        !           930:     angle = -arcPtr->start*(PI/180.0);
        !           931:     pointPtr[0] = rx*cos(angle);
        !           932:     pointPtr[1] = ry*sin(angle);
        !           933:     angle += -arcPtr->extent*(PI/180.0);
        !           934:     pointPtr[2] = rx*cos(angle);
        !           935:     pointPtr[3] = ry*sin(angle);
        !           936:     numPoints = 2;
        !           937:     pointPtr += 4;
        !           938: 
        !           939:     if ((arcPtr->style == pieSliceUid) && (arcPtr->extent < 180.0)) {
        !           940:        pointPtr[0] = 0.0;
        !           941:        pointPtr[1] = 0.0;
        !           942:        numPoints++;
        !           943:        pointPtr += 2;
        !           944:     }
        !           945: 
        !           946:     tmp = -arcPtr->start;
        !           947:     if (tmp < 0) {
        !           948:        tmp += 360.0;
        !           949:     }
        !           950:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           951:        pointPtr[0] = rx;
        !           952:        pointPtr[1] = 0.0;
        !           953:        numPoints++;
        !           954:        pointPtr += 2;
        !           955:     }
        !           956:     tmp = 90.0 - arcPtr->start;
        !           957:     if (tmp < 0) {
        !           958:        tmp += 360.0;
        !           959:     }
        !           960:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           961:        pointPtr[0] = 0.0;
        !           962:        pointPtr[1] = -ry;
        !           963:        numPoints++;
        !           964:        pointPtr += 2;
        !           965:     }
        !           966:     tmp = 180.0 - arcPtr->start;
        !           967:     if (tmp < 0) {
        !           968:        tmp += 360.0;
        !           969:     }
        !           970:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           971:        pointPtr[0] = -rx;
        !           972:        pointPtr[1] = 0.0;
        !           973:        numPoints++;
        !           974:        pointPtr += 2;
        !           975:     }
        !           976:     tmp = 270.0 - arcPtr->start;
        !           977:     if (tmp < 0) {
        !           978:        tmp += 360.0;
        !           979:     }
        !           980:     if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) {
        !           981:        pointPtr[0] = 0.0;
        !           982:        pointPtr[1] = ry;
        !           983:        numPoints++;
        !           984:        pointPtr += 2;
        !           985:     }
        !           986: 
        !           987:     /*
        !           988:      * Now that we've located the extreme points, loop through them all
        !           989:      * to see which are inside the rectangle.
        !           990:      */
        !           991: 
        !           992:     inside = (points[0] > tRect[0]) && (points[0] < tRect[2])
        !           993:            && (points[1] > tRect[1]) && (points[1] < tRect[3]);
        !           994:     for (pointPtr = points+2; numPoints > 1; pointPtr += 2, numPoints--) {
        !           995:        newInside = (pointPtr[0] > tRect[0]) && (pointPtr[0] < tRect[2])
        !           996:                && (pointPtr[1] > tRect[1]) && (pointPtr[1] < tRect[3]);
        !           997:        if (newInside != inside) {
        !           998:            return 0;
        !           999:        }
        !          1000:     }
        !          1001: 
        !          1002:     if (inside) {
        !          1003:        return 1;
        !          1004:     }
        !          1005: 
        !          1006:     /*
        !          1007:      * So far, oval appears to be outside rectangle, but can't yet tell
        !          1008:      * for sure.  Next, test each of the four sides of the rectangle
        !          1009:      * against the bounding region for the arc.  If any intersections
        !          1010:      * are found, then return "overlapping".  First, test against the
        !          1011:      * polygon(s) forming the sides of a chord or pie-slice.
        !          1012:      */
        !          1013: 
        !          1014:     if (arcPtr->style == pieSliceUid) {
        !          1015:        if (width >= 1.0) {
        !          1016:            if (TkPolygonToArea(arcPtr->outlinePtr, PIE_OUTLINE1_PTS,
        !          1017:                    rectPtr) != -1)  {
        !          1018:                return 0;
        !          1019:            }
        !          1020:            if (TkPolygonToArea(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS,
        !          1021:                    PIE_OUTLINE2_PTS, rectPtr) != -1) {
        !          1022:                return 0;
        !          1023:            }
        !          1024:        } else {
        !          1025:            if ((TkLineToArea(center, arcPtr->center1, rectPtr) != -1) ||
        !          1026:                    (TkLineToArea(center, arcPtr->center2, rectPtr) != -1)) {
        !          1027:                return 0;
        !          1028:            }
        !          1029:        }
        !          1030:     } else if (arcPtr->style == chordUid) {
        !          1031:        if (width >= 1.0) {
        !          1032:            if (TkPolygonToArea(arcPtr->outlinePtr, CHORD_OUTLINE_PTS,
        !          1033:                    rectPtr) != -1) {
        !          1034:                return 0;
        !          1035:            }
        !          1036:        } else {
        !          1037:            if (TkLineToArea(arcPtr->center1, arcPtr->center2,
        !          1038:                    rectPtr) != -1) {
        !          1039:                return 0;
        !          1040:            }
        !          1041:        }
        !          1042:     }
        !          1043: 
        !          1044:     /*
        !          1045:      * Next check for overlap between each of the four sides and the
        !          1046:      * outer perimiter of the arc.  If the arc isn't filled, then also
        !          1047:      * check the inner perimeter of the arc.
        !          1048:      */
        !          1049: 
        !          1050:     if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
        !          1051:                arcPtr->extent)
        !          1052:            || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
        !          1053:                arcPtr->start, arcPtr->extent)
        !          1054:            || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
        !          1055:                arcPtr->start, arcPtr->extent)
        !          1056:            || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
        !          1057:                arcPtr->start, arcPtr->extent)) {
        !          1058:        return 0;
        !          1059:     }
        !          1060:     if ((width > 1.0) && !filled) {
        !          1061:        rx -= width;
        !          1062:        ry -= width;
        !          1063:        if (HorizLineToArc(tRect[0], tRect[2], tRect[1], rx, ry, arcPtr->start,
        !          1064:                    arcPtr->extent)
        !          1065:                || HorizLineToArc(tRect[0], tRect[2], tRect[3], rx, ry,
        !          1066:                    arcPtr->start, arcPtr->extent)
        !          1067:                || VertLineToArc(tRect[0], tRect[1], tRect[3], rx, ry,
        !          1068:                    arcPtr->start, arcPtr->extent)
        !          1069:                || VertLineToArc(tRect[2], tRect[1], tRect[3], rx, ry,
        !          1070:                    arcPtr->start, arcPtr->extent)) {
        !          1071:            return 0;
        !          1072:        }
        !          1073:     }
        !          1074: 
        !          1075:     /*
        !          1076:      * The arc still appears to be totally disjoint from the rectangle,
        !          1077:      * but it's also possible that the rectangle is totally inside the arc.
        !          1078:      * Do one last check, which is to check one point of the rectangle
        !          1079:      * to see if it's inside the arc.  If it is, we've got overlap.  If
        !          1080:      * it isn't, the arc's really outside the rectangle.
        !          1081:      */
        !          1082: 
        !          1083:     if (ArcToPoint(canvasPtr, itemPtr, rectPtr) == 0.0) {
        !          1084:        return 0;
        !          1085:     }
        !          1086:     return -1;
        !          1087: }
        !          1088: 
        !          1089: /*
        !          1090:  *--------------------------------------------------------------
        !          1091:  *
        !          1092:  * ScaleArc --
        !          1093:  *
        !          1094:  *     This procedure is invoked to rescale an arc item.
        !          1095:  *
        !          1096:  * Results:
        !          1097:  *     None.
        !          1098:  *
        !          1099:  * Side effects:
        !          1100:  *     The arc referred to by itemPtr is rescaled so that the
        !          1101:  *     following transformation is applied to all point
        !          1102:  *     coordinates:
        !          1103:  *             x' = originX + scaleX*(x-originX)
        !          1104:  *             y' = originY + scaleY*(y-originY)
        !          1105:  *
        !          1106:  *--------------------------------------------------------------
        !          1107:  */
        !          1108: 
        !          1109: static void
        !          1110: ScaleArc(canvasPtr, itemPtr, originX, originY, scaleX, scaleY)
        !          1111:     Tk_Canvas *canvasPtr;              /* Canvas containing arc. */
        !          1112:     Tk_Item *itemPtr;                  /* Arc to be scaled. */
        !          1113:     double originX, originY;           /* Origin about which to scale rect. */
        !          1114:     double scaleX;                     /* Amount to scale in X direction. */
        !          1115:     double scaleY;                     /* Amount to scale in Y direction. */
        !          1116: {
        !          1117:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !          1118: 
        !          1119:     arcPtr->bbox[0] = originX + scaleX*(arcPtr->bbox[0] - originX);
        !          1120:     arcPtr->bbox[1] = originY + scaleY*(arcPtr->bbox[1] - originY);
        !          1121:     arcPtr->bbox[2] = originX + scaleX*(arcPtr->bbox[2] - originX);
        !          1122:     arcPtr->bbox[3] = originY + scaleY*(arcPtr->bbox[3] - originY);
        !          1123:     ComputeArcBbox(canvasPtr, arcPtr);
        !          1124: }
        !          1125: 
        !          1126: /*
        !          1127:  *--------------------------------------------------------------
        !          1128:  *
        !          1129:  * TranslateArc --
        !          1130:  *
        !          1131:  *     This procedure is called to move an arc by a given amount.
        !          1132:  *
        !          1133:  * Results:
        !          1134:  *     None.
        !          1135:  *
        !          1136:  * Side effects:
        !          1137:  *     The position of the arc is offset by (xDelta, yDelta), and
        !          1138:  *     the bounding box is updated in the generic part of the item
        !          1139:  *     structure.
        !          1140:  *
        !          1141:  *--------------------------------------------------------------
        !          1142:  */
        !          1143: 
        !          1144: static void
        !          1145: TranslateArc(canvasPtr, itemPtr, deltaX, deltaY)
        !          1146:     Tk_Canvas *canvasPtr;              /* Canvas containing item. */
        !          1147:     Tk_Item *itemPtr;                  /* Item that is being moved. */
        !          1148:     double deltaX, deltaY;             /* Amount by which item is to be
        !          1149:                                         * moved. */
        !          1150: {
        !          1151:     register ArcItem *arcPtr = (ArcItem *) itemPtr;
        !          1152: 
        !          1153:     arcPtr->bbox[0] += deltaX;
        !          1154:     arcPtr->bbox[1] += deltaY;
        !          1155:     arcPtr->bbox[2] += deltaX;
        !          1156:     arcPtr->bbox[3] += deltaY;
        !          1157:     ComputeArcBbox(canvasPtr, arcPtr);
        !          1158: }
        !          1159: 
        !          1160: /*
        !          1161:  *--------------------------------------------------------------
        !          1162:  *
        !          1163:  * ComputeArcOutline --
        !          1164:  *
        !          1165:  *     This procedure creates a polygon describing everything in
        !          1166:  *     the outline for an arc except what's in the curved part.
        !          1167:  *     For a "pie slice" arc this is a V-shaped chunk, and for
        !          1168:  *     a "chord" arc this is a linear chunk (with cutaway corners).
        !          1169:  *     For "arc" arcs, this stuff isn't relevant.
        !          1170:  *
        !          1171:  * Results:
        !          1172:  *     None.
        !          1173:  *
        !          1174:  * Side effects:
        !          1175:  *     The information at arcPtr->outlinePtr gets modified, and
        !          1176:  *     storage for arcPtr->outlinePtr may be allocated or freed.
        !          1177:  *
        !          1178:  *--------------------------------------------------------------
        !          1179:  */
        !          1180: 
        !          1181: static void
        !          1182: ComputeArcOutline(arcPtr)
        !          1183:     register ArcItem *arcPtr;
        !          1184: {
        !          1185:     double sin1, cos1, sin2, cos2, angle, halfWidth;
        !          1186:     double boxWidth, boxHeight;
        !          1187:     double vertex[2], corner1[2], corner2[2];
        !          1188:     double *outlinePtr;
        !          1189: 
        !          1190:     /*
        !          1191:      * Make sure that the outlinePtr array is large enough to hold
        !          1192:      * either a chord or pie-slice outline.
        !          1193:      */
        !          1194: 
        !          1195:     if (arcPtr->numOutlinePoints == 0) {
        !          1196:        arcPtr->outlinePtr = (double *) ckalloc((unsigned)
        !          1197:                (26 * sizeof(double)));
        !          1198:        arcPtr->numOutlinePoints = 22;
        !          1199:     }
        !          1200:     outlinePtr = arcPtr->outlinePtr;
        !          1201: 
        !          1202:     /*
        !          1203:      * First compute the two points that lie at the centers of
        !          1204:      * the ends of the curved arc segment, which are marked with
        !          1205:      * X's in the figure below:
        !          1206:      *
        !          1207:      *
        !          1208:      *                           * * *
        !          1209:      *                       *          *
        !          1210:      *                    *      * *      *
        !          1211:      *                  *    *         *    *
        !          1212:      *                 *   *             *   *
        !          1213:      *                  X *               * X
        !          1214:      *
        !          1215:      * The code is tricky because the arc can be ovular in shape.
        !          1216:      * It computes the position for a unit circle, and then
        !          1217:      * scales to fit the shape of the arc's bounding box.
        !          1218:      *
        !          1219:      * Also, watch out because angles go counter-clockwise like you
        !          1220:      * might expect, but the y-coordinate system is inverted.  To
        !          1221:      * handle this, just negate the angles in all the computations.
        !          1222:      */
        !          1223: 
        !          1224:     boxWidth = arcPtr->bbox[2] - arcPtr->bbox[0];
        !          1225:     boxHeight = arcPtr->bbox[3] - arcPtr->bbox[1];
        !          1226:     angle = -arcPtr->start*PI/180.0;
        !          1227:     sin1 = sin(angle);
        !          1228:     cos1 = cos(angle);
        !          1229:     angle -= arcPtr->extent*PI/180.0;
        !          1230:     sin2 = sin(angle);
        !          1231:     cos2 = cos(angle);
        !          1232:     vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0;
        !          1233:     vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0;
        !          1234:     arcPtr->center1[0] = vertex[0] + cos1*boxWidth/2.0;
        !          1235:     arcPtr->center1[1] = vertex[1] + sin1*boxHeight/2.0;
        !          1236:     arcPtr->center2[0] = vertex[0] + cos2*boxWidth/2.0;
        !          1237:     arcPtr->center2[1] = vertex[1] + sin2*boxHeight/2.0;
        !          1238: 
        !          1239:     /*
        !          1240:      * Next compute the "outermost corners" of the arc, which are
        !          1241:      * marked with X's in the figure below:
        !          1242:      *
        !          1243:      *                           * * *
        !          1244:      *                       *          *
        !          1245:      *                    *      * *      *
        !          1246:      *                  *    *         *    *
        !          1247:      *                 X   *             *   X
        !          1248:      *                    *               *
        !          1249:      *
        !          1250:      * The code below is tricky because it has to handle eccentricity
        !          1251:      * in the shape of the oval.  The key in the code below is to
        !          1252:      * realize that the slope of the line from arcPtr->center1 to corner1
        !          1253:      * is (boxWidth*sin1)/(boxHeight*cos1), and similarly for arcPtr->center2
        !          1254:      * and corner2.  These formulas can be computed from the formula for
        !          1255:      * the oval.
        !          1256:      */
        !          1257: 
        !          1258:     halfWidth = arcPtr->width/2.0;
        !          1259:     angle = atan2(boxWidth*sin1, boxHeight*cos1);
        !          1260:     corner1[0] = arcPtr->center1[0] + cos(angle)*halfWidth;
        !          1261:     corner1[1] = arcPtr->center1[1] + sin(angle)*halfWidth;
        !          1262:     angle = atan2(boxWidth*sin2, boxHeight*cos2);
        !          1263:     corner2[0] = arcPtr->center2[0] + cos(angle)*halfWidth;
        !          1264:     corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth;
        !          1265: 
        !          1266:     /*
        !          1267:      * For a chord outline, generate a six-sided polygon with three
        !          1268:      * points for each end of the chord.  The first and third points
        !          1269:      * for each end are butt points generated on either side of the
        !          1270:      * center point.  The second point is the corner point.
        !          1271:      */
        !          1272: 
        !          1273:     if (arcPtr->style == chordUid) {
        !          1274:        outlinePtr[0] = outlinePtr[12] = corner1[0];
        !          1275:        outlinePtr[1] = outlinePtr[13] = corner1[1];
        !          1276:        TkGetButtPoints(arcPtr->center2, arcPtr->center1,
        !          1277:                (double) arcPtr->width, 0, outlinePtr+10, outlinePtr+2);
        !          1278:        outlinePtr[4] = arcPtr->center2[0] + outlinePtr[2]
        !          1279:                - arcPtr->center1[0];
        !          1280:        outlinePtr[5] = arcPtr->center2[1] + outlinePtr[3]
        !          1281:                - arcPtr->center1[1];
        !          1282:        outlinePtr[6] = corner2[0];
        !          1283:        outlinePtr[7] = corner2[1];
        !          1284:        outlinePtr[8] = arcPtr->center2[0] + outlinePtr[10]
        !          1285:                - arcPtr->center1[0];
        !          1286:        outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11]
        !          1287:                - arcPtr->center1[1];
        !          1288:     } else if (arcPtr->style == pieSliceUid) {
        !          1289:        /*
        !          1290:         * For pie slices, generate two polygons, one for each side
        !          1291:         * of the pie slice.  The first arm has a shape like this,
        !          1292:         * where the center of the oval is X, arcPtr->center1 is at Y, and
        !          1293:         * corner1 is at Z:
        !          1294:         *
        !          1295:         *       _____________________
        !          1296:         *      |                     \
        !          1297:         *      |                      \
        !          1298:         *      X                    Y  Z
        !          1299:         *      |                      /
        !          1300:         *      |_____________________/
        !          1301:         *
        !          1302:         */
        !          1303: 
        !          1304:        TkGetButtPoints(arcPtr->center1, vertex, (double) arcPtr->width, 0,
        !          1305:                outlinePtr, outlinePtr+2);
        !          1306:        outlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0];
        !          1307:        outlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1];
        !          1308:        outlinePtr[6] = corner1[0];
        !          1309:        outlinePtr[7] = corner1[1];
        !          1310:        outlinePtr[8] = arcPtr->center1[0] + outlinePtr[0] - vertex[0];
        !          1311:        outlinePtr[9] = arcPtr->center1[1] + outlinePtr[1] - vertex[1];
        !          1312:        outlinePtr[10] = outlinePtr[0];
        !          1313:        outlinePtr[11] = outlinePtr[1];
        !          1314: 
        !          1315:        /*
        !          1316:         * The second arm has a shape like this:
        !          1317:         *
        !          1318:         *
        !          1319:         *         ______________________
        !          1320:         *        /                       \
        !          1321:         *       /                         \
        !          1322:         *      Z  Y                    X  /
        !          1323:         *       \                        /
        !          1324:         *        \______________________/
        !          1325:         *
        !          1326:         * Similar to above X is the center of the oval/circle, Y is
        !          1327:         * arcPtr->center2, and Z is corner2.  The extra jog out to the left
        !          1328:         * of X is needed in or to produce a butted joint with the
        !          1329:         * first arm;  the corner to the right of X is one of the
        !          1330:         * first two points of the first arm, depending on extent.
        !          1331:         */
        !          1332: 
        !          1333:        TkGetButtPoints(arcPtr->center2, vertex, (double) arcPtr->width, 0,
        !          1334:                outlinePtr+12, outlinePtr+16);
        !          1335:        if ((arcPtr->extent > 180) ||
        !          1336:                ((arcPtr->extent < 0) && (arcPtr->extent > -180))) {
        !          1337:            outlinePtr[14] = outlinePtr[0];
        !          1338:            outlinePtr[15] = outlinePtr[1];
        !          1339:        } else {
        !          1340:            outlinePtr[14] = outlinePtr[2];
        !          1341:            outlinePtr[15] = outlinePtr[3];
        !          1342:        }
        !          1343:        outlinePtr[18] = arcPtr->center2[0] + outlinePtr[16] - vertex[0];
        !          1344:        outlinePtr[19] = arcPtr->center2[1] + outlinePtr[17] - vertex[1];
        !          1345:        outlinePtr[20] = corner2[0];
        !          1346:        outlinePtr[21] = corner2[1];
        !          1347:        outlinePtr[22] = arcPtr->center2[0] + outlinePtr[12] - vertex[0];
        !          1348:        outlinePtr[23] = arcPtr->center2[1] + outlinePtr[13] - vertex[1];
        !          1349:        outlinePtr[24] = outlinePtr[12];
        !          1350:        outlinePtr[25] = outlinePtr[13];
        !          1351:     }
        !          1352: }
        !          1353: 
        !          1354: /*
        !          1355:  *--------------------------------------------------------------
        !          1356:  *
        !          1357:  * HorizLineToArc --
        !          1358:  *
        !          1359:  *     Determines whether a horizontal line segment intersects
        !          1360:  *     a given arc.
        !          1361:  *
        !          1362:  * Results:
        !          1363:  *     The return value is 1 if the given line intersects the
        !          1364:  *     infinitely-thin arc section defined by rx, ry, start,
        !          1365:  *     and extent, and 0 otherwise.  Only the perimeter of the
        !          1366:  *     arc is checked: interior areas (e.g. pie-slice or chord)
        !          1367:  *     are not checked.
        !          1368:  *
        !          1369:  * Side effects:
        !          1370:  *     None.
        !          1371:  *
        !          1372:  *--------------------------------------------------------------
        !          1373:  */
        !          1374: 
        !          1375: static int
        !          1376: HorizLineToArc(x1, x2, y, rx, ry, start, extent)
        !          1377:     double x1, x2;             /* X-coords of endpoints of line segment. 
        !          1378:                                 * X1 must be <= x2. */
        !          1379:     double y;                  /* Y-coordinate of line segment. */
        !          1380:     double rx, ry;             /* These x- and y-radii define an oval
        !          1381:                                 * centered at the origin. */
        !          1382:     double start, extent;      /* Angles that define extent of arc, in
        !          1383:                                 * the standard fashion for this module. */
        !          1384: {
        !          1385:     double tmp;
        !          1386:     double tx, ty;             /* Coordinates of intersection point in
        !          1387:                                 * transformed coordinate system. */
        !          1388:     double x;
        !          1389: 
        !          1390:     /*
        !          1391:      * Compute the x-coordinate of one possible intersection point
        !          1392:      * between the arc and the line.  Use a transformed coordinate
        !          1393:      * system where the oval is a unit circle centered at the origin.
        !          1394:      * Then scale back to get actual x-coordinate.
        !          1395:      */
        !          1396: 
        !          1397:     ty = y/ry;
        !          1398:     tmp = 1 - ty*ty;
        !          1399:     if (tmp < 0) {
        !          1400:        return 0;
        !          1401:     }
        !          1402:     tx = sqrt(tmp);
        !          1403:     x = tx*rx;
        !          1404: 
        !          1405:     /*
        !          1406:      * Test both intersection points.
        !          1407:      */
        !          1408: 
        !          1409:     if ((x >= x1) && (x <= x2) && AngleInRange(tx, ty, start, extent)) {
        !          1410:        return 1;
        !          1411:     }
        !          1412:     if ((-x >= x1) && (-x <= x2) && AngleInRange(-tx, ty, start, extent)) {
        !          1413:        return 1;
        !          1414:     }
        !          1415:     return 0;
        !          1416: }
        !          1417: 
        !          1418: /*
        !          1419:  *--------------------------------------------------------------
        !          1420:  *
        !          1421:  * VertLineToArc --
        !          1422:  *
        !          1423:  *     Determines whether a vertical line segment intersects
        !          1424:  *     a given arc.
        !          1425:  *
        !          1426:  * Results:
        !          1427:  *     The return value is 1 if the given line intersects the
        !          1428:  *     infinitely-thin arc section defined by rx, ry, start,
        !          1429:  *     and extent, and 0 otherwise.  Only the perimeter of the
        !          1430:  *     arc is checked: interior areas (e.g. pie-slice or chord)
        !          1431:  *     are not checked.
        !          1432:  *
        !          1433:  * Side effects:
        !          1434:  *     None.
        !          1435:  *
        !          1436:  *--------------------------------------------------------------
        !          1437:  */
        !          1438: 
        !          1439: static int
        !          1440: VertLineToArc(x, y1, y2, rx, ry, start, extent)
        !          1441:     double x;                  /* X-coordinate of line segment. */
        !          1442:     double y1, y2;             /* Y-coords of endpoints of line segment. 
        !          1443:                                 * Y1 must be <= y2. */
        !          1444:     double rx, ry;             /* These x- and y-radii define an oval
        !          1445:                                 * centered at the origin. */
        !          1446:     double start, extent;      /* Angles that define extent of arc, in
        !          1447:                                 * the standard fashion for this module. */
        !          1448: {
        !          1449:     double tmp;
        !          1450:     double tx, ty;             /* Coordinates of intersection point in
        !          1451:                                 * transformed coordinate system. */
        !          1452:     double y;
        !          1453: 
        !          1454:     /*
        !          1455:      * Compute the y-coordinate of one possible intersection point
        !          1456:      * between the arc and the line.  Use a transformed coordinate
        !          1457:      * system where the oval is a unit circle centered at the origin.
        !          1458:      * Then scale back to get actual y-coordinate.
        !          1459:      */
        !          1460: 
        !          1461:     tx = x/rx;
        !          1462:     tmp = 1 - tx*tx;
        !          1463:     if (tmp < 0) {
        !          1464:        return 0;
        !          1465:     }
        !          1466:     ty = sqrt(tmp);
        !          1467:     y = ty*ry;
        !          1468: 
        !          1469:     /*
        !          1470:      * Test both intersection points.
        !          1471:      */
        !          1472: 
        !          1473:     if ((y > y1) && (y < y2) && AngleInRange(tx, ty, start, extent)) {
        !          1474:        return 1;
        !          1475:     }
        !          1476:     if ((-y > y1) && (-y < y2) && AngleInRange(tx, -ty, start, extent)) {
        !          1477:        return 1;
        !          1478:     }
        !          1479:     return 0;
        !          1480: }
        !          1481: 
        !          1482: /*
        !          1483:  *--------------------------------------------------------------
        !          1484:  *
        !          1485:  * AngleInRange --
        !          1486:  *
        !          1487:  *     Determine whether the angle from the origin to a given
        !          1488:  *     point is within a given range.
        !          1489:  *
        !          1490:  * Results:
        !          1491:  *     The return value is 1 if the angle from (0,0) to (x,y)
        !          1492:  *     is in the range given by start and extent, where angles
        !          1493:  *     are interpreted in the standard way for ovals (meaning
        !          1494:  *     backwards from normal interpretation).  Otherwise the
        !          1495:  *     return value is 0.
        !          1496:  *
        !          1497:  * Side effects:
        !          1498:  *     None.
        !          1499:  *
        !          1500:  *--------------------------------------------------------------
        !          1501:  */
        !          1502: 
        !          1503: static int
        !          1504: AngleInRange(x, y, start, extent)
        !          1505:     double x, y;               /* Coordinate of point;  angle measured
        !          1506:                                 * from origin to here, relative to x-axis. */
        !          1507:     double start;              /* First angle, degrees, >=0, <=360. */
        !          1508:     double extent;             /* Size of arc in degrees >=-360, <=360. */
        !          1509: {
        !          1510:     double diff;
        !          1511: 
        !          1512:     diff = -atan2(y, x);
        !          1513:     diff = diff*(180.0/PI) - start;
        !          1514:     while (diff > 360.0) {
        !          1515:        diff -= 360.0;
        !          1516:     }
        !          1517:     while (diff < 0.0) {
        !          1518:        diff += 360.0;
        !          1519:     }
        !          1520:     if (extent >= 0) {
        !          1521:        return diff <= extent;
        !          1522:     }
        !          1523:     return (diff-360.0) >= extent;
        !          1524: }

unix.superglobalmegacorp.com

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