Code

Fix version check for wheel selector.
[inkscape.git] / src / svg / path-string.h
1 /**
2  * Inkscape::SVG::PathString - builder for SVG path strings
3  *
4  * Copyright 2007 MenTaLguY <mental@rydia.net>
5  * Copyright 2008 Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * See the file COPYING for details.
13  *
14  */
16 #ifndef SEEN_INKSCAPE_SVG_PATH_STRING_H
17 #define SEEN_INKSCAPE_SVG_PATH_STRING_H
19 #include <glibmm/ustring.h>
20 #include <string>
21 #include <stdio.h>
22 #include <2geom/point.h>
24 namespace Inkscape {
26 namespace SVG {
28 class PathString {
29 public:
30     PathString();
32     // default copy
33     // default assign
35     std::string const &string() {
36         std::string const &t = tail();
37         final.reserve(commonbase.size()+t.size());
38         final = commonbase;
39         final += tail();
40         return final;
41     }
43     operator std::string const &() {
44         return string();
45     }
47     operator Glib::ustring const () const {
48         return commonbase + tail();
49     }
51     char const *c_str() {
52         return string().c_str();
53     }
55     PathString &moveTo(Geom::Coord x, Geom::Coord y) {
56         return moveTo(Geom::Point(x, y));
57     }
59     PathString &moveTo(Geom::Point p) {
60         _appendOp('M','m');
61         _appendPoint(p, true);
63         _initial_point = _current_point;
64         return *this;
65     }
67     PathString &lineTo(Geom::Coord x, Geom::Coord y) {
68         return lineTo(Geom::Point(x, y));
69     }
71     PathString &lineTo(Geom::Point p) {
72         _appendOp('L','l');
73         _appendPoint(p, true);
74         return *this;
75     }
77     PathString &horizontalLineTo(Geom::Coord x) {
78         _appendOp('H','h');
79         _appendX(x, true);
80         return *this;
81     }
83     PathString &verticalLineTo(Geom::Coord y) {
84         _appendOp('V','v');
85         _appendY(y, true);
86         return *this;
87     }
89     PathString &quadTo(Geom::Coord cx, Geom::Coord cy, Geom::Coord x, Geom::Coord y) {
90         return quadTo(Geom::Point(cx, cy), Geom::Point(x, y));
91     }
93     PathString &quadTo(Geom::Point c, Geom::Point p) {
94         _appendOp('Q','q');
95         _appendPoint(c, false);
96         _appendPoint(p, true);
97         return *this;
98     }
100     PathString &curveTo(Geom::Coord x0, Geom::Coord y0,
101                         Geom::Coord x1, Geom::Coord y1,
102                         Geom::Coord x,  Geom::Coord y)
103     {
104         return curveTo(Geom::Point(x0, y0), Geom::Point(x1, y1), Geom::Point(x, y));
105     }
107     PathString &curveTo(Geom::Point c0, Geom::Point c1, Geom::Point p) {
108         _appendOp('C','c');
109         _appendPoint(c0, false);
110         _appendPoint(c1, false);
111         _appendPoint(p, true);
112         return *this;
113     }
115     /**
116      *  \param rot the angle in degrees
117      */
118     PathString &arcTo(Geom::Coord rx, Geom::Coord ry, Geom::Coord rot,
119                       bool large_arc, bool sweep,
120                       Geom::Point p)
121     {
122         _appendOp('A','a');
123         _appendValue(Geom::Point(rx,ry));
124         _appendValue(rot);
125         _appendFlag(large_arc);
126         _appendFlag(sweep);
127         _appendPoint(p, true);
128         return *this;
129     }
131     PathString &closePath() {
132         _abs_state.appendOp('z');
133         _rel_state.appendOp('z');
134         _current_point = _initial_point;
135         return *this;
136     }
138 private:
140     void _appendOp(char abs_op, char rel_op);
142     void _appendFlag(bool flag) {
143         _abs_state.append(flag);
144         _rel_state.append(flag);
145     }
147     void _appendValue(Geom::Coord v) {
148         _abs_state.append(v);
149         _rel_state.append(v);
150     }
152     void _appendValue(Geom::Point p) {
153         _abs_state.append(p);
154         _rel_state.append(p);
155     }
157     void _appendX(Geom::Coord x, bool sc) {
158         double rx;
159         _abs_state.append(x, rx);
160         _rel_state.appendRelative(rx, _current_point[Geom::X]);
161         if (sc) _current_point[Geom::X] = rx;
162     }
164     void _appendY(Geom::Coord y, bool sc) {
165         double ry;
166         _abs_state.append(y, ry);
167         _rel_state.appendRelative(ry, _current_point[Geom::Y]);
168         if (sc) _current_point[Geom::Y] = ry;
169     }
171     void _appendPoint(Geom::Point p, bool sc) {
172         Geom::Point rp;
173         _abs_state.append(p, rp);
174         _rel_state.appendRelative(rp, _current_point);
175         if (sc) _current_point = rp;
176     }
178     struct State {
179         State() { prevop = 0; switches = 0; }
181         void appendOp(char op) {
182             if (prevop != 0) str += ' ';
183             str += op;
184             prevop = ( op == 'M' ? 'L' : op == 'm' ? 'l' : op );
185         }
187         void append(bool flag) {
188             str += ' ';
189             str += ( flag ? '1' : '0' );
190         }
192         void append(Geom::Coord v);
193         void append(Geom::Point v);
194         void append(Geom::Coord v, Geom::Coord& rv);
195         void append(Geom::Point p, Geom::Point& rp);
196         void appendRelative(Geom::Coord v, Geom::Coord r);
197         void appendRelative(Geom::Point p, Geom::Point r);
199         bool operator<=(const State& s) const {
200             if ( str.size() < s.str.size() ) return true;
201             if ( str.size() > s.str.size() ) return false;
202             if ( switches < s.switches ) return true;
203             if ( switches > s.switches ) return false;
204             return true;
205         }
207         // Note: changing this to Glib::ustring might cause problems in path-string.cpp because it assumes that
208         //       size() returns the size of the string in BYTES (and Glib::ustring::resize is terribly slow)
209         std::string str;
210         unsigned int switches;
211         char prevop;
213     private:
214         void appendNumber(double v, int precision=numericprecision, int minexp=minimumexponent);
215         void appendNumber(double v, double &rv, int precision=numericprecision, int minexp=minimumexponent);
216         void appendRelativeCoord(Geom::Coord v, Geom::Coord r);
217     } _abs_state, _rel_state; // State with the last operator being an absolute/relative operator
219     Geom::Point _initial_point;
220     Geom::Point _current_point;
222     // If both states have a common prefix it is stored here.
223     // Separating out the common prefix prevents repeated copying between the states
224     // to cause a quadratic time complexity (in the number of characters/operators)
225     std::string commonbase;
226     std::string final;
227     std::string const &tail() const { return ((_abs_state <= _rel_state || !allow_relative_coordinates) ? _abs_state.str : _rel_state.str); }
229     bool const allow_relative_coordinates;
230     bool const force_repeat_commands;
231     static int numericprecision;
232     static int minimumexponent;
233 };
239 #endif
240 /*
241   Local Variables:
242   mode:c++
243   c-file-style:"stroustrup"
244   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
245   indent-tabs-mode:nil
246   fill-column:99
247   End:
248 */
249 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :