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

1.1     ! root        1: /* 
        !             2:  * tkCanvPoly.c --
        !             3:  *
        !             4:  *     This file implements polygon items for canvas widgets.
        !             5:  *
        !             6:  * Copyright 1991-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/tkCanvPoly.c,v 1.6 92/07/28 15:40:10 ouster Exp $ SPRITE (Berkeley)";
        !            18: #endif
        !            19: 
        !            20: #include <stdio.h>
        !            21: #include <math.h>
        !            22: #include "tkint.h"
        !            23: #include "tkcanvas.h"
        !            24: #include "tkconfig.h"
        !            25: 
        !            26: /*
        !            27:  * The structure below defines the record for each polygon item.
        !            28:  */
        !            29: 
        !            30: typedef struct PolygonItem  {
        !            31:     Tk_Item header;            /* Generic stuff that's the same for all
        !            32:                                 * types.  MUST BE FIRST IN STRUCTURE. */
        !            33:     int numPoints;             /* Number of points in polygon (always >= 3).
        !            34:                                 * Polygon is always closed. */
        !            35:     double *coordPtr;          /* Pointer to malloc-ed array containing
        !            36:                                 * x- and y-coords of all points in polygon.
        !            37:                                 * X-coords are even-valued indices, y-coords
        !            38:                                 * are corresponding odd-valued indices. */
        !            39:     XColor *fg;                        /* Foreground color for polygon. */
        !            40:     Pixmap fillStipple;                /* Stipple bitmap for filling polygon. */
        !            41:     GC gc;                     /* Graphics context for filling polygon. */
        !            42:     int smooth;                        /* Non-zero means draw shape smoothed (i.e.
        !            43:                                 * with Bezier splines). */
        !            44:     int splineSteps;           /* Number of steps in each spline segment. */
        !            45: } PolygonItem;
        !            46: 
        !            47: /*
        !            48:  * Information used for parsing configuration specs:
        !            49:  */
        !            50: 
        !            51: static Tk_ConfigSpec configSpecs[] = {
        !            52:     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
        !            53:        "black", Tk_Offset(PolygonItem, fg), TK_CONFIG_NULL_OK},
        !            54:     {TK_CONFIG_BOOLEAN, "-smooth", (char *) NULL, (char *) NULL,
        !            55:        "no", Tk_Offset(PolygonItem, smooth), TK_CONFIG_DONT_SET_DEFAULT},
        !            56:     {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
        !            57:        "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
        !            58:     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
        !            59:        (char *) NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK},
        !            60:     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
        !            61:        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tkCanvasTagsOption},
        !            62:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
        !            63:        (char *) NULL, 0, 0}
        !            64: };
        !            65: 
        !            66: /*
        !            67:  * Prototypes for procedures defined in this file:
        !            68:  */
        !            69: 
        !            70: static void            ComputePolygonBbox _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            71:                            PolygonItem *polyPtr));
        !            72: static int             ConfigurePolygon _ANSI_ARGS_((
        !            73:                            Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int argc,
        !            74:                            char **argv, int flags));
        !            75: static int             CreatePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            76:                            struct Tk_Item *itemPtr, int argc, char **argv));
        !            77: static void            DeletePolygon _ANSI_ARGS_((Tk_Item *itemPtr));
        !            78: static void            DisplayPolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            79:                            Tk_Item *itemPtr, Drawable dst));
        !            80: static int             PolygonCoords _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            81:                            Tk_Item *itemPtr, int argc, char **argv));
        !            82: static int             PolygonToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            83:                            Tk_Item *itemPtr, double *rectPtr));
        !            84: static double          PolygonToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            85:                            Tk_Item *itemPtr, double *pointPtr));
        !            86: static void            ScalePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            87:                            Tk_Item *itemPtr, double originX, double originY,
        !            88:                            double scaleX, double scaleY));
        !            89: static void            TranslatePolygon _ANSI_ARGS_((Tk_Canvas *canvasPtr,
        !            90:                            Tk_Item *itemPtr, double deltaX, double deltaY));
        !            91: 
        !            92: /*
        !            93:  * The structures below defines the polygon item type by means
        !            94:  * of procedures that can be invoked by generic item code.
        !            95:  */
        !            96: 
        !            97: Tk_ItemType TkPolygonType = {
        !            98:     "polygon",                         /* name */
        !            99:     sizeof(PolygonItem),               /* itemSize */
        !           100:     CreatePolygon,                     /* createProc */
        !           101:     configSpecs,                       /* configSpecs */
        !           102:     ConfigurePolygon,                  /* configureProc */
        !           103:     PolygonCoords,                     /* coordProc */
        !           104:     DeletePolygon,                     /* deleteProc */
        !           105:     DisplayPolygon,                    /* displayProc */
        !           106:     0,                                 /* alwaysRedraw */
        !           107:     PolygonToPoint,                    /* pointProc */
        !           108:     PolygonToArea,                     /* areaProc */
        !           109:     (Tk_ItemPostscriptProc *) NULL,    /* postscriptProc */
        !           110:     ScalePolygon,                      /* scaleProc */
        !           111:     TranslatePolygon,                  /* translateProc */
        !           112:     (Tk_ItemIndexProc *) NULL,         /* indexProc */
        !           113:     (Tk_ItemCursorProc *) NULL,                /* cursorProc */
        !           114:     (Tk_ItemSelectionProc *) NULL,     /* selectionProc */
        !           115:     (Tk_ItemInsertProc *) NULL,                /* insertProc */
        !           116:     (Tk_ItemDCharsProc *) NULL,                /* dTextProc */
        !           117:     (Tk_ItemType *) NULL               /* nextPtr */
        !           118: };
        !           119: 
        !           120: /*
        !           121:  * The definition below determines how large are static arrays
        !           122:  * used to hold spline points (splines larger than this have to
        !           123:  * have their arrays malloc-ed).
        !           124:  */
        !           125: 
        !           126: #define MAX_STATIC_POINTS 200
        !           127: 
        !           128: /*
        !           129:  *--------------------------------------------------------------
        !           130:  *
        !           131:  * CreatePolygon --
        !           132:  *
        !           133:  *     This procedure is invoked to create a new polygon item in
        !           134:  *     a canvas.
        !           135:  *
        !           136:  * Results:
        !           137:  *     A standard Tcl return value.  If an error occurred in
        !           138:  *     creating the item, then an error message is left in
        !           139:  *     canvasPtr->interp->result;  in this case itemPtr is
        !           140:  *     left uninitialized, so it can be safely freed by the
        !           141:  *     caller.
        !           142:  *
        !           143:  * Side effects:
        !           144:  *     A new polygon item is created.
        !           145:  *
        !           146:  *--------------------------------------------------------------
        !           147:  */
        !           148: 
        !           149: static int
        !           150: CreatePolygon(canvasPtr, itemPtr, argc, argv)
        !           151:     register Tk_Canvas *canvasPtr;     /* Canvas to hold new item. */
        !           152:     Tk_Item *itemPtr;                  /* Record to hold new item;  header
        !           153:                                         * has been initialized by caller. */
        !           154:     int argc;                          /* Number of arguments in argv. */
        !           155:     char **argv;                       /* Arguments describing polygon. */
        !           156: {
        !           157:     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           158:     int i;
        !           159: 
        !           160:     if (argc < 6) {
        !           161:        Tcl_AppendResult(canvasPtr->interp, "wrong # args:  should be \"",
        !           162:                Tk_PathName(canvasPtr->tkwin),
        !           163:                "\" create x1 y1 x2 y2 x3 y3 ?x4 y4 ...? ?options?",
        !           164:                (char *) NULL);
        !           165:        return TCL_ERROR;
        !           166:     }
        !           167: 
        !           168:     /*
        !           169:      * Carry out initialization that is needed in order to clean
        !           170:      * up after errors during the the remainder of this procedure.
        !           171:      */
        !           172: 
        !           173:     polyPtr->numPoints = 0;
        !           174:     polyPtr->coordPtr = NULL;
        !           175:     polyPtr->fg = None;
        !           176:     polyPtr->fillStipple = None;
        !           177:     polyPtr->gc = None;
        !           178:     polyPtr->smooth = 0;
        !           179:     polyPtr->splineSteps = 12;
        !           180: 
        !           181:     /*
        !           182:      * Count the number of points and then parse them into a point
        !           183:      * array.  Leading arguments are assumed to be points if they
        !           184:      * start with a digit or a minus sign followed by a digit.
        !           185:      */
        !           186: 
        !           187:     for (i = 4; i < (argc-1); i+=2) {
        !           188:        if ((!isdigit(argv[i][0])) &&
        !           189:                ((argv[i][0] != '-') || (!isdigit(argv[i][1])))) {
        !           190:            break;
        !           191:        }
        !           192:     }
        !           193:     if (PolygonCoords(canvasPtr, itemPtr, i, argv) != TCL_OK) {
        !           194:        goto error;
        !           195:     }
        !           196: 
        !           197:     if (ConfigurePolygon(canvasPtr, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
        !           198:        return TCL_OK;
        !           199:     }
        !           200: 
        !           201:     error:
        !           202:     DeletePolygon(itemPtr);
        !           203:     return TCL_ERROR;
        !           204: }
        !           205: 
        !           206: /*
        !           207:  *--------------------------------------------------------------
        !           208:  *
        !           209:  * PolygonCoords --
        !           210:  *
        !           211:  *     This procedure is invoked to process the "coords" widget
        !           212:  *     command on polygons.  See the user documentation for details
        !           213:  *     on what it does.
        !           214:  *
        !           215:  * Results:
        !           216:  *     Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
        !           217:  *
        !           218:  * Side effects:
        !           219:  *     The coordinates for the given item may be changed.
        !           220:  *
        !           221:  *--------------------------------------------------------------
        !           222:  */
        !           223: 
        !           224: static int
        !           225: PolygonCoords(canvasPtr, itemPtr, argc, argv)
        !           226:     register Tk_Canvas *canvasPtr;     /* Canvas containing item. */
        !           227:     Tk_Item *itemPtr;                  /* Item whose coordinates are to be
        !           228:                                         * read or modified. */
        !           229:     int argc;                          /* Number of coordinates supplied in
        !           230:                                         * argv. */
        !           231:     char **argv;                       /* Array of coordinates: x1, y1,
        !           232:                                         * x2, y2, ... */
        !           233: {
        !           234:     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           235:     char buffer[300];
        !           236:     int i, numPoints;
        !           237: 
        !           238:     if (argc == 0) {
        !           239:        for (i = 0; i < 2*polyPtr->numPoints; i++) {
        !           240:            sprintf(buffer, "%g", polyPtr->coordPtr[i]);
        !           241:            Tcl_AppendElement(canvasPtr->interp, buffer, 0);
        !           242:        }
        !           243:     } else if (argc < 6) {
        !           244:        Tcl_AppendResult(canvasPtr->interp,
        !           245:                "too few coordinates for polygon:  must have at least 6",
        !           246:                (char *) NULL);
        !           247:        return TCL_ERROR;
        !           248:     } else if (argc & 1) {
        !           249:        Tcl_AppendResult(canvasPtr->interp,
        !           250:                "odd number of coordinates specified for polygon",
        !           251:                (char *) NULL);
        !           252:        return TCL_ERROR;
        !           253:     } else {
        !           254:        numPoints = argc/2;
        !           255:        if (polyPtr->numPoints != numPoints) {
        !           256:            if (polyPtr->coordPtr != NULL) {
        !           257:                ckfree((char *) polyPtr->coordPtr);
        !           258:            }
        !           259: 
        !           260:            /*
        !           261:             * One extra point gets allocated here, just in case we have
        !           262:             * to add another point to close the polygon.
        !           263:             */
        !           264: 
        !           265:            polyPtr->coordPtr = (double *) ckalloc((unsigned)
        !           266:                    (sizeof(double) * (argc+2)));
        !           267:            polyPtr->numPoints = numPoints;
        !           268:        }
        !           269:        for (i = argc-1; i >= 0; i--) {
        !           270:            if (TkGetCanvasCoord(canvasPtr, argv[i], &polyPtr->coordPtr[i])
        !           271:                    != TCL_OK) {
        !           272:                return TCL_ERROR;
        !           273:            }
        !           274:        }
        !           275:     
        !           276:        /*
        !           277:         * Close the polygon if it isn't already closed.
        !           278:         */
        !           279:     
        !           280:        if ((polyPtr->coordPtr[argc-2] != polyPtr->coordPtr[0])
        !           281:                || (polyPtr->coordPtr[argc-1] != polyPtr->coordPtr[1])) {
        !           282:            polyPtr->numPoints++;
        !           283:            polyPtr->coordPtr[argc] = polyPtr->coordPtr[0];
        !           284:            polyPtr->coordPtr[argc+1] = polyPtr->coordPtr[1];
        !           285:        }
        !           286:        ComputePolygonBbox(canvasPtr, polyPtr);
        !           287:     }
        !           288:     return TCL_OK;
        !           289: }
        !           290: 
        !           291: /*
        !           292:  *--------------------------------------------------------------
        !           293:  *
        !           294:  * ConfigurePolygon --
        !           295:  *
        !           296:  *     This procedure is invoked to configure various aspects
        !           297:  *     of a polygon item such as its background color.
        !           298:  *
        !           299:  * Results:
        !           300:  *     A standard Tcl result code.  If an error occurs, then
        !           301:  *     an error message is left in canvasPtr->interp->result.
        !           302:  *
        !           303:  * Side effects:
        !           304:  *     Configuration information, such as colors and stipple
        !           305:  *     patterns, may be set for itemPtr.
        !           306:  *
        !           307:  *--------------------------------------------------------------
        !           308:  */
        !           309: 
        !           310: static int
        !           311: ConfigurePolygon(canvasPtr, itemPtr, argc, argv, flags)
        !           312:     Tk_Canvas *canvasPtr;      /* Canvas containing itemPtr. */
        !           313:     Tk_Item *itemPtr;          /* Polygon item to reconfigure. */
        !           314:     int argc;                  /* Number of elements in argv.  */
        !           315:     char **argv;               /* Arguments describing things to configure. */
        !           316:     int flags;                 /* Flags to pass to Tk_ConfigureWidget. */
        !           317: {
        !           318:     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           319:     XGCValues gcValues;
        !           320:     GC newGC;
        !           321:     unsigned long mask;
        !           322: 
        !           323:     if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
        !           324:            configSpecs, argc, argv, (char *) polyPtr, flags) != TCL_OK) {
        !           325:        return TCL_ERROR;
        !           326:     }
        !           327: 
        !           328:     /*
        !           329:      * A few of the options require additional processing, such as
        !           330:      * graphics contexts.
        !           331:      */
        !           332: 
        !           333:     if (polyPtr->fg == NULL) {
        !           334:        newGC = None;
        !           335:     } else {
        !           336:        gcValues.foreground = polyPtr->fg->pixel;
        !           337:        mask = GCForeground;
        !           338:        if (polyPtr->fillStipple != None) {
        !           339:            gcValues.stipple = polyPtr->fillStipple;
        !           340:            gcValues.fill_style = FillStippled;
        !           341:            mask |= GCStipple|GCFillStyle;
        !           342:        }
        !           343:        newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
        !           344:     }
        !           345:     if (polyPtr->gc != None) {
        !           346:        Tk_FreeGC(polyPtr->gc);
        !           347:     }
        !           348:     polyPtr->gc = newGC;
        !           349: 
        !           350:     /*
        !           351:      * Keep spline parameters within reasonable limits.
        !           352:      */
        !           353: 
        !           354:     if (polyPtr->splineSteps < 1) {
        !           355:        polyPtr->splineSteps = 1;
        !           356:     } else if (polyPtr->splineSteps > 100) {
        !           357:        polyPtr->splineSteps = 100;
        !           358:     }
        !           359: 
        !           360:     ComputePolygonBbox(canvasPtr, polyPtr);
        !           361:     return TCL_OK;
        !           362: }
        !           363: 
        !           364: /*
        !           365:  *--------------------------------------------------------------
        !           366:  *
        !           367:  * DeletePolygon --
        !           368:  *
        !           369:  *     This procedure is called to clean up the data structure
        !           370:  *     associated with a polygon item.
        !           371:  *
        !           372:  * Results:
        !           373:  *     None.
        !           374:  *
        !           375:  * Side effects:
        !           376:  *     Resources associated with itemPtr are released.
        !           377:  *
        !           378:  *--------------------------------------------------------------
        !           379:  */
        !           380: 
        !           381: static void
        !           382: DeletePolygon(itemPtr)
        !           383:     Tk_Item *itemPtr;                  /* Item that is being deleted. */
        !           384: {
        !           385:     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           386: 
        !           387:     if (polyPtr->coordPtr != NULL) {
        !           388:        ckfree((char *) polyPtr->coordPtr);
        !           389:     }
        !           390:     if (polyPtr->fg != NULL) {
        !           391:        Tk_FreeColor(polyPtr->fg);
        !           392:     }
        !           393:     if (polyPtr->fillStipple != None) {
        !           394:        Tk_FreeBitmap(polyPtr->fillStipple);
        !           395:     }
        !           396:     if (polyPtr->gc != None) {
        !           397:        Tk_FreeGC(polyPtr->gc);
        !           398:     }
        !           399: }
        !           400: 
        !           401: /*
        !           402:  *--------------------------------------------------------------
        !           403:  *
        !           404:  * ComputePolygonBbox --
        !           405:  *
        !           406:  *     This procedure is invoked to compute the bounding box of
        !           407:  *     all the pixels that may be drawn as part of a polygon.
        !           408:  *
        !           409:  * Results:
        !           410:  *     None.
        !           411:  *
        !           412:  * Side effects:
        !           413:  *     The fields x1, y1, x2, and y2 are updated in the header
        !           414:  *     for itemPtr.
        !           415:  *
        !           416:  *--------------------------------------------------------------
        !           417:  */
        !           418: 
        !           419: static void
        !           420: ComputePolygonBbox(canvasPtr, polyPtr)
        !           421:     register Tk_Canvas *canvasPtr;     /* Canvas that contains item. */
        !           422:     PolygonItem *polyPtr;              /* Item whose bbox is to be
        !           423:                                         * recomputed. */
        !           424: {
        !           425:     register double *coordPtr;
        !           426:     int i;
        !           427: 
        !           428:     coordPtr = polyPtr->coordPtr;
        !           429:     polyPtr->header.x1 = polyPtr->header.x2 = *coordPtr;
        !           430:     polyPtr->header.y1 = polyPtr->header.y2 = coordPtr[1];
        !           431: 
        !           432:     for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints;
        !           433:            i++, coordPtr += 2) {
        !           434:        TkIncludePoint(canvasPtr, (Tk_Item *) polyPtr, coordPtr);
        !           435:     }
        !           436: 
        !           437:     /*
        !           438:      * Add one more pixel of fudge factor just to be safe (e.g.
        !           439:      * X may round differently than we do).
        !           440:      */
        !           441: 
        !           442:     polyPtr->header.x1 -= 1;
        !           443:     polyPtr->header.x2 += 1;
        !           444:     polyPtr->header.y1 -= 1;
        !           445:     polyPtr->header.y2 += 1;
        !           446: }
        !           447: 
        !           448: /*
        !           449:  *--------------------------------------------------------------
        !           450:  *
        !           451:  * TkFillPolygon --
        !           452:  *
        !           453:  *     This procedure is invoked to convert a polygon to screen
        !           454:  *     coordinates and display it using a particular GC.
        !           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: void
        !           467: TkFillPolygon(canvasPtr, coordPtr, numPoints, drawable, gc)
        !           468:     register Tk_Canvas *canvasPtr;     /* Canvas whose coordinate system
        !           469:                                         * is to be used for drawing. */
        !           470:     double *coordPtr;                  /* Array of coordinates for polygon:
        !           471:                                         * x1, y1, x2, y2, .... */
        !           472:     int numPoints;                     /* Twice this many coordinates are
        !           473:                                         * present at *coordPtr. */
        !           474:     Drawable drawable;                 /* Pixmap or window in which to draw
        !           475:                                         * polygon. */
        !           476:     GC gc;                             /* Graphics context for drawing. */
        !           477: {
        !           478:     XPoint staticPoints[MAX_STATIC_POINTS];
        !           479:     XPoint *pointPtr;
        !           480:     register XPoint *pPtr;
        !           481:     int i;
        !           482: 
        !           483:     /*
        !           484:      * Build up an array of points in screen coordinates.  Use a
        !           485:      * static array unless the polygon has an enormous number of points;
        !           486:      * in this case, dynamically allocate an array.
        !           487:      */
        !           488: 
        !           489:     if (numPoints <= MAX_STATIC_POINTS) {
        !           490:        pointPtr = staticPoints;
        !           491:     } else {
        !           492:        pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));
        !           493:     }
        !           494: 
        !           495:     for (i = 0, pPtr = pointPtr; i < numPoints; i += 1, coordPtr += 2, pPtr++) {
        !           496:        pPtr->x = SCREEN_X(canvasPtr, coordPtr[0]);
        !           497:        pPtr->y = SCREEN_Y(canvasPtr, coordPtr[1]);
        !           498:     }
        !           499: 
        !           500:     /*
        !           501:      * Display polygon, then free up polygon storage if it was dynamically
        !           502:      * allocated.
        !           503:      */
        !           504: 
        !           505:     XFillPolygon(Tk_Display(canvasPtr->tkwin), drawable, gc, pointPtr,
        !           506:            numPoints, Complex, CoordModeOrigin);
        !           507:     if (pointPtr != staticPoints) {
        !           508:        ckfree((char *) pointPtr);
        !           509:     }
        !           510: 
        !           511: }
        !           512: 
        !           513: /*
        !           514:  *--------------------------------------------------------------
        !           515:  *
        !           516:  * DisplayPolygon --
        !           517:  *
        !           518:  *     This procedure is invoked to draw a polygon item in a given
        !           519:  *     drawable.
        !           520:  *
        !           521:  * Results:
        !           522:  *     None.
        !           523:  *
        !           524:  * Side effects:
        !           525:  *     ItemPtr is drawn in drawable using the transformation
        !           526:  *     information in canvasPtr.
        !           527:  *
        !           528:  *--------------------------------------------------------------
        !           529:  */
        !           530: 
        !           531: static void
        !           532: DisplayPolygon(canvasPtr, itemPtr, drawable)
        !           533:     register Tk_Canvas *canvasPtr;     /* Canvas that contains item. */
        !           534:     Tk_Item *itemPtr;                  /* Item to be displayed. */
        !           535:     Drawable drawable;                 /* Pixmap or window in which to draw
        !           536:                                         * item. */
        !           537: {
        !           538:     register PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           539: 
        !           540:     if (polyPtr->gc == None) {
        !           541:        return;
        !           542:     }
        !           543: 
        !           544:     if (!polyPtr->smooth) {
        !           545:        TkFillPolygon(canvasPtr, polyPtr->coordPtr, polyPtr->numPoints,
        !           546:                drawable, polyPtr->gc);
        !           547:     } else {
        !           548:        int numPoints;
        !           549:        XPoint staticPoints[MAX_STATIC_POINTS];
        !           550:        XPoint *pointPtr;
        !           551: 
        !           552:        /*
        !           553:         * This is a smoothed polygon.  Display using a set of generated
        !           554:         * spline points rather than the original points.
        !           555:         */
        !           556: 
        !           557:        numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
        !           558:        if (numPoints <= MAX_STATIC_POINTS) {
        !           559:            pointPtr = staticPoints;
        !           560:        } else {
        !           561:            pointPtr = (XPoint *) ckalloc((unsigned)
        !           562:                    (numPoints * sizeof(XPoint)));
        !           563:        }
        !           564:        numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
        !           565:                polyPtr->numPoints, polyPtr->splineSteps, pointPtr,
        !           566:                (double *) NULL);
        !           567:        XFillPolygon(Tk_Display(canvasPtr->tkwin), drawable, polyPtr->gc,
        !           568:                pointPtr, numPoints, Complex, CoordModeOrigin);
        !           569:        if (pointPtr != staticPoints) {
        !           570:            ckfree((char *) pointPtr);
        !           571:        }
        !           572:     }
        !           573: }
        !           574: 
        !           575: /*
        !           576:  *--------------------------------------------------------------
        !           577:  *
        !           578:  * PolygonToPoint --
        !           579:  *
        !           580:  *     Computes the distance from a given point to a given
        !           581:  *     polygon, in canvas units.
        !           582:  *
        !           583:  * Results:
        !           584:  *     The return value is 0 if the point whose x and y coordinates
        !           585:  *     are pointPtr[0] and pointPtr[1] is inside the polygon.  If the
        !           586:  *     point isn't inside the polygon then the return value is the
        !           587:  *     distance from the point to the polygon.
        !           588:  *
        !           589:  * Side effects:
        !           590:  *     None.
        !           591:  *
        !           592:  *--------------------------------------------------------------
        !           593:  */
        !           594: 
        !           595:        /* ARGSUSED */
        !           596: static double
        !           597: PolygonToPoint(canvasPtr, itemPtr, pointPtr)
        !           598:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
        !           599:     Tk_Item *itemPtr;          /* Item to check against point. */
        !           600:     double *pointPtr;          /* Pointer to x and y coordinates. */
        !           601: {
        !           602:     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           603:     double *coordPtr, distance;
        !           604:     double staticSpace[2*MAX_STATIC_POINTS];
        !           605:     int numPoints;
        !           606: 
        !           607:     if (!polyPtr->smooth) {
        !           608:        return TkPolygonToPoint(polyPtr->coordPtr, polyPtr->numPoints,
        !           609:                pointPtr);
        !           610:     }
        !           611: 
        !           612:     /*
        !           613:      * Smoothed polygon.  Generate a new set of points and use them
        !           614:      * for comparison.
        !           615:      */
        !           616: 
        !           617:     numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
        !           618:     if (numPoints <= MAX_STATIC_POINTS) {
        !           619:        coordPtr = staticSpace;
        !           620:     } else {
        !           621:        coordPtr = (double *) ckalloc((unsigned)
        !           622:                (2*numPoints*sizeof(double)));
        !           623:     }
        !           624:     numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
        !           625:            polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
        !           626:            coordPtr);
        !           627:     distance = TkPolygonToPoint(coordPtr, numPoints, pointPtr);
        !           628:     if (coordPtr != staticSpace) {
        !           629:        ckfree((char *) coordPtr);
        !           630:     }
        !           631:     return distance;
        !           632: }
        !           633: 
        !           634: /*
        !           635:  *--------------------------------------------------------------
        !           636:  *
        !           637:  * PolygonToArea --
        !           638:  *
        !           639:  *     This procedure is called to determine whether an item
        !           640:  *     lies entirely inside, entirely outside, or overlapping
        !           641:  *     a given rectangular area.
        !           642:  *
        !           643:  * Results:
        !           644:  *     -1 is returned if the item is entirely outside the area
        !           645:  *     given by rectPtr, 0 if it overlaps, and 1 if it is entirely
        !           646:  *     inside the given area.
        !           647:  *
        !           648:  * Side effects:
        !           649:  *     None.
        !           650:  *
        !           651:  *--------------------------------------------------------------
        !           652:  */
        !           653: 
        !           654:        /* ARGSUSED */
        !           655: static int
        !           656: PolygonToArea(canvasPtr, itemPtr, rectPtr)
        !           657:     Tk_Canvas *canvasPtr;      /* Canvas containing item. */
        !           658:     Tk_Item *itemPtr;          /* Item to check against polygon. */
        !           659:     double *rectPtr;           /* Pointer to array of four coordinates
        !           660:                                 * (x1, y1, x2, y2) describing rectangular
        !           661:                                 * area.  */
        !           662: {
        !           663:     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           664:     double *coordPtr;
        !           665:     double staticSpace[2*MAX_STATIC_POINTS];
        !           666:     int numPoints, result;
        !           667: 
        !           668:     if (!polyPtr->smooth) {
        !           669:        return TkPolygonToArea(polyPtr->coordPtr, polyPtr->numPoints, rectPtr);
        !           670:     }
        !           671: 
        !           672:     /*
        !           673:      * Smoothed polygon.  Generate a new set of points and use them
        !           674:      * for comparison.
        !           675:      */
        !           676: 
        !           677:     numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps;
        !           678:     if (numPoints <= MAX_STATIC_POINTS) {
        !           679:        coordPtr = staticSpace;
        !           680:     } else {
        !           681:        coordPtr = (double *) ckalloc((unsigned)
        !           682:                (2*numPoints*sizeof(double)));
        !           683:     }
        !           684:     numPoints = TkMakeBezierCurve(canvasPtr, polyPtr->coordPtr,
        !           685:            polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
        !           686:            coordPtr);
        !           687:     result = TkPolygonToArea(coordPtr, numPoints, rectPtr);
        !           688:     if (coordPtr != staticSpace) {
        !           689:        ckfree((char *) coordPtr);
        !           690:     }
        !           691:     return result;
        !           692: }
        !           693: 
        !           694: /*
        !           695:  *--------------------------------------------------------------
        !           696:  *
        !           697:  * ScalePolygon --
        !           698:  *
        !           699:  *     This procedure is invoked to rescale a polygon item.
        !           700:  *
        !           701:  * Results:
        !           702:  *     None.
        !           703:  *
        !           704:  * Side effects:
        !           705:  *     The polygon referred to by itemPtr is rescaled so that the
        !           706:  *     following transformation is applied to all point
        !           707:  *     coordinates:
        !           708:  *             x' = originX + scaleX*(x-originX)
        !           709:  *             y' = originY + scaleY*(y-originY)
        !           710:  *
        !           711:  *--------------------------------------------------------------
        !           712:  */
        !           713: 
        !           714: static void
        !           715: ScalePolygon(canvasPtr, itemPtr, originX, originY, scaleX, scaleY)
        !           716:     Tk_Canvas *canvasPtr;              /* Canvas containing polygon. */
        !           717:     Tk_Item *itemPtr;                  /* Polygon to be scaled. */
        !           718:     double originX, originY;           /* Origin about which to scale rect. */
        !           719:     double scaleX;                     /* Amount to scale in X direction. */
        !           720:     double scaleY;                     /* Amount to scale in Y direction. */
        !           721: {
        !           722:     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           723:     register double *coordPtr;
        !           724:     int i;
        !           725: 
        !           726:     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
        !           727:            i++, coordPtr += 2) {
        !           728:        *coordPtr = originX + scaleX*(*coordPtr - originX);
        !           729:        coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
        !           730:     }
        !           731:     ComputePolygonBbox(canvasPtr, polyPtr);
        !           732: }
        !           733: 
        !           734: /*
        !           735:  *--------------------------------------------------------------
        !           736:  *
        !           737:  * TranslatePolygon --
        !           738:  *
        !           739:  *     This procedure is called to move a polygon by a given
        !           740:  *     amount.
        !           741:  *
        !           742:  * Results:
        !           743:  *     None.
        !           744:  *
        !           745:  * Side effects:
        !           746:  *     The position of the polygon is offset by (xDelta, yDelta),
        !           747:  *     and the bounding box is updated in the generic part of the
        !           748:  *     item structure.
        !           749:  *
        !           750:  *--------------------------------------------------------------
        !           751:  */
        !           752: 
        !           753: static void
        !           754: TranslatePolygon(canvasPtr, itemPtr, deltaX, deltaY)
        !           755:     Tk_Canvas *canvasPtr;              /* Canvas containing item. */
        !           756:     Tk_Item *itemPtr;                  /* Item that is being moved. */
        !           757:     double deltaX, deltaY;             /* Amount by which item is to be
        !           758:                                         * moved. */
        !           759: {
        !           760:     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
        !           761:     register double *coordPtr;
        !           762:     int i;
        !           763: 
        !           764:     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
        !           765:            i++, coordPtr += 2) {
        !           766:        *coordPtr += deltaX;
        !           767:        coordPtr[1] += deltaY;
        !           768:     }
        !           769:     ComputePolygonBbox(canvasPtr, polyPtr);
        !           770: }

unix.superglobalmegacorp.com

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