|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.