/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkrectoval.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkrectoval.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (show annotations) (download)
Sat Nov 5 11:07:06 2016 UTC (8 years, 1 month ago) by dashley
File MIME type: text/plain
File size: 43827 byte(s)
Set EOL properties appropriately to facilitate simultaneous Linux and Windows development.
1 /* $Header$ */
2
3 /*
4 * tkRectOval.c --
5 *
6 * This file implements rectangle and oval items for canvas
7 * widgets.
8 *
9 * Copyright (c) 1991-1994 The Regents of the University of California.
10 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tkrectoval.c,v 1.1.1.1 2001/06/13 05:07:29 dtashley Exp $
16 */
17
18 #include <stdio.h>
19 #include "tk.h"
20 #include "tkInt.h"
21 #include "tkPort.h"
22 #include "tkCanvas.h"
23
24 /*
25 * The structure below defines the record for each rectangle/oval item.
26 */
27
28 typedef struct RectOvalItem {
29 Tk_Item header; /* Generic stuff that's the same for all
30 * types. MUST BE FIRST IN STRUCTURE. */
31 Tk_Outline outline; /* Outline structure */
32 double bbox[4]; /* Coordinates of bounding box for rectangle
33 * or oval (x1, y1, x2, y2). Item includes
34 * x1 and x2 but not y1 and y2. */
35 Tk_TSOffset tsoffset;
36 XColor *fillColor; /* Color for filling rectangle/oval. */
37 XColor *activeFillColor; /* Color for filling rectangle/oval if state is active. */
38 XColor *disabledFillColor; /* Color for filling rectangle/oval if state is disabled. */
39 Pixmap fillStipple; /* Stipple bitmap for filling item. */
40 Pixmap activeFillStipple; /* Stipple bitmap for filling item if state is active. */
41 Pixmap disabledFillStipple; /* Stipple bitmap for filling item if state is disabled. */
42 GC fillGC; /* Graphics context for filling item. */
43 } RectOvalItem;
44
45 /*
46 * Information used for parsing configuration specs:
47 */
48
49 static Tk_CustomOption stateOption = {
50 (Tk_OptionParseProc *) TkStateParseProc,
51 TkStatePrintProc, (ClientData) 2
52 };
53 static Tk_CustomOption tagsOption = {
54 (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
55 Tk_CanvasTagsPrintProc, (ClientData) NULL
56 };
57 static Tk_CustomOption dashOption = {
58 (Tk_OptionParseProc *) TkCanvasDashParseProc,
59 TkCanvasDashPrintProc, (ClientData) NULL
60 };
61 static Tk_CustomOption offsetOption = {
62 (Tk_OptionParseProc *) TkOffsetParseProc,
63 TkOffsetPrintProc, (ClientData) TK_OFFSET_RELATIVE
64 };
65 static Tk_CustomOption pixelOption = {
66 (Tk_OptionParseProc *) TkPixelParseProc,
67 TkPixelPrintProc, (ClientData) NULL
68 };
69
70 static Tk_ConfigSpec configSpecs[] = {
71 {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
72 (char *) NULL, Tk_Offset(RectOvalItem, outline.activeDash),
73 TK_CONFIG_NULL_OK, &dashOption},
74 {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
75 (char *) NULL, Tk_Offset(RectOvalItem, activeFillColor),
76 TK_CONFIG_NULL_OK},
77 {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
78 (char *) NULL, Tk_Offset(RectOvalItem, outline.activeColor),
79 TK_CONFIG_NULL_OK},
80 {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
81 (char *) NULL, Tk_Offset(RectOvalItem, outline.activeStipple),
82 TK_CONFIG_NULL_OK},
83 {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
84 (char *) NULL, Tk_Offset(RectOvalItem, activeFillStipple),
85 TK_CONFIG_NULL_OK},
86 {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
87 "0.0", Tk_Offset(RectOvalItem, outline.activeWidth),
88 TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
89 {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
90 (char *) NULL, Tk_Offset(RectOvalItem, outline.dash),
91 TK_CONFIG_NULL_OK, &dashOption},
92 {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
93 "0", Tk_Offset(RectOvalItem, outline.offset),
94 TK_CONFIG_DONT_SET_DEFAULT},
95 {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
96 (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledDash),
97 TK_CONFIG_NULL_OK, &dashOption},
98 {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
99 (char *) NULL, Tk_Offset(RectOvalItem, disabledFillColor),
100 TK_CONFIG_NULL_OK},
101 {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
102 (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledColor),
103 TK_CONFIG_NULL_OK},
104 {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
105 (char *) NULL, Tk_Offset(RectOvalItem, outline.disabledStipple),
106 TK_CONFIG_NULL_OK},
107 {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
108 (char *) NULL, Tk_Offset(RectOvalItem, disabledFillStipple),
109 TK_CONFIG_NULL_OK},
110 {TK_CONFIG_PIXELS, "-disabledwidth", (char *) NULL, (char *) NULL,
111 "0.0", Tk_Offset(RectOvalItem, outline.disabledWidth),
112 TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
113 {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
114 (char *) NULL, Tk_Offset(RectOvalItem, fillColor), TK_CONFIG_NULL_OK},
115 {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
116 "0,0", Tk_Offset(RectOvalItem, tsoffset),
117 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
118 {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
119 "black", Tk_Offset(RectOvalItem, outline.color), TK_CONFIG_NULL_OK},
120 {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
121 "0,0", Tk_Offset(RectOvalItem, outline.tsoffset),
122 TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
123 {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
124 (char *) NULL, Tk_Offset(RectOvalItem, outline.stipple),
125 TK_CONFIG_NULL_OK},
126 {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
127 (char *) NULL, Tk_Offset(Tk_Item, state),TK_CONFIG_NULL_OK,
128 &stateOption},
129 {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
130 (char *) NULL, Tk_Offset(RectOvalItem, fillStipple), TK_CONFIG_NULL_OK},
131 {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
132 (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
133 {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
134 "1.0", Tk_Offset(RectOvalItem, outline.width),
135 TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
136 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
137 (char *) NULL, 0, 0}
138 };
139
140 /*
141 * Prototypes for procedures defined in this file:
142 */
143
144 static void ComputeRectOvalBbox _ANSI_ARGS_((Tk_Canvas canvas,
145 RectOvalItem *rectOvalPtr));
146 static int ConfigureRectOval _ANSI_ARGS_((Tcl_Interp *interp,
147 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
148 Tcl_Obj *CONST argv[], int flags));
149 static int CreateRectOval _ANSI_ARGS_((Tcl_Interp *interp,
150 Tk_Canvas canvas, struct Tk_Item *itemPtr,
151 int argc, Tcl_Obj *CONST argv[]));
152 static void DeleteRectOval _ANSI_ARGS_((Tk_Canvas canvas,
153 Tk_Item *itemPtr, Display *display));
154 static void DisplayRectOval _ANSI_ARGS_((Tk_Canvas canvas,
155 Tk_Item *itemPtr, Display *display, Drawable dst,
156 int x, int y, int width, int height));
157 static int OvalToArea _ANSI_ARGS_((Tk_Canvas canvas,
158 Tk_Item *itemPtr, double *areaPtr));
159 static double OvalToPoint _ANSI_ARGS_((Tk_Canvas canvas,
160 Tk_Item *itemPtr, double *pointPtr));
161 static int RectOvalCoords _ANSI_ARGS_((Tcl_Interp *interp,
162 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
163 Tcl_Obj *CONST argv[]));
164 static int RectOvalToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
165 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
166 static int RectToArea _ANSI_ARGS_((Tk_Canvas canvas,
167 Tk_Item *itemPtr, double *areaPtr));
168 static double RectToPoint _ANSI_ARGS_((Tk_Canvas canvas,
169 Tk_Item *itemPtr, double *pointPtr));
170 static void ScaleRectOval _ANSI_ARGS_((Tk_Canvas canvas,
171 Tk_Item *itemPtr, double originX, double originY,
172 double scaleX, double scaleY));
173 static void TranslateRectOval _ANSI_ARGS_((Tk_Canvas canvas,
174 Tk_Item *itemPtr, double deltaX, double deltaY));
175
176 /*
177 * The structures below defines the rectangle and oval item types
178 * by means of procedures that can be invoked by generic item code.
179 */
180
181 Tk_ItemType tkRectangleType = {
182 "rectangle", /* name */
183 sizeof(RectOvalItem), /* itemSize */
184 CreateRectOval, /* createProc */
185 configSpecs, /* configSpecs */
186 ConfigureRectOval, /* configureProc */
187 RectOvalCoords, /* coordProc */
188 DeleteRectOval, /* deleteProc */
189 DisplayRectOval, /* displayProc */
190 TK_CONFIG_OBJS, /* flags */
191 RectToPoint, /* pointProc */
192 RectToArea, /* areaProc */
193 RectOvalToPostscript, /* postscriptProc */
194 ScaleRectOval, /* scaleProc */
195 TranslateRectOval, /* translateProc */
196 (Tk_ItemIndexProc *) NULL, /* indexProc */
197 (Tk_ItemCursorProc *) NULL, /* icursorProc */
198 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
199 (Tk_ItemInsertProc *) NULL, /* insertProc */
200 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
201 (Tk_ItemType *) NULL, /* nextPtr */
202 };
203
204 Tk_ItemType tkOvalType = {
205 "oval", /* name */
206 sizeof(RectOvalItem), /* itemSize */
207 CreateRectOval, /* createProc */
208 configSpecs, /* configSpecs */
209 ConfigureRectOval, /* configureProc */
210 RectOvalCoords, /* coordProc */
211 DeleteRectOval, /* deleteProc */
212 DisplayRectOval, /* displayProc */
213 TK_CONFIG_OBJS, /* flags */
214 OvalToPoint, /* pointProc */
215 OvalToArea, /* areaProc */
216 RectOvalToPostscript, /* postscriptProc */
217 ScaleRectOval, /* scaleProc */
218 TranslateRectOval, /* translateProc */
219 (Tk_ItemIndexProc *) NULL, /* indexProc */
220 (Tk_ItemCursorProc *) NULL, /* cursorProc */
221 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
222 (Tk_ItemInsertProc *) NULL, /* insertProc */
223 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
224 (Tk_ItemType *) NULL, /* nextPtr */
225 };
226
227 /*
228 *--------------------------------------------------------------
229 *
230 * CreateRectOval --
231 *
232 * This procedure is invoked to create a new rectangle
233 * or oval item in a canvas.
234 *
235 * Results:
236 * A standard Tcl return value. If an error occurred in
237 * creating the item, then an error message is left in
238 * the interp's result; in this case itemPtr is left uninitialized,
239 * so it can be safely freed by the caller.
240 *
241 * Side effects:
242 * A new rectangle or oval item is created.
243 *
244 *--------------------------------------------------------------
245 */
246
247 static int
248 CreateRectOval(interp, canvas, itemPtr, argc, argv)
249 Tcl_Interp *interp; /* For error reporting. */
250 Tk_Canvas canvas; /* Canvas to hold new item. */
251 Tk_Item *itemPtr; /* Record to hold new item; header
252 * has been initialized by caller. */
253 int argc; /* Number of arguments in argv. */
254 Tcl_Obj *CONST argv[]; /* Arguments describing rectangle. */
255 {
256 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
257 int i;
258
259
260 if (argc==1) {
261 i = 1;
262 } else {
263 char *arg = Tcl_GetStringFromObj(argv[1], NULL);
264 if ((argc>1) && (arg[0] == '-')
265 && (arg[1] >= 'a') && (arg[1] <= 'z')) {
266 i = 1;
267 } else {
268 i = 4;
269 }
270 }
271
272 if (argc < i) {
273 Tcl_AppendResult(interp, "wrong # args: should be \"",
274 Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
275 itemPtr->typePtr->name, " x1 y1 x2 y2 ?options?\"",
276 (char *) NULL);
277 return TCL_ERROR;
278 }
279
280 /*
281 * Carry out initialization that is needed in order to clean
282 * up after errors during the the remainder of this procedure.
283 */
284
285 Tk_CreateOutline(&(rectOvalPtr->outline));
286 rectOvalPtr->tsoffset.flags = 0;
287 rectOvalPtr->tsoffset.xoffset = 0;
288 rectOvalPtr->tsoffset.yoffset = 0;
289 rectOvalPtr->fillColor = NULL;
290 rectOvalPtr->activeFillColor = NULL;
291 rectOvalPtr->disabledFillColor = NULL;
292 rectOvalPtr->fillStipple = None;
293 rectOvalPtr->activeFillStipple = None;
294 rectOvalPtr->disabledFillStipple = None;
295 rectOvalPtr->fillGC = None;
296
297 /*
298 * Process the arguments to fill in the item record.
299 */
300
301 if ((RectOvalCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
302 goto error;
303 }
304 if (ConfigureRectOval(interp, canvas, itemPtr, argc-i, argv+i, 0)
305 == TCL_OK) {
306 return TCL_OK;
307 }
308
309 error:
310 DeleteRectOval(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
311 return TCL_ERROR;
312 }
313
314 /*
315 *--------------------------------------------------------------
316 *
317 * RectOvalCoords --
318 *
319 * This procedure is invoked to process the "coords" widget
320 * command on rectangles and ovals. See the user documentation
321 * for details on what it does.
322 *
323 * Results:
324 * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
325 *
326 * Side effects:
327 * The coordinates for the given item may be changed.
328 *
329 *--------------------------------------------------------------
330 */
331
332 static int
333 RectOvalCoords(interp, canvas, itemPtr, argc, argv)
334 Tcl_Interp *interp; /* Used for error reporting. */
335 Tk_Canvas canvas; /* Canvas containing item. */
336 Tk_Item *itemPtr; /* Item whose coordinates are to be
337 * read or modified. */
338 int argc; /* Number of coordinates supplied in
339 * argv. */
340 Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
341 * x2, y2, ... */
342 {
343 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
344
345 if (argc == 0) {
346 Tcl_Obj *obj = Tcl_NewObj();
347 Tcl_Obj *subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[0]);
348 Tcl_ListObjAppendElement(interp, obj, subobj);
349 subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[1]);
350 Tcl_ListObjAppendElement(interp, obj, subobj);
351 subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[2]);
352 Tcl_ListObjAppendElement(interp, obj, subobj);
353 subobj = Tcl_NewDoubleObj(rectOvalPtr->bbox[3]);
354 Tcl_ListObjAppendElement(interp, obj, subobj);
355 Tcl_SetObjResult(interp, obj);
356 } else if ((argc == 1)||(argc == 4)) {
357 if (argc==1) {
358 if (Tcl_ListObjGetElements(interp, argv[0], &argc,
359 (Tcl_Obj ***) &argv) != TCL_OK) {
360 return TCL_ERROR;
361 } else if (argc != 4) {
362 char buf[64 + TCL_INTEGER_SPACE];
363
364 sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
365 Tcl_SetResult(interp, buf, TCL_VOLATILE);
366 return TCL_ERROR;
367 }
368 }
369 if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0],
370 &rectOvalPtr->bbox[0]) != TCL_OK)
371 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
372 &rectOvalPtr->bbox[1]) != TCL_OK)
373 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[2],
374 &rectOvalPtr->bbox[2]) != TCL_OK)
375 || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[3],
376 &rectOvalPtr->bbox[3]) != TCL_OK)) {
377 return TCL_ERROR;
378 }
379 ComputeRectOvalBbox(canvas, rectOvalPtr);
380 } else {
381 char buf[64 + TCL_INTEGER_SPACE];
382
383 sprintf(buf, "wrong # coordinates: expected 0 or 4, got %d", argc);
384 Tcl_SetResult(interp, buf, TCL_VOLATILE);
385 return TCL_ERROR;
386 }
387 return TCL_OK;
388 }
389
390 /*
391 *--------------------------------------------------------------
392 *
393 * ConfigureRectOval --
394 *
395 * This procedure is invoked to configure various aspects
396 * of a rectangle or oval item, such as its border and
397 * background colors.
398 *
399 * Results:
400 * A standard Tcl result code. If an error occurs, then
401 * an error message is left in the interp's result.
402 *
403 * Side effects:
404 * Configuration information, such as colors and stipple
405 * patterns, may be set for itemPtr.
406 *
407 *--------------------------------------------------------------
408 */
409
410 static int
411 ConfigureRectOval(interp, canvas, itemPtr, argc, argv, flags)
412 Tcl_Interp *interp; /* Used for error reporting. */
413 Tk_Canvas canvas; /* Canvas containing itemPtr. */
414 Tk_Item *itemPtr; /* Rectangle item to reconfigure. */
415 int argc; /* Number of elements in argv. */
416 Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
417 int flags; /* Flags to pass to Tk_ConfigureWidget. */
418 {
419 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
420 XGCValues gcValues;
421 GC newGC;
422 unsigned long mask;
423 Tk_Window tkwin;
424 Tk_TSOffset *tsoffset;
425 XColor *color;
426 Pixmap stipple;
427 Tk_State state;
428
429 tkwin = Tk_CanvasTkwin(canvas);
430
431 if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
432 (char *) rectOvalPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
433 return TCL_ERROR;
434 }
435 state = itemPtr->state;
436
437 /*
438 * A few of the options require additional processing, such as
439 * graphics contexts.
440 */
441
442 if (rectOvalPtr->outline.activeWidth > rectOvalPtr->outline.width ||
443 rectOvalPtr->outline.activeDash.number != 0 ||
444 rectOvalPtr->outline.activeColor != NULL ||
445 rectOvalPtr->outline.activeStipple != None ||
446 rectOvalPtr->activeFillColor != NULL ||
447 rectOvalPtr->activeFillStipple != None) {
448 itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
449 } else {
450 itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
451 }
452
453 tsoffset = &rectOvalPtr->outline.tsoffset;
454 flags = tsoffset->flags;
455 if (flags & TK_OFFSET_LEFT) {
456 tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
457 } else if (flags & TK_OFFSET_CENTER) {
458 tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
459 } else if (flags & TK_OFFSET_RIGHT) {
460 tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
461 }
462 if (flags & TK_OFFSET_TOP) {
463 tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
464 } else if (flags & TK_OFFSET_MIDDLE) {
465 tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
466 } else if (flags & TK_OFFSET_BOTTOM) {
467 tsoffset->yoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
468 }
469
470 /*
471 * Configure the outline graphics context. If mask is non-zero,
472 * the gc has changed and must be reallocated, provided that the
473 * new settings specify a valid outline (non-zero width and non-NULL
474 * color)
475 */
476
477 mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
478 &(rectOvalPtr->outline));
479 if (mask && \
480 rectOvalPtr->outline.width != 0 && \
481 rectOvalPtr->outline.color != NULL) {
482 gcValues.cap_style = CapProjecting;
483 mask |= GCCapStyle;
484 newGC = Tk_GetGC(tkwin, mask, &gcValues);
485 } else {
486 newGC = None;
487 }
488 if (rectOvalPtr->outline.gc != None) {
489 Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->outline.gc);
490 }
491 rectOvalPtr->outline.gc = newGC;
492
493 if(state == TK_STATE_NULL) {
494 state = ((TkCanvas *)canvas)->canvas_state;
495 }
496 if (state==TK_STATE_HIDDEN) {
497 ComputeRectOvalBbox(canvas, rectOvalPtr);
498 return TCL_OK;
499 }
500
501 color = rectOvalPtr->fillColor;
502 stipple = rectOvalPtr->fillStipple;
503 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
504 if (rectOvalPtr->activeFillColor!=NULL) {
505 color = rectOvalPtr->activeFillColor;
506 }
507 if (rectOvalPtr->activeFillStipple!=None) {
508 stipple = rectOvalPtr->activeFillStipple;
509 }
510 } else if (state==TK_STATE_DISABLED) {
511 if (rectOvalPtr->disabledFillColor!=NULL) {
512 color = rectOvalPtr->disabledFillColor;
513 }
514 if (rectOvalPtr->disabledFillStipple!=None) {
515 stipple = rectOvalPtr->disabledFillStipple;
516 }
517 }
518
519 if (color == NULL) {
520 newGC = None;
521 } else {
522 gcValues.foreground = color->pixel;
523 if (stipple != None) {
524 gcValues.stipple = stipple;
525 gcValues.fill_style = FillStippled;
526 mask = GCForeground|GCStipple|GCFillStyle;
527 } else {
528 mask = GCForeground;
529 }
530 newGC = Tk_GetGC(tkwin, mask, &gcValues);
531 }
532 if (rectOvalPtr->fillGC != None) {
533 Tk_FreeGC(Tk_Display(tkwin), rectOvalPtr->fillGC);
534 }
535 rectOvalPtr->fillGC = newGC;
536
537 tsoffset = &rectOvalPtr->tsoffset;
538 flags = tsoffset->flags;
539 if (flags & TK_OFFSET_LEFT) {
540 tsoffset->xoffset = (int) (rectOvalPtr->bbox[0] + 0.5);
541 } else if (flags & TK_OFFSET_CENTER) {
542 tsoffset->xoffset = (int) ((rectOvalPtr->bbox[0]+rectOvalPtr->bbox[2]+1)/2);
543 } else if (flags & TK_OFFSET_RIGHT) {
544 tsoffset->xoffset = (int) (rectOvalPtr->bbox[2] + 0.5);
545 }
546 if (flags & TK_OFFSET_TOP) {
547 tsoffset->yoffset = (int) (rectOvalPtr->bbox[1] + 0.5);
548 } else if (flags & TK_OFFSET_MIDDLE) {
549 tsoffset->yoffset = (int) ((rectOvalPtr->bbox[1]+rectOvalPtr->bbox[3]+1)/2);
550 } else if (flags & TK_OFFSET_BOTTOM) {
551 tsoffset->yoffset = (int) (rectOvalPtr->bbox[3] + 0.5);
552 }
553
554 ComputeRectOvalBbox(canvas, rectOvalPtr);
555
556 return TCL_OK;
557 }
558
559 /*
560 *--------------------------------------------------------------
561 *
562 * DeleteRectOval --
563 *
564 * This procedure is called to clean up the data structure
565 * associated with a rectangle or oval item.
566 *
567 * Results:
568 * None.
569 *
570 * Side effects:
571 * Resources associated with itemPtr are released.
572 *
573 *--------------------------------------------------------------
574 */
575
576 static void
577 DeleteRectOval(canvas, itemPtr, display)
578 Tk_Canvas canvas; /* Info about overall widget. */
579 Tk_Item *itemPtr; /* Item that is being deleted. */
580 Display *display; /* Display containing window for
581 * canvas. */
582 {
583 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
584
585 Tk_DeleteOutline(display, &(rectOvalPtr->outline));
586 if (rectOvalPtr->fillColor != NULL) {
587 Tk_FreeColor(rectOvalPtr->fillColor);
588 }
589 if (rectOvalPtr->activeFillColor != NULL) {
590 Tk_FreeColor(rectOvalPtr->activeFillColor);
591 }
592 if (rectOvalPtr->disabledFillColor != NULL) {
593 Tk_FreeColor(rectOvalPtr->disabledFillColor);
594 }
595 if (rectOvalPtr->fillStipple != None) {
596 Tk_FreeBitmap(display, rectOvalPtr->fillStipple);
597 }
598 if (rectOvalPtr->activeFillStipple != None) {
599 Tk_FreeBitmap(display, rectOvalPtr->activeFillStipple);
600 }
601 if (rectOvalPtr->disabledFillStipple != None) {
602 Tk_FreeBitmap(display, rectOvalPtr->disabledFillStipple);
603 }
604 if (rectOvalPtr->fillGC != None) {
605 Tk_FreeGC(display, rectOvalPtr->fillGC);
606 }
607 }
608
609 /*
610 *--------------------------------------------------------------
611 *
612 * ComputeRectOvalBbox --
613 *
614 * This procedure is invoked to compute the bounding box of
615 * all the pixels that may be drawn as part of a rectangle
616 * or oval.
617 *
618 * Results:
619 * None.
620 *
621 * Side effects:
622 * The fields x1, y1, x2, and y2 are updated in the header
623 * for itemPtr.
624 *
625 *--------------------------------------------------------------
626 */
627
628 /* ARGSUSED */
629 static void
630 ComputeRectOvalBbox(canvas, rectOvalPtr)
631 Tk_Canvas canvas; /* Canvas that contains item. */
632 RectOvalItem *rectOvalPtr; /* Item whose bbox is to be
633 * recomputed. */
634 {
635 int bloat, tmp;
636 double dtmp, width;
637 Tk_State state = rectOvalPtr->header.state;
638
639 if(state == TK_STATE_NULL) {
640 state = ((TkCanvas *)canvas)->canvas_state;
641 }
642
643 width = rectOvalPtr->outline.width;
644 if (state==TK_STATE_HIDDEN) {
645 rectOvalPtr->header.x1 = rectOvalPtr->header.y1 =
646 rectOvalPtr->header.x2 = rectOvalPtr->header.y2 = -1;
647 return;
648 }
649 if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
650 if (rectOvalPtr->outline.activeWidth>width) {
651 width = rectOvalPtr->outline.activeWidth;
652 }
653 } else if (state==TK_STATE_DISABLED) {
654 if (rectOvalPtr->outline.disabledWidth>0) {
655 width = rectOvalPtr->outline.disabledWidth;
656 }
657 }
658
659 /*
660 * Make sure that the first coordinates are the lowest ones.
661 */
662
663 if (rectOvalPtr->bbox[1] > rectOvalPtr->bbox[3]) {
664 double tmp;
665 tmp = rectOvalPtr->bbox[3];
666 rectOvalPtr->bbox[3] = rectOvalPtr->bbox[1];
667 rectOvalPtr->bbox[1] = tmp;
668 }
669 if (rectOvalPtr->bbox[0] > rectOvalPtr->bbox[2]) {
670 double tmp;
671 tmp = rectOvalPtr->bbox[2];
672 rectOvalPtr->bbox[2] = rectOvalPtr->bbox[0];
673 rectOvalPtr->bbox[0] = tmp;
674 }
675
676 if (rectOvalPtr->outline.gc == None) {
677 /*
678 * The Win32 switch was added for 8.3 to solve a problem
679 * with ovals leaving traces on bottom and right of 1 pixel.
680 * This may not be the correct place to solve it, but it works.
681 */
682 #ifdef __WIN32__
683 bloat = 1;
684 #else
685 bloat = 0;
686 #endif
687 } else {
688 bloat = (int) (width+1)/2;
689 }
690
691 /*
692 * Special note: the rectangle is always drawn at least 1x1 in
693 * size, so round up the upper coordinates to be at least 1 unit
694 * greater than the lower ones.
695 */
696
697 tmp = (int) ((rectOvalPtr->bbox[0] >= 0) ? rectOvalPtr->bbox[0] + .5
698 : rectOvalPtr->bbox[0] - .5);
699 rectOvalPtr->header.x1 = tmp - bloat;
700 tmp = (int) ((rectOvalPtr->bbox[1] >= 0) ? rectOvalPtr->bbox[1] + .5
701 : rectOvalPtr->bbox[1] - .5);
702 rectOvalPtr->header.y1 = tmp - bloat;
703 dtmp = rectOvalPtr->bbox[2];
704 if (dtmp < (rectOvalPtr->bbox[0] + 1)) {
705 dtmp = rectOvalPtr->bbox[0] + 1;
706 }
707 tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
708 rectOvalPtr->header.x2 = tmp + bloat;
709 dtmp = rectOvalPtr->bbox[3];
710 if (dtmp < (rectOvalPtr->bbox[1] + 1)) {
711 dtmp = rectOvalPtr->bbox[1] + 1;
712 }
713 tmp = (int) ((dtmp >= 0) ? dtmp + .5 : dtmp - .5);
714 rectOvalPtr->header.y2 = tmp + bloat;
715 }
716
717 /*
718 *--------------------------------------------------------------
719 *
720 * DisplayRectOval --
721 *
722 * This procedure is invoked to draw a rectangle or oval
723 * item in a given drawable.
724 *
725 * Results:
726 * None.
727 *
728 * Side effects:
729 * ItemPtr is drawn in drawable using the transformation
730 * information in canvas.
731 *
732 *--------------------------------------------------------------
733 */
734
735 static void
736 DisplayRectOval(canvas, itemPtr, display, drawable, x, y, width, height)
737 Tk_Canvas canvas; /* Canvas that contains item. */
738 Tk_Item *itemPtr; /* Item to be displayed. */
739 Display *display; /* Display on which to draw item. */
740 Drawable drawable; /* Pixmap or window in which to draw
741 * item. */
742 int x, y, width, height; /* Describes region of canvas that
743 * must be redisplayed (not used). */
744 {
745 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
746 short x1, y1, x2, y2;
747 Pixmap fillStipple;
748 Tk_State state = itemPtr->state;
749
750 /*
751 * Compute the screen coordinates of the bounding box for the item.
752 * Make sure that the bbox is at least one pixel large, since some
753 * X servers will die if it isn't.
754 */
755
756 Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0], rectOvalPtr->bbox[1],
757 &x1, &y1);
758 Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2], rectOvalPtr->bbox[3],
759 &x2, &y2);
760 if (x2 <= x1) {
761 x2 = x1+1;
762 }
763 if (y2 <= y1) {
764 y2 = y1+1;
765 }
766
767 /*
768 * Display filled part first (if wanted), then outline. If we're
769 * stippling, then modify the stipple offset in the GC. Be sure to
770 * reset the offset when done, since the GC is supposed to be
771 * read-only.
772 */
773
774 if(state == TK_STATE_NULL) {
775 state = ((TkCanvas *)canvas)->canvas_state;
776 }
777 fillStipple = rectOvalPtr->fillStipple;
778 if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)rectOvalPtr) {
779 if (rectOvalPtr->activeFillStipple!=None) {
780 fillStipple = rectOvalPtr->activeFillStipple;
781 }
782 } else if (state==TK_STATE_DISABLED) {
783 if (rectOvalPtr->disabledFillStipple!=None) {
784 fillStipple = rectOvalPtr->disabledFillStipple;
785 }
786 }
787
788 if (rectOvalPtr->fillGC != None) {
789 if (fillStipple != None) {
790 Tk_TSOffset *tsoffset;
791 int w=0; int h=0;
792 tsoffset = &rectOvalPtr->tsoffset;
793 if (tsoffset) {
794 int flags = tsoffset->flags;
795 if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
796 Tk_SizeOfBitmap(display, fillStipple, &w, &h);
797 if (flags & TK_OFFSET_CENTER) {
798 w /= 2;
799 } else {
800 w = 0;
801 }
802 if (flags & TK_OFFSET_MIDDLE) {
803 h /= 2;
804 } else {
805 h = 0;
806 }
807 }
808 tsoffset->xoffset -= w;
809 tsoffset->yoffset -= h;
810 }
811 Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);
812 if (tsoffset) {
813 tsoffset->xoffset += w;
814 tsoffset->yoffset += h;
815 }
816 }
817 if (rectOvalPtr->header.typePtr == &tkRectangleType) {
818 XFillRectangle(display, drawable, rectOvalPtr->fillGC,
819 x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
820 } else {
821 XFillArc(display, drawable, rectOvalPtr->fillGC,
822 x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
823 0, 360*64);
824 }
825 if (fillStipple != None) {
826 XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
827 }
828 }
829 if (rectOvalPtr->outline.gc != None) {
830 Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
831 if (rectOvalPtr->header.typePtr == &tkRectangleType) {
832 XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
833 x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
834 } else {
835 XDrawArc(display, drawable, rectOvalPtr->outline.gc,
836 x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
837 }
838 Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
839 }
840 }
841
842 /*
843 *--------------------------------------------------------------
844 *
845 * RectToPoint --
846 *
847 * Computes the distance from a given point to a given
848 * rectangle, in canvas units.
849 *
850 * Results:
851 * The return value is 0 if the point whose x and y coordinates
852 * are coordPtr[0] and coordPtr[1] is inside the rectangle. If the
853 * point isn't inside the rectangle then the return value is the
854 * distance from the point to the rectangle. If itemPtr is filled,
855 * then anywhere in the interior is considered "inside"; if
856 * itemPtr isn't filled, then "inside" means only the area
857 * occupied by the outline.
858 *
859 * Side effects:
860 * None.
861 *
862 *--------------------------------------------------------------
863 */
864
865 /* ARGSUSED */
866 static double
867 RectToPoint(canvas, itemPtr, pointPtr)
868 Tk_Canvas canvas; /* Canvas containing item. */
869 Tk_Item *itemPtr; /* Item to check against point. */
870 double *pointPtr; /* Pointer to x and y coordinates. */
871 {
872 RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
873 double xDiff, yDiff, x1, y1, x2, y2, inc, tmp;
874 double width;
875 Tk_State state = itemPtr->state;
876
877 if(state == TK_STATE_NULL) {
878 state = ((TkCanvas *)canvas)->canvas_state;
879 }
880
881 width = rectPtr->outline.width;
882 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
883 if (rectPtr->outline.activeWidth>width) {
884 width = rectPtr->outline.activeWidth;
885 }
886 } else if (state==TK_STATE_DISABLED) {
887 if (rectPtr->outline.disabledWidth>0) {
888 width = rectPtr->outline.disabledWidth;
889 }
890 }
891
892 /*
893 * Generate a new larger rectangle that includes the border
894 * width, if there is one.
895 */
896
897 x1 = rectPtr->bbox[0];
898 y1 = rectPtr->bbox[1];
899 x2 = rectPtr->bbox[2];
900 y2 = rectPtr->bbox[3];
901 if (rectPtr->outline.gc != None) {
902 inc = width/2.0;
903 x1 -= inc;
904 y1 -= inc;
905 x2 += inc;
906 y2 += inc;
907 }
908
909 /*
910 * If the point is inside the rectangle, handle specially:
911 * distance is 0 if rectangle is filled, otherwise compute
912 * distance to nearest edge of rectangle and subtract width
913 * of edge.
914 */
915
916 if ((pointPtr[0] >= x1) && (pointPtr[0] < x2)
917 && (pointPtr[1] >= y1) && (pointPtr[1] < y2)) {
918 if ((rectPtr->fillGC != None) || (rectPtr->outline.gc == None)) {
919 return 0.0;
920 }
921 xDiff = pointPtr[0] - x1;
922 tmp = x2 - pointPtr[0];
923 if (tmp < xDiff) {
924 xDiff = tmp;
925 }
926 yDiff = pointPtr[1] - y1;
927 tmp = y2 - pointPtr[1];
928 if (tmp < yDiff) {
929 yDiff = tmp;
930 }
931 if (yDiff < xDiff) {
932 xDiff = yDiff;
933 }
934 xDiff -= width;
935 if (xDiff < 0.0) {
936 return 0.0;
937 }
938 return xDiff;
939 }
940
941 /*
942 * Point is outside rectangle.
943 */
944
945 if (pointPtr[0] < x1) {
946 xDiff = x1 - pointPtr[0];
947 } else if (pointPtr[0] > x2) {
948 xDiff = pointPtr[0] - x2;
949 } else {
950 xDiff = 0;
951 }
952
953 if (pointPtr[1] < y1) {
954 yDiff = y1 - pointPtr[1];
955 } else if (pointPtr[1] > y2) {
956 yDiff = pointPtr[1] - y2;
957 } else {
958 yDiff = 0;
959 }
960
961 return hypot(xDiff, yDiff);
962 }
963
964 /*
965 *--------------------------------------------------------------
966 *
967 * OvalToPoint --
968 *
969 * Computes the distance from a given point to a given
970 * oval, in canvas units.
971 *
972 * Results:
973 * The return value is 0 if the point whose x and y coordinates
974 * are coordPtr[0] and coordPtr[1] is inside the oval. If the
975 * point isn't inside the oval then the return value is the
976 * distance from the point to the oval. If itemPtr is filled,
977 * then anywhere in the interior is considered "inside"; if
978 * itemPtr isn't filled, then "inside" means only the area
979 * occupied by the outline.
980 *
981 * Side effects:
982 * None.
983 *
984 *--------------------------------------------------------------
985 */
986
987 /* ARGSUSED */
988 static double
989 OvalToPoint(canvas, itemPtr, pointPtr)
990 Tk_Canvas canvas; /* Canvas containing item. */
991 Tk_Item *itemPtr; /* Item to check against point. */
992 double *pointPtr; /* Pointer to x and y coordinates. */
993 {
994 RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
995 double width;
996 int filled;
997 Tk_State state = itemPtr->state;
998
999 if(state == TK_STATE_NULL) {
1000 state = ((TkCanvas *)canvas)->canvas_state;
1001 }
1002
1003 width = (double) ovalPtr->outline.width;
1004 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1005 if (ovalPtr->outline.activeWidth>width) {
1006 width = (double) ovalPtr->outline.activeWidth;
1007 }
1008 } else if (state==TK_STATE_DISABLED) {
1009 if (ovalPtr->outline.disabledWidth>0) {
1010 width = (double) ovalPtr->outline.disabledWidth;
1011 }
1012 }
1013
1014
1015 filled = ovalPtr->fillGC != None;
1016 if (ovalPtr->outline.gc == None) {
1017 width = 0.0;
1018 filled = 1;
1019 }
1020 return TkOvalToPoint(ovalPtr->bbox, width, filled, pointPtr);
1021 }
1022
1023 /*
1024 *--------------------------------------------------------------
1025 *
1026 * RectToArea --
1027 *
1028 * This procedure is called to determine whether an item
1029 * lies entirely inside, entirely outside, or overlapping
1030 * a given rectangle.
1031 *
1032 * Results:
1033 * -1 is returned if the item is entirely outside the area
1034 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1035 * inside the given area.
1036 *
1037 * Side effects:
1038 * None.
1039 *
1040 *--------------------------------------------------------------
1041 */
1042
1043 /* ARGSUSED */
1044 static int
1045 RectToArea(canvas, itemPtr, areaPtr)
1046 Tk_Canvas canvas; /* Canvas containing item. */
1047 Tk_Item *itemPtr; /* Item to check against rectangle. */
1048 double *areaPtr; /* Pointer to array of four coordinates
1049 * (x1, y1, x2, y2) describing rectangular
1050 * area. */
1051 {
1052 RectOvalItem *rectPtr = (RectOvalItem *) itemPtr;
1053 double halfWidth;
1054 double width;
1055 Tk_State state = itemPtr->state;
1056
1057 if(state == TK_STATE_NULL) {
1058 state = ((TkCanvas *)canvas)->canvas_state;
1059 }
1060
1061 width = rectPtr->outline.width;
1062 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1063 if (rectPtr->outline.activeWidth>width) {
1064 width = rectPtr->outline.activeWidth;
1065 }
1066 } else if (state==TK_STATE_DISABLED) {
1067 if (rectPtr->outline.disabledWidth>0) {
1068 width = rectPtr->outline.disabledWidth;
1069 }
1070 }
1071
1072 halfWidth = width/2.0;
1073 if (rectPtr->outline.gc == None) {
1074 halfWidth = 0.0;
1075 }
1076
1077 if ((areaPtr[2] <= (rectPtr->bbox[0] - halfWidth))
1078 || (areaPtr[0] >= (rectPtr->bbox[2] + halfWidth))
1079 || (areaPtr[3] <= (rectPtr->bbox[1] - halfWidth))
1080 || (areaPtr[1] >= (rectPtr->bbox[3] + halfWidth))) {
1081 return -1;
1082 }
1083 if ((rectPtr->fillGC == None) && (rectPtr->outline.gc != None)
1084 && (areaPtr[0] >= (rectPtr->bbox[0] + halfWidth))
1085 && (areaPtr[1] >= (rectPtr->bbox[1] + halfWidth))
1086 && (areaPtr[2] <= (rectPtr->bbox[2] - halfWidth))
1087 && (areaPtr[3] <= (rectPtr->bbox[3] - halfWidth))) {
1088 return -1;
1089 }
1090 if ((areaPtr[0] <= (rectPtr->bbox[0] - halfWidth))
1091 && (areaPtr[1] <= (rectPtr->bbox[1] - halfWidth))
1092 && (areaPtr[2] >= (rectPtr->bbox[2] + halfWidth))
1093 && (areaPtr[3] >= (rectPtr->bbox[3] + halfWidth))) {
1094 return 1;
1095 }
1096 return 0;
1097 }
1098
1099 /*
1100 *--------------------------------------------------------------
1101 *
1102 * OvalToArea --
1103 *
1104 * This procedure is called to determine whether an item
1105 * lies entirely inside, entirely outside, or overlapping
1106 * a given rectangular area.
1107 *
1108 * Results:
1109 * -1 is returned if the item is entirely outside the area
1110 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1111 * inside the given area.
1112 *
1113 * Side effects:
1114 * None.
1115 *
1116 *--------------------------------------------------------------
1117 */
1118
1119 /* ARGSUSED */
1120 static int
1121 OvalToArea(canvas, itemPtr, areaPtr)
1122 Tk_Canvas canvas; /* Canvas containing item. */
1123 Tk_Item *itemPtr; /* Item to check against oval. */
1124 double *areaPtr; /* Pointer to array of four coordinates
1125 * (x1, y1, x2, y2) describing rectangular
1126 * area. */
1127 {
1128 RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
1129 double oval[4], halfWidth;
1130 int result;
1131 double width;
1132 Tk_State state = itemPtr->state;
1133
1134 if(state == TK_STATE_NULL) {
1135 state = ((TkCanvas *)canvas)->canvas_state;
1136 }
1137
1138 width = ovalPtr->outline.width;
1139 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1140 if (ovalPtr->outline.activeWidth>width) {
1141 width = ovalPtr->outline.activeWidth;
1142 }
1143 } else if (state==TK_STATE_DISABLED) {
1144 if (ovalPtr->outline.disabledWidth>0) {
1145 width = ovalPtr->outline.disabledWidth;
1146 }
1147 }
1148
1149 /*
1150 * Expand the oval to include the width of the outline, if any.
1151 */
1152
1153 halfWidth = width/2.0;
1154 if (ovalPtr->outline.gc == None) {
1155 halfWidth = 0.0;
1156 }
1157 oval[0] = ovalPtr->bbox[0] - halfWidth;
1158 oval[1] = ovalPtr->bbox[1] - halfWidth;
1159 oval[2] = ovalPtr->bbox[2] + halfWidth;
1160 oval[3] = ovalPtr->bbox[3] + halfWidth;
1161
1162 result = TkOvalToArea(oval, areaPtr);
1163
1164 /*
1165 * If the rectangle appears to overlap the oval and the oval
1166 * isn't filled, do one more check to see if perhaps all four
1167 * of the rectangle's corners are totally inside the oval's
1168 * unfilled center, in which case we should return "outside".
1169 */
1170
1171 if ((result == 0) && (ovalPtr->outline.gc != None)
1172 && (ovalPtr->fillGC == None)) {
1173 double centerX, centerY, height;
1174 double xDelta1, yDelta1, xDelta2, yDelta2;
1175
1176 centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
1177 centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
1178 width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
1179 height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
1180 xDelta1 = (areaPtr[0] - centerX)/width;
1181 xDelta1 *= xDelta1;
1182 yDelta1 = (areaPtr[1] - centerY)/height;
1183 yDelta1 *= yDelta1;
1184 xDelta2 = (areaPtr[2] - centerX)/width;
1185 xDelta2 *= xDelta2;
1186 yDelta2 = (areaPtr[3] - centerY)/height;
1187 yDelta2 *= yDelta2;
1188 if (((xDelta1 + yDelta1) < 1.0)
1189 && ((xDelta1 + yDelta2) < 1.0)
1190 && ((xDelta2 + yDelta1) < 1.0)
1191 && ((xDelta2 + yDelta2) < 1.0)) {
1192 return -1;
1193 }
1194 }
1195 return result;
1196 }
1197
1198 /*
1199 *--------------------------------------------------------------
1200 *
1201 * ScaleRectOval --
1202 *
1203 * This procedure is invoked to rescale a rectangle or oval
1204 * item.
1205 *
1206 * Results:
1207 * None.
1208 *
1209 * Side effects:
1210 * The rectangle or oval referred to by itemPtr is rescaled
1211 * so that the following transformation is applied to all
1212 * point coordinates:
1213 * x' = originX + scaleX*(x-originX)
1214 * y' = originY + scaleY*(y-originY)
1215 *
1216 *--------------------------------------------------------------
1217 */
1218
1219 static void
1220 ScaleRectOval(canvas, itemPtr, originX, originY, scaleX, scaleY)
1221 Tk_Canvas canvas; /* Canvas containing rectangle. */
1222 Tk_Item *itemPtr; /* Rectangle to be scaled. */
1223 double originX, originY; /* Origin about which to scale rect. */
1224 double scaleX; /* Amount to scale in X direction. */
1225 double scaleY; /* Amount to scale in Y direction. */
1226 {
1227 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1228
1229 rectOvalPtr->bbox[0] = originX + scaleX*(rectOvalPtr->bbox[0] - originX);
1230 rectOvalPtr->bbox[1] = originY + scaleY*(rectOvalPtr->bbox[1] - originY);
1231 rectOvalPtr->bbox[2] = originX + scaleX*(rectOvalPtr->bbox[2] - originX);
1232 rectOvalPtr->bbox[3] = originY + scaleY*(rectOvalPtr->bbox[3] - originY);
1233 ComputeRectOvalBbox(canvas, rectOvalPtr);
1234 }
1235
1236 /*
1237 *--------------------------------------------------------------
1238 *
1239 * TranslateRectOval --
1240 *
1241 * This procedure is called to move a rectangle or oval by a
1242 * given amount.
1243 *
1244 * Results:
1245 * None.
1246 *
1247 * Side effects:
1248 * The position of the rectangle or oval is offset by
1249 * (xDelta, yDelta), and the bounding box is updated in the
1250 * generic part of the item structure.
1251 *
1252 *--------------------------------------------------------------
1253 */
1254
1255 static void
1256 TranslateRectOval(canvas, itemPtr, deltaX, deltaY)
1257 Tk_Canvas canvas; /* Canvas containing item. */
1258 Tk_Item *itemPtr; /* Item that is being moved. */
1259 double deltaX, deltaY; /* Amount by which item is to be
1260 * moved. */
1261 {
1262 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1263
1264 rectOvalPtr->bbox[0] += deltaX;
1265 rectOvalPtr->bbox[1] += deltaY;
1266 rectOvalPtr->bbox[2] += deltaX;
1267 rectOvalPtr->bbox[3] += deltaY;
1268 ComputeRectOvalBbox(canvas, rectOvalPtr);
1269 }
1270
1271 /*
1272 *--------------------------------------------------------------
1273 *
1274 * RectOvalToPostscript --
1275 *
1276 * This procedure is called to generate Postscript for
1277 * rectangle and oval items.
1278 *
1279 * Results:
1280 * The return value is a standard Tcl result. If an error
1281 * occurs in generating Postscript then an error message is
1282 * left in the interp's result, replacing whatever used to be there.
1283 * If no error occurs, then Postscript for the rectangle is
1284 * appended to the result.
1285 *
1286 * Side effects:
1287 * None.
1288 *
1289 *--------------------------------------------------------------
1290 */
1291
1292 static int
1293 RectOvalToPostscript(interp, canvas, itemPtr, prepass)
1294 Tcl_Interp *interp; /* Interpreter for error reporting. */
1295 Tk_Canvas canvas; /* Information about overall canvas. */
1296 Tk_Item *itemPtr; /* Item for which Postscript is
1297 * wanted. */
1298 int prepass; /* 1 means this is a prepass to
1299 * collect font information; 0 means
1300 * final Postscript is being created. */
1301 {
1302 char pathCmd[500];
1303 RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
1304 double y1, y2;
1305 XColor *color;
1306 XColor *fillColor;
1307 Pixmap fillStipple;
1308 Tk_State state = itemPtr->state;
1309
1310 y1 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[1]);
1311 y2 = Tk_CanvasPsY(canvas, rectOvalPtr->bbox[3]);
1312
1313 /*
1314 * Generate a string that creates a path for the rectangle or oval.
1315 * This is the only part of the procedure's code that is type-
1316 * specific.
1317 */
1318
1319
1320 if (rectOvalPtr->header.typePtr == &tkRectangleType) {
1321 sprintf(pathCmd, "%.15g %.15g moveto %.15g 0 rlineto 0 %.15g rlineto %.15g 0 rlineto closepath\n",
1322 rectOvalPtr->bbox[0], y1,
1323 rectOvalPtr->bbox[2]-rectOvalPtr->bbox[0], y2-y1,
1324 rectOvalPtr->bbox[0]-rectOvalPtr->bbox[2]);
1325 } else {
1326 sprintf(pathCmd, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
1327 (rectOvalPtr->bbox[0] + rectOvalPtr->bbox[2])/2, (y1 + y2)/2,
1328 (rectOvalPtr->bbox[2] - rectOvalPtr->bbox[0])/2, (y1 - y2)/2);
1329 }
1330
1331 if(state == TK_STATE_NULL) {
1332 state = ((TkCanvas *)canvas)->canvas_state;
1333 }
1334 color = rectOvalPtr->outline.color;
1335 fillColor = rectOvalPtr->fillColor;
1336 fillStipple = rectOvalPtr->fillStipple;
1337 if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1338 if (rectOvalPtr->outline.activeColor!=NULL) {
1339 color = rectOvalPtr->outline.activeColor;
1340 }
1341 if (rectOvalPtr->activeFillColor!=NULL) {
1342 fillColor = rectOvalPtr->activeFillColor;
1343 }
1344 if (rectOvalPtr->activeFillStipple!=None) {
1345 fillStipple = rectOvalPtr->activeFillStipple;
1346 }
1347 } else if (state==TK_STATE_DISABLED) {
1348 if (rectOvalPtr->outline.disabledColor!=NULL) {
1349 color = rectOvalPtr->outline.disabledColor;
1350 }
1351 if (rectOvalPtr->disabledFillColor!=NULL) {
1352 fillColor = rectOvalPtr->disabledFillColor;
1353 }
1354 if (rectOvalPtr->disabledFillStipple!=None) {
1355 fillStipple = rectOvalPtr->disabledFillStipple;
1356 }
1357 }
1358
1359 /*
1360 * First draw the filled area of the rectangle.
1361 */
1362
1363 if (fillColor != NULL) {
1364 Tcl_AppendResult(interp, pathCmd, (char *) NULL);
1365 if (Tk_CanvasPsColor(interp, canvas, fillColor)
1366 != TCL_OK) {
1367 return TCL_ERROR;
1368 }
1369 if (fillStipple != None) {
1370 Tcl_AppendResult(interp, "clip ", (char *) NULL);
1371 if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
1372 != TCL_OK) {
1373 return TCL_ERROR;
1374 }
1375 if (color != NULL) {
1376 Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1377 }
1378 } else {
1379 Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1380 }
1381 }
1382
1383 /*
1384 * Now draw the outline, if there is one.
1385 */
1386
1387 if (color != NULL) {
1388 Tcl_AppendResult(interp, pathCmd, "0 setlinejoin 2 setlinecap\n",
1389 (char *) NULL);
1390 if (Tk_CanvasPsOutline(canvas, itemPtr,
1391 &(rectOvalPtr->outline))!= TCL_OK) {
1392 return TCL_ERROR;
1393 }
1394 }
1395 return TCL_OK;
1396 }
1397
1398 /* End of tkrectoval.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25