summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbulia byak <buliabyak@gmail.com>2008-03-18 04:53:42 +0000
committerbuliabyak <buliabyak@users.sourceforge.net>2008-03-18 04:53:42 +0000
commitb555f4f62c62c7d5b2bab05d4b56ad068537c9f4 (patch)
treea683e43ff1d65eea28738c6016243283266739eb /src
parentA fix for bug #199357 "cannot load emf file" based on the patch submitted by ... (diff)
downloadinkscape-b555f4f62c62c7d5b2bab05d4b56ad068537c9f4.tar.gz
inkscape-b555f4f62c62c7d5b2bab05d4b56ad068537c9f4.zip
patch by Jasper for optimizing path data
(bzr r5110)
Diffstat (limited to 'src')
-rw-r--r--src/preferences-skeleton.h2
-rw-r--r--src/svg/Makefile_insert1
-rw-r--r--src/svg/path-string.cpp57
-rw-r--r--src/svg/path-string.h146
-rw-r--r--src/svg/svg-path.cpp4
5 files changed, 168 insertions, 42 deletions
diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h
index ab8c29f42..225d572b0 100644
--- a/src/preferences-skeleton.h
+++ b/src/preferences-skeleton.h
@@ -254,7 +254,7 @@ static char const preferences_skeleton[] =
" images=\"4278190335\"" //ff0000ff
" clips=\"16711935\"" // 00ff00ff
" masks=\"65535\"/>\n" // 0x0000ffff
-" <group id=\"svgoutput\" usenamedcolors=\"0\" numericprecision=\"8\" minimumexponent=\"-8\" inlineattrs=\"0\" indent=\"2\"/>\n"
+" <group id=\"svgoutput\" usenamedcolors=\"0\" numericprecision=\"8\" minimumexponent=\"-8\" inlineattrs=\"0\" indent=\"2\" allowrelativecoordinates=\"1\" allowshorthands=\"1\" forcerepeatcommands=\"0\"/>\n"
" <group id=\"forkgradientvectors\" value=\"1\"/>\n"
" <group id=\"grids\""
" no_emphasize_when_zoomedout=\"0\">\n"
diff --git a/src/svg/Makefile_insert b/src/svg/Makefile_insert
index 5c723dfac..5e57c7068 100644
--- a/src/svg/Makefile_insert
+++ b/src/svg/Makefile_insert
@@ -20,6 +20,7 @@ svg_libspsvg_a_SOURCES = \
svg/gnome-canvas-bpath-util.h \
svg/itos.cpp \
svg/path-string.h \
+ svg/path-string.cpp \
svg/round.cpp \
svg/stringstream.h \
svg/stringstream.cpp \
diff --git a/src/svg/path-string.cpp b/src/svg/path-string.cpp
new file mode 100644
index 000000000..4cf790a9b
--- /dev/null
+++ b/src/svg/path-string.cpp
@@ -0,0 +1,57 @@
+/*
+ * Inkscape::SVG::PathString - builder for SVG path strings
+ *
+ * Copyright 2008 Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * See the file COPYING for details.
+ *
+ */
+
+#include "svg/path-string.h"
+#include "prefs-utils.h"
+
+Inkscape::SVG::PathString::PathString() :
+ allow_relative_coordinates(0 != prefs_get_int_attribute("options.svgoutput", "allowrelativecoordinates", 1)),
+ allow_shorthands(0 != prefs_get_int_attribute("options.svgoutput", "allowshorthands", 1)),
+ force_repeat_commands(0 != prefs_get_int_attribute("options.svgoutput", "forcerepeatcommands", 0))
+{}
+
+void Inkscape::SVG::PathString::_appendOp(char abs_op, char rel_op) {
+ bool abs_op_repeated = _abs_state.prevop == abs_op && !force_repeat_commands;
+ bool rel_op_repeated = _rel_state.prevop == rel_op && !force_repeat_commands;
+ unsigned int const abs_added_size = abs_op_repeated ? 0 : 2;
+ unsigned int const rel_added_size = rel_op_repeated ? 0 : 2;
+ if ( _rel_state.str.size()+2 < _abs_state.str.size()+abs_added_size && allow_relative_coordinates ) {
+ // Copy rel to abs
+ _abs_state = _rel_state;
+ _abs_state.switches++;
+ abs_op_repeated = false;
+ // We do not have to copy abs to rel:
+ // _rel_state.str.size()+2 < _abs_state.str.size()+abs_added_size
+ // _rel_state.str.size()+rel_added_size < _abs_state.str.size()+2
+ // _abs_state.str.size()+2 > _rel_state.str.size()+rel_added_size
+ } else if ( _abs_state.str.size()+2 < _rel_state.str.size()+rel_added_size ) {
+ // Copy abs to rel
+ _rel_state = _abs_state;
+ _abs_state.switches++;
+ rel_op_repeated = false;
+ }
+ if ( !abs_op_repeated ) _abs_state.appendOp(abs_op);
+ if ( !rel_op_repeated ) _rel_state.appendOp(rel_op);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/svg/path-string.h b/src/svg/path-string.h
index 3139466ef..e90e11048 100644
--- a/src/svg/path-string.h
+++ b/src/svg/path-string.h
@@ -2,6 +2,7 @@
* Inkscape::SVG::PathString - builder for SVG path strings
*
* Copyright 2007 MenTaLguY <mental@rydia.net>
+ * Copyright 2008 Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,6 +18,7 @@
#include <glibmm/ustring.h>
#include "libnr/nr-point.h"
+#include "libnr/nr-point-ops.h"
#include "svg/stringstream.h"
namespace Inkscape {
@@ -25,13 +27,13 @@ namespace SVG {
class PathString {
public:
- PathString() {}
+ PathString();
// default copy
// default assign
Glib::ustring const &ustring() const {
- return _str;
+ return (_abs_state <= _rel_state || !allow_relative_coordinates) ? _abs_state.str : _rel_state.str;
}
operator Glib::ustring const &() const {
@@ -39,7 +41,7 @@ public:
}
char const *c_str() const {
- return _str.c_str();
+ return ustring().c_str();
}
PathString &moveTo(NR::Coord x, NR::Coord y) {
@@ -47,8 +49,10 @@ public:
}
PathString &moveTo(NR::Point p) {
- _appendOp('M');
- _append(p);
+ _appendOp('M','m');
+ _appendPoint(p);
+
+ _current_point = _initial_point = p;
return *this;
}
@@ -57,8 +61,10 @@ public:
}
PathString &lineTo(NR::Point p) {
- _appendOp('L');
- _append(p);
+ _appendOp('L','l');
+ _appendPoint(p);
+
+ _current_point = p;
return *this;
}
@@ -67,9 +73,11 @@ public:
}
PathString &quadTo(NR::Point c, NR::Point p) {
- _appendOp('Q');
- _append(c);
- _append(p);
+ _appendOp('Q','q');
+ _appendPoint(c);
+ _appendPoint(p);
+
+ _current_point = p;
return *this;
}
@@ -79,13 +87,14 @@ public:
{
return curveTo(NR::Point(x0, y0), NR::Point(x1, y1), NR::Point(x, y));
}
-
PathString &curveTo(NR::Point c0, NR::Point c1, NR::Point p) {
- _appendOp('C');
- _append(c0);
- _append(c1);
- _append(p);
+ _appendOp('C','c');
+ _appendPoint(c0);
+ _appendPoint(c1);
+ _appendPoint(p);
+
+ _current_point = p;
return *this;
}
@@ -93,46 +102,103 @@ public:
bool large_arc, bool sweep,
NR::Point p)
{
- _appendOp('A');
- _append(NR::Point(rx, ry));
- _append(rot);
- _append(large_arc);
- _append(sweep);
- _append(p);
+ _appendOp('A','a');
+ _appendValue(NR::Point(rx,ry));
+ _appendValue(rot);
+ _appendFlag(large_arc);
+ _appendFlag(sweep);
+ _appendPoint(p);
+
+ _current_point = p;
return *this;
}
PathString &closePath() {
- _appendOp('z');
- return *this;
+ _abs_state.appendOp('z');
+ _rel_state.appendOp('z');
+ _current_point = _initial_point;
+ return *this;
}
private:
- void _appendOp(char op) {
- if (!_str.empty()) {
- _str.append(1, ' ');
- }
- _str.append(1, op);
+
+ void _appendOp(char abs_op, char rel_op);
+
+ void _appendFlag(bool flag) {
+ _abs_state.append(flag);
+ _rel_state.append(flag);
+ }
+
+ void _appendValue(NR::Coord v) {
+ _abs_state.append(v);
+ _rel_state.append(v);
}
- void _append(bool flag) {
- _str.append(1, ' ');
- _str.append(1, ( flag ? '1' : '0' ));
+ void _appendValue(NR::Point p) {
+ _abs_state.append(p);
+ _rel_state.append(p);
}
- void _append(NR::Coord v) {
- SVGOStringStream os;
- os << ' ' << v;
- _str.append(os.str());
+ void _appendX(NR::Coord x) {
+ _abs_state.append(x);
+ _rel_state.append(x-_current_point[NR::X]);
}
- void _append(NR::Point p) {
- SVGOStringStream os;
- os << ' ' << p[NR::X] << ',' << p[NR::Y];
- _str.append(os.str());
+ void _appendY(NR::Coord y) {
+ _abs_state.append(y);
+ _rel_state.append(y-_current_point[NR::Y]);
}
- Glib::ustring _str;
+ void _appendPoint(NR::Point p) {
+ _abs_state.append(p);
+ _rel_state.append(p-_current_point);
+ }
+
+ 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;
+ }
+
+ 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());
+ }
+
+ void append(NR::Point p) {
+ SVGOStringStream os;
+ os << ' ' << p[NR::X] << ',' << p[NR::Y];
+ str.append(os.str());
+ }
+
+ bool operator<=(const State& s) const {
+ if ( str.size() < s.str.size() ) return true;
+ if ( str.size() > s.str.size() ) return false;
+ if ( switches < s.switches ) return true;
+ if ( switches > s.switches ) return false;
+ return true;
+ }
+
+ Glib::ustring str;
+ unsigned int switches;
+ char prevop;
+ } _abs_state, _rel_state; // State with the last operator being an absolute/relative operator
+
+ NR::Point _initial_point;
+ NR::Point _current_point;
+
+ bool const allow_relative_coordinates;
+ bool const allow_shorthands;
+ bool const force_repeat_commands;
};
}
diff --git a/src/svg/svg-path.cpp b/src/svg/svg-path.cpp
index 0239d2ae0..30b259fa8 100644
--- a/src/svg/svg-path.cpp
+++ b/src/svg/svg-path.cpp
@@ -664,7 +664,9 @@ gchar *sp_svg_write_path(NArtBpath const *bpath)
for (int i = 0; bpath[i].code != NR_END; i++){
switch (bpath [i].code){
case NR_LINETO:
- str.lineTo(bpath[i].x3, bpath[i].y3);
+ if (!closed || bpath[i+1].code == NR_LINETO || bpath[i+1].code == NR_CURVETO) {
+ str.lineTo(bpath[i].x3, bpath[i].y3);
+ }
break;
case NR_CURVETO: