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