GCC Code Coverage Report


Directory: ./
File: include/2geom/path-sink.h
Date: 2024-03-18 17:01:34
Exec Total Coverage
Lines: 23 52 44.2%
Functions: 6 14 42.9%
Branches: 6 26 23.1%

Line Branch Exec Source
1 /**
2 * \file
3 * \brief callback interface for SVG path data
4 *//*
5 * Copyright 2007 MenTaLguY <mental@rydia.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
14 *
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
20 *
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
25 *
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
29 *
30 */
31
32 #ifndef LIB2GEOM_SEEN_PATH_SINK_H
33 #define LIB2GEOM_SEEN_PATH_SINK_H
34
35 #include <2geom/forward.h>
36 #include <2geom/pathvector.h>
37 #include <2geom/curves.h>
38 #include <iterator>
39
40 namespace Geom {
41
42
43 /** @brief Callback interface for processing path data.
44 *
45 * PathSink provides an interface that allows one to easily write
46 * code which processes path data, for instance when converting
47 * between path formats used by different graphics libraries.
48 * It is also useful for writing algorithms which must do something
49 * for each curve in the path.
50 *
51 * To store a path in a new format, implement the virtual methods
52 * for segments in a derived class and call feed().
53 *
54 * @ingroup Paths
55 */
56 class PathSink {
57 public:
58 /** @brief Move to a different point without creating a segment.
59 * Usually starts a new subpath. */
60 virtual void moveTo(Point const &p) = 0;
61 /// Output a line segment.
62 virtual void lineTo(Point const &p) = 0;
63 /// Output a quadratic Bezier segment.
64 virtual void curveTo(Point const &c0, Point const &c1, Point const &p) = 0;
65 /// Output a cubic Bezier segment.
66 virtual void quadTo(Point const &c, Point const &p) = 0;
67 /** @brief Output an elliptical arc segment.
68 * See the EllipticalArc class for the documentation of parameters. */
69 virtual void arcTo(Coord rx, Coord ry, Coord angle,
70 bool large_arc, bool sweep, Point const &p) = 0;
71
72 /// Close the current path with a line segment.
73 virtual void closePath() = 0;
74 /** @brief Flush any internal state of the generator.
75 * This call should implicitly finish the current subpath.
76 * Calling this method should be idempotent, because the default
77 * implementations of path() and pathvector() will call it
78 * multiple times in a row. */
79 virtual void flush() = 0;
80 // Get the current point, e.g. where the initial point of the next segment will be.
81 //virtual Point currentPoint() const = 0;
82
83 /** @brief Undo the last segment.
84 * This method is optional.
85 * @return true true if a segment was erased, false otherwise. */
86 virtual bool backspace() { return false; }
87
88 // these have a default implementation
89 virtual void feed(Curve const &c, bool moveto_initial = true);
90 /** @brief Output a subpath.
91 * Calls the appropriate segment methods according to the contents
92 * of the passed subpath. You can override this function.
93 * NOTE: if you override only some of the feed() functions,
94 * always write this in the derived class:
95 * @code
96 using PathSink::feed;
97 @endcode
98 * Otherwise the remaining methods will be hidden. */
99 virtual void feed(Path const &p);
100 /** @brief Output a path.
101 * Calls feed() on each path in the vector. You can override this function. */
102 virtual void feed(PathVector const &v);
103 /// Output an axis-aligned rectangle, using moveTo, lineTo and closePath.
104 virtual void feed(Rect const &);
105 /// Output a circle as two elliptical arcs.
106 virtual void feed(Circle const &e);
107 /// Output an ellipse as two elliptical arcs.
108 virtual void feed(Ellipse const &e);
109
110 630 virtual ~PathSink() {}
111 };
112
113 /** @brief Store paths to an output iterator
114 * @ingroup Paths */
115 template <typename OutputIterator>
116 class PathIteratorSink : public PathSink {
117 public:
118 315 explicit PathIteratorSink(OutputIterator out)
119
1/2
✓ Branch 4 taken 315 times.
✗ Branch 5 not taken.
315 : _in_path(false), _out(out) {}
120
121 861 void moveTo(Point const &p) override {
122 861 flush();
123 861 _path.start(p);
124 861 _start_p = p;
125 861 _in_path = true;
126 861 }
127 //TODO: what if _in_path = false?
128
129 /** @brief Detect if the builder is in a path and thus will NOT
130 create a new moveTo command when given the next line
131 @return true if the builder is inside a subpath.
132 */
133 bool inPath() const {
134 return _in_path;
135 }
136
137 549 void lineTo(Point const &p) override {
138 // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 549 times.
549 if (!_in_path) {
140 moveTo(_start_p);
141 }
142 549 _path.template appendNew<LineSegment>(p);
143 549 }
144
145 void quadTo(Point const &c, Point const &p) override {
146 // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
147 if (!_in_path) {
148 moveTo(_start_p);
149 }
150 _path.template appendNew<QuadraticBezier>(c, p);
151 }
152
153 22725 void curveTo(Point const &c0, Point const &c1, Point const &p) override {
154 // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22725 times.
22725 if (!_in_path) {
156 moveTo(_start_p);
157 }
158 22725 _path.template appendNew<CubicBezier>(c0, c1, p);
159 22725 }
160
161 void arcTo(Coord rx, Coord ry, Coord angle,
162 bool large_arc, bool sweep, Point const &p) override
163 {
164 // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
165 if (!_in_path) {
166 moveTo(_start_p);
167 }
168 _path.template appendNew<EllipticalArc>(rx, ry, angle,
169 large_arc, sweep, p);
170 }
171
172 bool backspace() override
173 {
174 if (_in_path && _path.size() > 0) {
175 _path.erase_last();
176 return true;
177 }
178 return false;
179 }
180
181 void append(Path const &other)
182 {
183 if (!_in_path) {
184 moveTo(other.initialPoint());
185 }
186 _path.append(other);
187 }
188
189 void closePath() override {
190 if (_in_path) {
191 _path.close();
192 flush();
193 }
194 }
195
196 1176 void flush() override {
197
2/2
✓ Branch 0 taken 861 times.
✓ Branch 1 taken 315 times.
1176 if (_in_path) {
198 861 _in_path = false;
199
1/2
✓ Branch 4 taken 861 times.
✗ Branch 5 not taken.
861 *_out++ = _path;
200 861 _path.clear();
201 }
202 1176 }
203
204 void setStitching(bool s) {
205 _path.setStitching(s);
206 }
207
208 using PathSink::feed;
209 void feed(Path const &other) override
210 {
211 flush();
212 *_out++ = other;
213 }
214
215 protected:
216 bool _in_path;
217 OutputIterator _out;
218 Path _path;
219 Point _start_p;
220 };
221
222 typedef std::back_insert_iterator<PathVector> SubpathInserter;
223
224 /** @brief Store paths to a PathVector
225 * @ingroup Paths */
226 class PathBuilder : public PathIteratorSink<SubpathInserter> {
227 private:
228 PathVector _pathset;
229 public:
230 /// Create a builder that outputs to an internal pathvector.
231 PathBuilder() : PathIteratorSink<SubpathInserter>(SubpathInserter(_pathset)) {}
232 /// Create a builder that outputs to pathvector given by reference.
233 PathBuilder(PathVector &pv) : PathIteratorSink<SubpathInserter>(SubpathInserter(pv)) {}
234
235 /// Retrieve the path
236 PathVector const &peek() const {return _pathset;}
237 /// Clear the stored path vector
238 void clear() { _pathset.clear(); }
239 };
240
241 }
242
243 #endif
244 /*
245 Local Variables:
246 mode:c++
247 c-file-style:"stroustrup"
248 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
249 indent-tabs-mode:nil
250 fill-column:99
251 End:
252 */
253 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
254