+++ /dev/null
-
-/*
- * bltGrLine.c --
- *
- * This module implements line graph and stripchart elements for
- * the BLT graph widget.
- *
- * Copyright 1993-1998 Lucent Technologies, Inc.
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that the copyright notice and warranty
- * disclaimer appear in supporting documentation, and that the names
- * of Lucent Technologies any of their entities not be used in
- * advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.
- *
- * Lucent Technologies disclaims all warranties with regard to this
- * software, including all implied warranties of merchantability and
- * fitness. In no event shall Lucent Technologies be liable for any
- * special, indirect or consequential damages or any damages
- * whatsoever resulting from loss of use, data or profits, whether in
- * an action of contract, negligence or other tortuous action, arising
- * out of or in connection with the use or performance of this
- * software.
- */
-#include "bltGraph.h"
-#include "bltChain.h"
-#include <X11/Xutil.h>
-
-#include "bltGrElem.h"
-
-#define COLOR_DEFAULT (XColor *)1
-#define PATTERN_SOLID ((Pixmap)1)
-
-#define PEN_INCREASING 1 /* Draw line segments for only those
- * data points whose abscissas are
- * monotonically increasing in
- * order */
-#define PEN_DECREASING 2 /* Lines will be drawn between only
- * those points whose abscissas are
- * decreasing in order */
-
-#define PEN_BOTH_DIRECTIONS (PEN_INCREASING | PEN_DECREASING)
- /* Lines will be drawn between points regardless of the ordering of
- * the abscissas */
-
-#define BROKEN_TRACE(dir,last,next) \
- (((((dir) & PEN_DECREASING) == 0) && ((next) < (last))) || \
- ((((dir) & PEN_INCREASING) == 0) && ((next) > (last))))
-
-#define DRAW_SYMBOL(linePtr) \
- (((linePtr)->symbolCounter % (linePtr)->symbolInterval) == 0)
-
-typedef enum {
- PEN_SMOOTH_NONE, /* Line segments */
- PEN_SMOOTH_STEP, /* Step-and-hold */
- PEN_SMOOTH_NATURAL, /* Natural cubic spline */
- PEN_SMOOTH_QUADRATIC, /* Quadratic spline */
- PEN_SMOOTH_CATROM, /* Catrom parametric spline */
- PEN_SMOOTH_LAST /* Sentinel */
-} Smoothing;
-
-typedef struct {
- char *name;
- Smoothing value;
-} SmoothingInfo;
-
-static SmoothingInfo smoothingInfo[] = {
- { "linear", PEN_SMOOTH_NONE },
- { "step", PEN_SMOOTH_STEP },
- { "natural", PEN_SMOOTH_NATURAL },
- { "cubic", PEN_SMOOTH_NATURAL },
- { "quadratic", PEN_SMOOTH_QUADRATIC },
- { "catrom", PEN_SMOOTH_CATROM },
- { (char *)NULL, PEN_SMOOTH_LAST }
-};
-
-
-typedef struct {
- Point2D *screenPts; /* Array of transformed coordinates */
- int nScreenPts; /* Number of coordinates */
- int *dataToStyle; /* Index of pen styles */
- int *indices; /* Maps segments/traces to data points */
-
-} MapInfo;
-
-/*
- * Symbol types for line elements
- */
-typedef enum {
- SYMBOL_NONE,
- SYMBOL_SQUARE,
- SYMBOL_CIRCLE,
- SYMBOL_DIAMOND,
- SYMBOL_PLUS,
- SYMBOL_CROSS,
- SYMBOL_SPLUS,
- SYMBOL_SCROSS,
- SYMBOL_TRIANGLE,
- SYMBOL_ARROW,
- SYMBOL_BITMAP
-} SymbolType;
-
-typedef struct {
- SymbolType type; /* Type of symbol to be drawn/printed */
-
- int size; /* Requested size of symbol in pixels */
-
- XColor *outlineColor; /* Outline color */
-
- int outlineWidth; /* Width of the outline */
-
- GC outlineGC; /* Outline graphics context */
-
- XColor *fillColor; /* Normal fill color */
-
- GC fillGC; /* Fill graphics context */
-
- /* The last two fields are used only for bitmap symbols. */
-
- Pixmap bitmap; /* Bitmap to determine foreground/background
- * pixels of the symbol */
-
- Pixmap mask; /* Bitmap representing the transparent
- * pixels of the symbol */
-
-} Symbol;
-
-typedef struct {
- int start; /* Index into the X-Y coordinate
- * arrays indicating where trace
- * starts. */
-
- int nScreenPts; /* Number of points in the continuous
- * trace */
-
- Point2D *screenPts; /* Array of screen coordinates
- * (malloc-ed) representing the
- * trace. */
-
- int *symbolToData; /* Reverse mapping of screen
- * coordinate indices back to their
- * data coordinates */
-} Trace;
-
-typedef struct {
- char *name; /* Name of pen style. If the pen was
- * statically allocated the name will
- * be NULL. */
-
- Blt_Uid classUid; /* Type of pen */
-
- char *typeId; /* String token identifying the type
- * of pen */
-
- unsigned int flags; /* Indicates if the pen element is
- * active or normal */
-
- int refCount; /* Reference count for elements using
- * this pen. */
- Blt_HashEntry *hashPtr;
-
- Tk_ConfigSpec *configSpecs; /* Configuration specifications */
-
- PenConfigureProc *configProc;
- PenDestroyProc *destroyProc;
-
- /* Symbol attributes. */
- Symbol symbol; /* Element symbol type */
-
- /* Trace attributes. */
- int traceWidth; /* Width of the line segments. If
- * lineWidth is 0, no line will be
- * drawn, only symbols. */
-
- Blt_Dashes traceDashes; /* Dash on-off list value */
-
- XColor *traceColor; /* Line segment color */
-
- XColor *traceOffColor; /* Line segment dash gap color */
-
- GC traceGC; /* Line segment graphics context */
-
- /* Error bar attributes. */
- int errorBarShow; /* Describes which error bars to
- * display: none, x, y, or * both. */
-
- int errorBarLineWidth; /* Width of the error bar segments. */
-
- int errorBarCapWidth; /* Width of the cap on error bars. */
-
- XColor *errorBarColor; /* Color of the error bar. */
-
- GC errorBarGC; /* Error bar graphics context. */
-
- /* Show value attributes. */
- int valueShow; /* Indicates whether to display data
- * value. Values are x, y, both, or
- * none. */
- char *valueFormat; /* A printf format string. */
-
- TextStyle valueStyle; /* Text attributes (color, font,
- * rotation, etc.) of the value. */
-
-} LinePen;
-
-typedef struct {
- Weight weight; /* Weight range where this pen is valid. */
-
- LinePen *penPtr; /* Pen used to draw symbols, traces, error
- * bars, segments, etc. */
-
- Segment2D *xErrorBars; /* Point to start of this pen's X-error bar
- * segments in the element's array. */
- Segment2D *yErrorBars; /* Point to start of this pen's Y-error bar
- * segments in the element's array. */
- int xErrorBarCnt; /* # of error bars for this pen. */
- int yErrorBarCnt; /* # of error bars for this pen. */
-
- int errorBarCapWidth; /* Length of the cap ends on each
- * error bar. */
-
- int symbolSize; /* Size of the pen's symbol scaled to the
- * current graph size. */
-
- /* Graph specific data. */
-
- Point2D *symbolPts; /* Points to start of array for this pen. */
-
- int nSymbolPts; /* # of points for this pen. */
-
- /* The last two fields are used only for stripcharts. */
-
- Segment2D *strips; /* Points to start of the line segments
- * for this pen. */
-
- int nStrips; /* # of line segments for this pen. */
-
-} LinePenStyle;
-
-typedef struct {
- char *name; /* Identifier used to refer the
- * element. Used in the "insert",
- * "delete", or "show", operations. */
-
- Blt_Uid classUid; /* Type of element */
-
- Graph *graphPtr; /* Graph widget of element*/
-
- unsigned int flags; /* Indicates if the entire element is
- * active, or if coordinates need to
- * be calculated */
-
- char **tags;
-
- int hidden; /* If non-zero, don't display the
- * element. */
-
- Blt_HashEntry *hashPtr;
-
- char *label; /* Label displayed in legend */
-
- int labelRelief; /* Relief of label in legend. */
-
- Axis2D axes;
-
- ElemVector x, y, w; /* Contains array of numeric values */
-
- ElemVector xError; /* Relative/symmetric X error values. */
- ElemVector yError; /* Relative/symmetric Y error values. */
- ElemVector xHigh, xLow; /* Absolute/asymmetric X-coordinate high/low
- error values. */
- ElemVector yHigh, yLow; /* Absolute/asymmetric Y-coordinate high/low
- error values. */
-
- int *activeIndices; /* Array of indices (malloc-ed) that
- * indicate the data points are active
- * (drawn with "active" colors). */
-
- int nActiveIndices; /* Number of active data points.
- * Special case: if < 0 then all data
- * points are drawn active. */
-
- ElementProcs *procsPtr;
- Tk_ConfigSpec *configSpecs; /* Configuration specifications */
-
- Segment2D *xErrorBars; /* Point to start of this pen's X-error bar
- * segments in the element's array. */
- Segment2D *yErrorBars; /* Point to start of this pen's Y-error bar
- * segments in the element's array. */
- int xErrorBarCnt; /* # of error bars for this pen. */
- int yErrorBarCnt; /* # of error bars for this pen. */
-
- int *xErrorToData; /* Maps individual error bar segments back
- * to the data point associated with it. */
- int *yErrorToData; /* Maps individual error bar segments back
- * to the data point associated with it. */
-
- int errorBarCapWidth; /* Length of cap on error bars */
-
- LinePen *activePenPtr; /* Pen to draw "active" elements. */
- LinePen *normalPenPtr; /* Pen to draw elements normally. */
-
- Blt_Chain *palette; /* Array of pen styles: pens are associated
- * with specific ranges of data.*/
-
- /* Symbol scaling */
- int scaleSymbols; /* If non-zero, the symbols will scale
- * in size as the graph is zoomed
- * in/out. */
-
- double xRange, yRange; /* Initial X-axis and Y-axis ranges:
- * used to scale the size of element's
- * symbol. */
-
- int state;
- /*
- * Line specific configurable attributes
- */
- LinePen builtinPen;
-
- /* Line smoothing */
- Smoothing reqSmooth; /* Requested smoothing function to use
- * for connecting the data points */
-
- Smoothing smooth; /* Smoothing function used. */
-
- double rTolerance; /* Tolerance to reduce the number of
- * points displayed. */
- /*
- * Drawing related data structures.
- */
-
- /* Area-under-curve fill attributes. */
- XColor *fillFgColor;
- XColor *fillBgColor;
- GC fillGC;
-
- Blt_Tile fillTile; /* Tile for fill area. */
- Pixmap fillStipple; /* Stipple for fill area. */
-
- int nFillPts;
- Point2D *fillPts; /* Array of points used to draw
- * polygon to fill area under the
- * curve */
-
- /* Symbol points */
- Point2D *symbolPts; /* Holds the screen coordinates of all
- * the data points for the element. */
- int nSymbolPts; /* Number of points */
-
- int *symbolToData; /* Contains indices of data points.
- * It's first used to map pens to the
- * visible points to sort them by pen
- * style, and later to find data
- * points from the index of a visible
- * point. */
-
- /* Active symbol points */
- Point2D *activePts; /* Array of indices representing the
- * "active" points. */
- int nActivePts; /* Number of indices in the above array. */
-
- int *activeToData; /* Contains indices of data points.
- * It's first used to map pens to the
- * visible points to sort them by pen
- * style, and later to find data
- * points from the index of a visible
- * point. */
-
- int reqMaxSymbols;
- int symbolInterval;
- int symbolCounter;
-
- /* X-Y graph-specific fields */
-
- int penDir; /* Indicates if a change in the pen
- * direction should be considered a
- * retrace (line segment is not
- * drawn). */
-
- Blt_Chain *traces; /* List of traces (a trace is a series
- * of contiguous line segments). New
- * traces are generated when either
- * the next segment changes the pen
- * direction, or the end point is
- * clipped by the plotting area. */
-
- /* Stripchart-specific fields */
-
- Segment2D *strips; /* Holds the the line segments of the
- * element trace. The segments are
- * grouped by pen style. */
- int nStrips; /* Number of line segments to be drawn. */
- int *stripToData; /* Pen to visible line segment mapping. */
-
-} Line;
-
-static Tk_OptionParseProc StringToPattern;
-static Tk_OptionPrintProc PatternToString;
-static Tk_OptionParseProc StringToSmooth;
-static Tk_OptionPrintProc SmoothToString;
-extern Tk_OptionParseProc Blt_StringToStyles;
-extern Tk_OptionPrintProc Blt_StylesToString;
-static Tk_OptionParseProc StringToPenDir;
-static Tk_OptionPrintProc PenDirToString;
-static Tk_OptionParseProc StringToSymbol;
-static Tk_OptionPrintProc SymbolToString;
-
-static Tk_CustomOption patternOption =
-{
- StringToPattern, PatternToString, (ClientData)0
-};
-static Tk_CustomOption smoothOption =
-{
- StringToSmooth, SmoothToString, (ClientData)0
-};
-static Tk_CustomOption stylesOption =
-{
- Blt_StringToStyles, Blt_StylesToString, (ClientData)sizeof(LinePenStyle)
-};
-static Tk_CustomOption penDirOption =
-{
- StringToPenDir, PenDirToString, (ClientData)0
-};
-static Tk_CustomOption symbolOption =
-{
- StringToSymbol, SymbolToString, (ClientData)0
-};
-extern Tk_CustomOption bltColorOption;
-extern Tk_CustomOption bltDashesOption;
-extern Tk_CustomOption bltDataOption;
-extern Tk_CustomOption bltDataPairsOption;
-extern Tk_CustomOption bltDistanceOption;
-extern Tk_CustomOption bltListOption;
-extern Tk_CustomOption bltLinePenOption;
-extern Tk_CustomOption bltShadowOption;
-extern Tk_CustomOption bltXAxisOption;
-extern Tk_CustomOption bltYAxisOption;
-extern Tk_CustomOption bltTileOption;
-extern Tk_CustomOption bltFillOption;
-extern Tk_CustomOption bltStateOption;
-
-#define DEF_LINE_ACTIVE_PEN "activeLine"
-#define DEF_LINE_AXIS_X "x"
-#define DEF_LINE_AXIS_Y "y"
-#define DEF_LINE_DASHES (char *)NULL
-#define DEF_LINE_DATA (char *)NULL
-#define DEF_LINE_FILL_COLOR "defcolor"
-#define DEF_LINE_FILL_MONO "defcolor"
-#define DEF_LINE_HIDE "no"
-#define DEF_LINE_LABEL (char *)NULL
-#define DEF_LINE_LABEL_RELIEF "flat"
-#define DEF_LINE_MAX_SYMBOLS "0"
-#define DEF_LINE_OFFDASH_COLOR (char *)NULL
-#define DEF_LINE_OFFDASH_MONO (char *)NULL
-#define DEF_LINE_OUTLINE_COLOR "defcolor"
-#define DEF_LINE_OUTLINE_MONO "defcolor"
-#define DEF_LINE_OUTLINE_WIDTH "1"
-#define DEF_LINE_PATTERN (char *)NULL
-#define DEF_LINE_PATTERN_BG "white"
-#define DEF_LINE_PATTERN_FG "black"
-#define DEF_LINE_PATTERN_TILE (char *)NULL
-#define DEF_LINE_PEN_COLOR RGB_NAVYBLUE
-#define DEF_LINE_PEN_DIRECTION "both"
-#define DEF_LINE_PEN_MONO RGB_BLACK
-#define DEF_LINE_PEN_WIDTH "1"
-#define DEF_LINE_PIXELS "0.125i"
-#define DEF_LINE_REDUCE "0.0"
-#define DEF_LINE_SCALE_SYMBOLS "yes"
-#define DEF_LINE_SMOOTH "linear"
-#define DEF_LINE_STATE "normal"
-#define DEF_LINE_STIPPLE (char *)NULL
-#define DEF_LINE_STYLES ""
-#define DEF_LINE_SYMBOL "circle"
-#define DEF_LINE_TAGS "all"
-#define DEF_LINE_X_DATA (char *)NULL
-#define DEF_LINE_Y_DATA (char *)NULL
-
-#define DEF_LINE_ERRORBAR_COLOR "defcolor"
-#define DEF_LINE_ERRORBAR_LINE_WIDTH "1"
-#define DEF_LINE_ERRORBAR_CAP_WIDTH "1"
-#define DEF_LINE_SHOW_ERRORBARS "both"
-
-#define DEF_PEN_ACTIVE_COLOR RGB_BLUE
-#define DEF_PEN_ACTIVE_MONO RGB_BLACK
-#define DEF_PEN_DASHES (char *)NULL
-#define DEF_PEN_FILL_COLOR "defcolor"
-#define DEF_PEN_FILL_MONO "defcolor"
-#define DEF_PEN_LINE_WIDTH "1"
-#define DEF_PEN_NORMAL_COLOR RGB_NAVYBLUE
-#define DEF_PEN_NORMAL_MONO RGB_BLACK
-#define DEF_PEN_OFFDASH_COLOR (char *)NULL
-#define DEF_PEN_OFFDASH_MONO (char *)NULL
-#define DEF_PEN_OUTLINE_COLOR "defcolor"
-#define DEF_PEN_OUTLINE_MONO "defcolor"
-#define DEF_PEN_OUTLINE_WIDTH "1"
-#define DEF_PEN_PIXELS "0.125i"
-#define DEF_PEN_SYMBOL "circle"
-#define DEF_PEN_TYPE "line"
-#define DEF_PEN_VALUE_ANCHOR "s"
-#define DEF_PEN_VALUE_COLOR RGB_BLACK
-#define DEF_PEN_VALUE_FONT STD_FONT_SMALL
-#define DEF_PEN_VALUE_FORMAT "%g"
-#define DEF_PEN_VALUE_ROTATE (char *)NULL
-#define DEF_PEN_VALUE_SHADOW (char *)NULL
-#define DEF_PEN_SHOW_VALUES "no"
-
-static Tk_ConfigSpec lineElemConfigSpecs[] =
-{
- {TK_CONFIG_CUSTOM, "-activepen", "activePen", "ActivePen",
- DEF_LINE_ACTIVE_PEN, Tk_Offset(Line, activePenPtr),
- TK_CONFIG_NULL_OK, &bltLinePenOption},
- {TK_CONFIG_CUSTOM, "-areapattern", "areaPattern", "AreaPattern",
- DEF_LINE_PATTERN, Tk_Offset(Line, fillStipple),
- TK_CONFIG_NULL_OK, &patternOption},
- {TK_CONFIG_COLOR, "-areaforeground", "areaForeground", "areaForeground",
- DEF_LINE_PATTERN_FG, Tk_Offset(Line, fillFgColor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_COLOR, "-areabackground", "areaBackground", "areaBackground",
- DEF_LINE_PATTERN_BG, Tk_Offset(Line, fillBgColor), TK_CONFIG_NULL_OK},
- {TK_CONFIG_CUSTOM, "-areatile", "areaTile", "AreaTile",
- DEF_LINE_PATTERN_TILE, Tk_Offset(Line, fillTile),
- TK_CONFIG_NULL_OK, &bltTileOption},
- {TK_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags",
- DEF_LINE_TAGS, Tk_Offset(Line, tags),
- TK_CONFIG_NULL_OK, &bltListOption},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_LINE_PEN_COLOR, Tk_Offset(Line, builtinPen.traceColor),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_LINE_PEN_MONO, Tk_Offset(Line, builtinPen.traceColor),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes",
- DEF_LINE_DASHES, Tk_Offset(Line, builtinPen.traceDashes),
- TK_CONFIG_NULL_OK, &bltDashesOption},
- {TK_CONFIG_CUSTOM, "-data", "data", "Data",
- DEF_LINE_DATA, 0, 0, &bltDataPairsOption},
- {TK_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
- DEF_LINE_ERRORBAR_COLOR, Tk_Offset(Line, builtinPen.errorBarColor),
- 0, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
- DEF_LINE_ERRORBAR_LINE_WIDTH,
- Tk_Offset(Line, builtinPen.errorBarLineWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-errorbarcap", "errorBarCap", "ErrorBarCap",
- DEF_LINE_ERRORBAR_CAP_WIDTH,
- Tk_Offset(Line, builtinPen.errorBarCapWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_LINE_FILL_COLOR, Tk_Offset(Line, builtinPen.symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_LINE_FILL_MONO, Tk_Offset(Line, builtinPen.symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_BOOLEAN, "-hide", "hide", "Hide",
- DEF_LINE_HIDE, Tk_Offset(Line, hidden), TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_STRING, "-label", "label", "Label",
- (char *)NULL, Tk_Offset(Line, label), TK_CONFIG_NULL_OK},
- {TK_CONFIG_RELIEF, "-labelrelief", "labelRelief", "LabelRelief",
- DEF_LINE_LABEL_RELIEF, Tk_Offset(Line, labelRelief),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_CUSTOM, "-linewidth", "lineWidth", "LineWidth",
- DEF_LINE_PEN_WIDTH, Tk_Offset(Line, builtinPen.traceWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-mapx", "mapX", "MapX",
- DEF_LINE_AXIS_X, Tk_Offset(Line, axes.x), 0, &bltXAxisOption},
- {TK_CONFIG_CUSTOM, "-mapy", "mapY", "MapY",
- DEF_LINE_AXIS_Y, Tk_Offset(Line, axes.y), 0, &bltYAxisOption},
- {TK_CONFIG_CUSTOM, "-maxsymbols", "maxSymbols", "MaxSymbols",
- DEF_LINE_MAX_SYMBOLS, Tk_Offset(Line, reqMaxSymbols),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_LINE_OFFDASH_COLOR, Tk_Offset(Line, builtinPen.traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_LINE_OFFDASH_MONO, Tk_Offset(Line, builtinPen.traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_LINE_OUTLINE_COLOR, Tk_Offset(Line, builtinPen.symbol.outlineColor),
- TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_LINE_OUTLINE_MONO, Tk_Offset(Line, builtinPen.symbol.outlineColor),
- TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outlinewidth", "outlineWidth", "OutlineWidth",
- DEF_LINE_OUTLINE_WIDTH, Tk_Offset(Line, builtinPen.symbol.outlineWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-pen", "pen", "Pen",
- (char *)NULL, Tk_Offset(Line, normalPenPtr),
- TK_CONFIG_NULL_OK, &bltLinePenOption},
- {TK_CONFIG_CUSTOM, "-pixels", "pixels", "Pixels",
- DEF_LINE_PIXELS, Tk_Offset(Line, builtinPen.symbol.size),
- GRAPH | STRIPCHART, &bltDistanceOption},
- {TK_CONFIG_DOUBLE, "-reduce", "reduce", "Reduce",
- DEF_LINE_REDUCE, Tk_Offset(Line, rTolerance),
- GRAPH | STRIPCHART | TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_BOOLEAN, "-scalesymbols", "scaleSymbols", "ScaleSymbols",
- DEF_LINE_SCALE_SYMBOLS, Tk_Offset(Line, scaleSymbols),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_CUSTOM, "-showerrorbars", "showErrorBars", "ShowErrorBars",
- DEF_LINE_SHOW_ERRORBARS, Tk_Offset(Line, builtinPen.errorBarShow),
- TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-showvalues", "showValues", "ShowValues",
- DEF_PEN_SHOW_VALUES, Tk_Offset(Line, builtinPen.valueShow),
- TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-smooth", "smooth", "Smooth",
- DEF_LINE_SMOOTH, Tk_Offset(Line, reqSmooth),
- TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
- {TK_CONFIG_CUSTOM, "-state", "state", "State",
- DEF_LINE_STATE, Tk_Offset(Line, state),
- TK_CONFIG_DONT_SET_DEFAULT, &bltStateOption},
- {TK_CONFIG_CUSTOM, "-styles", "styles", "Styles",
- DEF_LINE_STYLES, Tk_Offset(Line, palette),
- TK_CONFIG_NULL_OK, &stylesOption},
- {TK_CONFIG_CUSTOM, "-symbol", "symbol", "Symbol",
- DEF_LINE_SYMBOL, Tk_Offset(Line, builtinPen.symbol),
- TK_CONFIG_DONT_SET_DEFAULT, &symbolOption},
- {TK_CONFIG_CUSTOM, "-trace", "trace", "Trace",
- DEF_LINE_PEN_DIRECTION, Tk_Offset(Line, penDir),
- TK_CONFIG_DONT_SET_DEFAULT, &penDirOption},
- {TK_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
- DEF_PEN_VALUE_ANCHOR,
- Tk_Offset(Line, builtinPen.valueStyle.anchor), 0},
- {TK_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
- DEF_PEN_VALUE_COLOR, Tk_Offset(Line, builtinPen.valueStyle.color), 0},
- {TK_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
- DEF_PEN_VALUE_FONT, Tk_Offset(Line, builtinPen.valueStyle.font), 0},
- {TK_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
- DEF_PEN_VALUE_FORMAT, Tk_Offset(Line, builtinPen.valueFormat),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_DOUBLE, "-valuerotate", "valueRotate", "ValueRotate",
- DEF_PEN_VALUE_ROTATE, Tk_Offset(Line, builtinPen.valueStyle.theta), 0},
- {TK_CONFIG_CUSTOM, "-valueshadow", "valueShadow", "ValueShadow",
- DEF_PEN_VALUE_SHADOW, Tk_Offset(Line, builtinPen.valueStyle.shadow),
- 0, &bltShadowOption},
- {TK_CONFIG_CUSTOM, "-weights", "weights", "Weights",
- (char *)NULL, Tk_Offset(Line, w), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-x", "xData", "XData",
- (char *)NULL, Tk_Offset(Line, x), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xdata", "xData", "XData",
- (char *)NULL, Tk_Offset(Line, x), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xerror", "xError", "XError",
- (char *)NULL, Tk_Offset(Line, xError), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xhigh", "xHigh", "XHigh",
- (char *)NULL, Tk_Offset(Line, xHigh), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xlow", "xLow", "XLow",
- (char *)NULL, Tk_Offset(Line, xLow), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-y", "yData", "YData",
- (char *)NULL, Tk_Offset(Line, y), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-ydata", "yData", "YData",
- (char *)NULL, Tk_Offset(Line, y), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-yerror", "yError", "YError",
- (char *)NULL, Tk_Offset(Line, yError), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-yhigh", "yHigh", "YHigh",
- (char *)NULL, Tk_Offset(Line, yHigh), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-ylow", "yLow", "YLow",
- (char *)NULL, Tk_Offset(Line, yLow), 0, &bltDataOption},
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-
-static Tk_ConfigSpec stripElemConfigSpecs[] =
-{
- {TK_CONFIG_CUSTOM, "-activepen", "activePen", "ActivePen",
- DEF_LINE_ACTIVE_PEN, Tk_Offset(Line, activePenPtr),
- TK_CONFIG_NULL_OK, &bltLinePenOption},
- {TK_CONFIG_CUSTOM, "-bindtags", "bindTags", "BindTags",
- DEF_LINE_TAGS, Tk_Offset(Line, tags),
- TK_CONFIG_NULL_OK, &bltListOption},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_LINE_PEN_COLOR, Tk_Offset(Line, builtinPen.traceColor),
- TK_CONFIG_COLOR_ONLY},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_LINE_PEN_MONO, Tk_Offset(Line, builtinPen.traceColor),
- TK_CONFIG_MONO_ONLY},
- {TK_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes",
- DEF_LINE_DASHES, Tk_Offset(Line, builtinPen.traceDashes),
- TK_CONFIG_NULL_OK, &bltDashesOption},
- {TK_CONFIG_CUSTOM, "-data", "data", "Data",
- DEF_LINE_DATA, 0, 0, &bltDataPairsOption},
- {TK_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
- DEF_LINE_ERRORBAR_COLOR, Tk_Offset(Line, builtinPen.errorBarColor),
- 0, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
- DEF_LINE_ERRORBAR_LINE_WIDTH,
- Tk_Offset(Line, builtinPen.errorBarLineWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-errorbarcap", "errorBarCap",
- "ErrorBarCap", DEF_LINE_ERRORBAR_CAP_WIDTH,
- Tk_Offset(Line, builtinPen.errorBarCapWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_LINE_FILL_COLOR, Tk_Offset(Line, builtinPen.symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_LINE_FILL_MONO, Tk_Offset(Line, builtinPen.symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_BOOLEAN, "-hide", "hide", "Hide",
- DEF_LINE_HIDE, Tk_Offset(Line, hidden), TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_STRING, "-label", "label", "Label",
- (char *)NULL, Tk_Offset(Line, label), TK_CONFIG_NULL_OK},
- {TK_CONFIG_RELIEF, "-labelrelief", "labelRelief", "LabelRelief",
- DEF_LINE_LABEL_RELIEF, Tk_Offset(Line, labelRelief),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_CUSTOM, "-linewidth", "lineWidth", "LineWidth",
- DEF_LINE_PEN_WIDTH, Tk_Offset(Line, builtinPen.traceWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-mapx", "mapX", "MapX",
- DEF_LINE_AXIS_X, Tk_Offset(Line, axes.x), 0, &bltXAxisOption},
- {TK_CONFIG_CUSTOM, "-mapy", "mapY", "MapY",
- DEF_LINE_AXIS_Y, Tk_Offset(Line, axes.y), 0, &bltYAxisOption},
- {TK_CONFIG_CUSTOM, "-maxsymbols", "maxSymbols", "MaxSymbols",
- DEF_LINE_MAX_SYMBOLS, Tk_Offset(Line, reqMaxSymbols),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_LINE_OFFDASH_COLOR, Tk_Offset(Line, builtinPen.traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_LINE_OFFDASH_MONO, Tk_Offset(Line, builtinPen.traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_LINE_OUTLINE_COLOR, Tk_Offset(Line, builtinPen.symbol.outlineColor),
- TK_CONFIG_COLOR_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_LINE_OUTLINE_MONO, Tk_Offset(Line, builtinPen.symbol.outlineColor),
- TK_CONFIG_MONO_ONLY, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outlinewidth", "outlineWidth", "OutlineWidth",
- DEF_LINE_OUTLINE_WIDTH, Tk_Offset(Line, builtinPen.symbol.outlineWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-pen", "pen", "Pen",
- (char *)NULL, Tk_Offset(Line, normalPenPtr),
- TK_CONFIG_NULL_OK, &bltLinePenOption},
- {TK_CONFIG_CUSTOM, "-pixels", "pixels", "Pixels",
- DEF_LINE_PIXELS, Tk_Offset(Line, builtinPen.symbol.size), 0,
- &bltDistanceOption},
- {TK_CONFIG_BOOLEAN, "-scalesymbols", "scaleSymbols", "ScaleSymbols",
- DEF_LINE_SCALE_SYMBOLS, Tk_Offset(Line, scaleSymbols),
- TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_CUSTOM, "-showerrorbars", "showErrorBars", "ShowErrorBars",
- DEF_LINE_SHOW_ERRORBARS, Tk_Offset(Line, builtinPen.errorBarShow),
- TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-showvalues", "showValues", "ShowValues",
- DEF_PEN_SHOW_VALUES, Tk_Offset(Line, builtinPen.valueShow),
- TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-smooth", "smooth", "Smooth",
- DEF_LINE_SMOOTH, Tk_Offset(Line, reqSmooth),
- TK_CONFIG_DONT_SET_DEFAULT, &smoothOption},
- {TK_CONFIG_CUSTOM, "-styles", "styles", "Styles",
- DEF_LINE_STYLES, Tk_Offset(Line, palette),
- TK_CONFIG_NULL_OK, &stylesOption},
- {TK_CONFIG_CUSTOM, "-symbol", "symbol", "Symbol",
- DEF_LINE_SYMBOL, Tk_Offset(Line, builtinPen.symbol),
- TK_CONFIG_DONT_SET_DEFAULT, &symbolOption},
- {TK_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
- DEF_PEN_VALUE_ANCHOR,
- Tk_Offset(Line, builtinPen.valueStyle.anchor), 0},
- {TK_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
- DEF_PEN_VALUE_COLOR, Tk_Offset(Line, builtinPen.valueStyle.color), 0},
- {TK_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
- DEF_PEN_VALUE_FONT, Tk_Offset(Line, builtinPen.valueStyle.font), 0},
- {TK_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
- DEF_PEN_VALUE_FORMAT, Tk_Offset(Line, builtinPen.valueFormat),
- TK_CONFIG_NULL_OK},
- {TK_CONFIG_DOUBLE, "-valuerotate", "valueRotate", "ValueRotate",
- DEF_PEN_VALUE_ROTATE, Tk_Offset(Line, builtinPen.valueStyle.theta), 0},
- {TK_CONFIG_CUSTOM, "-valueshadow", "valueShadow", "ValueShadow",
- DEF_PEN_VALUE_SHADOW, Tk_Offset(Line, builtinPen.valueStyle.shadow), 0,
- &bltShadowOption},
- {TK_CONFIG_CUSTOM, "-weights", "weights", "Weights",
- (char *)NULL, Tk_Offset(Line, w), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-x", "xData", "XData",
- (char *)NULL, Tk_Offset(Line, x), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xdata", "xData", "XData",
- (char *)NULL, Tk_Offset(Line, x), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-y", "yData", "YData",
- (char *)NULL, Tk_Offset(Line, y), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xerror", "xError", "XError", (char *)NULL,
- Tk_Offset(Line, xError), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-ydata", "yData", "YData",
- (char *)NULL, Tk_Offset(Line, y), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-yerror", "yError", "YError", (char *)NULL,
- Tk_Offset(Line, yError), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xhigh", "xHigh", "XHigh", (char *)NULL,
- Tk_Offset(Line, xHigh), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-xlow", "xLow", "XLow", (char *)NULL,
- Tk_Offset(Line, xLow), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-yhigh", "yHigh", "YHigh", (char *)NULL,
- Tk_Offset(Line, xHigh), 0, &bltDataOption},
- {TK_CONFIG_CUSTOM, "-ylow", "yLow", "YLow", (char *)NULL,
- Tk_Offset(Line, yLow), 0, &bltDataOption},
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-static Tk_ConfigSpec linePenConfigSpecs[] =
-{
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_PEN_ACTIVE_COLOR, Tk_Offset(LinePen, traceColor),
- TK_CONFIG_COLOR_ONLY | ACTIVE_PEN},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_PEN_ACTIVE_MONO, Tk_Offset(LinePen, traceColor),
- TK_CONFIG_MONO_ONLY | ACTIVE_PEN},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_PEN_NORMAL_COLOR, Tk_Offset(LinePen, traceColor),
- TK_CONFIG_COLOR_ONLY | NORMAL_PEN},
- {TK_CONFIG_COLOR, "-color", "color", "Color",
- DEF_PEN_NORMAL_MONO, Tk_Offset(LinePen, traceColor),
- TK_CONFIG_MONO_ONLY | NORMAL_PEN},
- {TK_CONFIG_CUSTOM, "-dashes", "dashes", "Dashes",
- DEF_PEN_DASHES, Tk_Offset(LinePen, traceDashes),
- TK_CONFIG_NULL_OK | ALL_PENS, &bltDashesOption},
- {TK_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
- DEF_LINE_ERRORBAR_COLOR, Tk_Offset(LinePen, errorBarColor),
- ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
- DEF_LINE_ERRORBAR_LINE_WIDTH, Tk_Offset(LinePen, errorBarLineWidth),
- ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-errorbarcap", "errorBarCap",
- "ErrorBarCap", DEF_LINE_ERRORBAR_CAP_WIDTH,
- Tk_Offset(LinePen, errorBarCapWidth),
- TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_PEN_FILL_COLOR, Tk_Offset(LinePen, symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-fill", "fill", "Fill",
- DEF_PEN_FILL_MONO, Tk_Offset(LinePen, symbol.fillColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-linewidth", "lineWidth", "LineWidth",
- (char *)NULL, Tk_Offset(LinePen, traceWidth),
- ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_PEN_OFFDASH_COLOR, Tk_Offset(LinePen, traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_COLOR_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
- DEF_PEN_OFFDASH_MONO, Tk_Offset(LinePen, traceOffColor),
- TK_CONFIG_NULL_OK | TK_CONFIG_MONO_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_PEN_OUTLINE_COLOR, Tk_Offset(LinePen, symbol.outlineColor),
- TK_CONFIG_COLOR_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outline", "outline", "Outline",
- DEF_PEN_OUTLINE_MONO, Tk_Offset(LinePen, symbol.outlineColor),
- TK_CONFIG_MONO_ONLY | ALL_PENS, &bltColorOption},
- {TK_CONFIG_CUSTOM, "-outlinewidth", "outlineWidth", "OutlineWidth",
- DEF_PEN_OUTLINE_WIDTH, Tk_Offset(LinePen, symbol.outlineWidth),
- TK_CONFIG_DONT_SET_DEFAULT | ALL_PENS, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-pixels", "pixels", "Pixels",
- DEF_PEN_PIXELS, Tk_Offset(LinePen, symbol.size),
- ALL_PENS, &bltDistanceOption},
- {TK_CONFIG_CUSTOM, "-showerrorbars", "showErrorBars", "ShowErrorBars",
- DEF_LINE_SHOW_ERRORBARS, Tk_Offset(LinePen, errorBarShow),
- TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-showvalues", "showValues", "ShowValues",
- DEF_PEN_SHOW_VALUES, Tk_Offset(LinePen, valueShow),
- ALL_PENS | TK_CONFIG_DONT_SET_DEFAULT, &bltFillOption},
- {TK_CONFIG_CUSTOM, "-symbol", "symbol", "Symbol",
- DEF_PEN_SYMBOL, Tk_Offset(LinePen, symbol),
- TK_CONFIG_DONT_SET_DEFAULT | ALL_PENS, &symbolOption},
- {TK_CONFIG_STRING, "-type", (char *)NULL, (char *)NULL,
- DEF_PEN_TYPE, Tk_Offset(Pen, typeId), ALL_PENS | TK_CONFIG_NULL_OK},
- {TK_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
- DEF_PEN_VALUE_ANCHOR, Tk_Offset(LinePen, valueStyle.anchor), ALL_PENS},
- {TK_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
- DEF_PEN_VALUE_COLOR, Tk_Offset(LinePen, valueStyle.color), ALL_PENS},
- {TK_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
- DEF_PEN_VALUE_FONT, Tk_Offset(LinePen, valueStyle.font), ALL_PENS},
- {TK_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
- DEF_PEN_VALUE_FORMAT, Tk_Offset(LinePen, valueFormat),
- ALL_PENS | TK_CONFIG_NULL_OK},
- {TK_CONFIG_DOUBLE, "-valuerotate", "valueRotate", "ValueRotate",
- DEF_PEN_VALUE_ROTATE, Tk_Offset(LinePen, valueStyle.theta), ALL_PENS},
- {TK_CONFIG_CUSTOM, "-valueshadow", "valueShadow", "ValueShadow",
- DEF_PEN_VALUE_SHADOW, Tk_Offset(LinePen, valueStyle.shadow),
- ALL_PENS, &bltShadowOption},
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
-};
-
-typedef double (DistanceProc) _ANSI_ARGS_((int x, int y, Point2D *p,
- Point2D *q, Point2D *t));
-
-/* Forward declarations */
-static PenConfigureProc ConfigurePen;
-static PenDestroyProc DestroyPen;
-static ElementClosestProc ClosestLine;
-static ElementConfigProc ConfigureLine;
-static ElementDestroyProc DestroyLine;
-static ElementDrawProc DrawActiveLine;
-static ElementDrawProc DrawNormalLine;
-static ElementDrawSymbolProc DrawSymbol;
-static ElementExtentsProc GetLineExtents;
-static ElementToPostScriptProc ActiveLineToPostScript;
-static ElementToPostScriptProc NormalLineToPostScript;
-static ElementSymbolToPostScriptProc SymbolToPostScript;
-static ElementMapProc MapLine;
-static DistanceProc DistanceToY;
-static DistanceProc DistanceToX;
-static DistanceProc DistanceToLine;
-static Blt_TileChangedProc TileChangedProc;
-
-#ifdef WIN32
-
-static int tkpWinRopModes[] =
-{
- R2_BLACK, /* GXclear */
- R2_MASKPEN, /* GXand */
- R2_MASKPENNOT, /* GXandReverse */
- R2_COPYPEN, /* GXcopy */
- R2_MASKNOTPEN, /* GXandInverted */
- R2_NOT, /* GXnoop */
- R2_XORPEN, /* GXxor */
- R2_MERGEPEN, /* GXor */
- R2_NOTMERGEPEN, /* GXnor */
- R2_NOTXORPEN, /* GXequiv */
- R2_NOT, /* GXinvert */
- R2_MERGEPENNOT, /* GXorReverse */
- R2_NOTCOPYPEN, /* GXcopyInverted */
- R2_MERGENOTPEN, /* GXorInverted */
- R2_NOTMASKPEN, /* GXnand */
- R2_WHITE /* GXset */
-};
-
-#endif
-
-INLINE static int
-Round(x)
- register double x;
-{
- return (int) (x + ((x < 0.0) ? -0.5 : 0.5));
-}
-
-/*
- * ----------------------------------------------------------------------
- * Custom configuration option (parse and print) routines
- * ----------------------------------------------------------------------
- */
-
-static int
-StringToBitmap(interp, tkwin, symbolPtr, string)
- Tcl_Interp *interp;
- Tk_Window tkwin;
- Symbol *symbolPtr;
- char *string;
-{
- Pixmap bitmap, mask;
- char **elemArr;
- int nElems;
- int result;
-
- if (Tcl_SplitList(interp, string, &nElems, &elemArr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (nElems > 2) {
- Tcl_AppendResult(interp, "too many elements in bitmap list \"", string,
- "\": should be \"bitmap mask\"", (char *)NULL);
- result = TCL_ERROR;
- goto error;
- }
- mask = None;
- bitmap = Tk_GetBitmap(interp, tkwin, Tk_GetUid(elemArr[0]));
- if (bitmap == None) {
- result = TCL_BREAK;
- Tcl_ResetResult(interp);
- goto error;
- }
- if ((nElems > 1) && (elemArr[1][0] != '\0')) {
- mask = Tk_GetBitmap(interp, tkwin, Tk_GetUid(elemArr[1]));
- if (mask == None) {
- Tk_FreeBitmap(Tk_Display(tkwin), bitmap);
- result = TCL_ERROR;
- goto error;
- }
- }
- Blt_Free(elemArr);
- if (symbolPtr->bitmap != None) {
- Tk_FreeBitmap(Tk_Display(tkwin), symbolPtr->bitmap);
- }
- symbolPtr->bitmap = bitmap;
- if (symbolPtr->mask != None) {
- Tk_FreeBitmap(Tk_Display(tkwin), symbolPtr->mask);
- }
- symbolPtr->mask = mask;
- return TCL_OK;
- error:
- Blt_Free(elemArr);
- return result;
-}
-
-/*ARGSUSED*/
-static char *
-PatternToString(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Not used. */
- Tk_Window tkwin;
- char *widgRec; /* Element information record */
- int offset; /* Offset of field in record */
- Tcl_FreeProc **freeProcPtr; /* Not used. */
-{
- Pixmap stipple = *(Pixmap *)(widgRec + offset);
-
- if (stipple == None) {
- return "";
- }
- if (stipple == PATTERN_SOLID) {
- return "solid";
- }
- return Tk_NameOfBitmap(Tk_Display(tkwin), stipple);
-}
-
-/*ARGSUSED*/
-static int
-StringToPattern(clientData, interp, tkwin, string, widgRec, offset)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter to send results back to */
- Tk_Window tkwin; /* Not used. */
- char *string; /* String representing field */
- char *widgRec; /* Element information record */
- int offset; /* Offset of field in record */
-{
- Pixmap *stipplePtr = (Pixmap *)(widgRec + offset);
- Pixmap stipple;
-
- if ((string == NULL) || (string[0] == '\0')) {
- stipple = None;
- } else if (strcmp(string, "solid") == 0) {
- stipple = PATTERN_SOLID;
- } else {
- stipple = Tk_GetBitmap(interp, tkwin, Tk_GetUid(string));
- if (stipple == None) {
- return TCL_ERROR;
- }
- }
- if ((*stipplePtr != None) && (*stipplePtr != PATTERN_SOLID)) {
- Tk_FreeBitmap(Tk_Display(tkwin), *stipplePtr);
- }
- *stipplePtr = stipple;
- return TCL_OK;
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * NameOfSymbol --
- *
- * Converts the symbol value into its string representation.
- *
- * Results:
- * The static string representing the symbol type is returned.
- *
- *----------------------------------------------------------------------
- */
-static char *
-NameOfSymbol(symbolPtr)
- Symbol *symbolPtr;
-{
- switch (symbolPtr->type) {
- case SYMBOL_NONE:
- return "none";
- case SYMBOL_SQUARE:
- return "square";
- case SYMBOL_CIRCLE:
- return "circle";
- case SYMBOL_DIAMOND:
- return "diamond";
- case SYMBOL_PLUS:
- return "plus";
- case SYMBOL_CROSS:
- return "cross";
- case SYMBOL_SPLUS:
- return "splus";
- case SYMBOL_SCROSS:
- return "scross";
- case SYMBOL_TRIANGLE:
- return "triangle";
- case SYMBOL_ARROW:
- return "arrow";
- case SYMBOL_BITMAP:
- return "bitmap";
- }
- return NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StringToSymbol --
- *
- * Convert the string representation of a line style or symbol name
- * into its numeric form.
- *
- * Results:
- * The return value is a standard Tcl result. The symbol type is
- * written into the widget record.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-StringToSymbol(clientData, interp, tkwin, string, widgRec, offset)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter to send results back to */
- Tk_Window tkwin; /* Not used. */
- char *string; /* String representing symbol type */
- char *widgRec; /* Element information record */
- int offset; /* Offset of symbol type field in record */
-{
- Symbol *symbolPtr = (Symbol *)(widgRec + offset);
- unsigned int length;
- char c;
-
- c = string[0];
- length = strlen(string);
- if (c == '\0') {
- symbolPtr->type = SYMBOL_NONE;
- } else if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
- symbolPtr->type = SYMBOL_NONE;
- } else if ((c == 'c') && (length > 1) &&
- (strncmp(string, "circle", length) == 0)) {
- symbolPtr->type = SYMBOL_CIRCLE;
- } else if ((c == 's') && (length > 1) &&
- (strncmp(string, "square", length) == 0)) {
- symbolPtr->type = SYMBOL_SQUARE;
- } else if ((c == 'd') && (strncmp(string, "diamond", length) == 0)) {
- symbolPtr->type = SYMBOL_DIAMOND;
- } else if ((c == 'p') && (strncmp(string, "plus", length) == 0)) {
- symbolPtr->type = SYMBOL_PLUS;
- } else if ((c == 'c') && (length > 1) &&
- (strncmp(string, "cross", length) == 0)) {
- symbolPtr->type = SYMBOL_CROSS;
- } else if ((c == 's') && (length > 1) &&
- (strncmp(string, "splus", length) == 0)) {
- symbolPtr->type = SYMBOL_SPLUS;
- } else if ((c == 's') && (length > 1) &&
- (strncmp(string, "scross", length) == 0)) {
- symbolPtr->type = SYMBOL_SCROSS;
- } else if ((c == 't') && (strncmp(string, "triangle", length) == 0)) {
- symbolPtr->type = SYMBOL_TRIANGLE;
- } else if ((c == 'a') && (strncmp(string, "arrow", length) == 0)) {
- symbolPtr->type = SYMBOL_ARROW;
- } else {
- int result;
-
- result = StringToBitmap(interp, tkwin, symbolPtr, string);
- if (result != TCL_OK) {
- if (result != TCL_ERROR) {
- Tcl_AppendResult(interp, "bad symbol \"", string,
-"\": should be \"none\", \"circle\", \"square\", \"diamond\", \"plus\", \
-\"cross\", \"splus\", \"scross\", \"triangle\", \"arrow\" \
-or the name of a bitmap", (char *)NULL);
- }
- return TCL_ERROR;
- }
- symbolPtr->type = SYMBOL_BITMAP;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SymbolToString --
- *
- * Convert the symbol value into a string.
- *
- * Results:
- * The string representing the symbol type or line style is returned.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static char *
-SymbolToString(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Not used. */
- Tk_Window tkwin;
- char *widgRec; /* Element information record */
- int offset; /* Offset of symbol type field in record */
- Tcl_FreeProc **freeProcPtr; /* Not used. */
-{
- Symbol *symbolPtr = (Symbol *)(widgRec + offset);
- char *result;
-
- if (symbolPtr->type == SYMBOL_BITMAP) {
- Tcl_DString dString;
-
- Tcl_DStringInit(&dString);
- Tcl_DStringAppendElement(&dString,
- Tk_NameOfBitmap(Tk_Display(tkwin), symbolPtr->bitmap));
- Tcl_DStringAppendElement(&dString, (symbolPtr->mask == None) ? "" :
- Tk_NameOfBitmap(Tk_Display(tkwin), symbolPtr->mask));
- result = Blt_Strdup(Tcl_DStringValue(&dString));
- Tcl_DStringFree(&dString);
- *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
- } else {
- result = NameOfSymbol(symbolPtr);
- }
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NameOfSmooth --
- *
- * Converts the smooth value into its string representation.
- *
- * Results:
- * The static string representing the smooth type is returned.
- *
- *----------------------------------------------------------------------
- */
-static char *
-NameOfSmooth(value)
- Smoothing value;
-{
- if ((value < 0) || (value >= PEN_SMOOTH_LAST)) {
- return "unknown smooth value";
- }
- return smoothingInfo[value].name;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StringToSmooth --
- *
- * Convert the string representation of a line style or smooth name
- * into its numeric form.
- *
- * Results:
- * The return value is a standard Tcl result. The smooth type is
- * written into the widget record.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-StringToSmooth(clientData, interp, tkwin, string, widgRec, offset)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter to send results back to */
- Tk_Window tkwin; /* Not used. */
- char *string; /* String representing smooth type */
- char *widgRec; /* Element information record */
- int offset; /* Offset of smooth type field in record */
-{
- Smoothing *valuePtr = (Smoothing *)(widgRec + offset);
- register SmoothingInfo *siPtr;
-
- for (siPtr = smoothingInfo; siPtr->name != NULL; siPtr++) {
- if (strcmp(string, siPtr->name) == 0) {
- *valuePtr = siPtr->value;
- return TCL_OK;
- }
- }
- Tcl_AppendResult(interp, "bad smooth value \"", string, "\": should be \
-linear, step, natural, or quadratic", (char *)NULL);
- return TCL_ERROR;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SmoothToString --
- *
- * Convert the smooth value into a string.
- *
- * Results:
- * The string representing the smooth type or line style is returned.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static char *
-SmoothToString(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Not used. */
- Tk_Window tkwin; /* Not used. */
- char *widgRec; /* Element information record */
- int offset; /* Offset of smooth type field in record */
- Tcl_FreeProc **freeProcPtr; /* Not used. */
-{
- int smooth = *(int *)(widgRec + offset);
-
- return NameOfSmooth(smooth);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * StringToPenDir --
- *
- * Convert the string representation of a line style or symbol name
- * into its numeric form.
- *
- * Results:
- * The return value is a standard Tcl result. The symbol type is
- * written into the widget record.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-StringToPenDir(clientData, interp, tkwin, string, widgRec, offset)
- ClientData clientData; /* Not used. */
- Tcl_Interp *interp; /* Interpreter to send results back to */
- Tk_Window tkwin; /* Not used. */
- char *string; /* String representing pen direction */
- char *widgRec; /* Element information record */
- int offset; /* Offset of pen direction field in record */
-{
- int *penDirPtr = (int *)(widgRec + offset);
- unsigned int length;
- char c;
-
- c = string[0];
- length = strlen(string);
- if ((c == 'i') && (strncmp(string, "increasing", length) == 0)) {
- *penDirPtr = PEN_INCREASING;
- } else if ((c == 'd') && (strncmp(string, "decreasing", length) == 0)) {
- *penDirPtr = PEN_DECREASING;
- } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
- *penDirPtr = PEN_BOTH_DIRECTIONS;
- } else {
- Tcl_AppendResult(interp, "bad trace value \"", string,
- "\" : should be \"increasing\", \"decreasing\", or \"both\"",
- (char *)NULL);
- return TCL_ERROR;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NameOfPenDir --
- *
- * Convert the pen direction into a string.
- *
- * Results:
- * The static string representing the pen direction is returned.
- *
- *----------------------------------------------------------------------
- */
-static char *
-NameOfPenDir(penDir)
- int penDir; /* Direction for pen drawing between points */
-{
- switch (penDir) {
- case PEN_INCREASING:
- return "increasing";
- case PEN_DECREASING:
- return "decreasing";
- case PEN_BOTH_DIRECTIONS:
- return "both";
- default:
- return "unknown trace direction";
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * PenDirToString --
- *
- * Convert the pen direction into a string.
- *
- * Results:
- * The string representing the pen drawing direction is returned.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static char *
-PenDirToString(clientData, tkwin, widgRec, offset, freeProcPtr)
- ClientData clientData; /* Not used. */
- Tk_Window tkwin; /* Not used. */
- char *widgRec; /* Element information record */
- int offset; /* Offset of pen direction field in record */
- Tcl_FreeProc **freeProcPtr; /* Not used. */
-{
- int penDir = *(int *)(widgRec + offset);
-
- return NameOfPenDir(penDir);
-}
-
-
-/*
- * Clear the number of points and segments, in case there are no
- * segments or points
- */
-static void
-ClearPalette(palette)
- Blt_Chain *palette;
-{
- register LinePenStyle *stylePtr;
- Blt_ChainLink *linkPtr;
-
- for (linkPtr = Blt_ChainFirstLink(palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->nStrips = stylePtr->nSymbolPts = 0;
- stylePtr->xErrorBarCnt = stylePtr->yErrorBarCnt = 0;
- }
-}
-
-\f
-/*
- *----------------------------------------------------------------------
- *
- * ConfigurePen --
- *
- * Sets up the appropriate configuration parameters in the GC.
- * It is assumed the parameters have been previously set by
- * a call to Tk_ConfigureWidget.
- *
- * Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
- *
- * Side effects:
- * Configuration information such as line width, line style, color
- * etc. get set in a new GC.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-ConfigurePen(graphPtr, penPtr)
- Graph *graphPtr;
- Pen *penPtr;
-{
- LinePen *lpPtr = (LinePen *)penPtr;
- unsigned long gcMask;
- GC newGC;
- XGCValues gcValues;
- XColor *colorPtr;
-
- Blt_ResetTextStyle(graphPtr->tkwin, &(lpPtr->valueStyle));
- /*
- * Set the outline GC for this pen: GCForeground is outline color.
- * GCBackground is the fill color (only used for bitmap symbols).
- */
- gcMask = (GCLineWidth | GCForeground);
- colorPtr = lpPtr->symbol.outlineColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = lpPtr->traceColor;
- }
- gcValues.foreground = colorPtr->pixel;
- if (lpPtr->symbol.type == SYMBOL_BITMAP) {
- colorPtr = lpPtr->symbol.fillColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = lpPtr->traceColor;
- }
- /*
- * Set a clip mask if either
- * 1) no background color was designated or
- * 2) a masking bitmap was specified.
- *
- * These aren't necessarily the bitmaps we'll be using for
- * clipping. But this makes it unlikely that anyone else will
- * be sharing this GC when we set the clip origin (at the time
- * the bitmap is drawn).
- */
- if (colorPtr != NULL) {
- gcValues.background = colorPtr->pixel;
- gcMask |= GCBackground;
- if (lpPtr->symbol.mask != None) {
- gcValues.clip_mask = lpPtr->symbol.mask;
- gcMask |= GCClipMask;
- }
- } else {
- gcValues.clip_mask = lpPtr->symbol.bitmap;
- gcMask |= GCClipMask;
- }
- }
- gcValues.line_width = LineWidth(lpPtr->symbol.outlineWidth);
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- if (lpPtr->symbol.outlineGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->symbol.outlineGC);
- }
- lpPtr->symbol.outlineGC = newGC;
-
- /* Fill GC for symbols: GCForeground is fill color */
-
- gcMask = (GCLineWidth | GCForeground);
- colorPtr = lpPtr->symbol.fillColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = lpPtr->traceColor;
- }
- newGC = NULL;
- if (colorPtr != NULL) {
- gcValues.foreground = colorPtr->pixel;
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- }
- if (lpPtr->symbol.fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->symbol.fillGC);
- }
- lpPtr->symbol.fillGC = newGC;
-
- /* Line segments */
-
- gcMask = (GCLineWidth | GCForeground | GCLineStyle | GCCapStyle |
- GCJoinStyle);
- gcValues.cap_style = CapButt;
- gcValues.join_style = JoinRound;
- gcValues.line_style = LineSolid;
- gcValues.line_width = LineWidth(lpPtr->traceWidth);
-
- colorPtr = lpPtr->traceOffColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = lpPtr->traceColor;
- }
- if (colorPtr != NULL) {
- gcMask |= GCBackground;
- gcValues.background = colorPtr->pixel;
- }
- gcValues.foreground = lpPtr->traceColor->pixel;
- if (LineIsDashed(lpPtr->traceDashes)) {
- gcValues.line_width = lpPtr->traceWidth;
- gcValues.line_style =
- (colorPtr == NULL) ? LineOnOffDash : LineDoubleDash;
- }
- newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
- if (lpPtr->traceGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, lpPtr->traceGC);
- }
- if (LineIsDashed(lpPtr->traceDashes)) {
- lpPtr->traceDashes.offset = lpPtr->traceDashes.values[0] / 2;
- Blt_SetDashes(graphPtr->display, newGC, &(lpPtr->traceDashes));
- }
- lpPtr->traceGC = newGC;
-
- gcMask = (GCLineWidth | GCForeground);
- colorPtr = lpPtr->errorBarColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = lpPtr->traceColor;
- }
- gcValues.line_width = LineWidth(lpPtr->errorBarLineWidth);
- gcValues.foreground = colorPtr->pixel;
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- if (lpPtr->errorBarGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->errorBarGC);
- }
- lpPtr->errorBarGC = newGC;
-
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DestroyPen --
- *
- * Release memory and resources allocated for the style.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Everything associated with the pen style is freed up.
- *
- *----------------------------------------------------------------------
- */
-static void
-DestroyPen(graphPtr, penPtr)
- Graph *graphPtr;
- Pen *penPtr;
-{
- LinePen *lpPtr = (LinePen *)penPtr;
-
- Blt_FreeTextStyle(graphPtr->display, &(lpPtr->valueStyle));
- /* TODO: Do this for all shadows.
- if (lpPtr->valueStyle.shadow.color != NULL) {
- Tk_FreeColor(lpPtr->valueStyle.shadow.color);
- }
- */
- if (lpPtr->symbol.outlineGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->symbol.outlineGC);
- }
- if (lpPtr->symbol.fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->symbol.fillGC);
- }
- if (lpPtr->errorBarGC != NULL) {
- Tk_FreeGC(graphPtr->display, lpPtr->errorBarGC);
- }
- if (lpPtr->traceGC != NULL) {
- Blt_FreePrivateGC(graphPtr->display, lpPtr->traceGC);
- }
- if (lpPtr->symbol.bitmap != None) {
- Tk_FreeBitmap(graphPtr->display, lpPtr->symbol.bitmap);
- lpPtr->symbol.bitmap = None;
- }
- if (lpPtr->symbol.mask != None) {
- Tk_FreeBitmap(graphPtr->display, lpPtr->symbol.mask);
- lpPtr->symbol.mask = None;
- }
-}
-
-
-static void
-InitPen(penPtr)
- LinePen *penPtr;
-{
- Blt_InitTextStyle(&penPtr->valueStyle);
- penPtr->configProc = ConfigurePen;
- penPtr->configSpecs = linePenConfigSpecs;
- penPtr->destroyProc = DestroyPen;
- penPtr->errorBarLineWidth = 1;
- penPtr->errorBarShow = SHOW_BOTH;
- penPtr->flags = NORMAL_PEN;
- penPtr->name = "";
- penPtr->symbol.bitmap = penPtr->symbol.mask = None;
- penPtr->symbol.outlineColor = penPtr->symbol.fillColor = COLOR_DEFAULT;
- penPtr->symbol.outlineWidth = penPtr->traceWidth = 1;
- penPtr->symbol.type = SYMBOL_CIRCLE;
- penPtr->valueShow = SHOW_NONE;
-}
-
-Pen *
-Blt_LinePen(penName)
- char *penName;
-{
- LinePen *penPtr;
-
- penPtr = Blt_Calloc(1, sizeof(LinePen));
- assert(penPtr);
- InitPen(penPtr);
- penPtr->name = Blt_Strdup(penName);
- if (strcmp(penName, "activeLine") == 0) {
- penPtr->flags = ACTIVE_PEN;
- }
- return (Pen *)penPtr;
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * In this section, the routines deal with building and filling
- * the element's data structures with transformed screen
- * coordinates. They are triggered from TranformLine which is
- * called whenever the data or coordinates axes have changed and
- * new screen coordinates need to be calculated.
- *
- * ----------------------------------------------------------------------
- */
-
-/*
- *----------------------------------------------------------------------
- *
- * ScaleSymbol --
- *
- * Returns the scaled size for the line element. Scaling depends
- * upon when the base line ranges for the element were set and
- * the current range of the graph.
- *
- * Results:
- * The new size of the symbol, after considering how much the
- * graph has been scaled, is returned.
- *
- *----------------------------------------------------------------------
- */
-static int
-ScaleSymbol(elemPtr, normalSize)
- Element *elemPtr;
- int normalSize;
-{
- int maxSize;
- double scale;
- int newSize;
-
- scale = 1.0;
- if (elemPtr->scaleSymbols) {
- double xRange, yRange;
-
- xRange = (elemPtr->axes.x->max - elemPtr->axes.x->min);
- yRange = (elemPtr->axes.y->max - elemPtr->axes.y->min);
- if (elemPtr->flags & SCALE_SYMBOL) {
- /* Save the ranges as a baseline for future scaling. */
- elemPtr->xRange = xRange;
- elemPtr->yRange = yRange;
- elemPtr->flags &= ~SCALE_SYMBOL;
- } else {
- double xScale, yScale;
-
- /* Scale the symbol by the smallest change in the X or Y axes */
- xScale = elemPtr->xRange / xRange;
- yScale = elemPtr->yRange / yRange;
- scale = MIN(xScale, yScale);
- }
- }
- newSize = Round(normalSize * scale);
-
- /*
- * Don't let the size of symbols go unbounded. Both X and Win32
- * drawing routines assume coordinates to be a signed short int.
- */
- maxSize = (int)MIN(elemPtr->graphPtr->hRange, elemPtr->graphPtr->vRange);
- if (newSize > maxSize) {
- newSize = maxSize;
- }
-
- /* Make the symbol size odd so that its center is a single pixel. */
- newSize |= 0x01;
- return newSize;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetScreenPoints --
- *
- * Generates a coordinate array of transformed screen coordinates
- * from the data points.
- *
- * Results:
- * The transformed screen coordinates are returned.
- *
- * Side effects:
- * Memory is allocated for the coordinate array.
- *
- *----------------------------------------------------------------------
- */
-static void
-GetScreenPoints(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- double *x, *y;
- register int i, n;
- register int count;
- register Point2D *screenPts;
- register int *indices;
-
- n = NumberOfPoints(linePtr);
- x = linePtr->x.valueArr;
- y = linePtr->y.valueArr;
- screenPts = Blt_Malloc(sizeof(Point2D) * n);
- assert(screenPts);
- indices = Blt_Malloc(sizeof(int) * n);
- assert(indices);
-
- count = 0; /* Count the valid screen coordinates */
- if (graphPtr->inverted) {
- for (i = 0; i < n; i++) {
- if ((FINITE(x[i])) && (FINITE(y[i]))) {
- screenPts[count].x = Blt_HMap(graphPtr, linePtr->axes.y, y[i]);
- screenPts[count].y = Blt_VMap(graphPtr, linePtr->axes.x, x[i]);
- indices[count] = i;
- count++;
- }
- }
- } else {
- for (i = 0; i < n; i++) {
- if ((FINITE(x[i])) && (FINITE(y[i]))) {
- screenPts[count].x = Blt_HMap(graphPtr, linePtr->axes.x, x[i]);
- screenPts[count].y = Blt_VMap(graphPtr, linePtr->axes.y, y[i]);
- indices[count] = i;
- count++;
- }
- }
- }
- mapPtr->screenPts = screenPts;
- mapPtr->nScreenPts = count;
- mapPtr->indices = indices;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ReducePoints --
- *
- * Generates a coordinate array of transformed screen coordinates
- * from the data points.
- *
- * Results:
- * The transformed screen coordinates are returned.
- *
- * Side effects:
- * Memory is allocated for the coordinate array.
- *
- *----------------------------------------------------------------------
- */
-static void
-ReducePoints(mapPtr, tolerance)
- MapInfo *mapPtr;
- double tolerance;
-{
- register int i, k, n;
- Point2D *screenPts;
- int *indices, *simple;
-
- simple = Blt_Malloc(sizeof(int) * mapPtr->nScreenPts);
- indices = Blt_Malloc(sizeof(int) * mapPtr->nScreenPts);
- screenPts = Blt_Malloc(sizeof(Point2D) * mapPtr->nScreenPts);
- n = Blt_SimplifyLine(mapPtr->screenPts, 0, mapPtr->nScreenPts - 1,
- tolerance, simple);
- for (i = 0; i < n; i++) {
- k = simple[i];
- screenPts[i] = mapPtr->screenPts[k];
- indices[i] = mapPtr->indices[k];
- }
-#ifdef notdef
- if (n < mapPtr->nScreenPts) {
- fprintf(stderr, "reduced from %d to %d\n", mapPtr->nScreenPts, n);
- }
-#endif
- Blt_Free(mapPtr->screenPts);
- Blt_Free(mapPtr->indices);
- Blt_Free(simple);
- mapPtr->screenPts = screenPts;
- mapPtr->indices = indices;
- mapPtr->nScreenPts = n;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GenerateSteps --
- *
- * Resets the coordinate and pen index arrays adding new points
- * for step-and-hold type smoothing.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * The temporary arrays for screen coordinates and pen indices
- * are updated.
- *
- *----------------------------------------------------------------------
- */
-static void
-GenerateSteps(mapPtr)
- MapInfo *mapPtr;
-{
- int newSize;
- register int i, count;
- Point2D *screenPts;
- int *indices;
-
- newSize = ((mapPtr->nScreenPts - 1) * 2) + 1;
- screenPts = Blt_Malloc(newSize * sizeof(Point2D));
- assert(screenPts);
- indices = Blt_Malloc(sizeof(int) * newSize);
- assert(indices);
-
- screenPts[0] = mapPtr->screenPts[0];
- indices[0] = 0;
-
- count = 1;
- for (i = 1; i < mapPtr->nScreenPts; i++) {
- screenPts[count + 1] = mapPtr->screenPts[i];
-
- /* Hold last y-coordinate, use new x-coordinate */
- screenPts[count].x = screenPts[count + 1].x;
- screenPts[count].y = screenPts[count - 1].y;
-
- /* Use the same style for both the hold and the step points */
- indices[count] = indices[count + 1] = mapPtr->indices[i];
- count += 2;
- }
- Blt_Free(mapPtr->screenPts);
- Blt_Free(mapPtr->indices);
- mapPtr->indices = indices;
- mapPtr->screenPts = screenPts;
- mapPtr->nScreenPts = newSize;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GenerateSpline --
- *
- * Computes a spline based upon the data points, returning a new
- * (larger) coordinate array or points.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * The temporary arrays for screen coordinates and data indices
- * are updated based upon spline.
- *
- * FIXME: Can't interpolate knots along the Y-axis. Need to break
- * up point array into interchangable X and Y vectors earlier.
- * Pass extents (left/right or top/bottom) as parameters.
- *
- *----------------------------------------------------------------------
- */
-static void
-GenerateSpline(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- int extra;
- register int i, j, count;
- Point2D *origPts, *intpPts;
- int *indices;
- int nIntpPts, nOrigPts;
- int result;
- int x;
-
- nOrigPts = mapPtr->nScreenPts;
- origPts = mapPtr->screenPts;
- assert(mapPtr->nScreenPts > 0);
- for (i = 0, j = 1; j < nOrigPts; i++, j++) {
- if (origPts[j].x <= origPts[i].x) {
- return; /* Points are not monotonically increasing */
- }
- }
- if (((origPts[0].x > (double)graphPtr->right)) ||
- ((origPts[mapPtr->nScreenPts - 1].x < (double)graphPtr->left))) {
- return; /* All points are clipped */
- }
- /*
- * The spline is computed in screen coordinates instead of data
- * points so that we can select the abscissas of the interpolated
- * points from each pixel horizontally across the plotting area.
- */
- extra = (graphPtr->right - graphPtr->left) + 1;
- if (extra < 1) {
- return;
- }
- nIntpPts = nOrigPts + extra + 1;
- intpPts = Blt_Malloc(nIntpPts * sizeof(Point2D));
- assert(intpPts);
-
- indices = Blt_Malloc(sizeof(int) * nIntpPts);
- assert(indices);
-
- /* Populate the x2 array with both the original X-coordinates and
- * extra X-coordinates for each horizontal pixel that the line
- * segment contains. */
- count = 0;
- for (i = 0, j = 1; j < nOrigPts; i++, j++) {
-
- /* Add the original x-coordinate */
- intpPts[count].x = origPts[i].x;
-
- /* Include the starting offset of the point in the offset array */
- indices[count] = mapPtr->indices[i];
- count++;
-
- /* Is any part of the interval (line segment) in the plotting
- * area? */
- if ((origPts[j].x >= (double)graphPtr->left) ||
- (origPts[i].x <= (double)graphPtr->right)) {
- int last;
-
- x = (int)(origPts[i].x + 1.0);
-
- /*
- * Since the line segment may be partially clipped on the
- * left or right side, the points to interpolate are
- * always interior to the plotting area.
- *
- * left right
- * x1----|--------------------------|---x2
- *
- * Pick the max of the starting X-coordinate and the
- * left edge and the min of the last X-coordinate and
- * the right edge.
- */
- x = MAX(x, graphPtr->left);
- last = (int)MIN(origPts[j].x, graphPtr->right);
-
- /* Add the extra x-coordinates to the interval. */
- while (x < last) {
- indices[count] = mapPtr->indices[i];
- intpPts[count++].x = (double)x;
- x++;
- }
- }
- }
- nIntpPts = count;
- result = FALSE;
- if (linePtr->smooth == PEN_SMOOTH_NATURAL) {
- result = Blt_NaturalSpline(origPts, nOrigPts, intpPts, nIntpPts);
- } else if (linePtr->smooth == PEN_SMOOTH_QUADRATIC) {
- result = Blt_QuadraticSpline(origPts, nOrigPts, intpPts, nIntpPts);
- }
- if (!result) {
- /* The spline interpolation failed. We'll fallback to the
- * current coordinates and do no smoothing (standard line
- * segments). */
- linePtr->smooth = PEN_SMOOTH_NONE;
- Blt_Free(intpPts);
- Blt_Free(indices);
- } else {
- Blt_Free(mapPtr->screenPts);
- Blt_Free(mapPtr->indices);
- mapPtr->indices = indices;
- mapPtr->screenPts = intpPts;
- mapPtr->nScreenPts = nIntpPts;
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * GenerateParametricSpline --
- *
- * Computes a spline based upon the data points, returning a new
- * (larger) coordinate array or points.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * The temporary arrays for screen coordinates and data indices
- * are updated based upon spline.
- *
- * FIXME: Can't interpolate knots along the Y-axis. Need to break
- * up point array into interchangable X and Y vectors earlier.
- * Pass extents (left/right or top/bottom) as parameters.
- *
- *----------------------------------------------------------------------
- */
-static void
-GenerateParametricSpline(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- Extents2D exts;
- Point2D *origPts, *intpPts;
- Point2D p, q;
- double dist;
- int *indices;
- int nIntpPts, nOrigPts;
- int result;
- register int i, j, count;
-
- nOrigPts = mapPtr->nScreenPts;
- origPts = mapPtr->screenPts;
- assert(mapPtr->nScreenPts > 0);
-
- Blt_GraphExtents(graphPtr, &exts);
-
- /*
- * Populate the x2 array with both the original X-coordinates and
- * extra X-coordinates for each horizontal pixel that the line
- * segment contains.
- */
- count = 1;
- for (i = 0, j = 1; j < nOrigPts; i++, j++) {
- p = origPts[i];
- q = origPts[j];
- count++;
- if (Blt_LineRectClip(&exts, &p, &q)) {
- count += (int)(hypot(q.x - p.x, q.y - p.y) * 0.5);
- }
- }
- nIntpPts = count;
- intpPts = Blt_Malloc(nIntpPts * sizeof(Point2D));
- assert(intpPts);
-
- indices = Blt_Malloc(sizeof(int) * nIntpPts);
- assert(indices);
-
- /*
- * FIXME: This is just plain wrong. The spline should be computed
- * and evaluated in separate steps. This will mean breaking
- * up this routine since the catrom coefficients can be
- * independently computed for original data point. This
- * also handles the problem of allocating enough points
- * since evaluation is independent of the number of points
- * to be evalualted. The interpolated
- * line segments should be clipped, not the original segments.
- */
- count = 0;
- for (i = 0, j = 1; j < nOrigPts; i++, j++) {
- p = origPts[i];
- q = origPts[j];
-
- dist = hypot(q.x - p.x, q.y - p.y);
- /* Add the original x-coordinate */
- intpPts[count].x = (double)i;
- intpPts[count].y = 0.0;
-
- /* Include the starting offset of the point in the offset array */
- indices[count] = mapPtr->indices[i];
- count++;
-
- /* Is any part of the interval (line segment) in the plotting
- * area? */
-
- if (Blt_LineRectClip(&exts, &p, &q)) {
- double distP, distQ;
-
- distP = hypot(p.x - origPts[i].x, p.y - origPts[i].y);
- distQ = hypot(q.x - origPts[i].x, q.y - origPts[i].y);
- distP += 2.0;
- while(distP <= distQ) {
- /* Point is indicated by its interval and parameter t. */
- intpPts[count].x = (double)i;
- intpPts[count].y = distP / dist;
- indices[count] = mapPtr->indices[i];
- count++;
- distP += 2.0;
- }
- }
- }
- intpPts[count].x = (double)i;
- intpPts[count].y = 0.0;
- indices[count] = mapPtr->indices[i];
- count++;
- nIntpPts = count;
- result = FALSE;
- if (linePtr->smooth == PEN_SMOOTH_NATURAL) {
- result = Blt_NaturalParametricSpline(origPts, nOrigPts, &exts, FALSE,
- intpPts, nIntpPts);
- } else if (linePtr->smooth == PEN_SMOOTH_CATROM) {
- result = Blt_CatromParametricSpline(origPts, nOrigPts, intpPts,
- nIntpPts);
- }
- if (!result) {
- /* The spline interpolation failed. We'll fallback to the
- * current coordinates and do no smoothing (standard line
- * segments). */
- linePtr->smooth = PEN_SMOOTH_NONE;
- Blt_Free(intpPts);
- Blt_Free(indices);
- } else {
- Blt_Free(mapPtr->screenPts);
- Blt_Free(mapPtr->indices);
- mapPtr->indices = indices;
- mapPtr->screenPts = intpPts;
- mapPtr->nScreenPts = nIntpPts;
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * MapSymbols --
- *
- * Creates two arrays of points and pen indices, filled with
- * the screen coordinates of the visible
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is freed and allocated for the index array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapSymbols(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- Extents2D exts;
- Point2D *symbolPts;
- int *indices;
- register int i, count;
-
- symbolPts = Blt_Malloc(sizeof(Point2D) * mapPtr->nScreenPts);
- assert(symbolPts);
-
- indices = Blt_Malloc(sizeof(int) * mapPtr->nScreenPts);
- assert(indices);
-
- Blt_GraphExtents(graphPtr, &exts);
- count = 0; /* Count the number of visible points */
-
- for (i = 0; i < mapPtr->nScreenPts; i++) {
- if (PointInRegion(&exts, mapPtr->screenPts[i].x,
- mapPtr->screenPts[i].y)) {
- symbolPts[count].x = mapPtr->screenPts[i].x;
- symbolPts[count].y = mapPtr->screenPts[i].y;
- indices[count] = mapPtr->indices[i];
- count++;
- }
- }
- linePtr->symbolPts = symbolPts;
- linePtr->nSymbolPts = count;
- linePtr->symbolToData = indices;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MapActiveSymbols --
- *
- * Creates an array of points of the active graph coordinates.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is freed and allocated for the active point array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapActiveSymbols(graphPtr, linePtr)
- Graph *graphPtr;
- Line *linePtr;
-{
- Extents2D exts;
- double x, y;
- int count;
- Point2D *activePts;
- register int i;
- int pointIndex;
- int nPoints;
- int *activeToData;
-
- if (linePtr->activePts != NULL) {
- Blt_Free(linePtr->activePts);
- linePtr->activePts = NULL;
- }
- if (linePtr->activeToData != NULL) {
- Blt_Free(linePtr->activeToData);
- linePtr->activeToData = NULL;
- }
- Blt_GraphExtents(graphPtr, &exts);
- activePts = Blt_Malloc(sizeof(Point2D) * linePtr->nActiveIndices);
- assert(activePts);
- activeToData = Blt_Malloc(sizeof(int) * linePtr->nActiveIndices);
- nPoints = NumberOfPoints(linePtr);
- count = 0; /* Count the visible active points */
- for (i = 0; i < linePtr->nActiveIndices; i++) {
- pointIndex = linePtr->activeIndices[i];
- if (pointIndex >= nPoints) {
- continue; /* Index not available */
- }
- x = linePtr->x.valueArr[pointIndex];
- y = linePtr->y.valueArr[pointIndex];
- activePts[count] = Blt_Map2D(graphPtr, x, y, &(linePtr->axes));
- activeToData[count] = pointIndex;
- if (PointInRegion(&exts, activePts[count].x, activePts[count].y)) {
- count++;
- }
- }
- if (count > 0) {
- linePtr->activePts = activePts;
- linePtr->activeToData = activeToData;
- } else {
- /* No active points were visible. */
- Blt_Free(activePts);
- Blt_Free(activeToData);
- }
- linePtr->nActivePts = count;
- linePtr->flags &= ~ACTIVE_PENDING;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MapStrip --
- *
- * Creates an array of line segments of the graph coordinates.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is allocated for the line segment array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapStrip(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- Extents2D exts;
- Segment2D *strips;
- int *indices, *indexPtr;
- register Point2D *endPtr, *pointPtr;
- register Segment2D *segPtr;
- register int count;
-
- indices = Blt_Malloc(sizeof(int) * mapPtr->nScreenPts);
- assert(indices);
-
- /*
- * Create array to hold points for line segments (not polyline
- * coordinates). So allocate twice the number of points.
- */
- segPtr = strips = Blt_Malloc(mapPtr->nScreenPts * sizeof(Segment2D));
- assert(strips);
-
- Blt_GraphExtents(graphPtr, &exts);
- count = 0; /* Count the number of segments. */
- indexPtr = mapPtr->indices;
- for (pointPtr = mapPtr->screenPts,
- endPtr = mapPtr->screenPts + (mapPtr->nScreenPts - 1);
- pointPtr < endPtr; pointPtr++, indexPtr++) {
- segPtr->p = pointPtr[0];
- segPtr->q = pointPtr[1];
- if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
- segPtr++;
- indices[count] = *indexPtr;
- count++;
- }
- }
- linePtr->stripToData = indices;
- linePtr->nStrips = count;
- linePtr->strips = strips;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MergePens --
- *
- * Reorders the both arrays of points and segments to merge pens.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The old arrays are freed and new ones allocated containing
- * the reordered points and segments.
- *
- *----------------------------------------------------------------------
- */
-static void
-MergePens(linePtr, dataToStyle)
- Line *linePtr;
- PenStyle **dataToStyle;
-{
- LinePenStyle *stylePtr;
- register int i;
- Blt_ChainLink *linkPtr;
-
- if (Blt_ChainGetLength(linePtr->palette) < 2) {
- linkPtr = Blt_ChainFirstLink(linePtr->palette);
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->nStrips = linePtr->nStrips;
- stylePtr->strips = linePtr->strips;
- stylePtr->nSymbolPts = linePtr->nSymbolPts;
- stylePtr->symbolPts = linePtr->symbolPts;
- stylePtr->xErrorBarCnt = linePtr->xErrorBarCnt;
- stylePtr->yErrorBarCnt = linePtr->yErrorBarCnt;
- stylePtr->xErrorBars = linePtr->xErrorBars;
- stylePtr->yErrorBars = linePtr->yErrorBars;
- stylePtr->errorBarCapWidth = linePtr->errorBarCapWidth;
- return;
- }
-
- /* We have more than one style. Group line segments and points of
- * like pen styles. */
-
- if (linePtr->nStrips > 0) {
- Segment2D *strips;
- int *stripToData;
- register Segment2D *segPtr;
- register int *indexPtr;
- int dataIndex;
-
- strips = Blt_Malloc(linePtr->nStrips * sizeof(Segment2D));
- stripToData = Blt_Malloc(linePtr->nStrips * sizeof(int));
- assert(strips && stripToData);
- segPtr = strips, indexPtr = stripToData;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->strips = segPtr;
- for (i = 0; i < linePtr->nStrips; i++) {
- dataIndex = linePtr->stripToData[i];
- if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
- *segPtr++ = linePtr->strips[i];
- *indexPtr++ = dataIndex;
- }
- }
- stylePtr->nStrips = segPtr - stylePtr->strips;
- }
- Blt_Free(linePtr->strips);
- linePtr->strips = strips;
- Blt_Free(linePtr->stripToData);
- linePtr->stripToData = stripToData;
- }
- if (linePtr->nSymbolPts > 0) {
- int *indexPtr;
- register Point2D *symbolPts, *pointPtr;
- register int *symbolToData;
- int dataIndex;
-
- symbolPts = Blt_Malloc(linePtr->nSymbolPts * sizeof(Point2D));
- symbolToData = Blt_Malloc(linePtr->nSymbolPts * sizeof(int));
- assert(symbolPts && symbolToData);
- pointPtr = symbolPts, indexPtr = symbolToData;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->symbolPts = pointPtr;
- for (i = 0; i < linePtr->nSymbolPts; i++) {
- dataIndex = linePtr->symbolToData[i];
- if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
- *pointPtr++ = linePtr->symbolPts[i];
- *indexPtr++ = dataIndex;
- }
- }
- stylePtr->nSymbolPts = pointPtr - stylePtr->symbolPts;
- }
- Blt_Free(linePtr->symbolPts);
- linePtr->symbolPts = symbolPts;
- Blt_Free(linePtr->symbolToData);
- linePtr->symbolToData = symbolToData;
- }
- if (linePtr->xErrorBarCnt > 0) {
- Segment2D *xErrorBars, *segPtr;
- int *xErrorToData, *indexPtr;
- int dataIndex;
-
- xErrorBars = Blt_Malloc(linePtr->xErrorBarCnt * sizeof(Segment2D));
- xErrorToData = Blt_Malloc(linePtr->xErrorBarCnt * sizeof(int));
- assert(xErrorBars);
- segPtr = xErrorBars, indexPtr = xErrorToData;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette);
- linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->xErrorBars = segPtr;
- for (i = 0; i < linePtr->xErrorBarCnt; i++) {
- dataIndex = linePtr->xErrorToData[i];
- if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
- *segPtr++ = linePtr->xErrorBars[i];
- *indexPtr++ = dataIndex;
- }
- }
- stylePtr->xErrorBarCnt = segPtr - stylePtr->xErrorBars;
- }
- Blt_Free(linePtr->xErrorBars);
- linePtr->xErrorBars = xErrorBars;
- Blt_Free(linePtr->xErrorToData);
- linePtr->xErrorToData = xErrorToData;
- }
- if (linePtr->yErrorBarCnt > 0) {
- Segment2D *errorBars, *segPtr;
- int *errorToData, *indexPtr;
- int dataIndex;
-
- errorBars = Blt_Malloc(linePtr->yErrorBarCnt * sizeof(Segment2D));
- errorToData = Blt_Malloc(linePtr->yErrorBarCnt * sizeof(int));
- assert(errorBars);
- segPtr = errorBars, indexPtr = errorToData;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette);
- linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->yErrorBars = segPtr;
- for (i = 0; i < linePtr->yErrorBarCnt; i++) {
- dataIndex = linePtr->yErrorToData[i];
- if (dataToStyle[dataIndex] == (PenStyle *)stylePtr) {
- *segPtr++ = linePtr->yErrorBars[i];
- *indexPtr++ = dataIndex;
- }
- }
- stylePtr->yErrorBarCnt = segPtr - stylePtr->yErrorBars;
- }
- Blt_Free(linePtr->yErrorBars);
- linePtr->yErrorBars = errorBars;
- Blt_Free(linePtr->yErrorToData);
- linePtr->yErrorToData = errorToData;
- }
-}
-
-#define CLIP_TOP (1<<0)
-#define CLIP_BOTTOM (1<<1)
-#define CLIP_RIGHT (1<<2)
-#define CLIP_LEFT (1<<3)
-
-INLINE static int
-OutCode(extsPtr, p)
- Extents2D *extsPtr;
- Point2D *p;
-{
- int code;
-
- code = 0;
- if (p->x > extsPtr->right) {
- code |= CLIP_RIGHT;
- } else if (p->x < extsPtr->left) {
- code |= CLIP_LEFT;
- }
- if (p->y > extsPtr->bottom) {
- code |= CLIP_BOTTOM;
- } else if (p->y < extsPtr->top) {
- code |= CLIP_TOP;
- }
- return code;
-}
-
-static int
-ClipSegment(extsPtr, code1, code2, p, q)
- Extents2D *extsPtr;
- register int code1, code2;
- register Point2D *p, *q;
-{
- int inside, outside;
-
- inside = ((code1 | code2) == 0);
- outside = ((code1 & code2) != 0);
-
- /*
- * In the worst case, we'll clip the line segment against each of
- * the four sides of the bounding rectangle.
- */
- while ((!outside) && (!inside)) {
- if (code1 == 0) {
- Point2D *tmp;
- int code;
-
- /* Swap pointers and out codes */
- tmp = p, p = q, q = tmp;
- code = code1, code1 = code2, code2 = code;
- }
- if (code1 & CLIP_LEFT) {
- p->y += (q->y - p->y) *
- (extsPtr->left - p->x) / (q->x - p->x);
- p->x = extsPtr->left;
- } else if (code1 & CLIP_RIGHT) {
- p->y += (q->y - p->y) *
- (extsPtr->right - p->x) / (q->x - p->x);
- p->x = extsPtr->right;
- } else if (code1 & CLIP_BOTTOM) {
- p->x += (q->x - p->x) *
- (extsPtr->bottom - p->y) / (q->y - p->y);
- p->y = extsPtr->bottom;
- } else if (code1 & CLIP_TOP) {
- p->x += (q->x - p->x) *
- (extsPtr->top - p->y) / (q->y - p->y);
- p->y = extsPtr->top;
- }
- code1 = OutCode(extsPtr, p);
-
- inside = ((code1 | code2) == 0);
- outside = ((code1 & code2) != 0);
- }
- return (!inside);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * SaveTrace --
- *
- * Creates a new trace and inserts it into the line's
- * list of traces.
- *
- * Results:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static void
-SaveTrace(linePtr, start, length, mapPtr)
- Line *linePtr;
- int start; /* Starting index of the trace in data point
- * array. Used to figure out closest point */
- int length; /* Number of points forming the trace */
- MapInfo *mapPtr;
-{
- Trace *tracePtr;
- Point2D *screenPts;
- int *indices;
- register int i, j;
-
- tracePtr = Blt_Malloc(sizeof(Trace));
- assert(tracePtr);
- screenPts = Blt_Malloc(sizeof(Point2D) * length);
- assert(screenPts);
- indices = Blt_Malloc(sizeof(int) * length);
- assert(indices);
-
- /* Copy the screen coordinates of the trace into the point array */
-
- if (mapPtr->indices != NULL) {
- for (i = 0, j = start; i < length; i++, j++) {
- screenPts[i].x = mapPtr->screenPts[j].x;
- screenPts[i].y = mapPtr->screenPts[j].y;
- indices[i] = mapPtr->indices[j];
- }
- } else {
- for (i = 0, j = start; i < length; i++, j++) {
- screenPts[i].x = mapPtr->screenPts[j].x;
- screenPts[i].y = mapPtr->screenPts[j].y;
- indices[i] = j;
- }
- }
- tracePtr->nScreenPts = length;
- tracePtr->screenPts = screenPts;
- tracePtr->symbolToData = indices;
- tracePtr->start = start;
- if (linePtr->traces == NULL) {
- linePtr->traces = Blt_ChainCreate();
- }
- Blt_ChainAppend(linePtr->traces, tracePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * FreeTraces --
- *
- * Deletes all the traces for the line.
- *
- * Results:
- * None.
- *
- *----------------------------------------------------------------------
- */
-static void
-FreeTraces(linePtr)
- Line *linePtr;
-{
- Blt_ChainLink *linkPtr;
- Trace *tracePtr;
-
- for (linkPtr = Blt_ChainFirstLink(linePtr->traces); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- tracePtr = Blt_ChainGetValue(linkPtr);
- Blt_Free(tracePtr->symbolToData);
- Blt_Free(tracePtr->screenPts);
- Blt_Free(tracePtr);
- }
- Blt_ChainDestroy(linePtr->traces);
- linePtr->traces = NULL;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MapTraces --
- *
- * Creates an array of line segments of the graph coordinates.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is allocated for the line segment array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapTraces(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- int start, count;
- int code1, code2;
- Point2D *p, *q;
- Point2D s;
- Extents2D exts;
- register int i;
- int broken, offscreen;
-
- Blt_GraphExtents(graphPtr, &exts);
- count = 1;
- code1 = OutCode(&exts, mapPtr->screenPts);
- p = mapPtr->screenPts;
- q = p + 1;
- for (i = 1; i < mapPtr->nScreenPts; i++, p++, q++) {
- code2 = OutCode(&exts, q);
- if (code2 != 0) {
- /* Save the coordinates of the last point, before clipping */
- s = *q;
- }
- broken = BROKEN_TRACE(linePtr->penDir, p->x, q->x);
- offscreen = ClipSegment(&exts, code1, code2, p, q);
- if (broken || offscreen) {
-
- /*
- * The last line segment is either totally clipped by the plotting
- * area or the x-direction is wrong, breaking the trace. Either
- * way, save information about the last trace (if one exists),
- * discarding the current line segment
- */
-
- if (count > 1) {
- start = i - count;
- SaveTrace(linePtr, start, count, mapPtr);
- count = 1;
- }
- } else {
- count++; /* Add the point to the trace. */
- if (code2 != 0) {
-
- /*
- * If the last point is clipped, this means that the trace is
- * broken after this point. Restore the original coordinate
- * (before clipping) after saving the trace.
- */
-
- start = i - (count - 1);
- SaveTrace(linePtr, start, count, mapPtr);
- mapPtr->screenPts[i] = s;
- count = 1;
- }
- }
- code1 = code2;
- }
- if (count > 1) {
- start = i - count;
- SaveTrace(linePtr, start, count, mapPtr);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MapFillArea --
- *
- * Creates an array of points that represent a polygon that fills
- * the area under the element.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is allocated for the polygon point array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapFillArea(graphPtr, linePtr, mapPtr)
- Graph *graphPtr;
- Line *linePtr;
- MapInfo *mapPtr;
-{
- Point2D *origPts, *clipPts;
- Extents2D exts;
- double maxY;
- register int i, n;
-
- if (linePtr->fillPts != NULL) {
- Blt_Free(linePtr->fillPts);
- linePtr->fillPts = NULL;
- linePtr->nFillPts = 0;
- }
- if (mapPtr->nScreenPts < 3) {
- return;
- }
- n = mapPtr->nScreenPts + 3;
- Blt_GraphExtents(graphPtr, &exts);
-
- maxY = (double)graphPtr->bottom;
- origPts = Blt_Malloc(sizeof(Point2D) * n);
- for (i = 0; i < mapPtr->nScreenPts; i++) {
- origPts[i].x = mapPtr->screenPts[i].x + 1;
- origPts[i].y = mapPtr->screenPts[i].y;
- if (origPts[i].y > maxY) {
- maxY = origPts[i].y;
- }
- }
- /* Add edges to make (if necessary) the polygon fill to the bottom
- * of plotting window */
- origPts[i].x = origPts[i - 1].x;
- origPts[i].y = maxY;
- i++;
- origPts[i].x = origPts[0].x;
- origPts[i].y = maxY;
- i++;
- origPts[i] = origPts[0];
-
- clipPts = Blt_Malloc(sizeof(Point2D) * n * 3);
- assert(clipPts);
- n = Blt_PolyRectClip(&exts, origPts, n - 1, clipPts);
-
- Blt_Free(origPts);
- if (n < 3) {
- Blt_Free(clipPts);
- } else {
- linePtr->fillPts = clipPts;
- linePtr->nFillPts = n;
- }
-}
-
-static void
-ResetLine(linePtr)
- Line *linePtr;
-{
- FreeTraces(linePtr);
- ClearPalette(linePtr->palette);
- if (linePtr->symbolPts != NULL) {
- Blt_Free(linePtr->symbolPts);
- }
- if (linePtr->symbolToData != NULL) {
- Blt_Free(linePtr->symbolToData);
- }
- if (linePtr->strips != NULL) {
- Blt_Free(linePtr->strips);
- }
- if (linePtr->stripToData != NULL) {
- Blt_Free(linePtr->stripToData);
- }
- if (linePtr->activePts != NULL) {
- Blt_Free(linePtr->activePts);
- }
- if (linePtr->activeToData != NULL) {
- Blt_Free(linePtr->activeToData);
- }
- if (linePtr->xErrorBars != NULL) {
- Blt_Free(linePtr->xErrorBars);
- }
- if (linePtr->xErrorToData != NULL) {
- Blt_Free(linePtr->xErrorToData);
- }
- if (linePtr->yErrorBars != NULL) {
- Blt_Free(linePtr->yErrorBars);
- }
- if (linePtr->yErrorToData != NULL) {
- Blt_Free(linePtr->yErrorToData);
- }
- linePtr->xErrorBars = linePtr->yErrorBars = linePtr->strips = NULL;
- linePtr->symbolPts = linePtr->activePts = NULL;
- linePtr->stripToData = linePtr->symbolToData = linePtr->xErrorToData =
- linePtr->yErrorToData = linePtr->activeToData = NULL;
- linePtr->nActivePts = linePtr->nSymbolPts = linePtr->nStrips =
- linePtr->xErrorBarCnt = linePtr->yErrorBarCnt = 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * MapLine --
- *
- * Calculates the actual window coordinates of the line element.
- * The window coordinates are saved in an allocated point array.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is (re)allocated for the point array.
- *
- *----------------------------------------------------------------------
- */
-static void
-MapLine(graphPtr, elemPtr)
- Graph *graphPtr; /* Graph widget record */
- Element *elemPtr; /* Element component record */
-{
- Line *linePtr = (Line *)elemPtr;
- MapInfo mapInfo;
- int size, nPoints;
- PenStyle **dataToStyle;
- Blt_ChainLink *linkPtr;
- LinePenStyle *stylePtr;
-
- ResetLine(linePtr);
- nPoints = NumberOfPoints(linePtr);
- if (nPoints < 1) {
- return; /* No data points */
- }
- GetScreenPoints(graphPtr, linePtr, &mapInfo);
- MapSymbols(graphPtr, linePtr, &mapInfo);
-
- if ((linePtr->flags & ACTIVE_PENDING) && (linePtr->nActiveIndices > 0)) {
- MapActiveSymbols(graphPtr, linePtr);
- }
- /*
- * Map connecting line segments if they are to be displayed.
- */
- if ((nPoints > 1) && ((graphPtr->classUid == bltStripElementUid) ||
- (linePtr->builtinPen.traceWidth > 0))) {
- linePtr->smooth = linePtr->reqSmooth;
-
- /*
- * Do smoothing if necessary. This can extend the coordinate array,
- * so both mapInfo.points and mapInfo.nPoints may change.
- */
-
- switch (linePtr->smooth) {
- case PEN_SMOOTH_STEP:
- GenerateSteps(&mapInfo);
- break;
-
- case PEN_SMOOTH_NATURAL:
- case PEN_SMOOTH_QUADRATIC:
- if (mapInfo.nScreenPts < 3) {
- /* Can't interpolate with less than three points. */
- linePtr->smooth = PEN_SMOOTH_NONE;
- } else {
- GenerateSpline(graphPtr, linePtr, &mapInfo);
- }
- break;
-
- case PEN_SMOOTH_CATROM:
- if (mapInfo.nScreenPts < 3) {
- /* Can't interpolate with less than three points. */
- linePtr->smooth = PEN_SMOOTH_NONE;
- } else {
- GenerateParametricSpline(graphPtr, linePtr, &mapInfo);
- }
- break;
-
- default:
- break;
- }
- if (linePtr->rTolerance > 0.0) {
- ReducePoints(&mapInfo, linePtr->rTolerance);
- }
- if ((Blt_HasTile(linePtr->fillTile)) || (linePtr->fillStipple != None)) {
- MapFillArea(graphPtr, linePtr, &mapInfo);
- }
- if (graphPtr->classUid == bltStripElementUid) {
- MapStrip(graphPtr, linePtr, &mapInfo);
- } else {
- MapTraces(graphPtr, linePtr, &mapInfo);
- }
- }
- Blt_Free(mapInfo.screenPts);
- Blt_Free(mapInfo.indices);
-
- /* Set the symbol size of all the pen styles. */
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- size = ScaleSymbol(elemPtr, stylePtr->penPtr->symbol.size);
- stylePtr->symbolSize = size;
- stylePtr->errorBarCapWidth = (stylePtr->penPtr->errorBarCapWidth > 0)
- ? stylePtr->penPtr->errorBarCapWidth : (int)(size * 0.6666666);
- stylePtr->errorBarCapWidth /= 2;
- }
- dataToStyle = Blt_StyleMap((Element *)linePtr);
- if (((linePtr->yHigh.nValues > 0) && (linePtr->yLow.nValues > 0)) ||
- ((linePtr->xHigh.nValues > 0) && (linePtr->xLow.nValues > 0)) ||
- (linePtr->xError.nValues > 0) || (linePtr->yError.nValues > 0)) {
- Blt_MapErrorBars(graphPtr, (Element *)linePtr, dataToStyle);
- }
- MergePens(linePtr, dataToStyle);
- Blt_Free(dataToStyle);
-}
-
-static double
-DistanceToLine(x, y, p, q, t)
- int x, y; /* Sample X-Y coordinate. */
- Point2D *p, *q; /* End points of the line segment. */
- Point2D *t; /* (out) Point on line segment. */
-{
- double right, left, top, bottom;
-
- *t = Blt_GetProjection(x, y, p, q);
- if (p->x > q->x) {
- right = p->x, left = q->x;
- } else {
- left = p->x, right = q->x;
- }
- if (p->y > q->y) {
- bottom = p->y, top = q->y;
- } else {
- top = p->y, bottom = q->y;
- }
- if (t->x > right) {
- t->x = right;
- } else if (t->x < left) {
- t->x = left;
- }
- if (t->y > bottom) {
- t->y = bottom;
- } else if (t->y < top) {
- t->y = top;
- }
- return hypot((t->x - x), (t->y - y));
-}
-
-static double
-DistanceToX(x, y, p, q, t)
- int x, y; /* Search X-Y coordinate. */
- Point2D *p, *q; /* End points of the line segment. */
- Point2D *t; /* (out) Point on line segment. */
-{
- double dx, dy;
- double dist;
-
- if (p->x > q->x) {
- if ((x > p->x) || (x < q->x)) {
- return DBL_MAX; /* X-coordinate outside line segment. */
- }
- } else {
- if ((x > q->x) || (x < p->x)) {
- return DBL_MAX; /* X-coordinate outside line segment. */
- }
- }
- dx = p->x - q->x;
- dy = p->y - q->y;
- t->x = (double)x;
- if (FABS(dx) < DBL_EPSILON) {
- double d1, d2;
- /* Same X-coordinate indicates a vertical line. Pick the
- * closest end point. */
- d1 = p->y - y;
- d2 = q->y - y;
- if (FABS(d1) < FABS(d2)) {
- t->y = p->y, dist = d1;
- } else {
- t->y = q->y, dist = d2;
- }
- } else if (FABS(dy) < DBL_EPSILON) {
- /* Horizontal line. */
- t->y = p->y, dist = p->y - y;
- } else {
- double m, b;
-
- m = dy / dx;
- b = p->y - (m * p->x);
- t->y = (x * m) + b;
- dist = y - t->y;
- }
- return FABS(dist);
-}
-
-static double
-DistanceToY(x, y, p, q, t)
- int x, y; /* Search X-Y coordinate. */
- Point2D *p, *q; /* End points of the line segment. */
- Point2D *t; /* (out) Point on line segment. */
-{
- double dx, dy;
- double dist;
-
- if (p->y > q->y) {
- if ((y > p->y) || (y < q->y)) {
- return DBL_MAX;
- }
- } else {
- if ((y > q->y) || (y < p->y)) {
- return DBL_MAX;
- }
- }
- dx = p->x - q->x;
- dy = p->y - q->y;
- t->y = y;
- if (FABS(dy) < DBL_EPSILON) {
- double d1, d2;
-
- /* Save Y-coordinate indicates an horizontal line. Pick the
- * closest end point. */
- d1 = p->x - x;
- d2 = q->x - x;
- if (FABS(d1) < FABS(d2)) {
- t->x = p->x, dist = d1;
- } else {
- t->x = q->x, dist = d2;
- }
- } else if (FABS(dx) < DBL_EPSILON) {
- /* Vertical line. */
- t->x = p->x, dist = p->x - x;
- } else {
- double m, b;
-
- m = dy / dx;
- b = p->y - (m * p->x);
- t->x = (y - b) / m;
- dist = x - t->x;
- }
- return FABS(dist);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ClosestTrace --
- *
- * Find the line segment closest to the given window coordinate
- * in the element.
- *
- * Results:
- * If a new minimum distance is found, the information regarding
- * it is returned via searchPtr.
- *
- *----------------------------------------------------------------------
- */
-static int
-ClosestTrace(graphPtr, linePtr, searchPtr, distProc)
- Graph *graphPtr; /* Graph widget record */
- Line *linePtr; /* Line element record */
- ClosestSearch *searchPtr; /* Info about closest point in element */
- DistanceProc *distProc;
-{
- Blt_ChainLink *linkPtr;
- Point2D closest, b;
- Trace *tracePtr;
- double dist, minDist;
- register Point2D *pointPtr, *endPtr;
- int i;
-
- i = -1; /* Suppress compiler warning. */
- minDist = searchPtr->dist;
- for (linkPtr = Blt_ChainFirstLink(linePtr->traces); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- tracePtr = Blt_ChainGetValue(linkPtr);
- for (pointPtr = tracePtr->screenPts,
- endPtr = tracePtr->screenPts + (tracePtr->nScreenPts - 1);
- pointPtr < endPtr; pointPtr++) {
- dist = (*distProc)(searchPtr->x, searchPtr->y, pointPtr,
- pointPtr + 1, &b);
- if (dist < minDist) {
- closest = b;
- i = tracePtr->symbolToData[pointPtr - tracePtr->screenPts];
- minDist = dist;
- }
- }
- }
- if (minDist < searchPtr->dist) {
- searchPtr->dist = minDist;
- searchPtr->elemPtr = (Element *)linePtr;
- searchPtr->index = i;
- searchPtr->point = Blt_InvMap2D(graphPtr, closest.x, closest.y,
- &(linePtr->axes));
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ClosestStrip --
- *
- * Find the line segment closest to the given window coordinate
- * in the element.
- *
- * Results:
- * If a new minimum distance is found, the information regarding
- * it is returned via searchPtr.
- *
- *----------------------------------------------------------------------
- */
-static int
-ClosestStrip(graphPtr, linePtr, searchPtr, distProc)
- Graph *graphPtr; /* Graph widget record */
- Line *linePtr; /* Line element record */
- ClosestSearch *searchPtr; /* Info about closest point in element */
- DistanceProc *distProc;
-{
- Point2D closest, b;
- double dist, minDist;
- int count;
- int i;
- register Segment2D *s;
-
- i = 0;
- minDist = searchPtr->dist;
- s = linePtr->strips;
- for (count = 0; count < linePtr->nStrips; count++, s++) {
- dist = (*distProc)(searchPtr->x, searchPtr->y, &(s->p), &(s->q), &b);
- if (dist < minDist) {
- closest = b;
- i = linePtr->stripToData[count];
- minDist = dist;
- }
- }
- if (minDist < searchPtr->dist) {
- searchPtr->dist = minDist;
- searchPtr->elemPtr = (Element *)linePtr;
- searchPtr->index = i;
- searchPtr->point = Blt_InvMap2D(graphPtr, closest.x, closest.y,
- &(linePtr->axes));
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ClosestPoint --
- *
- * Find the element whose data point is closest to the given screen
- * coordinate.
- *
- * Results:
- * If a new minimum distance is found, the information regarding
- * it is returned via searchPtr.
- *
- *----------------------------------------------------------------------
- */
-static void
-ClosestPoint(linePtr, searchPtr)
- Line *linePtr; /* Line element that we are looking at */
- ClosestSearch *searchPtr; /* Assorted information related to searching
- * for the closest point */
-{
- double dist, minDist;
- double dx, dy;
- int count, i;
- register Point2D *pointPtr;
-
- minDist = searchPtr->dist;
- i = 0;
-
- /*
- * Instead of testing each data point in graph coordinates, look at
- * the array of mapped screen coordinates. The advantages are
- * 1) only examine points that are visible (unclipped), and
- * 2) the computed distance is already in screen coordinates.
- */
- pointPtr = linePtr->symbolPts;
- for (count = 0; count < linePtr->nSymbolPts; count++, pointPtr++) {
- dx = (double)(searchPtr->x - pointPtr->x);
- dy = (double)(searchPtr->y - pointPtr->y);
- if (searchPtr->along == SEARCH_BOTH) {
- dist = hypot(dx, dy);
- } else if (searchPtr->along == SEARCH_X) {
- dist = dx;
- } else if (searchPtr->along == SEARCH_Y) {
- dist = dy;
- } else {
- /* This can't happen */
- continue;
- }
- if (dist < minDist) {
- i = linePtr->symbolToData[count];
- minDist = dist;
- }
- }
- if (minDist < searchPtr->dist) {
- searchPtr->elemPtr = (Element *)linePtr;
- searchPtr->dist = minDist;
- searchPtr->index = i;
- searchPtr->point.x = linePtr->x.valueArr[i];
- searchPtr->point.y = linePtr->y.valueArr[i];
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * GetLineExtents --
- *
- * Retrieves the range of the line element
- *
- * Results:
- * Returns the number of data points in the element.
- *
- *----------------------------------------------------------------------
- */
-static void
-GetLineExtents(elemPtr, extsPtr)
- Element *elemPtr;
- Extents2D *extsPtr;
-{
- int nPoints;
-
- extsPtr->top = extsPtr->left = DBL_MAX;
- extsPtr->bottom = extsPtr->right = -DBL_MAX;
-
- nPoints = NumberOfPoints(elemPtr);
- if (nPoints < 1) {
- return;
- }
- extsPtr->right = elemPtr->x.max;
- if ((elemPtr->x.min <= 0.0) && (elemPtr->axes.x->logScale)) {
- extsPtr->left = Blt_FindElemVectorMinimum(&elemPtr->x, DBL_MIN);
- } else {
- extsPtr->left = elemPtr->x.min;
- }
- extsPtr->bottom = elemPtr->y.max;
- if ((elemPtr->y.min <= 0.0) && (elemPtr->axes.y->logScale)) {
- extsPtr->top = Blt_FindElemVectorMinimum(&elemPtr->y, DBL_MIN);
- } else {
- extsPtr->top = elemPtr->y.min;
- }
-
- /* Correct the data limits for error bars */
-
- if (elemPtr->xError.nValues > 0) {
- register int i;
- double x;
-
- nPoints = MIN(elemPtr->xError.nValues, nPoints);
- for (i = 0; i < nPoints; i++) {
- x = elemPtr->x.valueArr[i] + elemPtr->xError.valueArr[i];
- if (x > extsPtr->right) {
- extsPtr->right = x;
- }
- x = elemPtr->x.valueArr[i] - elemPtr->xError.valueArr[i];
- if (elemPtr->axes.x->logScale) {
- if (x < 0.0) {
- x = -x; /* Mirror negative values, instead
- * of ignoring them. */
- }
- if ((x > DBL_MIN) && (x < extsPtr->left)) {
- extsPtr->left = x;
- }
- } else if (x < extsPtr->left) {
- extsPtr->left = x;
- }
- }
- } else {
- if ((elemPtr->xHigh.nValues > 0) &&
- (elemPtr->xHigh.max > extsPtr->right)) {
- extsPtr->right = elemPtr->xHigh.max;
- }
- if (elemPtr->xLow.nValues > 0) {
- double left;
-
- if ((elemPtr->xLow.min <= 0.0) &&
- (elemPtr->axes.x->logScale)) {
- left = Blt_FindElemVectorMinimum(&elemPtr->xLow, DBL_MIN);
- } else {
- left = elemPtr->xLow.min;
- }
- if (left < extsPtr->left) {
- extsPtr->left = left;
- }
- }
- }
-
- if (elemPtr->yError.nValues > 0) {
- register int i;
- double y;
-
- nPoints = MIN(elemPtr->yError.nValues, nPoints);
- for (i = 0; i < nPoints; i++) {
- y = elemPtr->y.valueArr[i] + elemPtr->yError.valueArr[i];
- if (y > extsPtr->bottom) {
- extsPtr->bottom = y;
- }
- y = elemPtr->y.valueArr[i] - elemPtr->yError.valueArr[i];
- if (elemPtr->axes.y->logScale) {
- if (y < 0.0) {
- y = -y; /* Mirror negative values, instead
- * of ignoring them. */
- }
- if ((y > DBL_MIN) && (y < extsPtr->left)) {
- extsPtr->top = y;
- }
- } else if (y < extsPtr->top) {
- extsPtr->top = y;
- }
- }
- } else {
- if ((elemPtr->yHigh.nValues > 0) &&
- (elemPtr->yHigh.max > extsPtr->bottom)) {
- extsPtr->bottom = elemPtr->yHigh.max;
- }
- if (elemPtr->yLow.nValues > 0) {
- double top;
-
- if ((elemPtr->yLow.min <= 0.0) &&
- (elemPtr->axes.y->logScale)) {
- top = Blt_FindElemVectorMinimum(&elemPtr->yLow, DBL_MIN);
- } else {
- top = elemPtr->yLow.min;
- }
- if (top < extsPtr->top) {
- extsPtr->top = top;
- }
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TileChangedProc
- *
- * Rebuilds the designated GC with the new tile pixmap.
- *
- * Results:
- * None.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static void
-TileChangedProc(clientData, tile)
- ClientData clientData;
- Blt_Tile tile; /* Not used. */
-{
- Line *linePtr = clientData;
- Graph *graphPtr;
-
- graphPtr = linePtr->graphPtr;
- if (graphPtr->tkwin != NULL) {
- graphPtr->flags |= REDRAW_WORLD;
- Blt_EventuallyRedrawGraph(graphPtr);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ConfigureLine --
- *
- * Sets up the appropriate configuration parameters in the GC.
- * It is assumed the parameters have been previously set by
- * a call to Tk_ConfigureWidget.
- *
- * Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
- *
- * Side effects:
- * Configuration information such as line width, line style, color
- * etc. get set in a new GC.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-ConfigureLine(graphPtr, elemPtr)
- Graph *graphPtr;
- Element *elemPtr;
-{
- Line *linePtr = (Line *)elemPtr;
- unsigned long gcMask;
- XGCValues gcValues;
- GC newGC;
- Blt_ChainLink *linkPtr;
-
- if (ConfigurePen(graphPtr, (Pen *)&(linePtr->builtinPen)) != TCL_OK) {
- return TCL_ERROR;
- }
- /*
- * Point to the static normal/active pens if no external pens have
- * been selected.
- */
- if (linePtr->normalPenPtr == NULL) {
- linePtr->normalPenPtr = &(linePtr->builtinPen);
- }
- linkPtr = Blt_ChainFirstLink(linePtr->palette);
- if (linkPtr != NULL) {
- LinePenStyle *stylePtr;
-
- stylePtr = Blt_ChainGetValue(linkPtr);
- stylePtr->penPtr = linePtr->normalPenPtr;
- }
- if (linePtr->fillTile != NULL) {
- Blt_SetTileChangedProc(linePtr->fillTile, TileChangedProc, linePtr);
- }
- /*
- * Set the outline GC for this pen: GCForeground is outline color.
- * GCBackground is the fill color (only used for bitmap symbols).
- */
- gcMask = 0;
- if (linePtr->fillFgColor != NULL) {
- gcMask |= GCForeground;
- gcValues.foreground = linePtr->fillFgColor->pixel;
- }
- if (linePtr->fillBgColor != NULL) {
- gcMask |= GCBackground;
- gcValues.background = linePtr->fillBgColor->pixel;
- }
- if ((linePtr->fillStipple != None) &&
- (linePtr->fillStipple != PATTERN_SOLID)) {
- gcMask |= (GCStipple | GCFillStyle);
- gcValues.stipple = linePtr->fillStipple;
- gcValues.fill_style = (linePtr->fillBgColor == NULL)
- ? FillStippled : FillOpaqueStippled;
- }
- newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
- if (linePtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, linePtr->fillGC);
- }
- linePtr->fillGC = newGC;
-
- if (Blt_ConfigModified(linePtr->configSpecs, graphPtr->interp, "-scalesymbols",
- (char *)NULL)) {
- linePtr->flags |= (MAP_ITEM | SCALE_SYMBOL);
- }
- if (Blt_ConfigModified(linePtr->configSpecs, graphPtr->interp, "-pixels", "-trace", "-*data",
- "-smooth", "-map*", "-label", "-hide", "-x", "-y", "-areapattern",
- (char *)NULL)) {
- linePtr->flags |= MAP_ITEM;
- }
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ClosestLine --
- *
- * Find the closest point or line segment (if interpolated) to
- * the given window coordinate in the line element.
- *
- * Results:
- * Returns the distance of the closest point among other
- * information.
- *
- *----------------------------------------------------------------------
- */
-static void
-ClosestLine(graphPtr, elemPtr, searchPtr)
- Graph *graphPtr; /* Graph widget record */
- Element *elemPtr; /* Element to examine */
- ClosestSearch *searchPtr; /* Info about closest point in element */
-{
- Line *linePtr = (Line *)elemPtr;
- int mode;
-
- mode = searchPtr->mode;
- if (mode == SEARCH_AUTO) {
- LinePen *penPtr = linePtr->normalPenPtr;
-
- mode = SEARCH_POINTS;
- if ((NumberOfPoints(linePtr) > 1) && (penPtr->traceWidth > 0)) {
- mode = SEARCH_TRACES;
- }
- }
- if (mode == SEARCH_POINTS) {
- ClosestPoint(linePtr, searchPtr);
- } else {
- DistanceProc *distProc;
- int found;
-
- if (searchPtr->along == SEARCH_X) {
- distProc = DistanceToX;
- } else if (searchPtr->along == SEARCH_Y) {
- distProc = DistanceToY;
- } else {
- distProc = DistanceToLine;
- }
- if (elemPtr->classUid == bltStripElementUid) {
- found = ClosestStrip(graphPtr, linePtr, searchPtr, distProc);
- } else {
- found = ClosestTrace(graphPtr, linePtr, searchPtr, distProc);
- }
- if ((!found) && (searchPtr->along != SEARCH_BOTH)) {
- ClosestPoint(linePtr, searchPtr);
- }
- }
-}
-
-/*
- * XDrawLines() points: XMaxRequestSize(dpy) - 3
- * XFillPolygon() points: XMaxRequestSize(dpy) - 4
- * XDrawSegments() segments: (XMaxRequestSize(dpy) - 3) / 2
- * XDrawRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
- * XFillRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
- * XDrawArcs() or XFillArcs() arcs: (XMaxRequestSize(dpy) - 3) / 3
- */
-
-#define MAX_DRAWLINES(d) Blt_MaxRequestSize(d, sizeof(XPoint))
-#define MAX_DRAWPOLYGON(d) Blt_MaxRequestSize(d, sizeof(XPoint))
-#define MAX_DRAWSEGMENTS(d) Blt_MaxRequestSize(d, sizeof(XSegment))
-#define MAX_DRAWRECTANGLES(d) Blt_MaxRequestSize(d, sizeof(XRectangle))
-#define MAX_DRAWARCS(d) Blt_MaxRequestSize(d, sizeof(XArc))
-
-#ifdef WIN32
-
-static void
-DrawCircles(
- Display *display,
- Drawable drawable,
- Line *linePtr,
- LinePen *penPtr,
- int nSymbolPts,
- Point2D *symbolPts,
- int radius)
-{
- HBRUSH brush, oldBrush;
- HPEN pen, oldPen;
- HDC dc;
- TkWinDCState state;
- register Point2D *pointPtr, *endPtr;
-
- if (drawable == None) {
- return; /* Huh? */
- }
- if ((penPtr->symbol.fillGC == NULL) &&
- (penPtr->symbol.outlineWidth == 0)) {
- return;
- }
- dc = TkWinGetDrawableDC(display, drawable, &state);
- /* SetROP2(dc, tkpWinRopModes[penPtr->symbol.fillGC->function]); */
- if (penPtr->symbol.fillGC != NULL) {
- brush = CreateSolidBrush(penPtr->symbol.fillGC->foreground);
- } else {
- brush = GetStockBrush(NULL_BRUSH);
- }
- if (penPtr->symbol.outlineWidth > 0) {
- pen = Blt_GCToPen(dc, penPtr->symbol.outlineGC);
- } else {
- pen = GetStockPen(NULL_PEN);
- }
- oldPen = SelectPen(dc, pen);
- oldBrush = SelectBrush(dc, brush);
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- Ellipse(dc, (int)pointPtr->x - radius, (int)pointPtr->y - radius,
- (int)pointPtr->x + radius + 1, (int)pointPtr->y + radius + 1);
- }
- DeleteBrush(SelectBrush(dc, oldBrush));
- DeletePen(SelectPen(dc, oldPen));
- TkWinReleaseDrawableDC(drawable, dc, &state);
-}
-
-#else
-
-static void
-DrawCircles(display, drawable, linePtr, penPtr, nSymbolPts, symbolPts, radius)
- Display *display;
- Drawable drawable;
- Line *linePtr;
- LinePen *penPtr;
- int nSymbolPts;
- Point2D *symbolPts;
- int radius;
-{
- register int i;
- XArc *arcArr; /* Array of arcs (circle) */
- register XArc *arcPtr;
- int reqSize, nArcs;
- int s;
- int count;
- register Point2D *pointPtr, *endPtr;
-
- s = radius + radius;
- arcArr = Blt_Malloc(nSymbolPts * sizeof(XArc));
- arcPtr = arcArr;
-
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- arcPtr->x = (short int)pointPtr->x - radius;
- arcPtr->y = (short int)pointPtr->y - radius;
- arcPtr->width = arcPtr->height = (unsigned short)s;
- arcPtr->angle1 = 0;
- arcPtr->angle2 = 23040;
- arcPtr++, count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- arcPtr->x = (short int)pointPtr->x - radius;
- arcPtr->y = (short int)pointPtr->y - radius;
- arcPtr->width = arcPtr->height = (unsigned short)s;
- arcPtr->angle1 = 0;
- arcPtr->angle2 = 23040;
- arcPtr++;
- }
- }
- reqSize = MAX_DRAWARCS(display);
- for (i = 0; i < count; i += reqSize) {
- nArcs = ((i + reqSize) > count) ? (count - i) : reqSize;
- if (penPtr->symbol.fillGC != NULL) {
- XFillArcs(display, drawable, penPtr->symbol.fillGC, arcArr + i,
- nArcs);
- }
- if (penPtr->symbol.outlineWidth > 0) {
- XDrawArcs(display, drawable, penPtr->symbol.outlineGC, arcArr + i,
- nArcs);
- }
- }
- Blt_Free(arcArr);
-}
-
-#endif
-
-static void
-DrawSquares(display, drawable, linePtr, penPtr, nSymbolPts, symbolPts, r)
- Display *display;
- Drawable drawable;
- Line *linePtr;
- LinePen *penPtr;
- int nSymbolPts;
- register Point2D *symbolPts;
- int r;
-{
- XRectangle *rectArr;
- register Point2D *pointPtr, *endPtr;
- register XRectangle *rectPtr;
- int reqSize, nRects;
- int s;
- register int i;
- int count;
-
- s = r + r;
- rectArr = Blt_Malloc(nSymbolPts * sizeof(XRectangle));
- rectPtr = rectArr;
-
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- rectPtr->x = (short int)(pointPtr->x - r);
- rectPtr->y = (short int)(pointPtr->y - r);
- rectPtr->width = rectPtr->height = (unsigned short)s;
- rectPtr++, count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- rectPtr->x = (short int)(pointPtr->x - r);
- rectPtr->y = (short int)(pointPtr->y - r);
- rectPtr->width = rectPtr->height = (unsigned short)s;
- rectPtr++;
- }
- }
- reqSize = MAX_DRAWRECTANGLES(display);
- for (i = 0; i < count; i += reqSize) {
- nRects = ((i + reqSize) > count) ? (count - i) : reqSize;
- if (penPtr->symbol.fillGC != NULL) {
- XFillRectangles(display, drawable, penPtr->symbol.fillGC,
- rectArr + i, nRects);
- }
- if (penPtr->symbol.outlineWidth > 0) {
- XDrawRectangles(display, drawable, penPtr->symbol.outlineGC,
- rectArr + i, nRects);
- }
- }
- Blt_Free(rectArr);
-}
-
-/*
- * -----------------------------------------------------------------
- *
- * DrawSymbols --
- *
- * Draw the symbols centered at the each given x,y coordinate
- * in the array of points.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * Draws a symbol at each coordinate given. If active,
- * only those coordinates which are currently active are
- * drawn.
- *
- * -----------------------------------------------------------------
- */
-static void
-DrawSymbols(graphPtr, drawable, linePtr, penPtr, size, nSymbolPts, symbolPts)
- Graph *graphPtr; /* Graph widget record */
- Drawable drawable; /* Pixmap or window to draw into */
- Line *linePtr;
- LinePen *penPtr;
- int size; /* Size of element */
- int nSymbolPts; /* Number of coordinates in array */
- Point2D *symbolPts; /* Array of x,y coordinates for line */
-{
- XPoint pattern[13]; /* Template for polygon symbols */
- int r1, r2;
- register int i, n;
- int count;
- register Point2D *pointPtr, *endPtr;
-#define SQRT_PI 1.77245385090552
-#define S_RATIO 0.886226925452758
-
- if (size < 3) {
- if (penPtr->symbol.fillGC != NULL) {
- XPoint *points;
-
- points = Blt_Malloc(nSymbolPts * sizeof(XPoint));
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- points[count].x = (short int)pointPtr->x;
- points[count].y = (short int)pointPtr->y;
- count++;
- }
- XDrawPoints(graphPtr->display, drawable, penPtr->symbol.fillGC,
- points, nSymbolPts, CoordModeOrigin);
- Blt_Free(points);
- }
- return;
- }
- r1 = (int)ceil(size * 0.5);
- r2 = (int)ceil(size * S_RATIO * 0.5);
-
- switch (penPtr->symbol.type) {
- case SYMBOL_NONE:
- break;
-
- case SYMBOL_SQUARE:
- DrawSquares(graphPtr->display, drawable, linePtr, penPtr, nSymbolPts,
- symbolPts, r2);
- break;
-
- case SYMBOL_CIRCLE:
- DrawCircles(graphPtr->display, drawable, linePtr, penPtr, nSymbolPts,
- symbolPts, r1);
- break;
-
- case SYMBOL_SPLUS:
- case SYMBOL_SCROSS:
- {
- XSegment *segArr; /* Array of line segments (splus, scross) */
- register XSegment *segPtr;
- int reqSize, nSegs, chunk;
-
- if (penPtr->symbol.type == SYMBOL_SCROSS) {
- r2 = Round(r2 * M_SQRT1_2);
- pattern[3].y = pattern[2].x = pattern[0].x = pattern[0].y = -r2;
- pattern[3].x = pattern[2].y = pattern[1].y = pattern[1].x = r2;
- } else {
- pattern[0].y = pattern[1].y = pattern[2].x = pattern[3].x = 0;
- pattern[0].x = pattern[2].y = -r2;
- pattern[1].x = pattern[3].y = r2;
- }
- segArr = Blt_Malloc(nSymbolPts * 2 * sizeof(XSegment));
- segPtr = segArr;
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- segPtr->x1 = pattern[0].x + (short int)pointPtr->x;
- segPtr->y1 = pattern[0].y + (short int)pointPtr->y;
- segPtr->x2 = pattern[1].x + (short int)pointPtr->x;
- segPtr->y2 = pattern[1].y + (short int)pointPtr->y;
- segPtr++;
- segPtr->x1 = pattern[2].x + (short int)pointPtr->x;
- segPtr->y1 = pattern[2].y + (short int)pointPtr->y;
- segPtr->x2 = pattern[3].x + (short int)pointPtr->x;
- segPtr->y2 = pattern[3].y + (short int)pointPtr->y;
- segPtr++;
- count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- segPtr->x1 = pattern[0].x + (short int)pointPtr->x;
- segPtr->y1 = pattern[0].y + (short int)pointPtr->y;
- segPtr->x2 = pattern[1].x + (short int)pointPtr->x;
- segPtr->y2 = pattern[1].y + (short int)pointPtr->y;
- segPtr++;
- segPtr->x1 = pattern[2].x + (short int)pointPtr->x;
- segPtr->y1 = pattern[2].y + (short int)pointPtr->y;
- segPtr->x2 = pattern[3].x + (short int)pointPtr->x;
- segPtr->y2 = pattern[3].y + (short int)pointPtr->y;
- segPtr++;
- }
- }
- nSegs = count * 2;
- /* Always draw skinny symbols regardless of the outline width */
- reqSize = MAX_DRAWSEGMENTS(graphPtr->display);
- for (i = 0; i < nSegs; i += reqSize) {
- chunk = ((i + reqSize) > nSegs) ? (nSegs - i) : reqSize;
- XDrawSegments(graphPtr->display, drawable,
- penPtr->symbol.outlineGC, segArr + i, chunk);
- }
- Blt_Free(segArr);
- }
- break;
-
- case SYMBOL_PLUS:
- case SYMBOL_CROSS:
- {
- XPoint *polygon;
- register XPoint *p;
- int d; /* Small delta for cross/plus thickness */
-
- d = (r2 / 3);
-
- /*
- *
- * 2 3 The plus/cross symbol is a closed polygon
- * of 12 points. The diagram to the left
- * 0,12 1 4 5 represents the positions of the points
- * x,y which are computed below. The extra
- * 11 10 7 6 (thirteenth) point connects the first and
- * last points.
- * 9 8
- */
-
- pattern[0].x = pattern[11].x = pattern[12].x = -r2;
- pattern[2].x = pattern[1].x = pattern[10].x = pattern[9].x = -d;
- pattern[3].x = pattern[4].x = pattern[7].x = pattern[8].x = d;
- pattern[5].x = pattern[6].x = r2;
- pattern[2].y = pattern[3].y = -r2;
- pattern[0].y = pattern[1].y = pattern[4].y = pattern[5].y =
- pattern[12].y = -d;
- pattern[11].y = pattern[10].y = pattern[7].y = pattern[6].y = d;
- pattern[9].y = pattern[8].y = r2;
-
- if (penPtr->symbol.type == SYMBOL_CROSS) {
- double dx, dy;
-
- /* For the cross symbol, rotate the points by 45 degrees. */
- for (n = 0; n < 12; n++) {
- dx = (double)pattern[n].x * M_SQRT1_2;
- dy = (double)pattern[n].y * M_SQRT1_2;
- pattern[n].x = Round(dx - dy);
- pattern[n].y = Round(dx + dy);
- }
- pattern[12] = pattern[0];
- }
- polygon = Blt_Malloc(nSymbolPts * 13 * sizeof(XPoint));
- p = polygon;
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- for (n = 0; n < 13; n++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- p++;
- }
- count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- for (n = 0; n < 13; n++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- p++;
- }
- }
- }
- if (penPtr->symbol.fillGC != NULL) {
- for (p = polygon, i = 0; i < count; i++, p += 13) {
- XFillPolygon(graphPtr->display, drawable,
- penPtr->symbol.fillGC, p, 13, Complex, CoordModeOrigin);
- }
- }
- if (penPtr->symbol.outlineWidth > 0) {
- for (p = polygon, i = 0; i < count; i++, p += 13) {
- XDrawLines(graphPtr->display, drawable,
- penPtr->symbol.outlineGC, p, 13, CoordModeOrigin);
- }
- }
- Blt_Free(polygon);
- }
- break;
-
- case SYMBOL_DIAMOND:
- {
- XPoint *polygon;
- register XPoint *p;
-
- /*
- *
- * The plus symbol is a closed polygon
- * 1 of 4 points. The diagram to the left
- * represents the positions of the points
- * 0,4 x,y 2 which are computed below. The extra
- * (fifth) point connects the first and
- * 3 last points.
- *
- */
- pattern[1].y = pattern[0].x = -r1;
- pattern[2].y = pattern[3].x = pattern[0].y = pattern[1].x = 0;
- pattern[3].y = pattern[2].x = r1;
- pattern[4] = pattern[0];
-
- polygon = Blt_Malloc(nSymbolPts * 5 * sizeof(XPoint));
- p = polygon;
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- for (n = 0; n < 5; n++, p++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- }
- count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- for (n = 0; n < 5; n++, p++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- }
- }
- }
- if (penPtr->symbol.fillGC != NULL) {
- for (p = polygon, i = 0; i < count; i++, p += 5) {
- XFillPolygon(graphPtr->display, drawable,
- penPtr->symbol.fillGC, p, 5, Convex, CoordModeOrigin);
-
- }
- }
- if (penPtr->symbol.outlineWidth > 0) {
- for (p = polygon, i = 0; i < count; i++, p += 5) {
- XDrawLines(graphPtr->display, drawable,
- penPtr->symbol.outlineGC, p, 5, CoordModeOrigin);
- }
- }
- Blt_Free(polygon);
- }
- break;
-
- case SYMBOL_TRIANGLE:
- case SYMBOL_ARROW:
- {
- XPoint *polygon;
- register XPoint *p;
- double b;
- int b2, h1, h2;
-#define H_RATIO 1.1663402261671607
-#define B_RATIO 1.3467736870885982
-#define TAN30 0.57735026918962573
-#define COS30 0.86602540378443871
-
- b = Round(size * B_RATIO * 0.7);
- b2 = Round(b * 0.5);
- h2 = Round(TAN30 * b2);
- h1 = Round(b2 / COS30);
- /*
- *
- * The triangle symbol is a closed polygon
- * 0,3 of 3 points. The diagram to the left
- * represents the positions of the points
- * x,y which are computed below. The extra
- * (fourth) point connects the first and
- * 2 1 last points.
- *
- */
-
- if (penPtr->symbol.type == SYMBOL_ARROW) {
- pattern[3].x = pattern[0].x = 0;
- pattern[3].y = pattern[0].y = h1;
- pattern[1].x = b2;
- pattern[2].y = pattern[1].y = -h2;
- pattern[2].x = -b2;
- } else {
- pattern[3].x = pattern[0].x = 0;
- pattern[3].y = pattern[0].y = -h1;
- pattern[1].x = b2;
- pattern[2].y = pattern[1].y = h2;
- pattern[2].x = -b2;
- }
- polygon = Blt_Malloc(nSymbolPts * 4 * sizeof(XPoint));
- p = polygon;
- if (linePtr->symbolInterval > 0) {
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- for (n = 0; n < 4; n++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- p++;
- }
- count++;
- }
- linePtr->symbolCounter++;
- }
- } else {
- count = nSymbolPts;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- for (n = 0; n < 4; n++) {
- p->x = pattern[n].x + (short int)pointPtr->x;
- p->y = pattern[n].y + (short int)pointPtr->y;
- p++;
- }
- }
- }
- if (penPtr->symbol.fillGC != NULL) {
- for (p = polygon, i = 0; i < count; i++, p += 4) {
- XFillPolygon(graphPtr->display, drawable,
- penPtr->symbol.fillGC, p, 4, Convex, CoordModeOrigin);
- }
- }
- if (penPtr->symbol.outlineWidth > 0) {
- for (p = polygon, i = 0; i < count; i++, p += 4) {
- XDrawLines(graphPtr->display, drawable,
- penPtr->symbol.outlineGC, p, 4, CoordModeOrigin);
- }
- }
- Blt_Free(polygon);
- }
- break;
- case SYMBOL_BITMAP:
- {
- Pixmap bitmap, mask;
- int width, height, bmWidth, bmHeight;
- double scale, sx, sy;
- int dx, dy;
- register int x, y;
-
- Tk_SizeOfBitmap(graphPtr->display, penPtr->symbol.bitmap,
- &width, &height);
- mask = None;
-
- /*
- * Compute the size of the scaled bitmap. Stretch the
- * bitmap to fit a nxn bounding box.
- */
- sx = (double)size / (double)width;
- sy = (double)size / (double)height;
- scale = MIN(sx, sy);
- bmWidth = (int)(width * scale);
- bmHeight = (int)(height * scale);
-
- XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC, None);
- if (penPtr->symbol.mask != None) {
- mask = Blt_ScaleBitmap(graphPtr->tkwin, penPtr->symbol.mask,
- width, height, bmWidth, bmHeight);
- XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC,
- mask);
- }
- bitmap = Blt_ScaleBitmap(graphPtr->tkwin, penPtr->symbol.bitmap,
- width, height, bmWidth, bmHeight);
- if (penPtr->symbol.fillGC == NULL) {
- XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC,
- bitmap);
- }
- dx = bmWidth / 2;
- dy = bmHeight / 2;
- if (linePtr->symbolInterval > 0) {
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- if (DRAW_SYMBOL(linePtr)) {
- x = (int)pointPtr->x - dx;
- y = (int)pointPtr->y - dy;
- if ((penPtr->symbol.fillGC == NULL) || (mask != None)) {
- XSetClipOrigin(graphPtr->display,
- penPtr->symbol.outlineGC, x, y);
- }
- XCopyPlane(graphPtr->display, bitmap, drawable,
- penPtr->symbol.outlineGC, 0, 0, bmWidth, bmHeight,
- x, y, 1);
- }
- linePtr->symbolCounter++;
- }
- } else {
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- x = (int)pointPtr->x - dx;
- y = (int)pointPtr->y - dy;
- if ((penPtr->symbol.fillGC == NULL) || (mask != None)) {
- XSetClipOrigin(graphPtr->display,
- penPtr->symbol.outlineGC, x, y);
- }
- XCopyPlane(graphPtr->display, bitmap, drawable,
- penPtr->symbol.outlineGC, 0, 0, bmWidth, bmHeight,
- x, y, 1);
- }
- }
- Tk_FreePixmap(graphPtr->display, bitmap);
- if (mask != None) {
- Tk_FreePixmap(graphPtr->display, mask);
- }
- }
- break;
- }
-}
-
-/*
- * -----------------------------------------------------------------
- *
- * DrawSymbol --
- *
- * Draw the symbol centered at the each given x,y coordinate.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * Draws a symbol at the coordinate given.
- *
- * -----------------------------------------------------------------
- */
-static void
-DrawSymbol(graphPtr, drawable, elemPtr, x, y, size)
- Graph *graphPtr; /* Graph widget record */
- Drawable drawable; /* Pixmap or window to draw into */
- Element *elemPtr; /* Line element information */
- int x, y; /* Center position of symbol */
- int size; /* Size of symbol. */
-{
- Line *linePtr = (Line *)elemPtr;
- LinePen *penPtr = linePtr->normalPenPtr;
-
- if (penPtr->traceWidth > 0) {
- /*
- * Draw an extra line offset by one pixel from the previous to
- * give a thicker appearance. This is only for the legend
- * entry. This routine is never called for drawing the actual
- * line segments.
- */
- XDrawLine(graphPtr->display, drawable, penPtr->traceGC, x - size,
- y, x + size, y);
- XDrawLine(graphPtr->display, drawable, penPtr->traceGC, x - size,
- y + 1, x + size, y + 1);
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- Point2D point;
-
- point.x = x, point.y = y;
- DrawSymbols(graphPtr, drawable, linePtr, linePtr->normalPenPtr, size,
- 1, &point);
- }
-}
-
-#ifdef WIN32
-
-static void
-DrawTraces(
- Graph *graphPtr,
- Drawable drawable, /* Pixmap or window to draw into */
- Line *linePtr,
- LinePen *penPtr)
-{
- Blt_ChainLink *linkPtr;
- HBRUSH brush, oldBrush;
- HDC dc;
- HPEN pen, oldPen;
- POINT *points;
- TkWinDCState state;
- Trace *tracePtr;
- int j;
- int nPoints, remaining;
- register POINT *p;
- register int count;
-
- /*
- * Depending if the line is wide (> 1 pixel), arbitrarily break
- * the line in sections of 100 points. This bit of weirdness has
- * to do with wide geometric pens. The longer the polyline, the
- * slower it draws. The trade off is that we lose dash and cap
- * uniformity for unbearably slow polyline draws.
- */
- if (penPtr->traceGC->line_width > 1) {
- nPoints = 100;
- } else {
- nPoints = Blt_MaxRequestSize(graphPtr->display, sizeof(POINT)) - 1;
- }
- points = Blt_Malloc((nPoints + 1) * sizeof(POINT));
-
- dc = TkWinGetDrawableDC(graphPtr->display, drawable, &state);
-
- pen = Blt_GCToPen(dc, penPtr->traceGC);
- oldPen = SelectPen(dc, pen);
- brush = CreateSolidBrush(penPtr->traceGC->foreground);
- oldBrush = SelectBrush(dc, brush);
- SetROP2(dc, tkpWinRopModes[penPtr->traceGC->function]);
-
- for (linkPtr = Blt_ChainFirstLink(linePtr->traces); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- tracePtr = Blt_ChainGetValue(linkPtr);
-
- /*
- * If the trace has to be split into separate XDrawLines
- * calls, then the end point of the current trace is also the
- * starting point of the new split.
- */
-
- /* Step 1. Convert and draw the first section of the trace.
- * It may contain the entire trace. */
-
- for (p = points, count = 0; count < MIN(nPoints, tracePtr->nScreenPts);
- count++, p++) {
- p->x = (int)tracePtr->screenPts[count].x;
- p->y = (int)tracePtr->screenPts[count].y;
- }
- Polyline(dc, points, count);
-
- /* Step 2. Next handle any full-size chunks left. */
-
- while ((count + nPoints) < tracePtr->nScreenPts) {
- /* Start with the last point of the previous trace. */
- points[0].x = points[nPoints - 1].x;
- points[0].y = points[nPoints - 1].y;
-
- for (p = points + 1, j = 0; j < nPoints; j++, count++, p++) {
- p->x = (int)tracePtr->screenPts[count].x;
- p->y = (int)tracePtr->screenPts[count].y;
- }
- Polyline(dc, points, nPoints + 1);
- }
-
- /* Step 3. Convert and draw the remaining points. */
-
- remaining = tracePtr->nScreenPts - count;
- if (remaining > 0) {
- /* Start with the last point of the previous trace. */
- points[0].x = points[nPoints - 1].x;
- points[0].y = points[nPoints - 1].y;
-
- for (p = points + 1; count < tracePtr->nScreenPts; count++, p++) {
- p->x = (int)tracePtr->screenPts[count].x;
- p->y = (int)tracePtr->screenPts[count].y;
- }
- Polyline(dc, points, remaining + 1);
- }
- }
- Blt_Free(points);
- DeletePen(SelectPen(dc, oldPen));
- DeleteBrush(SelectBrush(dc, oldBrush));
- TkWinReleaseDrawableDC(drawable, dc, &state);
-}
-
-#else
-
-static void
-DrawTraces(graphPtr, drawable, linePtr, penPtr)
- Graph *graphPtr;
- Drawable drawable; /* Pixmap or window to draw into */
- Line *linePtr;
- LinePen *penPtr;
-{
- Blt_ChainLink *linkPtr;
- Trace *tracePtr;
- XPoint *points;
- int j;
- int nPoints, remaining;
- register XPoint *p;
- register int count;
-
- nPoints = Blt_MaxRequestSize(graphPtr->display, sizeof(XPoint)) - 1;
- points = Blt_Malloc((nPoints + 1) * sizeof(XPoint));
-
- for (linkPtr = Blt_ChainFirstLink(linePtr->traces); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- int n;
-
- tracePtr = Blt_ChainGetValue(linkPtr);
-
- /*
- * If the trace has to be split into separate XDrawLines
- * calls, then the end point of the current trace is also the
- * starting point of the new split.
- */
- /* Step 1. Convert and draw the first section of the trace.
- * It may contain the entire trace. */
-
- n = MIN(nPoints, tracePtr->nScreenPts);
- for (p = points, count = 0; count < n; count++, p++) {
- p->x = (short int)tracePtr->screenPts[count].x;
- p->y = (short int)tracePtr->screenPts[count].y;
- }
- XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
- count, CoordModeOrigin);
-
- /* Step 2. Next handle any full-size chunks left. */
-
- while ((count + nPoints) < tracePtr->nScreenPts) {
- /* Start with the last point of the previous trace. */
- points[0].x = points[nPoints - 1].x;
- points[0].y = points[nPoints - 1].y;
-
- for (p = points + 1, j = 0; j < nPoints; j++, count++, p++) {
- p->x = (short int)tracePtr->screenPts[count].x;
- p->y = (short int)tracePtr->screenPts[count].y;
- }
- XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
- nPoints + 1, CoordModeOrigin);
- }
-
- /* Step 3. Convert and draw the remaining points. */
-
- remaining = tracePtr->nScreenPts - count;
- if (remaining > 0) {
- /* Start with the last point of the previous trace. */
- points[0].x = points[nPoints - 1].x;
- points[0].y = points[nPoints - 1].y;
- for (p = points + 1; count < tracePtr->nScreenPts; count++, p++) {
- p->x = (short int)tracePtr->screenPts[count].x;
- p->y = (short int)tracePtr->screenPts[count].y;
- }
- XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
- remaining + 1, CoordModeOrigin);
- }
- }
- Blt_Free(points);
-}
-#endif /* WIN32 */
-
-static void
-DrawValues(graphPtr, drawable, linePtr, penPtr, nSymbolPts, symbolPts,
- pointToData)
- Graph *graphPtr;
- Drawable drawable;
- Line *linePtr;
- LinePen *penPtr;
- int nSymbolPts;
- Point2D *symbolPts;
- int *pointToData;
-{
- Point2D *pointPtr, *endPtr;
- int count;
- char string[TCL_DOUBLE_SPACE * 2 + 2];
- char *fmt;
- double x, y;
-
- fmt = penPtr->valueFormat;
- if (fmt == NULL) {
- fmt = "%g";
- }
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- x = linePtr->x.valueArr[pointToData[count]];
- y = linePtr->y.valueArr[pointToData[count]];
- count++;
- if (penPtr->valueShow == SHOW_X) {
- sprintf(string, fmt, x);
- } else if (penPtr->valueShow == SHOW_Y) {
- sprintf(string, fmt, y);
- } else if (penPtr->valueShow == SHOW_BOTH) {
- sprintf(string, fmt, x);
- strcat(string, ",");
- sprintf(string + strlen(string), fmt, y);
- }
- Blt_DrawText(graphPtr->tkwin, drawable, string, &(penPtr->valueStyle),
- (int)pointPtr->x, (int)pointPtr->y);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawActiveLine --
- *
- * Draws the connected line(s) representing the element. If the
- * line is made up of non-line symbols and the line width
- * parameter has been set (linewidth > 0), the element will also
- * be drawn as a line (with the linewidth requested). The line
- * may consist of separate line segments.
- *
- * Results:
- * None.
- *
- * Side effects:
- * X drawing commands are output.
- *
- *----------------------------------------------------------------------
- */
-static void
-DrawActiveLine(graphPtr, drawable, elemPtr)
- Graph *graphPtr; /* Graph widget record */
- Drawable drawable; /* Pixmap or window to draw into */
- Element *elemPtr; /* Element to be drawn */
-{
- Line *linePtr = (Line *)elemPtr;
- LinePen *penPtr = linePtr->activePenPtr;
- int symbolSize;
-
- if (penPtr == NULL) {
- return;
- }
- symbolSize = ScaleSymbol(elemPtr, linePtr->activePenPtr->symbol.size);
-
- /*
- * nActiveIndices
- * > 0 Some points are active. Uses activeArr.
- * < 0 All points are active.
- * == 0 No points are active.
- */
- if (linePtr->nActiveIndices > 0) {
- if (linePtr->flags & ACTIVE_PENDING) {
- MapActiveSymbols(graphPtr, linePtr);
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- DrawSymbols(graphPtr, drawable, linePtr, penPtr, symbolSize,
- linePtr->nActivePts, linePtr->activePts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- DrawValues(graphPtr, drawable, linePtr, penPtr,
- linePtr->nActivePts, linePtr->activePts,
- linePtr->activeToData);
- }
- } else if (linePtr->nActiveIndices < 0) {
- if (penPtr->traceWidth > 0) {
- if (linePtr->nStrips > 0) {
- Blt_Draw2DSegments(graphPtr->display, drawable,
- penPtr->traceGC, linePtr->strips, linePtr->nStrips);
- } else if (Blt_ChainGetLength(linePtr->traces) > 0) {
- DrawTraces(graphPtr, drawable, linePtr, penPtr);
- }
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- DrawSymbols(graphPtr, drawable, linePtr, penPtr, symbolSize,
- linePtr->nSymbolPts, linePtr->symbolPts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- DrawValues(graphPtr, drawable, linePtr, penPtr,
- linePtr->nSymbolPts, linePtr->symbolPts,
- linePtr->symbolToData);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DrawNormalLine --
- *
- * Draws the connected line(s) representing the element. If the
- * line is made up of non-line symbols and the line width parameter
- * has been set (linewidth > 0), the element will also be drawn as
- * a line (with the linewidth requested). The line may consist of
- * separate line segments.
- *
- * Results:
- * None.
- *
- * Side effects:
- * X drawing commands are output.
- *
- *----------------------------------------------------------------------
- */
-static void
-DrawNormalLine(graphPtr, drawable, elemPtr)
- Graph *graphPtr; /* Graph widget record */
- Drawable drawable; /* Pixmap or window to draw into */
- Element *elemPtr; /* Element to be drawn */
-{
- Line *linePtr = (Line *)elemPtr;
- LinePen *penPtr;
- Blt_ChainLink *linkPtr;
- register LinePenStyle *stylePtr;
- unsigned int count;
-
- /* Fill area under the curve */
- if (linePtr->fillPts != NULL) {
- XPoint *points;
- Point2D *endPtr, *pointPtr;
-
- points = Blt_Malloc(sizeof(XPoint) * linePtr->nFillPts);
- count = 0;
- for(pointPtr = linePtr->fillPts,
- endPtr = linePtr->fillPts + linePtr->nFillPts;
- pointPtr < endPtr; pointPtr++) {
- points[count].x = (short int)pointPtr->x;
- points[count].y = (short int)pointPtr->y;
- count++;
- }
- if (Blt_HasTile(linePtr->fillTile)) {
- Blt_SetTileOrigin(graphPtr->tkwin, linePtr->fillTile, 0, 0);
- Blt_TilePolygon(graphPtr->tkwin, drawable, linePtr->fillTile,
- points, linePtr->nFillPts);
- } else if (linePtr->fillStipple != None) {
- XFillPolygon(graphPtr->display, drawable, linePtr->fillGC,
- points, linePtr->nFillPts, Complex, CoordModeOrigin);
- }
- Blt_Free(points);
- }
-
- /* Lines: stripchart segments or graph traces. */
-
- if (linePtr->nStrips > 0) {
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- penPtr = stylePtr->penPtr;
- if ((stylePtr->nStrips > 0) && (penPtr->traceWidth > 0)) {
- Blt_Draw2DSegments(graphPtr->display, drawable,
- penPtr->traceGC, stylePtr->strips, stylePtr->nStrips);
- }
- }
- } else if ((Blt_ChainGetLength(linePtr->traces) > 0) &&
- (linePtr->normalPenPtr->traceWidth > 0)) {
- DrawTraces(graphPtr, drawable, linePtr, linePtr->normalPenPtr);
- }
-
- if (linePtr->reqMaxSymbols > 0) {
- int total;
-
- total = 0;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- total += stylePtr->nSymbolPts;
- }
- linePtr->symbolInterval = total / linePtr->reqMaxSymbols;
- linePtr->symbolCounter = 0;
- }
-
- /* Symbols, error bars, values. */
-
- count = 0;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- penPtr = stylePtr->penPtr;
- if ((stylePtr->xErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_X)) {
- Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
- stylePtr->xErrorBars, stylePtr->xErrorBarCnt);
- }
- if ((stylePtr->yErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_Y)) {
- Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
- stylePtr->yErrorBars, stylePtr->yErrorBarCnt);
- }
- if ((stylePtr->nSymbolPts > 0) &&
- (penPtr->symbol.type != SYMBOL_NONE)) {
- DrawSymbols(graphPtr, drawable, linePtr, penPtr,
- stylePtr->symbolSize, stylePtr->nSymbolPts,
- stylePtr->symbolPts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- DrawValues(graphPtr, drawable, linePtr, penPtr,
- stylePtr->nSymbolPts, stylePtr->symbolPts,
- linePtr->symbolToData + count);
- }
- count += stylePtr->nSymbolPts;
- }
- linePtr->symbolInterval = 0;
-}
-
-/*
- * -----------------------------------------------------------------
- *
- * GetSymbolPostScriptInfo --
- *
- * Set up the PostScript environment with the macros and
- * attributes needed to draw the symbols of the element.
- *
- * Results:
- * None.
- *
- * -----------------------------------------------------------------
- */
-static void
-GetSymbolPostScriptInfo(graphPtr, psToken, penPtr, size)
- Graph *graphPtr;
- PsToken psToken;
- LinePen *penPtr;
- int size;
-{
- XColor *outlineColor, *fillColor, *defaultColor;
-
- /* Set line and foreground attributes */
- outlineColor = penPtr->symbol.outlineColor;
- fillColor = penPtr->symbol.fillColor;
- defaultColor = penPtr->traceColor;
-
- if (fillColor == COLOR_DEFAULT) {
- fillColor = defaultColor;
- }
- if (outlineColor == COLOR_DEFAULT) {
- outlineColor = defaultColor;
- }
- if (penPtr->symbol.type == SYMBOL_NONE) {
- Blt_LineAttributesToPostScript(psToken, defaultColor,
- penPtr->traceWidth + 2, &(penPtr->traceDashes),
- CapButt, JoinMiter);
- } else {
- Blt_LineWidthToPostScript(psToken, penPtr->symbol.outlineWidth);
- Blt_LineDashesToPostScript(psToken, (Blt_Dashes *)NULL);
- }
-
- /*
- * Build a PostScript procedure to draw the symbols. For bitmaps,
- * paint both the bitmap and its mask. Otherwise fill and stroke
- * the path formed already.
- */
- Blt_AppendToPostScript(psToken, "\n/DrawSymbolProc {\n", (char *)NULL);
- switch (penPtr->symbol.type) {
- case SYMBOL_NONE:
- break; /* Do nothing */
- case SYMBOL_BITMAP:
- {
- int width, height;
- double sx, sy, scale;
-
- /*
- * Compute how much to scale the bitmap. Don't let the
- * scaled bitmap exceed the bounding square for the
- * symbol.
- */
- Tk_SizeOfBitmap(graphPtr->display, penPtr->symbol.bitmap,
- &width, &height);
- sx = (double)size / (double)width;
- sy = (double)size / (double)height;
- scale = MIN(sx, sy);
-
- if ((penPtr->symbol.mask != None) && (fillColor != NULL)) {
- Blt_AppendToPostScript(psToken,
- "\n % Bitmap mask is \"",
- Tk_NameOfBitmap(graphPtr->display, penPtr->symbol.mask),
- "\"\n\n ", (char *)NULL);
- Blt_BackgroundToPostScript(psToken, fillColor);
- Blt_BitmapToPostScript(psToken, graphPtr->display,
- penPtr->symbol.mask, scale, scale);
- }
- Blt_AppendToPostScript(psToken,
- "\n % Bitmap symbol is \"",
- Tk_NameOfBitmap(graphPtr->display, penPtr->symbol.bitmap),
- "\"\n\n ", (char *)NULL);
- Blt_ForegroundToPostScript(psToken, outlineColor);
- Blt_BitmapToPostScript(psToken, graphPtr->display,
- penPtr->symbol.bitmap, scale, scale);
- }
- break;
- default:
- if (fillColor != NULL) {
- Blt_AppendToPostScript(psToken, " ", (char *)NULL);
- Blt_BackgroundToPostScript(psToken, fillColor);
- Blt_AppendToPostScript(psToken, " Fill\n", (char *)NULL);
- }
- if ((outlineColor != NULL) && (penPtr->symbol.outlineWidth > 0)) {
- Blt_AppendToPostScript(psToken, " ", (char *)NULL);
- Blt_ForegroundToPostScript(psToken, outlineColor);
- Blt_AppendToPostScript(psToken, " stroke\n", (char *)NULL);
- }
- break;
- }
- Blt_AppendToPostScript(psToken, "} def\n\n", (char *)NULL);
-}
-
-/*
- * -----------------------------------------------------------------
- *
- * SymbolsToPostScript --
- *
- * Draw a symbol centered at the given x,y window coordinate
- * based upon the element symbol type and size.
- *
- * Results:
- * None.
- *
- * Problems:
- * Most notable is the round-off errors generated when
- * calculating the centered position of the symbol.
- *
- * -----------------------------------------------------------------
- */
-static void
-SymbolsToPostScript(graphPtr, psToken, penPtr, size, nSymbolPts, symbolPts)
- Graph *graphPtr;
- PsToken psToken;
- LinePen *penPtr;
- int size;
- int nSymbolPts;
- Point2D *symbolPts;
-{
- double symbolSize;
- register Point2D *pointPtr, *endPtr;
- static char *symbolMacros[] =
- {
- "Li", "Sq", "Ci", "Di", "Pl", "Cr", "Sp", "Sc", "Tr", "Ar", "Bm",
- (char *)NULL,
- };
- GetSymbolPostScriptInfo(graphPtr, psToken, penPtr, size);
-
- symbolSize = (double)size;
- switch (penPtr->symbol.type) {
- case SYMBOL_SQUARE:
- case SYMBOL_CROSS:
- case SYMBOL_PLUS:
- case SYMBOL_SCROSS:
- case SYMBOL_SPLUS:
- symbolSize = (double)Round(size * S_RATIO);
- break;
- case SYMBOL_TRIANGLE:
- case SYMBOL_ARROW:
- symbolSize = (double)Round(size * 0.7);
- break;
- case SYMBOL_DIAMOND:
- symbolSize = (double)Round(size * M_SQRT1_2);
- break;
-
- default:
- break;
- }
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- Blt_FormatToPostScript(psToken, "%g %g %g %s\n", pointPtr->x,
- pointPtr->y, symbolSize, symbolMacros[penPtr->symbol.type]);
- }
-}
-
-/*
- * -----------------------------------------------------------------
- *
- * SymbolToPostScript --
- *
- * Draw the symbol centered at the each given x,y coordinate.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * Draws a symbol at the coordinate given.
- *
- * -----------------------------------------------------------------
- */
-static void
-SymbolToPostScript(graphPtr, psToken, elemPtr, x, y, size)
- Graph *graphPtr; /* Graph widget record */
- PsToken psToken;
- Element *elemPtr; /* Line element information */
- double x, y; /* Center position of symbol */
- int size; /* Size of element */
-{
- Line *linePtr = (Line *)elemPtr;
- LinePen *penPtr = linePtr->normalPenPtr;
-
- if (penPtr->traceWidth > 0) {
- /*
- * Draw an extra line offset by one pixel from the previous to
- * give a thicker appearance. This is only for the legend
- * entry. This routine is never called for drawing the actual
- * line segments.
- */
- Blt_LineAttributesToPostScript(psToken, penPtr->traceColor,
- penPtr->traceWidth + 2, &(penPtr->traceDashes), CapButt, JoinMiter);
- Blt_FormatToPostScript(psToken, "%g %g %d Li\n", x, y, size + size);
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- Point2D point;
-
- point.x = x, point.y = y;
- SymbolsToPostScript(graphPtr, psToken, penPtr, size, 1, &point);
- }
-}
-
-static void
-SetLineAttributes(psToken, penPtr)
- PsToken psToken;
- LinePen *penPtr;
-{
- /* Set the attributes of the line (color, dashes, linewidth) */
- Blt_LineAttributesToPostScript(psToken, penPtr->traceColor,
- penPtr->traceWidth, &(penPtr->traceDashes), CapButt, JoinMiter);
- if ((LineIsDashed(penPtr->traceDashes)) &&
- (penPtr->traceOffColor != NULL)) {
- Blt_AppendToPostScript(psToken, "/DashesProc {\n gsave\n ",
- (char *)NULL);
- Blt_BackgroundToPostScript(psToken, penPtr->traceOffColor);
- Blt_AppendToPostScript(psToken, " ", (char *)NULL);
- Blt_LineDashesToPostScript(psToken, (Blt_Dashes *)NULL);
- Blt_AppendToPostScript(psToken, "stroke\n grestore\n} def\n",
- (char *)NULL);
- } else {
- Blt_AppendToPostScript(psToken, "/DashesProc {} def\n", (char *)NULL);
- }
-}
-
-static void
-TracesToPostScript(psToken, linePtr, penPtr)
- PsToken psToken;
- Line *linePtr;
- LinePen *penPtr;
-{
- Blt_ChainLink *linkPtr;
- Trace *tracePtr;
- register Point2D *pointPtr, *endPtr;
- int count;
-
- SetLineAttributes(psToken, penPtr);
- for (linkPtr = Blt_ChainFirstLink(linePtr->traces); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- tracePtr = Blt_ChainGetValue(linkPtr);
- if (tracePtr->nScreenPts <= 0) {
- continue;
- }
-#define PS_MAXPATH 1500 /* Maximum number of components in a PostScript
- * (level 1) path. */
- pointPtr = tracePtr->screenPts;
- Blt_FormatToPostScript(psToken, " newpath %g %g moveto\n",
- pointPtr->x,
- pointPtr->y);
- pointPtr++;
- count = 0;
- for (endPtr = tracePtr->screenPts + (tracePtr->nScreenPts - 1);
- pointPtr < endPtr; pointPtr++) {
- Blt_FormatToPostScript(psToken, " %g %g lineto\n",
- pointPtr->x,
- pointPtr->y);
- if ((count % PS_MAXPATH) == 0) {
- Blt_FormatToPostScript(psToken,
- "DashesProc stroke\n newpath %g %g moveto\n",
- pointPtr->x,
- pointPtr->y);
- }
- count++;
- }
- Blt_FormatToPostScript(psToken, " %g %g lineto\n",
- pointPtr->x,
- pointPtr->y);
- Blt_AppendToPostScript(psToken, "DashesProc stroke\n", (char *)NULL);
- }
-}
-
-
-static void
-ValuesToPostScript(psToken, linePtr, penPtr, nSymbolPts, symbolPts,
- pointToData)
- PsToken psToken;
- Line *linePtr;
- LinePen *penPtr;
- int nSymbolPts;
- Point2D *symbolPts;
- int *pointToData;
-{
- Point2D *pointPtr, *endPtr;
- int count;
- char string[TCL_DOUBLE_SPACE * 2 + 2];
- char *fmt;
- double x, y;
-
- fmt = penPtr->valueFormat;
- if (fmt == NULL) {
- fmt = "%g";
- }
- count = 0;
- for (pointPtr = symbolPts, endPtr = symbolPts + nSymbolPts;
- pointPtr < endPtr; pointPtr++) {
- x = linePtr->x.valueArr[pointToData[count]];
- y = linePtr->y.valueArr[pointToData[count]];
- count++;
- if (penPtr->valueShow == SHOW_X) {
- sprintf(string, fmt, x);
- } else if (penPtr->valueShow == SHOW_Y) {
- sprintf(string, fmt, y);
- } else if (penPtr->valueShow == SHOW_BOTH) {
- sprintf(string, fmt, x);
- strcat(string, ",");
- sprintf(string + strlen(string), fmt, y);
- }
- Blt_TextToPostScript(psToken, string, &(penPtr->valueStyle),
- pointPtr->x, pointPtr->y);
- }
-}
-
-
-/*
- *----------------------------------------------------------------------
- *
- * ActiveLineToPostScript --
- *
- * Generates PostScript commands to draw as "active" the points
- * (symbols) and or line segments (trace) representing the
- * element.
- *
- * Results:
- * None.
- *
- * Side effects:
- * PostScript pen width, dashes, and color settings are changed.
- *
- *----------------------------------------------------------------------
- */
-static void
-ActiveLineToPostScript(graphPtr, psToken, elemPtr)
- Graph *graphPtr;
- PsToken psToken;
- Element *elemPtr;
-{
- Line *linePtr = (Line *)elemPtr;
- LinePen *penPtr = linePtr->activePenPtr;
- int symbolSize;
-
- if (penPtr == NULL) {
- return;
- }
- symbolSize = ScaleSymbol(elemPtr, penPtr->symbol.size);
- if (linePtr->nActiveIndices > 0) {
- if (linePtr->flags & ACTIVE_PENDING) {
- MapActiveSymbols(graphPtr, linePtr);
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- SymbolsToPostScript(graphPtr, psToken, penPtr, symbolSize,
- linePtr->nActivePts, linePtr->activePts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- ValuesToPostScript(psToken, linePtr, penPtr, linePtr->nActivePts,
- linePtr->activePts, linePtr->activeToData);
- }
- } else if (linePtr->nActiveIndices < 0) {
- if (penPtr->traceWidth > 0) {
- if (linePtr->nStrips > 0) {
- SetLineAttributes(psToken, penPtr);
- Blt_2DSegmentsToPostScript(psToken, linePtr->strips,
- linePtr->nStrips);
- }
- if (Blt_ChainGetLength(linePtr->traces) > 0) {
- TracesToPostScript(psToken, linePtr, (LinePen *)penPtr);
- }
- }
- if (penPtr->symbol.type != SYMBOL_NONE) {
- SymbolsToPostScript(graphPtr, psToken, penPtr, symbolSize,
- linePtr->nSymbolPts, linePtr->symbolPts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- ValuesToPostScript(psToken, linePtr, penPtr, linePtr->nSymbolPts,
- linePtr->symbolPts, linePtr->symbolToData);
- }
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * NormalLineToPostScript --
- *
- * Similar to the DrawLine procedure, prints PostScript related
- * commands to form the connected line(s) representing the element.
- *
- * Results:
- * None.
- *
- * Side effects:
- * PostScript pen width, dashes, and color settings are changed.
- *
- *----------------------------------------------------------------------
- */
-static void
-NormalLineToPostScript(graphPtr, psToken, elemPtr)
- Graph *graphPtr;
- PsToken psToken;
- Element *elemPtr;
-{
- Line *linePtr = (Line *)elemPtr;
- register LinePenStyle *stylePtr;
- Blt_ChainLink *linkPtr;
- LinePen *penPtr;
- unsigned int count;
- XColor *colorPtr;
-
- /* Draw fill area */
- if (linePtr->fillPts != NULL) {
- /* Create a path to use for both the polygon and its outline. */
- Blt_PathToPostScript(psToken, linePtr->fillPts, linePtr->nFillPts);
- Blt_AppendToPostScript(psToken, "closepath\n", (char *)NULL);
-
- /* If the background fill color was specified, draw the
- * polygon in a solid fashion with that color. */
- if (linePtr->fillBgColor != NULL) {
- Blt_BackgroundToPostScript(psToken, linePtr->fillBgColor);
- Blt_AppendToPostScript(psToken, "Fill\n", (char *)NULL);
- }
- Blt_ForegroundToPostScript(psToken, linePtr->fillFgColor);
- if (Blt_HasTile(linePtr->fillTile)) {
- /* TBA: Transparent tiling is the hard part. */
- } else if ((linePtr->fillStipple != None) &&
- (linePtr->fillStipple != PATTERN_SOLID)) {
- /* Draw the stipple in the foreground color. */
- Blt_StippleToPostScript(psToken, graphPtr->display,
- linePtr->fillStipple);
- } else {
- Blt_AppendToPostScript(psToken, "Fill\n", (char *)NULL);
- }
- }
- /* Draw lines */
- if (linePtr->nStrips > 0) {
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- penPtr = stylePtr->penPtr;
- if ((stylePtr->nStrips > 0) && (penPtr->traceWidth > 0)) {
- SetLineAttributes(psToken, penPtr);
- Blt_2DSegmentsToPostScript(psToken, stylePtr->strips,
- stylePtr->nStrips);
- }
- }
- } else if ((Blt_ChainGetLength(linePtr->traces) > 0) &&
- (linePtr->normalPenPtr->traceWidth > 0)) {
- TracesToPostScript(psToken, linePtr, linePtr->normalPenPtr);
- }
-
- /* Draw symbols, error bars, values. */
-
- count = 0;
- for (linkPtr = Blt_ChainFirstLink(linePtr->palette); linkPtr != NULL;
- linkPtr = Blt_ChainNextLink(linkPtr)) {
- stylePtr = Blt_ChainGetValue(linkPtr);
- penPtr = stylePtr->penPtr;
- colorPtr = penPtr->errorBarColor;
- if (colorPtr == COLOR_DEFAULT) {
- colorPtr = penPtr->traceColor;
- }
- if ((stylePtr->xErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_X)) {
- Blt_LineAttributesToPostScript(psToken, colorPtr,
- penPtr->errorBarLineWidth, NULL, CapButt, JoinMiter);
- Blt_2DSegmentsToPostScript(psToken, stylePtr->xErrorBars,
- stylePtr->xErrorBarCnt);
- }
- if ((stylePtr->yErrorBarCnt > 0) && (penPtr->errorBarShow & SHOW_Y)) {
- Blt_LineAttributesToPostScript(psToken, colorPtr,
- penPtr->errorBarLineWidth, NULL, CapButt, JoinMiter);
- Blt_2DSegmentsToPostScript(psToken, stylePtr->yErrorBars,
- stylePtr->yErrorBarCnt);
- }
- if ((stylePtr->nSymbolPts > 0) &&
- (stylePtr->penPtr->symbol.type != SYMBOL_NONE)) {
- SymbolsToPostScript(graphPtr, psToken, penPtr,
- stylePtr->symbolSize, stylePtr->nSymbolPts,
- stylePtr->symbolPts);
- }
- if (penPtr->valueShow != SHOW_NONE) {
- ValuesToPostScript(psToken, linePtr, penPtr,
- stylePtr->nSymbolPts, stylePtr->symbolPts,
- linePtr->symbolToData + count);
- }
- count += stylePtr->nSymbolPts;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * DestroyLine --
- *
- * Release memory and resources allocated for the line element.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Everything associated with the line element is freed up.
- *
- *----------------------------------------------------------------------
- */
-#define FreeVector(v) \
- if ((v).clientId != NULL) { \
- Blt_FreeVectorId((v).clientId); \
- } else if ((v).valueArr != NULL) { \
- Blt_Free((v).valueArr); \
- }
-
-static void
-DestroyLine(graphPtr, elemPtr)
- Graph *graphPtr;
- Element *elemPtr;
-{
- Line *linePtr = (Line *)elemPtr;
-
- if (linePtr->normalPenPtr != &(linePtr->builtinPen)) {
- Blt_FreePen(graphPtr, (Pen *)linePtr->normalPenPtr);
- }
- DestroyPen(graphPtr, (Pen *)&(linePtr->builtinPen));
- if (linePtr->activePenPtr != NULL) {
- Blt_FreePen(graphPtr, (Pen *)linePtr->activePenPtr);
- }
-
- FreeVector(linePtr->w);
- FreeVector(linePtr->x);
- FreeVector(linePtr->xHigh);
- FreeVector(linePtr->xLow);
- FreeVector(linePtr->xError);
- FreeVector(linePtr->y);
- FreeVector(linePtr->yHigh);
- FreeVector(linePtr->yLow);
- FreeVector(linePtr->yError);
-
- ResetLine(linePtr);
- if (linePtr->palette != NULL) {
- Blt_FreePalette(graphPtr, linePtr->palette);
- Blt_ChainDestroy(linePtr->palette);
- }
- if (linePtr->tags != NULL) {
- Blt_Free(linePtr->tags);
- }
- if (linePtr->activeIndices != NULL) {
- Blt_Free(linePtr->activeIndices);
- }
- if (linePtr->fillPts != NULL) {
- Blt_Free(linePtr->fillPts);
- }
- if (linePtr->fillTile != NULL) {
- Blt_FreeTile(linePtr->fillTile);
- }
- if ((linePtr->fillStipple != None) &&
- (linePtr->fillStipple != PATTERN_SOLID)) {
- Tk_FreeBitmap(graphPtr->display, linePtr->fillStipple);
- }
- if (linePtr->fillGC != NULL) {
- Tk_FreeGC(graphPtr->display, linePtr->fillGC);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Blt_LineElement --
- *
- * Allocate memory and initialize methods for the new line element.
- *
- * Results:
- * The pointer to the newly allocated element structure is returned.
- *
- * Side effects:
- * Memory is allocated for the line element structure.
- *
- *----------------------------------------------------------------------
- */
-
-static ElementProcs lineProcs =
-{
- ClosestLine, /* Finds the closest element/data point */
- ConfigureLine, /* Configures the element. */
- DestroyLine, /* Destroys the element. */
- DrawActiveLine, /* Draws active element */
- DrawNormalLine, /* Draws normal element */
- DrawSymbol, /* Draws the element symbol. */
- GetLineExtents, /* Find the extents of the element's data. */
- ActiveLineToPostScript, /* Prints active element. */
- NormalLineToPostScript, /* Prints normal element. */
- SymbolToPostScript, /* Prints the line's symbol. */
- MapLine /* Compute element's screen coordinates. */
-};
-
-Element *
-Blt_LineElement(graphPtr, name, classUid)
- Graph *graphPtr;
- char *name;
- Blt_Uid classUid;
-{
- register Line *linePtr;
-
- linePtr = Blt_Calloc(1, sizeof(Line));
- assert(linePtr);
- linePtr->procsPtr = &lineProcs;
- if (classUid == bltLineElementUid) {
- linePtr->configSpecs = lineElemConfigSpecs;
- } else {
- linePtr->configSpecs = stripElemConfigSpecs;
- }
-
- /* By default an element's name and label are the same. */
- linePtr->label = Blt_Strdup(name);
- linePtr->name = Blt_Strdup(name);
-
- linePtr->classUid = classUid;
- linePtr->flags = SCALE_SYMBOL;
- linePtr->graphPtr = graphPtr;
- linePtr->labelRelief = TK_RELIEF_FLAT;
- linePtr->normalPenPtr = &linePtr->builtinPen;
- linePtr->palette = Blt_ChainCreate();
- linePtr->penDir = PEN_BOTH_DIRECTIONS;
- linePtr->reqSmooth = PEN_SMOOTH_NONE;
- InitPen(linePtr->normalPenPtr);
- return (Element *)linePtr;
-}