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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25