From: buliabyak Date: Tue, 18 Mar 2008 04:53:42 +0000 (+0000) Subject: patch by Jasper for optimizing path data X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=fb0d01bc96f0187b163d3fd6587e15e8d7a7cecf;p=inkscape.git patch by Jasper for optimizing path data --- 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 -" \n" +" \n" " \n" " \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 + * + * 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 + * Copyright 2008 Jasper van de Gronde * * 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 #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: