4 * This procedure contains a collection of utility procedures
5 * used by the implementations of various canvas item types.
7 * Copyright (c) 1994 Sun Microsystems, Inc.
8 * Copyright (c) 1994 Sun Microsystems, Inc.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
22 *----------------------------------------------------------------------
26 * Given a token for a canvas, this procedure returns the
27 * widget that represents the canvas.
30 * The return value is a handle for the widget.
35 *----------------------------------------------------------------------
39 Tk_CanvasTkwin(canvas)
40 Tk_Canvas canvas; /* Token for the canvas. */
42 TkCanvas *canvasPtr = (TkCanvas *) canvas;
43 return canvasPtr->tkwin;
47 *----------------------------------------------------------------------
49 * Tk_CanvasDrawableCoords --
51 * Given an (x,y) coordinate pair within a canvas, this procedure
52 * returns the corresponding coordinates at which the point should
53 * be drawn in the drawable used for display.
56 * There is no return value. The values at *drawableXPtr and
57 * *drawableYPtr are filled in with the coordinates at which
58 * x and y should be drawn. These coordinates are clipped
59 * to fit within a "short", since this is what X uses in
60 * most cases for drawing.
65 *----------------------------------------------------------------------
69 Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr)
70 Tk_Canvas canvas; /* Token for the canvas. */
71 double x, y; /* Coordinates in canvas space. */
72 short *drawableXPtr, *drawableYPtr; /* Screen coordinates are stored
75 TkCanvas *canvasPtr = (TkCanvas *) canvas;
78 tmp = x - canvasPtr->drawableXOrigin;
85 *drawableXPtr = 32767;
86 } else if (tmp < -32768) {
87 *drawableXPtr = -32768;
89 *drawableXPtr = (short) tmp;
92 tmp = y - canvasPtr->drawableYOrigin;
99 *drawableYPtr = 32767;
100 } else if (tmp < -32768) {
101 *drawableYPtr = -32768;
103 *drawableYPtr = (short) tmp;
108 *----------------------------------------------------------------------
110 * Tk_CanvasWindowCoords --
112 * Given an (x,y) coordinate pair within a canvas, this procedure
113 * returns the corresponding coordinates in the canvas's window.
116 * There is no return value. The values at *screenXPtr and
117 * *screenYPtr are filled in with the coordinates at which
118 * (x,y) appears in the canvas's window. These coordinates
119 * are clipped to fit within a "short", since this is what X
120 * uses in most cases for drawing.
125 *----------------------------------------------------------------------
129 Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr)
130 Tk_Canvas canvas; /* Token for the canvas. */
131 double x, y; /* Coordinates in canvas space. */
132 short *screenXPtr, *screenYPtr; /* Screen coordinates are stored
135 TkCanvas *canvasPtr = (TkCanvas *) canvas;
138 tmp = x - canvasPtr->xOrigin;
146 } else if (tmp < -32768) {
147 *screenXPtr = -32768;
149 *screenXPtr = (short) tmp;
152 tmp = y - canvasPtr->yOrigin;
160 } else if (tmp < -32768) {
161 *screenYPtr = -32768;
163 *screenYPtr = (short) tmp;
168 *--------------------------------------------------------------
170 * Tk_CanvasGetCoord --
172 * Given a string, returns a floating-point canvas coordinate
173 * corresponding to that string.
176 * The return value is a standard Tcl return result. If
177 * TCL_OK is returned, then everything went well and the
178 * canvas coordinate is stored at *doublePtr; otherwise
179 * TCL_ERROR is returned and an error message is left in
180 * the interp's result.
185 *--------------------------------------------------------------
189 Tk_CanvasGetCoord(interp, canvas, string, doublePtr)
190 Tcl_Interp *interp; /* Interpreter for error reporting. */
191 Tk_Canvas canvas; /* Canvas to which coordinate applies. */
192 CONST char *string; /* Describes coordinate (any screen
193 * coordinate form may be used here). */
194 double *doublePtr; /* Place to store converted coordinate. */
196 TkCanvas *canvasPtr = (TkCanvas *) canvas;
197 if (Tk_GetScreenMM(canvasPtr->interp, canvasPtr->tkwin, string,
198 doublePtr) != TCL_OK) {
201 *doublePtr *= canvasPtr->pixelsPerMM;
206 *--------------------------------------------------------------
208 * Tk_CanvasGetCoordFromObj --
210 * Given a string, returns a floating-point canvas coordinate
211 * corresponding to that string.
214 * The return value is a standard Tcl return result. If
215 * TCL_OK is returned, then everything went well and the
216 * canvas coordinate is stored at *doublePtr; otherwise
217 * TCL_ERROR is returned and an error message is left in
223 *--------------------------------------------------------------
227 Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr)
228 Tcl_Interp *interp; /* Interpreter for error reporting. */
229 Tk_Canvas canvas; /* Canvas to which coordinate applies. */
230 Tcl_Obj *obj; /* Describes coordinate (any screen
231 * coordinate form may be used here). */
232 double *doublePtr; /* Place to store converted coordinate. */
234 TkCanvas *canvasPtr = (TkCanvas *) canvas;
235 if (Tk_GetMMFromObj(canvasPtr->interp, canvasPtr->tkwin, obj,
236 doublePtr) != TCL_OK) {
239 *doublePtr *= canvasPtr->pixelsPerMM;
244 *----------------------------------------------------------------------
246 * Tk_CanvasSetStippleOrigin --
248 * This procedure sets the stipple origin in a graphics context
249 * so that stipples drawn with the GC will line up with other
250 * stipples previously drawn in the canvas.
256 * The graphics context is modified.
258 *----------------------------------------------------------------------
262 Tk_CanvasSetStippleOrigin(canvas, gc)
263 Tk_Canvas canvas; /* Token for a canvas. */
264 GC gc; /* Graphics context that is about to be
265 * used to draw a stippled pattern as
266 * part of redisplaying the canvas. */
269 TkCanvas *canvasPtr = (TkCanvas *) canvas;
271 XSetTSOrigin(canvasPtr->display, gc, -canvasPtr->drawableXOrigin,
272 -canvasPtr->drawableYOrigin);
276 *----------------------------------------------------------------------
278 * Tk_CanvasSetOffset--
280 * This procedure sets the stipple offset in a graphics
281 * context so that stipples drawn with the GC will
282 * line up with other stipples with the same offset.
288 * The graphics context is modified.
290 *----------------------------------------------------------------------
294 Tk_CanvasSetOffset(canvas, gc, offset)
295 Tk_Canvas canvas; /* Token for a canvas. */
296 GC gc; /* Graphics context that is about to be
297 * used to draw a stippled pattern as
298 * part of redisplaying the canvas. */
299 Tk_TSOffset *offset; /* offset (may be NULL pointer)*/
301 TkCanvas *canvasPtr = (TkCanvas *) canvas;
303 int x = - canvasPtr->drawableXOrigin;
304 int y = - canvasPtr->drawableYOrigin;
306 if (offset != NULL) {
307 flags = offset->flags;
308 x += offset->xoffset;
309 y += offset->yoffset;
311 if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {
312 Tk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,
313 y - canvasPtr->yOrigin);
315 XSetTSOrigin(canvasPtr->display, gc, x, y);
320 *----------------------------------------------------------------------
322 * Tk_CanvasGetTextInfo --
324 * This procedure returns a pointer to a structure containing
325 * information about the selection and insertion cursor for
326 * a canvas widget. Items such as text items save the pointer
327 * and use it to share access to the information with the generic
331 * The return value is a pointer to the structure holding text
332 * information for the canvas. Most of the fields should not
333 * be modified outside the generic canvas code; see the user
334 * documentation for details.
339 *----------------------------------------------------------------------
343 Tk_CanvasGetTextInfo(canvas)
344 Tk_Canvas canvas; /* Token for the canvas widget. */
346 return &((TkCanvas *) canvas)->textInfo;
350 *--------------------------------------------------------------
352 * Tk_CanvasTagsParseProc --
354 * This procedure is invoked during option processing to handle
355 * "-tags" options for canvas items.
358 * A standard Tcl return value.
361 * The tags for a given item get replaced by those indicated
362 * in the value argument.
364 *--------------------------------------------------------------
368 Tk_CanvasTagsParseProc(clientData, interp, tkwin, value, widgRec, offset)
369 ClientData clientData; /* Not used.*/
370 Tcl_Interp *interp; /* Used for reporting errors. */
371 Tk_Window tkwin; /* Window containing canvas widget. */
372 CONST char *value; /* Value of option (list of tag
374 char *widgRec; /* Pointer to record for item. */
375 int offset; /* Offset into item (ignored). */
377 register Tk_Item *itemPtr = (Tk_Item *) widgRec;
383 * Break the value up into the individual tag names.
386 if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
391 * Make sure that there's enough space in the item to hold the
395 if (itemPtr->tagSpace < argc) {
396 newPtr = (Tk_Uid *) ckalloc((unsigned) (argc * sizeof(Tk_Uid)));
397 for (i = itemPtr->numTags-1; i >= 0; i--) {
398 newPtr[i] = itemPtr->tagPtr[i];
400 if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
401 ckfree((char *) itemPtr->tagPtr);
403 itemPtr->tagPtr = newPtr;
404 itemPtr->tagSpace = argc;
406 itemPtr->numTags = argc;
407 for (i = 0; i < argc; i++) {
408 itemPtr->tagPtr[i] = Tk_GetUid(argv[i]);
410 ckfree((char *) argv);
415 *--------------------------------------------------------------
417 * Tk_CanvasTagsPrintProc --
419 * This procedure is invoked by the Tk configuration code
420 * to produce a printable string for the "-tags" configuration
421 * option for canvas items.
424 * The return value is a string describing all the tags for
425 * the item referred to by "widgRec". In addition, *freeProcPtr
426 * is filled in with the address of a procedure to call to free
427 * the result string when it's no longer needed (or NULL to
428 * indicate that the string doesn't need to be freed).
433 *--------------------------------------------------------------
437 Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
438 ClientData clientData; /* Ignored. */
439 Tk_Window tkwin; /* Window containing canvas widget. */
440 char *widgRec; /* Pointer to record for item. */
441 int offset; /* Ignored. */
442 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
443 * information about how to reclaim
444 * storage for return string. */
446 register Tk_Item *itemPtr = (Tk_Item *) widgRec;
448 if (itemPtr->numTags == 0) {
449 *freeProcPtr = (Tcl_FreeProc *) NULL;
452 if (itemPtr->numTags == 1) {
453 *freeProcPtr = (Tcl_FreeProc *) NULL;
454 return (char *) itemPtr->tagPtr[0];
456 *freeProcPtr = TCL_DYNAMIC;
457 return Tcl_Merge(itemPtr->numTags, (CONST char **) itemPtr->tagPtr);
461 static int DashConvert _ANSI_ARGS_((char *l, CONST char *p,
462 int n, double width));
463 #define ABS(a) ((a>=0)?(a):(-(a)))
466 *--------------------------------------------------------------
468 * TkCanvasDashParseProc --
470 * This procedure is invoked during option processing to handle
471 * "-dash", "-activedash" and "-disableddash" options for canvas
475 * A standard Tcl return value.
478 * The dash list for a given canvas object gets replaced by
479 * those indicated in the value argument.
481 *--------------------------------------------------------------
485 TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset)
486 ClientData clientData; /* Not used.*/
487 Tcl_Interp *interp; /* Used for reporting errors. */
488 Tk_Window tkwin; /* Window containing canvas widget. */
489 CONST char *value; /* Value of option. */
490 char *widgRec; /* Pointer to record for item. */
491 int offset; /* Offset into item. */
493 return Tk_GetDash(interp, value, (Tk_Dash *)(widgRec+offset));
497 *--------------------------------------------------------------
499 * TkCanvasDashPrintProc --
501 * This procedure is invoked by the Tk configuration code
502 * to produce a printable string for the "-dash", "-activedash"
503 * and "-disableddash" configuration options for canvas items.
506 * The return value is a string describing all the dash list for
507 * the item referred to by "widgRec"and "offset". In addition,
508 * *freeProcPtr is filled in with the address of a procedure to
509 * call to free the result string when it's no longer needed (or
510 * NULL to indicate that the string doesn't need to be freed).
515 *--------------------------------------------------------------
519 TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
520 ClientData clientData; /* Ignored. */
521 Tk_Window tkwin; /* Window containing canvas widget. */
522 char *widgRec; /* Pointer to record for item. */
523 int offset; /* Offset in record for item. */
524 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
525 * information about how to reclaim
526 * storage for return string. */
528 Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
531 int i = dash->number;
535 *freeProcPtr = TCL_DYNAMIC;
536 buffer = (char *) ckalloc((unsigned int) (i+1));
537 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
538 memcpy(buffer, p, (unsigned int) i);
542 *freeProcPtr = (Tcl_FreeProc *) NULL;
545 buffer = (char *)ckalloc((unsigned int) (4*i));
546 *freeProcPtr = TCL_DYNAMIC;
548 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
549 sprintf(buffer, "%d", *p++ & 0xff);
551 sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
557 *--------------------------------------------------------------
559 * Tk_CreateSmoothMethod --
561 * This procedure is invoked to add additional values
562 * for the "-smooth" option to the list.
565 * A standard Tcl return value.
568 * In the future "-smooth <name>" will be accepted as
569 * smooth method for the line and polygon.
571 *--------------------------------------------------------------
574 Tk_SmoothMethod tkBezierSmoothMethod = {
577 (void (*) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas,
578 double *coordPtr, int numPoints, int numSteps)))
579 TkMakeBezierPostscript,
582 static void SmoothMethodCleanupProc _ANSI_ARGS_((ClientData clientData,
583 Tcl_Interp *interp));
585 typedef struct SmoothAssocData {
586 struct SmoothAssocData *nextPtr; /* pointer to next SmoothAssocData */
587 Tk_SmoothMethod smooth; /* name and functions associated with this
592 Tk_CreateSmoothMethod(interp, smooth)
594 Tk_SmoothMethod *smooth;
596 SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
597 methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
598 (Tcl_InterpDeleteProc **) NULL);
601 * If there's already a smooth method with the given name, remove it.
604 for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;
605 prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
606 if (!strcmp(typePtr2->smooth.name, smooth->name)) {
607 if (prevPtr == NULL) {
608 methods = typePtr2->nextPtr;
610 prevPtr->nextPtr = typePtr2->nextPtr;
612 ckfree((char *) typePtr2);
616 ptr = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData));
617 ptr->smooth.name = smooth->name;
618 ptr->smooth.coordProc = smooth->coordProc;
619 ptr->smooth.postscriptProc = smooth->postscriptProc;
620 ptr->nextPtr = methods;
621 Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,
625 *----------------------------------------------------------------------
627 * SmoothMethodCleanupProc --
629 * This procedure is invoked whenever an interpreter is deleted
630 * to cleanup the smooth methods.
636 * Smooth methods are removed.
638 *----------------------------------------------------------------------
642 SmoothMethodCleanupProc(clientData, interp)
643 ClientData clientData; /* Points to "smoothMethod" AssocData
644 * for the interpreter. */
645 Tcl_Interp *interp; /* Interpreter that is being deleted. */
647 SmoothAssocData *ptr, *methods = (SmoothAssocData *) clientData;
649 while (methods != NULL) {
650 methods = (ptr = methods)->nextPtr;
651 ckfree((char *) ptr);
655 *--------------------------------------------------------------
657 * TkSmoothParseProc --
659 * This procedure is invoked during option processing to handle
660 * the "-smooth" option.
663 * A standard Tcl return value.
666 * The smooth option for a given item gets replaced by the value
667 * indicated in the value argument.
669 *--------------------------------------------------------------
673 TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset)
674 ClientData clientData; /* some flags.*/
675 Tcl_Interp *interp; /* Used for reporting errors. */
676 Tk_Window tkwin; /* Window containing canvas widget. */
677 CONST char *value; /* Value of option. */
678 char *widgRec; /* Pointer to record for item. */
679 int offset; /* Offset into item. */
681 register Tk_SmoothMethod **smoothPtr =
682 (Tk_SmoothMethod **) (widgRec + offset);
683 Tk_SmoothMethod *smooth = NULL;
686 SmoothAssocData *methods;
688 if (value == NULL || *value == 0) {
689 *smoothPtr = (Tk_SmoothMethod *) NULL;
692 length = strlen(value);
693 methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
694 (Tcl_InterpDeleteProc **) NULL);
695 while (methods != (SmoothAssocData *) NULL) {
696 if (strncmp(value, methods->smooth.name, length) == 0) {
697 if (smooth != (Tk_SmoothMethod *) NULL) {
698 Tcl_AppendResult(interp, "ambigeous smooth method \"", value,
699 "\"", (char *) NULL);
702 smooth = &methods->smooth;
704 methods = methods->nextPtr;
709 } else if (strncmp(value, tkBezierSmoothMethod.name, length) == 0) {
711 * We need to do handle the built-in bezier method.
713 *smoothPtr = &tkBezierSmoothMethod;
718 if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
721 *smoothPtr = b ? &tkBezierSmoothMethod : (Tk_SmoothMethod*) NULL;
725 *--------------------------------------------------------------
727 * TkSmoothPrintProc --
729 * This procedure is invoked by the Tk configuration code
730 * to produce a printable string for the "-smooth"
731 * configuration option.
734 * The return value is a string describing the smooth option for
735 * the item referred to by "widgRec". In addition, *freeProcPtr
736 * is filled in with the address of a procedure to call to free
737 * the result string when it's no longer needed (or NULL to
738 * indicate that the string doesn't need to be freed).
743 *--------------------------------------------------------------
747 TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
748 ClientData clientData; /* Ignored. */
749 Tk_Window tkwin; /* Window containing canvas widget. */
750 char *widgRec; /* Pointer to record for item. */
751 int offset; /* Offset into item. */
752 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
753 * information about how to reclaim
754 * storage for return string. */
756 register Tk_SmoothMethod **smoothPtr = (Tk_SmoothMethod **) (widgRec + offset);
758 return (*smoothPtr) ? (*smoothPtr)->name : "0";
761 *--------------------------------------------------------------
765 * This procedure is used to parse a string, assuming
766 * it is dash information.
769 * The return value is a standard Tcl result: TCL_OK means
770 * that the dash information was parsed ok, and
771 * TCL_ERROR means it couldn't be parsed.
774 * Dash information in the dash structure is updated.
776 *--------------------------------------------------------------
780 Tk_GetDash(interp, value, dash)
781 Tcl_Interp *interp; /* Used for error reporting. */
782 CONST char *value; /* Textual specification of dash list. */
783 Tk_Dash *dash; /* Pointer to record in which to
784 * store dash information. */
787 CONST char **largv, **argv = NULL;
790 if ((value==(char *) NULL) || (*value==0) ) {
794 if ((*value == '.') || (*value == ',') ||
795 (*value == '-') || (*value == '_')) {
796 i = DashConvert((char *) NULL, value, -1, 0.0);
802 if (i > sizeof(char *)) {
803 dash->pattern.pt = pt = (char *) ckalloc(strlen(value));
805 pt = dash->pattern.array;
807 memcpy(pt,value, (unsigned int) i);
811 if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
812 Tcl_ResetResult(interp);
814 Tcl_AppendResult(interp, "bad dash list \"", value,
815 "\": must be a list of integers or a format like \"-..\"",
819 ckfree((char *) argv);
821 if (ABS(dash->number) > sizeof(char *))
822 ckfree((char *) dash->pattern.pt);
827 if (ABS(dash->number) > sizeof(char *)) {
828 ckfree((char *) dash->pattern.pt);
830 if (argc > sizeof(char *)) {
831 dash->pattern.pt = pt = (char *) ckalloc((unsigned int) argc);
833 pt = dash->pattern.array;
839 if (Tcl_GetInt(interp, *largv, &i) != TCL_OK ||
841 Tcl_ResetResult(interp);
842 Tcl_AppendResult(interp, "expected integer in the range 1..255 but got \"",
843 *largv, "\"", (char *) NULL);
851 ckfree((char *) argv);
858 *--------------------------------------------------------------
862 * This procedure initializes the Tk_Outline structure
863 * with default values.
871 *--------------------------------------------------------------
874 void Tk_CreateOutline(outline)
878 outline->width = 1.0;
879 outline->activeWidth = 0.0;
880 outline->disabledWidth = 0.0;
882 outline->dash.number = 0;
883 outline->activeDash.number = 0;
884 outline->disabledDash.number = 0;
885 outline->tsoffset.flags = 0;
886 outline->tsoffset.xoffset = 0;
887 outline->tsoffset.yoffset = 0;
888 outline->color = NULL;
889 outline->activeColor = NULL;
890 outline->disabledColor = NULL;
891 outline->stipple = None;
892 outline->activeStipple = None;
893 outline->disabledStipple = None;
897 *--------------------------------------------------------------
901 * This procedure frees all memory that might be
902 * allocated and referenced in the Tk_Outline structure.
910 *--------------------------------------------------------------
913 void Tk_DeleteOutline(display, outline)
914 Display *display; /* Display containing window */
917 if (outline->gc != None) {
918 Tk_FreeGC(display, outline->gc);
920 if (ABS(outline->dash.number) > sizeof(char *)) {
921 ckfree((char *) outline->dash.pattern.pt);
923 if (ABS(outline->activeDash.number) > sizeof(char *)) {
924 ckfree((char *) outline->activeDash.pattern.pt);
926 if (ABS(outline->disabledDash.number) > sizeof(char *)) {
927 ckfree((char *) outline->disabledDash.pattern.pt);
929 if (outline->color != NULL) {
930 Tk_FreeColor(outline->color);
932 if (outline->activeColor != NULL) {
933 Tk_FreeColor(outline->activeColor);
935 if (outline->disabledColor != NULL) {
936 Tk_FreeColor(outline->disabledColor);
938 if (outline->stipple != None) {
939 Tk_FreeBitmap(display, outline->stipple);
941 if (outline->activeStipple != None) {
942 Tk_FreeBitmap(display, outline->activeStipple);
944 if (outline->disabledStipple != None) {
945 Tk_FreeBitmap(display, outline->disabledStipple);
950 *--------------------------------------------------------------
954 * This procedure should be called in the canvas object
955 * during the configure command. The graphics context
956 * description in gcValues is updated according to the
957 * information in the dash structure, as far as possible.
960 * The return-value is a mask, indicating which
961 * elements of gcValues have been updated.
962 * 0 means there is no outline.
965 * GC information in gcValues is updated.
967 *--------------------------------------------------------------
970 int Tk_ConfigOutlineGC(gcValues, canvas, item, outline)
981 Tk_State state = item->state;
983 if (outline->width < 0.0) {
984 outline->width = 0.0;
986 if (outline->activeWidth < 0.0) {
987 outline->activeWidth = 0.0;
989 if (outline->disabledWidth < 0) {
990 outline->disabledWidth = 0.0;
992 if (state==TK_STATE_HIDDEN) {
996 width = outline->width;
1000 dash = &(outline->dash);
1001 color = outline->color;
1002 stipple = outline->stipple;
1003 if (state == TK_STATE_NULL) {
1004 state = ((TkCanvas *)canvas)->canvas_state;
1006 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1007 if (outline->activeWidth>width) {
1008 width = outline->activeWidth;
1010 if (outline->activeDash.number != 0) {
1011 dash = &(outline->activeDash);
1013 if (outline->activeColor!=NULL) {
1014 color = outline->activeColor;
1016 if (outline->activeStipple!=None) {
1017 stipple = outline->activeStipple;
1019 } else if (state==TK_STATE_DISABLED) {
1020 if (outline->disabledWidth>0) {
1021 width = outline->disabledWidth;
1023 if (outline->disabledDash.number != 0) {
1024 dash = &(outline->disabledDash);
1026 if (outline->disabledColor!=NULL) {
1027 color = outline->disabledColor;
1029 if (outline->disabledStipple!=None) {
1030 stipple = outline->disabledStipple;
1038 gcValues->line_width = (int) (width + 0.5);
1039 if (color != NULL) {
1040 gcValues->foreground = color->pixel;
1041 mask = GCForeground|GCLineWidth;
1042 if (stipple != None) {
1043 gcValues->stipple = stipple;
1044 gcValues->fill_style = FillStippled;
1045 mask |= GCStipple|GCFillStyle;
1048 if (mask && (dash->number != 0)) {
1049 gcValues->line_style = LineOnOffDash;
1050 gcValues->dash_offset = outline->offset;
1051 if (dash->number >= 2) {
1052 gcValues->dashes = 4;
1053 } else if (dash->number > 0) {
1054 gcValues->dashes = dash->pattern.array[0];
1056 gcValues->dashes = (char) (4 * width);
1058 mask |= GCLineStyle|GCDashList|GCDashOffset;
1064 *--------------------------------------------------------------
1066 * Tk_ChangeOutlineGC
1068 * Updates the GC to represent the full information of
1069 * the dash structure. Partly this is already done in
1070 * Tk_ConfigOutlineGC().
1071 * This function should be called just before drawing
1075 * 1 if there is a stipple pattern.
1081 *--------------------------------------------------------------
1085 Tk_ChangeOutlineGC(canvas, item, outline)
1088 Tk_Outline *outline;
1095 Tk_State state = item->state;
1097 width = outline->width;
1101 dash = &(outline->dash);
1102 color = outline->color;
1103 stipple = outline->stipple;
1104 if (state == TK_STATE_NULL) {
1105 state = ((TkCanvas *)canvas)->canvas_state;
1107 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1108 if (outline->activeWidth > width) {
1109 width = outline->activeWidth;
1111 if (outline->activeDash.number != 0) {
1112 dash = &(outline->activeDash);
1114 if (outline->activeColor != NULL) {
1115 color = outline->activeColor;
1117 if (outline->activeStipple != None) {
1118 stipple = outline->activeStipple;
1120 } else if (state == TK_STATE_DISABLED) {
1121 if (outline->disabledWidth > width) {
1122 width = outline->disabledWidth;
1124 if (outline->disabledDash.number != 0) {
1125 dash = &(outline->disabledDash);
1127 if (outline->disabledColor != NULL) {
1128 color = outline->disabledColor;
1130 if (outline->disabledStipple != None) {
1131 stipple = outline->disabledStipple;
1138 if ((dash->number<-1) || ((dash->number == -1) && (dash->pattern.array[1]!=','))) {
1140 int i = -dash->number;
1142 p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
1143 q = (char *) ckalloc(2*(unsigned int)i);
1144 i = DashConvert(q, p, i, width);
1145 XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, q, i);
1147 } else if ( dash->number>2 || (dash->number==2 &&
1148 (dash->pattern.array[0]!=dash->pattern.array[1]))) {
1149 p = (char *) (dash->number > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
1150 XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, p, dash->number);
1152 if (stipple!=None) {
1154 Tk_TSOffset *tsoffset = &outline->tsoffset;
1155 int flags = tsoffset->flags;
1156 if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
1157 Tk_SizeOfBitmap(((TkCanvas *)canvas)->display, stipple, &w, &h);
1158 if (flags & TK_OFFSET_CENTER) {
1163 if (flags & TK_OFFSET_MIDDLE) {
1169 tsoffset->xoffset -= w;
1170 tsoffset->yoffset -= h;
1171 Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
1172 tsoffset->xoffset += w;
1173 tsoffset->yoffset += h;
1181 *--------------------------------------------------------------
1185 * Restores the GC to the situation before
1186 * Tk_ChangeDashGC() was called.
1187 * This function should be called just after the dashed
1188 * item is drawn, because the GC is supposed to be
1192 * 1 if there is a stipple pattern.
1198 *--------------------------------------------------------------
1201 Tk_ResetOutlineGC(canvas, item, outline)
1204 Tk_Outline *outline;
1211 Tk_State state = item->state;
1213 width = outline->width;
1217 dash = &(outline->dash);
1218 color = outline->color;
1219 stipple = outline->stipple;
1220 if (state == TK_STATE_NULL) {
1221 state = ((TkCanvas *)canvas)->canvas_state;
1223 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1224 if (outline->activeWidth>width) {
1225 width = outline->activeWidth;
1227 if (outline->activeDash.number != 0) {
1228 dash = &(outline->activeDash);
1230 if (outline->activeColor!=NULL) {
1231 color = outline->activeColor;
1233 if (outline->activeStipple!=None) {
1234 stipple = outline->activeStipple;
1236 } else if (state==TK_STATE_DISABLED) {
1237 if (outline->disabledWidth>width) {
1238 width = outline->disabledWidth;
1240 if (outline->disabledDash.number != 0) {
1241 dash = &(outline->disabledDash);
1243 if (outline->disabledColor!=NULL) {
1244 color = outline->disabledColor;
1246 if (outline->disabledStipple!=None) {
1247 stipple = outline->disabledStipple;
1254 if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&
1255 (dash->pattern.array[0] != dash->pattern.array[1])) ||
1256 ((dash->number == -1) && (dash->pattern.array[1] != ','))) {
1257 if (dash->number < 0) {
1258 dashList = (int) (4 * width + 0.5);
1259 } else if (dash->number<3) {
1260 dashList = dash->pattern.array[0];
1264 XSetDashes(((TkCanvas *)canvas)->display, outline->gc,
1265 outline->offset, &dashList , 1);
1267 if (stipple != None) {
1268 XSetTSOrigin(((TkCanvas *)canvas)->display, outline->gc, 0, 0);
1276 *--------------------------------------------------------------
1278 * Tk_CanvasPsOutline
1280 * Creates the postscript command for the correct
1281 * Outline-information (width, dash, color and stipple).
1284 * TCL_OK if succeeded, otherwise TCL_ERROR.
1287 * canvas->interp->result contains the postscript string,
1288 * or an error message if the result was TCL_ERROR.
1290 *--------------------------------------------------------------
1293 Tk_CanvasPsOutline(canvas, item, outline)
1296 Tk_Outline *outline;
1303 char *lptr = pattern;
1304 Tcl_Interp *interp = ((TkCanvas *)canvas)->interp;
1309 Tk_State state = item->state;
1311 width = outline->width;
1312 dash = &(outline->dash);
1313 color = outline->color;
1314 stipple = outline->stipple;
1315 if (state == TK_STATE_NULL) {
1316 state = ((TkCanvas *)canvas)->canvas_state;
1318 if (((TkCanvas *)canvas)->currentItemPtr == item) {
1319 if (outline->activeWidth > width) {
1320 width = outline->activeWidth;
1322 if (outline->activeDash.number > 0) {
1323 dash = &(outline->activeDash);
1325 if (outline->activeColor != NULL) {
1326 color = outline->activeColor;
1328 if (outline->activeStipple != None) {
1329 stipple = outline->activeStipple;
1331 } else if (state == TK_STATE_DISABLED) {
1332 if (outline->disabledWidth > 0) {
1333 width = outline->disabledWidth;
1335 if (outline->disabledDash.number > 0) {
1336 dash = &(outline->disabledDash);
1338 if (outline->disabledColor != NULL) {
1339 color = outline->disabledColor;
1341 if (outline->disabledStipple != None) {
1342 stipple = outline->disabledStipple;
1345 sprintf(string, "%.15g setlinewidth\n", width);
1346 Tcl_AppendResult(interp, string, (char *) NULL);
1348 if (dash->number > 10) {
1349 str = (char *)ckalloc((unsigned int) (1 + 4*dash->number));
1350 } else if (dash->number < -5) {
1351 str = (char *)ckalloc((unsigned int) (1 - 8*dash->number));
1352 lptr = (char *)ckalloc((unsigned int) (1 - 2*dash->number));
1354 ptr = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
1355 dash->pattern.pt : dash->pattern.array;
1356 if (dash->number > 0) {
1358 sprintf(str, "[%d", *ptr++ & 0xff);
1361 sprintf(str+strlen(str), " %d", *ptr++ & 0xff);
1363 Tcl_AppendResult(interp, str, (char *)NULL);
1364 if (dash->number&1) {
1365 Tcl_AppendResult(interp, " ", str+1, (char *)NULL);
1367 sprintf(str, "] %d setdash\n", outline->offset);
1368 Tcl_AppendResult(interp, str, (char *)NULL);
1370 } else if (dash->number < 0) {
1371 if ((i = DashConvert(lptr, ptr, -dash->number, width)) != 0) {
1373 sprintf(str, "[%d", *lptr++ & 0xff);
1375 sprintf(str+strlen(str), " %d", *lptr++ & 0xff);
1377 Tcl_AppendResult(interp, str, (char *)NULL);
1378 sprintf(str, "] %d setdash\n", outline->offset);
1379 Tcl_AppendResult(interp, str, (char *)NULL);
1382 Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
1385 Tcl_AppendResult(interp, "[] 0 setdash\n", (char *)NULL);
1387 if (str != string) {
1390 if (lptr != pattern) {
1393 if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
1396 if (stipple != None) {
1397 Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
1398 if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
1402 Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
1410 *--------------------------------------------------------------
1414 * Converts a character-like dash-list (e.g. "-..")
1415 * into an X11-style. l must point to a string that
1416 * holds room to at least 2*n characters. if
1417 * l == NULL, this function can be used for
1418 * syntax checking only.
1421 * The length of the resulting X11 compatible
1422 * dash-list. -1 if failed.
1427 *--------------------------------------------------------------
1431 DashConvert (l, p, n, width)
1443 intWidth = (int) (width + 0.5);
1452 l[-1] += intWidth + 1;
1475 *l++ = size * intWidth;
1476 *l++ = 4 * intWidth;