|
|
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.