summaryrefslogtreecommitdiffstats
path: root/generic/tkCanvLine.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/tkCanvLine.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/tkCanvLine.c')
-rw-r--r--generic/tkCanvLine.c1207
1 files changed, 1023 insertions, 184 deletions
diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c
index 131b73d..328d184 100644
--- a/generic/tkCanvLine.c
+++ b/generic/tkCanvLine.c
@@ -10,23 +10,29 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkCanvLine.c,v 1.4 1999/04/16 01:51:11 stanton Exp $
+ * RCS: @(#) $Id: tkCanvLine.c,v 1.5 1999/12/14 06:52:26 hobbs Exp $
*/
#include <stdio.h>
#include "tkInt.h"
#include "tkPort.h"
+#include "tkCanvas.h"
/*
* The structure below defines the record for each line item.
*/
+typedef enum {
+ ARROWS_NONE, ARROWS_FIRST, ARROWS_LAST, ARROWS_BOTH
+} Arrows;
+
typedef struct LineItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
+ Tk_Outline outline; /* Outline structure */
Tk_Canvas canvas; /* Canvas containing item. Needed for
* parsing arrow shapes. */
- int numPoints; /* Number of points in line (always >= 2). */
+ int numPoints; /* Number of points in line (always >= 0). */
double *coordPtr; /* Pointer to malloc-ed array containing
* x- and y-coords of all points in line.
* X-coords are even-valued indices, y-coords
@@ -37,14 +43,10 @@ typedef struct LineItem {
* their tips. The actual endpoints are
* stored in the *firstArrowPtr and
* *lastArrowPtr, if they exist. */
- int width; /* Width of line. */
- XColor *fg; /* Foreground color for line. */
- Pixmap fillStipple; /* Stipple bitmap for filling line. */
int capStyle; /* Cap style for line. */
int joinStyle; /* Join style for line. */
- GC gc; /* Graphics context for filling line. */
GC arrowGC; /* Graphics context for drawing arrowheads. */
- Tk_Uid arrow; /* Indicates whether or not to draw arrowheads:
+ Arrows arrow; /* Indicates whether or not to draw arrowheads:
* "none", "first", "last", or "both". */
float arrowShapeA; /* Distance from tip of arrowhead to center. */
float arrowShapeB; /* Distance from tip of arrowhead to trailing
@@ -60,7 +62,7 @@ typedef struct LineItem {
* point in line (PTS_IN_ARROW points, first
* of which is tip). Malloc'ed. NULL means
* no arrowhead at last point. */
- int smooth; /* Non-zero means draw line smoothed (i.e.
+ Tk_SmoothMethod *smooth; /* Non-zero means draw line smoothed (i.e.
* with Bezier splines). */
int splineSteps; /* Number of steps in each spline segment. */
} LineItem;
@@ -82,29 +84,42 @@ static void ComputeLineBbox _ANSI_ARGS_((Tk_Canvas canvas,
LineItem *linePtr));
static int ConfigureLine _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
- char **argv, int flags));
+ Tcl_Obj *CONST argv[], int flags));
static int ConfigureArrows _ANSI_ARGS_((Tk_Canvas canvas,
LineItem *linePtr));
static int CreateLine _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
static void DeleteLine _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayLine _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display, Drawable dst,
int x, int y, int width, int height));
+static int GetLineIndex _ANSI_ARGS_((Tcl_Interp *interp,
+ Tk_Canvas canvas, Tk_Item *itemPtr,
+ Tcl_Obj *obj, int *indexPtr));
static int LineCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
- int argc, char **argv));
+ int argc, Tcl_Obj *CONST argv[]));
+static void LineDeleteCoords _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int first, int last));
+static void LineInsert _ANSI_ARGS_((Tk_Canvas canvas,
+ Tk_Item *itemPtr, int beforeThis, Tcl_Obj *obj));
static int LineToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double LineToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *coordPtr));
static int LineToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
+static int ArrowParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *recordPtr, int offset));
+static char * ArrowPrintProc _ANSI_ARGS_((ClientData clientData,
+ Tk_Window tkwin, char *recordPtr, int offset,
+ Tcl_FreeProc **freeProcPtr));
static int ParseArrowShape _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, Tk_Window tkwin, char *value,
- char *recordPtr, int offset));
+ Tcl_Interp *interp, Tk_Window tkwin,
+ CONST char *value, char *recordPtr, int offset));
static char * PrintArrowShape _ANSI_ARGS_((ClientData clientData,
Tk_Window tkwin, char *recordPtr, int offset,
Tcl_FreeProc **freeProcPtr));
@@ -120,34 +135,101 @@ static void TranslateLine _ANSI_ARGS_((Tk_Canvas canvas,
* values in CreateLine.
*/
-static Tk_CustomOption arrowShapeOption = {ParseArrowShape,
- PrintArrowShape, (ClientData) NULL};
-static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
+static Tk_CustomOption arrowShapeOption = {
+ (Tk_OptionParseProc *) ParseArrowShape,
+ PrintArrowShape, (ClientData) NULL
+};
+static Tk_CustomOption arrowOption = {
+ (Tk_OptionParseProc *) ArrowParseProc,
+ ArrowPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption smoothOption = {
+ (Tk_OptionParseProc *) TkSmoothParseProc,
+ TkSmoothPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) 2
+};
+static Tk_CustomOption tagsOption = {
+ (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
+static Tk_CustomOption dashOption = {
+ (Tk_OptionParseProc *) TkCanvasDashParseProc,
+ TkCanvasDashPrintProc, (ClientData) NULL
+};
+static Tk_CustomOption offsetOption = {
+ (Tk_OptionParseProc *) TkOffsetParseProc,
+ TkOffsetPrintProc,
+ (ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
+};
+static Tk_CustomOption pixelOption = {
+ (Tk_OptionParseProc *) TkPixelParseProc,
+ TkPixelPrintProc, (ClientData) NULL
+};
static Tk_ConfigSpec configSpecs[] = {
- {TK_CONFIG_UID, "-arrow", (char *) NULL, (char *) NULL,
- "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-activedash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-activefill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-activestipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.activeStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-activewidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(LineItem, outline.activeWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
+ {TK_CONFIG_CUSTOM, "-arrow", (char *) NULL, (char *) NULL,
+ "none", Tk_Offset(LineItem, arrow), TK_CONFIG_DONT_SET_DEFAULT, &arrowOption},
{TK_CONFIG_CUSTOM, "-arrowshape", (char *) NULL, (char *) NULL,
"8 10 3", Tk_Offset(LineItem, arrowShapeA),
TK_CONFIG_DONT_SET_DEFAULT, &arrowShapeOption},
{TK_CONFIG_CAP_STYLE, "-capstyle", (char *) NULL, (char *) NULL,
"butt", Tk_Offset(LineItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
- "black", Tk_Offset(LineItem, fg), TK_CONFIG_NULL_OK},
+ "black", Tk_Offset(LineItem, outline.color), TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-dash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.dash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_PIXELS, "-dashoffset", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(LineItem, outline.offset),
+ TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-disableddash", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledDash),
+ TK_CONFIG_NULL_OK, &dashOption},
+ {TK_CONFIG_COLOR, "-disabledfill", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledColor),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_BITMAP, "-disabledstipple", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(LineItem, outline.disabledStipple),
+ TK_CONFIG_NULL_OK},
+ {TK_CONFIG_CUSTOM, "-disabledwidth", (char *) NULL, (char *) NULL,
+ "0.0", Tk_Offset(LineItem, outline.disabledWidth),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_JOIN_STYLE, "-joinstyle", (char *) NULL, (char *) NULL,
"round", Tk_Offset(LineItem, joinStyle), TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_BOOLEAN, "-smooth", (char *) NULL, (char *) NULL,
- "0", Tk_Offset(LineItem, smooth), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-offset", (char *) NULL, (char *) NULL,
+ "0,0", Tk_Offset(LineItem, outline.tsoffset),
+ TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
+ {TK_CONFIG_CUSTOM, "-smooth", (char *) NULL, (char *) NULL,
+ "0", Tk_Offset(LineItem, smooth),
+ TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
{TK_CONFIG_INT, "-splinesteps", (char *) NULL, (char *) NULL,
"12", Tk_Offset(LineItem, splineSteps), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
+ (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
+ &stateOption},
{TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(LineItem, fillStipple), TK_CONFIG_NULL_OK},
+ (char *) NULL, Tk_Offset(LineItem, outline.stipple),
+ TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
(char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
- {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
- "1", Tk_Offset(LineItem, width), TK_CONFIG_DONT_SET_DEFAULT},
+ {TK_CONFIG_CUSTOM, "-width", (char *) NULL, (char *) NULL,
+ "1.0", Tk_Offset(LineItem, outline.width),
+ TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
(char *) NULL, 0, 0}
};
@@ -166,18 +248,18 @@ Tk_ItemType tkLineType = {
LineCoords, /* coordProc */
DeleteLine, /* deleteProc */
DisplayLine, /* displayProc */
- 0, /* alwaysRedraw */
+ TK_CONFIG_OBJS, /* flags */
LineToPoint, /* pointProc */
LineToArea, /* areaProc */
LineToPostscript, /* postscriptProc */
ScaleLine, /* scaleProc */
TranslateLine, /* translateProc */
- (Tk_ItemIndexProc *) NULL, /* indexProc */
+ (Tk_ItemIndexProc *) GetLineIndex, /* indexProc */
(Tk_ItemCursorProc *) NULL, /* icursorProc */
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
- (Tk_ItemInsertProc *) NULL, /* insertProc */
- (Tk_ItemDCharsProc *) NULL, /* dTextProc */
- (Tk_ItemType *) NULL /* nextPtr */
+ (Tk_ItemInsertProc *) LineInsert, /* insertProc */
+ LineDeleteCoords, /* dTextProc */
+ (Tk_ItemType *) NULL, /* nextPtr */
};
/*
@@ -215,42 +297,31 @@ CreateLine(interp, canvas, itemPtr, argc, argv)
Tk_Item *itemPtr; /* Record to hold new item; header
* has been initialized by caller. */
int argc; /* Number of arguments in argv. */
- char **argv; /* Arguments describing line. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing line. */
{
LineItem *linePtr = (LineItem *) itemPtr;
int i;
- if (argc < 4) {
- Tcl_AppendResult(interp, "wrong # args: should be \"",
- Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
- itemPtr->typePtr->name, " x1 y1 x2 y2 ?x3 y3 ...? ?options?\"",
- (char *) NULL);
- return TCL_ERROR;
- }
-
/*
* Carry out initialization that is needed to set defaults and to
* allow proper cleanup after errors during the the remainder of
* this procedure.
*/
+ Tk_CreateOutline(&(linePtr->outline));
linePtr->canvas = canvas;
linePtr->numPoints = 0;
linePtr->coordPtr = NULL;
- linePtr->width = 1;
- linePtr->fg = None;
- linePtr->fillStipple = None;
linePtr->capStyle = CapButt;
linePtr->joinStyle = JoinRound;
- linePtr->gc = None;
linePtr->arrowGC = None;
- linePtr->arrow = Tk_GetUid("none");
+ linePtr->arrow = ARROWS_NONE;
linePtr->arrowShapeA = (float)8.0;
linePtr->arrowShapeB = (float)10.0;
linePtr->arrowShapeC = (float)3.0;
linePtr->firstArrowPtr = NULL;
linePtr->lastArrowPtr = NULL;
- linePtr->smooth = 0;
+ linePtr->smooth = (Tk_SmoothMethod *) NULL;
linePtr->splineSteps = 12;
/*
@@ -259,14 +330,14 @@ CreateLine(interp, canvas, itemPtr, argc, argv)
* start with a digit or a minus sign followed by a digit.
*/
- for (i = 4; i < (argc-1); i+=2) {
- if ((!isdigit(UCHAR(argv[i][0]))) &&
- ((argv[i][0] != '-')
- || ((argv[i][1] != '.') && !isdigit(UCHAR(argv[i][1]))))) {
+ for (i = 0; i < argc; i++) {
+ char *arg = Tcl_GetStringFromObj(argv[i], NULL);
+ if ((arg[0] == '-') && (arg[1] >= 'a')
+ && (arg[1] <= 'z')) {
break;
}
}
- if (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK) {
+ if (i && (LineCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
goto error;
}
if (ConfigureLine(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
@@ -304,16 +375,16 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
* read or modified. */
int argc; /* Number of coordinates supplied in
* argv. */
- char **argv; /* Array of coordinates: x1, y1,
+ Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
LineItem *linePtr = (LineItem *) itemPtr;
- char buffer[TCL_DOUBLE_SPACE];
int i, numPoints;
+ double *coordPtr;
if (argc == 0) {
- double *coordPtr;
int numCoords;
+ Tcl_Obj *subobj, *obj = Tcl_NewObj();
numCoords = 2*linePtr->numPoints;
if (linePtr->firstArrowPtr != NULL) {
@@ -328,15 +399,19 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
if ((linePtr->lastArrowPtr != NULL) && (i == (numCoords-2))) {
coordPtr = linePtr->lastArrowPtr;
}
- Tcl_PrintDouble(interp, *coordPtr, buffer);
- Tcl_AppendElement(interp, buffer);
+ subobj = Tcl_NewDoubleObj(*coordPtr);
+ Tcl_ListObjAppendElement(interp, obj, subobj);
}
- } else if (argc < 4) {
- Tcl_AppendResult(interp,
- "too few coordinates for line: must have at least 4",
- (char *) NULL);
- return TCL_ERROR;
- } else if (argc & 1) {
+ Tcl_SetObjResult(interp, obj);
+ return TCL_OK;
+ }
+ if (argc == 1) {
+ if (Tcl_ListObjGetElements(interp, argv[0], &argc,
+ (Tcl_Obj ***) &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (argc & 1) {
Tcl_AppendResult(interp,
"odd number of coordinates specified for line",
(char *) NULL);
@@ -344,19 +419,21 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
} else {
numPoints = argc/2;
if (linePtr->numPoints != numPoints) {
+ coordPtr = (double *) ckalloc((unsigned)
+ (sizeof(double) * argc));
if (linePtr->coordPtr != NULL) {
ckfree((char *) linePtr->coordPtr);
}
- linePtr->coordPtr = (double *) ckalloc((unsigned)
- (sizeof(double) * argc));
+ linePtr->coordPtr = coordPtr;
linePtr->numPoints = numPoints;
}
- for (i = argc-1; i >= 0; i--) {
- if (Tk_CanvasGetCoord(interp, canvas, argv[i],
- &linePtr->coordPtr[i]) != TCL_OK) {
- return TCL_ERROR;
- }
- }
+ coordPtr = linePtr->coordPtr;
+ for (i = 0; i <argc; i++) {
+ if (Tk_CanvasGetCoordFromObj(interp, canvas, argv[i],
+ coordPtr++) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
/*
* Update arrowheads by throwing away any existing arrow-head
@@ -371,7 +448,7 @@ LineCoords(interp, canvas, itemPtr, argc, argv)
ckfree((char *) linePtr->lastArrowPtr);
linePtr->lastArrowPtr = NULL;
}
- if (linePtr->arrow != Tk_GetUid("none")) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -404,7 +481,7 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Line item to reconfigure. */
int argc; /* Number of elements in argv. */
- char **argv; /* Arguments describing things to configure. */
+ Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
LineItem *linePtr = (LineItem *) itemPtr;
@@ -412,14 +489,11 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
GC newGC, arrowGC;
unsigned long mask;
Tk_Window tkwin;
- Tk_Uid noneUid = Tk_GetUid("none");
- Tk_Uid bothUid = Tk_GetUid("both");
- Tk_Uid firstUid = Tk_GetUid("first");
- Tk_Uid lastUid = Tk_GetUid("last");
+ Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
- if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
- (char *) linePtr, flags) != TCL_OK) {
+ if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, (char **) argv,
+ (char *) linePtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
@@ -428,36 +502,42 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
* graphics contexts.
*/
- if (linePtr->fg == NULL) {
- newGC = arrowGC = None;
+ state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (linePtr->outline.activeWidth > linePtr->outline.width ||
+ linePtr->outline.activeDash.number > 0 ||
+ linePtr->outline.activeColor != NULL ||
+ linePtr->outline.activeStipple != None) {
+ itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
} else {
- gcValues.foreground = linePtr->fg->pixel;
- gcValues.join_style = linePtr->joinStyle;
- if (linePtr->width < 0) {
- linePtr->width = 1;
- }
- gcValues.line_width = linePtr->width;
- mask = GCForeground|GCJoinStyle|GCLineWidth;
- if (linePtr->fillStipple != None) {
- gcValues.stipple = linePtr->fillStipple;
- gcValues.fill_style = FillStippled;
- mask |= GCStipple|GCFillStyle;
- }
- if (linePtr->arrow == noneUid) {
+ itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
+ }
+ mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
+ &(linePtr->outline));
+ if (mask) {
+ if (linePtr->arrow == ARROWS_NONE) {
gcValues.cap_style = linePtr->capStyle;
mask |= GCCapStyle;
}
+ gcValues.join_style = linePtr->joinStyle;
+ mask |= GCJoinStyle;
newGC = Tk_GetGC(tkwin, mask, &gcValues);
gcValues.line_width = 0;
arrowGC = Tk_GetGC(tkwin, mask, &gcValues);
+ } else {
+ newGC = arrowGC = None;
}
- if (linePtr->gc != None) {
- Tk_FreeGC(Tk_Display(tkwin), linePtr->gc);
+ if (linePtr->outline.gc != None) {
+ Tk_FreeGC(Tk_Display(tkwin), linePtr->outline.gc);
}
if (linePtr->arrowGC != None) {
Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC);
}
- linePtr->gc = newGC;
+ linePtr->outline.gc = newGC;
linePtr->arrowGC = arrowGC;
/*
@@ -470,21 +550,26 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
linePtr->splineSteps = 100;
}
+ if ((!linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
+ ComputeLineBbox(canvas, linePtr);
+ return TCL_OK;
+ }
+
/*
* Setup arrowheads, if needed. If arrowheads are turned off,
* restore the line's endpoints (they were shortened when the
* arrowheads were added).
*/
- if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != firstUid)
- && (linePtr->arrow != bothUid)) {
+ if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != ARROWS_FIRST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
ckfree((char *) linePtr->firstArrowPtr);
linePtr->firstArrowPtr = NULL;
}
- if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != lastUid)
- && (linePtr->arrow != bothUid)) {
+ if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != ARROWS_LAST)
+ && (linePtr->arrow != ARROWS_BOTH)) {
int i;
i = 2*(linePtr->numPoints-1);
@@ -493,15 +578,7 @@ ConfigureLine(interp, canvas, itemPtr, argc, argv, flags)
ckfree((char *) linePtr->lastArrowPtr);
linePtr->lastArrowPtr = NULL;
}
- if (linePtr->arrow != noneUid) {
- if ((linePtr->arrow != firstUid) && (linePtr->arrow != lastUid)
- && (linePtr->arrow != bothUid)) {
- Tcl_AppendResult(interp, "bad arrow spec \"",
- linePtr->arrow, "\": must be none, first, last, or both",
- (char *) NULL);
- linePtr->arrow = noneUid;
- return TCL_ERROR;
- }
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
@@ -540,18 +617,10 @@ DeleteLine(canvas, itemPtr, display)
{
LineItem *linePtr = (LineItem *) itemPtr;
+ Tk_DeleteOutline(display, &(linePtr->outline));
if (linePtr->coordPtr != NULL) {
ckfree((char *) linePtr->coordPtr);
}
- if (linePtr->fg != NULL) {
- Tk_FreeColor(linePtr->fg);
- }
- if (linePtr->fillStipple != None) {
- Tk_FreeBitmap(display, linePtr->fillStipple);
- }
- if (linePtr->gc != None) {
- Tk_FreeGC(display, linePtr->gc);
- }
if (linePtr->arrowGC != None) {
Tk_FreeGC(display, linePtr->arrowGC);
}
@@ -588,7 +657,33 @@ ComputeLineBbox(canvas, linePtr)
* recomputed. */
{
double *coordPtr;
- int i, width;
+ int i, intWidth;
+ double width;
+ Tk_State state = linePtr->header.state;
+ Tk_TSOffset *tsoffset;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (!(linePtr->numPoints) || (state==TK_STATE_HIDDEN)) {
+ linePtr->header.x1 = -1;
+ linePtr->header.x2 = -1;
+ linePtr->header.y1 = -1;
+ linePtr->header.y2 = -1;
+ return;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
coordPtr = linePtr->coordPtr;
linePtr->header.x1 = linePtr->header.x2 = (int) *coordPtr;
@@ -608,14 +703,66 @@ ComputeLineBbox(canvas, linePtr)
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
}
- width = linePtr->width;
- if (width < 1) {
- width = 1;
+ width = linePtr->outline.width;
+ if (width < 1.0) {
+ width = 1.0;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->firstArrowPtr);
+ }
+ if (linePtr->arrow != ARROWS_FIRST) {
+ TkIncludePoint((Tk_Item *) linePtr, linePtr->lastArrowPtr);
+ }
+ }
+
+ tsoffset = &linePtr->outline.tsoffset;
+ if (tsoffset->flags & TK_OFFSET_INDEX) {
+ double *coordPtr = linePtr->coordPtr + (tsoffset->flags & ~TK_OFFSET_INDEX);
+ if (tsoffset->flags <= 0) {
+ coordPtr = linePtr->coordPtr;
+ if ((linePtr->arrow == ARROWS_FIRST) || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->firstArrowPtr;
+ }
+ }
+ if (tsoffset->flags > (linePtr->numPoints * 2)) {
+ coordPtr = linePtr->coordPtr + (linePtr->numPoints * 2);
+ if ((linePtr->arrow == ARROWS_LAST) || (linePtr->arrow == ARROWS_BOTH)) {
+ coordPtr = linePtr->lastArrowPtr;
+ }
+ }
+ tsoffset->xoffset = (int) (coordPtr[0] + 0.5);
+ tsoffset->yoffset = (int) (coordPtr[1] + 0.5);
+ } else {
+ if (tsoffset->flags & TK_OFFSET_LEFT) {
+ tsoffset->xoffset = linePtr->header.x1;
+ } else if (tsoffset->flags & TK_OFFSET_CENTER) {
+ tsoffset->xoffset = (linePtr->header.x1 + linePtr->header.x2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_RIGHT) {
+ tsoffset->xoffset = linePtr->header.x2;
+ }
+ if (tsoffset->flags & TK_OFFSET_TOP) {
+ tsoffset->yoffset = linePtr->header.y1;
+ } else if (tsoffset->flags & TK_OFFSET_MIDDLE) {
+ tsoffset->yoffset = (linePtr->header.y1 + linePtr->header.y2)/2;
+ } else if (tsoffset->flags & TK_OFFSET_BOTTOM) {
+ tsoffset->yoffset = linePtr->header.y2;
+ }
+ }
+
+ intWidth = (int) (width + 0.5);
+ linePtr->header.x1 -= intWidth;
+ linePtr->header.x2 += intWidth;
+ linePtr->header.y1 -= intWidth;
+ linePtr->header.y2 += intWidth;
+
+ if (linePtr->numPoints==1) {
+ linePtr->header.x1 -= 1;
+ linePtr->header.x2 += 1;
+ linePtr->header.y1 -= 1;
+ linePtr->header.y2 += 1;
+ return;
}
- linePtr->header.x1 -= width;
- linePtr->header.x2 += width;
- linePtr->header.y1 -= width;
- linePtr->header.y2 += width;
/*
* For mitered lines, make a second pass through all the points.
@@ -630,7 +777,7 @@ ComputeLineBbox(canvas, linePtr)
int j;
if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,
- (double) width, miter, miter+2)) {
+ width, miter, miter+2)) {
for (j = 0; j < 4; j += 2) {
TkIncludePoint((Tk_Item *) linePtr, miter+j);
}
@@ -642,14 +789,14 @@ ComputeLineBbox(canvas, linePtr)
* Add in the sizes of arrowheads, if any.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
}
}
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
i++, coordPtr += 2) {
TkIncludePoint((Tk_Item *) linePtr, coordPtr);
@@ -700,13 +847,34 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
XPoint staticPoints[MAX_STATIC_POINTS];
XPoint *pointPtr;
XPoint *pPtr;
- double *coordPtr;
+ double *coordPtr, linewidth;
int i, numPoints;
+ Tk_State state = itemPtr->state;
+ Pixmap stipple = linePtr->outline.stipple;
- if (linePtr->gc == None) {
+ if ((!linePtr->numPoints)||(linePtr->outline.gc==None)) {
return;
}
+ if (state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ linewidth = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ if (linePtr->outline.activeWidth>linewidth) {
+ linewidth = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ if (linePtr->outline.disabledWidth>linewidth) {
+ linewidth = linePtr->outline.activeWidth;
+ }
+ }
/*
* Build up an array of points in screen coordinates. Use a
* static array unless the line has an enormous number of points;
@@ -715,7 +883,9 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
*/
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
} else {
numPoints = linePtr->numPoints;
}
@@ -727,7 +897,7 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
}
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, pointPtr,
(double *) NULL);
} else {
@@ -745,12 +915,21 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
* GC is supposed to be read-only.
*/
- if (linePtr->fillStipple != None) {
- Tk_CanvasSetStippleOrigin(canvas, linePtr->gc);
- Tk_CanvasSetStippleOrigin(canvas, linePtr->arrowGC);
+ if (Tk_ChangeOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
+ Tk_CanvasSetOffset(canvas, linePtr->arrowGC, &linePtr->outline.tsoffset);
}
- XDrawLines(display, drawable, linePtr->gc, pointPtr, numPoints,
+ if (numPoints>1) {
+ XDrawLines(display, drawable, linePtr->outline.gc, pointPtr, numPoints,
CoordModeOrigin);
+ } else {
+ int intwidth = (int) (linewidth + 0.5);
+ if (intwidth<1) {
+ intwidth=1;
+ }
+ XFillArc(display, drawable, linePtr->outline.gc,
+ pointPtr->x - intwidth/2, pointPtr->y - intwidth/2,
+ (unsigned int)intwidth+1, (unsigned int)intwidth+1, 0, 64*360);
+ }
if (pointPtr != staticPoints) {
ckfree((char *) pointPtr);
}
@@ -761,14 +940,13 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
if (linePtr->firstArrowPtr != NULL) {
TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW,
- display, drawable, linePtr->gc, NULL);
+ display, drawable, linePtr->arrowGC, NULL);
}
if (linePtr->lastArrowPtr != NULL) {
TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW,
- display, drawable, linePtr->gc, NULL);
+ display, drawable, linePtr->arrowGC, NULL);
}
- if (linePtr->fillStipple != None) {
- XSetTSOrigin(display, linePtr->gc, 0, 0);
+ if (Tk_ResetOutlineGC(canvas, itemPtr, &(linePtr->outline))) {
XSetTSOrigin(display, linePtr->arrowGC, 0, 0);
}
}
@@ -776,6 +954,325 @@ DisplayLine(canvas, itemPtr, display, drawable, x, y, width, height)
/*
*--------------------------------------------------------------
*
+ * LineInsert --
+ *
+ * Insert coords into a line item at a given index.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The coords in the given item is modified.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineInsert(canvas, itemPtr, beforeThis, obj)
+ Tk_Canvas canvas; /* Canvas containing text item. */
+ Tk_Item *itemPtr; /* Line item to be modified. */
+ int beforeThis; /* Index before which new coordinates
+ * are to be inserted. */
+ Tcl_Obj *obj; /* New coordinates to be inserted. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int length, argc, i;
+ double *new, *coordPtr;
+ Tk_State state = itemPtr->state;
+ Tcl_Obj **objv;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ if (!obj || (Tcl_ListObjGetElements((Tcl_Interp *) NULL, obj, &argc, &objv) != TCL_OK)
+ || !argc || argc&1) {
+ return;
+ }
+ length = 2*linePtr->numPoints;
+ if (beforeThis < 0) {
+ beforeThis = 0;
+ }
+ if (beforeThis > length) {
+ beforeThis = length;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ new = (double *) ckalloc((unsigned)(sizeof(double) * (length + argc)));
+ for(i=0; i<beforeThis; i++) {
+ new[i] = linePtr->coordPtr[i];
+ }
+ for(i=0; i<argc; i++) {
+ if (Tcl_GetDoubleFromObj((Tcl_Interp *) NULL,objv[i],
+ new+(i+beforeThis))!=TCL_OK) {
+ Tcl_ResetResult(((TkCanvas *)canvas)->interp);
+ ckfree((char *) new);
+ return;
+ }
+ }
+
+ for(i=beforeThis; i<length; i++) {
+ new[i+argc] = linePtr->coordPtr[i];
+ }
+ if(linePtr->coordPtr) ckfree((char *)linePtr->coordPtr);
+ linePtr->coordPtr = new;
+ linePtr->numPoints = (length + argc)/2;
+
+ if ((length>3) && (state != TK_STATE_HIDDEN)) {
+ /*
+ * This is some optimizing code that will result that only the part
+ * of the polygon that changed (and the objects that are overlapping
+ * with that part) need to be redrawn. A special flag is set that
+ * instructs the general canvas code not to redraw the whole
+ * object. If this flag is not set, the canvas will do the redrawing,
+ * otherwise I have to do it here.
+ */
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+
+ if (beforeThis>0) {beforeThis -= 2; argc+=2; }
+ if ((beforeThis+argc)<length) argc+=2;
+ if (linePtr->smooth) {
+ if(beforeThis>0) {
+ beforeThis-=2; argc+=2;
+ }
+ if((beforeThis+argc+2)<length) {
+ argc+=2;
+ }
+ }
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[beforeThis];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[beforeThis+1];
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis<1)) {
+ /* include old first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)>=length)) {
+ /* include old last arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr+beforeThis+2;
+ for(i=2; i<argc; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr+=2;
+ }
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree((char *) linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree((char *) linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+
+ if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+ if ((linePtr->firstArrowPtr != NULL) && (beforeThis>2)) {
+ /* include new first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && ((beforeThis+argc)<(length-2))) {
+ /* include new right arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * LineDeleteCoords --
+ *
+ * Delete one or more coordinates from a line item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Characters between "first" and "last", inclusive, get
+ * deleted from itemPtr.
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+LineDeleteCoords(canvas, itemPtr, first, last)
+ Tk_Canvas canvas; /* Canvas containing itemPtr. */
+ Tk_Item *itemPtr; /* Item in which to delete characters. */
+ int first; /* Index of first character to delete. */
+ int last; /* Index of last character to delete. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ int count, i, first1, last1;
+ int length = 2*linePtr->numPoints;
+ double *coordPtr;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ first &= -2;
+ last &= -2;
+
+ if (first < 0) {
+ first = 0;
+ }
+ if (last >= length) {
+ last = length-2;
+ }
+ if (first > last) {
+ return;
+ }
+ if (linePtr->firstArrowPtr != NULL) {
+ linePtr->coordPtr[0] = linePtr->firstArrowPtr[0];
+ linePtr->coordPtr[1] = linePtr->firstArrowPtr[1];
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ linePtr->coordPtr[length-2] = linePtr->lastArrowPtr[0];
+ linePtr->coordPtr[length-1] = linePtr->lastArrowPtr[1];
+ }
+ first1 = first; last1 = last;
+ if(first1>0) first1 -= 2;
+ if(last1<length-2) last1 += 2;
+ if (linePtr->smooth) {
+ if(first1>0) first1 -= 2;
+ if(last1<length-2) last1 += 2;
+ }
+
+ if((first1<2) && (last1 >= length-2)) {
+ /*
+ * This is some optimizing code that will result that only the part
+ * of the line that changed (and the objects that are overlapping
+ * with that part) need to be redrawn. A special flag is set that
+ * instructs the general canvas code not to redraw the whole
+ * object. If this flag is set, the redrawing has to be done here,
+ * otherwise the general Canvas code will take care of it.
+ */
+
+ itemPtr->redraw_flags |= TK_ITEM_DONT_REDRAW;
+ itemPtr->x1 = itemPtr->x2 = (int) linePtr->coordPtr[first1];
+ itemPtr->y1 = itemPtr->y2 = (int) linePtr->coordPtr[first1+1];
+ if ((linePtr->firstArrowPtr != NULL) && (first1<2)) {
+ /* include old first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1>=length-2)) {
+ /* include old last arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ coordPtr = linePtr->coordPtr+first1+2;
+ for (i=first1+2; i<=last1; i+=2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ coordPtr+=2;
+ }
+ }
+
+ count = last + 2 - first;
+ for (i=last+2; i<length; i++) {
+ linePtr->coordPtr[i-count] = linePtr->coordPtr[i];
+ }
+ linePtr->numPoints -= count/2;
+ if (linePtr->firstArrowPtr != NULL) {
+ ckfree((char *) linePtr->firstArrowPtr);
+ linePtr->firstArrowPtr = NULL;
+ }
+ if (linePtr->lastArrowPtr != NULL) {
+ ckfree((char *) linePtr->lastArrowPtr);
+ linePtr->lastArrowPtr = NULL;
+ }
+ if (linePtr->arrow != ARROWS_NONE) {
+ ConfigureArrows(canvas, linePtr);
+ }
+ if(itemPtr->redraw_flags & TK_ITEM_DONT_REDRAW) {
+ double width;
+ int intWidth;
+ if ((linePtr->firstArrowPtr != NULL) && (first1<4)) {
+ /* include new first arrow */
+ for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ if ((linePtr->lastArrowPtr != NULL) && (last1>(length-4))) {
+ /* include new right arrow */
+ for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;
+ i++, coordPtr += 2) {
+ TkIncludePoint(itemPtr, coordPtr);
+ }
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+ intWidth = (int) (width + 0.5);
+ if (intWidth < 1) {
+ intWidth = 1;
+ }
+ itemPtr->x1 -= intWidth; itemPtr->y1 -= intWidth;
+ itemPtr->x2 += intWidth; itemPtr->y2 += intWidth;
+ Tk_CanvasEventuallyRedraw(canvas, itemPtr->x1, itemPtr->y1,
+ itemPtr->x2, itemPtr->y2);
+ }
+ ComputeLineBbox(canvas, linePtr);
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* LineToPoint --
*
* Computes the distance from a given point to a given
@@ -800,6 +1297,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
Tk_Item *itemPtr; /* Item to check against point. */
double *pointPtr; /* Pointer to x and y coordinates. */
{
+ Tk_State state = itemPtr->state;
LineItem *linePtr = (LineItem *) itemPtr;
double *coordPtr, *linePoints;
double staticSpace[2*MAX_STATIC_POINTS];
@@ -817,15 +1315,32 @@ LineToPoint(canvas, itemPtr, pointPtr)
* against which to do the check.
*/
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
linePoints = staticSpace;
} else {
linePoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
linePoints);
} else {
@@ -833,11 +1348,19 @@ LineToPoint(canvas, itemPtr, pointPtr)
linePoints = linePtr->coordPtr;
}
- width = (double) linePtr->width;
if (width < 1.0) {
width = 1.0;
}
+ if (!numPoints || itemPtr->state==TK_STATE_HIDDEN) {
+ return bestDist;
+ } else if (numPoints == 1) {
+ bestDist = hypot(linePoints[0] - pointPtr[0], linePoints[1] - pointPtr[1])
+ - width/2.0;
+ if (bestDist < 0) bestDist = 0;
+ return bestDist;
+ }
+
/*
* The overall idea is to iterate through all of the edges of
* the line, computing a polygon for each edge and testing the
@@ -950,8 +1473,8 @@ LineToPoint(canvas, itemPtr, pointPtr)
* If there are arrowheads, check the distance to the arrowheads.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
dist = TkPolygonToPoint(linePtr->firstArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -961,7 +1484,7 @@ LineToPoint(canvas, itemPtr, pointPtr)
bestDist = dist;
}
}
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
dist = TkPolygonToPoint(linePtr->lastArrowPtr, PTS_IN_ARROW,
pointPtr);
if (dist <= 0.0) {
@@ -1010,8 +1533,36 @@ LineToArea(canvas, itemPtr, rectPtr)
LineItem *linePtr = (LineItem *) itemPtr;
double staticSpace[2*MAX_STATIC_POINTS];
double *linePoints;
- double width;
int numPoints, result;
+ double radius, width;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
+
+ radius = (width+1.0)/2.0;
+
+ if ((state==TK_STATE_HIDDEN) || !linePtr->numPoints) {
+ return -1;
+ } else if (linePtr->numPoints == 1) {
+ double oval[4];
+ oval[0] = linePtr->coordPtr[0]-radius;
+ oval[1] = linePtr->coordPtr[1]-radius;
+ oval[2] = linePtr->coordPtr[0]+radius;
+ oval[3] = linePtr->coordPtr[1]+radius;
+ return TkOvalToArea(oval, rectPtr);
+ }
/*
* Handle smoothed lines by generating an expanded set of points
@@ -1019,14 +1570,16 @@ LineToArea(canvas, itemPtr, rectPtr)
*/
if ((linePtr->smooth) && (linePtr->numPoints > 2)) {
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
if (numPoints <= MAX_STATIC_POINTS) {
linePoints = staticSpace;
} else {
linePoints = (double *) ckalloc((unsigned)
(2*numPoints*sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
linePoints);
} else {
@@ -1038,8 +1591,7 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check the segments of the line.
*/
- width = (double) linePtr->width;
- if (width < 1.0) {
+ if (width < 1.0) {
width = 1.0;
}
@@ -1054,15 +1606,15 @@ LineToArea(canvas, itemPtr, rectPtr)
* Check arrowheads, if any.
*/
- if (linePtr->arrow != Tk_GetUid("none")) {
- if (linePtr->arrow != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_NONE) {
+ if (linePtr->arrow != ARROWS_LAST) {
if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,
rectPtr) != result) {
result = 0;
goto done;
}
}
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,
rectPtr) != result) {
result = 0;
@@ -1135,7 +1687,7 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
coordPtr[0] = originX + scaleX*(*coordPtr - originX);
coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);
}
- if (linePtr->arrow != Tk_GetUid("none")) {
+ if (linePtr->arrow != ARROWS_NONE) {
ConfigureArrows(canvas, linePtr);
}
ComputeLineBbox(canvas, linePtr);
@@ -1144,6 +1696,96 @@ ScaleLine(canvas, itemPtr, originX, originY, scaleX, scaleY)
/*
*--------------------------------------------------------------
*
+ * GetLineIndex --
+ *
+ * Parse an index into a line item and return either its value
+ * or an error.
+ *
+ * Results:
+ * A standard Tcl result. If all went well, then *indexPtr is
+ * filled in with the index (into itemPtr) corresponding to
+ * string. Otherwise an error message is left in
+ * interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+GetLineIndex(interp, canvas, itemPtr, obj, indexPtr)
+ Tcl_Interp *interp; /* Used for error reporting. */
+ Tk_Canvas canvas; /* Canvas containing item. */
+ Tk_Item *itemPtr; /* Item for which the index is being
+ * specified. */
+ Tcl_Obj *obj; /* Specification of a particular coord
+ * in itemPtr's line. */
+ int *indexPtr; /* Where to store converted index. */
+{
+ LineItem *linePtr = (LineItem *) itemPtr;
+ size_t length;
+ char *string = Tcl_GetStringFromObj(obj, (int *) &length);
+
+ if (string[0] == 'e') {
+ if (strncmp(string, "end", length) == 0) {
+ *indexPtr = 2*linePtr->numPoints;
+ } else {
+ badIndex:
+
+ /*
+ * Some of the paths here leave messages in interp->result,
+ * so we have to clear it out before storing our own message.
+ */
+
+ Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
+ Tcl_AppendResult(interp, "bad index \"", string, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else if (string[0] == '@') {
+ int i;
+ double x ,y, bestDist, dist, *coordPtr;
+ char *end, *p;
+
+ p = string+1;
+ x = strtod(p, &end);
+ if ((end == p) || (*end != ',')) {
+ goto badIndex;
+ }
+ p = end+1;
+ y = strtod(p, &end);
+ if ((end == p) || (*end != 0)) {
+ goto badIndex;
+ }
+ bestDist = 1.0e36;
+ coordPtr = linePtr->coordPtr;
+ *indexPtr = 0;
+ for(i=0; i<linePtr->numPoints; i++) {
+ dist = hypot(coordPtr[0] - x, coordPtr[1] - y);
+ if (dist<bestDist) {
+ bestDist = dist;
+ *indexPtr = 2*i;
+ }
+ coordPtr += 2;
+ }
+ } else {
+ if (Tcl_GetIntFromObj(interp, obj, indexPtr) != TCL_OK) {
+ goto badIndex;
+ }
+ *indexPtr &= -2; /* if index is odd, make it even */
+ if (*indexPtr < 0){
+ *indexPtr = 0;
+ } else if (*indexPtr > (2*linePtr->numPoints)) {
+ *indexPtr = (2*linePtr->numPoints);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
* TranslateLine --
*
* This procedure is called to move a line by a given amount.
@@ -1217,7 +1859,7 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)
ClientData clientData; /* Not used. */
Tcl_Interp *interp; /* Used for error reporting. */
Tk_Window tkwin; /* Not used. */
- char *value; /* Textual specification of arrow shape. */
+ CONST char *value; /* Textual specification of arrow shape. */
char *recordPtr; /* Pointer to item record in which to
* store arrow information. */
int offset; /* Offset of shape information in widget
@@ -1232,7 +1874,7 @@ ParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)
panic("ParseArrowShape received bogus offset");
}
- if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
+ if (Tcl_SplitList(interp, (char *) value, &argc, &argv) != TCL_OK) {
syntaxError:
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "bad arrow shape \"", value,
@@ -1297,6 +1939,117 @@ PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr)
return buffer;
}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowParseProc --
+ *
+ * This procedure is invoked during option processing to handle
+ * the "-arrow" option.
+ *
+ * Results:
+ * A standard Tcl return value.
+ *
+ * Side effects:
+ * The arrow for a given item gets replaced by the arrow
+ * indicated in the value argument.
+ *
+ *--------------------------------------------------------------
+ */
+
+static int
+ArrowParseProc(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. */
+{
+ int c;
+ size_t length;
+
+ register Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ if(value == NULL || *value == 0) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+
+ c = value[0];
+ length = strlen(value);
+
+ if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
+ *arrowPtr = ARROWS_NONE;
+ return TCL_OK;
+ }
+ if ((c == 'f') && (strncmp(value, "first", length) == 0)) {
+ *arrowPtr = ARROWS_FIRST;
+ return TCL_OK;
+ }
+ if ((c == 'l') && (strncmp(value, "last", length) == 0)) {
+ *arrowPtr = ARROWS_LAST;
+ return TCL_OK;
+ }
+ if ((c == 'b') && (strncmp(value, "both", length) == 0)) {
+ *arrowPtr = ARROWS_BOTH;
+ return TCL_OK;
+ }
+
+ Tcl_AppendResult(interp, "bad arrow spec \"", value,
+ "\": must be none, first, last, or both",
+ (char *) NULL);
+ *arrowPtr = ARROWS_NONE;
+ return TCL_ERROR;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ArrowPrintProc --
+ *
+ * This procedure is invoked by the Tk configuration code
+ * to produce a printable string for the "-arrow"
+ * configuration option.
+ *
+ * Results:
+ * The return value is a string describing the arrows 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+static char *
+ArrowPrintProc(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 Arrows *arrowPtr = (Arrows *) (widgRec + offset);
+
+ switch (*arrowPtr) {
+ case ARROWS_FIRST:
+ return "first";
+ case ARROWS_LAST:
+ return "last";
+ case ARROWS_BOTH:
+ return "both";
+ default:
+ return "none";
+ }
+}
+
/*
*--------------------------------------------------------------
*
@@ -1336,6 +2089,27 @@ ConfigureArrows(canvas, linePtr)
double vertX, vertY; /* Position of arrowhead vertex. */
double shapeA, shapeB, shapeC; /* Adjusted coordinates (see
* explanation below). */
+ double width;
+ Tk_State state = linePtr->header.state;
+
+ if (linePtr->numPoints <2) {
+ return TCL_OK;
+ }
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ }
/*
* The code below makes a tiny increase in the shape parameters
@@ -1346,7 +2120,7 @@ ConfigureArrows(canvas, linePtr)
shapeA = linePtr->arrowShapeA + 0.001;
shapeB = linePtr->arrowShapeB + 0.001;
- shapeC = linePtr->arrowShapeC + linePtr->width/2.0 + 0.001;
+ shapeC = linePtr->arrowShapeC + width/2.0 + 0.001;
/*
* If there's an arrowhead on the first point of the line, compute
@@ -1354,9 +2128,9 @@ ConfigureArrows(canvas, linePtr)
* line doesn't stick out past the leading edge of the arrowhead.
*/
- fracHeight = (linePtr->width/2.0)/shapeC;
+ fracHeight = (width/2.0)/shapeC;
backup = fracHeight*shapeB + shapeA*(1.0 - fracHeight)/2.0;
- if (linePtr->arrow != Tk_GetUid("last")) {
+ if (linePtr->arrow != ARROWS_LAST) {
poly = linePtr->firstArrowPtr;
if (poly == NULL) {
poly = (double *) ckalloc((unsigned)
@@ -1401,7 +2175,7 @@ ConfigureArrows(canvas, linePtr)
* Similar arrowhead calculation for the last point of the line.
*/
- if (linePtr->arrow != Tk_GetUid("first")) {
+ if (linePtr->arrow != ARROWS_FIRST) {
coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2);
poly = linePtr->lastArrowPtr;
if (poly == NULL) {
@@ -1475,21 +2249,75 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
char buffer[64 + TCL_INTEGER_SPACE];
char *style;
- if (linePtr->fg == NULL) {
+ double width;
+ XColor *color;
+ Pixmap stipple;
+ Tk_State state = itemPtr->state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ width = linePtr->outline.width;
+ color = linePtr->outline.color;
+ stipple = linePtr->outline.stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
+ if (linePtr->outline.activeWidth>width) {
+ width = linePtr->outline.activeWidth;
+ }
+ if (linePtr->outline.activeColor!=NULL) {
+ color = linePtr->outline.activeColor;
+ }
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.disabledWidth>0) {
+ width = linePtr->outline.disabledWidth;
+ }
+ if (linePtr->outline.disabledColor!=NULL) {
+ color = linePtr->outline.disabledColor;
+ }
+ if (linePtr->outline.disabledStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
+ if (color == NULL || linePtr->numPoints<1 || linePtr->coordPtr==NULL) {
return TCL_OK;
}
+ if (linePtr->numPoints==1) {
+ sprintf(buffer, "%.15g %.15g translate %.15g %.15g",
+ linePtr->coordPtr[0], Tk_CanvasPsY(canvas, linePtr->coordPtr[1]),
+ width/2.0, width/2.0);
+ Tcl_AppendResult(interp, "matrix currentmatrix\n",buffer,
+ " scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n", (char *) NULL);
+ if (Tk_CanvasPsColor(interp, canvas, color)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (stipple != None) {
+ Tcl_AppendResult(interp, "clip ", (char *) NULL);
+ if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "fill\n", (char *) NULL);
+ }
+ return TCL_OK;
+ }
/*
* Generate a path for the line's center-line (do this differently
* for straight lines and smoothed lines).
*/
- if ((!linePtr->smooth) || (linePtr->numPoints <= 2)) {
+ if ((!linePtr->smooth) || (linePtr->numPoints < 3)) {
Tk_CanvasPsPath(interp, canvas, linePtr->coordPtr, linePtr->numPoints);
} else {
- if (linePtr->fillStipple == None) {
- TkMakeBezierPostscript(interp, canvas, linePtr->coordPtr,
- linePtr->numPoints);
+ if ((stipple == None) && linePtr->smooth->postscriptProc) {
+ linePtr->smooth->postscriptProc(interp, canvas,
+ linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps);
} else {
/*
* Special hack: Postscript printers don't appear to be able
@@ -1504,13 +2332,15 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
double *pointPtr;
int numPoints;
- numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;
+ numPoints = linePtr->smooth->coordProc(canvas, (double *) NULL,
+ linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
+ (double *) NULL);
pointPtr = staticPoints;
if (numPoints > MAX_STATIC_POINTS) {
pointPtr = (double *) ckalloc((unsigned)
(numPoints * 2 * sizeof(double)));
}
- numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr,
+ numPoints = linePtr->smooth->coordProc(canvas, linePtr->coordPtr,
linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,
pointPtr);
Tk_CanvasPsPath(interp, canvas, pointPtr, numPoints);
@@ -1524,8 +2354,6 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
* Set other line-drawing parameters and stroke out the line.
*/
- sprintf(buffer, "%d setlinewidth\n", linePtr->width);
- Tcl_AppendResult(interp, buffer, (char *) NULL);
style = "0 setlinecap\n";
if (linePtr->capStyle == CapRound) {
style = "1 setlinecap\n";
@@ -1540,17 +2368,10 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
style = "2 setlinejoin\n";
}
Tcl_AppendResult(interp, style, (char *) NULL);
- if (Tk_CanvasPsColor(interp, canvas, linePtr->fg) != TCL_OK) {
+
+ if (Tk_CanvasPsOutline(canvas, itemPtr,
+ &(linePtr->outline)) != TCL_OK) {
return TCL_ERROR;
- };
- if (linePtr->fillStipple != None) {
- Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, linePtr->fillStipple)
- != TCL_OK) {
- return TCL_ERROR;
- }
- } else {
- Tcl_AppendResult(interp, "stroke\n", (char *) NULL);
}
/*
@@ -1558,7 +2379,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
*/
if (linePtr->firstArrowPtr != NULL) {
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "grestore gsave\n",
(char *) NULL);
}
@@ -1568,7 +2389,7 @@ LineToPostscript(interp, canvas, itemPtr, prepass)
}
}
if (linePtr->lastArrowPtr != NULL) {
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL);
}
if (ArrowheadPostscript(interp, canvas, linePtr,
@@ -1610,10 +2431,28 @@ ArrowheadPostscript(interp, canvas, linePtr, arrowPtr)
double *arrowPtr; /* Pointer to first of five points
* describing arrowhead polygon. */
{
+ Pixmap stipple;
+ Tk_State state = linePtr->header.state;
+
+ if(state == TK_STATE_NULL) {
+ state = ((TkCanvas *)canvas)->canvas_state;
+ }
+
+ stipple = linePtr->outline.stipple;
+ if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)linePtr) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.activeStipple;
+ }
+ } else if (state==TK_STATE_DISABLED) {
+ if (linePtr->outline.activeStipple!=None) {
+ stipple = linePtr->outline.disabledStipple;
+ }
+ }
+
Tk_CanvasPsPath(interp, canvas, arrowPtr, PTS_IN_ARROW);
- if (linePtr->fillStipple != None) {
+ if (stipple != None) {
Tcl_AppendResult(interp, "clip ", (char *) NULL);
- if (Tk_CanvasPsStipple(interp, canvas, linePtr->fillStipple)
+ if (Tk_CanvasPsStipple(interp, canvas, stipple)
!= TCL_OK) {
return TCL_ERROR;
}