📄 tkcanvpoly.c
字号:
i = (polyPtr->width+1)/2 + 1; polyPtr->header.x1 -= i; polyPtr->header.x2 += i; polyPtr->header.y1 -= i; polyPtr->header.y2 += i;}/* *-------------------------------------------------------------- * * TkFillPolygon -- * * This procedure is invoked to convert a polygon to screen * coordinates and display it using a particular GC. * * Results: * None. * * Side effects: * ItemPtr is drawn in drawable using the transformation * information in canvas. * *-------------------------------------------------------------- */voidTkFillPolygon(canvas, coordPtr, numPoints, display, drawable, gc, outlineGC) Tk_Canvas canvas; /* Canvas whose coordinate system * is to be used for drawing. */ double *coordPtr; /* Array of coordinates for polygon: * x1, y1, x2, y2, .... */ int numPoints; /* Twice this many coordinates are * present at *coordPtr. */ Display *display; /* Display on which to draw polygon. */ Drawable drawable; /* Pixmap or window in which to draw * polygon. */ GC gc; /* Graphics context for drawing. */ GC outlineGC; /* If not None, use this to draw an * outline around the polygon after * filling it. */{ XPoint staticPoints[MAX_STATIC_POINTS]; XPoint *pointPtr; XPoint *pPtr; int i; /* * Build up an array of points in screen coordinates. Use a * static array unless the polygon has an enormous number of points; * in this case, dynamically allocate an array. */ if (numPoints <= MAX_STATIC_POINTS) { pointPtr = staticPoints; } else { pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint))); } for (i = 0, pPtr = pointPtr; i < numPoints; i += 1, coordPtr += 2, pPtr++) { Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x, &pPtr->y); } /* * Display polygon, then free up polygon storage if it was dynamically * allocated. */ if (gc != None) { XFillPolygon(display, drawable, gc, pointPtr, numPoints, Complex, CoordModeOrigin); } if (outlineGC != None) { XDrawLines(display, drawable, outlineGC, pointPtr, numPoints, CoordModeOrigin); } if (pointPtr != staticPoints) { ckfree((char *) pointPtr); }}/* *-------------------------------------------------------------- * * DisplayPolygon -- * * This procedure is invoked to draw a polygon item in a given * drawable. * * Results: * None. * * Side effects: * ItemPtr is drawn in drawable using the transformation * information in canvas. * *-------------------------------------------------------------- */static voidDisplayPolygon(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). */{ PolygonItem *polyPtr = (PolygonItem *) itemPtr; if ((polyPtr->fillGC == None) && (polyPtr->outlineGC == None)) { return; } /* * 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. */ if ((polyPtr->fillStipple != None) && (polyPtr->fillGC != None)) { Tk_CanvasSetStippleOrigin(canvas, polyPtr->fillGC); } if (!polyPtr->smooth) { TkFillPolygon(canvas, polyPtr->coordPtr, polyPtr->numPoints, display, drawable, polyPtr->fillGC, polyPtr->outlineGC); } else { int numPoints; XPoint staticPoints[MAX_STATIC_POINTS]; XPoint *pointPtr; /* * This is a smoothed polygon. Display using a set of generated * spline points rather than the original points. */ numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps; if (numPoints <= MAX_STATIC_POINTS) { pointPtr = staticPoints; } else { pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint))); } numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr, polyPtr->numPoints, polyPtr->splineSteps, pointPtr, (double *) NULL); if (polyPtr->fillGC != None) { XFillPolygon(display, drawable, polyPtr->fillGC, pointPtr, numPoints, Complex, CoordModeOrigin); } if (polyPtr->outlineGC != None) { XDrawLines(display, drawable, polyPtr->outlineGC, pointPtr, numPoints, CoordModeOrigin); } if (pointPtr != staticPoints) { ckfree((char *) pointPtr); } } if ((polyPtr->fillStipple != None) && (polyPtr->fillGC != None)) { XSetTSOrigin(display, polyPtr->fillGC, 0, 0); }}/* *-------------------------------------------------------------- * * PolygonToPoint -- * * Computes the distance from a given point to a given * polygon, 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 polygon. If the * point isn't inside the polygon then the return value is the * distance from the point to the polygon. * * Side effects: * None. * *-------------------------------------------------------------- */ /* ARGSUSED */static doublePolygonToPoint(canvas, itemPtr, pointPtr) Tk_Canvas canvas; /* Canvas containing item. */ Tk_Item *itemPtr; /* Item to check against point. */ double *pointPtr; /* Pointer to x and y coordinates. */{ PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr, distance; double staticSpace[2*MAX_STATIC_POINTS]; int numPoints; if (!polyPtr->smooth) { distance = TkPolygonToPoint(polyPtr->coordPtr, polyPtr->numPoints, pointPtr); } else { /* * Smoothed polygon. Generate a new set of points and use them * for comparison. */ numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps; if (numPoints <= MAX_STATIC_POINTS) { coordPtr = staticSpace; } else { coordPtr = (double *) ckalloc((unsigned) (2*numPoints*sizeof(double))); } numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr, polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, coordPtr); distance = TkPolygonToPoint(coordPtr, numPoints, pointPtr); if (coordPtr != staticSpace) { ckfree((char *) coordPtr); } } if (polyPtr->outlineColor != NULL) { distance -= polyPtr->width/2.0; if (distance < 0) { distance = 0; } } return distance;}/* *-------------------------------------------------------------- * * PolygonToArea -- * * 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 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely * inside the given area. * * Side effects: * None. * *-------------------------------------------------------------- */ /* ARGSUSED */static intPolygonToArea(canvas, itemPtr, rectPtr) Tk_Canvas canvas; /* Canvas containing item. */ Tk_Item *itemPtr; /* Item to check against polygon. */ double *rectPtr; /* Pointer to array of four coordinates * (x1, y1, x2, y2) describing rectangular * area. */{ PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr, rect2[4], halfWidth; double staticSpace[2*MAX_STATIC_POINTS]; int numPoints, result; /* * Handle smoothed polygons by generating an expanded set of points * against which to do the check. */ if (polyPtr->smooth) { numPoints = 1 + polyPtr->numPoints*polyPtr->splineSteps; if (numPoints <= MAX_STATIC_POINTS) { coordPtr = staticSpace; } else { coordPtr = (double *) ckalloc((unsigned) (2*numPoints*sizeof(double))); } numPoints = TkMakeBezierCurve(canvas, polyPtr->coordPtr, polyPtr->numPoints, polyPtr->splineSteps, (XPoint *) NULL, coordPtr); } else { numPoints = polyPtr->numPoints; coordPtr = polyPtr->coordPtr; } if (polyPtr->width <= 1) { /* * The outline of the polygon doesn't stick out, so we can * do a simple check. */ result = TkPolygonToArea(coordPtr, numPoints, rectPtr); } else { /* * The polygon has a wide outline, so the check is more complicated. * First, check the line segments to see if they overlap the area. */ result = TkThickPolyLineToArea(coordPtr, numPoints, (double) polyPtr->width, CapRound, JoinRound, rectPtr); if (result >= 0) { goto done; } /* * There is no overlap between the polygon's outline and the * rectangle. This means either the rectangle is entirely outside * the polygon or entirely inside. To tell the difference, * see whether the polygon (with 0 outline width) overlaps the * rectangle bloated by half the outline width. */ halfWidth = polyPtr->width/2.0; rect2[0] = rectPtr[0] - halfWidth; rect2[1] = rectPtr[1] - halfWidth; rect2[2] = rectPtr[2] + halfWidth; rect2[3] = rectPtr[3] + halfWidth; if (TkPolygonToArea(coordPtr, numPoints, rect2) == -1) { result = -1; } else { result = 0; } } done: if ((coordPtr != staticSpace) && (coordPtr != polyPtr->coordPtr)) { ckfree((char *) coordPtr); } return result;}/* *-------------------------------------------------------------- * * ScalePolygon -- * * This procedure is invoked to rescale a polygon item. * * Results: * None. * * Side effects: * The polygon referred to by itemPtr is rescaled so that the * following transformation is applied to all point * coordinates: * x' = originX + scaleX*(x-originX) * y' = originY + scaleY*(y-originY) * *-------------------------------------------------------------- */static voidScalePolygon(canvas, itemPtr, originX, originY, scaleX, scaleY) Tk_Canvas canvas; /* Canvas containing polygon. */ Tk_Item *itemPtr; /* Polygon 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. */{ PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr; int i; for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints; i++, coordPtr += 2) { *coordPtr = originX + scaleX*(*coordPtr - originX); coordPtr[1] = originY + scaleY*(coordPtr[1] - originY); } ComputePolygonBbox(canvas, polyPtr);}/* *-------------------------------------------------------------- * * TranslatePolygon -- * * This procedure is called to move a polygon by a given * amount. * * Results: * None. * * Side effects: * The position of the polygon is offset by (xDelta, yDelta), * and the bounding box is updated in the generic part of the * item structure. * *-------------------------------------------------------------- */static voidTranslatePolygon(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. */{ PolygonItem *polyPtr = (PolygonItem *) itemPtr; double *coordPtr; int i; for (i = 0, coordPtr = polyPtr->coordPtr; i < polyPtr->numPoints; i++, coordPtr += 2) { *coordPtr += deltaX; coordPtr[1] += deltaY; } ComputePolygonBbox(canvas, polyPtr);}/* *-------------------------------------------------------------- * * PolygonToPostscript -- * * This procedure is called to generate Postscript for * polygon items. * * Results: * The return value is a standard Tcl result. If an error * occurs in generating Postscript then an error message is * left in 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 intPolygonToPostscript(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. */{ char string[100]; PolygonItem *polyPtr = (PolygonItem *) itemPtr; /* * Fill the area of the polygon. */ if (polyPtr->fillColor != NULL) { if (!polyPtr->smooth) { Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr, polyPtr->numPoints); } else { TkMakeBezierPostscript(interp, canvas, polyPtr->coordPtr, polyPtr->numPoints); } if (Tk_CanvasPsColor(interp, canvas, polyPtr->fillColor) != TCL_OK) { return TCL_ERROR; } if (polyPtr->fillStipple != None) { Tcl_AppendResult(interp, "eoclip ", (char *) NULL); if (Tk_CanvasPsStipple(interp, canvas, polyPtr->fillStipple) != TCL_OK) { return TCL_ERROR; } if (polyPtr->outlineColor != NULL) { Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); } } else { Tcl_AppendResult(interp, "eofill\n", (char *) NULL); } } /* * Now draw the outline, if there is one. */ if (polyPtr->outlineColor != NULL) { if (!polyPtr->smooth) { Tk_CanvasPsPath(interp, canvas, polyPtr->coordPtr, polyPtr->numPoints); } else { TkMakeBezierPostscript(interp, canvas, polyPtr->coordPtr, polyPtr->numPoints); } sprintf(string, "%d setlinewidth\n", polyPtr->width); Tcl_AppendResult(interp, string, "1 setlinecap\n1 setlinejoin\n", (char *) NULL); if (Tk_CanvasPsColor(interp, canvas, polyPtr->outlineColor) != TCL_OK) { return TCL_ERROR; } Tcl_AppendResult(interp, "stroke\n", (char *) NULL); } return TCL_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -