]> git.zerfleddert.de Git - micropolis/blob - src/tk/tkcvpoly.c
show mini-map when hovering over the empty mini-map frame
[micropolis] / src / tk / tkcvpoly.c
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 }
Impressum, Datenschutz