From aad4b63a80f7461314e733de4f559d94f09246e9 Mon Sep 17 00:00:00 2001 From: joye Date: Wed, 19 Mar 2014 19:19:22 +0000 Subject: *** empty log message *** --- bltGrMarkerBitmap.C | 345 +++++++++++++---------------------------------- bltGrMarkerBitmap.h | 72 +++------- src/bltGrElemLine.C | 67 +-------- src/bltGrMarker.C | 164 +--------------------- src/bltGrMarker.h | 39 ++---- src/bltGrMarkerLine.C | 178 +++++++++++++++++++++--- src/bltGrMarkerLine.h | 67 +++------ src/bltGrMarkerPolygon.C | 160 ++++++++++++++++++++-- src/bltGrMarkerPolygon.h | 89 +++--------- src/bltGrMarkerText.C | 183 +++++++++++-------------- src/bltGrMarkerText.h | 45 +++---- src/bltGrText.C | 138 ++++++++----------- src/bltGrText.h | 10 -- tests/bitmapmarker.tcl | 8 +- tests/textmarker.tcl | 2 +- 15 files changed, 630 insertions(+), 937 deletions(-) diff --git a/bltGrMarkerBitmap.C b/bltGrMarkerBitmap.C index cf008b9..da754bb 100644 --- a/bltGrMarkerBitmap.C +++ b/bltGrMarkerBitmap.C @@ -34,8 +34,6 @@ extern "C" { #include "bltGrMarkerBitmap.h" -#define GETBITMAP(b) (((b)->destBitmap == None) ? (b)->srcBitmap : (b)->destBitmap) - static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", "center", -1, Tk_Offset(BitmapMarker, anchor), 0, NULL, 0}, @@ -46,10 +44,7 @@ static Tk_OptionSpec optionSpecs[] = { "Bitmap all", -1, Tk_Offset(BitmapMarker, obj.tags), TK_OPTION_NULL_OK, &listObjOption, 0}, {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", - NULL, -1, Tk_Offset(BitmapMarker, srcBitmap), TK_OPTION_NULL_OK, NULL, 0}, - {TK_OPTION_CUSTOM, "-coords", "coords", "Coords", - NULL, -1, Tk_Offset(BitmapMarker, worldPts), - TK_OPTION_NULL_OK, &coordsObjOption, 0}, + NULL, -1, Tk_Offset(BitmapMarker, bitmap), TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-element", "element", "Element", NULL, -1, Tk_Offset(BitmapMarker, elemName), TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, @@ -64,14 +59,16 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CUSTOM, "-mapy", "mapY", "MapY", "y", -1, Tk_Offset(BitmapMarker, axes.y), 0, &yAxisObjOption, 0}, {TK_OPTION_SYNONYM, "-outline", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, - // {TK_OPTION_DOUBLE, "-rotate", "rotate", "Rotate", - // "0", -1, Tk_Offset(BitmapMarker, reqAngle), 0, NULL, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", "normal", -1, Tk_Offset(BitmapMarker, state), 0, &stateObjOption, 0}, {TK_OPTION_BOOLEAN, "-under", "under", "Under", "no", -1, Tk_Offset(BitmapMarker, drawUnder), 0, NULL, 0}, + {TK_OPTION_DOUBLE, "-x", "x", "X", + "0", -1, Tk_Offset(BitmapMarker, world.x), 0, NULL, 0}, {TK_OPTION_PIXELS, "-xoffset", "xOffset", "XOffset", "0", -1, Tk_Offset(BitmapMarker, xOffset), 0, NULL, 0}, + {TK_OPTION_DOUBLE, "-y", "y", "Y", + "0", -1, Tk_Offset(BitmapMarker, world.y), 0, NULL, 0}, {TK_OPTION_PIXELS, "-yoffset", "yOffset", "YOffset", "0", -1, Tk_Offset(BitmapMarker, yOffset), 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} @@ -106,325 +103,170 @@ Marker* Blt_CreateBitmapProc(Graph* graphPtr) return (Marker*)bmPtr; } -static int ConfigureBitmapProc(Marker *markerPtr) +static int ConfigureBitmapProc(Marker* markerPtr) { Graph* graphPtr = markerPtr->obj.graphPtr; BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - GC newGC; - XGCValues gcValues; - unsigned long gcMask; - if (bmPtr->srcBitmap == None) + if (bmPtr->bitmap == None) return TCL_OK; - bmPtr->angle = fmod(bmPtr->reqAngle, 360.0); - if (bmPtr->angle < 0.0) - bmPtr->angle += 360.0; - - gcMask = 0; - + XGCValues gcValues; + unsigned long gcMask = 0; if (bmPtr->outlineColor) { gcMask |= GCForeground; gcValues.foreground = bmPtr->outlineColor->pixel; } if (bmPtr->fillColor) { - /* Opaque bitmap: both foreground and background (fill) colors - * are used. */ + // Opaque bitmap: both foreground and background (fill) colors are used gcValues.background = bmPtr->fillColor->pixel; gcMask |= GCBackground; - } else { - /* Transparent bitmap: set the clip mask to the current bitmap. */ - gcValues.clip_mask = bmPtr->srcBitmap; + } + else { + // Transparent bitmap: set the clip mask to the current bitmap + gcValues.clip_mask = bmPtr->bitmap; gcMask |= GCClipMask; } - /* - * This is technically a shared GC, but we're going to set/change the clip - * origin anyways before we draw the bitmap. This relies on the fact that - * no other client will be allocated this GC with the GCClipMask set to - * this particular bitmap. - */ - newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues); - if (bmPtr->gc) { + // This is technically a shared GC, but we're going to set/change the clip + // origin anyways before we draw the bitmap. This relies on the fact that + // no other client will be allocated this GC with the GCClipMask set to + // this particular bitmap. + GC newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues); + if (bmPtr->gc) Tk_FreeGC(graphPtr->display, bmPtr->gc); - } bmPtr->gc = newGC; - /* Create the background GC containing the fill color. */ - + // Create the background GC containing the fill color if (bmPtr->fillColor) { gcValues.foreground = bmPtr->fillColor->pixel; newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues); - if (bmPtr->fillGC) { + if (bmPtr->fillGC) Tk_FreeGC(graphPtr->display, bmPtr->fillGC); - } bmPtr->fillGC = newGC; } markerPtr->flags |= MAP_ITEM; - if (markerPtr->drawUnder) { + if (markerPtr->drawUnder) graphPtr->flags |= CACHE_DIRTY; - } Blt_EventuallyRedrawGraph(graphPtr); return TCL_OK; } -static void MapBitmapProc(Marker *markerPtr) +static void MapBitmapProc(Marker* markerPtr) { BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - Region2d extents; Graph* graphPtr = markerPtr->obj.graphPtr; - Point2d anchorPt; - Point2d corner1, corner2; - int destWidth, destHeight; - int srcWidth, srcHeight; - int i; - if (bmPtr->srcBitmap == None) + if (bmPtr->bitmap == None) return; + + int width, height; + Tk_SizeOfBitmap(graphPtr->display, bmPtr->bitmap, &width, &height); - if (bmPtr->destBitmap != None) { - Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap); - bmPtr->destBitmap = None; - } - /* - * Collect the coordinates. The number of coordinates will determine the - * calculations to be made. - * - * x1 y1 A single pair of X-Y coordinates. They represent - * the anchor position of the bitmap. - * - * x1 y1 x2 y2 Two pairs of X-Y coordinates. They represent - * two opposite corners of a bounding rectangle. The - * bitmap is possibly rotated and scaled to fit into - * this box. - * - */ - Tk_SizeOfBitmap(graphPtr->display, bmPtr->srcBitmap, &srcWidth, - &srcHeight); - corner1 = Blt_MapPoint(markerPtr->worldPts, &markerPtr->axes); - if (markerPtr->nWorldPts > 1) { - double hold; - - corner2 = Blt_MapPoint(markerPtr->worldPts + 1, &markerPtr->axes); - /* Flip the corners if necessary */ - if (corner1.x > corner2.x) { - hold = corner1.x, corner1.x = corner2.x, corner2.x = hold; - } - if (corner1.y > corner2.y) { - hold = corner1.y, corner1.y = corner2.y, corner2.y = hold; - } - } else { - corner2.x = corner1.x + srcWidth - 1; - corner2.y = corner1.y + srcHeight - 1; - } - destWidth = (int)(corner2.x - corner1.x) + 1; - destHeight = (int)(corner2.y - corner1.y) + 1; - - if (markerPtr->nWorldPts == 1) { - anchorPt = Blt_AnchorPoint(corner1.x, corner1.y, (double)destWidth, - (double)destHeight, bmPtr->anchor); - } - else - anchorPt = corner1; - + Point2d anchorPt = Blt_MapPoint(&bmPtr->world, &markerPtr->axes); + anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, width, height, + bmPtr->anchor); anchorPt.x += markerPtr->xOffset; anchorPt.y += markerPtr->yOffset; - /* Check if the bitmap sits at least partially in the plot area. */ - extents.left = anchorPt.x; - extents.top = anchorPt.y; - extents.right = anchorPt.x + destWidth - 1; - extents.bottom = anchorPt.y + destHeight - 1; + Region2d extents; + extents.left = anchorPt.x; + extents.top = anchorPt.y; + extents.right = anchorPt.x + width - 1; + extents.bottom = anchorPt.y + height - 1; markerPtr->clipped = Blt_BoxesDontOverlap(graphPtr, &extents); - if (markerPtr->clipped) { - return; /* Bitmap is offscreen. Don't generate - * rotated or scaled bitmaps. */ - } - /* - * Scale the bitmap if necessary. It's a little tricky because we only - * want to scale what's visible on the screen, not the entire bitmap. - */ - if ((bmPtr->angle != 0.0f) || (destWidth != srcWidth) || - (destHeight != srcHeight)) { - int regionX, regionY, regionWidth, regionHeight; - double left, right, top, bottom; - - /* Ignore parts of the bitmap outside of the plot area. */ - left = MAX(graphPtr->left, extents.left); - right = MIN(graphPtr->right, extents.right); - top = MAX(graphPtr->top, extents.top); - bottom = MIN(graphPtr->bottom, extents.bottom); - - /* Determine the portion of the scaled bitmap to display. */ - regionX = regionY = 0; - if (graphPtr->left > extents.left) { - regionX = (int)(graphPtr->left - extents.left); - } - if (graphPtr->top > extents.top) { - regionY = (int)(graphPtr->top - extents.top); - } - regionWidth = (int)(right - left) + 1; - regionHeight = (int)(bottom - top) + 1; - - anchorPt.x = left; - anchorPt.y = top; - bmPtr->destBitmap = Blt_ScaleRotateBitmapArea(graphPtr->tkwin, bmPtr->srcBitmap, srcWidth, srcHeight, regionX, regionY, regionWidth, regionHeight, destWidth, destHeight, bmPtr->angle); - bmPtr->destWidth = regionWidth; - bmPtr->destHeight = regionHeight; - } else { - bmPtr->destWidth = srcWidth; - bmPtr->destHeight = srcHeight; - bmPtr->destBitmap = None; - } + if (markerPtr->clipped) + return; + + bmPtr->width = width; + bmPtr->height = height; bmPtr->anchorPt = anchorPt; - { - double xScale, yScale; - double tx, ty; - double rotWidth, rotHeight; - Point2d polygon[5]; - int n; - - /* - * Compute a polygon to represent the background area of the bitmap. - * This is needed for backgrounds of arbitrarily rotated bitmaps. We - * also use it to print a background in PostScript. - */ - Blt_GetBoundingBox(srcWidth, srcHeight, bmPtr->angle, &rotWidth, - &rotHeight, polygon); - xScale = (double)destWidth / rotWidth; - yScale = (double)destHeight / rotHeight; + + // Compute a polygon to represent the background area of the bitmap. + // This is needed for print a background in PostScript. + double rotWidth, rotHeight; + Point2d polygon[5]; + Blt_GetBoundingBox(width, height, 0, &rotWidth, &rotHeight, polygon); - /* - * Adjust each point of the polygon. Both scale it to the new size and - * translate it to the actual screen position of the bitmap. - */ - tx = extents.left + destWidth * 0.5; - ty = extents.top + destHeight * 0.5; - for (i = 0; i < 4; i++) { - polygon[i].x = (polygon[i].x * xScale) + tx; - polygon[i].y = (polygon[i].y * yScale) + ty; - } - Blt_GraphExtents(graphPtr, &extents); - n = Blt_PolyRectClip(&extents, polygon, 4, bmPtr->outline); - if (n < 3) { - memcpy(&bmPtr->outline, polygon, sizeof(Point2d) * 4); - bmPtr->nOutlinePts = 4; - } else { - bmPtr->nOutlinePts = n; - } + // Adjust each point of the polygon. Both scale it to the new size and + // translate it to the actual screen position of the bitmap. + double tx = extents.left + width * 0.5; + double ty = extents.top + height * 0.5; + for (int ii=0; ii<4; ii++) { + polygon[ii].x = (polygon[ii].x) + tx; + polygon[ii].y = (polygon[ii].y) + ty; + } + Blt_GraphExtents(graphPtr, &extents); + int nn = Blt_PolyRectClip(&extents, polygon, 4, bmPtr->outline); + if (nn < 3) { + memcpy(&bmPtr->outline, polygon, sizeof(Point2d) * 4); + bmPtr->nOutlinePts = 4; } + else + bmPtr->nOutlinePts = nn; } -static int PointInBitmapProc(Marker *markerPtr, Point2d *samplePtr) +static int PointInBitmapProc(Marker* markerPtr, Point2d *samplePtr) { BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - if (bmPtr->srcBitmap == None) + if (bmPtr->bitmap == None) return 0; - if (bmPtr->angle != 0.0f) { - Point2d points[MAX_OUTLINE_POINTS]; - int i; - - /* - * Generate the bounding polygon (isolateral) for the bitmap and see - * if the point is inside of it. - */ - for (i = 0; i < bmPtr->nOutlinePts; i++) { - points[i].x = bmPtr->outline[i].x + bmPtr->anchorPt.x; - points[i].y = bmPtr->outline[i].y + bmPtr->anchorPt.y; - } - return Blt_PointInPolygon(samplePtr, points, bmPtr->nOutlinePts); - } return ((samplePtr->x >= bmPtr->anchorPt.x) && - (samplePtr->x < (bmPtr->anchorPt.x + bmPtr->destWidth)) && + (samplePtr->x < (bmPtr->anchorPt.x + bmPtr->width)) && (samplePtr->y >= bmPtr->anchorPt.y) && - (samplePtr->y < (bmPtr->anchorPt.y + bmPtr->destHeight))); + (samplePtr->y < (bmPtr->anchorPt.y + bmPtr->height))); } -static int RegionInBitmapProc(Marker *markerPtr, Region2d *extsPtr, +static int RegionInBitmapProc(Marker* markerPtr, Region2d *extsPtr, int enclosed) { BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - if (markerPtr->nWorldPts < 1) - return FALSE; - - if (bmPtr->angle != 0.0f) { - Point2d points[MAX_OUTLINE_POINTS]; - int i; - - /* - * Generate the bounding polygon (isolateral) for the bitmap and see - * if the point is inside of it. - */ - for (i = 0; i < bmPtr->nOutlinePts; i++) { - points[i].x = bmPtr->outline[i].x + bmPtr->anchorPt.x; - points[i].y = bmPtr->outline[i].y + bmPtr->anchorPt.y; - } - return Blt_RegionInPolygon(extsPtr, points, bmPtr->nOutlinePts, - enclosed); - } if (enclosed) { return ((bmPtr->anchorPt.x >= extsPtr->left) && (bmPtr->anchorPt.y >= extsPtr->top) && - ((bmPtr->anchorPt.x + bmPtr->destWidth) <= extsPtr->right) && - ((bmPtr->anchorPt.y + bmPtr->destHeight) <= extsPtr->bottom)); + ((bmPtr->anchorPt.x + bmPtr->width) <= extsPtr->right) && + ((bmPtr->anchorPt.y + bmPtr->height) <= extsPtr->bottom)); } + return !((bmPtr->anchorPt.x >= extsPtr->right) || (bmPtr->anchorPt.y >= extsPtr->bottom) || - ((bmPtr->anchorPt.x + bmPtr->destWidth) <= extsPtr->left) || - ((bmPtr->anchorPt.y + bmPtr->destHeight) <= extsPtr->top)); + ((bmPtr->anchorPt.x + bmPtr->width) <= extsPtr->left) || + ((bmPtr->anchorPt.y + bmPtr->height) <= extsPtr->top)); } -static void DrawBitmapProc(Marker *markerPtr, Drawable drawable) +static void DrawBitmapProc(Marker* markerPtr, Drawable drawable) { Graph* graphPtr = markerPtr->obj.graphPtr; BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - Pixmap bitmap = GETBITMAP(bmPtr); - if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) + if ((bmPtr->bitmap == None) || (bmPtr->width < 1) || (bmPtr->height < 1)) return; - double rangle = fmod(bmPtr->angle, 90.0); - if ((bmPtr->fillColor == NULL) || (rangle != 0.0)) { - - /* - * If the bitmap is rotated and a filled background is required, then - * a filled polygon is drawn before the bitmap. - */ - if (bmPtr->fillColor) { - int i; - XPoint polygon[MAX_OUTLINE_POINTS]; - - for (i = 0; i < bmPtr->nOutlinePts; i++) { - polygon[i].x = (short int)bmPtr->outline[i].x; - polygon[i].y = (short int)bmPtr->outline[i].y; - } - XFillPolygon(graphPtr->display, drawable, bmPtr->fillGC, - polygon, bmPtr->nOutlinePts, Convex, CoordModeOrigin); - } - XSetClipMask(graphPtr->display, bmPtr->gc, bitmap); - XSetClipOrigin(graphPtr->display, bmPtr->gc, (int)bmPtr->anchorPt.x, - (int)bmPtr->anchorPt.y); - } else { + if (bmPtr->fillColor == NULL) { + XSetClipMask(graphPtr->display, bmPtr->gc, bmPtr->bitmap); + XSetClipOrigin(graphPtr->display, bmPtr->gc, bmPtr->anchorPt.x, + bmPtr->anchorPt.y); + } + else { XSetClipMask(graphPtr->display, bmPtr->gc, None); XSetClipOrigin(graphPtr->display, bmPtr->gc, 0, 0); } - XCopyPlane(graphPtr->display, bitmap, drawable, bmPtr->gc, 0, 0, - bmPtr->destWidth, bmPtr->destHeight, (int)bmPtr->anchorPt.x, - (int)bmPtr->anchorPt.y, 1); + XCopyPlane(graphPtr->display, bmPtr->bitmap, drawable, bmPtr->gc, 0, 0, + bmPtr->width, bmPtr->height, bmPtr->anchorPt.x, + bmPtr->anchorPt.y, 1); } -static void BitmapToPostscriptProc(Marker *markerPtr, Blt_Ps ps) +static void BitmapToPostscriptProc(Marker* markerPtr, Blt_Ps ps) { Graph* graphPtr = markerPtr->obj.graphPtr; BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; - Pixmap bitmap = GETBITMAP(bmPtr); - if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) + if ((bmPtr->bitmap == None) || (bmPtr->width < 1) || (bmPtr->height < 1)) return; if (bmPtr->fillColor) { @@ -435,19 +277,19 @@ static void BitmapToPostscriptProc(Marker *markerPtr, Blt_Ps ps) Blt_Ps_Format(ps, " gsave\n %g %g translate\n %d %d scale\n", - bmPtr->anchorPt.x, bmPtr->anchorPt.y + bmPtr->destHeight, - bmPtr->destWidth, -bmPtr->destHeight); + bmPtr->anchorPt.x, bmPtr->anchorPt.y + bmPtr->height, + bmPtr->width, -bmPtr->height); Blt_Ps_Format(ps, " %d %d true [%d 0 0 %d 0 %d] {", - bmPtr->destWidth, bmPtr->destHeight, bmPtr->destWidth, - -bmPtr->destHeight, bmPtr->destHeight); - Blt_Ps_XSetBitmapData(ps, graphPtr->display, bitmap, - bmPtr->destWidth, bmPtr->destHeight); + bmPtr->width, bmPtr->height, bmPtr->width, + -bmPtr->height, bmPtr->height); + Blt_Ps_XSetBitmapData(ps, graphPtr->display, bmPtr->bitmap, + bmPtr->width, bmPtr->height); Blt_Ps_VarAppend(ps, " } imagemask\n", "grestore\n", (char*)NULL); } -static void FreeBitmapProc(Marker *markerPtr) +static void FreeBitmapProc(Marker* markerPtr) { BitmapMarker* bmPtr = (BitmapMarker*)markerPtr; Graph* graphPtr = markerPtr->obj.graphPtr; @@ -457,8 +299,5 @@ static void FreeBitmapProc(Marker *markerPtr) if (bmPtr->fillGC) Tk_FreeGC(graphPtr->display, bmPtr->fillGC); - - if (bmPtr->destBitmap != None) - Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap); } diff --git a/bltGrMarkerBitmap.h b/bltGrMarkerBitmap.h index eb5d22b..7233d0c 100644 --- a/bltGrMarkerBitmap.h +++ b/bltGrMarkerBitmap.h @@ -34,66 +34,34 @@ class BitmapMarker { public: - GraphObj obj; /* Must be first field in marker. */ - + GraphObj obj; MarkerClass *classPtr; - - Tk_OptionTable optionTable; /* Configuration specifications */ + Tk_OptionTable optionTable; Tcl_HashEntry *hashPtr; - Blt_ChainLink link; - - const char* elemName; /* Element associated with marker. Let's - * you link a marker to an element. The - * marker is drawn only if the element - * is also visible. */ + const char* elemName; Axis2d axes; - - Point2d *worldPts; /* Coordinate array to position - * marker. */ - int nWorldPts; /* # of points in above array. */ - - int drawUnder; /* If non-zero, draw the marker - * underneath any elements. This can be - * a performance penalty because the - * graph must be redraw entirely each - * time the marker is redrawn. */ - - int clipped; /* Indicates if the marker is totally - * clipped by the plotting area. */ - + int drawUnder; + int clipped; int hide; unsigned int flags; - - - int xOffset, yOffset; /* Pixel offset from graph position */ - + int xOffset; + int yOffset; int state; - /* Fields specific to bitmap markers. */ - - Pixmap srcBitmap; /* Original bitmap. May be further - * scaled or rotated. */ - double reqAngle; /* Requested rotation of the bitmap */ - float angle; /* Normalized rotation (0..360 - * degrees) */ - Tk_Anchor anchor; /* If only one X-Y coordinate is given, - * indicates how to translate the given - * marker position. Otherwise, if there - * are two X-Y coordinates, then this - * value is ignored. */ - Point2d anchorPt; /* Translated anchor point. */ - - XColor *outlineColor; /* Foreground color */ - XColor* fillColor; /* Background color */ - - GC gc; /* Private graphic context */ - GC fillGC; /* Shared graphic context */ - Pixmap destBitmap; /* Bitmap to be drawn. */ - int destWidth, destHeight; /* Dimensions of the final bitmap */ - - Point2d outline[MAX_OUTLINE_POINTS];/* Polygon representing the background - * of the bitmap. */ + // Fields specific to bitmap + + Point2d world; + Pixmap bitmap; + Tk_Anchor anchor; + Point2d anchorPt; + XColor* outlineColor; + XColor* fillColor; + GC gc; + GC fillGC; + int width; + int height; + Point2d outline[MAX_OUTLINE_POINTS]; int nOutlinePts; }; diff --git a/src/bltGrElemLine.C b/src/bltGrElemLine.C index ce946c8..dbb0d99 100644 --- a/src/bltGrElemLine.C +++ b/src/bltGrElemLine.C @@ -76,7 +76,7 @@ typedef struct { typedef enum { SYMBOL_NONE, SYMBOL_SQUARE, SYMBOL_CIRCLE, SYMBOL_DIAMOND, SYMBOL_PLUS, SYMBOL_CROSS, SYMBOL_SPLUS, SYMBOL_SCROSS, SYMBOL_TRIANGLE, SYMBOL_ARROW, - SYMBOL_BITMAP, SYMBOL_IMAGE + SYMBOL_BITMAP } SymbolType; typedef struct { @@ -293,8 +293,6 @@ typedef struct { // Defs static void DestroySymbol(Display *display, Symbol *symbolPtr); -static void ImageChangedProc(ClientData clientData, int x, int y, int w, int h, - int imageWidth, int imageHeight); typedef double (DistanceProc)(int x, int y, Point2d *p, Point2d *q, Point2d *t); static void InitLinePen(Graph* graphPtr, LinePen* penPtr); static void ResetLine(LineElement* elemPtr); @@ -411,20 +409,6 @@ static int SymbolSetProc(ClientData clientData, Tcl_Interp* interp, } } - // image - { - Element* elemPtr = (Element*)widgRec; - - Tk_Image tkImage = - Tk_GetImage(interp, tkwin, string, ImageChangedProc, elemPtr); - if (tkImage) { - DestroySymbol(Tk_Display(tkwin), symbolPtr); - symbolPtr->image = tkImage; - symbolPtr->type = SYMBOL_IMAGE; - return TCL_OK; - } - } - // bitmap { Tcl_Obj **objv; @@ -920,17 +904,6 @@ static void DestroySymbol(Display *display, Symbol *symbolPtr) symbolPtr->type = SYMBOL_NONE; } -static void ImageChangedProc(ClientData clientData, - int x, int y, int w, int h, - int imageWidth, int imageHeight) -{ - Element* elemPtr = (Element*)clientData; - Graph* graphPtr = elemPtr->obj.graphPtr; - elemPtr->flags |= MAP_ITEM; - graphPtr->flags |= CACHE_DIRTY; - Blt_EventuallyRedrawGraph(graphPtr); -} - /* * Reset the number of points and segments, in case there are no segments or * points @@ -2912,44 +2885,6 @@ static void DrawSymbols(Graph* graphPtr, Drawable drawable, } break; - case SYMBOL_IMAGE: - { - int w, h; - int dx, dy; - - Tk_SizeOfImage(penPtr->symbol.image, &w, &h); - - dx = w / 2; - dy = h / 2; - if (elemPtr->symbolInterval > 0) { - Point2d *pp, *endp; - - for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) { - if (DRAW_SYMBOL(elemPtr)) { - int x, y; - - x = Round(pp->x) - dx; - y = Round(pp->y) - dy; - Tk_RedrawImage(penPtr->symbol.image, 0, 0, w, h, - drawable, x, y); - } - elemPtr->symbolCounter++; - } - } else { - Point2d *pp, *endp; - - for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) { - int x, y; - - x = Round(pp->x) - dx; - y = Round(pp->y) - dy; - Tk_RedrawImage(penPtr->symbol.image, 0, 0, w, h, - drawable, x, y); - } - } - } - break; - case SYMBOL_BITMAP: { Pixmap bitmap, mask; diff --git a/src/bltGrMarker.C b/src/bltGrMarker.C index 221be91..3018efb 100644 --- a/src/bltGrMarker.C +++ b/src/bltGrMarker.C @@ -50,9 +50,6 @@ extern MarkerCreateProc Blt_CreateWindowProc; typedef int (GraphMarkerProc)(Graph* graphPtr, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]); -static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, - int objc, Tcl_Obj* const objv[]); -static Tcl_Obj* PrintCoordinate(double x); static int MarkerObjConfigure( Tcl_Interp* interp, Graph* graphPtr, Marker* markerPtr, int objc, Tcl_Obj* const objv[]); @@ -72,51 +69,6 @@ extern "C" { Marker* Blt_NearestMarker(Graph* graphPtr, int x, int y, int under); }; -// OptionSpecs - -static Tk_CustomOptionSetProc CoordsSetProc; -static Tk_CustomOptionGetProc CoordsGetProc; -Tk_ObjCustomOption coordsObjOption = - { - "coords", CoordsSetProc, CoordsGetProc, NULL, NULL, NULL - }; - -static int CoordsSetProc(ClientData clientData, Tcl_Interp* interp, - Tk_Window tkwin, Tcl_Obj** objPtr, char* widgRec, - int offset, char* save, int flags) -{ - Marker* markerPtr = (Marker*)widgRec; - - int objc; - Tcl_Obj** objv; - if (Tcl_ListObjGetElements(interp, *objPtr, &objc, &objv) != TCL_OK) - return TCL_ERROR; - - if (objc == 0) - return TCL_OK; - - return ParseCoordinates(interp, markerPtr, objc, objv); -} - -static Tcl_Obj* CoordsGetProc(ClientData clientData, Tk_Window tkwin, - char *widgRec, int offset) -{ - Marker* markerPtr = (Marker*)widgRec; - - int cnt = markerPtr->nWorldPts*2; - Tcl_Obj** ll = (Tcl_Obj**)calloc(cnt, sizeof(Tcl_Obj*)); - - Point2d* pp = markerPtr->worldPts; - for (int ii=0; ii < markerPtr->nWorldPts*2; pp++) { - ll[ii++] = PrintCoordinate(pp->x); - ll[ii++] = PrintCoordinate(pp->y); - } - - Tcl_Obj* listObjPtr = Tcl_NewListObj(cnt, ll); - free(ll); - return listObjPtr; -} - static Tk_CustomOptionSetProc CapStyleSetProc; static Tk_CustomOptionGetProc CapStyleGetProc; Tk_ObjCustomOption capStyleObjOption = @@ -630,110 +582,6 @@ int Blt_MarkerOp(Graph* graphPtr, Tcl_Interp* interp, // Support -static int GetCoordinate(Tcl_Interp* interp, Tcl_Obj *objPtr, double *valuePtr) -{ - const char* expr = Tcl_GetString(objPtr); - char c = expr[0]; - if ((c == 'I') && (strcmp(expr, "Inf") == 0)) - *valuePtr = DBL_MAX; /* Elastic upper bound */ - else if ((c == '-') && (expr[1] == 'I') && (strcmp(expr, "-Inf") == 0)) - *valuePtr = -DBL_MAX; /* Elastic lower bound */ - else if ((c == '+') && (expr[1] == 'I') && (strcmp(expr, "+Inf") == 0)) - *valuePtr = DBL_MAX; /* Elastic upper bound */ - else if (Blt_ExprDoubleFromObj(interp, objPtr, valuePtr) != TCL_OK) - return TCL_ERROR; - - return TCL_OK; -} - -static Tcl_Obj* PrintCoordinate(double x) -{ - if (x == DBL_MAX) - return Tcl_NewStringObj("+Inf", -1); - else if (x == -DBL_MAX) - return Tcl_NewStringObj("-Inf", -1); - else - return Tcl_NewDoubleObj(x); -} - -static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, - int objc, Tcl_Obj* const objv[]) -{ - if (objc == 0) - return TCL_OK; - - if (objc & 1) { - Tcl_AppendResult(interp, "odd number of marker coordinates specified", - (char*)NULL); - return TCL_ERROR; - } - - int minArgs, maxArgs; - switch (markerPtr->obj.classId) { - case CID_MARKER_LINE: - minArgs = 4; - maxArgs = 0; - break; - case CID_MARKER_POLYGON: - minArgs = 6; - maxArgs = 0; - break; - case CID_MARKER_WINDOW: - case CID_MARKER_TEXT: - minArgs = 2; - maxArgs = 2; - break; - case CID_MARKER_IMAGE: - case CID_MARKER_BITMAP: - minArgs = 2; - maxArgs = 4; - break; - default: - Tcl_AppendResult(interp, "unknown marker type", (char*)NULL); - return TCL_ERROR; - } - - if (objc < minArgs) { - Tcl_AppendResult(interp, "too few marker coordinates specified", - (char*)NULL); - return TCL_ERROR; - } - if ((maxArgs > 0) && (objc > maxArgs)) { - Tcl_AppendResult(interp, "too many marker coordinates specified", - (char*)NULL); - return TCL_ERROR; - } - int nWorldPts = objc / 2; - Point2d* worldPts = (Point2d*)malloc(nWorldPts * sizeof(Point2d)); - if (worldPts == NULL) { - Tcl_AppendResult(interp, "can't allocate new coordinate array", - (char*)NULL); - return TCL_ERROR; - } - - Point2d* pp = worldPts; - for (int ii=0; iix = x, pp->y = y, pp++; - } - - // Don't free the old coordinate array until we've parsed the new - // coordinates without errors. - if (markerPtr->worldPts) - free(markerPtr->worldPts); - - markerPtr->worldPts = worldPts; - markerPtr->nWorldPts = nWorldPts; - markerPtr->flags |= MAP_ITEM; - - return TCL_OK; -} - static int IsElementHidden(Marker *markerPtr) { Tcl_HashEntry *hPtr; @@ -832,8 +680,7 @@ void Blt_MarkersToPostScript(Graph* graphPtr, Blt_Ps ps, int under) for (Blt_ChainLink link = Blt_Chain_LastLink(graphPtr->markers.displayList); link; link = Blt_Chain_PrevLink(link)) { Marker* markerPtr = (Marker*)Blt_Chain_GetValue(link); - if ((markerPtr->classPtr->postscriptProc == NULL) || - (markerPtr->nWorldPts == 0)) + if (markerPtr->classPtr->postscriptProc == NULL) continue; if (markerPtr->drawUnder != under) @@ -857,8 +704,7 @@ void Blt_DrawMarkers(Graph* graphPtr, Drawable drawable, int under) link; link = Blt_Chain_PrevLink(link)) { Marker* markerPtr = (Marker*)Blt_Chain_GetValue(link); - if ((markerPtr->nWorldPts == 0) || - (markerPtr->drawUnder != under) || + if ((markerPtr->drawUnder != under) || (markerPtr->clipped) || (markerPtr->flags & DELETE_PENDING) || (markerPtr->hide)) @@ -885,8 +731,6 @@ void Blt_MapMarkers(Graph* graphPtr) for (Blt_ChainLink link = Blt_Chain_FirstLink(graphPtr->markers.displayList); link; link = Blt_Chain_NextLink(link)) { Marker *markerPtr = (Marker*)Blt_Chain_GetValue(link); - if (markerPtr->nWorldPts == 0) - continue; if ((markerPtr->flags & DELETE_PENDING) || markerPtr->hide) continue; @@ -923,9 +767,7 @@ Marker* Blt_NearestMarker(Graph* graphPtr, int x, int y, int under) for (Blt_ChainLink link = Blt_Chain_FirstLink(graphPtr->markers.displayList); link; link = Blt_Chain_NextLink(link)) { Marker* markerPtr = (Marker*)Blt_Chain_GetValue(link); - if ((markerPtr->nWorldPts == 0) || - (markerPtr->flags & (DELETE_PENDING|MAP_ITEM)) || - (markerPtr->hide)) + if ((markerPtr->flags & (DELETE_PENDING|MAP_ITEM)) || (markerPtr->hide)) continue; /* Don't consider markers that are * pending to be mapped. Even if the * marker has already been mapped, the diff --git a/src/bltGrMarker.h b/src/bltGrMarker.h index 9f1ebd0..e065b94 100644 --- a/src/bltGrMarker.h +++ b/src/bltGrMarker.h @@ -52,39 +52,25 @@ typedef struct { MarkerPostscriptProc *postscriptProc; } MarkerClass; -struct _Marker { - GraphObj obj; /* Must be first field in marker. */ +typedef struct { + Point2d* points; + int num; +} WorldPts; +struct _Marker { + GraphObj obj; MarkerClass *classPtr; - - Tk_OptionTable optionTable; /* Configuration specifications */ + Tk_OptionTable optionTable; Tcl_HashEntry *hashPtr; - Blt_ChainLink link; - - const char* elemName; /* Element associated with marker. Let's - * you link a marker to an element. The - * marker is drawn only if the element - * is also visible. */ + const char* elemName; Axis2d axes; - Point2d *worldPts; /* Coordinate array to position - * marker */ - int nWorldPts; /* Number of points in above array */ - int drawUnder; /* If non-zero, draw the marker - * underneath any elements. This can be - * a performance penalty because the - * graph must be redraw entirely each - * time the marker is redrawn. */ - - int clipped; /* Indicates if the marker is totally - * clipped by the plotting area. */ - + int drawUnder; + int clipped; int hide; unsigned int flags; - - - int xOffset, yOffset; /* Pixel offset from graph position */ - + int xOffset; + int yOffset; int state; }; @@ -92,7 +78,6 @@ Point2d Blt_MapPoint(Point2d *pointPtr, Axis2d *axesPtr); void Blt_FreeMarker(char*); int Blt_BoxesDontOverlap(Graph* graphPtr, Region2d *extsPtr); -extern Tk_ObjCustomOption coordsObjOption; extern Tk_ObjCustomOption capStyleObjOption; extern Tk_ObjCustomOption joinStyleObjOption; extern Tk_ObjCustomOption xAxisObjOption; diff --git a/src/bltGrMarkerLine.C b/src/bltGrMarkerLine.C index 4314196..68572b1 100644 --- a/src/bltGrMarkerLine.C +++ b/src/bltGrMarkerLine.C @@ -33,6 +33,58 @@ extern "C" { #include "bltGrMarkerLine.h" +// Defs + +static int GetCoordinate(Tcl_Interp* interp, Tcl_Obj *objPtr, double *valuePtr); +static Tcl_Obj* PrintCoordinate(double x); +static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, + int objc, Tcl_Obj* const objv[]); + +// OptionSpecs + +static Tk_CustomOptionSetProc CoordsSetProc; +static Tk_CustomOptionGetProc CoordsGetProc; +static Tk_ObjCustomOption coordsObjOption = + { + "coords", CoordsSetProc, CoordsGetProc, NULL, NULL, NULL + }; + +static int CoordsSetProc(ClientData clientData, Tcl_Interp* interp, + Tk_Window tkwin, Tcl_Obj** objPtr, char* widgRec, + int offset, char* save, int flags) +{ + Marker* markerPtr = (Marker*)widgRec; + + int objc; + Tcl_Obj** objv; + if (Tcl_ListObjGetElements(interp, *objPtr, &objc, &objv) != TCL_OK) + return TCL_ERROR; + + if (objc == 0) + return TCL_OK; + + return ParseCoordinates(interp, markerPtr, objc, objv); +} + +static Tcl_Obj* CoordsGetProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset) +{ + LineMarker* lmPtr = (LineMarker*)widgRec; + + int cnt = lmPtr->nWorldPts*2; + Tcl_Obj** ll = (Tcl_Obj**)calloc(cnt, sizeof(Tcl_Obj*)); + + Point2d* pp = lmPtr->worldPts; + for (int ii=0; ii < lmPtr->nWorldPts*2; pp++) { + ll[ii++] = PrintCoordinate(pp->x); + ll[ii++] = PrintCoordinate(pp->y); + } + + Tcl_Obj* listObjPtr = Tcl_NewListObj(cnt, ll); + free(ll); + return listObjPtr; +} + static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CUSTOM, "-bindtags", "bindTags", "BindTags", "Line all", -1, Tk_Offset(LineMarker, obj.tags), @@ -109,7 +161,7 @@ Marker* Blt_CreateLineProc(Graph* graphPtr) static int PointInLineProc(Marker *markerPtr, Point2d *samplePtr) { - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; return Blt_PointInSegments(samplePtr, lmPtr->segments, lmPtr->nSegments, (double)markerPtr->obj.graphPtr->search.halo); @@ -117,13 +169,15 @@ static int PointInLineProc(Marker *markerPtr, Point2d *samplePtr) static int RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed) { - if (markerPtr->nWorldPts < 2) + LineMarker *lmPtr = (LineMarker*)markerPtr; + + if (lmPtr->nWorldPts < 2) return FALSE; if (enclosed) { Point2d *pp, *pend; - for (pp = markerPtr->worldPts, pend = pp + markerPtr->nWorldPts; + for (pp = lmPtr->worldPts, pend = pp + lmPtr->nWorldPts; pp < pend; pp++) { Point2d p = Blt_MapPoint(pp, &markerPtr->axes); if ((p.x < extsPtr->left) && (p.x > extsPtr->right) && @@ -136,7 +190,7 @@ static int RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed) else { Point2d *pp, *pend; int count = 0; - for (pp = markerPtr->worldPts, pend = pp + (markerPtr->nWorldPts - 1); + for (pp = lmPtr->worldPts, pend = pp + (lmPtr->nWorldPts - 1); pp < pend; pp++) { Point2d p = Blt_MapPoint(pp, &markerPtr->axes); Point2d q = Blt_MapPoint(pp + 1, &markerPtr->axes); @@ -150,7 +204,7 @@ static int RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed) static void DrawLineProc(Marker *markerPtr, Drawable drawable) { - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; if (lmPtr->nSegments > 0) { Graph* graphPtr = markerPtr->obj.graphPtr; @@ -165,7 +219,7 @@ static void DrawLineProc(Marker *markerPtr, Drawable drawable) static int ConfigureLineProc(Marker *markerPtr) { Graph* graphPtr = markerPtr->obj.graphPtr; - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; Drawable drawable = Tk_WindowId(graphPtr->tkwin); unsigned long gcMask = (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle); @@ -225,7 +279,7 @@ static int ConfigureLineProc(Marker *markerPtr) static void LineToPostscriptProc(Marker *markerPtr, Blt_Ps ps) { - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; if (lmPtr->nSegments > 0) { Blt_Ps_XSetLineAttributes(ps, lmPtr->outlineColor, @@ -235,7 +289,7 @@ static void LineToPostscriptProc(Marker *markerPtr, Blt_Ps ps) Blt_Ps_Append(ps, "/DashesProc {\n gsave\n "); Blt_Ps_XSetBackground(ps, lmPtr->fillColor); Blt_Ps_Append(ps, " "); - Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL); + Blt_Ps_XSetDashes(ps, (Blt_Dashes*)NULL); Blt_Ps_VarAppend(ps, "stroke\n", " grestore\n", @@ -249,27 +303,26 @@ static void LineToPostscriptProc(Marker *markerPtr, Blt_Ps ps) static void FreeLineProc(Marker *markerPtr) { - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; Graph* graphPtr = markerPtr->obj.graphPtr; - if (lmPtr->gc) { + if (lmPtr->gc) Blt_FreePrivateGC(graphPtr->display, lmPtr->gc); - } - if (lmPtr->segments) { + + if (lmPtr->segments) free(lmPtr->segments); - } } static void MapLineProc(Marker *markerPtr) { Graph* graphPtr = markerPtr->obj.graphPtr; - LineMarker *lmPtr = (LineMarker *)markerPtr; + LineMarker *lmPtr = (LineMarker*)markerPtr; lmPtr->nSegments = 0; if (lmPtr->segments) free(lmPtr->segments); - if (markerPtr->nWorldPts < 2) + if (lmPtr->nWorldPts < 2) return; Region2d extents; @@ -282,19 +335,19 @@ static void MapLineProc(Marker *markerPtr) * disconnected segments. */ Segment2d* segments = - (Segment2d*)malloc(markerPtr->nWorldPts * sizeof(Segment2d)); - Point2d* srcPtr = markerPtr->worldPts; + (Segment2d*)malloc(lmPtr->nWorldPts * sizeof(Segment2d)); + Point2d* srcPtr = lmPtr->worldPts; Point2d p = Blt_MapPoint(srcPtr, &markerPtr->axes); p.x += markerPtr->xOffset; p.y += markerPtr->yOffset; Segment2d* segPtr = segments; Point2d* pend; - for (srcPtr++, pend = markerPtr->worldPts + markerPtr->nWorldPts; + for (srcPtr++, pend = lmPtr->worldPts + lmPtr->nWorldPts; srcPtr < pend; srcPtr++) { Point2d next = Blt_MapPoint(srcPtr, &markerPtr->axes); - next.x += markerPtr->xOffset; - next.y += markerPtr->yOffset; + next.x += lmPtr->xOffset; + next.y += lmPtr->yOffset; Point2d q = next; if (Blt_LineRectClip(&extents, &p, &q)) { @@ -306,6 +359,89 @@ static void MapLineProc(Marker *markerPtr) } lmPtr->nSegments = segPtr - segments; lmPtr->segments = segments; - markerPtr->clipped = (lmPtr->nSegments == 0); + lmPtr->clipped = (lmPtr->nSegments == 0); +} + +static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, + int objc, Tcl_Obj* const objv[]) +{ + LineMarker* lmPtr = (LineMarker*)markerPtr; + + if (objc == 0) + return TCL_OK; + + if (objc & 1) { + Tcl_AppendResult(interp, "odd number of marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + + int minArgs = 4; + int maxArgs = 0; + if (objc < minArgs) { + Tcl_AppendResult(interp, "too few marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + if ((maxArgs > 0) && (objc > maxArgs)) { + Tcl_AppendResult(interp, "too many marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + int nWorldPts = objc / 2; + Point2d* worldPts = (Point2d*)malloc(nWorldPts * sizeof(Point2d)); + if (worldPts == NULL) { + Tcl_AppendResult(interp, "can't allocate new coordinate array", + (char*)NULL); + return TCL_ERROR; + } + + Point2d* pp = worldPts; + for (int ii=0; iix = x, pp->y = y, pp++; + } + + // Don't free the old coordinate array until we've parsed the new + // coordinates without errors. + if (lmPtr->worldPts) + free(lmPtr->worldPts); + + lmPtr->worldPts = worldPts; + lmPtr->nWorldPts = nWorldPts; + markerPtr->flags |= MAP_ITEM; + + return TCL_OK; +} + +static Tcl_Obj* PrintCoordinate(double x) +{ + if (x == DBL_MAX) + return Tcl_NewStringObj("+Inf", -1); + else if (x == -DBL_MAX) + return Tcl_NewStringObj("-Inf", -1); + else + return Tcl_NewDoubleObj(x); +} + +static int GetCoordinate(Tcl_Interp* interp, Tcl_Obj *objPtr, double *valuePtr) +{ + const char* expr = Tcl_GetString(objPtr); + char c = expr[0]; + if ((c == 'I') && (strcmp(expr, "Inf") == 0)) + *valuePtr = DBL_MAX; /* Elastic upper bound */ + else if ((c == '-') && (expr[1] == 'I') && (strcmp(expr, "-Inf") == 0)) + *valuePtr = -DBL_MAX; /* Elastic lower bound */ + else if ((c == '+') && (expr[1] == 'I') && (strcmp(expr, "+Inf") == 0)) + *valuePtr = DBL_MAX; /* Elastic upper bound */ + else if (Blt_ExprDoubleFromObj(interp, objPtr, valuePtr) != TCL_OK) + return TCL_ERROR; + + return TCL_OK; } diff --git a/src/bltGrMarkerLine.h b/src/bltGrMarkerLine.h index ab987c9..5401a05 100644 --- a/src/bltGrMarkerLine.h +++ b/src/bltGrMarkerLine.h @@ -34,63 +34,36 @@ class LineMarker { public: - GraphObj obj; /* Must be first field in marker. */ - + GraphObj obj; MarkerClass *classPtr; - - Tk_OptionTable optionTable; /* Configuration specifications */ + Tk_OptionTable optionTable; Tcl_HashEntry *hashPtr; - Blt_ChainLink link; - - const char* elemName; /* Element associated with marker. Let's - * you link a marker to an element. The - * marker is drawn only if the element - * is also visible. */ + const char* elemName; Axis2d axes; - - Point2d *worldPts; /* Coordinate array to position - * marker. */ - - int nWorldPts; /* Number of points in above array */ - - int drawUnder; /* If non-zero, draw the marker - * underneath any elements. This can be - * a performance penalty because the - * graph must be redraw entirely each - * time the marker is redrawn. */ - - int clipped; /* Indicates if the marker is totally - * clipped by the plotting area. */ - + int drawUnder; + int clipped; int hide; unsigned int flags; - - - int xOffset, yOffset; /* Pixel offset from graph position */ - + int xOffset; + int yOffset; int state; - XColor* fillColor; - XColor* outlineColor; /* Foreground and background colors */ - - int lineWidth; /* Line width. */ - int capStyle; /* Cap style. */ - int joinStyle; /* Join style.*/ - Blt_Dashes dashes; /* Dash list values (max 11) */ + // Fields specific to line - GC gc; /* Private graphic context */ - - Segment2d *segments; /* Malloc'ed array of points. - * Represents individual line segments - * (2 points per segment) comprising the - * mapped line. The segments may not - * necessarily be connected after - * clipping. */ - int nSegments; /* # segments in the above array. */ + Point2d *worldPts; + int nWorldPts; + XColor* fillColor; + XColor* outlineColor; + int lineWidth; + int capStyle; + int joinStyle; + Blt_Dashes dashes; + GC gc; + Segment2d *segments; + int nSegments; int xorr; - int xorState; /* State of the XOR drawing. Indicates - * if the marker is currently drawn. */ + int xorState; }; #endif diff --git a/src/bltGrMarkerPolygon.C b/src/bltGrMarkerPolygon.C index db4a80d..fd07701 100644 --- a/src/bltGrMarkerPolygon.C +++ b/src/bltGrMarkerPolygon.C @@ -33,6 +33,55 @@ extern "C" { #include "bltGrMarkerPolygon.h" +static int GetCoordinate(Tcl_Interp* interp, Tcl_Obj *objPtr, double *valuePtr); +static Tcl_Obj* PrintCoordinate(double x); +static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, + int objc, Tcl_Obj* const objv[]); +// OptionSpecs + +static Tk_CustomOptionSetProc CoordsSetProc; +static Tk_CustomOptionGetProc CoordsGetProc; +static Tk_ObjCustomOption coordsObjOption = + { + "coords", CoordsSetProc, CoordsGetProc, NULL, NULL, NULL + }; + +static int CoordsSetProc(ClientData clientData, Tcl_Interp* interp, + Tk_Window tkwin, Tcl_Obj** objPtr, char* widgRec, + int offset, char* save, int flags) +{ + Marker* markerPtr = (Marker*)widgRec; + + int objc; + Tcl_Obj** objv; + if (Tcl_ListObjGetElements(interp, *objPtr, &objc, &objv) != TCL_OK) + return TCL_ERROR; + + if (objc == 0) + return TCL_OK; + + return ParseCoordinates(interp, markerPtr, objc, objv); +} + +static Tcl_Obj* CoordsGetProc(ClientData clientData, Tk_Window tkwin, + char *widgRec, int offset) +{ + PolygonMarker* pmPtr = (PolygonMarker*)widgRec; + + int cnt = pmPtr->nWorldPts*2; + Tcl_Obj** ll = (Tcl_Obj**)calloc(cnt, sizeof(Tcl_Obj*)); + + Point2d* pp = pmPtr->worldPts; + for (int ii=0; ii < pmPtr->nWorldPts*2; pp++) { + ll[ii++] = PrintCoordinate(pp->x); + ll[ii++] = PrintCoordinate(pp->y); + } + + Tcl_Obj* listObjPtr = Tcl_NewListObj(cnt, ll); + free(ll); + return listObjPtr; +} + static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CUSTOM, "-bindtags", "bindTags", "BindTags", "Polygon all", -1, Tk_Offset(PolygonMarker, obj.tags), @@ -115,9 +164,9 @@ static int PointInPolygonProc(Marker *markerPtr, Point2d *samplePtr) { PolygonMarker *pmPtr = (PolygonMarker *)markerPtr; - if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts)) { + if ((pmPtr->nWorldPts >= 3) && (pmPtr->screenPts)) { return Blt_PointInPolygon(samplePtr, pmPtr->screenPts, - markerPtr->nWorldPts + 1); + pmPtr->nWorldPts + 1); } return FALSE; } @@ -127,9 +176,9 @@ static int RegionInPolygonProc(Marker *markerPtr, Region2d *extsPtr, { PolygonMarker *pmPtr = (PolygonMarker *)markerPtr; - if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts)) { + if ((pmPtr->nWorldPts >= 3) && (pmPtr->screenPts)) { return Blt_RegionInPolygon(extsPtr, pmPtr->screenPts, - markerPtr->nWorldPts, enclosed); + pmPtr->nWorldPts, enclosed); } return FALSE; } @@ -357,7 +406,7 @@ static void MapPolygonProc(Marker *markerPtr) free(pmPtr->screenPts); pmPtr->screenPts = NULL; } - if (markerPtr->nWorldPts < 3) { + if (pmPtr->nWorldPts < 3) { return; /* Too few points */ } @@ -365,33 +414,33 @@ static void MapPolygonProc(Marker *markerPtr) * Allocate and fill a temporary array to hold the screen coordinates of * the polygon. */ - int nScreenPts = markerPtr->nWorldPts + 1; + int nScreenPts = pmPtr->nWorldPts + 1; Point2d* screenPts = (Point2d*)malloc((nScreenPts + 1) * sizeof(Point2d)); { Point2d *sp, *dp, *send; dp = screenPts; - for (sp = markerPtr->worldPts, send = sp + markerPtr->nWorldPts; + for (sp = pmPtr->worldPts, send = sp + pmPtr->nWorldPts; sp < send; sp++) { - *dp = Blt_MapPoint(sp, &markerPtr->axes); - dp->x += markerPtr->xOffset; - dp->y += markerPtr->yOffset; + *dp = Blt_MapPoint(sp, &pmPtr->axes); + dp->x += pmPtr->xOffset; + dp->y += pmPtr->yOffset; dp++; } *dp = screenPts[0]; } Region2d extents; Blt_GraphExtents(graphPtr, &extents); - markerPtr->clipped = TRUE; + pmPtr->clipped = TRUE; if (pmPtr->fill) { /* Polygon fill required. */ Point2d* fillPts = (Point2d*)malloc(sizeof(Point2d) * nScreenPts * 3); - int n = Blt_PolyRectClip(&extents, screenPts, markerPtr->nWorldPts,fillPts); + int n = Blt_PolyRectClip(&extents, screenPts, pmPtr->nWorldPts,fillPts); if (n < 3) { free(fillPts); } else { pmPtr->nFillPts = n; pmPtr->fillPts = fillPts; - markerPtr->clipped = FALSE; + pmPtr->clipped = FALSE; } } if ((pmPtr->outline) && (pmPtr->lineWidth > 0)) { @@ -421,9 +470,92 @@ static void MapPolygonProc(Marker *markerPtr) pmPtr->nOutlinePts = segPtr - outlinePts; pmPtr->outlinePts = outlinePts; if (pmPtr->nOutlinePts > 0) { - markerPtr->clipped = FALSE; + pmPtr->clipped = FALSE; } } pmPtr->screenPts = screenPts; } +static int ParseCoordinates(Tcl_Interp* interp, Marker *markerPtr, + int objc, Tcl_Obj* const objv[]) +{ + PolygonMarker* pmPtr = (PolygonMarker*)markerPtr; + + if (objc == 0) + return TCL_OK; + + if (objc & 1) { + Tcl_AppendResult(interp, "odd number of marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + + int minArgs = 6; + int maxArgs = 0; + if (objc < minArgs) { + Tcl_AppendResult(interp, "too few marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + if ((maxArgs > 0) && (objc > maxArgs)) { + Tcl_AppendResult(interp, "too many marker coordinates specified", + (char*)NULL); + return TCL_ERROR; + } + int nWorldPts = objc / 2; + Point2d* worldPts = (Point2d*)malloc(nWorldPts * sizeof(Point2d)); + if (worldPts == NULL) { + Tcl_AppendResult(interp, "can't allocate new coordinate array", + (char*)NULL); + return TCL_ERROR; + } + + Point2d* pp = worldPts; + for (int ii=0; iix = x, pp->y = y, pp++; + } + + // Don't free the old coordinate array until we've parsed the new + // coordinates without errors. + if (pmPtr->worldPts) + free(pmPtr->worldPts); + + pmPtr->worldPts = worldPts; + pmPtr->nWorldPts = nWorldPts; + pmPtr->flags |= MAP_ITEM; + + return TCL_OK; +} + +static Tcl_Obj* PrintCoordinate(double x) +{ + if (x == DBL_MAX) + return Tcl_NewStringObj("+Inf", -1); + else if (x == -DBL_MAX) + return Tcl_NewStringObj("-Inf", -1); + else + return Tcl_NewDoubleObj(x); +} + +static int GetCoordinate(Tcl_Interp* interp, Tcl_Obj *objPtr, double *valuePtr) +{ + const char* expr = Tcl_GetString(objPtr); + char c = expr[0]; + if ((c == 'I') && (strcmp(expr, "Inf") == 0)) + *valuePtr = DBL_MAX; /* Elastic upper bound */ + else if ((c == '-') && (expr[1] == 'I') && (strcmp(expr, "-Inf") == 0)) + *valuePtr = -DBL_MAX; /* Elastic lower bound */ + else if ((c == '+') && (expr[1] == 'I') && (strcmp(expr, "+Inf") == 0)) + *valuePtr = DBL_MAX; /* Elastic upper bound */ + else if (Blt_ExprDoubleFromObj(interp, objPtr, valuePtr) != TCL_OK) + return TCL_ERROR; + + return TCL_OK; +} + diff --git a/src/bltGrMarkerPolygon.h b/src/bltGrMarkerPolygon.h index 45c70d1..8b29075 100644 --- a/src/bltGrMarkerPolygon.h +++ b/src/bltGrMarkerPolygon.h @@ -34,90 +34,43 @@ class PolygonMarker { public: - GraphObj obj; /* Must be first field in marker. */ - + GraphObj obj; MarkerClass *classPtr; - - Tk_OptionTable optionTable; /* Configuration specifications */ + Tk_OptionTable optionTable; Tcl_HashEntry *hashPtr; - Blt_ChainLink link; - - const char* elemName; /* Element associated with marker. Let's - * you link a marker to an element. The - * marker is drawn only if the element - * is also visible. */ + const char* elemName; Axis2d axes; - - Point2d *worldPts; /* Coordinate array to position - * marker. */ - - int nWorldPts; /* Number of points in above array */ - - int drawUnder; /* If non-zero, draw the marker - * underneath any elements. This can be - * a performance penalty because the - * graph must be redraw entirely each - * time the marker is redrawn. */ - - int clipped; /* Indicates if the marker is totally - * clipped by the plotting area. */ - + int drawUnder; + int clipped; int hide; unsigned int flags; - - - int xOffset, yOffset; /* Pixel offset from graph position */ - + int xOffset; + int yOffset; int state; - // derived - - Point2d *screenPts; /* Array of points representing the - * polygon in screen coordinates. It's - * not used for drawing, but to generate - * the outlinePts and fillPts arrays - * that are the coordinates of the - * possibly clipped outline and filled - * polygon. */ + // Fields specific to polygon + Point2d *worldPts; + int nWorldPts; + Point2d *screenPts; XColor* outline; XColor* outlineBg; XColor* fill; XColor* fillBg; - - Pixmap stipple; /* Stipple pattern to fill the - * polygon. */ - int lineWidth; /* Width of polygon outline. */ + Pixmap stipple; + int lineWidth; int capStyle; int joinStyle; - Blt_Dashes dashes; /* List of dash values. Indicates how - * to draw the dashed line. If no dash - * values are provided, or the first - * value is zero, then the line is drawn - * solid. */ - - GC outlineGC; /* Graphics context to draw the outline - * of the polygon. */ - GC fillGC; /* Graphics context to draw the filled - * polygon. */ - - Point2d *fillPts; /* Malloc'ed array of points used to - * draw the filled polygon. These points - * may form a degenerate polygon after - * clipping. */ - int nFillPts; /* # points in the above array. */ - Segment2d *outlinePts; /* Malloc'ed array of points. - * Represents individual line segments - * (2 points per segment) comprising the - * outline of the polygon. The segments - * may not necessarily be closed or - * connected after clipping. */ - int nOutlinePts; /* # points in the above array. */ + Blt_Dashes dashes; + GC outlineGC; + GC fillGC; + Point2d *fillPts; + int nFillPts; + Segment2d *outlinePts; + int nOutlinePts; int xorr; - int xorState; /* State of the XOR drawing. Indicates - * if the marker is visible. We have to - * drawn it again to erase it. */ + int xorState; }; #endif diff --git a/src/bltGrMarkerText.C b/src/bltGrMarkerText.C index 6060c08..224368a 100644 --- a/src/bltGrMarkerText.C +++ b/src/bltGrMarkerText.C @@ -43,9 +43,6 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CUSTOM, "-bindtags", "bindTags", "BindTags", "Text all", -1, Tk_Offset(TextMarker, obj.tags), TK_OPTION_NULL_OK, &listObjOption, 0}, - {TK_OPTION_CUSTOM, "-coords", "coords", "Coords", - NULL, -1, Tk_Offset(TextMarker, worldPts), - TK_OPTION_NULL_OK, &coordsObjOption, 0}, {TK_OPTION_STRING, "-element", "element", "Element", NULL, -1, Tk_Offset(TextMarker, elemName), TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_SYNONYM, "-fg", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, @@ -53,8 +50,7 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_FONT, "-font", "font", "Font", STD_FONT_NORMAL, -1, Tk_Offset(TextMarker, style.font), 0, NULL, 0}, {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground", - STD_NORMAL_FOREGROUND, -1, Tk_Offset(TextMarker, style.color), - TK_OPTION_NULL_OK, NULL, 0}, + STD_NORMAL_FOREGROUND, -1, Tk_Offset(TextMarker, style.color), 0, NULL, 0}, {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify", "left", -1, Tk_Offset(TextMarker, style.justify), 0, NULL, 0}, {TK_OPTION_BOOLEAN, "-hide", "hide", "Hide", @@ -64,10 +60,6 @@ static Tk_OptionSpec optionSpecs[] = { {TK_OPTION_CUSTOM, "-mapy", "mapY", "MapY", "y", -1, Tk_Offset(TextMarker, axes.y), 0, &yAxisObjOption, 0}, {TK_OPTION_SYNONYM, "-outline", NULL, NULL, NULL, -1, 0, 0, "-foreground", 0}, - {TK_OPTION_PIXELS, "-padx", "padX", "PadX", - "4", -1, Tk_Offset(TextMarker, style.xPad), 0, NULL, 0}, - {TK_OPTION_PIXELS, "-pady", "padY", "PadY", - "4", -1, Tk_Offset(TextMarker, style.yPad), 0, NULL, 0}, {TK_OPTION_DOUBLE, "-rotate", "rotate", "Rotate", "0", -1, Tk_Offset(TextMarker, style.angle), 0, NULL, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", @@ -76,8 +68,12 @@ static Tk_OptionSpec optionSpecs[] = { NULL, -1, Tk_Offset(TextMarker, string), TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_BOOLEAN, "-under", "under", "Under", "no", -1, Tk_Offset(TextMarker, drawUnder), 0, NULL, 0}, + {TK_OPTION_DOUBLE, "-x", "x", "X", + "0", -1, Tk_Offset(TextMarker, world.x), 0, NULL, 0}, {TK_OPTION_PIXELS, "-xoffset", "xOffset", "XOffset", "0", -1, Tk_Offset(TextMarker, xOffset), 0, NULL, 0}, + {TK_OPTION_DOUBLE, "-y", "y", "Y", + "0", -1, Tk_Offset(TextMarker, world.y), 0, NULL, 0}, {TK_OPTION_PIXELS, "-yoffset", "yOffset", "YOffset", "0", -1, Tk_Offset(TextMarker, yOffset), 0, NULL, 0}, {TK_OPTION_END, NULL, NULL, NULL, NULL, -1, 0, 0, NULL, 0} @@ -110,200 +106,183 @@ Marker* Blt_CreateTextProc(Graph* graphPtr) Blt_Ts_InitStyle(tmPtr->style); tmPtr->optionTable = Tk_CreateOptionTable(graphPtr->interp, optionSpecs); - return (Marker *)tmPtr; + return (Marker*)tmPtr; } -static int ConfigureTextProc(Marker *markerPtr) +static int ConfigureTextProc(Marker* markerPtr) { Graph* graphPtr = markerPtr->obj.graphPtr; - TextMarker *tmPtr = (TextMarker *)markerPtr; - GC newGC; - XGCValues gcValues; - unsigned long gcMask; + TextMarker* tmPtr = (TextMarker*)markerPtr; tmPtr->style.angle = (float)fmod(tmPtr->style.angle, 360.0); if (tmPtr->style.angle < 0.0f) { tmPtr->style.angle += 360.0f; } - newGC = NULL; + + GC newGC = NULL; + XGCValues gcValues; + unsigned long gcMask; if (tmPtr->fillColor) { gcMask = GCForeground; gcValues.foreground = tmPtr->fillColor->pixel; newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues); } - if (tmPtr->fillGC) { + if (tmPtr->fillGC) Tk_FreeGC(graphPtr->display, tmPtr->fillGC); - } tmPtr->fillGC = newGC; markerPtr->flags |= MAP_ITEM; - if (markerPtr->drawUnder) { + if (markerPtr->drawUnder) graphPtr->flags |= CACHE_DIRTY; - } + Blt_EventuallyRedrawGraph(graphPtr); return TCL_OK; } -static void MapTextProc(Marker *markerPtr) +static void MapTextProc(Marker* markerPtr) { Graph* graphPtr = markerPtr->obj.graphPtr; - TextMarker *tmPtr = (TextMarker *)markerPtr; - Region2d extents; - Point2d anchorPt; - int i; - unsigned int w, h; - double rw, rh; + TextMarker* tmPtr = (TextMarker*)markerPtr; - tmPtr->width = tmPtr->height = 0; - if (tmPtr->string == NULL) { + if (!tmPtr->string) return; - } + + tmPtr->width =0; + tmPtr->height =0; + + unsigned int w, h; Blt_Ts_GetExtents(&tmPtr->style, tmPtr->string, &w, &h); + + double rw, rh; Blt_GetBoundingBox(w, h, tmPtr->style.angle, &rw, &rh, tmPtr->outline); tmPtr->width = ROUND(rw); tmPtr->height = ROUND(rh); - for (i = 0; i < 4; i++) { - tmPtr->outline[i].x += ROUND(rw * 0.5); - tmPtr->outline[i].y += ROUND(rh * 0.5); + for (int ii=0; ii<4; ii++) { + tmPtr->outline[ii].x += ROUND(rw * 0.5); + tmPtr->outline[ii].y += ROUND(rh * 0.5); } tmPtr->outline[4].x = tmPtr->outline[0].x; tmPtr->outline[4].y = tmPtr->outline[0].y; - anchorPt = Blt_MapPoint(markerPtr->worldPts, &markerPtr->axes); - anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, (double)(tmPtr->width), - (double)(tmPtr->height), tmPtr->anchor); + + Point2d anchorPt = Blt_MapPoint(&tmPtr->world, &markerPtr->axes); + anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, tmPtr->width, + tmPtr->height, tmPtr->anchor); anchorPt.x += markerPtr->xOffset; anchorPt.y += markerPtr->yOffset; - /* - * Determine the bounding box of the text and test to see if it is at - * least partially contained within the plotting area. - */ + + Region2d extents; extents.left = anchorPt.x; extents.top = anchorPt.y; extents.right = anchorPt.x + tmPtr->width - 1; extents.bottom = anchorPt.y + tmPtr->height - 1; markerPtr->clipped = Blt_BoxesDontOverlap(graphPtr, &extents); tmPtr->anchorPt = anchorPt; - } -static int PointInTextProc(Marker *markerPtr, Point2d *samplePtr) +static int PointInTextProc(Marker* markerPtr, Point2d *samplePtr) { - TextMarker *tmPtr = (TextMarker *)markerPtr; + TextMarker* tmPtr = (TextMarker*)markerPtr; - if (tmPtr->string == NULL) { + if (!tmPtr->string) return 0; - } + if (tmPtr->style.angle != 0.0f) { Point2d points[5]; - int i; - - /* - * Figure out the bounding polygon (isolateral) for the text and see - * if the point is inside of it. - */ - for (i = 0; i < 5; i++) { - points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x; - points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y; + + // Figure out the bounding polygon (isolateral) for the text and see + // if the point is inside of it. + for (int ii=0; ii<5; ii++) { + points[ii].x = tmPtr->outline[ii].x + tmPtr->anchorPt.x; + points[ii].y = tmPtr->outline[ii].y + tmPtr->anchorPt.y; } return Blt_PointInPolygon(samplePtr, points, 5); } + return ((samplePtr->x >= tmPtr->anchorPt.x) && (samplePtr->x < (tmPtr->anchorPt.x + tmPtr->width)) && (samplePtr->y >= tmPtr->anchorPt.y) && (samplePtr->y < (tmPtr->anchorPt.y + tmPtr->height))); } -static int RegionInTextProc(Marker *markerPtr, Region2d *extsPtr, int enclosed) +static int RegionInTextProc(Marker* markerPtr, Region2d *extsPtr, int enclosed) { - TextMarker *tmPtr = (TextMarker *)markerPtr; + TextMarker* tmPtr = (TextMarker*)markerPtr; - if (markerPtr->nWorldPts < 1) { - return FALSE; - } if (tmPtr->style.angle != 0.0f) { + // Generate the bounding polygon (isolateral) for the bitmap and see + // if the point is inside of it. Point2d points[5]; - int i; - - /* - * Generate the bounding polygon (isolateral) for the bitmap and see - * if the point is inside of it. - */ - for (i = 0; i < 4; i++) { - points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x; - points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y; + for (int ii=0; ii<4; ii++) { + points[ii].x = tmPtr->outline[ii].x + tmPtr->anchorPt.x; + points[ii].y = tmPtr->outline[ii].y + tmPtr->anchorPt.y; } return Blt_RegionInPolygon(extsPtr, points, 4, enclosed); } - if (enclosed) { + + if (enclosed) return ((tmPtr->anchorPt.x >= extsPtr->left) && (tmPtr->anchorPt.y >= extsPtr->top) && ((tmPtr->anchorPt.x + tmPtr->width) <= extsPtr->right) && ((tmPtr->anchorPt.y + tmPtr->height) <= extsPtr->bottom)); - } + return !((tmPtr->anchorPt.x >= extsPtr->right) || (tmPtr->anchorPt.y >= extsPtr->bottom) || ((tmPtr->anchorPt.x + tmPtr->width) <= extsPtr->left) || ((tmPtr->anchorPt.y + tmPtr->height) <= extsPtr->top)); } -static void DrawTextProc(Marker *markerPtr, Drawable drawable) +static void DrawTextProc(Marker* markerPtr, Drawable drawable) { - TextMarker *tmPtr = (TextMarker *)markerPtr; + TextMarker* tmPtr = (TextMarker*)markerPtr; Graph* graphPtr = markerPtr->obj.graphPtr; - if (tmPtr->string == NULL) { + if (!tmPtr->string) return; - } + if (tmPtr->fillGC) { + // Simulate the rotated background of the bitmap by filling a bounding + // polygon with the background color. XPoint points[4]; - int i; - - /* - * Simulate the rotated background of the bitmap by filling a bounding - * polygon with the background color. - */ - for (i = 0; i < 4; i++) { - points[i].x = (short int)(tmPtr->outline[i].x + tmPtr->anchorPt.x); - points[i].y = (short int)(tmPtr->outline[i].y + tmPtr->anchorPt.y); + for (int ii=0; ii<4; ii++) { + points[ii].x = (short int)(tmPtr->outline[ii].x + tmPtr->anchorPt.x); + points[ii].y = (short int)(tmPtr->outline[ii].y + tmPtr->anchorPt.y); } XFillPolygon(graphPtr->display, drawable, tmPtr->fillGC, points, 4, Convex, CoordModeOrigin); } - if (tmPtr->style.color) { - Blt_Ts_DrawText(graphPtr->tkwin, drawable, tmPtr->string, -1, - &tmPtr->style, (int)tmPtr->anchorPt.x, (int)tmPtr->anchorPt.y); - } + + // be sure to update style->gc, things might have changed + tmPtr->style.flags |= UPDATE_GC; + Blt_Ts_DrawText(graphPtr->tkwin, drawable, tmPtr->string, -1, + &tmPtr->style, tmPtr->anchorPt.x, tmPtr->anchorPt.y); } -static void TextToPostscriptProc(Marker *markerPtr, Blt_Ps ps) +static void TextToPostscriptProc(Marker* markerPtr, Blt_Ps ps) { - TextMarker *tmPtr = (TextMarker *)markerPtr; + TextMarker* tmPtr = (TextMarker*)markerPtr; - if (tmPtr->string == NULL) { + if (!tmPtr->string) return; - } + if (tmPtr->fillGC) { + // Simulate the rotated background of the bitmap by filling a bounding + // polygon with the background color. Point2d points[4]; - int i; - - /* - * Simulate the rotated background of the bitmap by filling a bounding - * polygon with the background color. - */ - for (i = 0; i < 4; i++) { - points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x; - points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y; + for (int ii=0; ii<4; ii++) { + points[ii].x = tmPtr->outline[ii].x + tmPtr->anchorPt.x; + points[ii].y = tmPtr->outline[ii].y + tmPtr->anchorPt.y; } Blt_Ps_XSetBackground(ps, tmPtr->fillColor); Blt_Ps_XFillPolygon(ps, points, 4); } + Blt_Ps_DrawText(ps, tmPtr->string, &tmPtr->style, tmPtr->anchorPt.x, tmPtr->anchorPt.y); } -static void FreeTextProc(Marker *markerPtr) +static void FreeTextProc(Marker* markerPtr) { - TextMarker *tmPtr = (TextMarker *)markerPtr; + TextMarker* tmPtr = (TextMarker*)markerPtr; Graph* graphPtr = markerPtr->obj.graphPtr; Blt_Ts_FreeStyle(graphPtr->display, &tmPtr->style); diff --git a/src/bltGrMarkerText.h b/src/bltGrMarkerText.h index b3e289d..7c26501 100644 --- a/src/bltGrMarkerText.h +++ b/src/bltGrMarkerText.h @@ -34,43 +34,30 @@ class TextMarker { public: - GraphObj obj; /* Must be first field in marker. */ + GraphObj obj; MarkerClass *classPtr; - - Tk_OptionTable optionTable; /* Configuration specifications */ + Tk_OptionTable optionTable; Tcl_HashEntry *hashPtr; Blt_ChainLink link; - const char* elemName; /* Element associated with marker. Let's - * you link a marker to an element. The - * marker is drawn only if the element - * is also visible. */ + const char* elemName; Axis2d axes; - Point2d *worldPts; /* Coordinate array to position - * marker. */ - int nWorldPts; /* # of points in above array */ - int drawUnder; /* If non-zero, draw the marker - * underneath any elements. This can be - * a performance penalty because the - * graph must be redraw entirely each - * time the marker is redrawn. */ - int clipped; /* Indicates if the marker is totally - * clipped by the plotting area. */ + int drawUnder; + int clipped; int hide; unsigned int flags; - - - int xOffset, yOffset; /* Pixel offset from graph position */ + int xOffset; + int yOffset; int state; - /* Fields specific to text markers. */ - const char* string; /* Text string to be display. The - * string make contain newlines. */ - Tk_Anchor anchor; /* Indicates how to translate the given - * marker position. */ - Point2d anchorPt; /* Translated anchor point. */ - int width, height; /* Dimension of bounding box. */ - TextStyle style; /* Text attributes (font, fg, anchor, - * etc) */ + // Fields specific to text + + Point2d world; + const char* string; + Tk_Anchor anchor; + Point2d anchorPt; + int width; + int height; + TextStyle style; Point2d outline[5]; XColor* fillColor; GC fillGC; diff --git a/src/bltGrText.C b/src/bltGrText.C index 1f3f0e5..eec1086 100644 --- a/src/bltGrText.C +++ b/src/bltGrText.C @@ -48,73 +48,58 @@ extern "C" { void Blt_GetTextExtents(Tk_Font font, int leader, const char *text, int textLen, unsigned int *widthPtr, unsigned int *heightPtr) { - unsigned int lineHeight; - - if (text == NULL) + if (!text) { + *widthPtr =0; + *heightPtr =0; return; + } - { - Tk_FontMetrics fm; + Tk_FontMetrics fm; + Tk_GetFontMetrics(font, &fm); + unsigned int lineHeight = fm.linespace; - Tk_GetFontMetrics(font, &fm); - lineHeight = fm.linespace; - } - if (textLen < 0) { + if (textLen < 0) textLen = strlen(text); - } - { - unsigned int lineLen; /* # of characters on each line */ - const char *p, *pend; - const char *line; - unsigned int maxWidth, maxHeight; - - maxWidth = maxHeight = 0; - lineLen = 0; - for (p = line = text, pend = text + textLen; p < pend; p++) { - if (*p == '\n') { - if (lineLen > 0) { - unsigned int lineWidth; - - lineWidth = Tk_TextWidth(font, line, lineLen); - if (lineWidth > maxWidth) { - maxWidth = lineWidth; - } - } - maxHeight += lineHeight; - line = p + 1; /* Point to the start of the next line. */ - lineLen = 0; /* Reset counter to indicate the start of a - * new line. */ - continue; + + unsigned int maxWidth =0; + unsigned int maxHeight =0; + unsigned int lineLen =0; + const char *line =NULL; + const char *p, *pend; + for (p = line = text, pend = text + textLen; p < pend; p++) { + if (*p == '\n') { + if (lineLen > 0) { + unsigned int lineWidth = Tk_TextWidth(font, line, lineLen); + if (lineWidth > maxWidth) + maxWidth = lineWidth; } - lineLen++; - } - if ((lineLen > 0) && (*(p - 1) != '\n')) { - unsigned int lineWidth; - maxHeight += lineHeight; - lineWidth = Tk_TextWidth(font, line, lineLen); - if (lineWidth > maxWidth) { - maxWidth = lineWidth; - } + line = p + 1; /* Point to the start of the next line. */ + lineLen = 0; /* Reset counter to indicate the start of a + * new line. */ + continue; } - *widthPtr = maxWidth; - *heightPtr = maxHeight; + lineLen++; + } + + if ((lineLen > 0) && (*(p - 1) != '\n')) { + maxHeight += lineHeight; + unsigned int lineWidth = Tk_TextWidth(font, line, lineLen); + if (lineWidth > maxWidth) + maxWidth = lineWidth; } + + *widthPtr = maxWidth; + *heightPtr = maxHeight; } void Blt_Ts_GetExtents(TextStyle *tsPtr, const char *text, unsigned int *widthPtr, unsigned int *heightPtr) { - - if (text == NULL) - *widthPtr = *heightPtr = 0; - else { - unsigned int w, h; - - Blt_GetTextExtents(tsPtr->font, tsPtr->leader, text, -1, &w, &h); - *widthPtr = w + 2*tsPtr->xPad; - *heightPtr = h + 2*tsPtr->yPad; - } + unsigned int w, h; + Blt_GetTextExtents(tsPtr->font, tsPtr->leader, text, -1, &w, &h); + *widthPtr = w + 2*tsPtr->xPad; + *heightPtr = h + 2*tsPtr->yPad; } /* @@ -161,11 +146,10 @@ void Blt_GetBoundingBox(int width, int height, float angle, if (fmod(angle, (double)90.0) == 0.0) { int ll, ur, ul, lr; double rotWidth, rotHeight; - int quadrant; /* Handle right-angle rotations specially. */ - quadrant = (int)(angle / 90.0); + int quadrant = (int)(angle / 90.0); switch (quadrant) { case ROTATE_270: /* 270 degrees */ ul = 3, ur = 0, lr = 1, ll = 2; @@ -216,12 +200,12 @@ void Blt_GetBoundingBox(int width, int height, float angle, for (i = 0; i < 4; i++) { x = (corner[i].x * cosTheta) - (corner[i].y * sinTheta); y = (corner[i].x * sinTheta) + (corner[i].y * cosTheta); - if (x > xMax) { + if (x > xMax) xMax = x; - } - if (y > yMax) { + + if (y > yMax) yMax = y; - } + if (bbox) { bbox[i].x = x; bbox[i].y = y; @@ -335,19 +319,16 @@ static Point2d Rotate_Text(int x, int y, int w1, int h1, TextStyle* stylePtr) void Blt_Ts_DrawText(Tk_Window tkwin, Drawable drawable, const char *text, int textLen, TextStyle *stylePtr,int x, int y) { - Tk_TextLayout layout; - int w1, h1; - Point2d rr; - - if ((text == NULL) || (*text == '\0')) + if (!text || !(*text)) return; if ((stylePtr->gc == NULL) || (stylePtr->flags & UPDATE_GC)) Blt_Ts_ResetStyle(tkwin, stylePtr); - layout = Tk_ComputeTextLayout(stylePtr->font, text, textLen,-1, - stylePtr->justify, 0, &w1, &h1); - rr = Rotate_Text(x, y, w1, h1, stylePtr); + int w1, h1; + Tk_TextLayout layout = Tk_ComputeTextLayout(stylePtr->font, text, textLen,-1, + stylePtr->justify, 0, &w1, &h1); + Point2d rr = Rotate_Text(x, y, w1, h1, stylePtr); TkDrawAngledTextLayout(Tk_Display(tkwin), drawable, stylePtr->gc, layout, rr.x, rr.y, stylePtr->angle, 0, textLen); } @@ -355,19 +336,16 @@ void Blt_Ts_DrawText(Tk_Window tkwin, Drawable drawable, const char *text, void Blt_DrawText2(Tk_Window tkwin, Drawable drawable, const char *text, TextStyle *stylePtr, int x, int y, Dim2D *areaPtr) { - Tk_TextLayout layout; - int w1, h1; - Point2d rr; - - if ((text == NULL) || (*text == '\0')) + if (!text || !(*text)) return; if ((stylePtr->gc == NULL) || (stylePtr->flags & UPDATE_GC)) Blt_Ts_ResetStyle(tkwin, stylePtr); - layout = Tk_ComputeTextLayout(stylePtr->font, text, -1, -1, + int w1, h1; + Tk_TextLayout layout = Tk_ComputeTextLayout(stylePtr->font, text, -1, -1, stylePtr->justify, 0, &w1, &h1); - rr = Rotate_Text(x, y, w1, h1, stylePtr); + Point2d rr = Rotate_Text(x, y, w1, h1, stylePtr); TkDrawAngledTextLayout(Tk_Display(tkwin), drawable, stylePtr->gc, layout, rr.x, rr.y, stylePtr->angle, 0, -1); @@ -377,7 +355,6 @@ void Blt_DrawText2(Tk_Window tkwin, Drawable drawable, const char *text, if (angle != 0.0) { double rotWidth, rotHeight; - Blt_GetBoundingBox(w1, h1, angle, &rotWidth, &rotHeight, (Point2d *)NULL); w1 = ROUND(rotWidth); @@ -391,19 +368,16 @@ void Blt_DrawText2(Tk_Window tkwin, Drawable drawable, const char *text, void Blt_DrawText(Tk_Window tkwin, Drawable drawable, const char *text, TextStyle *stylePtr, int x, int y) { - Tk_TextLayout layout; - int w1, h1; - Point2d rr; - if (!text || (*text == '\0')) return; if (!stylePtr->gc || (stylePtr->flags & UPDATE_GC)) Blt_Ts_ResetStyle(tkwin, stylePtr); - layout = Tk_ComputeTextLayout(stylePtr->font, text, -1, -1, + int w1, h1; + Tk_TextLayout layout = Tk_ComputeTextLayout(stylePtr->font, text, -1, -1, stylePtr->justify, 0, &w1, &h1); - rr = Rotate_Text(x, y, w1, h1, stylePtr); + Point2d rr = Rotate_Text(x, y, w1, h1, stylePtr); TkDrawAngledTextLayout(Tk_Display(tkwin), drawable, stylePtr->gc, layout, rr.x, rr.y, stylePtr->angle, 0, -1); } diff --git a/src/bltGrText.h b/src/bltGrText.h index ec9399e..f01aa85 100644 --- a/src/bltGrText.h +++ b/src/bltGrText.h @@ -30,18 +30,8 @@ #ifndef _BLT_TEXT_H #define _BLT_TEXT_H -#define DEF_TEXT_FLAGS (TK_PARTIAL_OK | TK_IGNORE_NEWLINES) #define UPDATE_GC 1 -/* - * TextStyle -- - * - * A somewhat convenient structure to hold text attributes that determine - * how a text string is to be displayed on the screen or drawn with - * PostScript commands. The alternative is to pass lots of parameters to - * the drawing and printing routines. This seems like a more efficient - * and less cumbersome way of passing parameters. - */ typedef struct { unsigned int state; /* If non-zero, indicates to draw text * in the active color */ diff --git a/tests/bitmapmarker.tcl b/tests/bitmapmarker.tcl index b71e58d..8d8f108 100644 --- a/tests/bitmapmarker.tcl +++ b/tests/bitmapmarker.tcl @@ -4,15 +4,13 @@ set w .line set graph [bltLineGraph $w] set mm [$graph marker create bitmap tt -element data1 \ - -coords {1.5 100} -bitmap error] -return + -x 1.5 -y 100 -bitmap error] + bltTest3 $graph marker $mm -anchor nw bltTest3 $graph marker $mm -background yellow bltTest3 $graph marker $mm -bg red bltTest3 $graph marker $mm -bindtags {aa} bltTest3 $graph marker $mm -bitmap hourglass -bltTest3 $graph marker $mm -coords {1 50} -bltTest3 $graph marker $mm -coords {1 50 1.1 60} bltTest3 $graph marker $mm -element data2 bltTest3 $graph marker $mm -fg cyan bltTest3 $graph marker $mm -fill yellow @@ -23,7 +21,9 @@ bltTest3 $graph marker $mm -mapy y bltTest3 $graph marker $mm -outline green bltTest3 $graph marker $mm -state disabled bltTest3 $graph marker $mm -under yes +bltTest3 $graph marker $mm -x 1 bltTest3 $graph marker $mm -xoffset 20 +bltTest3 $graph marker $mm -y 150 bltTest3 $graph marker $mm -yoffset 20 echo "done" diff --git a/tests/textmarker.tcl b/tests/textmarker.tcl index 29da9b2..3d1fa2a 100644 --- a/tests/textmarker.tcl +++ b/tests/textmarker.tcl @@ -5,7 +5,7 @@ set graph [bltLineGraph $w] set mm [$graph marker create text tt -element data1 \ -x 1.5 -y 100 -text {Text Marker} -font {24}] -return + bltTest3 $graph marker $mm -anchor nw bltTest3 $graph marker $mm -background blue bltTest3 $graph marker $mm -bg red -- cgit v0.12