svg-path-geom-test.h revision c0537dcfe264414d52ad86579d57cb0cb2183dcb
#include <cxxtest/TestSuite.h>
#include "2geom/pathvector.h"
#include "preferences.h"
#include "streq.h"
#include <stdio.h>
#include <string>
#include <vector>
#include <glib.h>
{
SvgPathGeomTest() {
// Lots of ways to define the same rectangle
// TODO: Should we make it mandatory that h/v in the path data results in a H/VLineSegment?
// If so, the tests should be modified to reflect this.
}
// createSuite and destroySuite get us per-suite setup and teardown
// without us having to worry about static initialization order, etc.
{
}
}
{
}
}
{
}
}
{
}
}
{
}
}
{
}
}
void testReadConcatenatedPaths()
{
// Note that finalPoint doesn't actually return the final point of the path, just the last given point... (but since this might be intentional and we're not testing lib2geom here, we just specify the final point explicitly
pv_good.push_back(rectanglepvopen.back() * Geom::Translate(1,2)/* * Geom::Translate(pv_good[0].finalPoint())*/);
pv_good.push_back(rectanglepvclosed.back() * Geom::Translate(2,4)/* *Geom::Translate(pv_good[1].finalPoint())*/);
std::string path_str = rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0];
}
void testReadZeroLengthSubpaths() {
// Per the SVG 1.1 specification (section F5) zero-length subpaths are relevant
{ // Test absolute version
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";
}
{ // Test relative version
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";
}
}
void testReadImplicitMoveto() {
TS_WARN("Currently lib2geom (/libnr) has no way of specifying the difference between 'M 0,0 ... z M 0,0 L 1,0' and 'M 0,0 ... z L 1,0', the SVG specification does state that these should be handled differently with respect to markers however, see the description of the 'orient' attribute of the 'marker' element.");
{ // Test absolute version
char const * path_str = "M 1,1 L 2,2 z L 3,3 z";
}
{ // Test relative version
char const * path_str = "M 1,1 l 1,1 z l 2,2 z";
}
}
void testReadFloatingPoint() {
{ // Test decimals
char const * path_str = "M .01,.02 L.04.02 L1.5,1.6L0.01,0.08 .01.02 z";
}
{ // Test exponent
char const * path_str = "M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L0150E-2,1.6e0L1.0e-2,80e-3 z";
}
}
void testReadImplicitSeparation() {
// Coordinates need not be separated by whitespace if they can still be read unambiguously
{ // Test absolute
char const * path_str = "M .1.2+0.4.2e0.4e0+8e-1.1.8 z";
}
{ // Test relative
char const * path_str = "m .1.2+0.3.0e0.0e0+6e-1-.3.0 z";
}
}
void testReadErrorMisplacedCharacter() {
char const * path_str;
// Comma in the wrong place (commas may only appear between parameters)
path_str = "M 1,2 4,2 4,8 1,8 z , m 13,15";
// Comma in the wrong place (commas may only appear between parameters)
path_str = "M 1,2 4,2 4,8 1,8 z m,13,15";
// Period in the wrong place (no numbers after a 'z')
path_str = "M 1,2 4,2 4,8 1,8 z . m 13,15";
// Sign in the wrong place (no numbers after a 'z')
path_str = "M 1,2 4,2 4,8 1,8 z + - m 13,15";
// Digit in the wrong place (no numbers after a 'z')
path_str = "M 1,2 4,2 4,8 1,8 z 9809 m 13,15";
// Digit in the wrong place (no numbers after a 'z')
path_str = "M 1,2 4,2 4,8 1,8 z 9809 876 m 13,15";
}
void testReadErrorUnrecognizedCharacter() {
char const * path_str;
// Unrecognized character
path_str = "M 1,2 4,2 4,8 1,8 z&m 13,15";
// Unrecognized character
path_str = "M 1,2 4,2 4,8 1,8 z m &13,15";
}
void testReadErrorTypo() {
char const * path_str;
// Typo
path_str = "M 1,2 4,2 4,8 1,8 z j 13,15";
// Typo
path_str = "M 1,2 4,2 4,8 1,8 L 1,2 x m 13,15";
}
void testReadErrorIllformedNumbers() {
char const * path_str;
// Double exponent
path_str = "M 1,2 4,2 4,8 1,8 z m 13e4e5,15";
// Double sign
path_str = "M 1,2 4,2 4,8 1,8 z m +-13,15";
// Double sign
path_str = "M 1,2 4,2 4,8 1,8 z m 13e+-12,15";
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m .e12,15";
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m .,15";
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m +,15";
// No digit
path_str = "M 1,2 4,2 4,8 1,8 z m +.e+,15";
}
void testReadErrorJunk() {
char const * path_str;
// 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";
}
void testReadErrorStopReading() {
char const * path_str;
// Unrecognized parameter
path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";
// Invalid parameter
path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34";
// Illformed parameter
path_str = "M 1,2 4,2 4,8 1,8 z m +-12,23,34";
// "Third" parameter
path_str = "M 1,2 4,2 4,8 1,8 1,2,3 M 12,23";
}
void testRoundTrip() {
// This is the easiest way to (also) test writing path data, as a path can be written in more than one way.
char * path_str;
// Rectangle (closed)
// Rectangle (open)
// Concatenated rectangles
org_path_str = rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0];
// Zero-length subpaths
org_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";
// Floating-point
org_path_str = "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";
}
void testMinexpPrecision() {
char * path_str;
// Default values
pv = sp_svg_read_pathv("M 123456781,1.23456781e-8 L 123456782,1.23456782e-8 L 123456785,1.23456785e-8 L 10123456400,1.23456785e-8 L 123456789,1.23456789e-8 L 123456789,101.234564e-8 L 123456789,1.23456789e-8");
TS_ASSERT_RELATION( streq_rel , "m 123456780,1.2345678e-8 0,0 10,1e-15 9999999210,0 -9999999210,0 0,9.99999921e-7 0,-9.99999921e-7" , path_str );
}
char temp[100];
sprintf(temp, "PathVectors not the same size: %u != %u", static_cast<unsigned int>(a.size()),static_cast<unsigned int>( b.size()));
return false;
}
char temp[100];
sprintf(temp, "Left subpath is closed, right subpath is open. Subpath: %u", static_cast<unsigned int>(i));
return false;
}
char temp[100];
sprintf(temp, "Right subpath is closed, left subpath is open. Subpath: %u", static_cast<unsigned int>(i));
return false;
}
char temp[100];
sprintf(temp, "Not the same number of segments: %u != %u, subpath: %u", static_cast<unsigned int>(pa.size()), static_cast<unsigned int>(pb.size()), static_cast<unsigned int>(i));
return false;
}
{
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
}
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
}
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
}
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[0][Geom::X], (*la)[0][Geom::Y], (*lb)[0][Geom::X], (*lb)[0][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different 1st control point: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[1][Geom::X], (*la)[1][Geom::Y], (*lb)[1][Geom::X], (*lb)[1][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different 2nd control point: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[2][Geom::X], (*la)[2][Geom::Y], (*lb)[2][Geom::X], (*lb)[2][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la)[3][Geom::X], (*la)[3][Geom::Y], (*lb)[3][Geom::X], (*lb)[3][Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
}
else
{
char temp[200];
sprintf(temp, "Unknown curve type: %s, subpath: %u, segment: %u", typeid(*ca).name(), static_cast<unsigned int>(i), static_cast<unsigned int>(j));
}
}
else // not same type
{
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "A LineSegment and an HLineSegment have been considered equal. Subpath: %u, segment: %u", static_cast<unsigned int>(i), static_cast<unsigned int>(j));
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "A LineSegment and a VLineSegment have been considered equal. Subpath: %u, segment: %u", static_cast<unsigned int>(i), static_cast<unsigned int>(j));
} else {
char temp[200];
sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), static_cast<unsigned int>(i), static_cast<unsigned int>(j));
}
}
{
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "An HLineSegment and a LineSegment have been considered equal. Subpath: %u, segment: %u", static_cast<unsigned int>(i), static_cast<unsigned int>(j));
char temp[200];
sprintf(temp, "Different start of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).initialPoint()[Geom::X], (*la).initialPoint()[Geom::Y], (*lb).initialPoint()[Geom::X], (*lb).initialPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "Different end of segment: (%g,%g) != (%g,%g), subpath: %u, segment: %u", (*la).finalPoint()[Geom::X], (*la).finalPoint()[Geom::Y], (*lb).finalPoint()[Geom::X], (*lb).finalPoint()[Geom::Y], static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
char temp[200];
sprintf(temp, "A VLineSegment and a LineSegment have been considered equal. Subpath: %u, segment: %u", static_cast<unsigned int>(i), static_cast<unsigned int>(j));
} else {
char temp[200];
sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), static_cast<unsigned int>(i), static_cast<unsigned int>(j));
return false;
}
} else {
char temp[200];
sprintf(temp, "Different curve types: %s != %s, subpath: %u, segment: %u", typeid(*ca).name(), typeid(*cb).name(), static_cast<unsigned int>(i), static_cast<unsigned int>(j));
}
}
}
}
return true;
}
};
/*
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:fileencoding=utf-8:textwidth=99 :