]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkrectov.c
Fixes for compilation with gcc 15
[micropolis] / src / tk / tkrectov.c
1 /*
2 * tkRectOval.c --
3 *
4 * This file implements rectangle and oval items for canvas
5 * widgets.
6 *
7 * Copyright 1991-1992 Regents of the University of California.
8 * Permission to use, copy, modify, and distribute this
9 * software and its documentation for any purpose and without
10 * fee is hereby granted, provided that the above copyright
11 * notice appear in all copies. The University of California
12 * makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without
14 * express or implied warranty.
15 */
16
17 #ifndef lint
18 static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkRectOval.c,v 1.15 92/08/24 09:23:58 ouster Exp $ SPRITE (Berkeley)";
19 #endif
20
21 #include <stdio.h>
22 #include <math.h>
23 #include "tkconfig.h"
24 #include "tkint.h"
25 #include "tkcanvas.h"
26
27 /*
28 * The structure below defines the record for each rectangle/oval item.
29 */
30
31 typedef struct RectOvalItem {
32 Tk_Item header; /* Generic stuff that's the same for all
33 * types. MUST BE FIRST IN STRUCTURE. */
34 double bbox[4]; /* Coordinates of bounding box for rectangle
35 * or oval (x1, y1, x2, y2). Item includes
36 * x1 and x2 but not y1 and y2. */
37 int width; /* Width of outline. */
38 XColor *outlineColor; /* Color for outline. */
39 XColor *fillColor; /* Color for filling rectangle/oval. */
40 Pixmap fillStipple; /* Stipple bitmap for filling item. */
41 GC outlineGC; /* Graphics context for outline. */
42 GC fillGC; /* Graphics context for filling item. */
43 } RectOvalItem;
44
45 /*
46 * Information used for parsing configuration specs:
47 */
48
49 static Tk_ConfigSpec configSpecs[] = {
50 {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
51 (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
52 {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
53 "black", Tk_Offset(RectOvalItem, outlineColor), TK_CONFIG_NULL_OK},
54 {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
55 (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
56 {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
57 (char *) NULL, 0, TK_CONFIG_NULL_OK, &tkCanvasTagsOption},
58 {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
59 "1", Tk_Offset(RectOvalItem, width), TK_CONFIG_DONT_SET_DEFAULT},
60 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
61 (char *) NULL, 0, 0}
62 };
63
64 /*
65 * Prototypes for procedures defined in this file:
66 */
67
68 static void ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas *canvasPtr,
69 RectOvalItem *rectOvalPtr));
70 static int ConfigureRectOval _ANSI_ARGS_((
71 Tk_Canvas *canvasPtr, Tk_Item *itemPtr, int argc,
72 char **argv, int flags));
73 static int CreateRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
74 struct Tk_Item *itemPtr, int argc, char **argv));
75 static void DeleteRectOval _ANSI_ARGS_((Tk_Item *itemPtr));
76 static void DisplayRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
77 Tk_Item *itemPtr, Drawable dst));
78 static int OvalToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
79 Tk_Item *itemPtr, double *areaPtr));
80 static double OvalToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
81 Tk_Item *itemPtr, double *pointPtr));
82 static int RectOvalCoords _ANSI_ARGS_((Tk_Canvas *canvasPtr,
83 Tk_Item *itemPtr, int argc, char **argv));
84 static int RectToArea _ANSI_ARGS_((Tk_Canvas *canvasPtr,
85 Tk_Item *itemPtr, double *areaPtr));
86 static double RectToPoint _ANSI_ARGS_((Tk_Canvas *canvasPtr,
87 Tk_Item *itemPtr, double *pointPtr));
88 static void ScaleRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
89 Tk_Item *itemPtr, double originX, double originY,
90 double scaleX, double scaleY));
91 static void TranslateRectOval _ANSI_ARGS_((Tk_Canvas *canvasPtr,
92 Tk_Item *itemPtr, double deltaX, double deltaY));
93
94 /*
95 * The structures below defines the rectangle and oval item types
96 * by means of procedures that can be invoked by generic item code.
97 */
98
99 Tk_ItemType TkRectangleType = {
100 "rectangle", /* name */
101 sizeof(RectOvalItem), /* itemSize */
102 CreateRectOval, /* createProc */
103 configSpecs, /* configSpecs */
104 ConfigureRectOval, /* configureProc */
105 RectOvalCoords, /* coordProc */
106 DeleteRectOval, /* deleteProc */
107 DisplayRectOval, /* displayProc */
108 0, /* alwaysRedraw */
109 RectToPoint, /* pointProc */
110 RectToArea, /* areaProc */
111 (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */
112 ScaleRectOval, /* scaleProc */
113 TranslateRectOval, /* translateProc */
114 (Tk_ItemIndexProc *) NULL, /* indexProc */
115 (Tk_ItemCursorProc *) NULL, /* cursorProc */
116 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
117 (Tk_ItemInsertProc *) NULL, /* insertProc */
118 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
119 (Tk_ItemType *) NULL /* nextPtr */
120 };
121
122 Tk_ItemType TkOvalType = {
123 "oval", /* name */
124 sizeof(RectOvalItem), /* itemSize */
125 CreateRectOval, /* createProc */
126 configSpecs, /* configSpecs */
127 ConfigureRectOval, /* configureProc */
128 RectOvalCoords, /* coordProc */
129 DeleteRectOval, /* deleteProc */
130 DisplayRectOval, /* displayProc */
131 0, /* alwaysRedraw */
132 OvalToPoint, /* pointProc */
133 OvalToArea, /* areaProc */
134 (Tk_ItemPostscriptProc *) NULL, /* postscriptProc */
135 ScaleRectOval, /* scaleProc */
136 TranslateRectOval, /* translateProc */
137 (Tk_ItemIndexProc *) NULL, /* indexProc */
138 (Tk_ItemCursorProc *) NULL, /* cursorProc */
139 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
140 (Tk_ItemInsertProc *) NULL, /* insertProc */
141 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
142 (Tk_ItemType *) NULL /* nextPtr */
143 };
144 \f
145 /*
146 *--------------------------------------------------------------
147 *
148 * CreateRectOval --
149 *
150 * This procedure is invoked to create a new rectangle
151 * or oval item in a canvas.
152 *
153 * Results:
154 * A standard Tcl return value. If an error occurred in
155 * creating the item, then an error message is left in
156 * canvasPtr->interp->result; in this case itemPtr is
157 * left uninitialized, so it can be safely freed by the
158 * caller.
159 *
160 * Side effects:
161 * A new rectangle or oval item is created.
162 *
163 *--------------------------------------------------------------
164 */
165
166 static int
167 CreateRectOval (
168 register Tk_Canvas *canvasPtr, /* Canvas to hold new item. */
169 Tk_Item *itemPtr, /* Record to hold new item; header
170 * has been initialized by caller. */
171 int argc, /* Number of arguments in argv. */
172 char **argv /* Arguments describing rectangle. */
173 )
174 {
175 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
176
177 if (argc < 4) {
178 Tcl_AppendResult(canvasPtr->interp, "wrong # args: should be \"",
179 Tk_PathName(canvasPtr->tkwin), "\" create ",
180 itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?",
181 (char *) NULL);
182 return TCL_ERROR;
183 }
184
185 /*
186 * Carry out initialization that is needed in order to clean
187 * up after errors during the the remainder of this procedure.
188 */
189
190 rectOvalPtr->width = 1;
191 rectOvalPtr->outlineColor = NULL;
192 rectOvalPtr->fillColor = NULL;
193 rectOvalPtr->fillStipple = None;
194 rectOvalPtr->outlineGC = None;
195 rectOvalPtr->fillGC = None;
196
197 /*
198 * Process the arguments to fill in the item record.
199 */
200
201 if ((TkGetCanvasCoord(canvasPtr, argv[0], &rectOvalPtr->bbox[0]) != TCL_OK)
202 || (TkGetCanvasCoord(canvasPtr, argv[1],
203 &rectOvalPtr->bbox[1]) != TCL_OK)
204 || (TkGetCanvasCoord(canvasPtr, argv[2],
205 &rectOvalPtr->bbox[2]) != TCL_OK)
206 || (TkGetCanvasCoord(canvasPtr, argv[3],
207 &rectOvalPtr->bbox[3]) != TCL_OK)) {
208 return TCL_ERROR;
209 }
210
211 if (ConfigureRectOval(canvasPtr, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
212 DeleteRectOval(itemPtr);
213 return TCL_ERROR;
214 }
215 return TCL_OK;
216 }
217 \f
218 /*
219 *--------------------------------------------------------------
220 *
221 * RectOvalCoords --
222 *
223 * This procedure is invoked to process the "coords" widget
224 * command on rectangles and ovals. See the user documentation
225 * for details on what it does.
226 *
227 * Results:
228 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
229 *
230 * Side effects:
231 * The coordinates for the given item may be changed.
232 *
233 *--------------------------------------------------------------
234 */
235
236 static int
237 RectOvalCoords (
238 register Tk_Canvas *canvasPtr, /* Canvas containing item. */
239 Tk_Item *itemPtr, /* Item whose coordinates are to be
240 * read or modified. */
241 int argc, /* Number of coordinates supplied in
242 * argv. */
243 char **argv /* Array of coordinates: x1, y1,
244 * x2, y2, ... */
245 )
246 {
247 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
248 char buffer[500];
249
250 if (argc == 0) {
251 sprintf(buffer, "%g %g %g %g", rectOvalPtr->bbox[0],
252 rectOvalPtr->bbox[1], rectOvalPtr->bbox[2],
253 rectOvalPtr->bbox[3]);
254 Tcl_SetResult(canvasPtr->interp, buffer, TCL_VOLATILE);
255 } else if (argc == 4) {
256 if ((TkGetCanvasCoord(canvasPtr, argv[0],
257 &rectOvalPtr->bbox[0]) != TCL_OK)
258 || (TkGetCanvasCoord(canvasPtr, argv[1],
259 &rectOvalPtr->bbox[1]) != TCL_OK)
260 || (TkGetCanvasCoord(canvasPtr, argv[2],
261 &rectOvalPtr->bbox[2]) != TCL_OK)
262 || (TkGetCanvasCoord(canvasPtr, argv[3],
263 &rectOvalPtr->bbox[3]) != TCL_OK)) {
264 return TCL_ERROR;
265 }
266 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
267 } else {
268 sprintf(canvasPtr->interp->result,
269 "wrong # coordinates: expected 0 or 4, got %d",
270 argc);
271 return TCL_ERROR;
272 }
273 return TCL_OK;
274 }
275 \f
276 /*
277 *--------------------------------------------------------------
278 *
279 * ConfigureRectOval --
280 *
281 * This procedure is invoked to configure various aspects
282 * of a rectangle or oval item, such as its border and
283 * background colors.
284 *
285 * Results:
286 * A standard Tcl result code. If an error occurs, then
287 * an error message is left in canvasPtr->interp->result.
288 *
289 * Side effects:
290 * Configuration information, such as colors and stipple
291 * patterns, may be set for itemPtr.
292 *
293 *--------------------------------------------------------------
294 */
295
296 static int
297 ConfigureRectOval (
298 Tk_Canvas *canvasPtr, /* Canvas containing itemPtr. */
299 Tk_Item *itemPtr, /* Rectangle item to reconfigure. */
300 int argc, /* Number of elements in argv. */
301 char **argv, /* Arguments describing things to configure. */
302 int flags /* Flags to pass to Tk_ConfigureWidget. */
303 )
304 {
305 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
306 XGCValues gcValues;
307 GC newGC;
308 unsigned long mask;
309
310 if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
311 configSpecs, argc, argv, (char *) rectOvalPtr, flags) != TCL_OK) {
312 return TCL_ERROR;
313 }
314
315 /*
316 * A few of the options require additional processing, such as
317 * graphics contexts.
318 */
319
320 if (rectOvalPtr->outlineColor == NULL) {
321 newGC = None;
322 } else {
323 gcValues.foreground = rectOvalPtr->outlineColor->pixel;
324 gcValues.cap_style = CapProjecting;
325 if (rectOvalPtr->width < 0) {
326 rectOvalPtr->width = 1;
327 }
328 gcValues.line_width = rectOvalPtr->width;
329 mask = GCForeground|GCCapStyle|GCLineWidth;
330 newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
331 }
332 if (rectOvalPtr->outlineGC != None) {
333 Tk_FreeGC(rectOvalPtr->outlineGC);
334 }
335 rectOvalPtr->outlineGC = newGC;
336
337 if (rectOvalPtr->fillColor == NULL) {
338 newGC = None;
339 } else {
340 gcValues.foreground = rectOvalPtr->fillColor->pixel;
341 if (rectOvalPtr->fillStipple != None) {
342 gcValues.stipple = rectOvalPtr->fillStipple;
343 gcValues.fill_style = FillStippled;
344 mask = GCForeground|GCStipple|GCFillStyle;
345 } else {
346 mask = GCForeground;
347 }
348 newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
349 }
350 if (rectOvalPtr->fillGC != None) {
351 Tk_FreeGC(rectOvalPtr->fillGC);
352 }
353 rectOvalPtr->fillGC = newGC;
354 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
355
356 return TCL_OK;
357 }
358 \f
359 /*
360 *--------------------------------------------------------------
361 *
362 * DeleteRectOval --
363 *
364 * This procedure is called to clean up the data structure
365 * associated with a rectangle or oval item.
366 *
367 * Results:
368 * None.
369 *
370 * Side effects:
371 * Resources associated with itemPtr are released.
372 *
373 *--------------------------------------------------------------
374 */
375
376 static void
377 DeleteRectOval (
378 Tk_Item *itemPtr /* Item that is being deleted. */
379 )
380 {
381 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
382
383 if (rectOvalPtr->outlineColor != NULL) {
384 Tk_FreeColor(rectOvalPtr->outlineColor);
385 }
386 if (rectOvalPtr->fillColor != NULL) {
387 Tk_FreeColor(rectOvalPtr->fillColor);
388 }
389 if (rectOvalPtr->fillStipple != None) {
390 Tk_FreeBitmap(rectOvalPtr->fillStipple);
391 }
392 if (rectOvalPtr->outlineGC != None) {
393 Tk_FreeGC(rectOvalPtr->outlineGC);
394 }
395 if (rectOvalPtr->fillGC != None) {
396 Tk_FreeGC(rectOvalPtr->fillGC);
397 }
398 }
399 \f
400 /*
401 *--------------------------------------------------------------
402 *
403 * ComputeRectOvalBbox --
404 *
405 * This procedure is invoked to compute the bounding box of
406 * all the pixels that may be drawn as part of a rectangle
407 * or oval.
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 /* ARGSUSED */
420 static void
421 ComputeRectOvalBbox (
422 Tk_Canvas *canvasPtr, /* Canvas that contains item. */
423 register RectOvalItem *rectOvalPtr /* Item whose bbox is to be
424 * recomputed. */
425 )
426 {
427 int bloat;
428
429 /*
430 * Make sure that the first coordinates are the lowest ones.
431 */
432
433 if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
434 double tmp;
435 tmp = rectOvalPtr->bbox[3];
436 rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
437 rectOvalPtr->bbox[1] = tmp;
438 }
439 if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
440 double tmp;
441 tmp = rectOvalPtr->bbox[2];
442 rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
443 rectOvalPtr->bbox[0] = tmp;
444 }
445
446 bloat = (rectOvalPtr->width+1)/2 + 1;
447 rectOvalPtr->header.x1 = rectOvalPtr->bbox[0] - bloat;
448 rectOvalPtr->header.y1 = rectOvalPtr->bbox[1] - bloat;
449 rectOvalPtr->header.x2 = rectOvalPtr->bbox[2] + bloat;
450 rectOvalPtr->header.y2 = rectOvalPtr->bbox[3] + bloat;
451 }
452 \f
453 /*
454 *--------------------------------------------------------------
455 *
456 * DisplayRectOval --
457 *
458 * This procedure is invoked to draw a rectangle or oval
459 * item in a given drawable.
460 *
461 * Results:
462 * None.
463 *
464 * Side effects:
465 * ItemPtr is drawn in drawable using the transformation
466 * information in canvasPtr.
467 *
468 *--------------------------------------------------------------
469 */
470
471 static void
472 DisplayRectOval (
473 register Tk_Canvas *canvasPtr, /* Canvas that contains item. */
474 Tk_Item *itemPtr, /* Item to be displayed. */
475 Drawable drawable /* Pixmap or window in which to draw
476 * item. */
477 )
478 {
479 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
480 Display *display = Tk_Display(canvasPtr->tkwin);
481 int x1, y1, x2, y2;
482
483 /*
484 * Compute the screen coordinates of the bounding box for the item.
485 * Make sure that the bbox is at least one pixel large, since some
486 * X servers will die if it isn't.
487 */
488
489 x1 = SCREEN_X(canvasPtr, rectOvalPtr->bbox[0]);
490 y1 = SCREEN_Y(canvasPtr, rectOvalPtr->bbox[1]);
491 x2 = SCREEN_X(canvasPtr, rectOvalPtr->bbox[2]);
492 y2 = SCREEN_Y(canvasPtr, rectOvalPtr->bbox[3]);
493 if (x2 <= x1) {
494 x2 = x1+1;
495 }
496 if (y2 <= y1) {
497 y2 = y1+1;
498 }
499
500 /*
501 * Display filled box first (if wanted), then outline.
502 */
503
504 if (rectOvalPtr->fillGC != None) {
505 if (rectOvalPtr->header.typePtr == &TkRectangleType) {
506 XFillRectangle(display, drawable, rectOvalPtr->fillGC,
507 x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
508 } else {
509 XFillArc(display, drawable, rectOvalPtr->fillGC,
510 x1, y1, (x2-x1), (y2-y1), 0, 360*64);
511 }
512 }
513 if (rectOvalPtr->outlineGC != None) {
514 if (rectOvalPtr->header.typePtr == &TkRectangleType) {
515 XDrawRectangle(display, drawable, rectOvalPtr->outlineGC,
516 x1, y1, (x2-x1-1), (y2-y1-1));
517 } else {
518 XDrawArc(display, drawable, rectOvalPtr->outlineGC,
519 x1, y1, (x2-x1-1), (y2-y1-1), 0, 360*64);
520 }
521 }
522 }
523 \f
524 /*
525 *--------------------------------------------------------------
526 *
527 * RectToPoint --
528 *
529 * Computes the distance from a given point to a given
530 * rectangle, in canvas units.
531 *
532 * Results:
533 * The return value is 0 if the point whose x and y coordinates
534 * are coordPtr[0] and coordPtr[1] is inside the rectangle. If the
535 * point isn't inside the rectangle then the return value is the
536 * distance from the point to the rectangle. If itemPtr is filled,
537 * then anywhere in the interior is considered "inside"; if
538 * itemPtr isn't filled, then "inside" means only the area
539 * occupied by the outline.
540 *
541 * Side effects:
542 * None.
543 *
544 *--------------------------------------------------------------
545 */
546
547 /* ARGSUSED */
548 static double
549 RectToPoint (
550 Tk_Canvas *canvasPtr, /* Canvas containing item. */
551 Tk_Item *itemPtr, /* Item to check against point. */
552 double *pointPtr /* Pointer to x and y coordinates. */
553 )
554 {
555 register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
556 double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
557
558 /*
559 * Generate a new larger rectangle that includes the border
560 * width, if there is one.
561 */
562
563 x1 = rectPtr->bbox[0];
564 y1 = rectPtr->bbox[1];
565 x2 = rectPtr->bbox[2];
566 y2 = rectPtr->bbox[3];
567 if (rectPtr->outlineGC != None) {
568 inc = rectPtr->width/2.0;
569 x1 -= inc;
570 y1 -= inc;
571 x2 += inc;
572 y2 += inc;
573 }
574
575 /*
576 * If the point is inside the rectangle, handle specially:
577 * distance is 0 if rectangle is filled, otherwise compute
578 * distance to nearest edge of rectangle and subtract width
579 * of edge.
580 */
581
582 if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
583 && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
584 if ((rectPtr->fillGC != None) || (rectPtr->outlineGC == None)) {
585 return 0.0;
586 }
587 xDiff = pointPtr[0] - x1;
588 tmp = x2 - pointPtr[0];
589 if (tmp < xDiff) {
590 xDiff = tmp;
591 }
592 yDiff = pointPtr[1] - y1;
593 tmp = y2 - pointPtr[1];
594 if (tmp < yDiff) {
595 yDiff = tmp;
596 }
597 if (yDiff < xDiff) {
598 xDiff = yDiff;
599 }
600 xDiff -= rectPtr->width;
601 if (xDiff < 0.0) {
602 return 0.0;
603 }
604 return xDiff;
605 }
606
607 /*
608 * Point is outside rectangle.
609 */
610
611 if (pointPtr[0] < x1) {
612 xDiff = x1 - pointPtr[0];
613 } else if (pointPtr[0] > x2) {
614 xDiff = pointPtr[0] - x2;
615 } else {
616 xDiff = 0;
617 }
618
619 if (pointPtr[1] < y1) {
620 yDiff = y1 - pointPtr[1];
621 } else if (pointPtr[1] > y2) {
622 yDiff = pointPtr[1] - y2;
623 } else {
624 yDiff = 0;
625 }
626
627 return hypot(xDiff, yDiff);
628 }
629 \f
630 /*
631 *--------------------------------------------------------------
632 *
633 * OvalToPoint --
634 *
635 * Computes the distance from a given point to a given
636 * oval, in canvas units.
637 *
638 * Results:
639 * The return value is 0 if the point whose x and y coordinates
640 * are coordPtr[0] and coordPtr[1] is inside the oval. If the
641 * point isn't inside the oval then the return value is the
642 * distance from the point to the oval. If itemPtr is filled,
643 * then anywhere in the interior is considered "inside"; if
644 * itemPtr isn't filled, then "inside" means only the area
645 * occupied by the outline.
646 *
647 * Side effects:
648 * None.
649 *
650 *--------------------------------------------------------------
651 */
652
653 /* ARGSUSED */
654 static double
655 OvalToPoint (
656 Tk_Canvas *canvasPtr, /* Canvas containing item. */
657 Tk_Item *itemPtr, /* Item to check against point. */
658 double *pointPtr /* Pointer to x and y coordinates. */
659 )
660 {
661 register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
662 double width;
663 int filled;
664
665 width = ovalPtr->width;
666 filled = ovalPtr->fillGC != None;
667 if (ovalPtr->outlineGC == None) {
668 width = 0.0;
669 filled = 1;
670 }
671 return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
672 }
673 \f
674 /*
675 *--------------------------------------------------------------
676 *
677 * RectToArea --
678 *
679 * This procedure is called to determine whether an item
680 * lies entirely inside, entirely outside, or overlapping
681 * a given rectangle.
682 *
683 * Results:
684 * -1 is returned if the item is entirely outside the area
685 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
686 * inside the given area.
687 *
688 * Side effects:
689 * None.
690 *
691 *--------------------------------------------------------------
692 */
693
694 /* ARGSUSED */
695 static int
696 RectToArea (
697 Tk_Canvas *canvasPtr, /* Canvas containing item. */
698 Tk_Item *itemPtr, /* Item to check against rectangle. */
699 double *areaPtr /* Pointer to array of four coordinates
700 * (x1, y1, x2, y2) describing rectangular
701 * area. */
702 )
703 {
704 register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
705 double halfWidth;
706
707 halfWidth = rectPtr->width/2.0;
708 if (rectPtr->outlineGC == None) {
709 halfWidth = 0.0;
710 }
711
712 if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
713 || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
714 || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
715 || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
716 return -1;
717 }
718 if ((rectPtr->fillGC == None) && (rectPtr->outlineGC != None)
719 && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
720 && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
721 && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
722 && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
723 return -1;
724 }
725 if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
726 && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
727 && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
728 && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
729 return 1;
730 }
731 return 0;
732 }
733 \f
734 /*
735 *--------------------------------------------------------------
736 *
737 * OvalToArea --
738 *
739 * This procedure is called to determine whether an item
740 * lies entirely inside, entirely outside, or overlapping
741 * a given rectangular area.
742 *
743 * Results:
744 * -1 is returned if the item is entirely outside the area
745 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
746 * inside the given area.
747 *
748 * Side effects:
749 * None.
750 *
751 *--------------------------------------------------------------
752 */
753
754 /* ARGSUSED */
755 static int
756 OvalToArea (
757 Tk_Canvas *canvasPtr, /* Canvas containing item. */
758 Tk_Item *itemPtr, /* Item to check against oval. */
759 double *areaPtr /* Pointer to array of four coordinates
760 * (x1, y1, x2, y2) describing rectangular
761 * area. */
762 )
763 {
764 register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
765 double oval[4], halfWidth;
766 int result;
767
768 /*
769 * Expand the oval to include the width of the outline, if any.
770 */
771
772 halfWidth = ovalPtr->width/2.0;
773 if (ovalPtr->outlineGC == None) {
774 halfWidth = 0.0;
775 }
776 oval[0] = ovalPtr->bbox[0] - halfWidth;
777 oval[1] = ovalPtr->bbox[1] - halfWidth;
778 oval[2] = ovalPtr->bbox[2] + halfWidth;
779 oval[3] = ovalPtr->bbox[3] + halfWidth;
780
781 result = TkOvalToArea(oval, areaPtr);
782
783 /*
784 * If the rectangle appears to overlap the oval and the oval
785 * isn't filled, do one more check to see if perhaps all four
786 * of the rectangle's corners are totally inside the oval's
787 * unfilled center, in which case we should return "outside".
788 */
789
790 if ((result == 0) && (ovalPtr->outlineGC != NULL)
791 && (ovalPtr->fillGC == NULL)) {
792 double centerX, centerY, width, height;
793 double xDelta1, yDelta1, xDelta2, yDelta2;
794
795 centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
796 centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
797 width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
798 height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
799 xDelta1 = (areaPtr[0] - centerX)/width;
800 xDelta1 *= xDelta1;
801 yDelta1 = (areaPtr[1] - centerY)/height;
802 yDelta1 *= yDelta1;
803 xDelta2 = (areaPtr[2] - centerX)/width;
804 xDelta2 *= xDelta2;
805 yDelta2 = (areaPtr[3] - centerY)/height;
806 yDelta2 *= yDelta2;
807 if (((xDelta1 + yDelta1) < 1.0)
808 && ((xDelta1 + yDelta2) < 1.0)
809 && ((xDelta2 + yDelta1) < 1.0)
810 && ((xDelta2 + yDelta2) < 1.0)) {
811 return -1;
812 }
813 }
814 return result;
815 }
816 \f
817 /*
818 *--------------------------------------------------------------
819 *
820 * ScaleRectOval --
821 *
822 * This procedure is invoked to rescale a rectangle or oval
823 * item.
824 *
825 * Results:
826 * None.
827 *
828 * Side effects:
829 * The rectangle or oval referred to by itemPtr is rescaled
830 * so that the following transformation is applied to all
831 * point coordinates:
832 * x' = originX + scaleX*(x-originX)
833 * y' = originY + scaleY*(y-originY)
834 *
835 *--------------------------------------------------------------
836 */
837
838 static void
839 ScaleRectOval (
840 Tk_Canvas *canvasPtr, /* Canvas containing rectangle. */
841 Tk_Item *itemPtr, /* Rectangle to be scaled. */
842 double originX,
843 double originY, /* Origin about which to scale rect. */
844 double scaleX, /* Amount to scale in X direction. */
845 double scaleY /* Amount to scale in Y direction. */
846 )
847 {
848 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
849
850 rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
851 rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
852 rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
853 rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
854 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
855 }
856 \f
857 /*
858 *--------------------------------------------------------------
859 *
860 * TranslateRectOval --
861 *
862 * This procedure is called to move a rectangle or oval by a
863 * given amount.
864 *
865 * Results:
866 * None.
867 *
868 * Side effects:
869 * The position of the rectangle or oval is offset by
870 * (xDelta, yDelta), and the bounding box is updated in the
871 * generic part of the item structure.
872 *
873 *--------------------------------------------------------------
874 */
875
876 static void
877 TranslateRectOval (
878 Tk_Canvas *canvasPtr, /* Canvas containing item. */
879 Tk_Item *itemPtr, /* Item that is being moved. */
880 double deltaX,
881 double deltaY /* Amount by which item is to be
882 * moved. */
883 )
884 {
885 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
886
887 rectOvalPtr->bbox[0] += deltaX;
888 rectOvalPtr->bbox[1] += deltaY;
889 rectOvalPtr->bbox[2] += deltaX;
890 rectOvalPtr->bbox[3] += deltaY;
891 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
892 }
Impressum, Datenschutz