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 *--------------------------------------------------------------
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. */
175 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
178 Tcl_AppendResult(canvasPtr
->interp
, "wrong # args: should be \"",
179 Tk_PathName(canvasPtr
->tkwin
), "\" create ",
180 itemPtr
->typePtr
->name
, " x1 y1 x2 y2 ?options?",
186 * Carry out initialization that is needed in order to clean
187 * up after errors during the the remainder of this procedure.
190 rectOvalPtr
->width
= 1;
191 rectOvalPtr
->outlineColor
= NULL
;
192 rectOvalPtr
->fillColor
= NULL
;
193 rectOvalPtr
->fillStipple
= None
;
194 rectOvalPtr
->outlineGC
= None
;
195 rectOvalPtr
->fillGC
= None
;
198 * Process the arguments to fill in the item record.
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
)) {
211 if (ConfigureRectOval(canvasPtr
, itemPtr
, argc
-4, argv
+4, 0) != TCL_OK
) {
212 DeleteRectOval(itemPtr
);
219 *--------------------------------------------------------------
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.
228 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
231 * The coordinates for the given item may be changed.
233 *--------------------------------------------------------------
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
243 char **argv
/* Array of coordinates: x1, y1,
247 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
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
)) {
266 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);
268 sprintf(canvasPtr
->interp
->result
,
269 "wrong # coordinates: expected 0 or 4, got %d",
277 *--------------------------------------------------------------
279 * ConfigureRectOval --
281 * This procedure is invoked to configure various aspects
282 * of a rectangle or oval item, such as its border and
286 * A standard Tcl result code. If an error occurs, then
287 * an error message is left in canvasPtr->interp->result.
290 * Configuration information, such as colors and stipple
291 * patterns, may be set for itemPtr.
293 *--------------------------------------------------------------
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. */
305 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
310 if (Tk_ConfigureWidget(canvasPtr
->interp
, canvasPtr
->tkwin
,
311 configSpecs
, argc
, argv
, (char *) rectOvalPtr
, flags
) != TCL_OK
) {
316 * A few of the options require additional processing, such as
320 if (rectOvalPtr
->outlineColor
== NULL
) {
323 gcValues
.foreground
= rectOvalPtr
->outlineColor
->pixel
;
324 gcValues
.cap_style
= CapProjecting
;
325 if (rectOvalPtr
->width
< 0) {
326 rectOvalPtr
->width
= 1;
328 gcValues
.line_width
= rectOvalPtr
->width
;
329 mask
= GCForeground
|GCCapStyle
|GCLineWidth
;
330 newGC
= Tk_GetGC(canvasPtr
->tkwin
, mask
, &gcValues
);
332 if (rectOvalPtr
->outlineGC
!= None
) {
333 Tk_FreeGC(rectOvalPtr
->outlineGC
);
335 rectOvalPtr
->outlineGC
= newGC
;
337 if (rectOvalPtr
->fillColor
== NULL
) {
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
;
348 newGC
= Tk_GetGC(canvasPtr
->tkwin
, mask
, &gcValues
);
350 if (rectOvalPtr
->fillGC
!= None
) {
351 Tk_FreeGC(rectOvalPtr
->fillGC
);
353 rectOvalPtr
->fillGC
= newGC
;
354 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);
360 *--------------------------------------------------------------
364 * This procedure is called to clean up the data structure
365 * associated with a rectangle or oval item.
371 * Resources associated with itemPtr are released.
373 *--------------------------------------------------------------
378 Tk_Item
*itemPtr
/* Item that is being deleted. */
381 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
383 if (rectOvalPtr
->outlineColor
!= NULL
) {
384 Tk_FreeColor(rectOvalPtr
->outlineColor
);
386 if (rectOvalPtr
->fillColor
!= NULL
) {
387 Tk_FreeColor(rectOvalPtr
->fillColor
);
389 if (rectOvalPtr
->fillStipple
!= None
) {
390 Tk_FreeBitmap(rectOvalPtr
->fillStipple
);
392 if (rectOvalPtr
->outlineGC
!= None
) {
393 Tk_FreeGC(rectOvalPtr
->outlineGC
);
395 if (rectOvalPtr
->fillGC
!= None
) {
396 Tk_FreeGC(rectOvalPtr
->fillGC
);
401 *--------------------------------------------------------------
403 * ComputeRectOvalBbox --
405 * This procedure is invoked to compute the bounding box of
406 * all the pixels that may be drawn as part of a rectangle
413 * The fields x1, y1, x2, and y2 are updated in the header
416 *--------------------------------------------------------------
421 ComputeRectOvalBbox (
422 Tk_Canvas
*canvasPtr
, /* Canvas that contains item. */
423 register RectOvalItem
*rectOvalPtr
/* Item whose bbox is to be
430 * Make sure that the first coordinates are the lowest ones.
433 if (rectOvalPtr
->bbox
[1] > rectOvalPtr
->bbox
[3]) {
435 tmp
= rectOvalPtr
->bbox
[3];
436 rectOvalPtr
->bbox
[3] = rectOvalPtr
->bbox
[1];
437 rectOvalPtr
->bbox
[1] = tmp
;
439 if (rectOvalPtr
->bbox
[0] > rectOvalPtr
->bbox
[2]) {
441 tmp
= rectOvalPtr
->bbox
[2];
442 rectOvalPtr
->bbox
[2] = rectOvalPtr
->bbox
[0];
443 rectOvalPtr
->bbox
[0] = tmp
;
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
;
454 *--------------------------------------------------------------
458 * This procedure is invoked to draw a rectangle or oval
459 * item in a given drawable.
465 * ItemPtr is drawn in drawable using the transformation
466 * information in canvasPtr.
468 *--------------------------------------------------------------
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
479 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
480 Display
*display
= Tk_Display(canvasPtr
->tkwin
);
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.
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]);
501 * Display filled box first (if wanted), then outline.
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
));
509 XFillArc(display
, drawable
, rectOvalPtr
->fillGC
,
510 x1
, y1
, (x2
-x1
), (y2
-y1
), 0, 360*64);
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));
518 XDrawArc(display
, drawable
, rectOvalPtr
->outlineGC
,
519 x1
, y1
, (x2
-x1
-1), (y2
-y1
-1), 0, 360*64);
525 *--------------------------------------------------------------
529 * Computes the distance from a given point to a given
530 * rectangle, in canvas units.
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.
544 *--------------------------------------------------------------
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. */
555 register RectOvalItem
*rectPtr
= (RectOvalItem
*) itemPtr
;
556 double xDiff
, yDiff
, x1
, y1
, x2
, y2
, inc
, tmp
;
559 * Generate a new larger rectangle that includes the border
560 * width, if there is one.
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;
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
582 if ((pointPtr
[0] >= x1
) && (pointPtr
[0] < x2
)
583 && (pointPtr
[1] >= y1
) && (pointPtr
[1] < y2
)) {
584 if ((rectPtr
->fillGC
!= None
) || (rectPtr
->outlineGC
== None
)) {
587 xDiff
= pointPtr
[0] - x1
;
588 tmp
= x2
- pointPtr
[0];
592 yDiff
= pointPtr
[1] - y1
;
593 tmp
= y2
- pointPtr
[1];
600 xDiff
-= rectPtr
->width
;
608 * Point is outside rectangle.
611 if (pointPtr
[0] < x1
) {
612 xDiff
= x1
- pointPtr
[0];
613 } else if (pointPtr
[0] > x2
) {
614 xDiff
= pointPtr
[0] - x2
;
619 if (pointPtr
[1] < y1
) {
620 yDiff
= y1
- pointPtr
[1];
621 } else if (pointPtr
[1] > y2
) {
622 yDiff
= pointPtr
[1] - y2
;
627 return hypot(xDiff
, yDiff
);
631 *--------------------------------------------------------------
635 * Computes the distance from a given point to a given
636 * oval, in canvas units.
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.
650 *--------------------------------------------------------------
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. */
661 register RectOvalItem
*ovalPtr
= (RectOvalItem
*) itemPtr
;
665 width
= ovalPtr
->width
;
666 filled
= ovalPtr
->fillGC
!= None
;
667 if (ovalPtr
->outlineGC
== None
) {
671 return TkOvalToPoint(ovalPtr
->bbox
, width
, filled
, pointPtr
);
675 *--------------------------------------------------------------
679 * This procedure is called to determine whether an item
680 * lies entirely inside, entirely outside, or overlapping
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.
691 *--------------------------------------------------------------
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
704 register RectOvalItem
*rectPtr
= (RectOvalItem
*) itemPtr
;
707 halfWidth
= rectPtr
->width
/2.0;
708 if (rectPtr
->outlineGC
== None
) {
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
))) {
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
))) {
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
))) {
735 *--------------------------------------------------------------
739 * This procedure is called to determine whether an item
740 * lies entirely inside, entirely outside, or overlapping
741 * a given rectangular area.
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.
751 *--------------------------------------------------------------
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
764 register RectOvalItem
*ovalPtr
= (RectOvalItem
*) itemPtr
;
765 double oval
[4], halfWidth
;
769 * Expand the oval to include the width of the outline, if any.
772 halfWidth
= ovalPtr
->width
/2.0;
773 if (ovalPtr
->outlineGC
== None
) {
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
;
781 result
= TkOvalToArea(oval
, areaPtr
);
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".
790 if ((result
== 0) && (ovalPtr
->outlineGC
!= NULL
)
791 && (ovalPtr
->fillGC
== NULL
)) {
792 double centerX
, centerY
, width
, height
;
793 double xDelta1
, yDelta1
, xDelta2
, yDelta2
;
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
;
801 yDelta1
= (areaPtr
[1] - centerY
)/height
;
803 xDelta2
= (areaPtr
[2] - centerX
)/width
;
805 yDelta2
= (areaPtr
[3] - centerY
)/height
;
807 if (((xDelta1
+ yDelta1
) < 1.0)
808 && ((xDelta1
+ yDelta2
) < 1.0)
809 && ((xDelta2
+ yDelta1
) < 1.0)
810 && ((xDelta2
+ yDelta2
) < 1.0)) {
818 *--------------------------------------------------------------
822 * This procedure is invoked to rescale a rectangle or oval
829 * The rectangle or oval referred to by itemPtr is rescaled
830 * so that the following transformation is applied to all
832 * x' = originX + scaleX*(x-originX)
833 * y' = originY + scaleY*(y-originY)
835 *--------------------------------------------------------------
840 Tk_Canvas
*canvasPtr
, /* Canvas containing rectangle. */
841 Tk_Item
*itemPtr
, /* Rectangle to be scaled. */
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. */
848 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
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
);
858 *--------------------------------------------------------------
860 * TranslateRectOval --
862 * This procedure is called to move a rectangle or oval by a
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.
873 *--------------------------------------------------------------
878 Tk_Canvas
*canvasPtr
, /* Canvas containing item. */
879 Tk_Item
*itemPtr
, /* Item that is being moved. */
881 double deltaY
/* Amount by which item is to be
885 register RectOvalItem
*rectOvalPtr
= (RectOvalItem
*) itemPtr
;
887 rectOvalPtr
->bbox
[0] += deltaX
;
888 rectOvalPtr
->bbox
[1] += deltaY
;
889 rectOvalPtr
->bbox
[2] += deltaX
;
890 rectOvalPtr
->bbox
[3] += deltaY
;
891 ComputeRectOvalBbox(canvasPtr
, rectOvalPtr
);