/*
* ptkCanvPoint.c --
*
* This file implements point items for canvas widgets.
*
* Copyright (c) 1991-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
* Copyright (c) 2002 Slaven Rezic.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: ptkCanvPoint.c,v 1.6 2004/08/08 16:37:06 eserte Exp $
*/
#include "tkPort.h"
#include "tkInt.h"
#include "tkCanvases.h"
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
# undef TkStateParseProc
# define TkStateParseProc Tk_StateParseProc
# undef TkStatePrintProc
# define TkStatePrintProc Tk_StatePrintProc
# define HAS_DASH_PATCH 1
# define CONST84
# undef CONST
# define CONST
#else
# undef HAS_DASH_PATCH
#endif
/*
* The structure below defines the record for each point item.
*/
typedef struct PointItem {
Tk_Item header; /* Generic stuff that's the same for all
* types. MUST BE FIRST IN STRUCTURE. */
Tk_Outline outline; /* Outline structure */
int capStyle; /* Cap style for point. */
double x, y; /* X- and y-coord of point */
} PointItem;
/*
* Prototypes for procedures defined in this file:
*/
static void ComputePointBbox _ANSI_ARGS_((Tk_Canvas canvas,
PointItem *pointPtr));
static int ConfigurePoint _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
CONST84 Tcl_Obj *CONST *objv, int flags));
static int CreatePoint _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, struct Tk_Item *itemPtr,
int argc, CONST84 Tcl_Obj *CONST *objv));
static void DeletePoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display));
static void DisplayPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, Display *display, Drawable dst,
int x, int y, int width, int height));
static int GetPointIndex _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
Tcl_Obj *obj, int *indexPtr));
static int PointCoords _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr,
int argc, CONST84 Tcl_Obj *CONST *objv));
static int PointToArea _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *rectPtr));
static double PointToPoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double *coordPtr));
static int PointToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
static void ScalePoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double originX, double originY,
double scaleX, double scaleY));
static void TranslatePoint _ANSI_ARGS_((Tk_Canvas canvas,
Tk_Item *itemPtr, double deltaX, double deltaY));
/*
* Information used for parsing configuration specs. If you change any
* of the default strings, be sure to change the corresponding default
* values in CreatePoint.
*/
static Tk_CustomOption stateOption = {
TkStateParseProc,
TkStatePrintProc, (ClientData) 2
};
static Tk_CustomOption tagsOption = {
Tk_CanvasTagsParseProc,
Tk_CanvasTagsPrintProc, (ClientData) NULL
};
static Tk_CustomOption tileOption = {
Tk_TileParseProc,
Tk_TilePrintProc, (ClientData) NULL
};
static Tk_CustomOption offsetOption = {
Tk_OffsetParseProc,
Tk_OffsetPrintProc,
(ClientData) (TK_OFFSET_RELATIVE|TK_OFFSET_INDEX)
};
static Tk_CustomOption pixelOption = {
Tk_PixelParseProc,
Tk_PixelPrintProc, (ClientData) NULL
};
static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_COLOR, "-activefill", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.activeColor),
TK_CONFIG_NULL_OK},
{TK_CONFIG_BITMAP, "-activestipple", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.activeStipple),
TK_CONFIG_NULL_OK},
#ifdef HAS_DASH_PATCH
{TK_CONFIG_CUSTOM, "-activetile", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.activeTile),
TK_CONFIG_NULL_OK, &tileOption},
#endif
{TK_CONFIG_CUSTOM, "-activewidth", NULL, NULL,
"0.0", Tk_Offset(PointItem, outline.activeWidth),
TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_CAP_STYLE, "-capstyle", NULL, NULL,
"round", Tk_Offset(PointItem, capStyle), TK_CONFIG_DONT_SET_DEFAULT},
{TK_CONFIG_COLOR, "-fill", NULL, NULL,
"black", Tk_Offset(PointItem, outline.color), TK_CONFIG_NULL_OK},
{TK_CONFIG_COLOR, "-disabledfill", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.disabledColor),
TK_CONFIG_NULL_OK},
{TK_CONFIG_BITMAP, "-disabledstipple", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.disabledStipple),
TK_CONFIG_NULL_OK},
#ifdef HAS_DASH_PATCH
{TK_CONFIG_CUSTOM, "-disabledtile", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.disabledTile),
TK_CONFIG_NULL_OK, &tileOption},
#endif
{TK_CONFIG_CUSTOM, "-disabledwidth", NULL, NULL,
"0.0", Tk_Offset(PointItem, outline.disabledWidth),
TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_CUSTOM, "-offset", NULL, NULL,
"0 0", Tk_Offset(PointItem, outline.tsoffset),
TK_CONFIG_DONT_SET_DEFAULT, &offsetOption},
{TK_CONFIG_CUSTOM, "-state", NULL, NULL,
NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
&stateOption},
{TK_CONFIG_BITMAP, "-stipple", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.stipple),
TK_CONFIG_NULL_OK},
{TK_CONFIG_CUSTOM, "-tags", NULL, NULL,
NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
#ifdef HAS_DASH_PATCH
{TK_CONFIG_CUSTOM, "-tile", NULL, NULL,
NULL, Tk_Offset(PointItem, outline.tile),
TK_CONFIG_NULL_OK, &tileOption},
#endif
{TK_CONFIG_CUSTOM, "-width", NULL, NULL,
"1.0", Tk_Offset(PointItem, outline.width),
TK_CONFIG_DONT_SET_DEFAULT, &pixelOption},
{TK_CONFIG_CALLBACK, "-updatecommand", NULL, NULL,
NULL, Tk_Offset(Tk_Item, updateCmd), TK_CONFIG_NULL_OK},
{TK_CONFIG_END, NULL, NULL, NULL,
NULL, 0, 0}
};
/*
* The structures below defines the line item type by means
* of procedures that can be invoked by generic item code.
*/
Tk_ItemType ptkCanvPointType = {
"point", /* name */
sizeof(PointItem), /* itemSize */
CreatePoint, /* createProc */
configSpecs, /* configSpecs */
ConfigurePoint, /* configureProc */
PointCoords, /* coordProc */
DeletePoint, /* deleteProc */
DisplayPoint, /* displayProc */
TK_CONFIG_OBJS, /* flags, no TK_ITEM_VISITOR_SUPPORT */
PointToPoint, /* pointProc */
PointToArea, /* areaProc */
PointToPostscript, /* postscriptProc */
ScalePoint, /* scaleProc */
TranslatePoint, /* translateProc */
NULL,// GetPointIndex, /* indexProc */
(Tk_ItemCursorProc *) NULL, /* icursorProc */
(Tk_ItemSelectionProc *) NULL, /* selectionProc */
(Tk_ItemInsertProc *) NULL, /* insertProc */
(Tk_ItemDCharsProc *) NULL, /* dTextProc */
(Tk_ItemType *) NULL, /* nextPtr */
(Tk_ItemBboxProc *) ComputePointBbox,/* bboxProc */
(Tk_VisitorItemProc *) NULL, /* acceptProc */
(Tk_ItemGetCoordProc *) NULL, /* getCoordProc */
(Tk_ItemSetCoordProc *) NULL /* setCoordProc */
};
/*
*--------------------------------------------------------------
*
* CreatePoint --
*
* This procedure is invoked to create a new point item in
* a canvas.
*
* Results:
* A standard Tcl return value. If an error occurred in
* creating the item, then an error message is left in
* Tcl_GetResult(interp); in this case itemPtr is left uninitialized,
* so it can be safely freed by the caller.
*
* Side effects:
* A new point item is created.
*
*--------------------------------------------------------------
*/
static int
CreatePoint(interp, canvas, itemPtr, argc, objv)
Tcl_Interp *interp; /* Interpreter for error reporting. */
Tk_Canvas canvas; /* Canvas to hold new item. */
Tk_Item *itemPtr; /* Record to hold new item; header
* has been initialized by caller. */
int argc; /* Number of arguments in objv. */
CONST84 Tcl_Obj *CONST *objv; /* Arguments describing point. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
int i;
/*
* 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(&(pointPtr->outline));
pointPtr->capStyle = CapRound;
/*
* Count the number of points and then parse them into a point
* array. Leading arguments are assumed to be points if they
* start with a digit or a minus sign followed by a digit.
*/
for (i = 0; i < argc; i++) {
char *arg = Tcl_GetStringFromObj(objv[i], NULL);
if ((arg[0] == '-') && (arg[1] >= 'a')
&& (arg[1] <= 'z')) {
break;
}
}
if (i && (PointCoords(interp, canvas, itemPtr, i, objv) != TCL_OK)) {
goto error;
}
if (ConfigurePoint(interp, canvas, itemPtr, argc-i, objv+i, 0) == TCL_OK) {
return TCL_OK;
}
error:
DeletePoint(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
return TCL_ERROR;
}
/*
*--------------------------------------------------------------
*
* PointCoords --
*
* This procedure is invoked to process the "coords" widget
* command on points. See the user documentation for details
* on what it does.
*
* Results:
* Returns TCL_OK or TCL_ERROR, and sets Tcl_GetResult(interp).
*
* Side effects:
* The coordinates for the given item may be changed.
*
*--------------------------------------------------------------
*/
static int
PointCoords(interp, canvas, itemPtr, argc, objv)
Tcl_Interp *interp; /* Used for error reporting. */
Tk_Canvas canvas; /* Canvas containing item. */
Tk_Item *itemPtr; /* Item whose coordinates are to be
* read or modified. */
int argc; /* Number of coordinates supplied in
* objv. Should be 2. */
CONST84 Tcl_Obj *CONST *objv; /* Array of coordinates: x1, y1,
* x2, y2, ... */
{
PointItem *pointPtr = (PointItem *) itemPtr;
if (argc == 0) {
Tcl_Obj *subobj, *obj = Tcl_NewObj();
subobj = Tcl_NewDoubleObj(pointPtr->x);
Tcl_ListObjAppendElement(interp, obj, subobj);
subobj = Tcl_NewDoubleObj(pointPtr->y);
Tcl_ListObjAppendElement(interp, obj, subobj);
Tcl_SetObjResult(interp, obj);
return TCL_OK;
}
//XXX kann weg?
/* if (argc == 1) { */
/* if (Tcl_ListObjGetElements(interp, objv[0], &argc, &objv) != TCL_OK) { */
/* return TCL_ERROR; */
/* } */
/* } */
if (argc != 2) {
Tcl_AppendResult(interp,
"not two coordinates specified for point",
NULL);
return TCL_ERROR;
} else {
if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[0],
&(pointPtr->x)) != TCL_OK) {
return TCL_ERROR;
}
if (Tk_CanvasGetCoordFromObj(interp, canvas, objv[1],
&(pointPtr->y)) != TCL_OK) {
return TCL_ERROR;
}
ComputePointBbox(canvas, pointPtr);
}
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* ConfigurePoint --
*
* This procedure is invoked to configure various aspects
* of a point item such as its background color.
*
* Results:
* A standard Tcl result code. If an error occurs, then
* an error message is left in Tcl_GetResult(interp).
*
* Side effects:
* Configuration information, such as colors and stipple
* patterns, may be set for itemPtr.
*
*--------------------------------------------------------------
*/
static int
ConfigurePoint(interp, canvas, itemPtr, argc, objv, flags)
Tcl_Interp *interp; /* Used for error reporting. */
Tk_Canvas canvas; /* Canvas containing itemPtr. */
Tk_Item *itemPtr; /* Point item to reconfigure. */
int argc; /* Number of elements in objv. */
CONST84 Tcl_Obj *CONST *objv; /* Arguments describing things to configure. */
int flags; /* Flags to pass to Tk_ConfigureWidget. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
XGCValues gcValues;
GC newGC;
unsigned long mask;
Tk_Window tkwin;
Tk_State state;
tkwin = Tk_CanvasTkwin(canvas);
if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, objv,
(char *) pointPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
return TCL_ERROR;
}
/*
* A few of the options require additional processing, such as
* graphics contexts.
*/
state = Tk_GetItemState(canvas, itemPtr);
if (pointPtr->outline.activeWidth > pointPtr->outline.width ||
#ifdef HAS_DASH_PATCH
pointPtr->outline.activeTile != None ||
#endif
pointPtr->outline.activeColor != NULL ||
pointPtr->outline.activeStipple != None) {
itemPtr->redraw_flags |= TK_ITEM_STATE_DEPENDANT;
} else {
itemPtr->redraw_flags &= ~TK_ITEM_STATE_DEPENDANT;
}
mask = Tk_ConfigOutlineGC(&gcValues, canvas, itemPtr,
&(pointPtr->outline));
if (mask) {
gcValues.cap_style = pointPtr->capStyle;
mask |= GCCapStyle;
newGC = Tk_GetGC(tkwin, mask, &gcValues);
gcValues.line_width = 0;
} else {
newGC = None;
}
if (pointPtr->outline.gc != None) {
Tk_FreeGC(Tk_Display(tkwin), pointPtr->outline.gc);
}
pointPtr->outline.gc = newGC;
/*
* Recompute bounding box for point.
*/
ComputePointBbox(canvas, pointPtr);
return TCL_OK;
}
/*
*--------------------------------------------------------------
*
* DeletePoint --
*
* This procedure is called to clean up the data structure
* associated with a point item.
*
* Results:
* None.
*
* Side effects:
* Resources associated with itemPtr are released.
*
*--------------------------------------------------------------
*/
static void
DeletePoint(canvas, itemPtr, display)
Tk_Canvas canvas; /* Info about overall canvas widget. */
Tk_Item *itemPtr; /* Item that is being deleted. */
Display *display; /* Display containing window for
* canvas. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
Tk_DeleteOutline(display, &(pointPtr->outline));
}
/*
*--------------------------------------------------------------
*
* ComputePointBbox --
*
* This procedure is invoked to compute the bounding box of
* all the pixels that may be drawn as part of a point.
*
* Results:
* None.
*
* Side effects:
* The fields x1, y1, x2, and y2 are updated in the header
* for itemPtr.
*
*--------------------------------------------------------------
*/
static void
ComputePointBbox(canvas, pointPtr)
Tk_Canvas canvas; /* Canvas that contains item. */
PointItem *pointPtr; /* Item whose bbox is to be
* recomputed. */
{
int intWidth;
double width;
Tk_State state = Tk_GetItemState(canvas, &pointPtr->header);
Tk_TSOffset *tsoffset;
if (state==TK_STATE_HIDDEN) {
pointPtr->header.x1 = -1;
pointPtr->header.x2 = -1;
pointPtr->header.y1 = -1;
pointPtr->header.y2 = -1;
return;
}
width = pointPtr->outline.width;
if (((TkCanvas *)canvas)->currentItemPtr == (Tk_Item *)pointPtr) {
if (pointPtr->outline.activeWidth>width) {
width = pointPtr->outline.activeWidth;
}
} else if (state==TK_STATE_DISABLED) {
if (pointPtr->outline.disabledWidth>0) {
width = pointPtr->outline.disabledWidth;
}
}
pointPtr->header.x1 = pointPtr->header.x2 = (int) pointPtr->x;
pointPtr->header.y1 = pointPtr->header.y2 = (int) pointPtr->y;
if (width < 1.0) {
width = 1.0;
}
intWidth = (int) (width + 0.5);
pointPtr->header.x1 -= intWidth - 1;
pointPtr->header.x2 += intWidth + 1;
pointPtr->header.y1 -= intWidth - 1;
pointPtr->header.y2 += intWidth + 1;
}
/*
*--------------------------------------------------------------
*
* DisplayPoint --
*
* This procedure is invoked to draw a point item in a given
* drawable.
*
* Results:
* None.
*
* Side effects:
* ItemPtr is drawn in drawable using the transformation
* information in canvas.
*
*--------------------------------------------------------------
*/
static void
DisplayPoint(canvas, itemPtr, display, drawable, x, y, width, height)
Tk_Canvas canvas; /* Canvas that contains item. */
Tk_Item *itemPtr; /* Item to be displayed. */
Display *display; /* Display on which to draw item. */
Drawable drawable; /* Pixmap or window in which to draw
* item. */
int x, y, width, height; /* Describes region of canvas that
* must be redisplayed (not used). */
{
PointItem *pointPtr = (PointItem *) itemPtr;
XPoint staticPoint;
double pointwidth;
int intwidth;
Tk_State state = Tk_GetItemState(canvas, itemPtr);
#ifdef HAS_DASH_PATCH
Tk_Tile tile = pointPtr->outline.tile;
#endif
Pixmap stipple = pointPtr->outline.stipple;
if (pointPtr->outline.gc==None) {
return;
}
pointwidth = pointPtr->outline.width;
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
if (pointPtr->outline.activeWidth>pointwidth) {
pointwidth = pointPtr->outline.activeWidth;
}
#ifdef HAS_DASH_PATCH
if (pointPtr->outline.activeTile!=NULL) {
tile = pointPtr->outline.activeTile;
}
#endif
if (pointPtr->outline.activeStipple!=None) {
stipple = pointPtr->outline.activeStipple;
}
} else if (state==TK_STATE_DISABLED) {
if (pointPtr->outline.disabledWidth>pointwidth) {
pointwidth = pointPtr->outline.disabledWidth;
}
#ifdef HAS_DASH_PATCH
if (pointPtr->outline.disabledTile!=NULL) {
tile = pointPtr->outline.disabledTile;
}
#endif
if (pointPtr->outline.disabledStipple!=None) {
stipple = pointPtr->outline.disabledStipple;
}
}
Tk_CanvasDrawableCoords(canvas, pointPtr->x, pointPtr->y,
&(staticPoint.x), &(staticPoint.y));
/*
* Display point. If we're stippling, then modify the stipple offset
* in the GC. Be sure to reset the offset when done, since the
* GC is supposed to be read-only.
*/
//XXX heißt das, stipple etc. wird bei lines eh nur im arrow gemalt?
/* if (Tk_ChangeOutlineGC(canvas, itemPtr, &(pointPtr->outline))) { */
/* Tk_CanvasSetOffset(canvas, pointPtr->arrowGC, &pointPtr->outline.tsoffset); */
/* } */
intwidth = (int) (pointwidth + 0.5);
XFillArc(display, drawable, pointPtr->outline.gc, staticPoint.x - intwidth/2,
staticPoint.y - intwidth/2, intwidth+1, intwidth+1, 0, 64*360);
}
/*
*--------------------------------------------------------------
*
* PointToPoint --
*
* Computes the distance from a given point to another given
* point, in canvas units.
*
* Results:
* The return value is 0 if the point whose x and y coordinates
* are pointPtr[0] and pointPtr[1] is inside the point. If the
* point isn't inside the point then the return value is the
* distance from the point to the other point.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
/* ARGSUSED */
static double
PointToPoint(canvas, itemPtr, otherPointPtr)
Tk_Canvas canvas; /* Canvas containing item. */
Tk_Item *itemPtr; /* Item to check against point. */
double *otherPointPtr; /* Pointer to x and y coordinates. */
{
Tk_State state = Tk_GetItemState(canvas, itemPtr);
PointItem *pointPtr = (PointItem *) itemPtr;
double bestDist, width;
bestDist = 1.0e36;
width = pointPtr->outline.width;
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
if (pointPtr->outline.activeWidth>width) {
width = pointPtr->outline.activeWidth;
}
} else if (state==TK_STATE_DISABLED) {
if (pointPtr->outline.disabledWidth>0) {
width = pointPtr->outline.disabledWidth;
}
}
if (width < 1.0) {
width = 1.0;
}
if (itemPtr->state==TK_STATE_HIDDEN) {
return bestDist;
} else {
bestDist = hypot(pointPtr->x - otherPointPtr[0], pointPtr->y - otherPointPtr[1])
- width/2.0;
if (bestDist < 0) bestDist = 0;
return bestDist;
}
}
/*
*--------------------------------------------------------------
*
* PointToArea --
*
* This procedure is called to determine whether an item
* lies entirely inside, entirely outside, or overlapping
* a given rectangular area.
*
* Results:
* -1 is returned if the item is entirely outside the
* area, 0 if it overlaps, and 1 if it is entirely
* inside the given area.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
/* ARGSUSED */
static int
PointToArea(canvas, itemPtr, rectPtr)
Tk_Canvas canvas; /* Canvas containing item. */
Tk_Item *itemPtr; /* Item to check against point. */
double *rectPtr;
{
PointItem *pointPtr = (PointItem *) itemPtr;
double radius, width;
Tk_State state = Tk_GetItemState(canvas, itemPtr);
width = pointPtr->outline.width;
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
if (pointPtr->outline.activeWidth>width) {
width = pointPtr->outline.activeWidth;
}
} else if (state==TK_STATE_DISABLED) {
if (pointPtr->outline.disabledWidth>0) {
width = pointPtr->outline.disabledWidth;
}
}
radius = (width+1.0)/2.0;
if (state==TK_STATE_HIDDEN) {
return -1;
} else {
double oval[4];
oval[0] = pointPtr->x-radius;
oval[1] = pointPtr->y-radius;
oval[2] = pointPtr->x+radius;
oval[3] = pointPtr->y+radius;
return TkOvalToArea(oval, rectPtr);
}
}
/*
*--------------------------------------------------------------
*
* ScalePoint --
*
* This procedure is invoked to rescale a point item.
*
* Results:
* None.
*
* Side effects:
* The point referred to by itemPtr is rescaled so that the
* following transformation is applied to its coordinates:
* x' = originX + scaleX*(x-originX)
* y' = originY + scaleY*(y-originY)
*
*--------------------------------------------------------------
*/
static void
ScalePoint(canvas, itemPtr, originX, originY, scaleX, scaleY)
Tk_Canvas canvas; /* Canvas containing point. */
Tk_Item *itemPtr; /* Point to be scaled. */
double originX, originY; /* Origin about which to scale rect. */
double scaleX; /* Amount to scale in X direction. */
double scaleY; /* Amount to scale in Y direction. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
pointPtr->x = originX + scaleX*(pointPtr->x - originX);
pointPtr->y = originY + scaleY*(pointPtr->y - originY);
ComputePointBbox(canvas, pointPtr);
}
#if 0
/*
*--------------------------------------------------------------
*
* 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
* Tcl_GetResult(interp).
*
* 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. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
int length;
char *string;
int i;
double x ,y, bestDist, dist, *coordPtr;
char *end, *p;
Tcl_Obj **objv;
if (Tcl_ListObjGetElements(interp, obj, &i, &objv) == TCL_OK && i == 2
&& Tcl_GetDoubleFromObj(interp, objv[0], &x) == TCL_OK
&& Tcl_GetDoubleFromObj(interp, objv[1], &y) == TCL_OK) {
goto doxy;
}
string = Tcl_GetStringFromObj(obj, &length);
if (string[0] == 'e') {
if (strncmp(string, "end", length) == 0) {
*indexPtr = 2*pointPtr->numPoints;
} else {
badIndex:
/*
* Some of the paths here leave messages in Tcl_GetResult(interp),
* so we have to clear it out before storing our own message.
*/
Tcl_SetResult(interp, NULL, TCL_STATIC);
Tcl_AppendResult(interp, "bad index \"", string, "\"",
NULL);
return TCL_ERROR;
}
} else if (string[0] == '@') {
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;
}
doxy:
bestDist = 1.0e36;
coordPtr = pointPtr->coordPtr;
*indexPtr = 0;
for(i=0; i<pointPtr->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*pointPtr->numPoints)) {
*indexPtr = (2*pointPtr->numPoints);
}
}
return TCL_OK;
}
#endif
/*
*--------------------------------------------------------------
*
* TranslatePoint --
*
* This procedure is called to move a point by a given amount.
*
* Results:
* None.
*
* Side effects:
* The position of the point is offset by (xDelta, yDelta), and
* the bounding box is updated in the generic part of the item
* structure.
*
*--------------------------------------------------------------
*/
static void
TranslatePoint(canvas, itemPtr, deltaX, deltaY)
Tk_Canvas canvas; /* Canvas containing item. */
Tk_Item *itemPtr; /* Item that is being moved. */
double deltaX, deltaY; /* Amount by which item is to be
* moved. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
pointPtr->x += deltaX;
pointPtr->y += deltaY;
ComputePointBbox(canvas, pointPtr);
}
/*
*--------------------------------------------------------------
*
* PointToPostscript --
*
* This procedure is called to generate Postscript for
* point items.
*
* Results:
* The return value is a standard Tcl result. If an error
* occurs in generating Postscript then an error message is
* left in Tcl_GetResult(interp), replacing whatever used
* to be there. If no error occurs, then Postscript for the
* item is appended to the result.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static int
PointToPostscript(interp, canvas, itemPtr, prepass)
Tcl_Interp *interp; /* Leave Postscript or error message
* here. */
Tk_Canvas canvas; /* Information about overall canvas. */
Tk_Item *itemPtr; /* Item for which Postscript is
* wanted. */
int prepass; /* 1 means this is a prepass to
* collect font information; 0 means
* final Postscript is being created. */
{
PointItem *pointPtr = (PointItem *) itemPtr;
char buffer[200];
char *style;
double width;
XColor *color;
Pixmap stipple;
Tk_State state = Tk_GetItemState(canvas, itemPtr);
width = pointPtr->outline.width;
color = pointPtr->outline.color;
stipple = pointPtr->outline.stipple;
if (((TkCanvas *)canvas)->currentItemPtr == itemPtr) {
if (pointPtr->outline.activeWidth>width) {
width = pointPtr->outline.activeWidth;
}
if (pointPtr->outline.activeColor!=NULL) {
color = pointPtr->outline.activeColor;
}
if (pointPtr->outline.activeStipple!=None) {
stipple = pointPtr->outline.activeStipple;
}
} else if (state==TK_STATE_DISABLED) {
if (pointPtr->outline.disabledWidth>0) {
width = pointPtr->outline.disabledWidth;
}
if (pointPtr->outline.disabledColor!=NULL) {
color = pointPtr->outline.disabledColor;
}
if (pointPtr->outline.disabledStipple!=None) {
stipple = pointPtr->outline.disabledStipple;
}
}
if (color == NULL) {
return TCL_OK;
}
sprintf(buffer, "%.15g %.15g translate %.15g %.15g",
pointPtr->x, Tk_CanvasPsY(canvas, pointPtr->y),
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",
NULL);
if (Tk_CanvasPsColor(interp, canvas, color) != TCL_OK) {
return TCL_ERROR;
}
if (stipple != None) {
Tcl_AppendResult(interp, "clip ", NULL);
if (Tk_CanvasPsStipple(interp, canvas, stipple) != TCL_OK) {
return TCL_ERROR;
}
} else {
Tcl_AppendResult(interp, "fill\n", NULL);
}
return TCL_OK;
}
/* Local variables: */
/* c-basic-offset: 4 */
/* End. */