Code

Commenting out Whiteboard configure flag
[inkscape.git] / src / svg / path-string.h
index e90e110486780550a80de5754592cf1d67891d03..9079acfb44294cb7580ce538b6a53bcb8a75357d 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/**
  * Inkscape::SVG::PathString - builder for SVG path strings
  *
  * Copyright 2007 MenTaLguY <mental@rydia.net>
@@ -17,9 +17,9 @@
 #define SEEN_INKSCAPE_SVG_PATH_STRING_H
 
 #include <glibmm/ustring.h>
-#include "libnr/nr-point.h"
-#include "libnr/nr-point-ops.h"
-#include "svg/stringstream.h"
+#include <string>
+#include <stdio.h>
+#include <2geom/point.h>
 
 namespace Inkscape {
 
@@ -32,84 +32,99 @@ public:
     // default copy
     // default assign
 
-    Glib::ustring const &ustring() const {
-        return (_abs_state <= _rel_state || !allow_relative_coordinates) ? _abs_state.str : _rel_state.str;
+    std::string const &string() {
+        std::string const &t = tail();
+        final.reserve(commonbase.size()+t.size());
+        final = commonbase;
+        final += tail();
+        return final;
+    }
+
+    operator std::string const &() {
+        return string();
     }
 
-    operator Glib::ustring const &() const {
-        return ustring();
+    operator Glib::ustring const () const {
+        return commonbase + tail();
     }
 
-    char const *c_str() const {
-        return ustring().c_str();
+    char const *c_str() {
+        return string().c_str();
     }
 
-    PathString &moveTo(NR::Coord x, NR::Coord y) {
-        return moveTo(NR::Point(x, y));
+    PathString &moveTo(Geom::Coord x, Geom::Coord y) {
+        return moveTo(Geom::Point(x, y));
     }
 
-    PathString &moveTo(NR::Point p) {
+    PathString &moveTo(Geom::Point p) {
         _appendOp('M','m');
-        _appendPoint(p);
+        _appendPoint(p, true);
 
-        _current_point = _initial_point = p;
+        _initial_point = _current_point;
         return *this;
     }
 
-    PathString &lineTo(NR::Coord x, NR::Coord y) {
-        return lineTo(NR::Point(x, y));
+    PathString &lineTo(Geom::Coord x, Geom::Coord y) {
+        return lineTo(Geom::Point(x, y));
     }
 
-    PathString &lineTo(NR::Point p) {
+    PathString &lineTo(Geom::Point p) {
         _appendOp('L','l');
-        _appendPoint(p);
+        _appendPoint(p, true);
+        return *this;
+    }
 
-        _current_point = p;
+    PathString &horizontalLineTo(Geom::Coord x) {
+        _appendOp('H','h');
+        _appendX(x, true);
         return *this;
     }
 
-    PathString &quadTo(NR::Coord cx, NR::Coord cy, NR::Coord x, NR::Coord y) {
-        return quadTo(NR::Point(cx, cy), NR::Point(x, y));
+    PathString &verticalLineTo(Geom::Coord y) {
+        _appendOp('V','v');
+        _appendY(y, true);
+        return *this;
     }
 
-    PathString &quadTo(NR::Point c, NR::Point p) {
-        _appendOp('Q','q');
-        _appendPoint(c);
-        _appendPoint(p);
+    PathString &quadTo(Geom::Coord cx, Geom::Coord cy, Geom::Coord x, Geom::Coord y) {
+        return quadTo(Geom::Point(cx, cy), Geom::Point(x, y));
+    }
 
-        _current_point = p;
+    PathString &quadTo(Geom::Point c, Geom::Point p) {
+        _appendOp('Q','q');
+        _appendPoint(c, false);
+        _appendPoint(p, true);
         return *this;
     }
 
-    PathString &curveTo(NR::Coord x0, NR::Coord y0,
-                        NR::Coord x1, NR::Coord y1,
-                        NR::Coord x,  NR::Coord y)
+    PathString &curveTo(Geom::Coord x0, Geom::Coord y0,
+                        Geom::Coord x1, Geom::Coord y1,
+                        Geom::Coord x,  Geom::Coord y)
     {
-        return curveTo(NR::Point(x0, y0), NR::Point(x1, y1), NR::Point(x, y));
+        return curveTo(Geom::Point(x0, y0), Geom::Point(x1, y1), Geom::Point(x, y));
     }
 
-    PathString &curveTo(NR::Point c0, NR::Point c1, NR::Point p) {
+    PathString &curveTo(Geom::Point c0, Geom::Point c1, Geom::Point p) {
         _appendOp('C','c');
-        _appendPoint(c0);
-        _appendPoint(c1);
-        _appendPoint(p);
-
-        _current_point = p;
+        _appendPoint(c0, false);
+        _appendPoint(c1, false);
+        _appendPoint(p, true);
         return *this;
     }
 
-    PathString &arcTo(NR::Coord rx, NR::Coord ry, NR::Coord rot,
+    /**
+     *  \param rot the angle in degrees
+     */
+    PathString &arcTo(Geom::Coord rx, Geom::Coord ry, Geom::Coord rot,
                       bool large_arc, bool sweep,
-                      NR::Point p)
+                      Geom::Point p)
     {
         _appendOp('A','a');
-        _appendValue(NR::Point(rx,ry));
+        _appendValue(Geom::Point(rx,ry));
         _appendValue(rot);
         _appendFlag(large_arc);
         _appendFlag(sweep);
-        _appendPoint(p);
-
-        _current_point = p;
+        _appendPoint(p, true);
         return *this;
     }
 
@@ -129,56 +144,57 @@ private:
         _rel_state.append(flag);
     }
 
-    void _appendValue(NR::Coord v) {
+    void _appendValue(Geom::Coord v) {
         _abs_state.append(v);
         _rel_state.append(v);
     }
 
-    void _appendValue(NR::Point p) {
+    void _appendValue(Geom::Point p) {
         _abs_state.append(p);
         _rel_state.append(p);
     }
 
-    void _appendX(NR::Coord x) {
-        _abs_state.append(x);
-        _rel_state.append(x-_current_point[NR::X]);
+    void _appendX(Geom::Coord x, bool sc) {
+        double rx;
+        _abs_state.append(x, rx);
+        _rel_state.appendRelative(rx, _current_point[Geom::X]);
+        if (sc) _current_point[Geom::X] = rx;
     }
 
-    void _appendY(NR::Coord y) {
-        _abs_state.append(y);
-        _rel_state.append(y-_current_point[NR::Y]);
+    void _appendY(Geom::Coord y, bool sc) {
+        double ry;
+        _abs_state.append(y, ry);
+        _rel_state.appendRelative(ry, _current_point[Geom::Y]);
+        if (sc) _current_point[Geom::Y] = ry;
     }
 
-    void _appendPoint(NR::Point p) {
-        _abs_state.append(p);
-        _rel_state.append(p-_current_point);
+    void _appendPoint(Geom::Point p, bool sc) {
+        Geom::Point rp;
+        _abs_state.append(p, rp);
+        _rel_state.appendRelative(rp, _current_point);
+        if (sc) _current_point = rp;
     }
 
     struct State {
         State() { prevop = 0; switches = 0; }
 
         void appendOp(char op) {
-            if (!str.empty()) str.append(1, ' ');
-            str.append(1, op);
-            prevop = op == 'M' ? 'L' : op == 'm' ? 'l' : op;
+            if (prevop != 0) str += ' ';
+            str += op;
+            prevop = ( op == 'M' ? 'L' : op == 'm' ? 'l' : op );
         }
 
         void append(bool flag) {
-            str.append(1, ' ');
-            str.append(1, ( flag ? '1' : '0' ));
-        }
-
-        void append(NR::Coord v) {
-            SVGOStringStream os;
-            os << ' ' << v;
-            str.append(os.str());
+            str += ' ';
+            str += ( flag ? '1' : '0' );
         }
 
-        void append(NR::Point p) {
-            SVGOStringStream os;
-            os << ' ' << p[NR::X] << ',' << p[NR::Y];
-            str.append(os.str());
-        }
+        void append(Geom::Coord v);
+        void append(Geom::Point v);
+        void append(Geom::Coord v, Geom::Coord& rv);
+        void append(Geom::Point p, Geom::Point& rp);
+        void appendRelative(Geom::Coord v, Geom::Coord r);
+        void appendRelative(Geom::Point p, Geom::Point r);
 
         bool operator<=(const State& s) const {
             if ( str.size() < s.str.size() ) return true;
@@ -188,17 +204,32 @@ private:
             return true;
         }
 
-        Glib::ustring str;
+        // Note: changing this to Glib::ustring might cause problems in path-string.cpp because it assumes that
+        //       size() returns the size of the string in BYTES (and Glib::ustring::resize is terribly slow)
+        std::string str;
         unsigned int switches;
         char prevop;
+
+    private:
+        void appendNumber(double v, int precision=numericprecision, int minexp=minimumexponent);
+        void appendNumber(double v, double &rv, int precision=numericprecision, int minexp=minimumexponent);
+        void appendRelativeCoord(Geom::Coord v, Geom::Coord r);
     } _abs_state, _rel_state; // State with the last operator being an absolute/relative operator
 
-    NR::Point _initial_point;
-    NR::Point _current_point;
+    Geom::Point _initial_point;
+    Geom::Point _current_point;
+
+    // If both states have a common prefix it is stored here.
+    // Separating out the common prefix prevents repeated copying between the states
+    // to cause a quadratic time complexity (in the number of characters/operators)
+    std::string commonbase;
+    std::string final;
+    std::string const &tail() const { return ((_abs_state <= _rel_state || !allow_relative_coordinates) ? _abs_state.str : _rel_state.str); }
 
     bool const allow_relative_coordinates;
-    bool const allow_shorthands;
     bool const force_repeat_commands;
+    static int numericprecision;
+    static int minimumexponent;
 };
 
 }