1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/* This file contains the endpath() method, which is a GNU extension to
libplot. A polyline object may be constructed incrementally, by
repeated invocation of the cont() routine. (See the comments in
g_cont.c.) The construction may be terminated, and the polyline object
finalized, by an explict invocation of endpath().
If endpath() is invoked when no polyline is under construction, it has
no effect. */
#include "sys-defines.h"
#include "plot.h"
#include "extern.h"
/* xfig polyline subtypes */
#define P_OPEN 1
#define P_BOX 2
#define P_CLOSED 3
/* Fig's line styles, indexed into by internal line number
(L_SOLID/L_DOTTED/ L_DOTDASHED/L_SHORTDASHED/L_LONGDASHED. Fig format
supports only dotted lines (isolated dots, with a specified inter-dot
distance) and dashed lines (on/off dashes, the lengths of the on and off
segments being equal). We map our canonical five line types into Fig
line types as best we can. */
const int _fig_line_style[] =
{ FIG_L_SOLID, FIG_L_DOTTED, FIG_L_DOTTED, FIG_L_DASHED, FIG_L_DASHED };
/* Fig's `style value', i.e. inter-dot length or on-and-off segment length,
indexed into by internal line number (L_SOLID/L_DOTTED/
L_DOTDASHED/L_SHORTDASHED/L_LONGDASHED; dash length ignored for
L_SOLID). Units are Fig display units. */
const double _fig_dash_length[] =
{ 0.0, 2.0, 4.0, 4.0, 8.0 };
/* Fig join styles, indexed by internal join type number (miter/rd./bevel) */
const int _fig_join_style[] =
{ FIG_JOIN_MITER, FIG_JOIN_ROUND, FIG_JOIN_BEVEL };
/* Fig cap styles, indexed by internal cap type number (butt/rd./project) */
const int _fig_cap_style[] =
{ FIG_CAP_BUTT, FIG_CAP_ROUND, FIG_CAP_PROJECT };
int
#ifdef _HAVE_PROTOS
_f_endpath (void)
#else
_f_endpath ()
#endif
{
int i;
bool closed, polyline_subtype;
const char *format;
if (!_plotter->open)
{
_plotter->error ("endpath: invalid operation");
return -1;
}
/* If a circular arc has been stashed rather than drawn, force it to be
drawn by invoking farc() with the `immediate' flag set. Note that
if an arc is stashed, PointsInLine must be zero. */
if (_plotter->drawstate->arc_stashed)
{
double axc = _plotter->drawstate->axc;
double ayc = _plotter->drawstate->ayc;
double ax0 = _plotter->drawstate->ax0;
double ay0 = _plotter->drawstate->ay0;
double ax1 = _plotter->drawstate->ax1;
double ay1 = _plotter->drawstate->ay1;
_plotter->drawstate->arc_immediate = true;
_plotter->drawstate->arc_polygonal = false; /* advisory only */
_plotter->farc (axc, ayc, ax0, ay0, ax1, ay1);
_plotter->drawstate->arc_immediate = false;
_plotter->drawstate->arc_stashed = false;
}
if (_plotter->drawstate->PointsInLine == 0) /* nothing to do */
return 0;
if (_plotter->drawstate->PointsInLine == 1) /* shouldn't happen */
{
/* just reset polyline storage buffer */
free (_plotter->drawstate->datapoints);
_plotter->drawstate->datapoints_len = 0;
_plotter->drawstate->PointsInLine = 0;
return 0;
}
if ((_plotter->drawstate->PointsInLine >= 3) /* check for closure */
&& (_plotter->drawstate->datapoints[_plotter->drawstate->PointsInLine - 1].x == _plotter->drawstate->datapoints[0].x)
&& (_plotter->drawstate->datapoints[_plotter->drawstate->PointsInLine - 1].y == _plotter->drawstate->datapoints[0].y))
closed = true;
else
closed = false; /* 2-point ones should be open */
/* Special case: disconnected points, no real polyline. We switch to a
temporary datapoints buffer for this. This is a hack, needed because
the point() method calls endpath(), which would otherwise mess the
real databuffer up. */
if (!_plotter->drawstate->points_are_connected)
{
Point saved_pos;
Point *saved_datapoints = _plotter->drawstate->datapoints;
int saved_PointsInLine = _plotter->drawstate->PointsInLine;
saved_pos = _plotter->drawstate->pos;
_plotter->drawstate->datapoints = NULL;
_plotter->drawstate->datapoints_len = 0;
_plotter->drawstate->PointsInLine = 0;
_plotter->drawstate->points_are_connected = true; /* for duration */
for (i = 0; i < saved_PointsInLine - (closed ? 1 : 0); i++)
_plotter->fpoint (saved_datapoints[i].x,
saved_datapoints[i].y);
free (saved_datapoints);
_plotter->drawstate->points_are_connected = false;
_plotter->drawstate->pos = saved_pos; /* restore graphics cursor */
return 0;
}
/* general case: points are vertices of a polyline */
if (closed)
{
polyline_subtype = P_CLOSED;
format = "#POLYLINE [CLOSED]\n%d %d %d %d %d %d %d %d %d %.3f %d %d %d %d %d %d";
}
else
{
polyline_subtype = P_OPEN;
format = "#POLYLINE [OPEN]\n%d %d %d %d %d %d %d %d %d %.3f %d %d %d %d %d %d";
}
/* evaluate fig colors lazily, i.e. only when needed */
_plotter->set_pen_color();
_plotter->set_fill_color();
/* recompute xfig's `depth' attribute, and keep track of the drawing
priority of the object we're drawing */
if (_plotter->fig_last_priority >= POLYLINE_PRIORITY)
if (_plotter->fig_drawing_depth > 0)
(_plotter->fig_drawing_depth)--;
_plotter->fig_last_priority = POLYLINE_PRIORITY;
sprintf(_plotter->outbuf.current,
format,
2, /* polyline object */
polyline_subtype, /* polyline subtype */
_fig_line_style[_plotter->drawstate->line_type], /* style */
/* thickness, in Fig display units */
_plotter->drawstate->quantized_device_line_width,
_plotter->drawstate->fig_fgcolor, /* pen color */
_plotter->drawstate->fig_fillcolor, /* fill color */
_plotter->fig_drawing_depth, /* depth */
0, /* pen style, ignored */
_plotter->drawstate->fig_fill_level, /* area fill */
/* style val, in Fig display units (float) */
_fig_dash_length[_plotter->drawstate->line_type],
_fig_join_style[_plotter->drawstate->join_type], /* join style */
_fig_cap_style[_plotter->drawstate->cap_type], /* cap style */
0, /* radius (of arc boxes, ignored here) */
0, /* forward arrow */
0, /* backward arrow */
_plotter->drawstate->PointsInLine /* number of points in line */
);
_update_buffer (&_plotter->outbuf);
for (i=0; i<_plotter->drawstate->PointsInLine; i++)
{
if ((i%5) == 0)
sprintf (_plotter->outbuf.current, "\n\t"); /* make human-readable */
else
sprintf (_plotter->outbuf.current, " ");
_update_buffer (&_plotter->outbuf);
sprintf (_plotter->outbuf.current,
"%d %d",
IROUND(XD((_plotter->drawstate->datapoints)[i].x,
(_plotter->drawstate->datapoints)[i].y)),
IROUND(YD((_plotter->drawstate->datapoints)[i].x,
(_plotter->drawstate->datapoints)[i].y)));
_update_buffer (&_plotter->outbuf);
}
sprintf (_plotter->outbuf.current, "\n");
_update_buffer (&_plotter->outbuf);
/* reset polyline storage buffer */
free (_plotter->drawstate->datapoints);
_plotter->drawstate->datapoints_len = 0;
_plotter->drawstate->PointsInLine = 0;
return 0;
}
|