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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (7 years, 4 months ago) by dashley
File MIME type: text/plain
File size: 40560 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkCanvUtil.c --
5 *
6 * This procedure contains a collection of utility procedures
7 * used by the implementations of various canvas item types.
8 *
9 * Copyright (c) 1994 Sun Microsystems, Inc.
10 * Copyright (c) 1994 Sun Microsystems, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tkcanvutil.c,v 1.1.1.1 2001/06/13 04:57:52 dtashley Exp $
16 */
17
18 #include "tkInt.h"
19 #include "tkCanvas.h"
20 #include "tkPort.h"
21
22
23 /*
24 *----------------------------------------------------------------------
25 *
26 * Tk_CanvasTkwin --
27 *
28 * Given a token for a canvas, this procedure returns the
29 * widget that represents the canvas.
30 *
31 * Results:
32 * The return value is a handle for the widget.
33 *
34 * Side effects:
35 * None.
36 *
37 *----------------------------------------------------------------------
38 */
39
40 Tk_Window
41 Tk_CanvasTkwin(canvas)
42 Tk_Canvas canvas; /* Token for the canvas. */
43 {
44 TkCanvas *canvasPtr = (TkCanvas *) canvas;
45 return canvasPtr->tkwin;
46 }
47
48 /*
49 *----------------------------------------------------------------------
50 *
51 * Tk_CanvasDrawableCoords --
52 *
53 * Given an (x,y) coordinate pair within a canvas, this procedure
54 * returns the corresponding coordinates at which the point should
55 * be drawn in the drawable used for display.
56 *
57 * Results:
58 * There is no return value. The values at *drawableXPtr and
59 * *drawableYPtr are filled in with the coordinates at which
60 * x and y should be drawn. These coordinates are clipped
61 * to fit within a "short", since this is what X uses in
62 * most cases for drawing.
63 *
64 * Side effects:
65 * None.
66 *
67 *----------------------------------------------------------------------
68 */
69
70 void
71 Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr)
72 Tk_Canvas canvas; /* Token for the canvas. */
73 double x, y; /* Coordinates in canvas space. */
74 short *drawableXPtr, *drawableYPtr; /* Screen coordinates are stored
75 * here. */
76 {
77 TkCanvas *canvasPtr = (TkCanvas *) canvas;
78 double tmp;
79
80 tmp = x - canvasPtr->drawableXOrigin;
81 if (tmp > 0) {
82 tmp += 0.5;
83 } else {
84 tmp -= 0.5;
85 }
86 if (tmp > 32767) {
87 *drawableXPtr = 32767;
88 } else if (tmp < -32768) {
89 *drawableXPtr = -32768;
90 } else {
91 *drawableXPtr = (short) tmp;
92 }
93
94 tmp = y - canvasPtr->drawableYOrigin;
95 if (tmp > 0) {
96 tmp += 0.5;
97 } else {
98 tmp -= 0.5;
99 }
100 if (tmp > 32767) {
101 *drawableYPtr = 32767;
102 } else if (tmp < -32768) {
103 *drawableYPtr = -32768;
104 } else {
105 *drawableYPtr = (short) tmp;
106 }
107 }
108
109 /*
110 *----------------------------------------------------------------------
111 *
112 * Tk_CanvasWindowCoords --
113 *
114 * Given an (x,y) coordinate pair within a canvas, this procedure
115 * returns the corresponding coordinates in the canvas's window.
116 *
117 * Results:
118 * There is no return value. The values at *screenXPtr and
119 * *screenYPtr are filled in with the coordinates at which
120 * (x,y) appears in the canvas's window. These coordinates
121 * are clipped to fit within a "short", since this is what X
122 * uses in most cases for drawing.
123 *
124 * Side effects:
125 * None.
126 *
127 *----------------------------------------------------------------------
128 */
129
130 void
131 Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr)
132 Tk_Canvas canvas; /* Token for the canvas. */
133 double x, y; /* Coordinates in canvas space. */
134 short *screenXPtr, *screenYPtr; /* Screen coordinates are stored
135 * here. */
136 {
137 TkCanvas *canvasPtr = (TkCanvas *) canvas;
138 double tmp;
139
140 tmp = x - canvasPtr->xOrigin;
141 if (tmp > 0) {
142 tmp += 0.5;
143 } else {
144 tmp -= 0.5;
145 }
146 if (tmp > 32767) {
147 *screenXPtr = 32767;
148 } else if (tmp < -32768) {
149 *screenXPtr = -32768;
150 } else {
151 *screenXPtr = (short) tmp;
152 }
153
154 tmp = y - canvasPtr->yOrigin;
155 if (tmp > 0) {
156 tmp += 0.5;
157 } else {
158 tmp -= 0.5;
159 }
160 if (tmp > 32767) {
161 *screenYPtr = 32767;
162 } else if (tmp < -32768) {
163 *screenYPtr = -32768;
164 } else {
165 *screenYPtr = (short) tmp;
166 }
167 }
168
169 /*
170 *--------------------------------------------------------------
171 *
172 * Tk_CanvasGetCoord --
173 *
174 * Given a string, returns a floating-point canvas coordinate
175 * corresponding to that string.
176 *
177 * Results:
178 * The return value is a standard Tcl return result. If
179 * TCL_OK is returned, then everything went well and the
180 * canvas coordinate is stored at *doublePtr; otherwise
181 * TCL_ERROR is returned and an error message is left in
182 * the interp's result.
183 *
184 * Side effects:
185 * None.
186 *
187 *--------------------------------------------------------------
188 */
189
190 int
191 Tk_CanvasGetCoord(interp, canvas, string, doublePtr)
192 Tcl_Interp *interp; /* Interpreter for error reporting. */
193 Tk_Canvas canvas; /* Canvas to which coordinate applies. */
194 char *string; /* Describes coordinate (any screen
195 * coordinate form may be used here). */
196 double *doublePtr; /* Place to store converted coordinate. */
197 {
198 TkCanvas *canvasPtr = (TkCanvas *) canvas;
199 if (Tk_GetScreenMM(canvasPtr->interp, canvasPtr->tkwin, string,
200 doublePtr) != TCL_OK) {
201 return TCL_ERROR;
202 }
203 *doublePtr *= canvasPtr->pixelsPerMM;
204 return TCL_OK;
205 }
206
207 /*
208 *--------------------------------------------------------------
209 *
210 * Tk_CanvasGetCoordFromObj --
211 *
212 * Given a string, returns a floating-point canvas coordinate
213 * corresponding to that string.
214 *
215 * Results:
216 * The return value is a standard Tcl return result. If
217 * TCL_OK is returned, then everything went well and the
218 * canvas coordinate is stored at *doublePtr; otherwise
219 * TCL_ERROR is returned and an error message is left in
220 * interp->result.
221 *
222 * Side effects:
223 * None.
224 *
225 *--------------------------------------------------------------
226 */
227
228 int
229 Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr)
230 Tcl_Interp *interp; /* Interpreter for error reporting. */
231 Tk_Canvas canvas; /* Canvas to which coordinate applies. */
232 Tcl_Obj *obj; /* Describes coordinate (any screen
233 * coordinate form may be used here). */
234 double *doublePtr; /* Place to store converted coordinate. */
235 {
236 TkCanvas *canvasPtr = (TkCanvas *) canvas;
237 if (Tk_GetMMFromObj(canvasPtr->interp, canvasPtr->tkwin, obj,
238 doublePtr) != TCL_OK) {
239 return TCL_ERROR;
240 }
241 *doublePtr *= canvasPtr->pixelsPerMM;
242 return TCL_OK;
243 }
244
245 /*
246 *----------------------------------------------------------------------
247 *
248 * Tk_CanvasSetStippleOrigin --
249 *
250 * This procedure sets the stipple origin in a graphics context
251 * so that stipples drawn with the GC will line up with other
252 * stipples previously drawn in the canvas.
253 *
254 * Results:
255 * None.
256 *
257 * Side effects:
258 * The graphics context is modified.
259 *
260 *----------------------------------------------------------------------
261 */
262
263 void
264 Tk_CanvasSetStippleOrigin(canvas, gc)
265 Tk_Canvas canvas; /* Token for a canvas. */
266 GC gc; /* Graphics context that is about to be
267 * used to draw a stippled pattern as
268 * part of redisplaying the canvas. */
269
270 {
271 TkCanvas *canvasPtr = (TkCanvas *) canvas;
272
273 XSetTSOrigin(canvasPtr->display, gc, -canvasPtr->drawableXOrigin,
274 -canvasPtr->drawableYOrigin);
275 }
276
277 /*
278 *----------------------------------------------------------------------
279 *
280 * Tk_CanvasSetOffset--
281 *
282 * This procedure sets the stipple offset in a graphics
283 * context so that stipples drawn with the GC will
284 * line up with other stipples with the same offset.
285 *
286 * Results:
287 * None.
288 *
289 * Side effects:
290 * The graphics context is modified.
291 *
292 *----------------------------------------------------------------------
293 */
294
295 void
296 Tk_CanvasSetOffset(canvas, gc, offset)
297 Tk_Canvas canvas; /* Token for a canvas. */
298 GC gc; /* Graphics context that is about to be
299 * used to draw a stippled pattern as
300 * part of redisplaying the canvas. */
301 Tk_TSOffset *offset; /* offset (may be NULL pointer)*/
302 {
303 TkCanvas *canvasPtr = (TkCanvas *) canvas;
304 int flags = 0;
305 int x = - canvasPtr->drawableXOrigin;
306 int y = - canvasPtr->drawableYOrigin;
307
308 if (offset != NULL) {
309 flags = offset->flags;
310 x += offset->xoffset;
311 y += offset->yoffset;
312 }
313 if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {
314 Tk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,
315 y - canvasPtr->yOrigin);
316 } else {
317 XSetTSOrigin(canvasPtr->display, gc, x, y);
318 }
319 }
320
321 /*
322 *----------------------------------------------------------------------
323 *
324 * Tk_CanvasGetTextInfo --
325 *
326 * This procedure returns a pointer to a structure containing
327 * information about the selection and insertion cursor for
328 * a canvas widget. Items such as text items save the pointer
329 * and use it to share access to the information with the generic
330 * canvas code.
331 *
332 * Results:
333 * The return value is a pointer to the structure holding text
334 * information for the canvas. Most of the fields should not
335 * be modified outside the generic canvas code; see the user
336 * documentation for details.
337 *
338 * Side effects:
339 * None.
340 *
341 *----------------------------------------------------------------------
342 */
343
344 Tk_CanvasTextInfo *
345 Tk_CanvasGetTextInfo(canvas)
346 Tk_Canvas canvas; /* Token for the canvas widget. */
347 {
348 return &((TkCanvas *) canvas)->textInfo;
349 }
350
351 /*
352 *--------------------------------------------------------------
353 *
354 * Tk_CanvasTagsParseProc --
355 *
356 * This procedure is invoked during option processing to handle
357 * "-tags" options for canvas items.
358 *
359 * Results:
360 * A standard Tcl return value.
361 *
362 * Side effects:
363 * The tags for a given item get replaced by those indicated
364 * in the value argument.
365 *
366 *--------------------------------------------------------------
367 */
368
369 int
370 Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset)
371 ClientData clientData; /* Not used.*/
372 Tcl_Interp *interp; /* Used for reporting errors. */
373 Tk_Window tkwin; /* Window containing canvas widget. */
374 char *value; /* Value of option (list of tag
375 * names). */
376 char *widgRec; /* Pointer to record for item. */
377 int offset; /* Offset into item (ignored). */
378 {
379 register Tk_Item *itemPtr = (Tk_Item *) widgRec;
380 int argc, i;
381 char **argv;
382 Tk_Uid *newPtr;
383
384 /*
385 * Break the value up into the individual tag names.
386 */
387
388 if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
389 return TCL_ERROR;
390 }
391
392 /*
393 * Make sure that there's enough space in the item to hold the
394 * tag names.
395 */
396
397 if (itemPtr->tagSpace < argc) {
398 newPtr = (Tk_Uid *) ckalloc((unsigned) (argc * sizeof(Tk_Uid)));
399 for (i = itemPtr->numTags-1; i >= 0; i--) {
400 newPtr[i] = itemPtr->tagPtr[i];
401 }
402 if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
403 ckfree((char *) itemPtr->tagPtr);
404 }
405 itemPtr->tagPtr = newPtr;
406 itemPtr->tagSpace = argc;
407 }
408 itemPtr->numTags = argc;
409 for (i = 0; i < argc; i++) {
410 itemPtr->tagPtr[i] = Tk_GetUid(argv[i]);
411 }
412 ckfree((char *) argv);
413 return TCL_OK;
414 }
415
416 /*
417 *--------------------------------------------------------------
418 *
419 * Tk_CanvasTagsPrintProc --
420 *
421 * This procedure is invoked by the Tk configuration code
422 * to produce a printable string for the "-tags" configuration
423 * option for canvas items.
424 *
425 * Results:
426 * The return value is a string describing all the tags for
427 * the item referred to by "widgRec". In addition, *freeProcPtr
428 * is filled in with the address of a procedure to call to free
429 * the result string when it's no longer needed (or NULL to
430 * indicate that the string doesn't need to be freed).
431 *
432 * Side effects:
433 * None.
434 *
435 *--------------------------------------------------------------
436 */
437
438 char *
439 Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
440 ClientData clientData; /* Ignored. */
441 Tk_Window tkwin; /* Window containing canvas widget. */
442 char *widgRec; /* Pointer to record for item. */
443 int offset; /* Ignored. */
444 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
445 * information about how to reclaim
446 * storage for return string. */
447 {
448 register Tk_Item *itemPtr = (Tk_Item *) widgRec;
449
450 if (itemPtr->numTags == 0) {
451 *freeProcPtr = (Tcl_FreeProc *) NULL;
452 return "";
453 }
454 if (itemPtr->numTags == 1) {
455 *freeProcPtr = (Tcl_FreeProc *) NULL;
456 return (char *) itemPtr->tagPtr[0];
457 }
458 *freeProcPtr = TCL_DYNAMIC;
459 return Tcl_Merge(itemPtr->numTags, (char **) itemPtr->tagPtr);
460 }
461
462
463 static int DashConvert _ANSI_ARGS_((char *l, CONST char *p,
464 int n, double width));
465 #define ABS(a) ((a>=0)?(a):(-(a)))
466
467 /*
468 *--------------------------------------------------------------
469 *
470 * TkCanvasDashParseProc --
471 *
472 * This procedure is invoked during option processing to handle
473 * "-dash", "-activedash" and "-disableddash" options for canvas
474 * objects.
475 *
476 * Results:
477 * A standard Tcl return value.
478 *
479 * Side effects:
480 * The dash list for a given canvas object gets replaced by
481 * those indicated in the value argument.
482 *
483 *--------------------------------------------------------------
484 */
485
486 int
487 TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset)
488 ClientData clientData; /* Not used.*/
489 Tcl_Interp *interp; /* Used for reporting errors. */
490 Tk_Window tkwin; /* Window containing canvas widget. */
491 CONST char *value; /* Value of option. */
492 char *widgRec; /* Pointer to record for item. */
493 int offset; /* Offset into item. */
494 {
495 return Tk_GetDash(interp, value, (Tk_Dash *)(widgRec+offset));
496 }
497
498 /*
499 *--------------------------------------------------------------
500 *
501 * TkCanvasDashPrintProc --
502 *
503 * This procedure is invoked by the Tk configuration code
504 * to produce a printable string for the "-dash", "-activedash"
505 * and "-disableddash" configuration options for canvas items.
506 *
507 * Results:
508 * The return value is a string describing all the dash list for
509 * the item referred to by "widgRec"and "offset". In addition,
510 * *freeProcPtr is filled in with the address of a procedure to
511 * call to free the result string when it's no longer needed (or
512 * NULL to indicate that the string doesn't need to be freed).
513 *
514 * Side effects:
515 * None.
516 *
517 *--------------------------------------------------------------
518 */
519
520 char *
521 TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
522 ClientData clientData; /* Ignored. */
523 Tk_Window tkwin; /* Window containing canvas widget. */
524 char *widgRec; /* Pointer to record for item. */
525 int offset; /* Offset in record for item. */
526 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
527 * information about how to reclaim
528 * storage for return string. */
529 {
530 Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
531 char *buffer;
532 char *p;
533 int i = dash->number;
534
535 if (i < 0) {
536 i = -i;
537 *freeProcPtr = TCL_DYNAMIC;
538 buffer = (char *) ckalloc((unsigned int) (i+1));
539 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
540 memcpy(buffer, p, (unsigned int) i);
541 buffer[i] = 0;
542 return buffer;
543 } else if (!i) {
544 *freeProcPtr = (Tcl_FreeProc *) NULL;
545 return "";
546 }
547 buffer = (char *)ckalloc((unsigned int) (4*i));
548 *freeProcPtr = TCL_DYNAMIC;
549
550 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
551 sprintf(buffer, "%d", *p++ & 0xff);
552 while(--i) {
553 sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
554 }
555 return buffer;
556 }
557
558 /*
559 *--------------------------------------------------------------
560 *
561 * Tk_CreateSmoothMethod --
562 *
563 * This procedure is invoked to add additional values
564 * for the "-smooth" option to the list.
565 *
566 * Results:
567 * A standard Tcl return value.
568 *
569 * Side effects:
570 * In the future "-smooth <name>" will be accepted as
571 * smooth method for the line and polygon.
572 *
573 *--------------------------------------------------------------
574 */
575
576 Tk_SmoothMethod tkBezierSmoothMethod = {
577 "bezier",
578 TkMakeBezierCurve,
579 (void (*) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas,
580 double *coordPtr, int numPoints, int numSteps)))
581 TkMakeBezierPostscript,
582 };
583
584 static void SmoothMethodCleanupProc _ANSI_ARGS_((ClientData clientData,
585 Tcl_Interp *interp));
586
587 typedef struct SmoothAssocData {
588 struct SmoothAssocData *nextPtr; /* pointer to next SmoothAssocData */
589 Tk_SmoothMethod smooth; /* name and functions associated with this
590 * option */
591 } SmoothAssocData;
592
593 void
594 Tk_CreateSmoothMethod(interp, smooth)
595 Tcl_Interp *interp;
596 Tk_SmoothMethod *smooth;
597 {
598 SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
599 methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
600 (Tcl_InterpDeleteProc **) NULL);
601
602 /*
603 * If there's already a smooth method with the given name, remove it.
604 */
605
606 for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;
607 prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
608 if (!strcmp(typePtr2->smooth.name, smooth->name)) {
609 if (prevPtr == NULL) {
610 methods = typePtr2->nextPtr;
611 } else {
612 prevPtr->nextPtr = typePtr2->nextPtr;
613 }
614 ckfree((char *) typePtr2);
615 break;
616 }
617 }
618 ptr = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData));
619 ptr->smooth.name = smooth->name;
620 ptr->smooth.coordProc = smooth->coordProc;
621 ptr->smooth.postscriptProc = smooth->postscriptProc;
622 ptr->nextPtr = methods;
623 Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,
624 (ClientData) ptr);
625 }
626 /*
627 *----------------------------------------------------------------------
628 *
629 * SmoothMethodCleanupProc --
630 *
631 * This procedure is invoked whenever an interpreter is deleted
632 * to cleanup the smooth methods.
633 *
634 * Results:
635 * None.
636 *
637 * Side effects:
638 * Smooth methods are removed.
639 *
640 *----------------------------------------------------------------------
641 */
642
643 static void
644 SmoothMethodCleanupProc(clientData, interp)
645 ClientData clientData; /* Points to "smoothMethod" AssocData
646 * for the interpreter. */
647 Tcl_Interp *interp; /* Interpreter that is being deleted. */
648 {
649 SmoothAssocData *ptr, *methods = (SmoothAssocData *) clientData;
650
651 while (methods != NULL) {
652 methods = (ptr = methods)->nextPtr;
653 ckfree((char *) ptr);
654 }
655 }
656 /*
657 *--------------------------------------------------------------
658 *
659 * TkSmoothParseProc --
660 *
661 * This procedure is invoked during option processing to handle
662 * the "-smooth" option.
663 *
664 * Results:
665 * A standard Tcl return value.
666 *
667 * Side effects:
668 * The smooth option for a given item gets replaced by the value
669 * indicated in the value argument.
670 *
671 *--------------------------------------------------------------
672 */
673
674 int
675 TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset)
676 ClientData clientData; /* some flags.*/
677 Tcl_Interp *interp; /* Used for reporting errors. */
678 Tk_Window tkwin; /* Window containing canvas widget. */
679 CONST char *value; /* Value of option. */
680 char *widgRec; /* Pointer to record for item. */
681 int offset; /* Offset into item. */
682 {
683 register Tk_SmoothMethod **smoothPtr =
684 (Tk_SmoothMethod **) (widgRec + offset);
685 Tk_SmoothMethod *smooth = NULL;
686 int b;
687 size_t length;
688 SmoothAssocData *methods;
689
690 if (value == NULL || *value == 0) {
691 *smoothPtr = (Tk_SmoothMethod *) NULL;
692 return TCL_OK;
693 }
694 length = strlen(value);
695 methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
696 (Tcl_InterpDeleteProc **) NULL);
697 while (methods != (SmoothAssocData *) NULL) {
698 if (strncmp(value, methods->smooth.name, length) == 0) {
699 if (smooth != (Tk_SmoothMethod *) NULL) {
700 Tcl_AppendResult(interp, "ambigeous smooth method \"", value,
701 "\"", (char *) NULL);
702 return TCL_ERROR;
703 }
704 smooth = &methods->smooth;
705 }
706 methods = methods->nextPtr;
707 }
708 if (smooth) {
709 *smoothPtr = smooth;
710 return TCL_OK;
711 }
712
713 if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
714 return TCL_ERROR;
715 }
716 *smoothPtr = b ? &tkBezierSmoothMethod : (Tk_SmoothMethod*) NULL;
717 return TCL_OK;
718 }
719 /*
720 *--------------------------------------------------------------
721 *
722 * TkSmoothPrintProc --
723 *
724 * This procedure is invoked by the Tk configuration code
725 * to produce a printable string for the "-smooth"
726 * configuration option.
727 *
728 * Results:
729 * The return value is a string describing the smooth option for
730 * the item referred to by "widgRec". In addition, *freeProcPtr
731 * is filled in with the address of a procedure to call to free
732 * the result string when it's no longer needed (or NULL to
733 * indicate that the string doesn't need to be freed).
734 *
735 * Side effects:
736 * None.
737 *
738 *--------------------------------------------------------------
739 */
740
741 char *
742 TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
743 ClientData clientData; /* Ignored. */
744 Tk_Window tkwin; /* Window containing canvas widget. */
745 char *widgRec; /* Pointer to record for item. */
746 int offset; /* Offset into item. */
747 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
748 * information about how to reclaim
749 * storage for return string. */
750 {
751 register Tk_SmoothMethod **smoothPtr = (Tk_SmoothMethod **) (widgRec + offset);
752
753 return (*smoothPtr) ? (*smoothPtr)->name : "0";
754 }
755 /*
756 *--------------------------------------------------------------
757 *
758 * Tk_GetDash
759 *
760 * This procedure is used to parse a string, assuming
761 * it is dash information.
762 *
763 * Results:
764 * The return value is a standard Tcl result: TCL_OK means
765 * that the dash information was parsed ok, and
766 * TCL_ERROR means it couldn't be parsed.
767 *
768 * Side effects:
769 * Dash information in the dash structure is updated.
770 *
771 *--------------------------------------------------------------
772 */
773
774 int
775 Tk_GetDash(interp, value, dash)
776 Tcl_Interp *interp; /* Used for error reporting. */
777 CONST char *value; /* Textual specification of dash list. */
778 Tk_Dash *dash; /* Pointer to record in which to
779 * store dash information. */
780 {
781 int argc, i;
782 char **largv, **argv = NULL;
783 char *pt;
784
785 if ((value==(char *) NULL) || (*value==0) ) {
786 dash->number = 0;
787 return TCL_OK;
788 }
789 if ((*value == '.') || (*value == ',') ||
790 (*value == '-') || (*value == '_')) {
791 i = DashConvert((char *) NULL, value, -1, 0.0);
792 if (i>0) {
793 i = strlen(value);
794 } else {
795 goto badDashList;
796 }
797 if (i > sizeof(char *)) {
798 dash->pattern.pt = pt = (char *) ckalloc(strlen(value));
799 } else {
800 pt = dash->pattern.array;
801 }
802 memcpy(pt,value, (unsigned int) i);
803 dash->number = -i;
804 return TCL_OK;
805 }
806 if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
807 Tcl_ResetResult(interp);
808 badDashList:
809 Tcl_AppendResult(interp, "bad dash list \"", value,
810 "\": must be a list of integers or a format like \"-..\"",
811 (char *) NULL);
812 syntaxError:
813 if (argv != NULL) {
814 ckfree((char *) argv);
815 }
816 if (ABS(dash->number) > sizeof(char *))
817 ckfree((char *) dash->pattern.pt);
818 dash->number = 0;
819 return TCL_ERROR;
820 }
821
822 if (ABS(dash->number) > sizeof(char *)) {
823 ckfree((char *) dash->pattern.pt);
824 }
825 if (argc > sizeof(char *)) {
826 dash->pattern.pt = pt = (char *) ckalloc((unsigned int) argc);
827 } else {
828 pt = dash->pattern.array;
829 }
830 dash->number = argc;
831
832 largv = argv;
833 while(argc>0) {
834 if (Tcl_GetInt(interp, *largv, &i) != TCL_OK ||
835 i < 1 || i>255) {
836 Tcl_ResetResult(interp);
837 Tcl_AppendResult(interp, "expected integer in the range 1..255 but got \"",
838 *largv, "\"", (char *) NULL);
839 goto syntaxError;
840 }
841 *pt++ = i;
842 argc--; largv++;
843 }
844
845 if (argv != NULL) {
846 ckfree((char *) argv);
847 }
848
849 return TCL_OK;
850 }
851
852 /*
853 *--------------------------------------------------------------
854 *
855 * Tk_CreateOutline
856 *
857 * This procedure initializes the Tk_Outline structure
858 * with default values.
859 *
860 * Results:
861 * None
862 *
863 * Side effects:
864 * None
865 *
866 *--------------------------------------------------------------
867 */
868
869 void Tk_CreateOutline(outline)
870 Tk_Outline *outline;
871 {
872 outline->gc = None;
873 outline->width = 1.0;
874 outline->activeWidth = 0.0;
875 outline->disabledWidth = 0.0;
876 outline->offset = 0;
877 outline->dash.number = 0;
878 outline->activeDash.number = 0;
879 outline->disabledDash.number = 0;
880 outline->tsoffset.flags = 0;
881 outline->tsoffset.xoffset = 0;
882 outline->tsoffset.yoffset = 0;
883 outline->color = NULL;
884 outline->activeColor = NULL;
885 outline->disabledColor = NULL;
886 outline->stipple = None;
887 outline->activeStipple = None;
888 outline->disabledStipple = None;
889 }
890
891 /*
892 *--------------------------------------------------------------
893 *
894 * Tk_DeleteOutline
895 *
896 * This procedure frees all memory that might be
897 * allocated and referenced in the Tk_Outline structure.
898 *
899 * Results:
900 * None
901 *
902 * Side effects:
903 * None
904 *
905 *--------------------------------------------------------------
906 */
907
908 void Tk_DeleteOutline(display, outline)
909 Display *display; /* Display containing window */
910 Tk_Outline *outline;
911 {
912 if (outline->gc != None) {
913 Tk_FreeGC(display, outline->gc);
914 }
915 if (ABS(outline->dash.number) > sizeof(char *)) {
916 ckfree((char *) outline->dash.pattern.pt);
917 }
918 if (ABS(outline->activeDash.number) > sizeof(char *)) {
919 ckfree((char *) outline->activeDash.pattern.pt);
920 }
921 if (ABS(outline->disabledDash.number) > sizeof(char *)) {
922 ckfree((char *) outline->disabledDash.pattern.pt);
923 }
924 if (outline->color != NULL) {
925 Tk_FreeColor(outline->color);
926 }
927 if (outline->activeColor != NULL) {
928 Tk_FreeColor(outline->activeColor);
929 }
930 if (outline->disabledColor != NULL) {
931 Tk_FreeColor(outline->disabledColor);
932 }
933 if (outline->stipple != None) {
934 Tk_FreeBitmap(display, outline->stipple);
935 }
936 if (outline->activeStipple != None) {
937 Tk_FreeBitmap(display, outline->activeStipple);
938 }
939 if (outline->disabledStipple != None) {
940 Tk_FreeBitmap(display, outline->disabledStipple);
941 }
942 }
943
944 /*
945 *--------------------------------------------------------------
946 *
947 * Tk_ConfigOutlineGC
948 *
949 * This procedure should be called in the canvas object
950 * during the configure command. The graphics context
951 * description in gcValues is updated according to the
952 * information in the dash structure, as far as possible.
953 *
954 * Results:
955 * The return-value is a mask, indicating which
956 * elements of gcValues have been updated.
957 * 0 means there is no outline.
958 *
959 * Side effects:
960 * GC information in gcValues is updated.
961 *
962 *--------------------------------------------------------------
963 */
964
965 int Tk_ConfigOutlineGC(gcValues, canvas, item, outline)
966 XGCValues *gcValues;
967 Tk_Canvas canvas;
968 Tk_Item *item;
969 Tk_Outline *outline;
970 {
971 int mask = 0;
972 double width;
973 Tk_Dash *dash;
974 XColor *color;
975 Pixmap stipple;
976 Tk_State state = item->state;
977
978 if (outline->width < 0.0) {
979 outline->width = 0.0;
980 }
981 if (outline->activeWidth < 0.0) {
982 outline->activeWidth = 0.0;
983 }
984 if (outline->disabledWidth < 0) {
985 outline->disabledWidth = 0.0;
986 }
987 if (state==TK_STATE_HIDDEN) {
988 return 0;
989 }
990
991 width = outline->width;
992 if (width < 1.0) {
993 width = 1.0;
994 }
995 dash = &(outline->dash);
996 color = outline->color;
997 stipple = outline->stipple;
998 if (state == TK_STATE_NULL) {
999 state = ((TkCanvas *)canvas)->canvas_state;
1000 }
1001 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1002 if (outline->activeWidth>width) {
1003 width = outline->activeWidth;
1004 }
1005 if (outline->activeDash.number != 0) {
1006 dash = &(outline->activeDash);
1007 }
1008 if (outline->activeColor!=NULL) {
1009 color = outline->activeColor;
1010 }
1011 if (outline->activeStipple!=None) {
1012 stipple = outline->activeStipple;
1013 }
1014 } else if (state==TK_STATE_DISABLED) {
1015 if (outline->disabledWidth>0) {
1016 width = outline->disabledWidth;
1017 }
1018 if (outline->disabledDash.number != 0) {
1019 dash = &(outline->disabledDash);
1020 }
1021 if (outline->disabledColor!=NULL) {
1022 color = outline->disabledColor;
1023 }
1024 if (outline->disabledStipple!=None) {
1025 stipple = outline->disabledStipple;
1026 }
1027 }
1028
1029 if (color==NULL) {
1030 return 0;
1031 }
1032
1033 gcValues->line_width = (int) (width + 0.5);
1034 if (color != NULL) {
1035 gcValues->foreground = color->pixel;
1036 mask = GCForeground|GCLineWidth;
1037 if (stipple != None) {
1038 gcValues->stipple = stipple;
1039 gcValues->fill_style = FillStippled;
1040 mask |= GCStipple|GCFillStyle;
1041 }
1042 }
1043 if (mask && (dash->number != 0)) {
1044 gcValues->line_style = LineOnOffDash;
1045 gcValues->dash_offset = outline->offset;
1046 if (dash->number >= 2) {
1047 gcValues->dashes = 4;
1048 } else if (dash->number > 0) {
1049 gcValues->dashes = dash->pattern.array[0];
1050 } else {
1051 gcValues->dashes = (char) (4 * width);
1052 }
1053 mask |= GCLineStyle|GCDashList|GCDashOffset;
1054 }
1055 return mask;
1056 }
1057
1058 /*
1059 *--------------------------------------------------------------
1060 *
1061 * Tk_ChangeOutlineGC
1062 *
1063 * Updates the GC to represent the full information of
1064 * the dash structure. Partly this is already done in
1065 * Tk_ConfigOutlineGC().
1066 * This function should be called just before drawing
1067 * the dashed item.
1068 *
1069 * Results:
1070 * 1 if there is a stipple pattern.
1071 * 0 otherwise.
1072 *
1073 * Side effects:
1074 * GC is updated.
1075 *
1076 *--------------------------------------------------------------
1077 */
1078
1079 int
1080 Tk_ChangeOutlineGC(canvas, item, outline)
1081 Tk_Canvas canvas;
1082 Tk_Item *item;
1083 Tk_Outline *outline;
1084 {
1085 CONST char *p;
1086 double width;
1087 Tk_Dash *dash;
1088 XColor *color;
1089 Pixmap stipple;
1090 Tk_State state = item->state;
1091
1092 width = outline->width;
1093 if (width < 1.0) {
1094 width = 1.0;
1095 }
1096 dash = &(outline->dash);
1097 color = outline->color;
1098 stipple = outline->stipple;
1099 if (state == TK_STATE_NULL) {
1100 state = ((TkCanvas *)canvas)->canvas_state;
1101 }
1102 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1103 if (outline->activeWidth > width) {
1104 width = outline->activeWidth;
1105 }
1106 if (outline->activeDash.number != 0) {
1107 dash = &(outline->activeDash);
1108 }
1109 if (outline->activeColor != NULL) {
1110 color = outline->activeColor;
1111 }
1112 if (outline->activeStipple != None) {
1113 stipple = outline->activeStipple;
1114 }
1115 } else if (state == TK_STATE_DISABLED) {
1116 if (outline->disabledWidth > width) {
1117 width = outline->disabledWidth;
1118 }
1119 if (outline->disabledDash.number != 0) {
1120 dash = &(outline->disabledDash);
1121 }
1122 if (outline->disabledColor != NULL) {
1123 color = outline->disabledColor;
1124 }
1125 if (outline->disabledStipple != None) {
1126 stipple = outline->disabledStipple;
1127 }
1128 }
1129 if (color==NULL) {
1130 return 0;
1131 }
1132
1133 if ((dash->number<-1) || ((dash->number == -1) && (dash->pattern.array[1]!=','))) {
1134 char *q;
1135 int i = -dash->number;
1136
1137 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
1138 q = (char *) ckalloc(2*(unsigned int)i);
1139 i = DashConvert(q, p, i, width);
1140 XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, q, i);
1141 ckfree(q);
1142 } else if ( dash->number>2 || (dash->number==2 &&
1143 (dash->pattern.array[0]!=dash->pattern.array[1]))) {
1144 p = (char *) (dash->number > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
1145 XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, p, dash->number);
1146 }
1147 if (stipple!=None) {
1148 int w=0; int h=0;
1149 Tk_TSOffset *tsoffset = &outline->tsoffset;
1150 int flags = tsoffset->flags;
1151 if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
1152 Tk_SizeOfBitmap(((TkCanvas *)canvas)->display, stipple, &w, &h);
1153 if (flags & TK_OFFSET_CENTER) {
1154 w /= 2;
1155 } else {
1156 w = 0;
1157 }
1158 if (flags & TK_OFFSET_MIDDLE) {
1159 h /= 2;
1160 } else {
1161 h = 0;
1162 }
1163 }
1164 tsoffset->xoffset -= w;
1165 tsoffset->yoffset -= h;
1166 Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
1167 tsoffset->xoffset += w;
1168 tsoffset->yoffset += h;
1169 return 1;
1170 }
1171 return 0;
1172 }
1173
1174
1175 /*
1176 *--------------------------------------------------------------
1177 *
1178 * Tk_ResetOutlineGC
1179 *
1180 * Restores the GC to the situation before
1181 * Tk_ChangeDashGC() was called.
1182 * This function should be called just after the dashed
1183 * item is drawn, because the GC is supposed to be
1184 * read-only.
1185 *
1186 * Results:
1187 * 1 if there is a stipple pattern.
1188 * 0 otherwise.
1189 *
1190 * Side effects:
1191 * GC is updated.
1192 *
1193 *--------------------------------------------------------------
1194 */
1195 int
1196 Tk_ResetOutlineGC(canvas, item, outline)
1197 Tk_Canvas canvas;
1198 Tk_Item *item;
1199 Tk_Outline *outline;
1200 {
1201 char dashList;
1202 double width;
1203 Tk_Dash *dash;
1204 XColor *color;
1205 Pixmap stipple;
1206 Tk_State state = item->state;
1207
1208 width = outline->width;
1209 if (width < 1.0) {
1210 width = 1.0;
1211 }
1212 dash = &(outline->dash);
1213 color = outline->color;
1214 stipple = outline->stipple;
1215 if (state == TK_STATE_NULL) {
1216 state = ((TkCanvas *)canvas)->canvas_state;
1217 }
1218 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1219 if (outline->activeWidth>width) {
1220 width = outline->activeWidth;
1221 }
1222 if (outline->activeDash.number != 0) {
1223 dash = &(outline->activeDash);
1224 }
1225 if (outline->activeColor!=NULL) {
1226 color = outline->activeColor;
1227 }
1228 if (outline->activeStipple!=None) {
1229 stipple = outline->activeStipple;
1230 }
1231 } else if (state==TK_STATE_DISABLED) {
1232 if (outline->disabledWidth>width) {
1233 width = outline->disabledWidth;
1234 }
1235 if (outline->disabledDash.number != 0) {
1236 dash = &(outline->disabledDash);
1237 }
1238 if (outline->disabledColor!=NULL) {
1239 color = outline->disabledColor;
1240 }
1241 if (outline->disabledStipple!=None) {
1242 stipple = outline->disabledStipple;
1243 }
1244 }
1245 if (color==NULL) {
1246 return 0;
1247 }
1248
1249 if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&
1250 (dash->pattern.array[0] != dash->pattern.array[1])) ||
1251 ((dash->number == -1) && (dash->pattern.array[1] != ','))) {
1252 if (dash->number < 0) {
1253 dashList = (int) (4 * width + 0.5);
1254 } else if (dash->number<3) {
1255 dashList = dash->pattern.array[0];
1256 } else {
1257 dashList = 4;
1258 }
1259 XSetDashes(((TkCanvas *)canvas)->display, outline->gc,
1260 outline->offset, &dashList , 1);
1261 }
1262 if (stipple != None) {
1263 XSetTSOrigin(((TkCanvas *)canvas)->display, outline->gc, 0, 0);
1264 return 1;
1265 }
1266 return 0;
1267 }
1268
1269
1270 /*
1271 *--------------------------------------------------------------
1272 *
1273 * Tk_CanvasPsOutline
1274 *
1275 * Creates the postscript command for the correct
1276 * Outline-information (width, dash, color and stipple).
1277 *
1278 * Results:
1279 * TCL_OK if succeeded, otherwise TCL_ERROR.
1280 *
1281 * Side effects:
1282 * canvas->interp->result contains the postscript string,
1283 * or an error message if the result was TCL_ERROR.
1284 *
1285 *--------------------------------------------------------------
1286 */
1287 int
1288 Tk_CanvasPsOutline(canvas, item, outline)
1289 Tk_Canvas canvas;
1290 Tk_Item *item;
1291 Tk_Outline *outline;
1292 {
1293 char string[41];
1294 char pattern[11];
1295 int i;
1296 char *ptr;
1297 char *str = string;
1298 char *lptr = pattern;
1299 Tcl_Interp *interp = ((TkCanvas *)canvas)->interp;
1300 double width;
1301 Tk_Dash *dash;
1302 XColor *color;
1303 Pixmap stipple;
1304 Tk_State state = item->state;
1305
1306 width = outline->width;
1307 dash = &(outline->dash);
1308 color = outline->color;
1309 stipple = outline->stipple;
1310 if (state == TK_STATE_NULL) {
1311 state = ((TkCanvas *)canvas)->canvas_state;
1312 }
1313 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1314 if (outline->activeWidth > width) {
1315 width = outline->activeWidth;
1316 }
1317 if (outline->activeDash.number > 0) {
1318 dash = &(outline->activeDash);
1319 }
1320 if (outline->activeColor != NULL) {
1321 color = outline->activeColor;
1322 }
1323 if (outline->activeStipple != None) {
1324 stipple = outline->activeStipple;
1325 }
1326 } else if (state == TK_STATE_DISABLED) {
1327 if (outline->disabledWidth > 0) {
1328 width = outline->disabledWidth;
1329 }
1330 if (outline->disabledDash.number > 0) {
1331 dash = &(outline->disabledDash);
1332 }
1333 if (outline->disabledColor != NULL) {
1334 color = outline->disabledColor;
1335 }
1336 if (outline->disabledStipple != None) {
1337 stipple = outline->disabledStipple;
1338 }
1339 }
1340 sprintf(string, "%.15g setlinewidth\n", width);
1341 Tcl_AppendResult(interp, string, (char *) NULL);
1342
1343 if (dash->number > 10) {
1344 str = (char *)ckalloc((unsigned int) (1 + 4*dash->number));
1345 } else if (dash->number < -5) {
1346 str = (char *)ckalloc((unsigned int) (1 - 8*dash->number));
1347 lptr = (char *)ckalloc((unsigned int) (1 - 2*dash->number));
1348 }
1349 ptr = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
1350 dash->pattern.pt : dash->pattern.array;
1351 if (dash->number > 0) {
1352 char *ptr0 = ptr;
1353 sprintf(str, "[%d", *ptr++ & 0xff);
1354 i = dash->number-1;
1355 while (i--) {
1356 sprintf(str+strlen(str), " %d", *ptr++ & 0xff);
1357 }
1358 Tcl_AppendResult(interp, str, (char *)NULL);
1359 if (dash->number&1) {
1360 Tcl_AppendResult(interp, " ", str+1, (char *)NULL);
1361 }
1362 sprintf(str, "] %d setdash\n", outline->offset);
1363 Tcl_AppendResult(interp, str, (char *)NULL);
1364 ptr = ptr0;
1365 } else if (dash->number < 0) {
1366 if ((i = DashConvert(lptr, ptr, -dash->number, width)) != 0) {
1367 char *lptr0 = lptr;
1368 sprintf(str, "[%d", *lptr++ & 0xff);
1369 while (--i) {
1370 sprintf(str+strlen(str), " %d", *lptr++ & 0xff);
1371 }
1372 Tcl_AppendResult(interp, str, (char *)NULL);
1373 sprintf(str, "] %d setdash\n", outline->offset);
1374 Tcl_AppendResult(interp, str, (char *)NULL);
1375 lptr = lptr0;
1376 } else {
1377 Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
1378 }
1379 } else {
1380 Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
1381 }
1382 if (str != string) {
1383 ckfree(str);
1384 }
1385 if (lptr != pattern) {
1386 ckfree(lptr);
1387 }
1388 if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
1389 return TCL_ERROR;
1390 }
1391 if (stipple != None) {
1392 Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
1393 if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
1394 return TCL_ERROR;
1395 }
1396 } else {
1397 Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
1398 }
1399
1400 return TCL_OK;
1401 }
1402
1403
1404 /*
1405 *--------------------------------------------------------------
1406 *
1407 * DashConvert
1408 *
1409 * Converts a character-like dash-list (e.g. "-..")
1410 * into an X11-style. l must point to a string that
1411 * holds room to at least 2*n characters. if
1412 * l == NULL, this function can be used for
1413 * syntax checking only.
1414 *
1415 * Results:
1416 * The length of the resulting X11 compatible
1417 * dash-list. -1 if failed.
1418 *
1419 * Side effects:
1420 * None
1421 *
1422 *--------------------------------------------------------------
1423 */
1424
1425 static int
1426 DashConvert (l, p, n, width)
1427 char *l;
1428 CONST char *p;
1429 int n;
1430 double width;
1431 {
1432 int result = 0;
1433 int size, intWidth;
1434
1435 if (n<0) {
1436 n = strlen(p);
1437 }
1438 intWidth = (int) (width + 0.5);
1439 if (intWidth < 1) {
1440 intWidth = 1;
1441 }
1442 while (n-- && *p) {
1443 switch (*p++) {
1444 case ' ':
1445 if (result) {
1446 if (l) {
1447 l[-1] += intWidth + 1;
1448 }
1449 continue;
1450 } else {
1451 return 0;
1452 }
1453 break;
1454 case '_':
1455 size = 8;
1456 break;
1457 case '-':
1458 size = 6;
1459 break;
1460 case ',':
1461 size = 4;
1462 break;
1463 case '.':
1464 size = 2;
1465 break;
1466 default:
1467 return -1;
1468 }
1469 if (l) {
1470 *l++ = size * intWidth;
1471 *l++ = 4 * intWidth;
1472 }
1473 result += 2;
1474 }
1475 return result;
1476 }
1477 /* $Header$ */
1478
1479 /* End of tkcanvutil.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25