Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / svg / svg-path.cpp
1 #define __SP_SVG_PARSE_C__
2 /*
3    svg-path.c: Parse SVG path element data into bezier path.
5    Copyright (C) 2000 Eazel, Inc.
6    Copyright (C) 2000 Lauris Kaplinski
7    Copyright (C) 2001 Ximian, Inc.
8    Copyright (C) 2008 Johan Engelen
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of the
13    License, or (at your option) any later version.
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the
22    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23    Boston, MA 02111-1307, USA.
25    Authors:
26      Johan Engelen
27      (old nartbpath code that has been deleted: Raph Levien <raph@artofcode.com>)
28      (old nartbpath code that has been deleted: Lauris Kaplinski <lauris@ximian.com>)
29 */
31 #include <cstring>
32 #include <string>
33 #include <cassert>
34 #include <glib/gmem.h>
35 #include <glib/gmessages.h>
36 #include <glib/gstrfuncs.h>
37 #include <glib.h> // g_assert()
39 #include "svg/svg.h"
40 #include "svg/path-string.h"
42 #include <2geom/pathvector.h>
43 #include <2geom/path.h>
44 #include <2geom/curves.h>
45 #include <2geom/sbasis-to-bezier.h>
46 #include <2geom/svg-path.h>
47 #include <2geom/svg-path-parser.h>
48 #include <2geom/exception.h>
49 #include <2geom/angle.h>
51 /*
52  * Parses the path in str. When an error is found in the pathstring, this method
53  * returns a truncated path up to where the error was found in the pathstring.
54  * Returns an empty PathVector when str==NULL
55  */
56 Geom::PathVector sp_svg_read_pathv(char const * str)
57 {
58     Geom::PathVector pathv;
59     if (!str)
60         return pathv;  // return empty pathvector when str == NULL
63     typedef std::back_insert_iterator<Geom::PathVector> Inserter;
64     Inserter iter(pathv);
65     Geom::SVGPathGenerator<Inserter> generator(iter);
67     try {
68         Geom::parse_svg_path(str, generator);
69     }
70     catch (Geom::SVGPathParseError e) {
71         generator.finish();
72         // This warning is extremely annoying when testing
73         //g_warning("Malformed SVG path, truncated path up to where error was found.\n Input path=\"%s\"\n Parsed path=\"%s\"", str, sp_svg_write_path(pathv));
74     }
76     return pathv;
77 }
79 static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve const * c) {
80     if(Geom::LineSegment const *line_segment = dynamic_cast<Geom::LineSegment const  *>(c)) {
81         // don't serialize stitch segments
82         if (!dynamic_cast<Geom::Path::StitchSegment const *>(c)) {
83             str.lineTo( (*line_segment)[1][0], (*line_segment)[1][1] );
84         }
85     }
86     else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const  *>(c)) {
87         str.quadTo( (*quadratic_bezier)[1][0], (*quadratic_bezier)[1][1],
88                     (*quadratic_bezier)[2][0], (*quadratic_bezier)[2][1] );
89     }
90     else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const  *>(c)) {
91         str.curveTo( (*cubic_bezier)[1][0], (*cubic_bezier)[1][1],
92                      (*cubic_bezier)[2][0], (*cubic_bezier)[2][1],
93                      (*cubic_bezier)[3][0], (*cubic_bezier)[3][1] );
94     }
95     else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc const *>(c)) {
96         str.arcTo( svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1),
97                    Geom::rad_to_deg(svg_elliptical_arc->rotation_angle()),
98                    svg_elliptical_arc->large_arc_flag(), svg_elliptical_arc->sweep_flag(),
99                    svg_elliptical_arc->finalPoint() );
100     }
101     else if(Geom::HLineSegment const *hline_segment = dynamic_cast<Geom::HLineSegment const  *>(c)) {
102         str.horizontalLineTo( hline_segment->finalPoint()[0] );
103     }
104     else if(Geom::VLineSegment const *vline_segment = dynamic_cast<Geom::VLineSegment const  *>(c)) {
105         str.verticalLineTo( vline_segment->finalPoint()[1] );
106     } else { 
107         //this case handles sbasis as well as all other curve types
108         Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c->toSBasis(), 0.1);
110         //recurse to convert the new path resulting from the sbasis to svgd
111         for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
112             sp_svg_write_curve(str, &(*iter));
113         }
114     }
117 static void sp_svg_write_path(Inkscape::SVG::PathString & str, Geom::Path const & p) {
118     str.moveTo( p.initialPoint()[0], p.initialPoint()[1] );
120     for(Geom::Path::const_iterator cit = p.begin(); cit != p.end_open(); cit++) {
121         sp_svg_write_curve(str, &(*cit));
122     }
124     if (p.closed()) {
125         str.closePath();
126     }
129 gchar * sp_svg_write_path(Geom::PathVector const &p) {
130     Inkscape::SVG::PathString str;
132     for(Geom::PathVector::const_iterator pit = p.begin(); pit != p.end(); pit++) {
133         sp_svg_write_path(str, *pit);
134     }
136     return g_strdup(str.c_str());
139 gchar * sp_svg_write_path(Geom::Path const &p) {
140     Inkscape::SVG::PathString str;
142     sp_svg_write_path(str, p);
144     return g_strdup(str.c_str());
147 /*
148   Local Variables:
149   mode:c++
150   c-file-style:"stroustrup"
151   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
152   indent-tabs-mode:nil
153   fill-column:99
154   End:
155 */
156 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :