summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bltGrMarkerBitmap.C482
-rw-r--r--bltGrMarkerBitmap.h104
-rw-r--r--src/bltGrMarker.C599
-rw-r--r--src/bltGrMarker.h105
4 files changed, 710 insertions, 580 deletions
diff --git a/bltGrMarkerBitmap.C b/bltGrMarkerBitmap.C
new file mode 100644
index 0000000..fe8913b
--- /dev/null
+++ b/bltGrMarkerBitmap.C
@@ -0,0 +1,482 @@
+/*
+ * Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+ * This code has been modified under the terms listed below and is made
+ * available under the same terms.
+ */
+
+/*
+ * bltGrMarkerBitmap.c --
+ *
+ * This module implements markers for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltGrElem.h"
+#include "bltBitmap.h"
+#include "bltConfig.h"
+#include "bltGrMarkerBitmap.h"
+
+#define GETBITMAP(b) (((b)->destBitmap == None) ? (b)->srcBitmap : (b)->destBitmap)
+
+static Blt_ConfigSpec bitmapConfigSpecs[] = {
+ {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center",
+ Tk_Offset(BitmapMarker, anchor), 0},
+ {BLT_CONFIG_COLOR, "-background", "background", "Background",
+ "white", Tk_Offset(BitmapMarker, fillColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char*)NULL, (char*)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags", "Bitmap all",
+ Tk_Offset(BitmapMarker, obj.tags), BLT_CONFIG_NULL_OK,
+ &listOption},
+ {BLT_CONFIG_BITMAP, "-bitmap", "bitmap", "Bitmap", NULL,
+ Tk_Offset(BitmapMarker, srcBitmap), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", NULL,
+ Tk_Offset(BitmapMarker, worldPts), BLT_CONFIG_NULL_OK,
+ &coordsOption},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", NULL,
+ Tk_Offset(BitmapMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char*)NULL, (char*)NULL, 0, 0},
+ {BLT_CONFIG_SYNONYM, "-fill", "background", (char*)NULL, (char*)NULL,
+ 0, 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ "black", Tk_Offset(BitmapMarker, outlineColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide", "no",
+ Tk_Offset(BitmapMarker, hide), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", "x",
+ Tk_Offset(BitmapMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", "y",
+ Tk_Offset(BitmapMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char*)NULL, (char*)NULL, NULL,
+ Tk_Offset(BitmapMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char*)NULL, (char*)NULL,
+ 0, 0},
+ {BLT_CONFIG_DOUBLE, "-rotate", "rotate", "Rotate", "0",
+ Tk_Offset(BitmapMarker, reqAngle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-state", "state", "State", "normal",
+ Tk_Offset(BitmapMarker, state), BLT_CONFIG_DONT_SET_DEFAULT, &stateOption},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", "no",
+ Tk_Offset(BitmapMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", "0",
+ Tk_Offset(BitmapMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", "0",
+ Tk_Offset(BitmapMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigureBitmapProc;
+MarkerCreateProc Blt_CreateBitmapProc;
+static MarkerDrawProc DrawBitmapProc;
+static MarkerFreeProc FreeBitmapProc;
+static MarkerMapProc MapBitmapProc;
+static MarkerPointProc PointInBitmapProc;
+static MarkerPostscriptProc BitmapToPostscriptProc;
+static MarkerRegionProc RegionInBitmapProc;
+
+static MarkerClass bitmapMarkerClass = {
+ bitmapConfigSpecs,
+ ConfigureBitmapProc,
+ DrawBitmapProc,
+ FreeBitmapProc,
+ MapBitmapProc,
+ PointInBitmapProc,
+ RegionInBitmapProc,
+ BitmapToPostscriptProc,
+};
+
+Marker* Blt_CreateBitmapProc(void)
+{
+ BitmapMarker *bmPtr;
+
+ bmPtr = calloc(1, sizeof(BitmapMarker));
+ bmPtr->classPtr = &bitmapMarkerClass;
+ return (Marker *)bmPtr;
+}
+
+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) {
+ return TCL_OK;
+ }
+ bmPtr->angle = fmod(bmPtr->reqAngle, 360.0);
+ if (bmPtr->angle < 0.0) {
+ bmPtr->angle += 360.0;
+ }
+ gcMask = 0;
+
+ if (bmPtr->outlineColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = bmPtr->outlineColor->pixel;
+ }
+
+ if (bmPtr->fillColor != NULL) {
+ /* 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;
+ 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 != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->gc);
+ }
+ bmPtr->gc = newGC;
+
+ /* Create the background GC containing the fill color. */
+
+ if (bmPtr->fillColor != NULL) {
+ gcValues.foreground = bmPtr->fillColor->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (bmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
+ }
+ bmPtr->fillGC = newGC;
+ }
+
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+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) {
+ return;
+ }
+ 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;
+ }
+ 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;
+ 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;
+ }
+ 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;
+
+ /*
+ * 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;
+ }
+ }
+}
+
+static int PointInBitmapProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+
+ if (bmPtr->srcBitmap == 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->y >= bmPtr->anchorPt.y) &&
+ (samplePtr->y < (bmPtr->anchorPt.y + bmPtr->destHeight)));
+}
+
+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));
+ }
+ 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));
+}
+
+static void DrawBitmapProc(Marker *markerPtr, Drawable drawable)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ double rangle;
+ Pixmap bitmap;
+
+ bitmap = GETBITMAP(bmPtr);
+ if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
+ return;
+ }
+ 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 != NULL) {
+ 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 {
+ 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);
+}
+
+static void BitmapToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ Pixmap bitmap;
+
+ bitmap = GETBITMAP(bmPtr);
+ if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
+ return; /* No bitmap to display. */
+ }
+ if (bmPtr->fillColor != NULL) {
+ Blt_Ps_XSetBackground(ps, bmPtr->fillColor);
+ Blt_Ps_XFillPolygon(ps, bmPtr->outline, 4);
+ }
+ Blt_Ps_XSetForeground(ps, bmPtr->outlineColor);
+
+ 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);
+ 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);
+ Blt_Ps_VarAppend(ps,
+ " } imagemask\n",
+ "grestore\n", (char*)NULL);
+}
+
+static void FreeBitmapProc(Marker *markerPtr)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+
+ if (bmPtr->gc != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->gc);
+ }
+ if (bmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
+ }
+ if (bmPtr->destBitmap != None) {
+ Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap);
+ }
+}
+
diff --git a/bltGrMarkerBitmap.h b/bltGrMarkerBitmap.h
new file mode 100644
index 0000000..19a7420
--- /dev/null
+++ b/bltGrMarkerBitmap.h
@@ -0,0 +1,104 @@
+/*
+ * Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+ * This code has been modified under the terms listed below and is made
+ * available under the same terms.
+ */
+
+/*
+ * bltGrMarkerBitmap.c --
+ *
+ * This module implements markers for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GR_MARKER_BITMAP_H
+#define _BLT_GR_MARKER_BITMAP_H
+
+#include "bltGrMarker.h"
+
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ 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. */
+ 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 hide;
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ 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. */
+ int nOutlinePts;
+} BitmapMarker;
+
+extern MarkerCreateProc Blt_CreateBitmapProc;
+
+#endif
diff --git a/src/bltGrMarker.C b/src/bltGrMarker.C
index 1e3e46c..0dc71dd 100644
--- a/src/bltGrMarker.C
+++ b/src/bltGrMarker.C
@@ -38,222 +38,33 @@
#include "bltGrElem.h"
#include "bltBitmap.h"
#include "bltConfig.h"
+#include "bltGrMarker.h"
+#include "bltGrMarkerBitmap.h"
typedef int (GraphMarkerProc)(Graph* graphPtr, Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[]);
-#define GETBITMAP(b) (((b)->destBitmap == None) ? (b)->srcBitmap : (b)->destBitmap)
-#define MAX_OUTLINE_POINTS 12
#define NORMALIZE(A,x) (((x) - (A)->axisRange.min) * (A)->axisRange.scale)
static Blt_OptionParseProc ObjToCoordsProc;
static Blt_OptionPrintProc CoordsToObjProc;
static Blt_OptionFreeProc FreeCoordsProc;
-static Blt_CustomOption coordsOption =
+Blt_CustomOption coordsOption =
{
- ObjToCoordsProc, CoordsToObjProc, FreeCoordsProc, (ClientData)0
+ ObjToCoordsProc, CoordsToObjProc, FreeCoordsProc, NULL
};
+
static Blt_OptionFreeProc FreeColorPairProc;
static Blt_OptionParseProc ObjToColorPairProc;
static Blt_OptionPrintProc ColorPairToObjProc;
-static Blt_CustomOption colorPairOption =
+Blt_CustomOption colorPairOption =
{
ObjToColorPairProc, ColorPairToObjProc, FreeColorPairProc, (ClientData)0
};
-extern Blt_CustomOption bltXAxisOption;
-extern Blt_CustomOption bltYAxisOption;
-
-typedef Marker *(MarkerCreateProc)(void);
-typedef void (MarkerDrawProc)(Marker *markerPtr, Drawable drawable);
-typedef void (MarkerFreeProc)(Marker *markerPtr);
-typedef int (MarkerConfigProc)(Marker *markerPtr);
-typedef void (MarkerMapProc)(Marker *markerPtr);
-typedef void (MarkerPostscriptProc)(Marker *markerPtr, Blt_Ps ps);
-typedef int (MarkerPointProc)(Marker *markerPtr, Point2d *samplePtr);
-typedef int (MarkerRegionProc)(Marker *markerPtr, Region2d *extsPtr,
- int enclosed);
-
static Tcl_FreeProc FreeMarker;
typedef struct {
- Blt_ConfigSpec *configSpecs; /* Marker configuration
- * specifications */
- MarkerConfigProc *configProc;
- MarkerDrawProc *drawProc;
- MarkerFreeProc *freeProc;
- MarkerMapProc *mapProc;
- MarkerPointProc *pointProc;
- MarkerRegionProc *regionProc;
- MarkerPostscriptProc *postscriptProc;
-
-} MarkerClass;
-
-struct _Marker {
- GraphObj obj; /* Must be first field in marker. */
-
- MarkerClass *classPtr;
-
- 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. */
- 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 hide;
- unsigned int flags;
-
-
- int xOffset, yOffset; /* Pixel offset from graph position */
-
- int state;
-};
-
-typedef struct {
- GraphObj obj; /* Must be first field in marker. */
-
- MarkerClass *classPtr;
-
- 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. */
- 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 hide;
- unsigned int flags;
-
-
- int xOffset, yOffset; /* Pixel offset from graph position */
-
- 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. */
- int nOutlinePts;
-} BitmapMarker;
-
-static Blt_ConfigSpec bitmapConfigSpecs[] = {
- {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", "center",
- Tk_Offset(BitmapMarker, anchor), 0},
- {BLT_CONFIG_COLOR, "-background", "background", "Background",
- "white", Tk_Offset(BitmapMarker, fillColor),
- BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_SYNONYM, "-bg", "background", (char*)NULL, (char*)NULL, 0, 0},
- {BLT_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags", "Bitmap all",
- Tk_Offset(BitmapMarker, obj.tags), BLT_CONFIG_NULL_OK,
- &listOption},
- {BLT_CONFIG_BITMAP, "-bitmap", "bitmap", "Bitmap", NULL,
- Tk_Offset(BitmapMarker, srcBitmap), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", NULL,
- Tk_Offset(BitmapMarker, worldPts), BLT_CONFIG_NULL_OK,
- &coordsOption},
- {BLT_CONFIG_STRING, "-element", "element", "Element", NULL,
- Tk_Offset(BitmapMarker, elemName), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char*)NULL, (char*)NULL, 0, 0},
- {BLT_CONFIG_SYNONYM, "-fill", "background", (char*)NULL, (char*)NULL,
- 0, 0},
- {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
- "black", Tk_Offset(BitmapMarker, outlineColor),
- BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide", "no",
- Tk_Offset(BitmapMarker, hide), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", "x",
- Tk_Offset(BitmapMarker, axes.x), 0, &bltXAxisOption},
- {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", "y",
- Tk_Offset(BitmapMarker, axes.y), 0, &bltYAxisOption},
- {BLT_CONFIG_STRING, "-name", (char*)NULL, (char*)NULL, NULL,
- Tk_Offset(BitmapMarker, obj.name), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char*)NULL, (char*)NULL,
- 0, 0},
- {BLT_CONFIG_DOUBLE, "-rotate", "rotate", "Rotate", "0",
- Tk_Offset(BitmapMarker, reqAngle), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-state", "state", "State", "normal",
- Tk_Offset(BitmapMarker, state), BLT_CONFIG_DONT_SET_DEFAULT, &stateOption},
- {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", "no",
- Tk_Offset(BitmapMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", "0",
- Tk_Offset(BitmapMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", "0",
- Tk_Offset(BitmapMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-static MarkerConfigProc ConfigureBitmapProc;
-static MarkerCreateProc CreateBitmapProc;
-static MarkerDrawProc DrawBitmapProc;
-static MarkerFreeProc FreeBitmapProc;
-static MarkerMapProc MapBitmapProc;
-static MarkerPointProc PointInBitmapProc;
-static MarkerPostscriptProc BitmapToPostscriptProc;
-static MarkerRegionProc RegionInBitmapProc;
-
-static MarkerClass bitmapMarkerClass = {
- bitmapConfigSpecs,
- ConfigureBitmapProc,
- DrawBitmapProc,
- FreeBitmapProc,
- MapBitmapProc,
- PointInBitmapProc,
- RegionInBitmapProc,
- BitmapToPostscriptProc,
-};
-
-typedef struct {
GraphObj obj; /* Must be first field in marker. */
MarkerClass *classPtr;
@@ -750,7 +561,7 @@ static MarkerClass windowMarkerClass = {
WindowToPostscriptProc,
};
-static int BoxesDontOverlap(Graph* graphPtr, Region2d *extsPtr)
+int Blt_BoxesDontOverlap(Graph* graphPtr, Region2d *extsPtr)
{
return (((double)graphPtr->right < extsPtr->left) ||
((double)graphPtr->bottom < extsPtr->top) ||
@@ -1111,7 +922,7 @@ static double VMap(Axis *axisPtr, double y)
return (((1.0 - y) * axisPtr->screenRange) + axisPtr->screenMin);
}
-static Point2d MapPoint(Point2d *pointPtr, Axis2d *axesPtr)
+Point2d Blt_MapPoint(Point2d *pointPtr, Axis2d *axesPtr)
{
Point2d result;
Graph* graphPtr = axesPtr->y->obj.graphPtr;
@@ -1131,7 +942,7 @@ static Marker* CreateMarker(Graph* graphPtr, const char* name, ClassId classId)
Marker *markerPtr;
switch (classId) {
case CID_MARKER_BITMAP:
- markerPtr = CreateBitmapProc(); /* bitmap */
+ markerPtr = Blt_CreateBitmapProc(); /* bitmap */
break;
case CID_MARKER_LINE:
markerPtr = CreateLineProc(); /* line */
@@ -1199,378 +1010,6 @@ static void FreeMarker(char* dataPtr)
DestroyMarker(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) {
- return TCL_OK;
- }
- bmPtr->angle = fmod(bmPtr->reqAngle, 360.0);
- if (bmPtr->angle < 0.0) {
- bmPtr->angle += 360.0;
- }
- gcMask = 0;
-
- if (bmPtr->outlineColor != NULL) {
- gcMask |= GCForeground;
- gcValues.foreground = bmPtr->outlineColor->pixel;
- }
-
- if (bmPtr->fillColor != NULL) {
- /* 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;
- 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 != NULL) {
- Tk_FreeGC(graphPtr->display, bmPtr->gc);
- }
- bmPtr->gc = newGC;
-
- /* Create the background GC containing the fill color. */
-
- if (bmPtr->fillColor != NULL) {
- gcValues.foreground = bmPtr->fillColor->pixel;
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- if (bmPtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
- }
- bmPtr->fillGC = newGC;
- }
-
- markerPtr->flags |= MAP_ITEM;
- if (markerPtr->drawUnder) {
- graphPtr->flags |= CACHE_DIRTY;
- }
-
- Blt_EventuallyRedrawGraph(graphPtr);
- return TCL_OK;
-}
-
-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) {
- return;
- }
- 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 = MapPoint(markerPtr->worldPts, &markerPtr->axes);
- if (markerPtr->nWorldPts > 1) {
- double hold;
-
- corner2 = 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;
- }
- 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;
- markerPtr->clipped = 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;
- }
- 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;
-
- /*
- * 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;
- }
- }
-}
-
-static int PointInBitmapProc(Marker *markerPtr, Point2d *samplePtr)
-{
- BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
-
- if (bmPtr->srcBitmap == 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->y >= bmPtr->anchorPt.y) &&
- (samplePtr->y < (bmPtr->anchorPt.y + bmPtr->destHeight)));
-}
-
-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));
- }
- 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));
-}
-
-static void DrawBitmapProc(Marker *markerPtr, Drawable drawable)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
- double rangle;
- Pixmap bitmap;
-
- bitmap = GETBITMAP(bmPtr);
- if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
- return;
- }
- 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 != NULL) {
- 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 {
- 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);
-}
-
-static void BitmapToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
- Pixmap bitmap;
-
- bitmap = GETBITMAP(bmPtr);
- if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
- return; /* No bitmap to display. */
- }
- if (bmPtr->fillColor != NULL) {
- Blt_Ps_XSetBackground(ps, bmPtr->fillColor);
- Blt_Ps_XFillPolygon(ps, bmPtr->outline, 4);
- }
- Blt_Ps_XSetForeground(ps, bmPtr->outlineColor);
-
- 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);
- 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);
- Blt_Ps_VarAppend(ps,
- " } imagemask\n",
- "grestore\n", (char*)NULL);
-}
-
-static void FreeBitmapProc(Marker *markerPtr)
-{
- BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
- Graph* graphPtr = markerPtr->obj.graphPtr;
-
- if (bmPtr->gc != NULL) {
- Tk_FreeGC(graphPtr->display, bmPtr->gc);
- }
- if (bmPtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
- }
- if (bmPtr->destBitmap != None) {
- Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap);
- }
-}
-
-static Marker* CreateBitmapProc(void)
-{
- BitmapMarker *bmPtr;
-
- bmPtr = calloc(1, sizeof(BitmapMarker));
- bmPtr->classPtr = &bitmapMarkerClass;
- return (Marker *)bmPtr;
-}
-
static int ConfigureTextProc(Marker *markerPtr)
{
Graph* graphPtr = markerPtr->obj.graphPtr;
@@ -1626,7 +1065,7 @@ static void MapTextProc(Marker *markerPtr)
}
tmPtr->outline[4].x = tmPtr->outline[0].x;
tmPtr->outline[4].y = tmPtr->outline[0].y;
- anchorPt = MapPoint(markerPtr->worldPts, &markerPtr->axes);
+ anchorPt = Blt_MapPoint(markerPtr->worldPts, &markerPtr->axes);
anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, (double)(tmPtr->width),
(double)(tmPtr->height), tmPtr->anchor);
anchorPt.x += markerPtr->xOffset;
@@ -1639,7 +1078,7 @@ static void MapTextProc(Marker *markerPtr)
extents.top = anchorPt.y;
extents.right = anchorPt.x + tmPtr->width - 1;
extents.bottom = anchorPt.y + tmPtr->height - 1;
- markerPtr->clipped = BoxesDontOverlap(graphPtr, &extents);
+ markerPtr->clipped = Blt_BoxesDontOverlap(graphPtr, &extents);
tmPtr->anchorPt = anchorPt;
}
@@ -1844,7 +1283,7 @@ static void MapWindowProc(Marker *markerPtr)
if (wmPtr->child == (Tk_Window)NULL) {
return;
}
- anchorPt = MapPoint(markerPtr->worldPts, &markerPtr->axes);
+ anchorPt = Blt_MapPoint(markerPtr->worldPts, &markerPtr->axes);
width = Tk_ReqWidth(wmPtr->child);
height = Tk_ReqHeight(wmPtr->child);
@@ -1869,7 +1308,7 @@ static void MapWindowProc(Marker *markerPtr)
extents.top = wmPtr->anchorPt.y;
extents.right = wmPtr->anchorPt.x + wmPtr->width - 1;
extents.bottom = wmPtr->anchorPt.y + wmPtr->height - 1;
- markerPtr->clipped = BoxesDontOverlap(graphPtr, &extents);
+ markerPtr->clipped = Blt_BoxesDontOverlap(graphPtr, &extents);
}
static int PointInWindowProc(Marker *markerPtr, Point2d *samplePtr)
@@ -2017,7 +1456,7 @@ static void MapLineProc(Marker *markerPtr)
*/
segments = malloc(markerPtr->nWorldPts * sizeof(Segment2d));
srcPtr = markerPtr->worldPts;
- p = MapPoint(srcPtr, &markerPtr->axes);
+ p = Blt_MapPoint(srcPtr, &markerPtr->axes);
p.x += markerPtr->xOffset;
p.y += markerPtr->yOffset;
@@ -2026,7 +1465,7 @@ static void MapLineProc(Marker *markerPtr)
srcPtr < pend; srcPtr++) {
Point2d next;
- next = MapPoint(srcPtr, &markerPtr->axes);
+ next = Blt_MapPoint(srcPtr, &markerPtr->axes);
next.x += markerPtr->xOffset;
next.y += markerPtr->yOffset;
q = next;
@@ -2063,7 +1502,7 @@ static int RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
pp < pend; pp++) {
Point2d p;
- p = MapPoint(pp, &markerPtr->axes);
+ p = Blt_MapPoint(pp, &markerPtr->axes);
if ((p.x < extsPtr->left) && (p.x > extsPtr->right) &&
(p.y < extsPtr->top) && (p.y > extsPtr->bottom)) {
return FALSE;
@@ -2079,8 +1518,8 @@ static int RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
pp < pend; pp++) {
Point2d p, q;
- p = MapPoint(pp, &markerPtr->axes);
- q = MapPoint(pp + 1, &markerPtr->axes);
+ p = Blt_MapPoint(pp, &markerPtr->axes);
+ q = Blt_MapPoint(pp + 1, &markerPtr->axes);
if (Blt_LineRectClip(extsPtr, &p, &q)) {
count++;
}
@@ -2256,7 +1695,7 @@ static void MapPolygonProc(Marker *markerPtr)
dp = screenPts;
for (sp = markerPtr->worldPts, send = sp + markerPtr->nWorldPts;
sp < send; sp++) {
- *dp = MapPoint(sp, &markerPtr->axes);
+ *dp = Blt_MapPoint(sp, &markerPtr->axes);
dp->x += markerPtr->xOffset;
dp->y += markerPtr->yOffset;
dp++;
diff --git a/src/bltGrMarker.h b/src/bltGrMarker.h
new file mode 100644
index 0000000..98fb5be
--- /dev/null
+++ b/src/bltGrMarker.h
@@ -0,0 +1,105 @@
+/*
+ * Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+ * This code has been modified under the terms listed below and is made
+ * available under the same terms.
+ */
+
+/*
+ * bltGrMarker.h --
+ *
+ * This module implements markers for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GR_MARKER_H
+#define _BLT_GR_MARKER_H
+
+#define MAX_OUTLINE_POINTS 12
+
+extern Blt_CustomOption coordsOption;
+extern Blt_CustomOption colorPairOption;
+extern Blt_CustomOption bltXAxisOption;
+extern Blt_CustomOption bltYAxisOption;
+
+typedef Marker *(MarkerCreateProc)(void);
+typedef void (MarkerDrawProc)(Marker *markerPtr, Drawable drawable);
+typedef void (MarkerFreeProc)(Marker *markerPtr);
+typedef int (MarkerConfigProc)(Marker *markerPtr);
+typedef void (MarkerMapProc)(Marker *markerPtr);
+typedef void (MarkerPostscriptProc)(Marker *markerPtr, Blt_Ps ps);
+typedef int (MarkerPointProc)(Marker *markerPtr, Point2d *samplePtr);
+typedef int (MarkerRegionProc)(Marker *markerPtr, Region2d *extsPtr,
+ int enclosed);
+
+typedef struct {
+ Blt_ConfigSpec *configSpecs; /* Marker configuration
+ * specifications */
+ MarkerConfigProc *configProc;
+ MarkerDrawProc *drawProc;
+ MarkerFreeProc *freeProc;
+ MarkerMapProc *mapProc;
+ MarkerPointProc *pointProc;
+ MarkerRegionProc *regionProc;
+ MarkerPostscriptProc *postscriptProc;
+
+} MarkerClass;
+
+struct _Marker {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ 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. */
+ 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 hide;
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+};
+
+Point2d Blt_MapPoint(Point2d *pointPtr, Axis2d *axesPtr);
+int Blt_BoxesDontOverlap(Graph* graphPtr, Region2d *extsPtr);
+
+#endif