📄 tkcanvarc.c
字号:
} if (arcPtr->fillGC != None) { Tk_FreeGC(Tk_Display(tkwin), arcPtr->fillGC); } arcPtr->fillGC = newGC; ComputeArcBbox(canvas, arcPtr); return TCL_OK;}/* *-------------------------------------------------------------- * * DeleteArc -- * * This procedure is called to clean up the data structure * associated with a arc item. * * Results: * None. * * Side effects: * Resources associated with itemPtr are released. * *-------------------------------------------------------------- */static voidDeleteArc(canvas, itemPtr, display) Tk_Canvas canvas; /* Info about overall canvas. */ Tk_Item *itemPtr; /* Item that is being deleted. */ Display *display; /* Display containing window for * canvas. */{ ArcItem *arcPtr = (ArcItem *) itemPtr; if (arcPtr->numOutlinePoints != 0) { ckfree((char *) arcPtr->outlinePtr); } if (arcPtr->outlineColor != NULL) { Tk_FreeColor(arcPtr->outlineColor); } if (arcPtr->fillColor != NULL) { Tk_FreeColor(arcPtr->fillColor); } if (arcPtr->fillStipple != None) { Tk_FreeBitmap(display, arcPtr->fillStipple); } if (arcPtr->outlineStipple != None) { Tk_FreeBitmap(display, arcPtr->outlineStipple); } if (arcPtr->outlineGC != None) { Tk_FreeGC(display, arcPtr->outlineGC); } if (arcPtr->fillGC != None) { Tk_FreeGC(display, arcPtr->fillGC); }}/* *-------------------------------------------------------------- * * ComputeArcBbox -- * * This procedure is invoked to compute the bounding box of * all the pixels that may be drawn as part of an arc. * * Results: * None. * * Side effects: * The fields x1, y1, x2, and y2 are updated in the header * for itemPtr. * *-------------------------------------------------------------- */ /* ARGSUSED */static voidComputeArcBbox(canvas, arcPtr) Tk_Canvas canvas; /* Canvas that contains item. */ ArcItem *arcPtr; /* Item whose bbox is to be * recomputed. */{ double tmp, center[2], point[2]; /* * Make sure that the first coordinates are the lowest ones. */ if (arcPtr->bbox[1] > arcPtr->bbox[3]) { double tmp; tmp = arcPtr->bbox[3]; arcPtr->bbox[3] = arcPtr->bbox[1]; arcPtr->bbox[1] = tmp; } if (arcPtr->bbox[0] > arcPtr->bbox[2]) { double tmp; tmp = arcPtr->bbox[2]; arcPtr->bbox[2] = arcPtr->bbox[0]; arcPtr->bbox[0] = tmp; } ComputeArcOutline(arcPtr); /* * To compute the bounding box, start with the the bbox formed * by the two endpoints of the arc. Then add in the center of * the arc's oval (if relevant) and the 3-o'clock, 6-o'clock, * 9-o'clock, and 12-o'clock positions, if they are relevant. */ arcPtr->header.x1 = arcPtr->header.x2 = (int) arcPtr->center1[0]; arcPtr->header.y1 = arcPtr->header.y2 = (int) arcPtr->center1[1]; TkIncludePoint((Tk_Item *) arcPtr, arcPtr->center2); center[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2; center[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2; if (arcPtr->style == pieSliceUid) { TkIncludePoint((Tk_Item *) arcPtr, center); } tmp = -arcPtr->start; if (tmp < 0) { tmp += 360.0; } if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) { point[0] = arcPtr->bbox[2]; point[1] = center[1]; TkIncludePoint((Tk_Item *) arcPtr, point); } tmp = 90.0 - arcPtr->start; if (tmp < 0) { tmp += 360.0; } if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) { point[0] = center[0]; point[1] = arcPtr->bbox[1]; TkIncludePoint((Tk_Item *) arcPtr, point); } tmp = 180.0 - arcPtr->start; if (tmp < 0) { tmp += 360.0; } if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) { point[0] = arcPtr->bbox[0]; point[1] = center[1]; TkIncludePoint((Tk_Item *) arcPtr, point); } tmp = 270.0 - arcPtr->start; if (tmp < 0) { tmp += 360.0; } if ((tmp < arcPtr->extent) || ((tmp-360) > arcPtr->extent)) { point[0] = center[0]; point[1] = arcPtr->bbox[3]; TkIncludePoint((Tk_Item *) arcPtr, point); } /* * Lastly, expand by the width of the arc (if the arc's outline is * being drawn) and add one extra pixel just for safety. */ if (arcPtr->outlineColor == NULL) { tmp = 1; } else { tmp = (arcPtr->width + 1)/2 + 1; } arcPtr->header.x1 -= (int) tmp; arcPtr->header.y1 -= (int) tmp; arcPtr->header.x2 += (int) tmp; arcPtr->header.y2 += (int) tmp;}/* *-------------------------------------------------------------- * * DisplayArc -- * * This procedure is invoked to draw an arc item in a given * drawable. * * Results: * None. * * Side effects: * ItemPtr is drawn in drawable using the transformation * information in canvas. * *-------------------------------------------------------------- */static voidDisplayArc(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). */{ ArcItem *arcPtr = (ArcItem *) itemPtr; short x1, y1, x2, y2; int start, extent; /* * Compute the screen coordinates of the bounding box for the item, * plus integer values for the angles. */ Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[0], arcPtr->bbox[1], &x1, &y1); Tk_CanvasDrawableCoords(canvas, arcPtr->bbox[2], arcPtr->bbox[3], &x2, &y2); if (x2 <= x1) { x2 = x1+1; } if (y2 <= y1) { y2 = y1+1; } start = (int) ((64*arcPtr->start) + 0.5); extent = (int) ((64*arcPtr->extent) + 0.5); /* * Display filled arc first (if wanted), then outline. If the extent * is zero then don't invoke XFillArc or XDrawArc, since this causes * some window servers to crash and should be a no-op anyway. */ if ((arcPtr->fillGC != None) && (extent != 0)) { if (arcPtr->fillStipple != None) { Tk_CanvasSetStippleOrigin(canvas, arcPtr->fillGC); } XFillArc(display, drawable, arcPtr->fillGC, x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), start, extent); if (arcPtr->fillStipple != None) { XSetTSOrigin(display, arcPtr->fillGC, 0, 0); } } if (arcPtr->outlineGC != None) { if (arcPtr->outlineStipple != None) { Tk_CanvasSetStippleOrigin(canvas, arcPtr->outlineGC); } if (extent != 0) { XDrawArc(display, drawable, arcPtr->outlineGC, x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), start, extent); } /* * If the outline width is very thin, don't use polygons to draw * the linear parts of the outline (this often results in nothing * being displayed); just draw lines instead. */ if (arcPtr->width <= 2) { Tk_CanvasDrawableCoords(canvas, arcPtr->center1[0], arcPtr->center1[1], &x1, &y1); Tk_CanvasDrawableCoords(canvas, arcPtr->center2[0], arcPtr->center2[1], &x2, &y2); if (arcPtr->style == chordUid) { XDrawLine(display, drawable, arcPtr->outlineGC, x1, y1, x2, y2); } else if (arcPtr->style == pieSliceUid) { short cx, cy; Tk_CanvasDrawableCoords(canvas, (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0, (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0, &cx, &cy); XDrawLine(display, drawable, arcPtr->outlineGC, cx, cy, x1, y1); XDrawLine(display, drawable, arcPtr->outlineGC, cx, cy, x2, y2); } } else { if (arcPtr->style == chordUid) { TkFillPolygon(canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS, display, drawable, arcPtr->outlineGC, None); } else if (arcPtr->style == pieSliceUid) { TkFillPolygon(canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS, display, drawable, arcPtr->outlineGC, None); TkFillPolygon(canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, PIE_OUTLINE2_PTS, display, drawable, arcPtr->outlineGC, None); } } if (arcPtr->outlineStipple != None) { XSetTSOrigin(display, arcPtr->outlineGC, 0, 0); } }}/* *-------------------------------------------------------------- * * ArcToPoint -- * * Computes the distance from a given point to a given * arc, in canvas units. * * Results: * The return value is 0 if the point whose x and y coordinates * are coordPtr[0] and coordPtr[1] is inside the arc. If the * point isn't inside the arc then the return value is the * distance from the point to the arc. If itemPtr is filled, * then anywhere in the interior is considered "inside"; if * itemPtr isn't filled, then "inside" means only the area * occupied by the outline. * * Side effects: * None. * *-------------------------------------------------------------- */ /* ARGSUSED */static doubleArcToPoint(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. */{ ArcItem *arcPtr = (ArcItem *) itemPtr; double vertex[2], pointAngle, diff, dist, newDist; double poly[8], polyDist, width, t1, t2; int filled, angleInRange; /* * See if the point is within the angular range of the arc. * Remember, X angles are backwards from the way we'd normally * think of them. Also, compensate for any eccentricity of * the oval. */ vertex[0] = (arcPtr->bbox[0] + arcPtr->bbox[2])/2.0; vertex[1] = (arcPtr->bbox[1] + arcPtr->bbox[3])/2.0; t1 = (pointPtr[1] - vertex[1])/(arcPtr->bbox[3] - arcPtr->bbox[1]); t2 = (pointPtr[0] - vertex[0])/(arcPtr->bbox[2] - arcPtr->bbox[0]); if ((t1 == 0.0) && (t2 == 0.0)) { pointAngle = 0; } else { pointAngle = -atan2(t1, t2)*180/PI; } diff = pointAngle - arcPtr->start; diff -= ((int) (diff/360.0) * 360.0); if (diff < 0) { diff += 360.0; } angleInRange = (diff <= arcPtr->extent) || ((arcPtr->extent < 0) && ((diff - 360.0) >= arcPtr->extent)); /* * Now perform different tests depending on what kind of arc * we're dealing with. */ if (arcPtr->style == arcUid) { if (angleInRange) { return TkOvalToPoint(arcPtr->bbox, (double) arcPtr->width, 0, pointPtr); } dist = hypot(pointPtr[0] - arcPtr->center1[0], pointPtr[1] - arcPtr->center1[1]); newDist = hypot(pointPtr[0] - arcPtr->center2[0], pointPtr[1] - arcPtr->center2[1]); if (newDist < dist) { return newDist; } return dist; } if ((arcPtr->fillGC != None) || (arcPtr->outlineGC == None)) { filled = 1; } else { filled = 0; } if (arcPtr->outlineGC == None) { width = 0.0; } else { width = arcPtr->width; } if (arcPtr->style == pieSliceUid) { if (width > 1.0) { dist = TkPolygonToPoint(arcPtr->outlinePtr, PIE_OUTLINE1_PTS, pointPtr); newDist = TkPolygonToPoint(arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, PIE_OUTLINE2_PTS, pointPtr); } else { dist = TkLineToPoint(vertex, arcPtr->center1, pointPtr); newDist = TkLineToPoint(vertex, arcPtr->center2, pointPtr); } if (newDist < dist) { dist = newDist; } if (angleInRange) { newDist = TkOvalToPoint(arcPtr->bbox, width, filled, pointPtr); if (newDist < dist) { dist = newDist; } } return dist; } /* * This is a chord-style arc. We have to deal specially with the * triangular piece that represents the difference between a * chord-style arc and a pie-slice arc (for small angles this piece * is excluded here where it would be included for pie slices; * for large angles the piece is included here but would be * excluded for pie slices). */ if (width > 1.0) { dist = TkPolygonToPoint(arcPtr->outlinePtr, CHORD_OUTLINE_PTS, pointPtr); } else { dist = TkLineToPoint(arcPtr->center1, arcPtr->center2, pointPtr); } poly[0] = poly[6] = vertex[0]; poly[1] = poly[7] = vertex[1]; poly[2] = arcPtr->center1[0]; poly[3] = arcPtr->center1[1]; poly[4] = arcPtr->center2[0]; poly[5] = arcPtr->center2[1]; polyDist = TkPolygonToPoint(poly, 4, pointPtr); if (angleInRange) { if ((arcPtr->extent < -180.0) || (arcPtr->extent > 180.0) || (polyDist > 0.0)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -