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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (7 years, 4 months ago) by dashley
File MIME type: text/plain
File size: 45225 byte(s)
License and property (keyword) changes.
1 dashley 69 /* $Header$ */
2 dashley 25
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 dashley 69 /* End of tkrectoval.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25