summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure1
-rwxr-xr-xconfigure.in1
-rw-r--r--src/bltGrMarker.C485
-rw-r--r--src/bltGrMarkerPolygon.C433
-rw-r--r--src/bltGrMarkerPolygon.h119
5 files changed, 556 insertions, 483 deletions
diff --git a/configure b/configure
index 980c6bb..f9fb410 100755
--- a/configure
+++ b/configure
@@ -5539,6 +5539,7 @@ done
bltGrMarker.c
bltGrMarkerBitmap.c
bltGrMarkerLine.c
+ bltGrMarkerPolygon.c
bltGrMisc.c
bltGrPen.c
bltGrPs.c
diff --git a/configure.in b/configure.in
index e5cd63f..33bb2c0 100755
--- a/configure.in
+++ b/configure.in
@@ -84,6 +84,7 @@ TEA_ADD_SOURCES([
bltGrMarker.c
bltGrMarkerBitmap.c
bltGrMarkerLine.c
+ bltGrMarkerPolygon.c
bltGrMisc.c
bltGrPen.c
bltGrPs.c
diff --git a/src/bltGrMarker.C b/src/bltGrMarker.C
index f0ed514..c208fcb 100644
--- a/src/bltGrMarker.C
+++ b/src/bltGrMarker.C
@@ -35,6 +35,7 @@
#include "bltGrMarker.h"
#include "bltGrMarkerBitmap.h"
#include "bltGrMarkerLine.h"
+#include "bltGrMarkerPolygon.h"
typedef int (GraphMarkerProc)(Graph* graphPtr, Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[]);
@@ -59,154 +60,7 @@ Blt_CustomOption colorPairOption =
static Tcl_FreeProc FreeMarker;
-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; /* 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 *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. */
-
- ColorPair outline;
- ColorPair fill;
-
- Pixmap stipple; /* Stipple pattern to fill the
- * polygon. */
- int lineWidth; /* Width of polygon outline. */
- 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. */
- int xor;
- int xorState; /* State of the XOR drawing. Indicates
- * if the marker is visible. We have to
- * drawn it again to erase it. */
-} PolygonMarker;
-
-
-static Blt_ConfigSpec polygonConfigSpecs[] = {
- {BLT_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags", "Polygon all",
- Tk_Offset(PolygonMarker, obj.tags), BLT_CONFIG_NULL_OK,
- &listOption},
- {BLT_CONFIG_CAP_STYLE, "-cap", "cap", "Cap", "butt",
- Tk_Offset(PolygonMarker, capStyle), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", NULL,
- Tk_Offset(PolygonMarker, worldPts), BLT_CONFIG_NULL_OK, &coordsOption},
- {BLT_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes", NULL,
- Tk_Offset(PolygonMarker, dashes), BLT_CONFIG_NULL_OK, &dashesOption},
- {BLT_CONFIG_STRING, "-element", "element", "Element", NULL,
- Tk_Offset(PolygonMarker, elemName), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_CUSTOM, "-fill", "fill", "Fill", "rred",
- Tk_Offset(PolygonMarker, fill), BLT_CONFIG_NULL_OK, &colorPairOption},
- {BLT_CONFIG_JOIN_STYLE, "-join", "join", "Join", "miter",
- Tk_Offset(PolygonMarker, joinStyle), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-linewidth", "lineWidth", "LineWidth",
- "1", Tk_Offset(PolygonMarker, lineWidth),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide", "no",
- Tk_Offset(PolygonMarker, hide), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", "x",
- Tk_Offset(PolygonMarker, axes.x), 0, &bltXAxisOption},
- {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", "y",
- Tk_Offset(PolygonMarker, axes.y), 0, &bltYAxisOption},
- {BLT_CONFIG_STRING, "-name", (char*)NULL, (char*)NULL, NULL,
- Tk_Offset(PolygonMarker, obj.name), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- "black", Tk_Offset(PolygonMarker, outline),
- BLT_CONFIG_NULL_OK, &colorPairOption},
- {BLT_CONFIG_CUSTOM, "-state", "state", "State", "normal",
- Tk_Offset(PolygonMarker, state), BLT_CONFIG_DONT_SET_DEFAULT, &stateOption},
- {BLT_CONFIG_BITMAP, "-stipple", "stipple", "Stipple", NULL,
- Tk_Offset(PolygonMarker, stipple), BLT_CONFIG_NULL_OK},
- {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", "no",
- Tk_Offset(PolygonMarker, drawUnder),
- BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", "0",
- Tk_Offset(PolygonMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_BOOLEAN, "-xor", "xor", "Xor", "no",
- Tk_Offset(PolygonMarker, xor), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", "0",
- Tk_Offset(PolygonMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
- {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-static MarkerConfigProc ConfigurePolygonProc;
-static MarkerCreateProc CreatePolygonProc;
-static MarkerDrawProc DrawPolygonProc;
-static MarkerFreeProc FreePolygonProc;
-static MarkerMapProc MapPolygonProc;
-static MarkerPointProc PointInPolygonProc;
-static MarkerPostscriptProc PolygonToPostscriptProc;
-static MarkerRegionProc RegionInPolygonProc;
-
-static MarkerClass polygonMarkerClass = {
- polygonConfigSpecs,
- ConfigurePolygonProc,
- DrawPolygonProc,
- FreePolygonProc,
- MapPolygonProc,
- PointInPolygonProc,
- RegionInPolygonProc,
- PolygonToPostscriptProc,
-};
typedef struct {
GraphObj obj; /* Must be first field in marker. */
@@ -824,7 +678,7 @@ static Marker* CreateMarker(Graph* graphPtr, const char* name, ClassId classId)
markerPtr = CreateTextProc(); /* text */
break;
case CID_MARKER_POLYGON:
- markerPtr = CreatePolygonProc(); /* polygon */
+ markerPtr = Blt_CreatePolygonProc(); /* polygon */
break;
case CID_MARKER_WINDOW:
markerPtr = CreateWindowProc(); /* window */
@@ -1300,341 +1154,6 @@ static void ChildCustodyProc(ClientData clientData, Tk_Window tkwin)
Blt_EventuallyRedrawGraph(graphPtr);
}
-static void MapPolygonProc(Marker *markerPtr)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
- Point2d *screenPts;
- Region2d extents;
- int nScreenPts;
-
- if (pmPtr->outlinePts != NULL) {
- free(pmPtr->outlinePts);
- pmPtr->outlinePts = NULL;
- pmPtr->nOutlinePts = 0;
- }
- if (pmPtr->fillPts != NULL) {
- free(pmPtr->fillPts);
- pmPtr->fillPts = NULL;
- pmPtr->nFillPts = 0;
- }
- if (pmPtr->screenPts != NULL) {
- free(pmPtr->screenPts);
- pmPtr->screenPts = NULL;
- }
- if (markerPtr->nWorldPts < 3) {
- return; /* Too few points */
- }
-
- /*
- * Allocate and fill a temporary array to hold the screen coordinates of
- * the polygon.
- */
- nScreenPts = markerPtr->nWorldPts + 1;
- screenPts = malloc((nScreenPts + 1) * sizeof(Point2d));
- {
- Point2d *sp, *dp, *send;
-
- dp = screenPts;
- for (sp = markerPtr->worldPts, send = sp + markerPtr->nWorldPts;
- sp < send; sp++) {
- *dp = Blt_MapPoint(sp, &markerPtr->axes);
- dp->x += markerPtr->xOffset;
- dp->y += markerPtr->yOffset;
- dp++;
- }
- *dp = screenPts[0];
- }
- Blt_GraphExtents(graphPtr, &extents);
- markerPtr->clipped = TRUE;
- if (pmPtr->fill.fgColor != NULL) { /* Polygon fill required. */
- Point2d *fillPts;
- int n;
-
- fillPts = malloc(sizeof(Point2d) * nScreenPts * 3);
- n = Blt_PolyRectClip(&extents, screenPts, markerPtr->nWorldPts,fillPts);
- if (n < 3) {
- free(fillPts);
- } else {
- pmPtr->nFillPts = n;
- pmPtr->fillPts = fillPts;
- markerPtr->clipped = FALSE;
- }
- }
- if ((pmPtr->outline.fgColor != NULL) && (pmPtr->lineWidth > 0)) {
- Segment2d *outlinePts;
- Segment2d *segPtr;
- Point2d *sp, *send;
-
- /*
- * Generate line segments representing the polygon outline. The
- * resulting outline may or may not be closed from viewport clipping.
- */
- outlinePts = malloc(nScreenPts * sizeof(Segment2d));
- if (outlinePts == NULL) {
- return; /* Can't allocate point array */
- }
- /*
- * Note that this assumes that the point array contains an extra point
- * that closes the polygon.
- */
- segPtr = outlinePts;
- for (sp = screenPts, send = sp + (nScreenPts - 1); sp < send; sp++) {
- segPtr->p = sp[0];
- segPtr->q = sp[1];
- if (Blt_LineRectClip(&extents, &segPtr->p, &segPtr->q)) {
- segPtr++;
- }
- }
- pmPtr->nOutlinePts = segPtr - outlinePts;
- pmPtr->outlinePts = outlinePts;
- if (pmPtr->nOutlinePts > 0) {
- markerPtr->clipped = FALSE;
- }
- }
- pmPtr->screenPts = screenPts;
-}
-
-static int PointInPolygonProc(Marker *markerPtr, Point2d *samplePtr)
-{
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
-
- if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
- return Blt_PointInPolygon(samplePtr, pmPtr->screenPts,
- markerPtr->nWorldPts + 1);
- }
- return FALSE;
-}
-
-static int RegionInPolygonProc(Marker *markerPtr, Region2d *extsPtr,
- int enclosed)
-{
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
-
- if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
- return Blt_RegionInPolygon(extsPtr, pmPtr->screenPts,
- markerPtr->nWorldPts, enclosed);
- }
- return FALSE;
-}
-
-static void DrawPolygonProc(Marker *markerPtr, Drawable drawable)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
-
- /* Draw polygon fill region */
- if ((pmPtr->nFillPts > 0) && (pmPtr->fill.fgColor != NULL)) {
- XPoint *dp, *points;
- Point2d *sp, *send;
-
- points = malloc(pmPtr->nFillPts * sizeof(XPoint));
- if (points == NULL) {
- return;
- }
- dp = points;
- for (sp = pmPtr->fillPts, send = sp + pmPtr->nFillPts; sp < send;
- sp++) {
- dp->x = (short int)sp->x;
- dp->y = (short int)sp->y;
- dp++;
- }
-
- XFillPolygon(graphPtr->display, drawable, pmPtr->fillGC, points,
- pmPtr->nFillPts, Complex, CoordModeOrigin);
- free(points);
- }
- /* and then the outline */
- if ((pmPtr->nOutlinePts > 0) && (pmPtr->lineWidth > 0) &&
- (pmPtr->outline.fgColor != NULL)) {
- Blt_Draw2DSegments(graphPtr->display, drawable, pmPtr->outlineGC,
- pmPtr->outlinePts, pmPtr->nOutlinePts);
- }
-}
-
-static void PolygonToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
-
- if (pmPtr->fill.fgColor != NULL) {
-
- /*
- * Options: fg bg
- * Draw outline only.
- * x Draw solid or stipple.
- * x x Draw solid or stipple.
- */
-
- /* Create a path to use for both the polygon and its outline. */
- Blt_Ps_Polyline(ps, pmPtr->fillPts, pmPtr->nFillPts);
-
- /* If the background fill color was specified, draw the polygon in a
- * solid fashion with that color. */
- if (pmPtr->fill.bgColor != NULL) {
- /* Draw the solid background as the background layer of the opaque
- * stipple */
- Blt_Ps_XSetBackground(ps, pmPtr->fill.bgColor);
- /* Retain the path. We'll need it for the foreground layer. */
- Blt_Ps_Append(ps, "gsave fill grestore\n");
- }
- Blt_Ps_XSetForeground(ps, pmPtr->fill.fgColor);
- if (pmPtr->stipple != None) {
- /* Draw the stipple in the foreground color. */
- Blt_Ps_XSetStipple(ps, graphPtr->display, pmPtr->stipple);
- } else {
- Blt_Ps_Append(ps, "fill\n");
- }
- }
-
- /* Draw the outline in the foreground color. */
- if ((pmPtr->lineWidth > 0) && (pmPtr->outline.fgColor != NULL)) {
-
- /* Set up the line attributes. */
- Blt_Ps_XSetLineAttributes(ps, pmPtr->outline.fgColor,
- pmPtr->lineWidth, &pmPtr->dashes, pmPtr->capStyle,
- pmPtr->joinStyle);
-
- /*
- * Define on-the-fly a PostScript macro "DashesProc" that will be
- * executed for each call to the Polygon drawing routine. If the line
- * isn't dashed, simply make this an empty definition.
- */
- if ((pmPtr->outline.bgColor != NULL) && (LineIsDashed(pmPtr->dashes))) {
- Blt_Ps_Append(ps, "/DashesProc {\ngsave\n ");
- Blt_Ps_XSetBackground(ps, pmPtr->outline.bgColor);
- Blt_Ps_Append(ps, " ");
- Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
- Blt_Ps_Append(ps, "stroke\n grestore\n} def\n");
- } else {
- Blt_Ps_Append(ps, "/DashesProc {} def\n");
- }
- Blt_Ps_Draw2DSegments(ps, pmPtr->outlinePts, pmPtr->nOutlinePts);
- }
-}
-
-static int ConfigurePolygonProc(Marker *markerPtr)
-{
- Graph* graphPtr = markerPtr->obj.graphPtr;
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
- GC newGC;
- XGCValues gcValues;
- unsigned long gcMask;
- Drawable drawable;
-
- drawable = Tk_WindowId(graphPtr->tkwin);
- gcMask = (GCLineWidth | GCLineStyle);
- if (pmPtr->outline.fgColor != NULL) {
- gcMask |= GCForeground;
- gcValues.foreground = pmPtr->outline.fgColor->pixel;
- }
- if (pmPtr->outline.bgColor != NULL) {
- gcMask |= GCBackground;
- gcValues.background = pmPtr->outline.bgColor->pixel;
- }
- gcMask |= (GCCapStyle | GCJoinStyle);
- gcValues.cap_style = pmPtr->capStyle;
- gcValues.join_style = pmPtr->joinStyle;
- gcValues.line_style = LineSolid;
- gcValues.dash_offset = 0;
- gcValues.line_width = LineWidth(pmPtr->lineWidth);
- if (LineIsDashed(pmPtr->dashes)) {
- gcValues.line_style = (pmPtr->outline.bgColor == NULL)
- ? LineOnOffDash : LineDoubleDash;
- }
- if (pmPtr->xor) {
- unsigned long pixel;
- gcValues.function = GXxor;
-
- gcMask |= GCFunction;
- pixel = Tk_3DBorderColor(graphPtr->plotBg)->pixel;
- if (gcMask & GCBackground) {
- gcValues.background ^= pixel;
- }
- gcValues.foreground ^= pixel;
- if (drawable != None) {
- DrawPolygonProc(markerPtr, drawable);
- }
- }
- newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
- if (LineIsDashed(pmPtr->dashes)) {
- Blt_SetDashes(graphPtr->display, newGC, &pmPtr->dashes);
- }
- if (pmPtr->outlineGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
- }
- pmPtr->outlineGC = newGC;
-
- gcMask = 0;
- if (pmPtr->fill.fgColor != NULL) {
- gcMask |= GCForeground;
- gcValues.foreground = pmPtr->fill.fgColor->pixel;
- }
- if (pmPtr->fill.bgColor != NULL) {
- gcMask |= GCBackground;
- gcValues.background = pmPtr->fill.bgColor->pixel;
- }
- if (pmPtr->stipple != None) {
- gcValues.stipple = pmPtr->stipple;
- gcValues.fill_style = (pmPtr->fill.bgColor != NULL)
- ? FillOpaqueStippled : FillStippled;
- gcMask |= (GCStipple | GCFillStyle);
- }
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- if (pmPtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
- }
- pmPtr->fillGC = newGC;
-
- if ((gcMask == 0) && !(graphPtr->flags & RESET_AXES) && (pmPtr->xor)) {
- if (drawable != None) {
- MapPolygonProc(markerPtr);
- DrawPolygonProc(markerPtr, drawable);
- }
- return TCL_OK;
- }
- markerPtr->flags |= MAP_ITEM;
- if (markerPtr->drawUnder) {
- graphPtr->flags |= CACHE_DIRTY;
- }
- graphPtr->flags |= RESET_WORLD;
- Blt_EventuallyRedrawGraph(graphPtr);
- return TCL_OK;
-}
-
-static void FreePolygonProc(Marker *markerPtr)
-{
- PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
- Graph* graphPtr = markerPtr->obj.graphPtr;
-
- if (pmPtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
- }
- if (pmPtr->outlineGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
- }
- if (pmPtr->fillPts != NULL) {
- free(pmPtr->fillPts);
- }
- if (pmPtr->outlinePts != NULL) {
- free(pmPtr->outlinePts);
- }
- if (pmPtr->screenPts != NULL) {
- free(pmPtr->screenPts);
- }
-}
-
-static Marker* CreatePolygonProc(void)
-{
- PolygonMarker *pmPtr;
-
- pmPtr = calloc(1, sizeof(PolygonMarker));
- pmPtr->classPtr = &polygonMarkerClass;
- pmPtr->capStyle = CapButt;
- pmPtr->joinStyle = JoinMiter;
- return (Marker *)pmPtr;
-}
-
static int GetMarkerFromObj(Tcl_Interp* interp, Graph* graphPtr,
Tcl_Obj *objPtr, Marker **markerPtrPtr)
{
diff --git a/src/bltGrMarkerPolygon.C b/src/bltGrMarkerPolygon.C
new file mode 100644
index 0000000..e959f28
--- /dev/null
+++ b/src/bltGrMarkerPolygon.C
@@ -0,0 +1,433 @@
+/*
+ * Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+ * This code has been modified under the terms listed below and is made
+ * available under the same terms.
+ */
+
+/*
+ * 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 "bltGraph.h"
+#include "bltGrMarkerPolygon.h"
+
+static Blt_ConfigSpec polygonConfigSpecs[] = {
+ {BLT_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags", "Polygon all",
+ Tk_Offset(PolygonMarker, obj.tags), BLT_CONFIG_NULL_OK,
+ &listOption},
+ {BLT_CONFIG_CAP_STYLE, "-cap", "cap", "Cap", "butt",
+ Tk_Offset(PolygonMarker, capStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", NULL,
+ Tk_Offset(PolygonMarker, worldPts), BLT_CONFIG_NULL_OK, &coordsOption},
+ {BLT_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes", NULL,
+ Tk_Offset(PolygonMarker, dashes), BLT_CONFIG_NULL_OK, &dashesOption},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", NULL,
+ Tk_Offset(PolygonMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-fill", "fill", "Fill", "rred",
+ Tk_Offset(PolygonMarker, fill), BLT_CONFIG_NULL_OK, &colorPairOption},
+ {BLT_CONFIG_JOIN_STYLE, "-join", "join", "Join", "miter",
+ Tk_Offset(PolygonMarker, joinStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-linewidth", "lineWidth", "LineWidth",
+ "1", Tk_Offset(PolygonMarker, lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide", "no",
+ Tk_Offset(PolygonMarker, hide), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", "x",
+ Tk_Offset(PolygonMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", "y",
+ Tk_Offset(PolygonMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char*)NULL, (char*)NULL, NULL,
+ Tk_Offset(PolygonMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-outline", "outline", "Outline",
+ "black", Tk_Offset(PolygonMarker, outline),
+ BLT_CONFIG_NULL_OK, &colorPairOption},
+ {BLT_CONFIG_CUSTOM, "-state", "state", "State", "normal",
+ Tk_Offset(PolygonMarker, state), BLT_CONFIG_DONT_SET_DEFAULT, &stateOption},
+ {BLT_CONFIG_BITMAP, "-stipple", "stipple", "Stipple", NULL,
+ Tk_Offset(PolygonMarker, stipple), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", "no",
+ Tk_Offset(PolygonMarker, drawUnder),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", "0",
+ Tk_Offset(PolygonMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-xor", "xor", "Xor", "no",
+ Tk_Offset(PolygonMarker, xor), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", "0",
+ Tk_Offset(PolygonMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+MarkerCreateProc Blt_CreatePolygonProc;
+static MarkerConfigProc ConfigurePolygonProc;
+static MarkerDrawProc DrawPolygonProc;
+static MarkerFreeProc FreePolygonProc;
+static MarkerMapProc MapPolygonProc;
+static MarkerPointProc PointInPolygonProc;
+static MarkerPostscriptProc PolygonToPostscriptProc;
+static MarkerRegionProc RegionInPolygonProc;
+
+static MarkerClass polygonMarkerClass = {
+ polygonConfigSpecs,
+ ConfigurePolygonProc,
+ DrawPolygonProc,
+ FreePolygonProc,
+ MapPolygonProc,
+ PointInPolygonProc,
+ RegionInPolygonProc,
+ PolygonToPostscriptProc,
+};
+
+Marker* Blt_CreatePolygonProc(void)
+{
+ PolygonMarker *pmPtr;
+
+ pmPtr = calloc(1, sizeof(PolygonMarker));
+ pmPtr->classPtr = &polygonMarkerClass;
+ pmPtr->capStyle = CapButt;
+ pmPtr->joinStyle = JoinMiter;
+ return (Marker *)pmPtr;
+}
+
+static int PointInPolygonProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
+ return Blt_PointInPolygon(samplePtr, pmPtr->screenPts,
+ markerPtr->nWorldPts + 1);
+ }
+ return FALSE;
+}
+
+static int RegionInPolygonProc(Marker *markerPtr, Region2d *extsPtr,
+ int enclosed)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
+ return Blt_RegionInPolygon(extsPtr, pmPtr->screenPts,
+ markerPtr->nWorldPts, enclosed);
+ }
+ return FALSE;
+}
+
+static void DrawPolygonProc(Marker *markerPtr, Drawable drawable)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ /* Draw polygon fill region */
+ if ((pmPtr->nFillPts > 0) && (pmPtr->fill.fgColor != NULL)) {
+ XPoint *dp, *points;
+ Point2d *sp, *send;
+
+ points = malloc(pmPtr->nFillPts * sizeof(XPoint));
+ if (points == NULL) {
+ return;
+ }
+ dp = points;
+ for (sp = pmPtr->fillPts, send = sp + pmPtr->nFillPts; sp < send;
+ sp++) {
+ dp->x = (short int)sp->x;
+ dp->y = (short int)sp->y;
+ dp++;
+ }
+
+ XFillPolygon(graphPtr->display, drawable, pmPtr->fillGC, points,
+ pmPtr->nFillPts, Complex, CoordModeOrigin);
+ free(points);
+ }
+ /* and then the outline */
+ if ((pmPtr->nOutlinePts > 0) && (pmPtr->lineWidth > 0) &&
+ (pmPtr->outline.fgColor != NULL)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, pmPtr->outlineGC,
+ pmPtr->outlinePts, pmPtr->nOutlinePts);
+ }
+}
+
+static void PolygonToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if (pmPtr->fill.fgColor != NULL) {
+
+ /*
+ * Options: fg bg
+ * Draw outline only.
+ * x Draw solid or stipple.
+ * x x Draw solid or stipple.
+ */
+
+ /* Create a path to use for both the polygon and its outline. */
+ Blt_Ps_Polyline(ps, pmPtr->fillPts, pmPtr->nFillPts);
+
+ /* If the background fill color was specified, draw the polygon in a
+ * solid fashion with that color. */
+ if (pmPtr->fill.bgColor != NULL) {
+ /* Draw the solid background as the background layer of the opaque
+ * stipple */
+ Blt_Ps_XSetBackground(ps, pmPtr->fill.bgColor);
+ /* Retain the path. We'll need it for the foreground layer. */
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ }
+ Blt_Ps_XSetForeground(ps, pmPtr->fill.fgColor);
+ if (pmPtr->stipple != None) {
+ /* Draw the stipple in the foreground color. */
+ Blt_Ps_XSetStipple(ps, graphPtr->display, pmPtr->stipple);
+ } else {
+ Blt_Ps_Append(ps, "fill\n");
+ }
+ }
+
+ /* Draw the outline in the foreground color. */
+ if ((pmPtr->lineWidth > 0) && (pmPtr->outline.fgColor != NULL)) {
+
+ /* Set up the line attributes. */
+ Blt_Ps_XSetLineAttributes(ps, pmPtr->outline.fgColor,
+ pmPtr->lineWidth, &pmPtr->dashes, pmPtr->capStyle,
+ pmPtr->joinStyle);
+
+ /*
+ * Define on-the-fly a PostScript macro "DashesProc" that will be
+ * executed for each call to the Polygon drawing routine. If the line
+ * isn't dashed, simply make this an empty definition.
+ */
+ if ((pmPtr->outline.bgColor != NULL) && (LineIsDashed(pmPtr->dashes))) {
+ Blt_Ps_Append(ps, "/DashesProc {\ngsave\n ");
+ Blt_Ps_XSetBackground(ps, pmPtr->outline.bgColor);
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
+ Blt_Ps_Append(ps, "stroke\n grestore\n} def\n");
+ } else {
+ Blt_Ps_Append(ps, "/DashesProc {} def\n");
+ }
+ Blt_Ps_Draw2DSegments(ps, pmPtr->outlinePts, pmPtr->nOutlinePts);
+ }
+}
+
+static int ConfigurePolygonProc(Marker *markerPtr)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+ Drawable drawable;
+
+ drawable = Tk_WindowId(graphPtr->tkwin);
+ gcMask = (GCLineWidth | GCLineStyle);
+ if (pmPtr->outline.fgColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = pmPtr->outline.fgColor->pixel;
+ }
+ if (pmPtr->outline.bgColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = pmPtr->outline.bgColor->pixel;
+ }
+ gcMask |= (GCCapStyle | GCJoinStyle);
+ gcValues.cap_style = pmPtr->capStyle;
+ gcValues.join_style = pmPtr->joinStyle;
+ gcValues.line_style = LineSolid;
+ gcValues.dash_offset = 0;
+ gcValues.line_width = LineWidth(pmPtr->lineWidth);
+ if (LineIsDashed(pmPtr->dashes)) {
+ gcValues.line_style = (pmPtr->outline.bgColor == NULL)
+ ? LineOnOffDash : LineDoubleDash;
+ }
+ if (pmPtr->xor) {
+ unsigned long pixel;
+ gcValues.function = GXxor;
+
+ gcMask |= GCFunction;
+ pixel = Tk_3DBorderColor(graphPtr->plotBg)->pixel;
+ if (gcMask & GCBackground) {
+ gcValues.background ^= pixel;
+ }
+ gcValues.foreground ^= pixel;
+ if (drawable != None) {
+ DrawPolygonProc(markerPtr, drawable);
+ }
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(pmPtr->dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &pmPtr->dashes);
+ }
+ if (pmPtr->outlineGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
+ }
+ pmPtr->outlineGC = newGC;
+
+ gcMask = 0;
+ if (pmPtr->fill.fgColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = pmPtr->fill.fgColor->pixel;
+ }
+ if (pmPtr->fill.bgColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = pmPtr->fill.bgColor->pixel;
+ }
+ if (pmPtr->stipple != None) {
+ gcValues.stipple = pmPtr->stipple;
+ gcValues.fill_style = (pmPtr->fill.bgColor != NULL)
+ ? FillOpaqueStippled : FillStippled;
+ gcMask |= (GCStipple | GCFillStyle);
+ }
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (pmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
+ }
+ pmPtr->fillGC = newGC;
+
+ if ((gcMask == 0) && !(graphPtr->flags & RESET_AXES) && (pmPtr->xor)) {
+ if (drawable != None) {
+ MapPolygonProc(markerPtr);
+ DrawPolygonProc(markerPtr, drawable);
+ }
+ return TCL_OK;
+ }
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+static void FreePolygonProc(Marker *markerPtr)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+
+ if (pmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
+ }
+ if (pmPtr->outlineGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
+ }
+ if (pmPtr->fillPts != NULL) {
+ free(pmPtr->fillPts);
+ }
+ if (pmPtr->outlinePts != NULL) {
+ free(pmPtr->outlinePts);
+ }
+ if (pmPtr->screenPts != NULL) {
+ free(pmPtr->screenPts);
+ }
+}
+
+static void MapPolygonProc(Marker *markerPtr)
+{
+ Graph* graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ Point2d *screenPts;
+ Region2d extents;
+ int nScreenPts;
+
+ if (pmPtr->outlinePts != NULL) {
+ free(pmPtr->outlinePts);
+ pmPtr->outlinePts = NULL;
+ pmPtr->nOutlinePts = 0;
+ }
+ if (pmPtr->fillPts != NULL) {
+ free(pmPtr->fillPts);
+ pmPtr->fillPts = NULL;
+ pmPtr->nFillPts = 0;
+ }
+ if (pmPtr->screenPts != NULL) {
+ free(pmPtr->screenPts);
+ pmPtr->screenPts = NULL;
+ }
+ if (markerPtr->nWorldPts < 3) {
+ return; /* Too few points */
+ }
+
+ /*
+ * Allocate and fill a temporary array to hold the screen coordinates of
+ * the polygon.
+ */
+ nScreenPts = markerPtr->nWorldPts + 1;
+ screenPts = malloc((nScreenPts + 1) * sizeof(Point2d));
+ {
+ Point2d *sp, *dp, *send;
+
+ dp = screenPts;
+ for (sp = markerPtr->worldPts, send = sp + markerPtr->nWorldPts;
+ sp < send; sp++) {
+ *dp = Blt_MapPoint(sp, &markerPtr->axes);
+ dp->x += markerPtr->xOffset;
+ dp->y += markerPtr->yOffset;
+ dp++;
+ }
+ *dp = screenPts[0];
+ }
+ Blt_GraphExtents(graphPtr, &extents);
+ markerPtr->clipped = TRUE;
+ if (pmPtr->fill.fgColor != NULL) { /* Polygon fill required. */
+ Point2d *fillPts;
+ int n;
+
+ fillPts = malloc(sizeof(Point2d) * nScreenPts * 3);
+ n = Blt_PolyRectClip(&extents, screenPts, markerPtr->nWorldPts,fillPts);
+ if (n < 3) {
+ free(fillPts);
+ } else {
+ pmPtr->nFillPts = n;
+ pmPtr->fillPts = fillPts;
+ markerPtr->clipped = FALSE;
+ }
+ }
+ if ((pmPtr->outline.fgColor != NULL) && (pmPtr->lineWidth > 0)) {
+ Segment2d *outlinePts;
+ Segment2d *segPtr;
+ Point2d *sp, *send;
+
+ /*
+ * Generate line segments representing the polygon outline. The
+ * resulting outline may or may not be closed from viewport clipping.
+ */
+ outlinePts = malloc(nScreenPts * sizeof(Segment2d));
+ if (outlinePts == NULL) {
+ return; /* Can't allocate point array */
+ }
+ /*
+ * Note that this assumes that the point array contains an extra point
+ * that closes the polygon.
+ */
+ segPtr = outlinePts;
+ for (sp = screenPts, send = sp + (nScreenPts - 1); sp < send; sp++) {
+ segPtr->p = sp[0];
+ segPtr->q = sp[1];
+ if (Blt_LineRectClip(&extents, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ }
+ }
+ pmPtr->nOutlinePts = segPtr - outlinePts;
+ pmPtr->outlinePts = outlinePts;
+ if (pmPtr->nOutlinePts > 0) {
+ markerPtr->clipped = FALSE;
+ }
+ }
+ pmPtr->screenPts = screenPts;
+}
+
diff --git a/src/bltGrMarkerPolygon.h b/src/bltGrMarkerPolygon.h
new file mode 100644
index 0000000..deb156e
--- /dev/null
+++ b/src/bltGrMarkerPolygon.h
@@ -0,0 +1,119 @@
+/*
+ * Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+ * This code has been modified under the terms listed below and is made
+ * available under the same terms.
+ */
+
+/*
+ * 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_POLYGON_H
+#define _BLT_GR_MARKER_POLYGON_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; /* 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 *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. */
+
+ ColorPair outline;
+ ColorPair fill;
+
+ Pixmap stipple; /* Stipple pattern to fill the
+ * polygon. */
+ int lineWidth; /* Width of polygon outline. */
+ 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. */
+ int xor;
+ int xorState; /* State of the XOR drawing. Indicates
+ * if the marker is visible. We have to
+ * drawn it again to erase it. */
+} PolygonMarker;
+
+extern MarkerCreateProc Blt_CreatePolygonProc;
+
+#endif