tkCanvUtil.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:48k
- /*
- * tkCanvUtil.c --
- *
- * This procedure contains a collection of utility procedures
- * used by the implementations of various canvas item types.
- *
- * Copyright (c) 1994 Sun Microsystems, Inc.
- * Copyright (c) 1994 Sun Microsystems, Inc.
- *
- * 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.10 2003/01/17 19:54:09 drh Exp $
- */
- #include "tkInt.h"
- #include "tkCanvas.h"
- #include "tkPort.h"
- #include <assert.h>
- /*
- *----------------------------------------------------------------------
- *
- * Tk_CanvasTkwin --
- *
- * Given a token for a canvas, this procedure returns the
- * widget that represents the canvas.
- *
- * Results:
- * The return value is a handle for the widget.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Tk_Window
- Tk_CanvasTkwin(canvas)
- Tk_Canvas canvas; /* Token for the canvas. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- return canvasPtr->tkwin;
- }
- /*
- *----------------------------------------------------------------------
- *
- * Tk_CanvasDrawableCoords --
- *
- * Given an (x,y) coordinate pair within a canvas, this procedure
- * returns the corresponding coordinates at which the point should
- * be drawn in the drawable used for display.
- *
- * Results:
- * There is no return value. The values at *drawableXPtr and
- * *drawableYPtr are filled in with the coordinates at which
- * x and y should be drawn. These coordinates are clipped
- * to fit within a "short", since this is what X uses in
- * most cases for drawing.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- Tk_CanvasDrawableCoords(canvas, x, y, drawableXPtr, drawableYPtr)
- Tk_Canvas canvas; /* Token for the canvas. */
- double x, y; /* Coordinates in canvas space. */
- short *drawableXPtr, *drawableYPtr; /* Screen coordinates are stored
- * here. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- double tmp;
- tmp = x - canvasPtr->drawableXOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- if (tmp > 32767) {
- *drawableXPtr = 32767;
- } else if (tmp < -32768) {
- *drawableXPtr = -32768;
- } else {
- *drawableXPtr = (short) tmp;
- }
- tmp = y - canvasPtr->drawableYOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- if (tmp > 32767) {
- *drawableYPtr = 32767;
- } else if (tmp < -32768) {
- *drawableYPtr = -32768;
- } else {
- *drawableYPtr = (short) tmp;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * Tk_CanvasWindowCoords --
- *
- * Given an (x,y) coordinate pair within a canvas, this procedure
- * returns the corresponding coordinates in the canvas's window.
- *
- * Results:
- * There is no return value. The values at *screenXPtr and
- * *screenYPtr are filled in with the coordinates at which
- * (x,y) appears in the canvas's window. These coordinates
- * are clipped to fit within a "short", since this is what X
- * uses in most cases for drawing.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- void
- Tk_CanvasWindowCoords(canvas, x, y, screenXPtr, screenYPtr)
- Tk_Canvas canvas; /* Token for the canvas. */
- double x, y; /* Coordinates in canvas space. */
- short *screenXPtr, *screenYPtr; /* Screen coordinates are stored
- * here. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- double tmp;
- tmp = x - canvasPtr->xOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- if (tmp > 32767) {
- *screenXPtr = 32767;
- } else if (tmp < -32768) {
- *screenXPtr = -32768;
- } else {
- *screenXPtr = (short) tmp;
- }
- tmp = y - canvasPtr->yOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- if (tmp > 32767) {
- *screenYPtr = 32767;
- } else if (tmp < -32768) {
- *screenYPtr = -32768;
- } else {
- *screenYPtr = (short) tmp;
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * Tk_CanvasGetCoord --
- *
- * 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
- * the interp's result.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
- int
- Tk_CanvasGetCoord(interp, canvas, string, doublePtr)
- Tcl_Interp *interp; /* Interpreter for error reporting. */
- Tk_Canvas canvas; /* Canvas to which coordinate applies. */
- CONST char *string; /* Describes coordinate (any screen
- * coordinate form may be used here). */
- double *doublePtr; /* Place to store converted coordinate. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- if (Tk_GetScreenMM(canvasPtr->interp, canvasPtr->tkwin, string,
- doublePtr) != TCL_OK) {
- return TCL_ERROR;
- }
- *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;
- }
- /*
- *----------------------------------------------------------------------
- *
- * Tk_CanvasSetStippleOrigin --
- *
- * This procedure sets the stipple origin in a graphics context
- * so that stipples drawn with the GC will line up with other
- * stipples previously drawn in the canvas.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The graphics context is modified.
- *
- *----------------------------------------------------------------------
- */
- void
- Tk_CanvasSetStippleOrigin(canvas, gc)
- 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. */
- {
- TkCanvas *canvasPtr = (TkCanvas *) canvas;
- XSetTSOrigin(canvasPtr->display, gc, -canvasPtr->drawableXOrigin,
- -canvasPtr->drawableYOrigin);
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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
- * information about the selection and insertion cursor for
- * a canvas widget. Items such as text items save the pointer
- * and use it to share access to the information with the generic
- * canvas code.
- *
- * Results:
- * The return value is a pointer to the structure holding text
- * information for the canvas. Most of the fields should not
- * be modified outside the generic canvas code; see the user
- * documentation for details.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- Tk_CanvasTextInfo *
- Tk_CanvasGetTextInfo(canvas)
- Tk_Canvas canvas; /* Token for the canvas widget. */
- {
- return &((TkCanvas *) canvas)->textInfo;
- }
- /*
- *--------------------------------------------------------------
- *
- * Tk_CanvasTagsParseProc --
- *
- * This procedure is invoked during option processing to handle
- * "-tags" options for canvas items.
- *
- * Results:
- * A standard Tcl return value.
- *
- * Side effects:
- * The tags for a given item get replaced by those indicated
- * in the value argument.
- *
- *--------------------------------------------------------------
- */
- int
- Tk_CanvasTagsParseProc(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 (list of tag
- * names). */
- char *widgRec; /* Pointer to record for item. */
- int offset; /* Offset into item (ignored). */
- {
- register Tk_Item *itemPtr = (Tk_Item *) widgRec;
- int argc, i;
- CONST char **argv;
- Tk_Uid *newPtr;
- /*
- * Break the value up into the individual tag names.
- */
- if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {
- return TCL_ERROR;
- }
- /*
- * Make sure that there's enough space in the item to hold the
- * tag names.
- */
- if (itemPtr->tagSpace < argc) {
- newPtr = (Tk_Uid *) ckalloc((unsigned) (argc * sizeof(Tk_Uid)));
- for (i = itemPtr->numTags-1; i >= 0; i--) {
- newPtr[i] = itemPtr->tagPtr[i];
- }
- if (itemPtr->tagPtr != itemPtr->staticTagSpace) {
- ckfree((char *) itemPtr->tagPtr);
- }
- itemPtr->tagPtr = newPtr;
- itemPtr->tagSpace = argc;
- }
- itemPtr->numTags = argc;
- for (i = 0; i < argc; i++) {
- itemPtr->tagPtr[i] = Tk_GetUid(argv[i]);
- }
- ckfree((char *) argv);
- return TCL_OK;
- }
- /*
- *--------------------------------------------------------------
- *
- * Tk_CanvasTagsPrintProc --
- *
- * This procedure is invoked by the Tk configuration code
- * to produce a printable string for the "-tags" configuration
- * option for canvas items.
- *
- * Results:
- * The return value is a string describing all the tags 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 *
- Tk_CanvasTagsPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Ignored. */
- Tk_Window tkwin; /* Window containing canvas widget. */
- char *widgRec; /* Pointer to record for item. */
- int offset; /* Ignored. */
- Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
- * information about how to reclaim
- * storage for return string. */
- {
- register Tk_Item *itemPtr = (Tk_Item *) widgRec;
- if (itemPtr->numTags == 0) {
- *freeProcPtr = (Tcl_FreeProc *) NULL;
- return "";
- }
- if (itemPtr->numTags == 1) {
- *freeProcPtr = (Tcl_FreeProc *) NULL;
- return (char *) itemPtr->tagPtr[0];
- }
- *freeProcPtr = TCL_DYNAMIC;
- return Tcl_Merge(itemPtr->numTags, (CONST 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;
- } else if (strncmp(value, tkBezierSmoothMethod.name, length) == 0) {
- /*
- * We need to do handle the built-in bezier method.
- */
- *smoothPtr = &tkBezierSmoothMethod;
- 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;
- CONST 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 *ptr;
- char *str = string;
- char *lptr = 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 setlinewidthn", width);
- Tcl_AppendResult(interp, string, (char *) NULL);
- if (dash->number > 10) {
- str = (char *)ckalloc((unsigned int) (1 + 4*dash->number));
- } else if (dash->number < -5) {
- str = (char *)ckalloc((unsigned int) (1 - 8*dash->number));
- lptr = (char *)ckalloc((unsigned int) (1 - 2*dash->number));
- }
- ptr = (char *) ((ABS(dash->number) > sizeof(char *)) ) ?
- dash->pattern.pt : dash->pattern.array;
- if (dash->number > 0) {
- char *ptr0 = ptr;
- sprintf(str, "[%d", *ptr++ & 0xff);
- i = dash->number-1;
- while (i--) {
- sprintf(str+strlen(str), " %d", *ptr++ & 0xff);
- }
- Tcl_AppendResult(interp, str, (char *)NULL);
- if (dash->number&1) {
- Tcl_AppendResult(interp, " ", str+1, (char *)NULL);
- }
- sprintf(str, "] %d setdashn", outline->offset);
- Tcl_AppendResult(interp, str, (char *)NULL);
- ptr = ptr0;
- } else if (dash->number < 0) {
- if ((i = DashConvert(lptr, ptr, -dash->number, width)) != 0) {
- char *lptr0 = lptr;
- sprintf(str, "[%d", *lptr++ & 0xff);
- while (--i) {
- sprintf(str+strlen(str), " %d", *lptr++ & 0xff);
- }
- Tcl_AppendResult(interp, str, (char *)NULL);
- sprintf(str, "] %d setdashn", outline->offset);
- Tcl_AppendResult(interp, str, (char *)NULL);
- lptr = lptr0;
- } else {
- Tcl_AppendResult(interp, "[] 0 setdashn", (char *)NULL);
- }
- } else {
- Tcl_AppendResult(interp, "[] 0 setdashn", (char *)NULL);
- }
- if (str != string) {
- ckfree(str);
- }
- if (lptr != pattern) {
- ckfree(lptr);
- }
- 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, "stroken", (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;
- }
- /*
- *----------------------------------------------------------------------
- *
- * translateAndAppendCoords --
- *
- * This is a helper routine for TkCanvTranslatePath() below.
- *
- * Given an (x,y) coordinate pair within a canvas, this procedure
- * computes the corresponding coordinates at which the point should
- * be drawn in the drawable used for display. Those coordinates are
- * then written into outArr[numOut*2] and outArr[numOut*2+1].
- *
- * Results:
- * There is no return value.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- static void
- translateAndAppendCoords(canvPtr, x, y, outArr, numOut)
- TkCanvas *canvPtr; /* The canvas. */
- double x, y; /* Coordinates in canvas space. */
- XPoint *outArr; /* Write results into this array */
- int numOut; /* Num of prior entries in outArr[] */
- {
- double tmp;
- tmp = x - canvPtr->drawableXOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- outArr[numOut].x = (short) tmp;
- tmp = y - canvPtr->drawableYOrigin;
- if (tmp > 0) {
- tmp += 0.5;
- } else {
- tmp -= 0.5;
- }
- outArr[numOut].y = (short) tmp;
- }
- /*
- *--------------------------------------------------------------
- *
- * TkCanvTranslatePath
- *
- * Translate a line or polygon path so that all vertices are
- * within a rectangle that is 1000 pixels larger than the total
- * size of the canvas window. This will prevent pixel coordinates
- * from overflowing the 16-bit integer size limitation imposed by
- * most windowing systems.
- *
- * coordPtr must point to an array of doubles, two doubles per
- * vertex. There are a total of numVertex vertices, or 2*numVertex
- * entries in coordPtr. The result vertices written into outArr
- * have their coordinate origin shifted to canvPtr->drawableXOrigin
- * by canvPtr->drawableYOrigin. There might be as many as 3 times
- * more output vertices than there are input vertices. The calling
- * function should allocate space accordingly.
- *
- * This routine limits the width and height of a canvas window
- * to 31767 pixels. At the highest resolution display devices
- * available today (210 ppi in Jan 2003) that's a window that is
- * over 13 feet wide and tall. Should be enough for the near
- * future.
- *
- * Results:
- * Clipped and translated path vertices are written into outArr[].
- * There might be as many as twice the vertices in outArr[] as there
- * are in coordPtr[]. The return value is the number of vertices
- * actually written into outArr[].
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------
- */
- int
- TkCanvTranslatePath (canvPtr, numVertex, coordArr, closedPath, outArr)
- TkCanvas *canvPtr; /* The canvas */
- int numVertex; /* Number of vertices specified by coordArr[] */
- double *coordArr; /* X and Y coordinates for each vertex */
- int closedPath; /* True if this is a closed polygon */
- XPoint *outArr; /* Write results here, if not NULL */
- {
- int numOutput = 0; /* Number of output coordinates */
- double lft, rgh; /* Left and right sides of the bounding box */
- double top, btm; /* Top and bottom sizes of the bounding box */
- double *tempArr; /* Temporary storage used by the clipper */
- double *a, *b, *t; /* Pointers to parts of the temporary storage */
- int i, j; /* Loop counters */
- int maxOutput; /* Maximum number of outputs that we will allow */
- double limit[4]; /* Boundries at which clipping occurs */
- double staticSpace[480]; /* Temp space from the stack */
- /*
- ** Constrain all vertices of the path to be within a box that is no
- ** larger than 32000 pixels wide or height. The top-left corner of
- ** this clipping box is 1000 pixels above and to the left of the top
- ** left corner of the window on which the canvas is displayed.
- **
- ** This means that a canvas will not display properly on a canvas
- ** window that is larger than 31000 pixels wide or high. That is not
- ** a problem today, but might someday become a factor for ultra-high
- ** resolutions displays.
- **
- ** The X11 protocol allows us (in theory) to expand the size of the
- ** clipping box to 32767 pixels. But we have found experimentally that
- ** XFree86 sometimes fails to draw lines correctly if they are longer
- ** than about 32500 pixels. So we have left a little margin in the
- ** size to mask that bug.
- */
- lft = canvPtr->xOrigin - 1000.0;
- top = canvPtr->yOrigin - 1000.0;
- rgh = lft + 32000.0;
- btm = top + 32000.0;
- /* Try the common case first - no clipping. Loop over the input
- ** coordinates and translate them into appropriate output coordinates.
- ** But if a vertex outside of the bounding box is seen, break out of
- ** the loop.
- **
- ** Most of the time, no clipping is needed, so this one loop is
- ** sufficient to do the translation.
- */
- for(i=0; i<numVertex; i++){
- double x, y;
- x = coordArr[i*2];
- y = coordArr[i*2+1];
- if( x<lft || x>rgh || y<top || y>btm ) break;
- translateAndAppendCoords(canvPtr, x, y, outArr, numOutput++);
- }
- if( i==numVertex ){
- assert( numOutput==numVertex );
- return numOutput;
- }
- /* If we reach this point, it means that some clipping is required.
- ** Begin by allocating some working storage - at least 6 times as much space
- ** as coordArr[] requires. Divide this space into two separate arrays
- ** a[] and b[]. Initialize a[] to be equal to coordArr[].
- */
- if( numVertex*12 <= sizeof(staticSpace)/sizeof(staticSpace[0]) ){
- tempArr = staticSpace;
- } else {
- tempArr = (double*)ckalloc( numVertex*12*sizeof(tempArr[0]) );
- }
- for(i=0; i<numVertex*2; i++){
- tempArr[i] = coordArr[i];
- }
- a = tempArr;
- b = &tempArr[numVertex*6];
- /* We will make four passes through the input data. On each pass,
- ** we copy the contents of a[] over into b[]. As we copy, we clip
- ** any line segments that extend to the right past xClip then we
- ** rotate the coordinate system 90 degrees clockwise. After each
- ** pass is complete, we interchange a[] and b[] in preparation for
- ** the next pass.
- **
- ** Each pass clips line segments that extend beyond a single side
- ** of the bounding box, and four passes rotate the coordinate system
- ** back to its original value. I'm not an expert on graphics
- ** algorithms, but I think this is called Cohen-Sutherland polygon
- ** clipping.
- **
- ** The limit[] array contains the xClip value used for each of the
- ** four passes.
- */
- limit[0] = rgh;
- limit[1] = -top;
- limit[2] = -lft;
- limit[3] = btm;
- /* This is the loop that makes the four passes through the data.
- */
- maxOutput = numVertex*3;
- for(j=0; j<4; j++){
- double xClip = limit[j];
- int inside = a[0]<xClip;
- double priorY = a[1];
- numOutput = 0;
- /* Clip everything to the right of xClip. Store the results in
- ** b[] rotated by 90 degrees clockwise.
- */
- for(i=0; i<numVertex; i++){
- double x = a[i*2];
- double y = a[i*2+1];
- if( x>=xClip ){
- /* The current vertex is to the right of xClip.
- */
- if( inside ){
- /* If the current vertex is to the right of xClip but
- ** the previous vertex was left of xClip, then draw a
- ** line segment from the previous vertex to until it
- ** intersects the vertical at xClip.
- */
- double x0, y0, yN;
- assert( i>0 );
- x0 = a[i*2-2];
- y0 = a[i*2-1];
- yN = y0 + (y - y0)*(xClip-x0)/(x-x0);
- b[numOutput*2] = -yN;
- b[numOutput*2+1] = xClip;
- numOutput++;
- assert( numOutput<=maxOutput );
- priorY = yN;
- inside = 0;
- }else if( i==0 ){
- /* If the first vertex is to the right of xClip, add
- ** a vertex that is the projection of the first vertex
- ** onto the vertical xClip line.
- */
- b[0] = -y;
- b[1] = xClip;
- numOutput = 1;
- priorY = y;
- }
- }else{
- /* The current vertex is to the left of xClip
- */
- if( !inside ){
- /* If the current vertex is on the left of xClip and
- ** one or more prior vertices where to the right, then
- ** we have to draw a line segment along xClip that extends
- ** from the spot where we first crossed from left to right
- ** to the spot where we cross back from right to left.
- */
- double x0, y0, yN;
- assert( i>0 );
- x0 = a[i*2-2];
- y0 = a[i*2-1];
- yN = y0 + (y - y0)*(xClip-x0)/(x-x0);
- if( yN!=priorY ){
- b[numOutput*2] = -yN;
- b[numOutput*2+1] = xClip;
- numOutput++;
- assert( numOutput<=maxOutput );
- }
- inside = 1;
- }
- b[numOutput*2] = -y;
- b[numOutput*2+1] = x;
- numOutput++;
- assert( numOutput<=maxOutput );
- }
- }
- /* Interchange a[] and b[] in preparation for the next pass.
- */
- t = a;
- a = b;
- b = t;
- numVertex = numOutput;
- }
- /* All clipping is now finished. Convert the coordinates from doubles
- ** into XPoints and translate the origin for the drawable.
- */
- for(i=0; i<numVertex; i++){
- translateAndAppendCoords(canvPtr, a[i*2], a[i*2+1], outArr, i);
- }
- if( tempArr!=staticSpace ){
- ckfree((char *) tempArr);
- }
- return numOutput;
- }