GCC Code Coverage Report


Directory: ./
File: include/2geom/svg-path-parser.h
Date: 2024-03-18 17:01:34
Exec Total Coverage
Lines: 7 21 33.3%
Functions: 1 3 33.3%
Branches: 2 14 14.3%

Line Branch Exec Source
1 /**
2 * \file
3 * \brief parse SVG path specifications
4 *
5 * Copyright 2007 MenTaLguY <mental@rydia.net>
6 * Copyright 2007 Aaron Spike <aaron@ekips.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it either under the terms of the GNU Lesser General Public
10 * License version 2.1 as published by the Free Software Foundation
11 * (the "LGPL") or, at your option, under the terms of the Mozilla
12 * Public License Version 1.1 (the "MPL"). If you do not alter this
13 * notice, a recipient may use your version of this file under either
14 * the MPL or the LGPL.
15 *
16 * You should have received a copy of the LGPL along with this library
17 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * You should have received a copy of the MPL along with this library
20 * in the file COPYING-MPL-1.1
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License at
25 * http://www.mozilla.org/MPL/
26 *
27 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29 * the specific language governing rights and limitations.
30 *
31 */
32
33 #ifndef LIB2GEOM_SEEN_SVG_PATH_PARSER_H
34 #define LIB2GEOM_SEEN_SVG_PATH_PARSER_H
35
36 #include <iostream>
37 #include <iterator>
38 #include <stdexcept>
39 #include <vector>
40 #include <cstdio>
41 #include <2geom/exception.h>
42 #include <2geom/point.h>
43 #include <2geom/path-sink.h>
44 #include <2geom/forward.h>
45
46 namespace Geom {
47
48 /** @brief Read SVG path data and feed it to a PathSink
49 *
50 * This class provides an interface to an SVG path data parser written in Ragel.
51 * It supports parsing the path data either at once or block-by-block.
52 * Use the parse() functions to parse complete data and the feed() and finish()
53 * functions to parse partial data.
54 *
55 * The parser will call the appropriate methods on the PathSink supplied
56 * at construction. To store the path in memory as a PathVector, pass
57 * a PathBuilder. You can also use one of the freestanding helper functions
58 * if you don't need to parse data block-by-block.
59 *
60 * @ingroup Paths
61 */
62 class SVGPathParser {
63 public:
64 SVGPathParser(PathSink &sink);
65 ~SVGPathParser();
66
67 /** @brief Reset internal state.
68 * Discards the internal state associated with partially parsed data,
69 * letting you start from scratch. Note that any partial data written
70 * to the path sink is not affected - you need to clear it yourself. */
71 void reset();
72
73 /** @brief Parse a C-style string.
74 * The path sink is flushed and the internal state is reset after this call.
75 * Note that the state is not reset before this method, so you can use it to
76 * process the last block of partial data.
77 * @param str String to parse
78 * @param len Length of string or -1 if null-terminated */
79 void parse(char const *str, int len = -1);
80 /** @brief Parse an STL string. */
81 void parse(std::string const &s);
82
83 /** @brief Parse a part of path data stored in a C-style string.
84 * This method does not reset internal state, so it can be called multiple
85 * times to parse successive blocks of a longer SVG path data string.
86 * To finish parsing, call finish() after the final block or call parse()
87 * with the last block of data.
88 * @param str String to parse
89 * @param len Length of string or -1 if null-terminated */
90 void feed(char const *str, int len = -1);
91 /** @brief Parse a part of path data stored in an STL string. */
92 void feed(std::string const &s);
93
94 /** @brief Finalize parsing.
95 * After the last block of data was submitted with feed(), call this method
96 * to finalize parsing, flush the path sink and reset internal state.
97 * You should not call this after parse(). */
98 void finish();
99
100 /** @brief Set the threshold for considering the closing segment degenerate.
101 * When the current point was reached by a relative command, is closer
102 * to the initial point of the path than the specified threshold
103 * and a 'z' is encountered, the last segment will be adjusted instead so that
104 * the closing segment has exactly zero length. This is useful when reading
105 * SVG 1.1 paths that have non-linear final segments written in relative
106 * coordinates, which always suffer from some loss of precision. SVG 2
107 * allows alternate placement of 'z' which does not have this problem. */
108 void setZSnapThreshold(Coord threshold) { _z_snap_threshold = threshold; }
109 Coord zSnapThreshold() const { return _z_snap_threshold; }
110
111 private:
112 bool _absolute;
113 bool _moveto_was_absolute;
114 Point _current;
115 Point _initial;
116 Point _cubic_tangent;
117 Point _quad_tangent;
118 std::vector<Coord> _params;
119 PathSink &_sink;
120 Coord _z_snap_threshold;
121 Curve *_curve;
122
123 int cs;
124 std::string _number_part;
125
126 void _push(Coord value);
127 Coord _pop();
128 bool _pop_flag();
129 Coord _pop_coord(Geom::Dim2 axis);
130 Point _pop_point();
131 void _moveTo(Point const &p);
132 void _lineTo(Point const &p);
133 void _curveTo(Point const &c0, Point const &c1, Point const &p);
134 void _quadTo(Point const &c, Point const &p);
135 void _arcTo(double rx, double ry, double angle,
136 bool large_arc, bool sweep, Point const &p);
137 void _closePath();
138 void _pushCurve(Curve *c);
139
140 void _parse(char const *str, char const *strend, bool finish);
141 };
142
143 /** @brief Feed SVG path data to the specified sink
144 * @ingroup Paths */
145 void parse_svg_path(char const *str, PathSink &sink);
146 /** @brief Feed SVG path data to the specified sink
147 * @ingroup Paths */
148 inline void parse_svg_path(std::string const &str, PathSink &sink) {
149 parse_svg_path(str.c_str(), sink);
150 }
151 /** Feed SVG path data from a C stream to the specified sink
152 * @ingroup Paths */
153 void parse_svg_path_file(FILE *fi, PathSink &sink);
154
155 /** @brief Create path vector from SVG path data stored in a C string
156 * @ingroup Paths */
157 315 inline PathVector parse_svg_path(char const *str) {
158 315 PathVector ret;
159 315 SubpathInserter iter(ret);
160
1/2
✓ Branch 2 taken 315 times.
✗ Branch 3 not taken.
315 PathIteratorSink<SubpathInserter> generator(iter);
161
162
1/2
✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
315 parse_svg_path(str, generator);
163 630 return ret;
164 315 }
165
166 /** @brief Create path vector from a C stream with SVG path data
167 * @ingroup Paths */
168 inline PathVector read_svgd_f(FILE * fi) {
169 PathVector ret;
170 SubpathInserter iter(ret);
171 PathIteratorSink<SubpathInserter> generator(iter);
172
173 parse_svg_path_file(fi, generator);
174 return ret;
175 }
176
177 /** @brief Create path vector from SVG path data stored in a file
178 * @ingroup Paths */
179 inline PathVector read_svgd(char const *filename) {
180 FILE* fi = fopen(filename, "r");
181 if(fi == NULL) throw(std::runtime_error("Error opening file"));
182 PathVector out = read_svgd_f(fi);
183 fclose(fi);
184 return out;
185 }
186
187 } // end namespace Geom
188
189 #endif
190 /*
191 Local Variables:
192 mode:c++
193 c-file-style:"stroustrup"
194 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
195 indent-tabs-mode:nil
196 fill-column:99
197 End:
198 */
199 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
200