📄 tkcanvline.c
字号:
* * Side effects: * Configuration information, such as colors and stipple * patterns, may be set for itemPtr. * *-------------------------------------------------------------- */static intConfigureLine(interp, canvas, itemPtr, argc, argv, flags) Tcl_Interp *interp; /* Used for error reporting. */ Tk_Canvas canvas; /* Canvas containing itemPtr. */ Tk_Item *itemPtr; /* Line item to reconfigure. */ int argc; /* Number of elements in argv. */ char **argv; /* Arguments describing things to configure. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */{ LineItem *linePtr = (LineItem *) itemPtr; XGCValues gcValues; GC newGC, arrowGC; unsigned long mask; Tk_Window tkwin; tkwin = Tk_CanvasTkwin(canvas); if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv, (char *) linePtr, flags) != TCL_OK) { return TCL_ERROR; } /* * A few of the options require additional processing, such as * graphics contexts. */ if (linePtr->fg == NULL) { newGC = arrowGC = None; } else { gcValues.foreground = linePtr->fg->pixel; gcValues.join_style = linePtr->joinStyle; if (linePtr->width < 0) { linePtr->width = 1; } gcValues.line_width = linePtr->width; mask = GCForeground|GCJoinStyle|GCLineWidth; if (linePtr->fillStipple != None) { gcValues.stipple = linePtr->fillStipple; gcValues.fill_style = FillStippled; mask |= GCStipple|GCFillStyle; } if (linePtr->arrow == noneUid) { gcValues.cap_style = linePtr->capStyle; mask |= GCCapStyle; } newGC = Tk_GetGC(tkwin, mask, &gcValues); gcValues.line_width = 0; arrowGC = Tk_GetGC(tkwin, mask, &gcValues); } if (linePtr->gc != None) { Tk_FreeGC(Tk_Display(tkwin), linePtr->gc); } if (linePtr->arrowGC != None) { Tk_FreeGC(Tk_Display(tkwin), linePtr->arrowGC); } linePtr->gc = newGC; linePtr->arrowGC = arrowGC; /* * Keep spline parameters within reasonable limits. */ if (linePtr->splineSteps < 1) { linePtr->splineSteps = 1; } else if (linePtr->splineSteps > 100) { linePtr->splineSteps = 100; } /* * Setup arrowheads, if needed. If arrowheads are turned off, * restore the line's endpoints (they were shortened when the * arrowheads were added). */ if ((linePtr->firstArrowPtr != NULL) && (linePtr->arrow != firstUid) && (linePtr->arrow != bothUid)) { linePtr->coordPtr[0] = linePtr->firstArrowPtr[0]; linePtr->coordPtr[1] = linePtr->firstArrowPtr[1]; ckfree((char *) linePtr->firstArrowPtr); linePtr->firstArrowPtr = NULL; } if ((linePtr->lastArrowPtr != NULL) && (linePtr->arrow != lastUid) && (linePtr->arrow != bothUid)) { int i; i = 2*(linePtr->numPoints-1); linePtr->coordPtr[i] = linePtr->lastArrowPtr[0]; linePtr->coordPtr[i+1] = linePtr->lastArrowPtr[1]; ckfree((char *) linePtr->lastArrowPtr); linePtr->lastArrowPtr = NULL; } if (linePtr->arrow != noneUid) { if ((linePtr->arrow != firstUid) && (linePtr->arrow != lastUid) && (linePtr->arrow != bothUid)) { Tcl_AppendResult(interp, "bad arrow spec \"", linePtr->arrow, "\": must be none, first, last, or both", (char *) NULL); linePtr->arrow = noneUid; return TCL_ERROR; } ConfigureArrows(canvas, linePtr); } /* * Recompute bounding box for line. */ ComputeLineBbox(canvas, linePtr); return TCL_OK;}/* *-------------------------------------------------------------- * * DeleteLine -- * * This procedure is called to clean up the data structure * associated with a line item. * * Results: * None. * * Side effects: * Resources associated with itemPtr are released. * *-------------------------------------------------------------- */static voidDeleteLine(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. */{ LineItem *linePtr = (LineItem *) itemPtr; if (linePtr->coordPtr != NULL) { ckfree((char *) linePtr->coordPtr); } if (linePtr->fg != NULL) { Tk_FreeColor(linePtr->fg); } if (linePtr->fillStipple != None) { Tk_FreeBitmap(display, linePtr->fillStipple); } if (linePtr->gc != None) { Tk_FreeGC(display, linePtr->gc); } if (linePtr->arrowGC != None) { Tk_FreeGC(display, linePtr->arrowGC); } if (linePtr->firstArrowPtr != NULL) { ckfree((char *) linePtr->firstArrowPtr); } if (linePtr->lastArrowPtr != NULL) { ckfree((char *) linePtr->lastArrowPtr); }}/* *-------------------------------------------------------------- * * ComputeLineBbox -- * * This procedure is invoked to compute the bounding box of * all the pixels that may be drawn as part of a line. * * Results: * None. * * Side effects: * The fields x1, y1, x2, and y2 are updated in the header * for itemPtr. * *-------------------------------------------------------------- */static voidComputeLineBbox(canvas, linePtr) Tk_Canvas canvas; /* Canvas that contains item. */ LineItem *linePtr; /* Item whose bbos is to be * recomputed. */{ double *coordPtr; int i, width; coordPtr = linePtr->coordPtr; linePtr->header.x1 = linePtr->header.x2 = (int) *coordPtr; linePtr->header.y1 = linePtr->header.y2 = (int) coordPtr[1]; /* * Compute the bounding box of all the points in the line, * then expand in all directions by the line's width to take * care of butting or rounded corners and projecting or * rounded caps. This expansion is an overestimate (worst-case * is square root of two over two) but it's simple. Don't do * anything special for curves. This causes an additional * overestimate in the bounding box, but is faster. */ for (i = 1, coordPtr = linePtr->coordPtr+2; i < linePtr->numPoints; i++, coordPtr += 2) { TkIncludePoint((Tk_Item *) linePtr, coordPtr); } width = linePtr->width; if (width < 1) { width = 1; } linePtr->header.x1 -= width; linePtr->header.x2 += width; linePtr->header.y1 -= width; linePtr->header.y2 += width; /* * For mitered lines, make a second pass through all the points. * Compute the locations of the two miter vertex points and add * those into the bounding box. */ if (linePtr->joinStyle == JoinMiter) { for (i = linePtr->numPoints, coordPtr = linePtr->coordPtr; i >= 3; i--, coordPtr += 2) { double miter[4]; int j; if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, (double) width, miter, miter+2)) { for (j = 0; j < 4; j += 2) { TkIncludePoint((Tk_Item *) linePtr, miter+j); } } } } /* * Add in the sizes of arrowheads, if any. */ if (linePtr->arrow != noneUid) { if (linePtr->arrow != lastUid) { for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint((Tk_Item *) linePtr, coordPtr); } } if (linePtr->arrow != firstUid) { for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW; i++, coordPtr += 2) { TkIncludePoint((Tk_Item *) linePtr, coordPtr); } } } /* * Add one more pixel of fudge factor just to be safe (e.g. * X may round differently than we do). */ linePtr->header.x1 -= 1; linePtr->header.x2 += 1; linePtr->header.y1 -= 1; linePtr->header.y2 += 1;}/* *-------------------------------------------------------------- * * DisplayLine -- * * This procedure is invoked to draw a line item in a given * drawable. * * Results: * None. * * Side effects: * ItemPtr is drawn in drawable using the transformation * information in canvas. * *-------------------------------------------------------------- */static voidDisplayLine(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). */{ LineItem *linePtr = (LineItem *) itemPtr; XPoint staticPoints[MAX_STATIC_POINTS]; XPoint *pointPtr; XPoint *pPtr; double *coordPtr; int i, numPoints; if (linePtr->gc == None) { return; } /* * Build up an array of points in screen coordinates. Use a * static array unless the line has an enormous number of points; * in this case, dynamically allocate an array. For smoothed lines, * generate the curve points on each redisplay. */ if ((linePtr->smooth) && (linePtr->numPoints > 2)) { numPoints = 1 + linePtr->numPoints*linePtr->splineSteps; } else { numPoints = linePtr->numPoints; } if (numPoints <= MAX_STATIC_POINTS) { pointPtr = staticPoints; } else { pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint))); } if ((linePtr->smooth) && (linePtr->numPoints > 2)) { numPoints = TkMakeBezierCurve(canvas, linePtr->coordPtr, linePtr->numPoints, linePtr->splineSteps, pointPtr, (double *) NULL); } else { for (i = 0, coordPtr = linePtr->coordPtr, pPtr = pointPtr; i < linePtr->numPoints; i += 1, coordPtr += 2, pPtr++) { Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1], &pPtr->x, &pPtr->y); } } /* * Display line, the free up line storage if it was dynamically * allocated. 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 (linePtr->fillStipple != None) { Tk_CanvasSetStippleOrigin(canvas, linePtr->gc); Tk_CanvasSetStippleOrigin(canvas, linePtr->arrowGC); } XDrawLines(display, drawable, linePtr->gc, pointPtr, numPoints, CoordModeOrigin); if (pointPtr != staticPoints) { ckfree((char *) pointPtr); } /* * Display arrowheads, if they are wanted. */ if (linePtr->firstArrowPtr != NULL) { TkFillPolygon(canvas, linePtr->firstArrowPtr, PTS_IN_ARROW, display, drawable, linePtr->gc, NULL); } if (linePtr->lastArrowPtr != NULL) { TkFillPolygon(canvas, linePtr->lastArrowPtr, PTS_IN_ARROW, display, drawable, linePtr->gc, NULL); } if (linePtr->fillStipple != None) { XSetTSOrigin(display, linePtr->gc, 0, 0); XSetTSOrigin(display, linePtr->arrowGC, 0, 0); }}/* *-------------------------------------------------------------- * * LineToPoint -- * * Computes the distance from a given point to a given * line, 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 line. If the * point isn't inside the line then the return value is the * distance from the point to the line. * * Side effects: * None. * *-------------------------------------------------------------- */ /* ARGSUSED */static doubleLineToPoint(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. */{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -