1
/* This file is part of the GNU plotutils package. Copyright (C) 1995,
2
1996, 1997, 1998, 1999, 2000, 2005, Free Software Foundation, Inc.
4
The GNU plotutils package is free software. You may redistribute it
5
and/or modify it under the terms of the GNU General Public License as
6
published by the Free Software foundation; either version 2, or (at your
7
option) any later version.
9
The GNU plotutils package is distributed in the hope that it will be
10
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
General Public License for more details.
14
You should have received a copy of the GNU General Public License along
15
with the GNU plotutils package; see the file COPYING. If not, write to
16
the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17
Boston, MA 02110-1301, USA. */
1
19
/* This file contains the internal paint_path() and paint_paths() methods,
2
20
which the public method endpath() is a wrapper around. */
11
29
/* SVG join styles, i.e., stroke-linejoin attribute, indexed by internal
12
30
number (miter/rd./bevel/triangular) */
13
static const char * _svg_join_style[] =
31
static const char * const svg_join_style[PL_NUM_JOIN_TYPES] =
14
32
{ "miter", "round", "bevel", "round" };
16
34
/* SVG cap styles, i.e., stroke-linecap attribute, indexed by internal
17
35
number (butt/rd./project/triangular) */
18
static const char * _svg_cap_style[] =
36
static const char * const svg_cap_style[PL_NUM_CAP_TYPES] =
19
37
{ "butt", "round", "square", "round" };
21
39
/* SVG fill rule styles, i.e., fill-rule attribute, indexed by internal
22
40
number (even-odd/nonzero winding number) */
23
static const char * _svg_fill_style[] =
41
static const char * const svg_fill_style[PL_NUM_FILL_RULES] =
24
42
{ "evenodd", "nonzero" };
26
static const double _identity_matrix[6] = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
44
static const double identity_matrix[6] = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
28
46
/* forward references */
29
static void _write_svg_path_data ____P((plOutbuf *page, const plPath *path));
30
static void _write_svg_path_style ____P((plOutbuf *page, const plDrawState *drawstate, bool need_cap, bool need_join));
47
static void write_svg_path_data (plOutbuf *page, const plPath *path);
48
static void write_svg_path_style (plOutbuf *page, const plDrawState *drawstate, bool need_cap, bool need_join);
34
_s_paint_path (S___(Plotter *_plotter))
36
_s_paint_path (S___(_plotter))
37
S___(Plotter *_plotter;)
51
_pl_s_paint_path (S___(Plotter *_plotter))
40
53
switch ((int)_plotter->drawstate->path->type)
79
92
sprintf (_plotter->data->page->point, "<line ");
80
93
_update_buffer (_plotter->data->page);
82
_s_set_matrix (R___(_plotter)
83
_plotter->drawstate->transform.m_user_to_ndc,
95
_pl_s_set_matrix (R___(_plotter) identity_matrix);
86
97
sprintf (_plotter->data->page->point,
87
98
"x1=\"%.5g\" y1=\"%.5g\" x2=\"%.5g\" y2=\"%.5g\" ",
91
102
_plotter->drawstate->path->segments[1].p.y);
92
103
_update_buffer (_plotter->data->page);
94
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
105
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
97
108
sprintf (_plotter->data->page->point, "/>\n");
104
115
sprintf (_plotter->data->page->point, "<polyline ");
105
116
_update_buffer (_plotter->data->page);
107
_s_set_matrix (R___(_plotter)
108
_plotter->drawstate->transform.m_user_to_ndc,
118
_pl_s_set_matrix (R___(_plotter) identity_matrix);
111
120
sprintf (_plotter->data->page->point,
126
135
_update_buffer (_plotter->data->page);
128
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
137
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
131
140
sprintf (_plotter->data->page->point,
139
148
sprintf (_plotter->data->page->point, "<polygon ");
140
149
_update_buffer (_plotter->data->page);
142
_s_set_matrix (R___(_plotter)
143
_plotter->drawstate->transform.m_user_to_ndc,
151
_pl_s_set_matrix (R___(_plotter) identity_matrix);
146
153
sprintf (_plotter->data->page->point,
161
168
_update_buffer (_plotter->data->page);
163
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
170
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
166
173
sprintf (_plotter->data->page->point,
174
181
sprintf (_plotter->data->page->point, "<path ");
175
182
_update_buffer (_plotter->data->page);
177
_s_set_matrix (R___(_plotter)
178
_plotter->drawstate->transform.m_user_to_ndc,
184
_pl_s_set_matrix (R___(_plotter) identity_matrix);
181
186
sprintf (_plotter->data->page->point,
183
188
_update_buffer (_plotter->data->page);
185
190
/* write SVG path data string */
186
_write_svg_path_data (_plotter->data->page,
191
write_svg_path_data (_plotter->data->page,
187
192
_plotter->drawstate->path);
189
194
sprintf (_plotter->data->page->point,
191
196
_update_buffer (_plotter->data->page);
193
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
198
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
196
201
sprintf (_plotter->data->page->point,
215
220
sprintf (_plotter->data->page->point, "<rect ");
216
221
_update_buffer (_plotter->data->page);
218
_s_set_matrix (R___(_plotter)
219
_plotter->drawstate->transform.m_user_to_ndc,
223
_pl_s_set_matrix (R___(_plotter) identity_matrix);
222
225
sprintf (_plotter->data->page->point,
223
226
"x=\"%.5g\" y=\"%.5g\" width=\"%.5g\" height=\"%.5g\" ",
224
227
xmin, ymin, xmax - xmin, ymax - ymin);
225
228
_update_buffer (_plotter->data->page);
227
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
230
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
229
232
sprintf (_plotter->data->page->point,
240
243
sprintf (_plotter->data->page->point, "<circle ");
241
244
_update_buffer (_plotter->data->page);
243
_s_set_matrix (R___(_plotter)
244
_plotter->drawstate->transform.m_user_to_ndc,
246
_pl_s_set_matrix (R___(_plotter) identity_matrix);
247
248
pc = _plotter->drawstate->path->pc;
248
249
sprintf (_plotter->data->page->point,
250
251
pc.x, pc.y, radius);
251
252
_update_buffer (_plotter->data->page);
253
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
254
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
256
257
sprintf (_plotter->data->page->point,
277
278
local_matrix[3] = cos (M_PI * angle / 180.0);
278
279
local_matrix[4] = pc.x;
279
280
local_matrix[5] = pc.y;
280
_s_set_matrix (R___(_plotter)
281
_plotter->drawstate->transform.m_user_to_ndc,
281
_pl_s_set_matrix (R___(_plotter) local_matrix);
284
283
sprintf (_plotter->data->page->point, "rx=\"%.5g\" ry=\"%.5g\" ",
286
285
_update_buffer (_plotter->data->page);
288
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
287
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
291
290
sprintf (_plotter->data->page->point, "/>\n");
313
307
_update_buffer (_plotter->data->page);
315
_s_set_matrix (R___(_plotter)
316
_plotter->drawstate->transform.m_user_to_ndc,
309
_pl_s_set_matrix (R___(_plotter) identity_matrix);
319
311
sprintf (_plotter->data->page->point,
453
445
_update_buffer (_plotter->data->page);
455
_write_svg_path_style (_plotter->data->page, _plotter->drawstate,
447
write_svg_path_style (_plotter->data->page, _plotter->drawstate,
458
450
sprintf (_plotter->data->page->point,
467
459
that consists of a single closed path primitive (box/circle/ellipse). */
471
_write_svg_path_data (plOutbuf *page, const plPath *path)
473
_write_svg_path_data (page, path)
462
write_svg_path_data (plOutbuf *page, const plPath *path)
479
465
plPoint p, oldpoint;
627
_write_svg_path_style (plOutbuf *page, const plDrawState *drawstate, bool need_cap, bool need_join)
629
_write_svg_path_style (page, drawstate, need_cap, need_join)
631
const plDrawState *drawstate;
632
bool need_cap, need_join;
612
write_svg_path_style (plOutbuf *page, const plDrawState *drawstate, bool need_cap, bool need_join)
635
614
char color_buf[8]; /* enough room for "#ffffff", incl. NUL */
637
sprintf (page->point, "style=\"");
638
_update_buffer (page);
640
616
if (drawstate->pen_type)
642
618
if (drawstate->fgcolor.red != 0
644
620
|| drawstate->fgcolor.blue != 0)
645
621
/* non-black, i.e. non-default */
647
sprintf (page->point, "stroke:%s;",
623
sprintf (page->point, "stroke=\"%s\" ",
648
624
_libplot_color_to_svg_color (drawstate->fgcolor,
650
626
_update_buffer (page);
653
sprintf (page->point, "stroke-width:%.5g;",
629
/* should use `px' here to specify user units, per the SVG Authoring
630
Guide, but ImageMagick objects to that */
631
sprintf (page->point, "stroke-width=\"%.5g\" ",
654
632
drawstate->line_width);
655
633
_update_buffer (page);
659
if (drawstate->cap_type != CAP_BUTT) /* i.e. not default */
637
if (drawstate->cap_type != PL_CAP_BUTT) /* i.e. not default */
661
sprintf (page->point, "stroke-linecap:%s;",
662
_svg_cap_style[drawstate->cap_type]);
639
sprintf (page->point, "stroke-linecap=\"%s\" ",
640
svg_cap_style[drawstate->cap_type]);
663
641
_update_buffer (page);
669
if (drawstate->join_type != JOIN_MITER) /* i.e. not default */
647
if (drawstate->join_type != PL_JOIN_MITER) /* i.e. not default */
671
sprintf (page->point, "stroke-linejoin:%s;",
672
_svg_join_style[drawstate->join_type]);
649
sprintf (page->point, "stroke-linejoin=\"%s\" ",
650
svg_join_style[drawstate->join_type]);
673
651
_update_buffer (page);
676
if (drawstate->join_type == JOIN_MITER
677
&& drawstate->miter_limit != DEFAULT_MITER_LIMIT)
654
if (drawstate->join_type == PL_JOIN_MITER
655
&& drawstate->miter_limit != PL_DEFAULT_MITER_LIMIT)
679
sprintf (page->point, "stroke-miterlimit:%.5g;",
657
sprintf (page->point, "stroke-miterlimit=\"%.5g\" ",
680
658
drawstate->miter_limit);
681
659
_update_buffer (page);
686
664
&& drawstate->dash_array_len > 0)
688
666
(drawstate->dash_array_in_effect == false
689
&& drawstate->line_type != L_SOLID)) /* non-solid builtin linetype*/
667
&& drawstate->line_type != PL_L_SOLID)) /* non-solid builtin linetype*/
690
668
/* need to specify stroke-array, maybe stroke-offset too */
712
690
&min_sing_val, &max_sing_val);
713
691
if (max_sing_val != 0.0)
715
DEFAULT_LINE_WIDTH_AS_FRACTION_OF_DISPLAY_SIZE / max_sing_val;
693
PL_DEFAULT_LINE_WIDTH_AS_FRACTION_OF_DISPLAY_SIZE / max_sing_val;
718
696
scale = DMAX(drawstate->line_width, min_width);
720
698
/* take normalized dash array (linemode-specific) from
721
699
internal table */
723
_line_styles[drawstate->line_type].dash_array;
701
_pl_g_line_styles[drawstate->line_type].dash_array;
725
_line_styles[drawstate->line_type].dash_array_len;
726
dashbuf = (double *)_plot_xmalloc (num_dashes * sizeof(double));
703
_pl_g_line_styles[drawstate->line_type].dash_array_len;
704
dashbuf = (double *)_pl_xmalloc (num_dashes * sizeof(double));
728
706
/* scale length of each dash by current line width, unless
729
707
it's too small (see above computation) */
732
710
offset = 0.0; /* true for all builtin line types */
735
sprintf (page->point, "stroke-dasharray:");
713
sprintf (page->point, "stroke-dasharray=\"");
736
714
_update_buffer (page);
737
715
for (i = 0; i < num_dashes; i++)
739
717
sprintf (page->point, "%.5g%s",
741
i < num_dashes - 1 ? " " : ";");
719
i < num_dashes - 1 ? " " : "\"");
742
720
_update_buffer (page);
745
723
if (offset != 0.0) /* not default */
747
sprintf (page->point, "stroke-dashoffset:%.5g;",
725
/* should use `px' here to specify user units, per the SVG
726
Authoring Guide, but ImageMagick objects to that */
727
sprintf (page->point, "stroke-dashoffset=\"%.5g\" ",
749
729
_update_buffer (page);
763
sprintf (page->point, "stroke:none;");
743
sprintf (page->point, "stroke=\"none\" ");
764
744
_update_buffer (page);
767
747
if (drawstate->fill_type)
769
sprintf (page->point, "fill:%s;",
749
sprintf (page->point, "fill=\"%s\" ",
770
750
_libplot_color_to_svg_color (drawstate->fillcolor, color_buf));
771
751
_update_buffer (page);
773
if (drawstate->fill_rule_type != FILL_ODD_WINDING) /* not default */
753
if (drawstate->fill_rule_type != PL_FILL_ODD_WINDING) /* not default */
775
sprintf (page->point, "fill-rule:%s;",
776
_svg_fill_style[drawstate->fill_rule_type]);
755
sprintf (page->point, "fill-rule=\"%s\" ",
756
svg_fill_style[drawstate->fill_rule_type]);
777
757
_update_buffer (page);
781
sprintf (page->point, "\"");
782
_update_buffer (page);