From d9aa18c623eea5d9abcf31c97305cd9eac77adb4 Mon Sep 17 00:00:00 2001 From: jaspervdg Date: Tue, 6 May 2008 11:56:53 +0000 Subject: [PATCH] Fix a regression in the SVG path data parser (it will now parse things like "M 1.3.4" correctly again). --- src/svg/svg-path-test.h | 472 ++++++++++++++++++++++++++++++++++++++++ src/svg/svg-path.cpp | 36 +-- 2 files changed, 491 insertions(+), 17 deletions(-) create mode 100644 src/svg/svg-path-test.h diff --git a/src/svg/svg-path-test.h b/src/svg/svg-path-test.h new file mode 100644 index 000000000..1b39ca227 --- /dev/null +++ b/src/svg/svg-path-test.h @@ -0,0 +1,472 @@ +#include +#include "libnr/n-art-bpath.h" +#include "svg/svg.h" +#include "2geom/coord.h" +#include +#include +#include + +class SvgPathTest : public CxxTest::TestSuite +{ +private: + std::vector rectanglesAbsoluteClosed; + std::vector rectanglesRelativeClosed; + std::vector rectanglesAbsoluteOpen; + std::vector rectanglesRelativeOpen; + NArtBpath rectangleBpath[5+1]; +public: + SvgPathTest() { + // Lots of ways to define the same rectangle + rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2 Z"); + rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 z"); + rectanglesAbsoluteClosed.push_back("M 1,2 4,2 4,8 1,8 z"); + rectanglesAbsoluteClosed.push_back("M 1,2 H 4 V 8 H 1 z"); + rectanglesRelativeClosed.push_back("m 1,2 l 3,0 l 0,6 l -3,0 z"); + rectanglesRelativeClosed.push_back("m 1,2 3,0 0,6 -3,0 z"); + rectanglesRelativeClosed.push_back("m 1,2 h 3 v 6 h -3 z"); + rectanglesAbsoluteOpen.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2"); + rectanglesAbsoluteOpen.push_back("M 1,2 4,2 4,8 1,8 1,2"); + rectanglesAbsoluteOpen.push_back("M 1,2 H 4 V 8 H 1 V 2"); + rectanglesRelativeOpen.push_back("m 1,2 l 3,0 l 0,6 l -3,0 l 0,-6"); + rectanglesRelativeOpen.push_back("m 1,2 3,0 0,6 -3,0 0,-6"); + rectanglesRelativeOpen.push_back("m 1,2 h 3 v 6 h -3 v -6"); + rectangleBpath[0].code = NR_MOVETO; + rectangleBpath[0].x3 = 1; + rectangleBpath[0].y3 = 2; + rectangleBpath[1].code = NR_LINETO; + rectangleBpath[1].x3 = 4; + rectangleBpath[1].y3 = 2; + rectangleBpath[2].code = NR_LINETO; + rectangleBpath[2].x3 = 4; + rectangleBpath[2].y3 = 8; + rectangleBpath[3].code = NR_LINETO; + rectangleBpath[3].x3 = 1; + rectangleBpath[3].y3 = 8; + rectangleBpath[4].code = NR_LINETO; + rectangleBpath[4].x3 = 1; + rectangleBpath[4].y3 = 2; + rectangleBpath[5].code = NR_END; + // TODO: Also test some (smooth) cubic/quadratic beziers and elliptical arcs + } + + void testReadRectanglesAbsoluteClosed() + { + rectangleBpath[0].code = NR_MOVETO; + for(size_t i=0; icode != NR_END && b->code == a->code) { + switch(a->code) { + case NR_MOVETO: + case NR_MOVETO_OPEN: + case NR_LINETO: + if (!Geom::are_near(a->x3,b->x3, eps) || !Geom::are_near(a->y3,b->y3, eps)) return false; + break; + case NR_CURVETO: + if (!Geom::are_near(a->x1,b->x1, eps) || !Geom::are_near(a->y1,b->y1, eps)) return false; + if (!Geom::are_near(a->x2,b->x2, eps) || !Geom::are_near(a->y2,b->y2, eps)) return false; + if (!Geom::are_near(a->x3,b->x3, eps) || !Geom::are_near(a->y3,b->y3, eps)) return false; + break; + default: + TS_FAIL("Unknown path code!"); + } + a++; + b++; + } + return a->code == b->code; + } +}; + + +/* + 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/svg-path.cpp b/src/svg/svg-path.cpp index 36c0b0ce3..460bec922 100644 --- a/src/svg/svg-path.cpp +++ b/src/svg/svg-path.cpp @@ -475,7 +475,7 @@ static void rsvg_parse_path_data(RSVGParsePathCtx *ctx, char const *begin) { * At some point we'll need to do all of * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */ - do { + while(*begin) { double val; char const *end = rsvg_parse_float(&val, begin); if (end != begin) { @@ -515,23 +515,25 @@ static void rsvg_parse_path_data(RSVGParsePathCtx *ctx, char const *begin) { } ctx->params[ctx->param++] = val; rsvg_parse_path_do_cmd (ctx, false, 0); // We don't know the next command yet + } else { + char c = *begin; + if (c >= 'A' && c <= 'Z' && c != 'E') { + char next_cmd = c + 'a' - 'A'; + if (ctx->cmd) + rsvg_parse_path_do_cmd (ctx, true, next_cmd); + ctx->cmd = next_cmd; + ctx->rel = false; + } else if (c >= 'a' && c <= 'z' && c != 'e') { + char next_cmd = c; + if (ctx->cmd) + rsvg_parse_path_do_cmd (ctx, true, next_cmd); + ctx->cmd = next_cmd; + ctx->rel = true; + } + /* else c _should_ be whitespace or , */ + begin++; } - char c = *begin; - if (c >= 'A' && c <= 'Z' && c != 'E') { - char next_cmd = c + 'a' - 'A'; - if (ctx->cmd) - rsvg_parse_path_do_cmd (ctx, true, next_cmd); - ctx->cmd = next_cmd; - ctx->rel = false; - } else if (c >= 'a' && c <= 'z' && c != 'e') { - char next_cmd = c; - if (ctx->cmd) - rsvg_parse_path_do_cmd (ctx, true, next_cmd); - ctx->cmd = next_cmd; - ctx->rel = true; - } - /* else c _should_ be whitespace or , */ - } while(*(begin++)); + } if (ctx->cmd) rsvg_parse_path_do_cmd (ctx, true, 0); } -- 2.30.2