summaryrefslogtreecommitdiffstats
path: root/generic/tkCanvUtil.c
diff options
context:
space:
mode:
authorhobbs <hobbs>1999-12-14 06:52:24 (GMT)
committerhobbs <hobbs>1999-12-14 06:52:24 (GMT)
commitb6b6ff8f0eee42e270a45b019789faa444ed4dad (patch)
tree5b5ddecf0f3677601c5511eaded466191ef3ba8a /generic/tkCanvUtil.c
parent9b37fa05b11850066aed28ed447109e55708bce0 (diff)
downloadtk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.zip
tk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.tar.gz
tk-b6b6ff8f0eee42e270a45b019789faa444ed4dad.tar.bz2
* generic/tkStubInit.c:
* generic/tkDecls.h: * generic/tkIntXlibDecls.h: * generic/tkInt.decls: added XSetDashes and XWarpPointer * generic/tk.decls: added Tk_CreateSmoothMethod, and reserved two spots * generic/tk.h: added Tk_SmoothMethod struct, state item to canvas record, #defines for item state, support for using old char*-based canvas item C creation procedures with -DUSE_OLD_CANVAS, Tk_Dash, Tk_TSOffset (-offsets) & Tk_Outline structs and #defs, decls for dash, outline and postscript routines * generic/tkBind.c: added support for Quadruple clicks, and added the -warp option to 'event' with pointer warping routines * xlib/xgc.c: * generic/tkRectOval.c: * generic/tkCanvArc.c: * generic/tkCanvBmap.c: * generic/tkCanvImg.c: * generic/tkCanvLine.c: * generic/tkCanvPoly.c: * generic/tkCanvPs.c: * generic/tkCanvText.c: * generic/tkCanvUtil.c: * generic/tkCanvWind.c: * generic/tkCanvas.c: * generic/tkCanvas.h: Canvas and items received overhaul to with the addition of the dash patch (Nijtmans, et al) This includes objectification of the 'canvas' command, as well as support for (where appropriate) dashes in items, extended stipple support, state for all items, and postscript generation of images and windows. See the new canvas man page for related docs. * generic/tkEntry.c: added entry widget validation, see entry.n * generic/tkEvent.c: on simulated events, ButtonPress should be matched with ButtonRelease to be correct * generic/tkFont.c: corrected possible null reference * generic/tkFrame.c: made frame a Tcl_Obj based command * generic/tkGet.c: added TkGetDoublePixels * generic/tkImage.c: bug fixes from Img patch and new Tk_PostscriptImage and Tk_SetTSOrigin functions * generic/tkImgBmap.c: new ImgBmapPostscript function * generic/tkImgPhoto.c: new Tk_CreatePhotoOption, Tk_DitherPhoto * generic/tkInt.h: declarations for some new functions * generic/tkMessage.c: reworked relief drawing * generic/tkOldConfig.c: added TK_CONFIG_OBJS so old style ConfigureWidget calls can pass in Tcl_Obj arrays * generic/tkScrollbar.c: * generic/tkScrollbar.h: made -orient use an option table * generic/tkText.c: * generic/tkText.h: made -wrap and -state use option tables * generic/tkTextBTree.c: * generic/tkTextDisp.c: * generic/tkTextImage.c: * generic/tkTextMark.c: * generic/tkTextTag.c: * generic/tkTextWind.c: added support for -elide and -state hidden * generic/tkTrig.c: changed TkMakeBezierCurve to support returning the upper limit of points needed for spline * generic/tkUtil.c: new option table parsing routines * generic/tkWindow.c: init'ing of warp stuff, mouseButtonState
Diffstat (limited to 'generic/tkCanvUtil.c')
-rw-r--r--generic/tkCanvUtil.c1099
1 files changed, 1097 insertions, 2 deletions
diff --git a/generic/tkCanvUtil.c b/generic/tkCanvUtil.c
index 7d203ec..3c79861 100644
--- a/generic/tkCanvUtil.c
+++ b/generic/tkCanvUtil.c
@@ -10,10 +10,10 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvUtil.c,v 1.3 1999/04/16 01:51:12 stanton Exp $
+ * RCS: @(#) $Id: tkCanvUtil.c,v 1.4 1999/12/14 06:52:26 hobbs Exp $
*/
-#include "tk.h"
+#include "tkInt.h"
#include "tkCanvas.h"
#include "tkPort.h"
@@ -201,6 +201,44 @@ Tk_CanvasGetCoord(interp, canvas, string, doublePtr)
*doublePtr *= canvasPtr->pixelsPerMM;
return TCL_OK;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasGetCoordFromObj --
+ *
+ * Given a string, returns a floating-point canvas coordinate
+ * corresponding to that string.
+ *
+ * Results:
+ * The return value is a standard Tcl return result. If
+ * TCL_OK is returned, then everything went well and the
+ * canvas coordinate is stored at *doublePtr; otherwise
+ * TCL_ERROR is returned and an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_CanvasGetCoordFromObj(interp, canvas, obj, doublePtr)
+ Tcl_Interp *interp; /* Interpreter for error reporting. */
+ Tk_Canvas canvas; /* Canvas to which coordinate applies. */
+ Tcl_Obj *obj; /* Describes coordinate (any screen
+ * coordinate form may be used here). */
+ double *doublePtr; /* Place to store converted coordinate. */
+{
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ if (Tk_GetMMFromObj(canvasPtr->interp, canvasPtr->tkwin, obj,
+ doublePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *doublePtr *= canvasPtr->pixelsPerMM;
+ return TCL_OK;
+}
/*
*----------------------------------------------------------------------
@@ -237,6 +275,50 @@ Tk_CanvasSetStippleOrigin(canvas, gc)
/*
*----------------------------------------------------------------------
*
+ * Tk_CanvasSetOffset--
+ *
+ * This procedure sets the stipple offset in a graphics
+ * context so that stipples drawn with the GC will
+ * line up with other stipples with the same offset.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The graphics context is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Tk_CanvasSetOffset(canvas, gc, offset)
+ Tk_Canvas canvas; /* Token for a canvas. */
+ GC gc; /* Graphics context that is about to be
+ * used to draw a stippled pattern as
+ * part of redisplaying the canvas. */
+ Tk_TSOffset *offset; /* offset (may be NULL pointer)*/
+{
+ TkCanvas *canvasPtr = (TkCanvas *) canvas;
+ int flags = 0;
+ int x = - canvasPtr->drawableXOrigin;
+ int y = - canvasPtr->drawableYOrigin;
+
+ if (offset != NULL) {
+ flags = offset->flags;
+ x += offset->xoffset;
+ y += offset->yoffset;
+ }
+ if ((flags & TK_OFFSET_RELATIVE) && !(flags & TK_OFFSET_INDEX)) {
+ Tk_SetTSOrigin(canvasPtr->tkwin, gc, x - canvasPtr->xOrigin,
+ y - canvasPtr->yOrigin);
+ } else {
+ XSetTSOrigin(canvasPtr->display, gc, x, y);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_CanvasGetTextInfo --
*
* This procedure returns a pointer to a structure containing
@@ -374,3 +456,1016 @@ Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
*freeProcPtr = TCL_DYNAMIC;
return Tcl_Merge(itemPtr->numTags, (char **) itemPtr->tagPtr);
}
+
+
+static int DashConvert _ANSI_ARGS_((char *l, CONST char *p,
+ int n, double width));
+#define ABS(a) ((a>=0)?(a):(-(a)))
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * "-dash", "-activedash" and "-disableddash" options for canvas
+ * objects.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The dash list for a given canvas object gets replaced by
+ * those indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkCanvasDashParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* Not used.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ return Tk_GetDash(interp, value, (Tk_Dash *)(widgRec+offset));
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * TkCanvasDashPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-dash", "-activedash"
+ * and "-disableddash" configuration options for canvas items.
+ *
+ * Results:
+ * The return value is a string describing all the dash list for
+ * the item referred to by "widgRec"and "offset". In addition,
+ * *freeProcPtr is filled in with the address of a procedure to
+ * call to free the result string when it's no longer needed (or
+ * NULL to indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkCanvasDashPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset in record for item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ Tk_Dash *dash = (Tk_Dash *) (widgRec+offset);
+ char *buffer;
+ char *p;
+ int i = dash->number;
+
+ if (i < 0) {
+ i = -i;
+ *freeProcPtr = TCL_DYNAMIC;
+ buffer = (char *) ckalloc((unsigned int) (i+1));
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ memcpy(buffer, p, (unsigned int) i);
+ buffer[i] = 0;
+ return buffer;
+ } else if (!i) {
+ *freeProcPtr = (Tcl_FreeProc *) NULL;
+ return "";
+ }
+ buffer = (char *)ckalloc((unsigned int) (4*i));
+ *freeProcPtr = TCL_DYNAMIC;
+
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ sprintf(buffer, "%d", *p++ & 0xff);
+ while(--i) {
+ sprintf(buffer+strlen(buffer), " %d", *p++ & 0xff);
+ }
+ return buffer;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateSmoothMethod --
+ *
+ * This procedure is invoked to add additional values
+ * for the "-smooth" option to the list.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * In the future "-smooth <name>" will be accepted as
+ * smooth method for the line and polygon.
+ *
+ *--------------------------------------------------------------
+ */
+
+Tk_SmoothMethod tkBezierSmoothMethod = {
+ "bezier",
+ TkMakeBezierCurve,
+ (void (*) _ANSI_ARGS_((Tcl_Interp *interp, Tk_Canvas canvas,
+ double *coordPtr, int numPoints, int numSteps)))
+ TkMakeBezierPostscript,
+};
+
+static void SmoothMethodCleanupProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp));
+
+typedef struct SmoothAssocData {
+ struct SmoothAssocData *nextPtr; /* pointer to next SmoothAssocData */
+ Tk_SmoothMethod smooth; /* name and functions associated with this
+ * option */
+} SmoothAssocData;
+
+void
+Tk_CreateSmoothMethod(interp, smooth)
+ Tcl_Interp *interp;
+ Tk_SmoothMethod *smooth;
+{
+ SmoothAssocData *methods, *typePtr2, *prevPtr, *ptr;
+ methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
+ (Tcl_InterpDeleteProc **) NULL);
+
+ /*
+ * If there's already a smooth method with the given name, remove it.
+ */
+
+ for (typePtr2 = methods, prevPtr = NULL; typePtr2 != NULL;
+ prevPtr = typePtr2, typePtr2 = typePtr2->nextPtr) {
+ if (!strcmp(typePtr2->smooth.name, smooth->name)) {
+ if (prevPtr == NULL) {
+ methods = typePtr2->nextPtr;
+ } else {
+ prevPtr->nextPtr = typePtr2->nextPtr;
+ }
+ ckfree((char *) typePtr2);
+ break;
+ }
+ }
+ ptr = (SmoothAssocData *) ckalloc(sizeof(SmoothAssocData));
+ ptr->smooth.name = smooth->name;
+ ptr->smooth.coordProc = smooth->coordProc;
+ ptr->smooth.postscriptProc = smooth->postscriptProc;
+ ptr->nextPtr = methods;
+ Tcl_SetAssocData(interp, "smoothMethod", SmoothMethodCleanupProc,
+ (ClientData) ptr);
+}
+/*
+ *----------------------------------------------------------------------
+ *
+ * SmoothMethodCleanupProc --
+ *
+ * This procedure is invoked whenever an interpreter is deleted
+ * to cleanup the smooth methods.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Smooth methods are removed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+SmoothMethodCleanupProc(clientData, interp)
+ ClientData clientData; /* Points to "smoothMethod" AssocData
+ * for the interpreter. */
+ Tcl_Interp *interp; /* Interpreter that is being deleted. */
+{
+ SmoothAssocData *ptr, *methods = (SmoothAssocData *) clientData;
+
+ while (methods != NULL) {
+ methods = (ptr = methods)->nextPtr;
+ ckfree((char *) ptr);
+ }
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-smooth" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The smooth option for a given item gets replaced by the value
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+TkSmoothParseProc(clientData, interp, tkwin, value, widgRec, offset)
+ ClientData clientData; /* some flags.*/
+ Tcl_Interp *interp; /* Used for reporting errors. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ CONST char *value; /* Value of option. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+{
+ register Tk_SmoothMethod **smoothPtr =
+ (Tk_SmoothMethod **) (widgRec + offset);
+ Tk_SmoothMethod *smooth = NULL;
+ int b;
+ size_t length;
+ SmoothAssocData *methods;
+
+ if(value == NULL || *value == 0) {
+ *smoothPtr = (Tk_SmoothMethod *) NULL;
+ return TCL_OK;
+ }
+ length = strlen(value);
+ methods = (SmoothAssocData *) Tcl_GetAssocData(interp, "smoothMethod",
+ (Tcl_InterpDeleteProc **) NULL);
+ while (methods != (SmoothAssocData *) NULL) {
+ if (strncmp(value, methods->smooth.name, length) == 0) {
+ if (smooth != (Tk_SmoothMethod *) NULL) {
+ Tcl_AppendResult(interp, "ambigeous smooth method \"", value,
+ "\"", (char *) NULL);
+ return TCL_ERROR;
+ }
+ smooth = &methods->smooth;
+ }
+ methods = methods->nextPtr;
+ }
+ if (smooth) {
+ *smoothPtr = smooth;
+ return TCL_OK;
+ }
+
+ if (Tcl_GetBoolean(interp, (char *) value, &b) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *smoothPtr = b ? &tkBezierSmoothMethod : (Tk_SmoothMethod*) NULL;
+ return TCL_OK;
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * TkSmoothPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-smooth"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the smooth option for
+ * the item referred to by "widgRec". In addition, *freeProcPtr
+ * is filled in with the address of a procedure to call to free
+ * the result string when it's no longer needed (or NULL to
+ * indicate that the string doesn't need to be freed).
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+char *
+TkSmoothPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
+ ClientData clientData; /* Ignored. */
+ Tk_Window tkwin; /* Window containing canvas widget. */
+ char *widgRec; /* Pointer to record for item. */
+ int offset; /* Offset into item. */
+ Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
+ * information about how to reclaim
+ * storage for return string. */
+{
+ register Tk_SmoothMethod **smoothPtr = (Tk_SmoothMethod **) (widgRec + offset);
+
+ return (*smoothPtr) ? (*smoothPtr)->name : "0";
+}
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_GetDash
+ *
+ * This procedure is used to parse a string, assuming
+ * it is dash information.
+ *
+ * Results:
+ * The return value is a standard Tcl result: TCL_OK means
+ * that the dash information was parsed ok, and
+ * TCL_ERROR means it couldn't be parsed.
+ *
+ * Side effects:
+ * Dash information in the dash structure is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_GetDash(interp, value, dash)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ CONST char *value; /* Textual specification of dash list. */
+ Tk_Dash *dash; /* Pointer to record in which to
+ * store dash information. */
+{
+ int argc, i;
+ char **largv, **argv = NULL;
+ char *pt;
+
+ if ((value==(char *) NULL) || (*value==0) ) {
+ dash->number = 0;
+ return TCL_OK;
+ }
+ if ((*value == '.') || (*value == ',') ||
+ (*value == '-') || (*value == '_')) {
+ i = DashConvert((char *) NULL, value, -1, 0.0);
+ if (i>0) {
+ i = strlen(value);
+ } else {
+ goto badDashList;
+ }
+ if (i > sizeof(char *)) {
+ dash->pattern.pt = pt = (char *) ckalloc(strlen(value));
+ } else {
+ pt = dash->pattern.array;
+ }
+ memcpy(pt,value, (unsigned int) i);
+ dash->number = -i;
+ return TCL_OK;
+ }
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ badDashList:
+ Tcl_AppendResult(interp, "bad dash list \"", value,
+ "\": must be a list of integers or a format like \"-..\"",
+ (char *) NULL);
+ syntaxError:
+ if (argv != NULL) {
+ ckfree((char *) argv);
+ }
+ if (ABS(dash->number) > sizeof(char *))
+ ckfree((char *) dash->pattern.pt);
+ dash->number = 0;
+ return TCL_ERROR;
+ }
+
+ if (ABS(dash->number) > sizeof(char *)) {
+ ckfree((char *) dash->pattern.pt);
+ }
+ if (argc > sizeof(char *)) {
+ dash->pattern.pt = pt = (char *) ckalloc((unsigned int) argc);
+ } else {
+ pt = dash->pattern.array;
+ }
+ dash->number = argc;
+
+ largv = argv;
+ while(argc>0) {
+ if (Tcl_GetInt(interp, *largv, &i) != TCL_OK ||
+ i < 1 || i>255) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "expected integer in the range 1..255 but got \"",
+ *largv, "\"", (char *) NULL);
+ goto syntaxError;
+ }
+ *pt++ = i;
+ argc--; largv++;
+ }
+
+ if (argv != NULL) {
+ ckfree((char *) argv);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CreateOutline
+ *
+ * This procedure initializes the Tk_Outline structure
+ * with default values.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void Tk_CreateOutline(outline)
+ Tk_Outline *outline;
+{
+ outline->gc = None;
+ outline->width = 1.0;
+ outline->activeWidth = 0.0;
+ outline->disabledWidth = 0.0;
+ outline->offset = 0;
+ outline->dash.number = 0;
+ outline->activeDash.number = 0;
+ outline->disabledDash.number = 0;
+ outline->tsoffset.flags = 0;
+ outline->tsoffset.xoffset = 0;
+ outline->tsoffset.yoffset = 0;
+ outline->color = NULL;
+ outline->activeColor = NULL;
+ outline->disabledColor = NULL;
+ outline->stipple = None;
+ outline->activeStipple = None;
+ outline->disabledStipple = None;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_DeleteOutline
+ *
+ * This procedure frees all memory that might be
+ * allocated and referenced in the Tk_Outline structure.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void Tk_DeleteOutline(display, outline)
+ Display *display; /* Display containing window */
+ Tk_Outline *outline;
+{
+ if (outline->gc != None) {
+ Tk_FreeGC(display, outline->gc);
+ }
+ if (ABS(outline->dash.number) > sizeof(char *)) {
+ ckfree((char *) outline->dash.pattern.pt);
+ }
+ if (ABS(outline->activeDash.number) > sizeof(char *)) {
+ ckfree((char *) outline->activeDash.pattern.pt);
+ }
+ if (ABS(outline->disabledDash.number) > sizeof(char *)) {
+ ckfree((char *) outline->disabledDash.pattern.pt);
+ }
+ if (outline->color != NULL) {
+ Tk_FreeColor(outline->color);
+ }
+ if (outline->activeColor != NULL) {
+ Tk_FreeColor(outline->activeColor);
+ }
+ if (outline->disabledColor != NULL) {
+ Tk_FreeColor(outline->disabledColor);
+ }
+ if (outline->stipple != None) {
+ Tk_FreeBitmap(display, outline->stipple);
+ }
+ if (outline->activeStipple != None) {
+ Tk_FreeBitmap(display, outline->activeStipple);
+ }
+ if (outline->disabledStipple != None) {
+ Tk_FreeBitmap(display, outline->disabledStipple);
+ }
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ConfigOutlineGC
+ *
+ * This procedure should be called in the canvas object
+ * during the configure command. The graphics context
+ * description in gcValues is updated according to the
+ * information in the dash structure, as far as possible.
+ *
+ * Results:
+ * The return-value is a mask, indicating which
+ * elements of gcValues have been updated.
+ * 0 means there is no outline.
+ *
+ * Side effects:
+ * GC information in gcValues is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int Tk_ConfigOutlineGC(gcValues, canvas, item, outline)
+ XGCValues *gcValues;
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ int mask = 0;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ if (outline->width < 0.0) {
+ outline->width = 0.0;
+ }
+ if (outline->activeWidth < 0.0) {
+ outline->activeWidth = 0.0;
+ }
+ if (outline->disabledWidth < 0) {
+ outline->disabledWidth = 0.0;
+ }
+ if (state==TK_STATE_HIDDEN) {
+ return 0;
+ }
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+
+ if (color==NULL) {
+ return 0;
+ }
+
+ gcValues->line_width = (int) (width + 0.5);
+ if (color != NULL) {
+ gcValues->foreground = color->pixel;
+ mask = GCForeground|GCLineWidth;
+ if (stipple != None) {
+ gcValues->stipple = stipple;
+ gcValues->fill_style = FillStippled;
+ mask |= GCStipple|GCFillStyle;
+ }
+ }
+ if (mask && (dash->number != 0)) {
+ gcValues->line_style = LineOnOffDash;
+ gcValues->dash_offset = outline->offset;
+ if (dash->number >= 2) {
+ gcValues->dashes = 4;
+ } else if (dash->number > 0) {
+ gcValues->dashes = dash->pattern.array[0];
+ } else {
+ gcValues->dashes = (char) (4 * width);
+ }
+ mask |= GCLineStyle|GCDashList|GCDashOffset;
+ }
+ return mask;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ChangeOutlineGC
+ *
+ * Updates the GC to represent the full information of
+ * the dash structure. Partly this is already done in
+ * Tk_ConfigOutlineGC().
+ * This function should be called just before drawing
+ * the dashed item.
+ *
+ * Results:
+ * 1 if there is a stipple pattern.
+ * 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+int
+Tk_ChangeOutlineGC(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ CONST char *p;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number<-1) || ((dash->number == -1) && (dash->pattern.array[1]!=','))) {
+ char *q;
+ int i = -dash->number;
+
+ p = (i > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ q = (char *) ckalloc(2*(unsigned int)i);
+ i = DashConvert(q, p, i, width);
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, q, i);
+ ckfree(q);
+ } else if ( dash->number>2 || (dash->number==2 &&
+ (dash->pattern.array[0]!=dash->pattern.array[1]))) {
+ p = (char *) (dash->number > sizeof(char *)) ? dash->pattern.pt : dash->pattern.array;
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, p, dash->number);
+ }
+ if (stipple!=None) {
+ int w=0; int h=0;
+ Tk_TSOffset *tsoffset = &outline->tsoffset;
+ int flags = tsoffset->flags;
+ if (!(flags & TK_OFFSET_INDEX) && (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE))) {
+ Tk_SizeOfBitmap(((TkCanvas *)canvas)->display, stipple, &w, &h);
+ if (flags & TK_OFFSET_CENTER) {
+ w /= 2;
+ } else {
+ w = 0;
+ }
+ if (flags & TK_OFFSET_MIDDLE) {
+ h /= 2;
+ } else {
+ h = 0;
+ }
+ }
+ tsoffset->xoffset -= w;
+ tsoffset->yoffset -= h;
+ Tk_CanvasSetOffset(canvas, outline->gc, tsoffset);
+ tsoffset->xoffset += w;
+ tsoffset->yoffset += h;
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_ResetOutlineGC
+ *
+ * Restores the GC to the situation before
+ * Tk_ChangeDashGC() was called.
+ * This function should be called just after the dashed
+ * item is drawn, because the GC is supposed to be
+ * read-only.
+ *
+ * Results:
+ * 1 if there is a stipple pattern.
+ * 0 otherwise.
+ *
+ * Side effects:
+ * GC is updated.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Tk_ResetOutlineGC(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ char dashList;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number != 0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>width) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number != 0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ if (color==NULL) {
+ return 0;
+ }
+
+ if ((dash->number > 2) || (dash->number < -1) || (dash->number==2 &&
+ (dash->pattern.array[0] != dash->pattern.array[1])) ||
+ ((dash->number == -1) && (dash->pattern.array[1] != ','))) {
+ if (dash->number < 0) {
+ dashList = (int) (4 * width + 0.5);
+ } else if (dash->number<3) {
+ dashList = dash->pattern.array[0];
+ } else {
+ dashList = 4;
+ }
+ XSetDashes(((TkCanvas *)canvas)->display, outline->gc, outline->offset, &dashList , 1);
+ }
+ if (stipple!=None) {
+ XSetTSOrigin(((TkCanvas *)canvas)->display, outline->gc, 0, 0);
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Tk_CanvasPsOutline
+ *
+ * Creates the postscript command for the correct
+ * Outline-information (width, dash, color and stipple).
+ *
+ * Results:
+ * TCL_OK if succeeded, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * canvas->interp->result contains the postscript string,
+ * or an error message if the result was TCL_ERROR.
+ *
+ *--------------------------------------------------------------
+ */
+int
+Tk_CanvasPsOutline(canvas, item, outline)
+ Tk_Canvas canvas;
+ Tk_Item *item;
+ Tk_Outline *outline;
+{
+ char string[41];
+ char pattern[11];
+ int i;
+ char *p;
+ char *s = string;
+ char *l = pattern;
+ Tcl_Interp *interp = ((TkCanvas *)canvas)->interp;
+ double width;
+ Tk_Dash *dash;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = item->state;
+
+ width = outline->width;
+ dash = &(outline->dash);
+ color = outline->color;
+ stipple = outline->stipple;
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ if (((TkCanvas *)canvas)->currentItemPtr == item) {
+ if (outline->activeWidth>width) {
+ width = outline->activeWidth;
+ }
+ if (outline->activeDash.number>0) {
+ dash = &(outline->activeDash);
+ }
+ if (outline->activeColor!=NULL) {
+ color = outline->activeColor;
+ }
+ if (outline->activeStipple!=None) {
+ stipple = outline->activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (outline->disabledWidth>0) {
+ width = outline->disabledWidth;
+ }
+ if (outline->disabledDash.number>0) {
+ dash = &(outline->disabledDash);
+ }
+ if (outline->disabledColor!=NULL) {
+ color = outline->disabledColor;
+ }
+ if (outline->disabledStipple!=None) {
+ stipple = outline->disabledStipple;
+ }
+ }
+ sprintf(string, "%.15g setlinewidth\n", width);
+ Tcl_AppendResult(interp, string, (char *) NULL);
+
+ if (dash->number > 10) {
+ s = (char *)ckalloc(1 + 4*(unsigned int)dash->number);
+ } else if (dash->number<-5) {
+ s = (char *)ckalloc(1 - 8*(unsigned int)dash->number);
+ l = (char *)ckalloc(1 - 2*(unsigned int)dash->number);
+ }
+ p = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
+ dash->pattern.pt : dash->pattern.array;
+ if (dash->number > 0) {
+ sprintf(s,"[%d",*p++ & 0xff);
+ i=dash->number-1;
+ while(i--) {
+ sprintf(s+strlen(s)," %d",*p++ & 0xff);
+ }
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ if (dash->number&1) {
+ Tcl_AppendResult(interp," ",s+1,(char *)NULL);
+ }
+ sprintf(s,"] %d setdash\n",outline->offset);
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ } else if (dash->number < 0) {
+ if ((i = DashConvert(l ,p, -dash->number, width)) != 0) {
+ sprintf(s,"[%d",*l++ & 0xff);
+ while(--i) {
+ sprintf(s+strlen(s)," %d",*l++ & 0xff);
+ }
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ sprintf(s,"] %d setdash\n",outline->offset);
+ Tcl_AppendResult(interp,s,(char *)NULL);
+ } else {
+ Tcl_AppendResult(interp,"[] 0 setdash\n",(char *)NULL);
+ }
+ } else {
+ Tcl_AppendResult(interp,"[] 0 setdash\n",(char *)NULL);
+ }
+ if (s!=string) {
+ ckfree(s);
+ }
+ if (l!=pattern) {
+ ckfree(l);
+ }
+ if (Tk_CanvasPsColor(interp, canvas, color)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (stipple != None) {
+ Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
+ if (Tk_CanvasPsStipple(interp, canvas,
+ stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
+ }
+
+ return TCL_OK;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DashConvert
+ *
+ * Converts a character-like dash-list (e.g. "-..")
+ * into an X11-style. l must point to a string that
+ * holds room to at least 2*n characters. if
+ * l == NULL, this function can be used for
+ * syntax checking only.
+ *
+ * Results:
+ * The length of the resulting X11 compatible
+ * dash-list. -1 if failed.
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+DashConvert (l, p, n, width)
+ char *l;
+ CONST char *p;
+ int n;
+ double width;
+{
+ int result = 0;
+ int size, intWidth;
+
+ if (n<0) {
+ n = strlen(p);
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ while (n-- && *p) {
+ switch (*p++) {
+ case ' ':
+ if (result) {
+ if (l) {
+ l[-1] += intWidth + 1;
+ }
+ continue;
+ } else {
+ return 0;
+ }
+ break;
+ case '_':
+ size = 8;
+ break;
+ case '-':
+ size = 6;
+ break;
+ case ',':
+ size = 4;
+ break;
+ case '.':
+ size = 2;
+ break;
+ default:
+ return -1;
+ }
+ if (l) {
+ *l++ = size * intWidth;
+ *l++ = 4 * intWidth;
+ }
+ result += 2;
+ }
+ return result;
+}