From 899bf4e12d82c895041ac9fb26dcd3032e5bb03e Mon Sep 17 00:00:00 2001 From: jaspervdg Date: Fri, 20 Jun 2008 11:11:50 +0000 Subject: [PATCH] Partial fix (for preventing numerical issues) and restructuring for PathString, plus a small fix for the new 2geom sp_svg_write_curve. --- src/svg/path-string.cpp | 101 ++++++++++++++++++---------------------- src/svg/path-string.h | 8 ++-- src/svg/svg-path.cpp | 2 +- 3 files changed, 50 insertions(+), 61 deletions(-) diff --git a/src/svg/path-string.cpp b/src/svg/path-string.cpp index c1725db6b..39d66d74e 100644 --- a/src/svg/path-string.cpp +++ b/src/svg/path-string.cpp @@ -28,7 +28,7 @@ void Inkscape::SVG::PathString::_appendOp(char abs_op, char rel_op) { 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 ( false && _rel_state.str.size()+2 < _abs_state.str.size()+abs_added_size && allow_relative_coordinates ) { + 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++; @@ -37,7 +37,7 @@ void Inkscape::SVG::PathString::_appendOp(char abs_op, char rel_op) { // _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 ( false && _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++; @@ -59,29 +59,29 @@ void Inkscape::SVG::PathString::State::append(NR::Point p) { str.append(os.str()); } -void Inkscape::SVG::PathString::State::append(NR::Coord v, NR::Coord &rv) { - SVGOStringStream os; +static void appendCoord(Glib::ustring& str, NR::Coord v, NR::Coord &rv) { + Inkscape::SVGOStringStream os; os << v; - str += ' '; str += os.str(); double c; sp_svg_number_read_d(os.str().c_str(), &c); rv = c; + /*{ + Inkscape::SVGOStringStream ost; + ost << rv; + if (ost.str()!=os.str()) { + FILE* file = fopen("pathstring log.txt","at"); + fprintf(file, "v: %g, rv: %g\n", v, rv); + fclose(file); + } + }*/ } void Inkscape::SVG::PathString::State::append(NR::Point p, NR::Point &rp) { - SVGOStringStream osx, osy; - osx << p[NR::X]; - osy << p[NR::Y]; str += ' '; - str += osx.str(); + appendCoord(str, p[NR::X], rp[NR::X]); str += ','; - str += osy.str(); - double x, y; - sp_svg_number_read_d(osx.str().c_str(), &x); - sp_svg_number_read_d(osy.str().c_str(), &y); - rp[NR::X] = x; - rp[NR::Y] = y; + appendCoord(str, p[NR::Y], rp[NR::Y]); } // NOTE: The following two appendRelative methods will not be exact if the total number of digits needed @@ -89,64 +89,53 @@ void Inkscape::SVG::PathString::State::append(NR::Point p, NR::Point &rp) { // it does happen the imprecise value is not likely to be chosen (because it will probably be a lot longer // than the absolute value). -void Inkscape::SVG::PathString::State::appendRelative(NR::Coord v, NR::Coord r) { - SVGOStringStream os; +static void appendRelativeCoord(Glib::ustring& str, NR::Coord v, NR::Coord r) { + Inkscape::SVGOStringStream os; int precision = (int)os.precision(); - int digitsBegin = (int)floor(log10(fabs(v-r))); // Position of first digit of difference int digitsEnd = (int)floor(log10(std::min(fabs(v),fabs(r)))) - precision; // Position just beyond the last significant digit of the smallest (in absolute sense) number - os << ' '; + double roundeddiff = floor((v-r)*pow(10.,-digitsEnd-1)+.5); + int numDigits = (int)floor(log10(fabs(roundeddiff)))+1; // Number of digits in roundeddiff if (r == 0) { os.precision(precision); os << v; } else if (v == 0) { os.precision(precision); os << -r; - } else if (digitsBegin>digitsEnd) { - os.precision(digitsBegin-digitsEnd); + } else if (numDigits>0) { + os.precision(numDigits); os << (v-r); } else { // This assumes the input numbers are already rounded to 'precision' digits os << '0'; } str.append(os.str()); + { + /*double c; + sp_svg_number_read_d(os.str().c_str(), &c); + if (fabs((v-r)-c)>5.*pow(10.,digitsEnd)) { + FILE* file = fopen("pathstring log.txt","at"); + fprintf(file, "bad, v: %.9g, r: %.9g, os: %s, c: %.12g, roundeddiff: %.12g, precision: %d, digitsEnd: %d, numDigits: %d\n", v, r, os.str().c_str(), c, roundeddiff, precision, digitsEnd, numDigits); + fclose(file); + } + Inkscape::SVGOStringStream ostr1, ostr2; + ostr1 << v; + ostr2 << (r+c); + if (ostr1.str() != ostr2.str()) { + FILE* file = fopen("pathstring log.txt","at"); + fprintf(file, "bad, v: %.9g, r: %.9g, os: %s, c: %.12g, ostr1: %s, ostr2: %s, roundeddiff: %.12g\n", v, r, os.str().c_str(), c, ostr1.str().c_str(), ostr2.str().c_str(), roundeddiff); + fclose(file); + }*/ + /*FILE* file = fopen("pathstring log.txt","at"); + fprintf(file, "good, v: %.9g, r: %.9g, os: %s, c: %.12g, roundeddiff: %.12g, precision: %d, digitsEnd: %d, numDigits: %d\n", v, r, os.str().c_str(), c, roundeddiff, precision, digitsEnd, numDigits); + fclose(file);*/ + } } void Inkscape::SVG::PathString::State::appendRelative(NR::Point p, NR::Point r) { - SVGOStringStream os; - int precision = (int)os.precision(); - int digitsBeginX = (int)floor(log10(fabs(p[NR::X]-r[NR::X]))); // Position of first digit of difference - int digitsEndX = (int)floor(log10(std::min(fabs(p[NR::X]),fabs(r[NR::X])))) - precision; // Position just beyond the last significant digit of the smallest (in absolute sense) number - int digitsBeginY = (int)floor(log10(fabs(p[NR::Y]-r[NR::Y]))); // Position of first digit of difference - int digitsEndY = (int)floor(log10(std::min(fabs(p[NR::Y]),fabs(r[NR::Y])))) - precision; // Position just beyond the last significant digit of the smallest (in absolute sense) number - os << ' '; - if (r[NR::X] == 0) { - os.precision(precision); - os << p[NR::X]; - } else if (p[NR::X] == 0) { - os.precision(precision); - os << -r[NR::X]; - } else if (digitsBeginX>digitsEndX) { - os.precision(digitsBeginX-digitsEndX); - os << (p[NR::X]-r[NR::X]); - } else { - // This assumes the input numbers are already rounded to 'precision' digits - os << '0'; - } - os << ','; - if (r[NR::Y] == 0) { - os.precision(precision); - os << p[NR::Y]; - } else if (p[NR::Y] == 0) { - os.precision(precision); - os << -r[NR::Y]; - } else if (digitsBeginY>digitsEndY) { - os.precision(digitsBeginY-digitsEndY); - os << (p[NR::Y]-r[NR::Y]); - } else { - // This assumes the input numbers are already rounded to 'precision' digits - os << '0'; - } - str.append(os.str()); + str += ' '; + appendRelativeCoord(str, p[NR::X], r[NR::X]); + str += ','; + appendRelativeCoord(str, p[NR::Y], r[NR::Y]); } /* diff --git a/src/svg/path-string.h b/src/svg/path-string.h index 9f06facd3..39d6d3f07 100644 --- a/src/svg/path-string.h +++ b/src/svg/path-string.h @@ -129,7 +129,7 @@ private: _abs_state.append(p); _rel_state.append(p); } - +/* void _appendX(NR::Coord x, bool sc) { double rx; _abs_state.append(x, rx); @@ -142,7 +142,7 @@ private: _abs_state.append(y, ry); _rel_state.appendRelative(ry, _current_point[NR::Y]); if (sc) _current_point[NR::Y] = ry; - } + }*/ void _appendPoint(NR::Point p, bool sc) { NR::Point rp; @@ -167,9 +167,9 @@ private: void append(NR::Coord v); void append(NR::Point v); - void append(NR::Coord v, NR::Coord& rv); + //void append(NR::Coord v, NR::Coord& rv); void append(NR::Point p, NR::Point& rp); - void appendRelative(NR::Coord v, NR::Coord r); + //void appendRelative(NR::Coord v, NR::Coord r); void appendRelative(NR::Point p, NR::Point r); bool operator<=(const State& s) const { diff --git a/src/svg/svg-path.cpp b/src/svg/svg-path.cpp index d610b9212..24ce3c15c 100644 --- a/src/svg/svg-path.cpp +++ b/src/svg/svg-path.cpp @@ -735,7 +735,7 @@ static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve cons str.lineTo( (*line_segment)[1][0], (*line_segment)[1][1] ); } else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast(c)) { - str.quadTo( (*quadratic_bezier)[1][0], (*quadratic_bezier)[1][0], + str.quadTo( (*quadratic_bezier)[1][0], (*quadratic_bezier)[1][1], (*quadratic_bezier)[2][0], (*quadratic_bezier)[2][1] ); } else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast(c)) { -- 2.30.2