📄 tkcanvline.c
字号:
poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight); poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight); poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight); /* * Polygon done. Now move the first point towards the second so * that the corners at the end of the line are inside the * arrowhead. */ linePtr->coordPtr[0] = poly[0] - backup*cosTheta; linePtr->coordPtr[1] = poly[1] - backup*sinTheta; } /* * Similar arrowhead calculation for the last point of the line. */ if (linePtr->arrow != firstUid) { coordPtr = linePtr->coordPtr + 2*(linePtr->numPoints-2); poly = linePtr->lastArrowPtr; if (poly == NULL) { poly = (double *) ckalloc((unsigned) (2*PTS_IN_ARROW*sizeof(double))); poly[0] = poly[10] = coordPtr[2]; poly[1] = poly[11] = coordPtr[3]; linePtr->lastArrowPtr = poly; } dx = poly[0] - coordPtr[0]; dy = poly[1] - coordPtr[1]; length = hypot(dx, dy); if (length == 0) { sinTheta = cosTheta = 0.0; } else { sinTheta = dy/length; cosTheta = dx/length; } vertX = poly[0] - linePtr->arrowShapeA*cosTheta; vertY = poly[1] - linePtr->arrowShapeA*sinTheta; temp = shapeC*sinTheta; poly[2] = poly[0] - linePtr->arrowShapeB*cosTheta + temp; poly[8] = poly[2] - 2*temp; temp = shapeC*cosTheta; poly[3] = poly[1] - linePtr->arrowShapeB*sinTheta - temp; poly[9] = poly[3] + 2*temp; poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight); poly[5] = poly[3]*fracHeight + vertY*(1.0-fracHeight); poly[6] = poly[8]*fracHeight + vertX*(1.0-fracHeight); poly[7] = poly[9]*fracHeight + vertY*(1.0-fracHeight); coordPtr[2] = poly[0] - backup*cosTheta; coordPtr[3] = poly[1] - backup*sinTheta; } return TCL_OK;}/* *-------------------------------------------------------------- * * LineToPostscript -- * * This procedure is called to generate Postscript for * line items. * * Results: * The return value is a standard Tcl result. If an error * occurs in generating Postscript then an error message is * left in canvasPtr->interp->result, replacing whatever used * to be there. If no error occurs, then Postscript for the * item is appended to the result. * * Side effects: * None. * *-------------------------------------------------------------- */static intLineToPostscript(canvasPtr, itemPtr, psInfoPtr) Tk_Canvas *canvasPtr; /* Information about overall canvas. */ Tk_Item *itemPtr; /* Item for which Postscript is * wanted. */ Tk_PostscriptInfo *psInfoPtr; /* Information about the Postscript; * must be passed back to Postscript * utility procedures. */{ register LineItem *linePtr = (LineItem *) itemPtr; char buffer[200]; char *style; if (linePtr->fg == 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) { TkCanvPsPath(canvasPtr->interp, linePtr->coordPtr, linePtr->numPoints, psInfoPtr); } else { if (linePtr->fillStipple == None) { TkMakeBezierPostscript(canvasPtr->interp, linePtr->coordPtr, linePtr->numPoints, psInfoPtr); } else { /* * Special hack: Postscript printers don't appear to be able * to turn a path drawn with "curveto"s into a clipping path * without exceeding resource limits, so TkMakeBezierPostscript * won't work for stippled curves. Instead, generate all of * the intermediate points here and output them into the * Postscript file with "lineto"s instead. */ double staticPoints[2*MAX_STATIC_POINTS]; double *pointPtr; int numPoints; numPoints = 1 + linePtr->numPoints*linePtr->splineSteps; pointPtr = staticPoints; if (numPoints > MAX_STATIC_POINTS) { pointPtr = (double *) ckalloc((unsigned) (numPoints * 2 * sizeof(double))); } numPoints = TkMakeBezierCurve(canvasPtr, linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL, pointPtr); TkCanvPsPath(canvasPtr->interp, pointPtr, numPoints, psInfoPtr); if (pointPtr != staticPoints) { ckfree((char *) pointPtr); } } } /* * Set other line-drawing parameters and stroke out the line. */ sprintf(buffer, "%d setlinewidth\n", linePtr->width); Tcl_AppendResult(canvasPtr->interp, buffer, (char *) NULL); style = "0 setlinecap\n"; if (linePtr->capStyle == CapRound) { style = "1 setlinecap\n"; } else if (linePtr->capStyle == CapProjecting) { style = "2 setlinecap\n"; } Tcl_AppendResult(canvasPtr->interp, style, (char *) NULL); style = "0 setlinejoin\n"; if (linePtr->joinStyle == JoinRound) { style = "1 setlinejoin\n"; } else if (linePtr->joinStyle == JoinBevel) { style = "2 setlinejoin\n"; } Tcl_AppendResult(canvasPtr->interp, style, (char *) NULL); if (TkCanvPsColor(canvasPtr, psInfoPtr, linePtr->fg) != TCL_OK) { return TCL_ERROR; }; if (linePtr->fillStipple != None) { if (TkCanvPsStipple(canvasPtr, psInfoPtr, linePtr->fillStipple, 0) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendResult(canvasPtr->interp, "stroke\n", (char *) NULL); } /* * Output polygons for the arrowheads, if there are any. */ if (linePtr->firstArrowPtr != NULL) { if (ArrowheadPostscript(canvasPtr, linePtr, linePtr->firstArrowPtr, psInfoPtr) != TCL_OK) { return TCL_ERROR; } } if (linePtr->lastArrowPtr != NULL) { if (ArrowheadPostscript(canvasPtr, linePtr, linePtr->lastArrowPtr, psInfoPtr) != TCL_OK) { return TCL_ERROR; } } return TCL_OK;}/* *-------------------------------------------------------------- * * ArrowheadPostscript -- * * This procedure is called to generate Postscript for * an arrowhead for a line item. * * Results: * The return value is a standard Tcl result. If an error * occurs in generating Postscript then an error message is * left in canvasPtr->interp->result, replacing whatever used * to be there. If no error occurs, then Postscript for the * arrowhead is appended to the result. * * Side effects: * None. * *-------------------------------------------------------------- */static intArrowheadPostscript(canvasPtr, linePtr, arrowPtr, psInfoPtr) Tk_Canvas *canvasPtr; /* Information about overall canvas. */ LineItem *linePtr; /* Line item for which Postscript is * being generated. */ double *arrowPtr; /* Pointer to first of five points * describing arrowhead polygon. */ Tk_PostscriptInfo *psInfoPtr; /* Information about the Postscript; * must be passed back to Postscript * utility procedures. */{ TkCanvPsPath(canvasPtr->interp, arrowPtr, PTS_IN_ARROW, psInfoPtr); if (linePtr->fillStipple != None) { if (TkCanvPsStipple(canvasPtr, psInfoPtr, linePtr->fillStipple, 1) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendResult(canvasPtr->interp, "fill\n", (char *) NULL); } return TCL_OK;}#include "feather.h"void FeatherConfigTags ARGS(( Tk_Item *itemPtr, int ntags, Tk_Uid *tagList ));/* FeatherCreateLine() Create a line on a Tk canvas. keeppoints - Set to nonzero if the point array was allocated with malloc() and Feather_CreateLine can take ownership. The calling routine should not modify the array any more. Feather_LineInfo will free the array when finished with it. Set keeppoints to zero if Feather_CreateLine should make its own copy of the point list.*/int FeatherCreateLine( canvasPtr, itemPtr, npoints, points, keeppoints, lineInfo, lineMask )Tk_Canvas *canvasPtr;Tk_Item *itemPtr;int npoints;double *points;int keeppoints;Feather_LineInfo *lineInfo;unsigned long lineMask;{ LineItem *linePtr; /* only the arrow, smooth, and fg options have been tested */ if (npoints < 2) { Tcl_AppendResult( canvasPtr->interp, "too few points for line: must have at least 2", (char *) NULL); return TCL_ERROR; } linePtr = (LineItem*)itemPtr; linePtr->canvasPtr = canvasPtr; linePtr->width = 1; linePtr->fg = None; linePtr->fillStipple = None; linePtr->capStyle = CapButt; linePtr->joinStyle = JoinRound; linePtr->gc = None; /* set unset static vars */ if (noneUid == NULL) { noneUid = Tk_GetUid( "none" ); firstUid = Tk_GetUid( "first" ); lastUid = Tk_GetUid( "last" ); bothUid = Tk_GetUid( "both" ); } linePtr->arrow = noneUid; linePtr->arrowShapeA = 8.0; linePtr->arrowShapeB = 10.0; linePtr->arrowShapeC = 3.0; linePtr->firstArrowPtr = NULL; linePtr->lastArrowPtr = NULL; linePtr->smooth = 0; linePtr->splineSteps = 12; if (keeppoints) { /* don't copy the point list, just usurp the pointer */ linePtr->coordPtr = points; } else { /* make a copy of the point list */ linePtr->coordPtr = (double*)ckalloc( sizeof(double) * npoints * 2 ); memcpy( linePtr->coordPtr, points, sizeof(double) * npoints * 2 ); } linePtr->numPoints = npoints; if (FeatherConfigureLine( canvasPtr, itemPtr, lineInfo, lineMask ) != TCL_OK) { DeleteLine( canvasPtr, itemPtr ); return TCL_ERROR; } return TCL_OK;}int FeatherConfigureLine( canvasPtr, itemPtr, lineInfo, lineMask )Tk_Canvas *canvasPtr;Tk_Item *itemPtr;Feather_LineInfo *lineInfo;unsigned long lineMask;{ static Feather_Color blackColor = 0; LineItem *linePtr; XGCValues gcValues; unsigned long mask; if (!blackColor) { blackColor = Feather_GetColor( canvasPtr->interp, canvasPtr->tkwin, None, Tk_GetUid( "black" ) ); } linePtr = (LineItem*)itemPtr; if (lineMask & FEATHER_ARROWSHAPE) { linePtr->arrowShapeA = lineInfo->arrowShapeA; linePtr->arrowShapeB = lineInfo->arrowShapeB; linePtr->arrowShapeC = lineInfo->arrowShapeC; } /* CapButt, CapProjecting, or CapRound */ if (lineMask & FEATHER_CAPSTYLE) { linePtr->capStyle = lineInfo->capStyle; } /* one of JoinBevel, JoinMiter, or JoinRound */ if (lineMask & FEATHER_JOINSTYLE) { linePtr->joinStyle = lineInfo->joinStyle; } if (lineMask & FEATHER_SMOOTH) { linePtr->smooth = lineInfo->smooth; } if (lineMask & FEATHER_SPLINESTEPS) { linePtr->splineSteps = lineInfo->splineSteps; } if (lineMask & FEATHER_TAGLIST) { FeatherConfigTags( itemPtr, lineInfo->ntags, lineInfo->tagList ); } if (lineMask & FEATHER_WIDTH) { linePtr->width = lineInfo->width; } if (lineMask & FEATHER_FILLSTIPPLE) { linePtr->fillStipple = Feather_UseBitmap( lineInfo->fillStipple ); } if (lineMask & FEATHER_FILLCOLOR) { linePtr->fg = Feather_UseColor( lineInfo->fg ); } else { linePtr->fg = Feather_UseColor( blackColor ); } if (linePtr->fg) { 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) { gcValues.cap_style = linePtr->capStyle; mask |= GCCapStyle; } linePtr->gc = Tk_GetGC( canvasPtr->tkwin, mask, &gcValues ); } else { linePtr->gc = None; } /* * Keep spline parameters within reasonable limits. */ if (linePtr->splineSteps < 1) { linePtr->splineSteps = 1; } else if (linePtr->splineSteps > 100) { linePtr->splineSteps = 100; } if (lineMask & FEATHER_ARROW) { /* if it's invalid, just set it to none */ linePtr->arrow = (lineInfo->arrow == last) ? lastUid : (lineInfo->arrow == first) ? firstUid : (lineInfo->arrow == both) ? bothUid : noneUid; } if (linePtr->arrow != noneUid) { ConfigureArrows( canvasPtr, linePtr ); } /* * Recompute bounding box for line */ ComputeLineBbox( canvasPtr, linePtr ); return TCL_OK;}/* Reconfigure arrows to fix head squishing.*/int FeatherReconfigArrows( canvasPtr, bbox )Tk_Canvas *canvasPtr;int bbox[4];{ Tk_Item *itemPtr; double x1, x2, y1, y2; int nconfigged = 0; /* traverse the item list */ itemPtr = canvasPtr->firstItemPtr; while (itemPtr) { /* if this item is a line and it has arrows, recompute them */ if (itemPtr->typePtr == &TkLineType && ((LineItem*)itemPtr)->arrow != noneUid) { ConfigureArrows( canvasPtr, (LineItem*)itemPtr ); if (nconfigged) { if (itemPtr->x1 < x1) x1 = itemPtr->x1; if (itemPtr->x2 > x2) x2 = itemPtr->x2; if (itemPtr->y1 < y1) y1 = itemPtr->y1; if (itemPtr->y2 > y2) y2 = itemPtr->y2; } else { x1 = itemPtr->x1; x2 = itemPtr->x2; y1 = itemPtr->y1; y2 = itemPtr->y2; } nconfigged++; } itemPtr = itemPtr->nextPtr; } if (nconfigged) { bbox[0] = x1; bbox[1] = y1; bbox[2] = x2; bbox[3] = y2; } else { bbox[0] = 0; bbox[2] = -1; } return TCL_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -