]> git.zerfleddert.de Git - micropolis/blob - src/tk/tkrectov.c
2e0c738a7e0c299781e04ca5a6d78582d907549b
[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(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. */
173 {
174 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
175
176 if (argc < 4) {
177 Tcl_AppendResult(canvasPtr->interp, "wrong # args: should be \"",
178 Tk_PathName(canvasPtr->tkwin), "\" create ",
179 itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?",
180 (char *) NULL);
181 return TCL_ERROR;
182 }
183
184 /*
185 * Carry out initialization that is needed in order to clean
186 * up after errors during the the remainder of this procedure.
187 */
188
189 rectOvalPtr->width = 1;
190 rectOvalPtr->outlineColor = NULL;
191 rectOvalPtr->fillColor = NULL;
192 rectOvalPtr->fillStipple = None;
193 rectOvalPtr->outlineGC = None;
194 rectOvalPtr->fillGC = None;
195
196 /*
197 * Process the arguments to fill in the item record.
198 */
199
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)) {
207 return TCL_ERROR;
208 }
209
210 if (ConfigureRectOval(canvasPtr, itemPtr, argc-4, argv+4, 0) != TCL_OK) {
211 DeleteRectOval(itemPtr);
212 return TCL_ERROR;
213 }
214 return TCL_OK;
215 }
216 \f
217 /*
218 *--------------------------------------------------------------
219 *
220 * RectOvalCoords --
221 *
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.
225 *
226 * Results:
227 * Returns TCL_OK or TCL_ERROR, and sets canvasPtr->interp->result.
228 *
229 * Side effects:
230 * The coordinates for the given item may be changed.
231 *
232 *--------------------------------------------------------------
233 */
234
235 static int
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
241 * argv. */
242 char **argv; /* Array of coordinates: x1, y1,
243 * x2, y2, ... */
244 {
245 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
246 char buffer[500];
247
248 if (argc == 0) {
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)) {
262 return TCL_ERROR;
263 }
264 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
265 } else {
266 sprintf(canvasPtr->interp->result,
267 "wrong # coordinates: expected 0 or 4, got %d",
268 argc);
269 return TCL_ERROR;
270 }
271 return TCL_OK;
272 }
273 \f
274 /*
275 *--------------------------------------------------------------
276 *
277 * ConfigureRectOval --
278 *
279 * This procedure is invoked to configure various aspects
280 * of a rectangle or oval item, such as its border and
281 * background colors.
282 *
283 * Results:
284 * A standard Tcl result code. If an error occurs, then
285 * an error message is left in canvasPtr->interp->result.
286 *
287 * Side effects:
288 * Configuration information, such as colors and stipple
289 * patterns, may be set for itemPtr.
290 *
291 *--------------------------------------------------------------
292 */
293
294 static int
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. */
301 {
302 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
303 XGCValues gcValues;
304 GC newGC;
305 unsigned long mask;
306
307 if (Tk_ConfigureWidget(canvasPtr->interp, canvasPtr->tkwin,
308 configSpecs, argc, argv, (char *) rectOvalPtr, flags) != TCL_OK) {
309 return TCL_ERROR;
310 }
311
312 /*
313 * A few of the options require additional processing, such as
314 * graphics contexts.
315 */
316
317 if (rectOvalPtr->outlineColor == NULL) {
318 newGC = None;
319 } else {
320 gcValues.foreground = rectOvalPtr->outlineColor->pixel;
321 gcValues.cap_style = CapProjecting;
322 if (rectOvalPtr->width < 0) {
323 rectOvalPtr->width = 1;
324 }
325 gcValues.line_width = rectOvalPtr->width;
326 mask = GCForeground|GCCapStyle|GCLineWidth;
327 newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
328 }
329 if (rectOvalPtr->outlineGC != None) {
330 Tk_FreeGC(rectOvalPtr->outlineGC);
331 }
332 rectOvalPtr->outlineGC = newGC;
333
334 if (rectOvalPtr->fillColor == NULL) {
335 newGC = None;
336 } else {
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;
342 } else {
343 mask = GCForeground;
344 }
345 newGC = Tk_GetGC(canvasPtr->tkwin, mask, &gcValues);
346 }
347 if (rectOvalPtr->fillGC != None) {
348 Tk_FreeGC(rectOvalPtr->fillGC);
349 }
350 rectOvalPtr->fillGC = newGC;
351 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
352
353 return TCL_OK;
354 }
355 \f
356 /*
357 *--------------------------------------------------------------
358 *
359 * DeleteRectOval --
360 *
361 * This procedure is called to clean up the data structure
362 * associated with a rectangle or oval item.
363 *
364 * Results:
365 * None.
366 *
367 * Side effects:
368 * Resources associated with itemPtr are released.
369 *
370 *--------------------------------------------------------------
371 */
372
373 static void
374 DeleteRectOval(itemPtr)
375 Tk_Item *itemPtr; /* Item that is being deleted. */
376 {
377 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
378
379 if (rectOvalPtr->outlineColor != NULL) {
380 Tk_FreeColor(rectOvalPtr->outlineColor);
381 }
382 if (rectOvalPtr->fillColor != NULL) {
383 Tk_FreeColor(rectOvalPtr->fillColor);
384 }
385 if (rectOvalPtr->fillStipple != None) {
386 Tk_FreeBitmap(rectOvalPtr->fillStipple);
387 }
388 if (rectOvalPtr->outlineGC != None) {
389 Tk_FreeGC(rectOvalPtr->outlineGC);
390 }
391 if (rectOvalPtr->fillGC != None) {
392 Tk_FreeGC(rectOvalPtr->fillGC);
393 }
394 }
395 \f
396 /*
397 *--------------------------------------------------------------
398 *
399 * ComputeRectOvalBbox --
400 *
401 * This procedure is invoked to compute the bounding box of
402 * all the pixels that may be drawn as part of a rectangle
403 * or oval.
404 *
405 * Results:
406 * None.
407 *
408 * Side effects:
409 * The fields x1, y1, x2, and y2 are updated in the header
410 * for itemPtr.
411 *
412 *--------------------------------------------------------------
413 */
414
415 /* ARGSUSED */
416 static void
417 ComputeRectOvalBbox(canvasPtr, rectOvalPtr)
418 Tk_Canvas *canvasPtr; /* Canvas that contains item. */
419 register RectOvalItem *rectOvalPtr; /* Item whose bbox is to be
420 * recomputed. */
421 {
422 int bloat;
423
424 /*
425 * Make sure that the first coordinates are the lowest ones.
426 */
427
428 if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
429 double tmp;
430 tmp = rectOvalPtr->bbox[3];
431 rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
432 rectOvalPtr->bbox[1] = tmp;
433 }
434 if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
435 double tmp;
436 tmp = rectOvalPtr->bbox[2];
437 rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
438 rectOvalPtr->bbox[0] = tmp;
439 }
440
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;
446 }
447 \f
448 /*
449 *--------------------------------------------------------------
450 *
451 * DisplayRectOval --
452 *
453 * This procedure is invoked to draw a rectangle or oval
454 * item in a given drawable.
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 static void
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
471 * item. */
472 {
473 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
474 Display *display = Tk_Display(canvasPtr->tkwin);
475 int x1, y1, x2, y2;
476
477 /*
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.
481 */
482
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]);
487 if (x2 <= x1) {
488 x2 = x1+1;
489 }
490 if (y2 <= y1) {
491 y2 = y1+1;
492 }
493
494 /*
495 * Display filled box first (if wanted), then outline.
496 */
497
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));
502 } else {
503 XFillArc(display, drawable, rectOvalPtr->fillGC,
504 x1, y1, (x2-x1), (y2-y1), 0, 360*64);
505 }
506 }
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));
511 } else {
512 XDrawArc(display, drawable, rectOvalPtr->outlineGC,
513 x1, y1, (x2-x1-1), (y2-y1-1), 0, 360*64);
514 }
515 }
516 }
517 \f
518 /*
519 *--------------------------------------------------------------
520 *
521 * RectToPoint --
522 *
523 * Computes the distance from a given point to a given
524 * rectangle, in canvas units.
525 *
526 * Results:
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.
534 *
535 * Side effects:
536 * None.
537 *
538 *--------------------------------------------------------------
539 */
540
541 /* ARGSUSED */
542 static double
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. */
547 {
548 register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
549 double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
550
551 /*
552 * Generate a new larger rectangle that includes the border
553 * width, if there is one.
554 */
555
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;
562 x1 -= inc;
563 y1 -= inc;
564 x2 += inc;
565 y2 += inc;
566 }
567
568 /*
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
572 * of edge.
573 */
574
575 if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
576 && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
577 if ((rectPtr->fillGC != None) || (rectPtr->outlineGC == None)) {
578 return 0.0;
579 }
580 xDiff = pointPtr[0] - x1;
581 tmp = x2 - pointPtr[0];
582 if (tmp < xDiff) {
583 xDiff = tmp;
584 }
585 yDiff = pointPtr[1] - y1;
586 tmp = y2 - pointPtr[1];
587 if (tmp < yDiff) {
588 yDiff = tmp;
589 }
590 if (yDiff < xDiff) {
591 xDiff = yDiff;
592 }
593 xDiff -= rectPtr->width;
594 if (xDiff < 0.0) {
595 return 0.0;
596 }
597 return xDiff;
598 }
599
600 /*
601 * Point is outside rectangle.
602 */
603
604 if (pointPtr[0] < x1) {
605 xDiff = x1 - pointPtr[0];
606 } else if (pointPtr[0] > x2) {
607 xDiff = pointPtr[0] - x2;
608 } else {
609 xDiff = 0;
610 }
611
612 if (pointPtr[1] < y1) {
613 yDiff = y1 - pointPtr[1];
614 } else if (pointPtr[1] > y2) {
615 yDiff = pointPtr[1] - y2;
616 } else {
617 yDiff = 0;
618 }
619
620 return hypot(xDiff, yDiff);
621 }
622 \f
623 /*
624 *--------------------------------------------------------------
625 *
626 * OvalToPoint --
627 *
628 * Computes the distance from a given point to a given
629 * oval, in canvas units.
630 *
631 * Results:
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.
639 *
640 * Side effects:
641 * None.
642 *
643 *--------------------------------------------------------------
644 */
645
646 /* ARGSUSED */
647 static double
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. */
652 {
653 register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
654 double width;
655 int filled;
656
657 width = ovalPtr->width;
658 filled = ovalPtr->fillGC != None;
659 if (ovalPtr->outlineGC == None) {
660 width = 0.0;
661 filled = 1;
662 }
663 return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
664 }
665 \f
666 /*
667 *--------------------------------------------------------------
668 *
669 * RectToArea --
670 *
671 * This procedure is called to determine whether an item
672 * lies entirely inside, entirely outside, or overlapping
673 * a given rectangle.
674 *
675 * Results:
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.
679 *
680 * Side effects:
681 * None.
682 *
683 *--------------------------------------------------------------
684 */
685
686 /* ARGSUSED */
687 static int
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
693 * area. */
694 {
695 register RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
696 double halfWidth;
697
698 halfWidth = rectPtr->width/2.0;
699 if (rectPtr->outlineGC == None) {
700 halfWidth = 0.0;
701 }
702
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))) {
707 return -1;
708 }
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))) {
714 return -1;
715 }
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))) {
720 return 1;
721 }
722 return 0;
723 }
724 \f
725 /*
726 *--------------------------------------------------------------
727 *
728 * OvalToArea --
729 *
730 * This procedure is called to determine whether an item
731 * lies entirely inside, entirely outside, or overlapping
732 * a given rectangular area.
733 *
734 * Results:
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.
738 *
739 * Side effects:
740 * None.
741 *
742 *--------------------------------------------------------------
743 */
744
745 /* ARGSUSED */
746 static int
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
752 * area. */
753 {
754 register RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
755 double oval[4], halfWidth;
756 int result;
757
758 /*
759 * Expand the oval to include the width of the outline, if any.
760 */
761
762 halfWidth = ovalPtr->width/2.0;
763 if (ovalPtr->outlineGC == None) {
764 halfWidth = 0.0;
765 }
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;
770
771 result = TkOvalToArea(oval, areaPtr);
772
773 /*
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".
778 */
779
780 if ((result == 0) && (ovalPtr->outlineGC != NULL)
781 && (ovalPtr->fillGC == NULL)) {
782 double centerX, centerY, width, height;
783 double xDelta1, yDelta1, xDelta2, yDelta2;
784
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;
790 xDelta1 *= xDelta1;
791 yDelta1 = (areaPtr[1] - centerY)/height;
792 yDelta1 *= yDelta1;
793 xDelta2 = (areaPtr[2] - centerX)/width;
794 xDelta2 *= xDelta2;
795 yDelta2 = (areaPtr[3] - centerY)/height;
796 yDelta2 *= yDelta2;
797 if (((xDelta1 + yDelta1) < 1.0)
798 && ((xDelta1 + yDelta2) < 1.0)
799 && ((xDelta2 + yDelta1) < 1.0)
800 && ((xDelta2 + yDelta2) < 1.0)) {
801 return -1;
802 }
803 }
804 return result;
805 }
806 \f
807 /*
808 *--------------------------------------------------------------
809 *
810 * ScaleRectOval --
811 *
812 * This procedure is invoked to rescale a rectangle or oval
813 * item.
814 *
815 * Results:
816 * None.
817 *
818 * Side effects:
819 * The rectangle or oval referred to by itemPtr is rescaled
820 * so that the following transformation is applied to all
821 * point coordinates:
822 * x' = originX + scaleX*(x-originX)
823 * y' = originY + scaleY*(y-originY)
824 *
825 *--------------------------------------------------------------
826 */
827
828 static void
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. */
835 {
836 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
837
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);
843 }
844 \f
845 /*
846 *--------------------------------------------------------------
847 *
848 * TranslateRectOval --
849 *
850 * This procedure is called to move a rectangle or oval by a
851 * given amount.
852 *
853 * Results:
854 * None.
855 *
856 * Side effects:
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.
860 *
861 *--------------------------------------------------------------
862 */
863
864 static void
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
869 * moved. */
870 {
871 register RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
872
873 rectOvalPtr->bbox[0] += deltaX;
874 rectOvalPtr->bbox[1] += deltaY;
875 rectOvalPtr->bbox[2] += deltaX;
876 rectOvalPtr->bbox[3] += deltaY;
877 ComputeRectOvalBbox(canvasPtr, rectOvalPtr);
878 }
Impressum, Datenschutz