svg-path-test.h revision e69f7d715a3db7f1fff1c8334714c8fab63852ab
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include <cxxtest/TestSuite.h>
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include "libnr/n-art-bpath.h"
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include "svg/svg.h"
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include "2geom/coord.h"
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include <string>
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include <vector>
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico#include <glib/gmem.h>
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNicoclass SvgPathTest : public CxxTest::TestSuite
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico{
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNicoprivate:
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico std::vector<std::string> rectanglesAbsoluteClosed;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico std::vector<std::string> rectanglesRelativeClosed;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico std::vector<std::string> rectanglesAbsoluteOpen;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico std::vector<std::string> rectanglesRelativeOpen;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath rectangleBpath[5+1];
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNicopublic:
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico SvgPathTest() {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico // Lots of ways to define the same rectangle
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2 Z");
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesAbsoluteClosed.push_back("M 1,2 4,2 4,8 1,8 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesAbsoluteClosed.push_back("M 1,2 H 4 V 8 H 1 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeClosed.push_back("m 1,2 l 3,0 l 0,6 l -3,0 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeClosed.push_back("m 1,2 3,0 0,6 -3,0 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeClosed.push_back("m 1,2 h 3 v 6 h -3 z");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesAbsoluteOpen.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesAbsoluteOpen.push_back("M 1,2 4,2 4,8 1,8 1,2");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesAbsoluteOpen.push_back("M 1,2 H 4 V 8 H 1 V 2");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeOpen.push_back("m 1,2 l 3,0 l 0,6 l -3,0 l 0,-6");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeOpen.push_back("m 1,2 3,0 0,6 -3,0 0,-6");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectanglesRelativeOpen.push_back("m 1,2 h 3 v 6 h -3 v -6");
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectangleBpath[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner rectangleBpath[0].x3 = 1;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[0].y3 = 2;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[1].code = NR_LINETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[1].x3 = 4;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[1].y3 = 2;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[2].code = NR_LINETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[2].x3 = 4;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[2].y3 = 8;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[3].code = NR_LINETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[3].x3 = 1;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[3].y3 = 8;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[4].code = NR_LINETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[4].x3 = 1;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[4].y3 = 2;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[5].code = NR_END;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico // TODO: Also test some (smooth) cubic/quadratic beziers and elliptical arcs
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico void testReadRectanglesAbsoluteClosed()
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[0].code = NR_MOVETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico for(size_t i=0; i<rectanglesAbsoluteClosed.size(); i++) {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath * bpath = sp_svg_read_path(rectanglesAbsoluteClosed[i].c_str());
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico TS_ASSERT(bpathEqual(bpath,rectangleBpath));
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico g_free(bpath);
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico void testReadRectanglesRelativeClosed()
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[0].code = NR_MOVETO;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico for(size_t i=0; i<rectanglesRelativeClosed.size(); i++) {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath * bpath = sp_svg_read_path(rectanglesRelativeClosed[i].c_str());
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico TS_ASSERT(bpathEqual(bpath,rectangleBpath));
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico g_free(bpath);
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico void testReadRectanglesAbsoluteOpen()
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[0].code = NR_MOVETO_OPEN;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico for(size_t i=0; i<rectanglesAbsoluteOpen.size(); i++) {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath * bpath = sp_svg_read_path(rectanglesAbsoluteOpen[i].c_str());
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico TS_ASSERT(bpathEqual(bpath,rectangleBpath));
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico void testReadRectanglesRelativeOpen()
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico rectangleBpath[0].code = NR_MOVETO_OPEN;
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico for(size_t i=0; i<rectanglesRelativeOpen.size(); i++) {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath * bpath = sp_svg_read_path(rectanglesRelativeOpen[i].c_str());
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico TS_ASSERT(bpathEqual(bpath,rectangleBpath));
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico g_free(bpath);
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico void testReadConcatenatedPaths()
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico NArtBpath bpath_good[4*5+1];
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico for(size_t i=0; i<4; i++) {
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico memcpy(bpath_good+i*5,rectangleBpath,sizeof(rectangleBpath[0])*5);
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico bpath_good[0*5].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1*5].code = NR_MOVETO_OPEN;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2*5].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3*5].code = NR_MOVETO_OPEN;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4*5].code = NR_END;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner for(size_t i=0; i<5; i++) {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1*5+i].x3 += bpath_good[0*5+4].x3;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1*5+i].y3 += bpath_good[0*5+4].y3;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner for(size_t i=0; i<5; i++) {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2*5+i].x3 += bpath_good[1*5+4].x3;
0033c073cef3bdf51409b8f8b37914941f340257apenner bpath_good[2*5+i].y3 += bpath_good[1*5+4].y3;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner std::string path_str = rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0];
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str.c_str());
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadZeroLengthSubpaths() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Per the SVG 1.1 specification (section F5) zero-length subpaths are relevant
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath bpath_good[8+1];
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO_OPEN;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].x3 = bpath_good[0].y3 = 0;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].code = NR_MOVETO_OPEN;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].x3 = bpath_good[1].y3 = 1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].x3 = bpath_good[2].y3 = 2;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].x3 = bpath_good[3].y3 = 3;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].x3 = bpath_good[4].y3 = 4;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].x3 = bpath_good[5].y3 = 5;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[6].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[6].x3 = bpath_good[6].y3 = 4;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[7].code = NR_MOVETO_OPEN;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[7].x3 = bpath_good[7].y3 = 6;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[8].code = NR_END;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test absolute version
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M 0,0 M 1,1 L 2,2 M 3,3 z M 4,4 L 5,5 z M 6,6";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test relative version
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "m 0,0 m 1,1 l 1,1 m 1,1 z m 1,1 l 1,1 z m 2,2";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadImplicitMoveto() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath bpath_good[6+1];
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].x3 = bpath_good[0].y3 = 1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].x3 = bpath_good[1].y3 = 2;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].x3 = bpath_good[2].y3 = 1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].x3 = bpath_good[3].y3 = 1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].x3 = bpath_good[4].y3 = 3;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].x3 = bpath_good[5].y3 = 1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[6].code = NR_END;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test absolute version
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M 1,1 L 2,2 z L 3,3 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test relative version
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M 1,1 L 2,2 z L 3,3 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadFloatingPoint() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath bpath_good[5+1];
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].x3 = .01;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].y3 = .02;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].x3 = .04;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].y3 = .02;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].x3 = 1.5;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].y3 = 1.6;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].x3 = .01;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].y3 = .08;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].x3 = .01;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].y3 = .02;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].code = NR_END;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test decimals
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M .01,.02 L.04.02 L1.5,1.6L0.01,0.08 .01.02 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test exponent
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L0150E-2,1.6e0L1.0e-2,80e-3 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadImplicitSeparation() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Coordinates need not be separated by whitespace if they can still be read unambiguously
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath bpath_good[5+1];
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].x3 = .1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].y3 = .2;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].x3 = .4;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[1].y3 = .2;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].x3 = .4;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[2].y3 = .8;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].x3 = .1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[3].y3 = .8;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].code = NR_LINETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].x3 = .1;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[4].y3 = .2;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[5].code = NR_END;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test absolute
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "M .1.2+0.4.2e0.4e0+8e-1.1.8 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner { // Test relative
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str = "m .1.2+0.3.0e0.0e0+6e-1-.3.0 z";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadErrorMisplacedCharacter() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath_good = rectangleBpath;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Comma in the wrong place (commas may only appear between parameters)
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z , m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Comma in the wrong place (commas may only appear between parameters)
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z m,13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Period in the wrong place (no numbers after a 'z')
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z . m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Sign in the wrong place (no numbers after a 'z')
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z + - m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Digit in the wrong place (no numbers after a 'z')
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z 9809 m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Digit in the wrong place (no numbers after a 'z')
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z 9809 876 m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner }
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner void testReadErrorUnrecognizedCharacter() {
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner char const * path_str;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner NArtBpath * bpath_good = rectangleBpath;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath_good[0].code = NR_MOVETO;
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Unrecognized character
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z&m 13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner // Unrecognized character
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner path_str = "M 1,2 4,2 4,8 1,8 z m &13,15";
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner bpath = sp_svg_read_path(path_str);
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner TS_ASSERT(bpathEqual(bpath,bpath_good));
ffbd2f8fa3a83d1d4ad8cd672cf738ffaa5cdfeeapenner g_free(bpath);
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico }
4a7ebbf91a516d588a7dcc45921c17a896b65f62JazzyNico
void testReadErrorTypo() {
char const * path_str;
NArtBpath * bpath;
NArtBpath * bpath_good = rectangleBpath;
bpath_good[0].code = NR_MOVETO;
// Typo
path_str = "M 1,2 4,2 4,8 1,8 z j 13,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
bpath_good[0].code = NR_MOVETO_OPEN;
// Typo
path_str = "M 1,2 4,2 4,8 1,8 L 1,2 x m 13,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
}
void testReadErrorIllformedNumbers() {
char const * path_str;
NArtBpath * bpath;
NArtBpath * bpath_good = rectangleBpath;
bpath_good[0].code = NR_MOVETO;
// Double exponent
path_str = "M 1,2 4,2 4,8 1,8 z m 13e4e5,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// Double sign
path_str = "M 1,2 4,2 4,8 1,8 z m +-13,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// Double sign
path_str = "M 1,2 4,2 4,8 1,8 z m 13e+-12,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m .e12,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m .,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m +,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m +.e+,15";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
}
void testReadErrorJunk() {
char const * path_str;
NArtBpath * bpath;
NArtBpath * bpath_good = rectangleBpath;
bpath_good[0].code = NR_MOVETO;
// Junk
path_str = "M 1,2 4,2 4,8 1,8 z j 357 hkjh.,34e34 90ih6kj4 h5k6vlh4N.,6,45wikuyi3yere..3487 m 13,23";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
}
void testReadErrorStopReading() {
char const * path_str;
NArtBpath * bpath;
NArtBpath * bpath_good = rectangleBpath;
bpath_good[0].code = NR_MOVETO;
// Unrecognized parameter
path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// Invalid parameter
path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
// Illformed parameter
path_str = "M 1,2 4,2 4,8 1,8 z m +-12,23,34";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
bpath_good[0].code = NR_MOVETO_OPEN;
// "Third" parameter
path_str = "M 1,2 4,2 4,8 1,8 1,2,3 M 12,23";
bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,bpath_good));
g_free(bpath);
}
void testRoundTrip() {
// This is the easiest way to (also) test writing path data, as a path can be written in more than one way.
NArtBpath * bpath;
NArtBpath * new_bpath;
char * path_str;
// Rectangle (closed)
bpath = sp_svg_read_path(rectanglesAbsoluteClosed[0].c_str());
path_str = sp_svg_write_path(bpath);
new_bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,new_bpath));
g_free(bpath); g_free(path_str); g_free(new_bpath);
// Rectangle (open)
bpath = sp_svg_read_path(rectanglesAbsoluteOpen[0].c_str());
path_str = sp_svg_write_path(bpath);
new_bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,new_bpath));
g_free(bpath); g_free(path_str); g_free(new_bpath);
// Concatenated rectangles
bpath = sp_svg_read_path((rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0]).c_str());
path_str = sp_svg_write_path(bpath);
new_bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,new_bpath));
g_free(bpath); g_free(path_str); g_free(new_bpath);
// Zero-length subpaths
bpath = sp_svg_read_path("M 0,0 M 1,1 L 2,2 M 3,3 z M 4,4 L 5,5 z M 6,6");
path_str = sp_svg_write_path(bpath);
new_bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath,new_bpath));
g_free(bpath); g_free(path_str); g_free(new_bpath);
// Floating-point
bpath = sp_svg_read_path("M .01,.02 L 0.04,0.02 L.04,.08L0.01,0.08 z""M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L04E-2,.08e0L1.0e-2,80e-3 z");
path_str = sp_svg_write_path(bpath);
new_bpath = sp_svg_read_path(path_str);
TS_ASSERT(bpathEqual(bpath, new_bpath, 1e-17));
g_free(bpath); g_free(path_str); g_free(new_bpath);
}
private:
bool bpathEqual(NArtBpath const * a, NArtBpath const * b, double eps = 1e-16) {
while(a->code != 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 :