4 * This file implements rectangle and oval items for canvas
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.
18 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkRectOval.c,v 1.15 92/08/24 09:23:58 ouster Exp $ SPRITE (Berkeley)";
28 * The structure below defines the record for each rectangle/oval item.
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. */
46 * Information used for parsing configuration specs:
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
,
65 * Prototypes for procedures defined in this file:
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
));
95 * The structures below defines the rectangle and oval item types
96 * by means of procedures that can be invoked by generic item code.
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 */
122 Tk_ItemType TkOvalType
= {
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 */
146 *--------------------------------------------------------------
150 * This procedure is invoked to create a new rectangle
151 * or oval item in a canvas.
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
161 * A new rectangle or oval item is created.
163 *--------------------------------------------------------------
167 CreateRectOval(canvasPtr
, itemPtr
, argc
, argv
)
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. */
174 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
177 Tcl_AppendResult(canvasPtr
->interp
, "wrong # args: should be \"",
178 Tk_PathName(canvasPtr
->tkwin
), "\" create ",
179 itemPtr
->typePtr
->name
, " x1 y1 x2 y2 ?options?",
185 * Carry out initialization that is needed in order to clean
186 * up after errors during the the remainder of this procedure.
189 rectOvalPtr
->width
= 1;
190 rectOvalPtr
->outlineColor
= NULL
;
191 rectOvalPtr
->fillColor
= NULL
;
192 rectOvalPtr
->fillStipple
= None
;
193 rectOvalPtr
->outlineGC
= None
;
194 rectOvalPtr
->fillGC
= None
;
197 * Process the arguments to fill in the item record.
200 if ((TkGetCanvasCoord(canvasPtr
, argv
[0], &rectOvalPtr
->bbox
[0]) != TCL_OK
)
201 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
202 &rectOvalPtr
->bbox
[1]) != TCL_OK
)
203 || (TkGetCanvasCoord(canvasPtr
, argv
[2],
204 &rectOvalPtr
->bbox
[2]) != TCL_OK
)
205 || (TkGetCanvasCoord(canvasPtr
, argv
[3],
206 &rectOvalPtr
->bbox
[3]) != TCL_OK
)) {
210 if (ConfigureRectOval(canvasPtr
, itemPtr
, argc
-4, argv
+4, 0) != TCL_OK
) {
211 DeleteRectOval(itemPtr
);
218 *--------------------------------------------------------------
222 * This procedure is invoked to process the "coords" widget
223 * command on rectangles and ovals. See the user documentation
224 * for details on what it does.
227 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
230 * The coordinates for the given item may be changed.
232 *--------------------------------------------------------------
236 RectOvalCoords(canvasPtr
, itemPtr
, argc
, argv
)
237 register Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
238 Tk_Item
*itemPtr
; /* Item whose coordinates are to be
239 * read or modified. */
240 int argc
; /* Number of coordinates supplied in
242 char **argv
; /* Array of coordinates: x1, y1,
245 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
249 sprintf(buffer
, "%g %g %g %g", rectOvalPtr
->bbox
[0],
250 rectOvalPtr
->bbox
[1], rectOvalPtr
->bbox
[2],
251 rectOvalPtr
->bbox
[3]);
252 Tcl_SetResult(canvasPtr
->interp
, buffer
, TCL_VOLATILE
);
253 } else if (argc
== 4) {
254 if ((TkGetCanvasCoord(canvasPtr
, argv
[0],
255 &rectOvalPtr
->bbox
[0]) != TCL_OK
)
256 || (TkGetCanvasCoord(canvasPtr
, argv
[1],
257 &rectOvalPtr
->bbox
[1]) != TCL_OK
)
258 || (TkGetCanvasCoord(canvasPtr
, argv
[2],
259 &rectOvalPtr
->bbox
[2]) != TCL_OK
)
260 || (TkGetCanvasCoord(canvasPtr
, argv
[3],
261 &rectOvalPtr
->bbox
[3]) != TCL_OK
)) {
264 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);
266 sprintf(canvasPtr
->interp
->result
,
267 "wrong # coordinates: expected 0 or 4, got %d",
275 *--------------------------------------------------------------
277 * ConfigureRectOval --
279 * This procedure is invoked to configure various aspects
280 * of a rectangle or oval item, such as its border and
284 * A standard Tcl result code. If an error occurs, then
285 * an error message is left in canvasPtr->interp->result.
288 * Configuration information, such as colors and stipple
289 * patterns, may be set for itemPtr.
291 *--------------------------------------------------------------
295 ConfigureRectOval(canvasPtr
, itemPtr
, argc
, argv
, flags
)
296 Tk_Canvas
*canvasPtr
; /* Canvas containing itemPtr. */
297 Tk_Item
*itemPtr
; /* Rectangle item to reconfigure. */
298 int argc
; /* Number of elements in argv. */
299 char **argv
; /* Arguments describing things to configure. */
300 int flags
; /* Flags to pass to Tk_ConfigureWidget. */
302 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
307 if (Tk_ConfigureWidget(canvasPtr
->interp
, canvasPtr
->tkwin
,
308 configSpecs
, argc
, argv
, (char *) rectOvalPtr
, flags
) != TCL_OK
) {
313 * A few of the options require additional processing, such as
317 if (rectOvalPtr
->outlineColor
== NULL
) {
320 gcValues
.foreground
= rectOvalPtr
->outlineColor
->pixel
;
321 gcValues
.cap_style
= CapProjecting
;
322 if (rectOvalPtr
->width
< 0) {
323 rectOvalPtr
->width
= 1;
325 gcValues
.line_width
= rectOvalPtr
->width
;
326 mask
= GCForeground
|GCCapStyle
|GCLineWidth
;
327 newGC
= Tk_GetGC(canvasPtr
->tkwin
, mask
, &gcValues
);
329 if (rectOvalPtr
->outlineGC
!= None
) {
330 Tk_FreeGC(rectOvalPtr
->outlineGC
);
332 rectOvalPtr
->outlineGC
= newGC
;
334 if (rectOvalPtr
->fillColor
== NULL
) {
337 gcValues
.foreground
= rectOvalPtr
->fillColor
->pixel
;
338 if (rectOvalPtr
->fillStipple
!= None
) {
339 gcValues
.stipple
= rectOvalPtr
->fillStipple
;
340 gcValues
.fill_style
= FillStippled
;
341 mask
= GCForeground
|GCStipple
|GCFillStyle
;
345 newGC
= Tk_GetGC(canvasPtr
->tkwin
, mask
, &gcValues
);
347 if (rectOvalPtr
->fillGC
!= None
) {
348 Tk_FreeGC(rectOvalPtr
->fillGC
);
350 rectOvalPtr
->fillGC
= newGC
;
351 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);
357 *--------------------------------------------------------------
361 * This procedure is called to clean up the data structure
362 * associated with a rectangle or oval item.
368 * Resources associated with itemPtr are released.
370 *--------------------------------------------------------------
374 DeleteRectOval(itemPtr
)
375 Tk_Item
*itemPtr
; /* Item that is being deleted. */
377 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
379 if (rectOvalPtr
->outlineColor
!= NULL
) {
380 Tk_FreeColor(rectOvalPtr
->outlineColor
);
382 if (rectOvalPtr
->fillColor
!= NULL
) {
383 Tk_FreeColor(rectOvalPtr
->fillColor
);
385 if (rectOvalPtr
->fillStipple
!= None
) {
386 Tk_FreeBitmap(rectOvalPtr
->fillStipple
);
388 if (rectOvalPtr
->outlineGC
!= None
) {
389 Tk_FreeGC(rectOvalPtr
->outlineGC
);
391 if (rectOvalPtr
->fillGC
!= None
) {
392 Tk_FreeGC(rectOvalPtr
->fillGC
);
397 *--------------------------------------------------------------
399 * ComputeRectOvalBbox --
401 * This procedure is invoked to compute the bounding box of
402 * all the pixels that may be drawn as part of a rectangle
409 * The fields x1, y1, x2, and y2 are updated in the header
412 *--------------------------------------------------------------
417 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
)
418 Tk_Canvas
*canvasPtr
; /* Canvas that contains item. */
419 register RectOvalItem
*rectOvalPtr
; /* Item whose bbox is to be
425 * Make sure that the first coordinates are the lowest ones.
428 if (rectOvalPtr
->bbox
[1] > rectOvalPtr
->bbox
[3]) {
430 tmp
= rectOvalPtr
->bbox
[3];
431 rectOvalPtr
->bbox
[3] = rectOvalPtr
->bbox
[1];
432 rectOvalPtr
->bbox
[1] = tmp
;
434 if (rectOvalPtr
->bbox
[0] > rectOvalPtr
->bbox
[2]) {
436 tmp
= rectOvalPtr
->bbox
[2];
437 rectOvalPtr
->bbox
[2] = rectOvalPtr
->bbox
[0];
438 rectOvalPtr
->bbox
[0] = tmp
;
441 bloat
= (rectOvalPtr
->width
+1)/2 + 1;
442 rectOvalPtr
->header
.x1
= rectOvalPtr
->bbox
[0] - bloat
;
443 rectOvalPtr
->header
.y1
= rectOvalPtr
->bbox
[1] - bloat
;
444 rectOvalPtr
->header
.x2
= rectOvalPtr
->bbox
[2] + bloat
;
445 rectOvalPtr
->header
.y2
= rectOvalPtr
->bbox
[3] + bloat
;
449 *--------------------------------------------------------------
453 * This procedure is invoked to draw a rectangle or oval
454 * item in a given drawable.
460 * ItemPtr is drawn in drawable using the transformation
461 * information in canvasPtr.
463 *--------------------------------------------------------------
467 DisplayRectOval(canvasPtr
, itemPtr
, drawable
)
468 register Tk_Canvas
*canvasPtr
; /* Canvas that contains item. */
469 Tk_Item
*itemPtr
; /* Item to be displayed. */
470 Drawable drawable
; /* Pixmap or window in which to draw
473 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
474 Display
*display
= Tk_Display(canvasPtr
->tkwin
);
478 * Compute the screen coordinates of the bounding box for the item.
479 * Make sure that the bbox is at least one pixel large, since some
480 * X servers will die if it isn't.
483 x1
= SCREEN_X(canvasPtr
, rectOvalPtr
->bbox
[0]);
484 y1
= SCREEN_Y(canvasPtr
, rectOvalPtr
->bbox
[1]);
485 x2
= SCREEN_X(canvasPtr
, rectOvalPtr
->bbox
[2]);
486 y2
= SCREEN_Y(canvasPtr
, rectOvalPtr
->bbox
[3]);
495 * Display filled box first (if wanted), then outline.
498 if (rectOvalPtr
->fillGC
!= None
) {
499 if (rectOvalPtr
->header
.typePtr
== &TkRectangleType
) {
500 XFillRectangle(display
, drawable
, rectOvalPtr
->fillGC
,
501 x1
, y1
, (unsigned int) (x2
-x1
), (unsigned int) (y2
-y1
));
503 XFillArc(display
, drawable
, rectOvalPtr
->fillGC
,
504 x1
, y1
, (x2
-x1
), (y2
-y1
), 0, 360*64);
507 if (rectOvalPtr
->outlineGC
!= None
) {
508 if (rectOvalPtr
->header
.typePtr
== &TkRectangleType
) {
509 XDrawRectangle(display
, drawable
, rectOvalPtr
->outlineGC
,
510 x1
, y1
, (x2
-x1
-1), (y2
-y1
-1));
512 XDrawArc(display
, drawable
, rectOvalPtr
->outlineGC
,
513 x1
, y1
, (x2
-x1
-1), (y2
-y1
-1), 0, 360*64);
519 *--------------------------------------------------------------
523 * Computes the distance from a given point to a given
524 * rectangle, in canvas units.
527 * The return value is 0 if the point whose x and y coordinates
528 * are coordPtr[0] and coordPtr[1] is inside the rectangle. If the
529 * point isn't inside the rectangle then the return value is the
530 * distance from the point to the rectangle. If itemPtr is filled,
531 * then anywhere in the interior is considered "inside"; if
532 * itemPtr isn't filled, then "inside" means only the area
533 * occupied by the outline.
538 *--------------------------------------------------------------
543 RectToPoint(canvasPtr
, itemPtr
, pointPtr
)
544 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
545 Tk_Item
*itemPtr
; /* Item to check against point. */
546 double *pointPtr
; /* Pointer to x and y coordinates. */
548 register RectOvalItem
*rectPtr
= (RectOvalItem
*) itemPtr
;
549 double xDiff
, yDiff
, x1
, y1
, x2
, y2
, inc
, tmp
;
552 * Generate a new larger rectangle that includes the border
553 * width, if there is one.
556 x1
= rectPtr
->bbox
[0];
557 y1
= rectPtr
->bbox
[1];
558 x2
= rectPtr
->bbox
[2];
559 y2
= rectPtr
->bbox
[3];
560 if (rectPtr
->outlineGC
!= None
) {
561 inc
= rectPtr
->width
/2.0;
569 * If the point is inside the rectangle, handle specially:
570 * distance is 0 if rectangle is filled, otherwise compute
571 * distance to nearest edge of rectangle and subtract width
575 if ((pointPtr
[0] >= x1
) && (pointPtr
[0] < x2
)
576 && (pointPtr
[1] >= y1
) && (pointPtr
[1] < y2
)) {
577 if ((rectPtr
->fillGC
!= None
) || (rectPtr
->outlineGC
== None
)) {
580 xDiff
= pointPtr
[0] - x1
;
581 tmp
= x2
- pointPtr
[0];
585 yDiff
= pointPtr
[1] - y1
;
586 tmp
= y2
- pointPtr
[1];
593 xDiff
-= rectPtr
->width
;
601 * Point is outside rectangle.
604 if (pointPtr
[0] < x1
) {
605 xDiff
= x1
- pointPtr
[0];
606 } else if (pointPtr
[0] > x2
) {
607 xDiff
= pointPtr
[0] - x2
;
612 if (pointPtr
[1] < y1
) {
613 yDiff
= y1
- pointPtr
[1];
614 } else if (pointPtr
[1] > y2
) {
615 yDiff
= pointPtr
[1] - y2
;
620 return hypot(xDiff
, yDiff
);
624 *--------------------------------------------------------------
628 * Computes the distance from a given point to a given
629 * oval, in canvas units.
632 * The return value is 0 if the point whose x and y coordinates
633 * are coordPtr[0] and coordPtr[1] is inside the oval. If the
634 * point isn't inside the oval then the return value is the
635 * distance from the point to the oval. If itemPtr is filled,
636 * then anywhere in the interior is considered "inside"; if
637 * itemPtr isn't filled, then "inside" means only the area
638 * occupied by the outline.
643 *--------------------------------------------------------------
648 OvalToPoint(canvasPtr
, itemPtr
, pointPtr
)
649 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
650 Tk_Item
*itemPtr
; /* Item to check against point. */
651 double *pointPtr
; /* Pointer to x and y coordinates. */
653 register RectOvalItem
*ovalPtr
= (RectOvalItem
*) itemPtr
;
657 width
= ovalPtr
->width
;
658 filled
= ovalPtr
->fillGC
!= None
;
659 if (ovalPtr
->outlineGC
== None
) {
663 return TkOvalToPoint(ovalPtr
->bbox
, width
, filled
, pointPtr
);
667 *--------------------------------------------------------------
671 * This procedure is called to determine whether an item
672 * lies entirely inside, entirely outside, or overlapping
676 * -1 is returned if the item is entirely outside the area
677 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
678 * inside the given area.
683 *--------------------------------------------------------------
688 RectToArea(canvasPtr
, itemPtr
, areaPtr
)
689 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
690 Tk_Item
*itemPtr
; /* Item to check against rectangle. */
691 double *areaPtr
; /* Pointer to array of four coordinates
692 * (x1, y1, x2, y2) describing rectangular
695 register RectOvalItem
*rectPtr
= (RectOvalItem
*) itemPtr
;
698 halfWidth
= rectPtr
->width
/2.0;
699 if (rectPtr
->outlineGC
== None
) {
703 if ((areaPtr
[2] <= (rectPtr
->bbox
[0] - halfWidth
))
704 || (areaPtr
[0] >= (rectPtr
->bbox
[2] + halfWidth
))
705 || (areaPtr
[3] <= (rectPtr
->bbox
[1] - halfWidth
))
706 || (areaPtr
[1] >= (rectPtr
->bbox
[3] + halfWidth
))) {
709 if ((rectPtr
->fillGC
== None
) && (rectPtr
->outlineGC
!= None
)
710 && (areaPtr
[0] >= (rectPtr
->bbox
[0] + halfWidth
))
711 && (areaPtr
[1] >= (rectPtr
->bbox
[1] + halfWidth
))
712 && (areaPtr
[2] <= (rectPtr
->bbox
[2] - halfWidth
))
713 && (areaPtr
[3] <= (rectPtr
->bbox
[3] - halfWidth
))) {
716 if ((areaPtr
[0] <= (rectPtr
->bbox
[0] - halfWidth
))
717 && (areaPtr
[1] <= (rectPtr
->bbox
[1] - halfWidth
))
718 && (areaPtr
[2] >= (rectPtr
->bbox
[2] + halfWidth
))
719 && (areaPtr
[3] >= (rectPtr
->bbox
[3] + halfWidth
))) {
726 *--------------------------------------------------------------
730 * This procedure is called to determine whether an item
731 * lies entirely inside, entirely outside, or overlapping
732 * a given rectangular area.
735 * -1 is returned if the item is entirely outside the area
736 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
737 * inside the given area.
742 *--------------------------------------------------------------
747 OvalToArea(canvasPtr
, itemPtr
, areaPtr
)
748 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
749 Tk_Item
*itemPtr
; /* Item to check against oval. */
750 double *areaPtr
; /* Pointer to array of four coordinates
751 * (x1, y1, x2, y2) describing rectangular
754 register RectOvalItem
*ovalPtr
= (RectOvalItem
*) itemPtr
;
755 double oval
[4], halfWidth
;
759 * Expand the oval to include the width of the outline, if any.
762 halfWidth
= ovalPtr
->width
/2.0;
763 if (ovalPtr
->outlineGC
== None
) {
766 oval
[0] = ovalPtr
->bbox
[0] - halfWidth
;
767 oval
[1] = ovalPtr
->bbox
[1] - halfWidth
;
768 oval
[2] = ovalPtr
->bbox
[2] + halfWidth
;
769 oval
[3] = ovalPtr
->bbox
[3] + halfWidth
;
771 result
= TkOvalToArea(oval
, areaPtr
);
774 * If the rectangle appears to overlap the oval and the oval
775 * isn't filled, do one more check to see if perhaps all four
776 * of the rectangle's corners are totally inside the oval's
777 * unfilled center, in which case we should return "outside".
780 if ((result
== 0) && (ovalPtr
->outlineGC
!= NULL
)
781 && (ovalPtr
->fillGC
== NULL
)) {
782 double centerX
, centerY
, width
, height
;
783 double xDelta1
, yDelta1
, xDelta2
, yDelta2
;
785 centerX
= (ovalPtr
->bbox
[0] + ovalPtr
->bbox
[2])/2.0;
786 centerY
= (ovalPtr
->bbox
[1] + ovalPtr
->bbox
[3])/2.0;
787 width
= (ovalPtr
->bbox
[2] - ovalPtr
->bbox
[0])/2.0 - halfWidth
;
788 height
= (ovalPtr
->bbox
[3] - ovalPtr
->bbox
[1])/2.0 - halfWidth
;
789 xDelta1
= (areaPtr
[0] - centerX
)/width
;
791 yDelta1
= (areaPtr
[1] - centerY
)/height
;
793 xDelta2
= (areaPtr
[2] - centerX
)/width
;
795 yDelta2
= (areaPtr
[3] - centerY
)/height
;
797 if (((xDelta1
+ yDelta1
) < 1.0)
798 && ((xDelta1
+ yDelta2
) < 1.0)
799 && ((xDelta2
+ yDelta1
) < 1.0)
800 && ((xDelta2
+ yDelta2
) < 1.0)) {
808 *--------------------------------------------------------------
812 * This procedure is invoked to rescale a rectangle or oval
819 * The rectangle or oval referred to by itemPtr is rescaled
820 * so that the following transformation is applied to all
822 * x' = originX + scaleX*(x-originX)
823 * y' = originY + scaleY*(y-originY)
825 *--------------------------------------------------------------
829 ScaleRectOval(canvasPtr
, itemPtr
, originX
, originY
, scaleX
, scaleY
)
830 Tk_Canvas
*canvasPtr
; /* Canvas containing rectangle. */
831 Tk_Item
*itemPtr
; /* Rectangle to be scaled. */
832 double originX
, originY
; /* Origin about which to scale rect. */
833 double scaleX
; /* Amount to scale in X direction. */
834 double scaleY
; /* Amount to scale in Y direction. */
836 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
838 rectOvalPtr
->bbox
[0] = originX
+ scaleX
*(rectOvalPtr
->bbox
[0] - originX
);
839 rectOvalPtr
->bbox
[1] = originY
+ scaleY
*(rectOvalPtr
->bbox
[1] - originY
);
840 rectOvalPtr
->bbox
[2] = originX
+ scaleX
*(rectOvalPtr
->bbox
[2] - originX
);
841 rectOvalPtr
->bbox
[3] = originY
+ scaleY
*(rectOvalPtr
->bbox
[3] - originY
);
842 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);
846 *--------------------------------------------------------------
848 * TranslateRectOval --
850 * This procedure is called to move a rectangle or oval by a
857 * The position of the rectangle or oval is offset by
858 * (xDelta, yDelta), and the bounding box is updated in the
859 * generic part of the item structure.
861 *--------------------------------------------------------------
865 TranslateRectOval(canvasPtr
, itemPtr
, deltaX
, deltaY
)
866 Tk_Canvas
*canvasPtr
; /* Canvas containing item. */
867 Tk_Item
*itemPtr
; /* Item that is being moved. */
868 double deltaX
, deltaY
; /* Amount by which item is to be
871 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
873 rectOvalPtr
->bbox
[0] += deltaX
;
874 rectOvalPtr
->bbox
[1] += deltaY
;
875 rectOvalPtr
->bbox
[2] += deltaX
;
876 rectOvalPtr
->bbox
[3] += deltaY
;
877 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);