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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (hide annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (7 years, 6 months ago) by dashley
File MIME type: text/plain
File size: 60939 byte(s)
License and property (keyword) changes.
1 dashley 69 /* $Header$ */
2 dashley 25
3     /*
4     * tkCanvPoly.c --
5     *
6     * This file implements polygon items for canvas widgets.
7     *
8     * Copyright (c) 1991-1994 The Regents of the University of California.
9     * Copyright (c) 1994-1997 Sun Microsystems, Inc.
10     *
11     * See the file "license.terms" for information on usage and redistribution
12     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13     *
14     * RCS: @(#) $Id: tkcanvpoly.c,v 1.1.1.1 2001/06/13 04:57:07 dtashley Exp $
15     */
16    
17     #include <stdio.h>
18     #include "tkInt.h"
19     #include "tkPort.h"
20     #include "tkCanvas.h"
21    
22     /*
23     * The structure below defines the record for each polygon item.
24     */
25    
26     typedef struct PolygonItem {
27     Tk_Item header; /* Generic stuff that's the same for all
28     * types. MUST BE FIRST IN STRUCTURE. */
29     Tk_Outline outline; /* Outline structure */
30     int numPoints; /* Number of points in polygon.
31     * Polygon is always closed. */
32     int pointsAllocated; /* Number of points for which space is
33     * allocated at *coordPtr. */
34     double *coordPtr; /* Pointer to malloc-ed array containing
35     * x- and y-coords of all points in polygon.
36     * X-coords are even-valued indices, y-coords
37     * are corresponding odd-valued indices. */
38     int joinStyle; /* Join style for outline */
39     Tk_TSOffset tsoffset;
40     XColor *fillColor; /* Foreground color for polygon. */
41     XColor *activeFillColor; /* Foreground color for polygon if state is active. */
42     XColor *disabledFillColor; /* Foreground color for polygon if state is disabled. */
43     Pixmap fillStipple; /* Stipple bitmap for filling polygon. */
44     Pixmap activeFillStipple; /* Stipple bitmap for filling polygon if state is active. */
45     Pixmap disabledFillStipple; /* Stipple bitmap for filling polygon if state is disabled. */
46     GC fillGC; /* Graphics context for filling polygon. */
47     Tk_SmoothMethod *smooth; /* Non-zero means draw shape smoothed (i.e.
48     * with Bezier splines). */
49     int splineSteps; /* Number of steps in each spline segment. */
50     int autoClosed; /* Zero means the given polygon was closed,
51     one means that we auto closed it. */
52     } PolygonItem;
53    
54     /*
55     * Information used for parsing configuration specs:
56     */
57    
58     static Tk_CustomOption smoothOption = {
59     (Tk_OptionParseProc *) TkSmoothParseProc,
60     TkSmoothPrintProc, (ClientData) NULL
61     };
62     static Tk_CustomOption stateOption = {
63     (Tk_OptionParseProc *) TkStateParseProc,
64     TkStatePrintProc, (ClientData) 2
65     };
66     static Tk_CustomOption tagsOption = {
67     (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
68     Tk_CanvasTagsPrintProc, (ClientData) NULL
69     };
70     static Tk_CustomOption dashOption = {
71     (Tk_OptionParseProc *) TkCanvasDashParseProc,
72     TkCanvasDashPrintProc, (ClientData) NULL
73     };
74     static Tk_CustomOption offsetOption = {
75     (Tk_OptionParseProc *) TkOffsetParseProc,
76     TkOffsetPrintProc,
77     (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
78     };
79     static Tk_CustomOption pixelOption = {
80     (Tk_OptionParseProc *) TkPixelParseProc,
81     TkPixelPrintProc, (ClientData) NULL
82     };
83    
84     static Tk_ConfigSpec configSpecs[] = {
85     {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
86     (char *) NULL, Tk_Offset(PolygonItem, outline.activeDash),
87     TK_CONFIG_NULL_OK, &dashOption},
88     {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
89     (char *) NULL, Tk_Offset(PolygonItem, activeFillColor),
90     TK_CONFIG_NULL_OK},
91     {TK_CONFIG_COLOR, "-activeoutline", (char *) NULL, (char *) NULL,
92     (char *) NULL, Tk_Offset(PolygonItem, outline.activeColor),
93     TK_CONFIG_NULL_OK},
94     {TK_CONFIG_BITMAP, "-activeoutlinestipple", (char *) NULL, (char *) NULL,
95     (char *) NULL, Tk_Offset(PolygonItem, outline.activeStipple),
96     TK_CONFIG_NULL_OK},
97     {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
98     (char *) NULL, Tk_Offset(PolygonItem, activeFillStipple),
99     TK_CONFIG_NULL_OK},
100     {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
101     "0.0", Tk_Offset(PolygonItem, outline.activeWidth),
102     TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
103     {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
104     (char *) NULL, Tk_Offset(PolygonItem, outline.dash),
105     TK_CONFIG_NULL_OK, &dashOption},
106     {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
107     "0", Tk_Offset(PolygonItem, outline.offset),
108     TK_CONFIG_DONT_SET_DEFAULT},
109     {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
110     (char *) NULL, Tk_Offset(PolygonItem, outline.disabledDash),
111     TK_CONFIG_NULL_OK, &dashOption},
112     {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
113     (char *) NULL, Tk_Offset(PolygonItem, disabledFillColor),
114     TK_CONFIG_NULL_OK},
115     {TK_CONFIG_COLOR, "-disabledoutline", (char *) NULL, (char *) NULL,
116     (char *) NULL, Tk_Offset(PolygonItem, outline.disabledColor),
117     TK_CONFIG_NULL_OK},
118     {TK_CONFIG_BITMAP, "-disabledoutlinestipple", (char *) NULL, (char *) NULL,
119     (char *) NULL, Tk_Offset(PolygonItem, outline.disabledStipple),
120     TK_CONFIG_NULL_OK},
121     {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
122     (char *) NULL, Tk_Offset(PolygonItem, disabledFillStipple),
123     TK_CONFIG_NULL_OK},
124     {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
125     "0.0", Tk_Offset(PolygonItem, outline.disabledWidth),
126     TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
127     {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
128     "black", Tk_Offset(PolygonItem, fillColor), TK_CONFIG_NULL_OK},
129     {TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,
130     "round", Tk_Offset(PolygonItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},
131     {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
132     "0,0", Tk_Offset(PolygonItem, tsoffset),
133     TK_CONFIG_NULL_OK, &offsetOption},
134     {TK_CONFIG_COLOR, "-outline", (char *) NULL, (char *) NULL,
135     (char *) NULL, Tk_Offset(PolygonItem, outline.color),
136     TK_CONFIG_NULL_OK},
137     {TK_CONFIG_CUSTOM, "-outlineoffset", (char *) NULL, (char *) NULL,
138     "0,0", Tk_Offset(PolygonItem, outline.tsoffset),
139     TK_CONFIG_NULL_OK, &offsetOption},
140     {TK_CONFIG_BITMAP, "-outlinestipple", (char *) NULL, (char *) NULL,
141     (char *) NULL, Tk_Offset(PolygonItem, outline.stipple),
142     TK_CONFIG_NULL_OK},
143     {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,
144     "0", Tk_Offset(PolygonItem, smooth),
145     TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
146     {TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
147     "12", Tk_Offset(PolygonItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
148     {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
149     (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
150     &stateOption},
151     {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
152     (char *) NULL, Tk_Offset(PolygonItem, fillStipple), TK_CONFIG_NULL_OK},
153     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
154     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
155     {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
156     "1.0", Tk_Offset(PolygonItem, outline.width),
157     TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
158     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
159     (char *) NULL, 0, 0}
160     };
161    
162     /*
163     * Prototypes for procedures defined in this file:
164     */
165    
166     static void ComputePolygonBbox _ANSI_ARGS_((Tk_Canvas canvas,
167     PolygonItem *polyPtr));
168     static int ConfigurePolygon _ANSI_ARGS_((Tcl_Interp *interp,
169     Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
170     Tcl_Obj *CONST argv[], int flags));
171     static int CreatePolygon _ANSI_ARGS_((Tcl_Interp *interp,
172     Tk_Canvas canvas, struct Tk_Item *itemPtr,
173     int argc, Tcl_Obj *CONST argv[]));
174     static void DeletePolygon _ANSI_ARGS_((Tk_Canvas canvas,
175     Tk_Item *itemPtr, Display *display));
176     static void DisplayPolygon _ANSI_ARGS_((Tk_Canvas canvas,
177     Tk_Item *itemPtr, Display *display, Drawable dst,
178     int x, int y, int width, int height));
179     static int GetPolygonIndex _ANSI_ARGS_((Tcl_Interp *interp,
180     Tk_Canvas canvas, Tk_Item *itemPtr,
181     Tcl_Obj *obj, int *indexPtr));
182     static int PolygonCoords _ANSI_ARGS_((Tcl_Interp *interp,
183     Tk_Canvas canvas, Tk_Item *itemPtr,
184     int argc, Tcl_Obj *CONST argv[]));
185     static void PolygonDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,
186     Tk_Item *itemPtr, int first, int last));
187     static void PolygonInsert _ANSI_ARGS_((Tk_Canvas canvas,
188     Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));
189     static int PolygonToArea _ANSI_ARGS_((Tk_Canvas canvas,
190     Tk_Item *itemPtr, double *rectPtr));
191     static double PolygonToPoint _ANSI_ARGS_((Tk_Canvas canvas,
192     Tk_Item *itemPtr, double *pointPtr));
193     static int PolygonToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
194     Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
195     static void ScalePolygon _ANSI_ARGS_((Tk_Canvas canvas,
196     Tk_Item *itemPtr, double originX, double originY,
197     double scaleX, double scaleY));
198     static void TranslatePolygon _ANSI_ARGS_((Tk_Canvas canvas,
199     Tk_Item *itemPtr, double deltaX, double deltaY));
200    
201     /*
202     * The structures below defines the polygon item type by means
203     * of procedures that can be invoked by generic item code.
204     */
205    
206     Tk_ItemType tkPolygonType = {
207     "polygon", /* name */
208     sizeof(PolygonItem), /* itemSize */
209     CreatePolygon, /* createProc */
210     configSpecs, /* configSpecs */
211     ConfigurePolygon, /* configureProc */
212     PolygonCoords, /* coordProc */
213     DeletePolygon, /* deleteProc */
214     DisplayPolygon, /* displayProc */
215     TK_CONFIG_OBJS, /* flags */
216     PolygonToPoint, /* pointProc */
217     PolygonToArea, /* areaProc */
218     PolygonToPostscript, /* postscriptProc */
219     ScalePolygon, /* scaleProc */
220     TranslatePolygon, /* translateProc */
221     (Tk_ItemIndexProc *) GetPolygonIndex,/* indexProc */
222     (Tk_ItemCursorProc *) NULL, /* icursorProc */
223     (Tk_ItemSelectionProc *) NULL, /* selectionProc */
224     (Tk_ItemInsertProc *) PolygonInsert,/* insertProc */
225     PolygonDeleteCoords, /* dTextProc */
226     (Tk_ItemType *) NULL, /* nextPtr */
227     };
228    
229     /*
230     * The definition below determines how large are static arrays
231     * used to hold spline points (splines larger than this have to
232     * have their arrays malloc-ed).
233     */
234    
235     #define MAX_STATIC_POINTS 200
236    
237     /*
238     *--------------------------------------------------------------
239     *
240     * CreatePolygon --
241     *
242     * This procedure is invoked to create a new polygon item in
243     * a canvas.
244     *
245     * Results:
246     * A standard Tcl return value. If an error occurred in
247     * creating the item, then an error message is left in
248     * the interp's result; in this case itemPtr is
249     * left uninitialized, so it can be safely freed by the
250     * caller.
251     *
252     * Side effects:
253     * A new polygon item is created.
254     *
255     *--------------------------------------------------------------
256     */
257    
258     static int
259     CreatePolygon(interp, canvas, itemPtr, argc, argv)
260     Tcl_Interp *interp; /* Interpreter for error reporting. */
261     Tk_Canvas canvas; /* Canvas to hold new item. */
262     Tk_Item *itemPtr; /* Record to hold new item; header
263     * has been initialized by caller. */
264     int argc; /* Number of arguments in argv. */
265     Tcl_Obj *CONST argv[]; /* Arguments describing polygon. */
266     {
267     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
268     int i;
269    
270     /*
271     * Carry out initialization that is needed in order to clean
272     * up after errors during the the remainder of this procedure.
273     */
274    
275     Tk_CreateOutline(&(polyPtr->outline));
276     polyPtr->numPoints = 0;
277     polyPtr->pointsAllocated = 0;
278     polyPtr->coordPtr = NULL;
279     polyPtr->joinStyle = JoinRound;
280     polyPtr->tsoffset.flags = 0;
281     polyPtr->tsoffset.xoffset = 0;
282     polyPtr->tsoffset.yoffset = 0;
283     polyPtr->fillColor = NULL;
284     polyPtr->activeFillColor = NULL;
285     polyPtr->disabledFillColor = NULL;
286     polyPtr->fillStipple = None;
287     polyPtr->activeFillStipple = None;
288     polyPtr->disabledFillStipple = None;
289     polyPtr->fillGC = None;
290     polyPtr->smooth = (Tk_SmoothMethod *) NULL;
291     polyPtr->splineSteps = 12;
292     polyPtr->autoClosed = 0;
293    
294     /*
295     * Count the number of points and then parse them into a point
296     * array. Leading arguments are assumed to be points if they
297     * start with a digit or a minus sign followed by a digit.
298     */
299    
300     for (i = 0; i < argc; i++) {
301     char *arg = Tcl_GetStringFromObj((Tcl_Obj *) argv[i], NULL);
302     if ((arg[0] == '-') && (arg[1] >= 'a')
303     && (arg[1] <= 'z')) {
304     break;
305     }
306     }
307     if (i && PolygonCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) {
308     goto error;
309     }
310    
311     if (ConfigurePolygon(interp, canvas, itemPtr, argc-i, argv+i, 0)
312     == TCL_OK) {
313     return TCL_OK;
314     }
315    
316     error:
317     DeletePolygon(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
318     return TCL_ERROR;
319     }
320    
321     /*
322     *--------------------------------------------------------------
323     *
324     * PolygonCoords --
325     *
326     * This procedure is invoked to process the "coords" widget
327     * command on polygons. See the user documentation for details
328     * on what it does.
329     *
330     * Results:
331     * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
332     *
333     * Side effects:
334     * The coordinates for the given item may be changed.
335     *
336     *--------------------------------------------------------------
337     */
338    
339     static int
340     PolygonCoords(interp, canvas, itemPtr, argc, argv)
341     Tcl_Interp *interp; /* Used for error reporting. */
342     Tk_Canvas canvas; /* Canvas containing item. */
343     Tk_Item *itemPtr; /* Item whose coordinates are to be
344     * read or modified. */
345     int argc; /* Number of coordinates supplied in
346     * argv. */
347     Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
348     * x2, y2, ... */
349     {
350     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
351     int i, numPoints;
352    
353     if (argc == 0) {
354     /*
355     * Print the coords used to create the polygon. If we auto
356     * closed the polygon then we don't report the last point.
357     */
358     Tcl_Obj *subobj, *obj = Tcl_NewObj();
359     for (i = 0; i < 2*(polyPtr->numPoints - polyPtr->autoClosed); i++) {
360     subobj = Tcl_NewDoubleObj(polyPtr->coordPtr[i]);
361     Tcl_ListObjAppendElement(interp, obj, subobj);
362     }
363     Tcl_SetObjResult(interp, obj);
364     return TCL_OK;
365     }
366     if (argc == 1) {
367     if (Tcl_ListObjGetElements(interp, argv[0], &argc,
368     (Tcl_Obj ***) &argv) != TCL_OK) {
369     return TCL_ERROR;
370     }
371     }
372     if (argc & 1) {
373     Tcl_AppendResult(interp,
374     "odd number of coordinates specified for polygon",
375     (char *) NULL);
376     return TCL_ERROR;
377     } else {
378     numPoints = argc/2;
379     if (polyPtr->pointsAllocated <= numPoints) {
380     if (polyPtr->coordPtr != NULL) {
381     ckfree((char *) polyPtr->coordPtr);
382     }
383    
384     /*
385     * One extra point gets allocated here, because we always
386     * add another point to close the polygon.
387     */
388    
389     polyPtr->coordPtr = (double *) ckalloc((unsigned)
390     (sizeof(double) * (argc+2)));
391     polyPtr->pointsAllocated = numPoints+1;
392     }
393     for (i = argc-1; i >= 0; i--) {
394     if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],
395     &polyPtr->coordPtr[i]) != TCL_OK) {
396     return TCL_ERROR;
397     }
398     }
399     polyPtr->numPoints = numPoints;
400     polyPtr->autoClosed = 0;
401    
402     /*
403     * Close the polygon if it isn't already closed.
404     */
405    
406     if (argc>2 && ((polyPtr->coordPtr[argc-2] != polyPtr->coordPtr[0])
407     || (polyPtr->coordPtr[argc-1] != polyPtr->coordPtr[1]))) {
408     polyPtr->autoClosed = 1;
409     polyPtr->numPoints++;
410     polyPtr->coordPtr[argc] = polyPtr->coordPtr[0];
411     polyPtr->coordPtr[argc+1] = polyPtr->coordPtr[1];
412     }
413     ComputePolygonBbox(canvas, polyPtr);
414     }
415     return TCL_OK;
416     }
417    
418     /*
419     *--------------------------------------------------------------
420     *
421     * ConfigurePolygon --
422     *
423     * This procedure is invoked to configure various aspects
424     * of a polygon item such as its background color.
425     *
426     * Results:
427     * A standard Tcl result code. If an error occurs, then
428     * an error message is left in the interp's result.
429     *
430     * Side effects:
431     * Configuration information, such as colors and stipple
432     * patterns, may be set for itemPtr.
433     *
434     *--------------------------------------------------------------
435     */
436    
437     static int
438     ConfigurePolygon(interp, canvas, itemPtr, argc, argv, flags)
439     Tcl_Interp *interp; /* Interpreter for error reporting. */
440     Tk_Canvas canvas; /* Canvas containing itemPtr. */
441     Tk_Item *itemPtr; /* Polygon item to reconfigure. */
442     int argc; /* Number of elements in argv. */
443     Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
444     int flags; /* Flags to pass to Tk_ConfigureWidget. */
445     {
446     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
447     XGCValues gcValues;
448     GC newGC;
449     unsigned long mask;
450     Tk_Window tkwin;
451     XColor *color;
452     Pixmap stipple;
453     Tk_State state;
454    
455     tkwin = Tk_CanvasTkwin(canvas);
456     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
457     (char *) polyPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
458     return TCL_ERROR;
459     }
460    
461     /*
462     * A few of the options require additional processing, such as
463     * graphics contexts.
464     */
465    
466     state = itemPtr->state;
467    
468     if (polyPtr->outline.activeWidth > polyPtr->outline.width ||
469     polyPtr->outline.activeDash.number != 0 ||
470     polyPtr->outline.activeColor != NULL ||
471     polyPtr->outline.activeStipple != None ||
472     polyPtr->activeFillColor != NULL ||
473     polyPtr->activeFillStipple != None) {
474     itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
475     } else {
476     itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
477     }
478    
479     if(state == TK_STATE_NULL) {
480     state = ((TkCanvas *)canvas)->canvas_state;
481     }
482     if (state==TK_STATE_HIDDEN) {
483     ComputePolygonBbox(canvas, polyPtr);
484     return TCL_OK;
485     }
486    
487     mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr, &(polyPtr->outline));
488     if (mask) {
489     gcValues.cap_style = CapRound;
490     gcValues.join_style = polyPtr->joinStyle;
491     mask |= GCCapStyle|GCJoinStyle;
492     newGC = Tk_GetGC(tkwin, mask, &gcValues);
493     } else {
494     newGC = None;
495     }
496     if (polyPtr->outline.gc != None) {
497     Tk_FreeGC(Tk_Display(tkwin), polyPtr->outline.gc);
498     }
499     polyPtr->outline.gc = newGC;
500    
501     color = polyPtr->fillColor;
502     stipple = polyPtr->fillStipple;
503     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
504     if (polyPtr->activeFillColor!=NULL) {
505     color = polyPtr->activeFillColor;
506     }
507     if (polyPtr->activeFillStipple!=None) {
508     stipple = polyPtr->activeFillStipple;
509     }
510     } else if (state==TK_STATE_DISABLED) {
511     if (polyPtr->disabledFillColor!=NULL) {
512     color = polyPtr->disabledFillColor;
513     }
514     if (polyPtr->disabledFillStipple!=None) {
515     stipple = polyPtr->disabledFillStipple;
516     }
517     }
518    
519     if (color == NULL) {
520     newGC = None;
521     } else {
522     gcValues.foreground = color->pixel;
523     mask = GCForeground;
524     if (stipple != None) {
525     gcValues.stipple = stipple;
526     gcValues.fill_style = FillStippled;
527     mask |= GCStipple|GCFillStyle;
528     }
529     newGC = Tk_GetGC(tkwin, mask, &gcValues);
530     }
531     if (polyPtr->fillGC != None) {
532     Tk_FreeGC(Tk_Display(tkwin), polyPtr->fillGC);
533     }
534     polyPtr->fillGC = newGC;
535    
536     /*
537     * Keep spline parameters within reasonable limits.
538     */
539    
540     if (polyPtr->splineSteps < 1) {
541     polyPtr->splineSteps = 1;
542     } else if (polyPtr->splineSteps > 100) {
543     polyPtr->splineSteps = 100;
544     }
545    
546     ComputePolygonBbox(canvas, polyPtr);
547     return TCL_OK;
548     }
549    
550     /*
551     *--------------------------------------------------------------
552     *
553     * DeletePolygon --
554     *
555     * This procedure is called to clean up the data structure
556     * associated with a polygon item.
557     *
558     * Results:
559     * None.
560     *
561     * Side effects:
562     * Resources associated with itemPtr are released.
563     *
564     *--------------------------------------------------------------
565     */
566    
567     static void
568     DeletePolygon(canvas, itemPtr, display)
569     Tk_Canvas canvas; /* Info about overall canvas widget. */
570     Tk_Item *itemPtr; /* Item that is being deleted. */
571     Display *display; /* Display containing window for
572     * canvas. */
573     {
574     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
575    
576     Tk_DeleteOutline(display,&(polyPtr->outline));
577     if (polyPtr->coordPtr != NULL) {
578     ckfree((char *) polyPtr->coordPtr);
579     }
580     if (polyPtr->fillColor != NULL) {
581     Tk_FreeColor(polyPtr->fillColor);
582     }
583     if (polyPtr->activeFillColor != NULL) {
584     Tk_FreeColor(polyPtr->activeFillColor);
585     }
586     if (polyPtr->disabledFillColor != NULL) {
587     Tk_FreeColor(polyPtr->disabledFillColor);
588     }
589     if (polyPtr->fillStipple != None) {
590     Tk_FreeBitmap(display, polyPtr->fillStipple);
591     }
592     if (polyPtr->activeFillStipple != None) {
593     Tk_FreeBitmap(display, polyPtr->activeFillStipple);
594     }
595     if (polyPtr->disabledFillStipple != None) {
596     Tk_FreeBitmap(display, polyPtr->disabledFillStipple);
597     }
598     if (polyPtr->fillGC != None) {
599     Tk_FreeGC(display, polyPtr->fillGC);
600     }
601     }
602    
603     /*
604     *--------------------------------------------------------------
605     *
606     * ComputePolygonBbox --
607     *
608     * This procedure is invoked to compute the bounding box of
609     * all the pixels that may be drawn as part of a polygon.
610     *
611     * Results:
612     * None.
613     *
614     * Side effects:
615     * The fields x1, y1, x2, and y2 are updated in the header
616     * for itemPtr.
617     *
618     *--------------------------------------------------------------
619     */
620    
621     static void
622     ComputePolygonBbox(canvas, polyPtr)
623     Tk_Canvas canvas; /* Canvas that contains item. */
624     PolygonItem *polyPtr; /* Item whose bbox is to be
625     * recomputed. */
626     {
627     double *coordPtr;
628     int i;
629     double width;
630     Tk_State state = polyPtr->header.state;
631     Tk_TSOffset *tsoffset;
632    
633     if(state == TK_STATE_NULL) {
634     state = ((TkCanvas *)canvas)->canvas_state;
635     }
636     width = polyPtr->outline.width;
637     if (polyPtr->coordPtr == NULL || (polyPtr->numPoints < 1) || (state==TK_STATE_HIDDEN)) {
638     polyPtr->header.x1 = polyPtr->header.x2 =
639     polyPtr->header.y1 = polyPtr->header.y2 = -1;
640     return;
641     }
642     if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)polyPtr) {
643     if (polyPtr->outline.activeWidth>width) {
644     width = polyPtr->outline.activeWidth;
645     }
646     } else if (state==TK_STATE_DISABLED) {
647     if (polyPtr->outline.disabledWidth>0.0) {
648     width = polyPtr->outline.disabledWidth;
649     }
650     }
651    
652     coordPtr = polyPtr->coordPtr;
653     polyPtr->header.x1 = polyPtr->header.x2 = (int) *coordPtr;
654     polyPtr->header.y1 = polyPtr->header.y2 = (int) coordPtr[1];
655    
656     /*
657     * Compute the bounding box of all the points in the polygon,
658     * then expand in all directions by the outline's width to take
659     * care of butting or rounded corners and projecting or
660     * rounded caps. This expansion is an overestimate (worst-case
661     * is square root of two over two) but it's simple. Don't do
662     * anything special for curves. This causes an additional
663     * overestimate in the bounding box, but is faster.
664     */
665    
666     for (i = 1, coordPtr = polyPtr->coordPtr+2; i < polyPtr->numPoints-1;
667     i++, coordPtr += 2) {
668     TkIncludePoint((Tk_Item *) polyPtr, coordPtr);
669     }
670    
671     tsoffset = &polyPtr->tsoffset;
672     if (tsoffset->flags & TK_OFFSET_INDEX) {
673     int index = tsoffset->flags & ~TK_OFFSET_INDEX;
674     if (tsoffset->flags == INT_MAX) {
675     index = (polyPtr->numPoints - polyPtr->autoClosed) * 2;
676     if (index < 0) {
677     index = 0;
678     }
679     }
680     index %= (polyPtr->numPoints - polyPtr->autoClosed) * 2;
681     if (index <0) {
682     index += (polyPtr->numPoints - polyPtr->autoClosed) * 2;
683     }
684     tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
685     tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
686     } else {
687     if (tsoffset->flags & TK_OFFSET_LEFT) {
688     tsoffset->xoffset = polyPtr->header.x1;
689     } else if (tsoffset->flags & TK_OFFSET_CENTER) {
690     tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;
691     } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
692     tsoffset->xoffset = polyPtr->header.x2;
693     }
694     if (tsoffset->flags & TK_OFFSET_TOP) {
695     tsoffset->yoffset = polyPtr->header.y1;
696     } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
697     tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;
698     } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
699     tsoffset->yoffset = polyPtr->header.y2;
700     }
701     }
702    
703     if (polyPtr->outline.gc != None) {
704     tsoffset = &polyPtr->outline.tsoffset;
705     if (tsoffset) {
706     if (tsoffset->flags & TK_OFFSET_INDEX) {
707     int index = tsoffset->flags & ~TK_OFFSET_INDEX;
708     if (tsoffset->flags == INT_MAX) {
709     index = (polyPtr->numPoints - 1) * 2;
710     }
711     index %= (polyPtr->numPoints - 1) * 2;
712     if (index <0) {
713     index += (polyPtr->numPoints - 1) * 2;
714     }
715     tsoffset->xoffset = (int) (polyPtr->coordPtr[index] + 0.5);
716     tsoffset->yoffset = (int) (polyPtr->coordPtr[index+1] + 0.5);
717     } else {
718     if (tsoffset->flags & TK_OFFSET_LEFT) {
719     tsoffset->xoffset = polyPtr->header.x1;
720     } else if (tsoffset->flags & TK_OFFSET_CENTER) {
721     tsoffset->xoffset = (polyPtr->header.x1 + polyPtr->header.x2)/2;
722     } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
723     tsoffset->xoffset = polyPtr->header.x2;
724     }
725     if (tsoffset->flags & TK_OFFSET_TOP) {
726     tsoffset->yoffset = polyPtr->header.y1;
727     } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
728     tsoffset->yoffset = (polyPtr->header.y1 + polyPtr->header.y2)/2;
729     } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
730     tsoffset->yoffset = polyPtr->header.y2;
731     }
732     }
733     }
734    
735     i = (int) ((width+1.5)/2.0);
736     polyPtr->header.x1 -= i;
737     polyPtr->header.x2 += i;
738     polyPtr->header.y1 -= i;
739     polyPtr->header.y2 += i;
740    
741     /*
742     * For mitered lines, make a second pass through all the points.
743     * Compute the locations of the two miter vertex points and add
744     * those into the bounding box.
745     */
746    
747     if (polyPtr->joinStyle == JoinMiter) {
748     double miter[4];
749     int j;
750     coordPtr = polyPtr->coordPtr;
751     if (polyPtr->numPoints>3) {
752     if (TkGetMiterPoints(coordPtr+2*(polyPtr->numPoints-2),
753     coordPtr, coordPtr+2, width,
754     miter, miter+2)) {
755     for (j = 0; j < 4; j += 2) {
756     TkIncludePoint((Tk_Item *) polyPtr, miter+j);
757     }
758     }
759     }
760     for (i = polyPtr->numPoints ; i >= 3;
761     i--, coordPtr += 2) {
762    
763     if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
764     width, miter, miter+2)) {
765     for (j = 0; j < 4; j += 2) {
766     TkIncludePoint((Tk_Item *) polyPtr, miter+j);
767     }
768     }
769     }
770     }
771     }
772    
773     /*
774     * Add one more pixel of fudge factor just to be safe (e.g.
775     * X may round differently than we do).
776     */
777    
778     polyPtr->header.x1 -= 1;
779     polyPtr->header.x2 += 1;
780     polyPtr->header.y1 -= 1;
781     polyPtr->header.y2 += 1;
782     }
783    
784     /*
785     *--------------------------------------------------------------
786     *
787     * TkFillPolygon --
788     *
789     * This procedure is invoked to convert a polygon to screen
790     * coordinates and display it using a particular GC.
791     *
792     * Results:
793     * None.
794     *
795     * Side effects:
796     * ItemPtr is drawn in drawable using the transformation
797     * information in canvas.
798     *
799     *--------------------------------------------------------------
800     */
801    
802     void
803     TkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC)
804     Tk_Canvas canvas; /* Canvas whose coordinate system
805     * is to be used for drawing. */
806     double *coordPtr; /* Array of coordinates for polygon:
807     * x1, y1, x2, y2, .... */
808     int numPoints; /* Twice this many coordinates are
809     * present at *coordPtr. */
810     Display *display; /* Display on which to draw polygon. */
811     Drawable drawable; /* Pixmap or window in which to draw
812     * polygon. */
813     GC gc; /* Graphics context for drawing. */
814     GC outlineGC; /* If not None, use this to draw an
815     * outline around the polygon after
816     * filling it. */
817     {
818     XPoint staticPoints[MAX_STATIC_POINTS];
819     XPoint *pointPtr;
820     XPoint *pPtr;
821     int i;
822    
823     /*
824     * Build up an array of points in screen coordinates. Use a
825     * static array unless the polygon has an enormous number of points;
826     * in this case, dynamically allocate an array.
827     */
828    
829     if (numPoints <= MAX_STATIC_POINTS) {
830     pointPtr = staticPoints;
831     } else {
832     pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));
833     }
834    
835     for (i = 0, pPtr = pointPtr; i < numPoints; i += 1, coordPtr += 2, pPtr++) {
836     Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x,
837     &pPtr->y);
838     }
839    
840     /*
841     * Display polygon, then free up polygon storage if it was dynamically
842     * allocated.
843     */
844    
845     if (gc != None && numPoints>3) {
846     XFillPolygon(display, drawable, gc, pointPtr, numPoints, Complex,
847     CoordModeOrigin);
848     }
849     if (outlineGC != None) {
850     XDrawLines(display, drawable, outlineGC, pointPtr,
851     numPoints, CoordModeOrigin);
852     }
853     if (pointPtr != staticPoints) {
854     ckfree((char *) pointPtr);
855     }
856     }
857    
858     /*
859     *--------------------------------------------------------------
860     *
861     * DisplayPolygon --
862     *
863     * This procedure is invoked to draw a polygon item in a given
864     * drawable.
865     *
866     * Results:
867     * None.
868     *
869     * Side effects:
870     * ItemPtr is drawn in drawable using the transformation
871     * information in canvas.
872     *
873     *--------------------------------------------------------------
874     */
875    
876     static void
877     DisplayPolygon(canvas, itemPtr, display, drawable, x, y, width, height)
878     Tk_Canvas canvas; /* Canvas that contains item. */
879     Tk_Item *itemPtr; /* Item to be displayed. */
880     Display *display; /* Display on which to draw item. */
881     Drawable drawable; /* Pixmap or window in which to draw
882     * item. */
883     int x, y, width, height; /* Describes region of canvas that
884     * must be redisplayed (not used). */
885     {
886     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
887     Tk_State state = itemPtr->state;
888     Pixmap stipple = polyPtr->fillStipple;
889     double linewidth = polyPtr->outline.width;
890    
891     if (((polyPtr->fillGC == None) && (polyPtr->outline.gc == None)) ||
892     (polyPtr->numPoints < 1) ||
893     (polyPtr->numPoints < 3 && polyPtr->outline.gc == None)) {
894     return;
895     }
896    
897     if(state == TK_STATE_NULL) {
898     state = ((TkCanvas *)canvas)->canvas_state;
899     }
900     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
901     if (polyPtr->outline.activeWidth>linewidth) {
902     linewidth = polyPtr->outline.activeWidth;
903     }
904     if (polyPtr->activeFillStipple != None) {
905     stipple = polyPtr->activeFillStipple;
906     }
907     } else if (state==TK_STATE_DISABLED) {
908     if (polyPtr->outline.disabledWidth>0.0) {
909     linewidth = polyPtr->outline.disabledWidth;
910     }
911     if (polyPtr->disabledFillStipple != None) {
912     stipple = polyPtr->disabledFillStipple;
913     }
914     }
915     /*
916     * If we're stippling then modify the stipple offset in the GC. Be
917     * sure to reset the offset when done, since the GC is supposed to be
918     * read-only.
919     */
920    
921     if (stipple != None) {
922     Tk_TSOffset *tsoffset = &polyPtr->tsoffset;
923     int w=0; int h=0;
924     int flags = tsoffset->flags;
925     if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
926     Tk_SizeOfBitmap(display, stipple, &w, &h);
927     if (flags & TK_OFFSET_CENTER) {
928     w /= 2;
929     } else {
930     w = 0;
931     }
932     if (flags & TK_OFFSET_MIDDLE) {
933     h /= 2;
934     } else {
935     h = 0;
936     }
937     }
938     tsoffset->xoffset -= w;
939     tsoffset->yoffset -= h;
940     Tk_CanvasSetOffset(canvas, polyPtr->fillGC, tsoffset);
941     tsoffset->xoffset += w;
942     tsoffset->yoffset += h;
943     }
944     Tk_ChangeOutlineGC(canvas, itemPtr, &(polyPtr->outline));
945    
946     if(polyPtr->numPoints < 3) {
947     short x,y;
948     int intLineWidth = (int) (linewidth + 0.5);
949     if (intLineWidth < 1) {
950     intLineWidth = 1;
951     }
952     Tk_CanvasDrawableCoords(canvas, polyPtr->coordPtr[0],
953     polyPtr->coordPtr[1], &x,&y);
954     XFillArc(display, drawable, polyPtr->outline.gc,
955     x - intLineWidth/2, y - intLineWidth/2,
956     (unsigned int)intLineWidth+1, (unsigned int)intLineWidth+1,
957     0, 64*360);
958     } else if (!polyPtr->smooth || polyPtr->numPoints < 4) {
959     TkFillPolygon(canvas, polyPtr->coordPtr, polyPtr->numPoints,
960     display, drawable, polyPtr->fillGC, polyPtr->outline.gc);
961     } else {
962     int numPoints;
963     XPoint staticPoints[MAX_STATIC_POINTS];
964     XPoint *pointPtr;
965    
966     /*
967     * This is a smoothed polygon. Display using a set of generated
968     * spline points rather than the original points.
969     */
970    
971     numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
972     polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
973     (double *) NULL);
974     if (numPoints <= MAX_STATIC_POINTS) {
975     pointPtr = staticPoints;
976     } else {
977     pointPtr = (XPoint *) ckalloc((unsigned)
978     (numPoints * sizeof(XPoint)));
979     }
980     numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
981     polyPtr->numPoints, polyPtr->splineSteps, pointPtr,
982     (double *) NULL);
983     if (polyPtr->fillGC != None) {
984     XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr,
985     numPoints, Complex, CoordModeOrigin);
986     }
987     if (polyPtr->outline.gc != None) {
988     XDrawLines(display, drawable, polyPtr->outline.gc, pointPtr,
989     numPoints, CoordModeOrigin);
990     }
991     if (pointPtr != staticPoints) {
992     ckfree((char *) pointPtr);
993     }
994     }
995     Tk_ResetOutlineGC(canvas, itemPtr, &(polyPtr->outline));
996     if (stipple != None) {
997     XSetTSOrigin(display, polyPtr->fillGC, 0, 0);
998     }
999     }
1000    
1001     /*
1002     *--------------------------------------------------------------
1003     *
1004     * PolygonInsert --
1005     *
1006     * Insert coords into a polugon item at a given index.
1007     *
1008     * Results:
1009     * None.
1010     *
1011     * Side effects:
1012     * The coords in the given item is modified.
1013     *
1014     *--------------------------------------------------------------
1015     */
1016    
1017     static void
1018     PolygonInsert(canvas, itemPtr, beforeThis, obj)
1019     Tk_Canvas canvas; /* Canvas containing text item. */
1020     Tk_Item *itemPtr; /* Line item to be modified. */
1021     int beforeThis; /* Index before which new coordinates
1022     * are to be inserted. */
1023     Tcl_Obj *obj; /* New coordinates to be inserted. */
1024     {
1025     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1026     int length, argc, i;
1027     Tcl_Obj **objv;
1028     double *new;
1029     Tk_State state = itemPtr->state;
1030    
1031     if (state == TK_STATE_NULL) {
1032     state = ((TkCanvas *)canvas)->canvas_state;
1033     }
1034    
1035     if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)
1036     || !argc || argc&1) {
1037     return;
1038     }
1039     length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
1040     while(beforeThis>length) beforeThis-=length;
1041     while(beforeThis<0) beforeThis+=length;
1042     new = (double *) ckalloc((unsigned)(sizeof(double) * (length + 2 + argc)));
1043     for (i=0; i<beforeThis; i++) {
1044     new[i] = polyPtr->coordPtr[i];
1045     }
1046     for (i=0; i<argc; i++) {
1047     if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],
1048     new+(i+beforeThis))!=TCL_OK) {
1049     ckfree((char *) new);
1050     return;
1051     }
1052     }
1053    
1054     for(i=beforeThis; i<length; i++) {
1055     new[i+argc] = polyPtr->coordPtr[i];
1056     }
1057     if(polyPtr->coordPtr) ckfree((char *) polyPtr->coordPtr);
1058     length+=argc;
1059     polyPtr->coordPtr = new;
1060     polyPtr->numPoints = (length/2) + polyPtr->autoClosed;
1061    
1062     /*
1063     * Close the polygon if it isn't already closed, or remove autoclosing
1064     * if the user's coordinates are now closed.
1065     */
1066    
1067     if (polyPtr->autoClosed) {
1068     if ((new[length-2] == new[0]) && (new[length-1] == new[1])) {
1069     polyPtr->autoClosed = 0;
1070     polyPtr->numPoints--;
1071     }
1072     }
1073     else {
1074     if ((new[length-2] != new[0]) || (new[length-1] != new[1])) {
1075     polyPtr->autoClosed = 1;
1076     polyPtr->numPoints++;
1077     }
1078     }
1079    
1080     new[length] = new[0];
1081     new[length+1] = new[1];
1082     if (((length-argc)>3) && (state != TK_STATE_HIDDEN)) {
1083     /*
1084     * This is some optimizing code that will result that only the part
1085     * of the polygon that changed (and the objects that are overlapping
1086     * with that part) need to be redrawn. A special flag is set that
1087     * instructs the general canvas code not to redraw the whole
1088     * object. If this flag is not set, the canvas will do the redrawing,
1089     * otherwise I have to do it here.
1090     */
1091     double width;
1092     int j;
1093     itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
1094    
1095     /*
1096     * The header elements that normally are used for the
1097     * bounding box, are now used to calculate the bounding
1098     * box for only the part that has to be redrawn. That
1099     * doesn't matter, because afterwards the bounding
1100     * box has to be re-calculated anyway.
1101     */
1102    
1103     itemPtr->x1 = itemPtr->x2 = (int) polyPtr->coordPtr[beforeThis];
1104     itemPtr->y1 = itemPtr->y2 = (int) polyPtr->coordPtr[beforeThis+1];
1105     beforeThis-=2; argc+=4;
1106     if(polyPtr->smooth) {
1107     beforeThis-=2; argc+=4;
1108     } /* be carefull; beforeThis could now be negative */
1109     for(i=beforeThis; i<beforeThis+argc; i+=2) {
1110     j=i;
1111     if(j<0) j+=length;
1112     if(j>=length) j-=length;
1113     TkIncludePoint(itemPtr, polyPtr->coordPtr+j);
1114     }
1115     width = polyPtr->outline.width;
1116     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1117     if (polyPtr->outline.activeWidth>width) {
1118     width = polyPtr->outline.activeWidth;
1119     }
1120     } else if (state==TK_STATE_DISABLED) {
1121     if (polyPtr->outline.disabledWidth>0.0) {
1122     width = polyPtr->outline.disabledWidth;
1123     }
1124     }
1125     itemPtr->x1 -= (int) width; itemPtr->y1 -= (int) width;
1126     itemPtr->x2 += (int) width; itemPtr->y2 += (int) width;
1127     Tk_CanvasEventuallyRedraw(canvas,
1128     itemPtr->x1, itemPtr->y1,
1129     itemPtr->x2, itemPtr->y2);
1130     }
1131    
1132     ComputePolygonBbox(canvas, polyPtr);
1133     }
1134    
1135     /*
1136     *--------------------------------------------------------------
1137     *
1138     * PolygonDeleteCoords --
1139     *
1140     * Delete one or more coordinates from a polygon item.
1141     *
1142     * Results:
1143     * None.
1144     *
1145     * Side effects:
1146     * Characters between "first" and "last", inclusive, get
1147     * deleted from itemPtr.
1148     *
1149     *--------------------------------------------------------------
1150     */
1151    
1152     static void
1153     PolygonDeleteCoords(canvas, itemPtr, first, last)
1154     Tk_Canvas canvas; /* Canvas containing itemPtr. */
1155     Tk_Item *itemPtr; /* Item in which to delete characters. */
1156     int first; /* Index of first character to delete. */
1157     int last; /* Index of last character to delete. */
1158     {
1159     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1160     int count, i;
1161     int length = 2*(polyPtr->numPoints - polyPtr->autoClosed);
1162    
1163     while(first>=length) first-=length;
1164     while(first<0) first+=length;
1165     while(last>=length) last-=length;
1166     while(last<0) last+=length;
1167    
1168     first &= -2;
1169     last &= -2;
1170    
1171     count = last + 2 - first;
1172     if(count<=0) count +=length;
1173    
1174     if(count >= length) {
1175     polyPtr->numPoints = 0;
1176     if(polyPtr->coordPtr != NULL) {
1177     ckfree((char *) polyPtr->coordPtr);
1178     }
1179     ComputePolygonBbox(canvas, polyPtr);
1180     return;
1181     }
1182    
1183     if(last>=first) {
1184     for(i=last+2; i<length; i++) {
1185     polyPtr->coordPtr[i-count] = polyPtr->coordPtr[i];
1186     }
1187     } else {
1188     for(i=last; i<=first; i++) {
1189     polyPtr->coordPtr[i-last] = polyPtr->coordPtr[i];
1190     }
1191     }
1192     polyPtr->coordPtr[length-count] = polyPtr->coordPtr[0];
1193     polyPtr->coordPtr[length-count+1] = polyPtr->coordPtr[1];
1194     polyPtr->numPoints -= count/2;
1195     ComputePolygonBbox(canvas, polyPtr);
1196     }
1197    
1198     /*
1199     *--------------------------------------------------------------
1200     *
1201     * PolygonToPoint --
1202     *
1203     * Computes the distance from a given point to a given
1204     * polygon, in canvas units.
1205     *
1206     * Results:
1207     * The return value is 0 if the point whose x and y coordinates
1208     * are pointPtr[0] and pointPtr[1] is inside the polygon. If the
1209     * point isn't inside the polygon then the return value is the
1210     * distance from the point to the polygon.
1211     *
1212     * Side effects:
1213     * None.
1214     *
1215     *--------------------------------------------------------------
1216     */
1217    
1218     /* ARGSUSED */
1219     static double
1220     PolygonToPoint(canvas, itemPtr, pointPtr)
1221     Tk_Canvas canvas; /* Canvas containing item. */
1222     Tk_Item *itemPtr; /* Item to check against point. */
1223     double *pointPtr; /* Pointer to x and y coordinates. */
1224     {
1225     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1226     double *coordPtr, *polyPoints;
1227     double staticSpace[2*MAX_STATIC_POINTS];
1228     double poly[10];
1229     double radius;
1230     double bestDist, dist;
1231     int numPoints, count;
1232     int changedMiterToBevel; /* Non-zero means that a mitered corner
1233     * had to be treated as beveled after all
1234     * because the angle was < 11 degrees. */
1235     double width;
1236     Tk_State state = itemPtr->state;
1237    
1238     bestDist = 1.0e36;
1239    
1240     if(state == TK_STATE_NULL) {
1241     state = ((TkCanvas *)canvas)->canvas_state;
1242     }
1243     width = polyPtr->outline.width;
1244     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1245     if (polyPtr->outline.activeWidth>width) {
1246     width = polyPtr->outline.activeWidth;
1247     }
1248     } else if (state==TK_STATE_DISABLED) {
1249     if (polyPtr->outline.disabledWidth>0.0) {
1250     width = polyPtr->outline.disabledWidth;
1251     }
1252     }
1253     radius = width/2.0;
1254    
1255     /*
1256     * Handle smoothed polygons by generating an expanded set of points
1257     * against which to do the check.
1258     */
1259    
1260     if ((polyPtr->smooth) && (polyPtr->numPoints>2)) {
1261     numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
1262     polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
1263     (double *) NULL);
1264     if (numPoints <= MAX_STATIC_POINTS) {
1265     polyPoints = staticSpace;
1266     } else {
1267     polyPoints = (double *) ckalloc((unsigned)
1268     (2*numPoints*sizeof(double)));
1269     }
1270     numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
1271     polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
1272     polyPoints);
1273     } else {
1274     numPoints = polyPtr->numPoints;
1275     polyPoints = polyPtr->coordPtr;
1276     }
1277    
1278     bestDist = TkPolygonToPoint(polyPoints, numPoints, pointPtr);
1279     if (bestDist<=0.0) {
1280     goto donepoint;
1281     }
1282     if ((polyPtr->outline.gc != None) && (polyPtr->joinStyle == JoinRound)) {
1283     dist = bestDist - radius;
1284     if (dist <= 0.0) {
1285     bestDist = 0.0;
1286     goto donepoint;
1287     } else {
1288     bestDist = dist;
1289     }
1290     }
1291    
1292     if ((polyPtr->outline.gc == None) || (width <= 1)) goto donepoint;
1293    
1294     /*
1295     * The overall idea is to iterate through all of the edges of
1296     * the line, computing a polygon for each edge and testing the
1297     * point against that polygon. In addition, there are additional
1298     * tests to deal with rounded joints and caps.
1299     */
1300    
1301     changedMiterToBevel = 0;
1302     for (count = numPoints, coordPtr = polyPoints; count >= 2;
1303     count--, coordPtr += 2) {
1304    
1305     /*
1306     * If rounding is done around the first point then compute
1307     * the distance between the point and the point.
1308     */
1309    
1310     if (polyPtr->joinStyle == JoinRound) {
1311     dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1])
1312     - radius;
1313     if (dist <= 0.0) {
1314     bestDist = 0.0;
1315     goto donepoint;
1316     } else if (dist < bestDist) {
1317     bestDist = dist;
1318     }
1319     }
1320    
1321     /*
1322     * Compute the polygonal shape corresponding to this edge,
1323     * consisting of two points for the first point of the edge
1324     * and two points for the last point of the edge.
1325     */
1326    
1327     if (count == numPoints) {
1328     TkGetButtPoints(coordPtr+2, coordPtr, (double) width,
1329     0, poly, poly+2);
1330     } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
1331     poly[0] = poly[6];
1332     poly[1] = poly[7];
1333     poly[2] = poly[4];
1334     poly[3] = poly[5];
1335     } else {
1336     TkGetButtPoints(coordPtr+2, coordPtr, (double) width, 0,
1337     poly, poly+2);
1338    
1339     /*
1340     * If this line uses beveled joints, then check the distance
1341     * to a polygon comprising the last two points of the previous
1342     * polygon and the first two from this polygon; this checks
1343     * the wedges that fill the mitered joint.
1344     */
1345    
1346     if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
1347     poly[8] = poly[0];
1348     poly[9] = poly[1];
1349     dist = TkPolygonToPoint(poly, 5, pointPtr);
1350     if (dist <= 0.0) {
1351     bestDist = 0.0;
1352     goto donepoint;
1353     } else if (dist < bestDist) {
1354     bestDist = dist;
1355     }
1356     changedMiterToBevel = 0;
1357     }
1358     }
1359     if (count == 2) {
1360     TkGetButtPoints(coordPtr, coordPtr+2, (double) width,
1361     0, poly+4, poly+6);
1362     } else if (polyPtr->joinStyle == JoinMiter) {
1363     if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
1364     (double) width, poly+4, poly+6) == 0) {
1365     changedMiterToBevel = 1;
1366     TkGetButtPoints(coordPtr, coordPtr+2, (double) width,
1367     0, poly+4, poly+6);
1368     }
1369     } else {
1370     TkGetButtPoints(coordPtr, coordPtr+2, (double) width, 0,
1371     poly+4, poly+6);
1372     }
1373     poly[8] = poly[0];
1374     poly[9] = poly[1];
1375     dist = TkPolygonToPoint(poly, 5, pointPtr);
1376     if (dist <= 0.0) {
1377     bestDist = 0.0;
1378     goto donepoint;
1379     } else if (dist < bestDist) {
1380     bestDist = dist;
1381     }
1382     }
1383    
1384     donepoint:
1385     if ((polyPoints != staticSpace) && polyPoints != polyPtr->coordPtr) {
1386     ckfree((char *) polyPoints);
1387     }
1388     return bestDist;
1389     }
1390    
1391     /*
1392     *--------------------------------------------------------------
1393     *
1394     * PolygonToArea --
1395     *
1396     * This procedure is called to determine whether an item
1397     * lies entirely inside, entirely outside, or overlapping
1398     * a given rectangular area.
1399     *
1400     * Results:
1401     * -1 is returned if the item is entirely outside the area
1402     * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
1403     * inside the given area.
1404     *
1405     * Side effects:
1406     * None.
1407     *
1408     *--------------------------------------------------------------
1409     */
1410    
1411     /* ARGSUSED */
1412     static int
1413     PolygonToArea(canvas, itemPtr, rectPtr)
1414     Tk_Canvas canvas; /* Canvas containing item. */
1415     Tk_Item *itemPtr; /* Item to check against polygon. */
1416     double *rectPtr; /* Pointer to array of four coordinates
1417     * (x1, y1, x2, y2) describing rectangular
1418     * area. */
1419     {
1420     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1421     double *coordPtr;
1422     double staticSpace[2*MAX_STATIC_POINTS];
1423     double *polyPoints, poly[10];
1424     double radius;
1425     int numPoints, count;
1426     int changedMiterToBevel; /* Non-zero means that a mitered corner
1427     * had to be treated as beveled after all
1428     * because the angle was < 11 degrees. */
1429     int inside; /* Tentative guess about what to return,
1430     * based on all points seen so far: one
1431     * means everything seen so far was
1432     * inside the area; -1 means everything
1433     * was outside the area. 0 means overlap
1434     * has been found. */
1435     double width;
1436     Tk_State state = itemPtr->state;
1437    
1438     if(state == TK_STATE_NULL) {
1439     state = ((TkCanvas *)canvas)->canvas_state;
1440     }
1441    
1442     width = polyPtr->outline.width;
1443     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1444     if (polyPtr->outline.activeWidth>width) {
1445     width = polyPtr->outline.activeWidth;
1446     }
1447     } else if (state==TK_STATE_DISABLED) {
1448     if (polyPtr->outline.disabledWidth>0.0) {
1449     width = polyPtr->outline.disabledWidth;
1450     }
1451     }
1452    
1453     radius = width/2.0;
1454     inside = -1;
1455    
1456     if ((state==TK_STATE_HIDDEN) || polyPtr->numPoints<2) {
1457     return -1;
1458     } else if (polyPtr->numPoints <3) {
1459     double oval[4];
1460     oval[0] = polyPtr->coordPtr[0]-radius;
1461     oval[1] = polyPtr->coordPtr[1]-radius;
1462     oval[2] = polyPtr->coordPtr[0]+radius;
1463     oval[3] = polyPtr->coordPtr[1]+radius;
1464     return TkOvalToArea(oval, rectPtr);
1465     }
1466     /*
1467     * Handle smoothed polygons by generating an expanded set of points
1468     * against which to do the check.
1469     */
1470    
1471     if (polyPtr->smooth) {
1472     numPoints = polyPtr->smooth->coordProc(canvas, (double *) NULL,
1473     polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
1474     (double *) NULL);
1475     if (numPoints <= MAX_STATIC_POINTS) {
1476     polyPoints = staticSpace;
1477     } else {
1478     polyPoints = (double *) ckalloc((unsigned)
1479     (2*numPoints*sizeof(double)));
1480     }
1481     numPoints = polyPtr->smooth->coordProc(canvas, polyPtr->coordPtr,
1482     polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL,
1483     polyPoints);
1484     } else {
1485     numPoints = polyPtr->numPoints;
1486     polyPoints = polyPtr->coordPtr;
1487     }
1488    
1489     if (polyPtr->fillGC != None) {
1490     inside = TkPolygonToArea(polyPoints, numPoints, rectPtr);
1491     if (inside==0) goto donearea;
1492     } else {
1493     if ((polyPoints[0] >= rectPtr[0])
1494     && (polyPoints[0] <= rectPtr[2])
1495     && (polyPoints[1] >= rectPtr[1])
1496     && (polyPoints[1] <= rectPtr[3])) {
1497     inside = 1;
1498     }
1499     }
1500    
1501     if (polyPtr->outline.gc == None) goto donearea ;
1502    
1503    
1504     /*
1505     * Iterate through all of the edges of the line, computing a polygon
1506     * for each edge and testing the area against that polygon. In
1507     * addition, there are additional tests to deal with rounded joints
1508     * and caps.
1509     */
1510    
1511     changedMiterToBevel = 0;
1512     for (count = numPoints, coordPtr = polyPoints; count >= 2;
1513     count--, coordPtr += 2) {
1514    
1515     /*
1516     * If rounding is done around the first point of the edge
1517     * then test a circular region around the point with the
1518     * area.
1519     */
1520    
1521     if (polyPtr->joinStyle == JoinRound) {
1522     poly[0] = coordPtr[0] - radius;
1523     poly[1] = coordPtr[1] - radius;
1524     poly[2] = coordPtr[0] + radius;
1525     poly[3] = coordPtr[1] + radius;
1526     if (TkOvalToArea(poly, rectPtr) != inside) {
1527     inside = 0;
1528     goto donearea;
1529     }
1530     }
1531    
1532     /*
1533     * Compute the polygonal shape corresponding to this edge,
1534     * consisting of two points for the first point of the edge
1535     * and two points for the last point of the edge.
1536     */
1537    
1538     if (count == numPoints) {
1539     TkGetButtPoints(coordPtr+2, coordPtr, width,
1540     0, poly, poly+2);
1541     } else if ((polyPtr->joinStyle == JoinMiter) && !changedMiterToBevel) {
1542     poly[0] = poly[6];
1543     poly[1] = poly[7];
1544     poly[2] = poly[4];
1545     poly[3] = poly[5];
1546     } else {
1547     TkGetButtPoints(coordPtr+2, coordPtr, width, 0,
1548     poly, poly+2);
1549    
1550     /*
1551     * If the last joint was beveled, then also check a
1552     * polygon comprising the last two points of the previous
1553     * polygon and the first two from this polygon; this checks
1554     * the wedges that fill the beveled joint.
1555     */
1556    
1557     if ((polyPtr->joinStyle == JoinBevel) || changedMiterToBevel) {
1558     poly[8] = poly[0];
1559     poly[9] = poly[1];
1560     if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
1561     inside = 0;
1562     goto donearea;
1563     }
1564     changedMiterToBevel = 0;
1565     }
1566     }
1567     if (count == 2) {
1568     TkGetButtPoints(coordPtr, coordPtr+2, width,
1569     0, poly+4, poly+6);
1570     } else if (polyPtr->joinStyle == JoinMiter) {
1571     if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
1572     width, poly+4, poly+6) == 0) {
1573     changedMiterToBevel = 1;
1574     TkGetButtPoints(coordPtr, coordPtr+2, width,
1575     0, poly+4, poly+6);
1576     }
1577     } else {
1578     TkGetButtPoints(coordPtr, coordPtr+2, width, 0,
1579     poly+4, poly+6);
1580     }
1581     poly[8] = poly[0];
1582     poly[9] = poly[1];
1583     if (TkPolygonToArea(poly, 5, rectPtr) != inside) {
1584     inside = 0;
1585     goto donearea;
1586     }
1587     }
1588    
1589     donearea:
1590     if ((polyPoints != staticSpace) && (polyPoints != polyPtr->coordPtr)) {
1591     ckfree((char *) polyPoints);
1592     }
1593     return inside;
1594     }
1595    
1596     /*
1597     *--------------------------------------------------------------
1598     *
1599     * ScalePolygon --
1600     *
1601     * This procedure is invoked to rescale a polygon item.
1602     *
1603     * Results:
1604     * None.
1605     *
1606     * Side effects:
1607     * The polygon referred to by itemPtr is rescaled so that the
1608     * following transformation is applied to all point
1609     * coordinates:
1610     * x' = originX + scaleX*(x-originX)
1611     * y' = originY + scaleY*(y-originY)
1612     *
1613     *--------------------------------------------------------------
1614     */
1615    
1616     static void
1617     ScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY)
1618     Tk_Canvas canvas; /* Canvas containing polygon. */
1619     Tk_Item *itemPtr; /* Polygon to be scaled. */
1620     double originX, originY; /* Origin about which to scale rect. */
1621     double scaleX; /* Amount to scale in X direction. */
1622     double scaleY; /* Amount to scale in Y direction. */
1623     {
1624     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1625     double *coordPtr;
1626     int i;
1627    
1628     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
1629     i++, coordPtr += 2) {
1630     *coordPtr = originX + scaleX*(*coordPtr - originX);
1631     coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
1632     }
1633     ComputePolygonBbox(canvas, polyPtr);
1634     }
1635    
1636     /*
1637     *--------------------------------------------------------------
1638     *
1639     * GetPolygonIndex --
1640     *
1641     * Parse an index into a polygon item and return either its value
1642     * or an error.
1643     *
1644     * Results:
1645     * A standard Tcl result. If all went well, then *indexPtr is
1646     * filled in with the index (into itemPtr) corresponding to
1647     * string. Otherwise an error message is left in
1648     * interp->result.
1649     *
1650     * Side effects:
1651     * None.
1652     *
1653     *--------------------------------------------------------------
1654     */
1655    
1656     static int
1657     GetPolygonIndex(interp, canvas, itemPtr, obj, indexPtr)
1658     Tcl_Interp *interp; /* Used for error reporting. */
1659     Tk_Canvas canvas; /* Canvas containing item. */
1660     Tk_Item *itemPtr; /* Item for which the index is being
1661     * specified. */
1662     Tcl_Obj *obj; /* Specification of a particular coord
1663     * in itemPtr's line. */
1664     int *indexPtr; /* Where to store converted index. */
1665     {
1666     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1667     size_t length;
1668     char *string = Tcl_GetStringFromObj(obj, (int *) &length);
1669    
1670     if (string[0] == 'e') {
1671     if (strncmp(string, "end", length) == 0) {
1672     *indexPtr = 2*(polyPtr->numPoints - polyPtr->autoClosed);
1673     } else {
1674     badIndex:
1675    
1676     /*
1677     * Some of the paths here leave messages in interp->result,
1678     * so we have to clear it out before storing our own message.
1679     */
1680    
1681     Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
1682     Tcl_AppendResult(interp, "bad index \"", string, "\"",
1683     (char *) NULL);
1684     return TCL_ERROR;
1685     }
1686     } else if (string[0] == '@') {
1687     int i;
1688     double x ,y, bestDist, dist, *coordPtr;
1689     char *end, *p;
1690    
1691     p = string+1;
1692     x = strtod(p, &end);
1693     if ((end == p) || (*end != ',')) {
1694     goto badIndex;
1695     }
1696     p = end+1;
1697     y = strtod(p, &end);
1698     if ((end == p) || (*end != 0)) {
1699     goto badIndex;
1700     }
1701     bestDist = 1.0e36;
1702     coordPtr = polyPtr->coordPtr;
1703     *indexPtr = 0;
1704     for(i=0; i<(polyPtr->numPoints-1); i++) {
1705     dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
1706     if (dist<bestDist) {
1707     bestDist = dist;
1708     *indexPtr = 2*i;
1709     }
1710     coordPtr += 2;
1711     }
1712     } else {
1713     int count = 2*(polyPtr->numPoints - polyPtr->autoClosed);
1714     if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
1715     goto badIndex;
1716     }
1717     *indexPtr &= -2; /* if odd, make it even */
1718     if (count) {
1719     if (*indexPtr > 0) {
1720     *indexPtr = ((*indexPtr - 2) % count) + 2;
1721     } else {
1722     *indexPtr = -((-(*indexPtr)) % count);
1723     }
1724     } else {
1725     *indexPtr = 0;
1726     }
1727     }
1728     return TCL_OK;
1729     }
1730    
1731     /*
1732     *--------------------------------------------------------------
1733     *
1734     * TranslatePolygon --
1735     *
1736     * This procedure is called to move a polygon by a given
1737     * amount.
1738     *
1739     * Results:
1740     * None.
1741     *
1742     * Side effects:
1743     * The position of the polygon is offset by (xDelta, yDelta),
1744     * and the bounding box is updated in the generic part of the
1745     * item structure.
1746     *
1747     *--------------------------------------------------------------
1748     */
1749    
1750     static void
1751     TranslatePolygon(canvas, itemPtr, deltaX, deltaY)
1752     Tk_Canvas canvas; /* Canvas containing item. */
1753     Tk_Item *itemPtr; /* Item that is being moved. */
1754     double deltaX, deltaY; /* Amount by which item is to be
1755     * moved. */
1756     {
1757     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1758     double *coordPtr;
1759     int i;
1760    
1761     for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints;
1762     i++, coordPtr += 2) {
1763     *coordPtr += deltaX;
1764     coordPtr[1] += deltaY;
1765     }
1766     ComputePolygonBbox(canvas, polyPtr);
1767     }
1768    
1769     /*
1770     *--------------------------------------------------------------
1771     *
1772     * PolygonToPostscript --
1773     *
1774     * This procedure is called to generate Postscript for
1775     * polygon items.
1776     *
1777     * Results:
1778     * The return value is a standard Tcl result. If an error
1779     * occurs in generating Postscript then an error message is
1780     * left in the interp's result, replacing whatever used
1781     * to be there. If no error occurs, then Postscript for the
1782     * item is appended to the result.
1783     *
1784     * Side effects:
1785     * None.
1786     *
1787     *--------------------------------------------------------------
1788     */
1789    
1790     static int
1791     PolygonToPostscript(interp, canvas, itemPtr, prepass)
1792     Tcl_Interp *interp; /* Leave Postscript or error message
1793     * here. */
1794     Tk_Canvas canvas; /* Information about overall canvas. */
1795     Tk_Item *itemPtr; /* Item for which Postscript is
1796     * wanted. */
1797     int prepass; /* 1 means this is a prepass to
1798     * collect font information; 0 means
1799     * final Postscript is being created. */
1800     {
1801     PolygonItem *polyPtr = (PolygonItem *) itemPtr;
1802     char *style;
1803     XColor *color;
1804     XColor *fillColor;
1805     Pixmap stipple;
1806     Pixmap fillStipple;
1807     Tk_State state = itemPtr->state;
1808     double width;
1809    
1810     if (polyPtr->numPoints<2 || polyPtr->coordPtr==NULL) {
1811     return TCL_OK;
1812     }
1813    
1814     if(state == TK_STATE_NULL) {
1815     state = ((TkCanvas *)canvas)->canvas_state;
1816     }
1817     width = polyPtr->outline.width;
1818     color = polyPtr->outline.color;
1819     stipple = polyPtr->fillStipple;
1820     fillColor = polyPtr->fillColor;
1821     fillStipple = polyPtr->fillStipple;
1822     if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
1823     if (polyPtr->outline.activeWidth>width) {
1824     width = polyPtr->outline.activeWidth;
1825     }
1826     if (polyPtr->outline.activeColor!=NULL) {
1827     color = polyPtr->outline.activeColor;
1828     }
1829     if (polyPtr->outline.activeStipple!=None) {
1830     stipple = polyPtr->outline.activeStipple;
1831     }
1832     if (polyPtr->activeFillColor!=NULL) {
1833     fillColor = polyPtr->activeFillColor;
1834     }
1835     if (polyPtr->activeFillStipple!=None) {
1836     fillStipple = polyPtr->activeFillStipple;
1837     }
1838     } else if (state==TK_STATE_DISABLED) {
1839     if (polyPtr->outline.disabledWidth>0.0) {
1840     width = polyPtr->outline.disabledWidth;
1841     }
1842     if (polyPtr->outline.disabledColor!=NULL) {
1843     color = polyPtr->outline.disabledColor;
1844     }
1845     if (polyPtr->outline.disabledStipple!=None) {
1846     stipple = polyPtr->outline.disabledStipple;
1847     }
1848     if (polyPtr->disabledFillColor!=NULL) {
1849     fillColor = polyPtr->disabledFillColor;
1850     }
1851     if (polyPtr->disabledFillStipple!=None) {
1852     fillStipple = polyPtr->disabledFillStipple;
1853     }
1854     }
1855     if (polyPtr->numPoints==2) {
1856     char string[128];
1857     sprintf(string, "%.15g %.15g translate %.15g %.15g",
1858     polyPtr->coordPtr[0], Tk_CanvasPsY(canvas, polyPtr->coordPtr[1]),
1859     width/2.0, width/2.0);
1860     Tcl_AppendResult(interp, "matrix currentmatrix\n",string,
1861     " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);
1862     if (Tk_CanvasPsColor(interp, canvas, color)
1863     != TCL_OK) {
1864     return TCL_ERROR;
1865     }
1866     if (stipple != None) {
1867     Tcl_AppendResult(interp, "clip ", (char *) NULL);
1868     if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
1869     return TCL_ERROR;
1870     }
1871     } else {
1872     Tcl_AppendResult(interp, "fill\n", (char *) NULL);
1873     }
1874     return TCL_OK;
1875     }
1876    
1877     /*
1878     * Fill the area of the polygon.
1879     */
1880    
1881     if (fillColor != NULL && polyPtr->numPoints>3) {
1882     if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
1883     Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
1884     polyPtr->numPoints);
1885     } else {
1886     polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
1887     polyPtr->numPoints, polyPtr->splineSteps);
1888     }
1889     if (Tk_CanvasPsColor(interp, canvas, fillColor) != TCL_OK) {
1890     return TCL_ERROR;
1891     }
1892     if (fillStipple != None) {
1893     Tcl_AppendResult(interp, "eoclip ", (char *) NULL);
1894     if (Tk_CanvasPsStipple(interp, canvas, fillStipple)
1895     != TCL_OK) {
1896     return TCL_ERROR;
1897     }
1898     if (color != NULL) {
1899     Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
1900     }
1901     } else {
1902     Tcl_AppendResult(interp, "eofill\n", (char *) NULL);
1903     }
1904     }
1905    
1906     /*
1907     * Now draw the outline, if there is one.
1908     */
1909    
1910     if (color != NULL) {
1911    
1912     if (!polyPtr->smooth || !polyPtr->smooth->postscriptProc) {
1913     Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr,
1914     polyPtr->numPoints);
1915     } else {
1916     polyPtr->smooth->postscriptProc(interp, canvas, polyPtr->coordPtr,
1917     polyPtr->numPoints, polyPtr->splineSteps);
1918     }
1919    
1920     if (polyPtr->joinStyle == JoinRound) {
1921     style = "1";
1922     } else if (polyPtr->joinStyle == JoinBevel) {
1923     style = "2";
1924     } else {
1925     style = "0";
1926     }
1927     Tcl_AppendResult(interp, style," setlinejoin 1 setlinecap\n",
1928     (char *) NULL);
1929     if (Tk_CanvasPsOutline(canvas, itemPtr,
1930     &(polyPtr->outline)) != TCL_OK) {
1931     return TCL_ERROR;
1932     }
1933     }
1934     return TCL_OK;
1935     }
1936    
1937 dashley 69 /* End of tkcanvpoly.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25