summaryrefslogtreecommitdiff
path: root/basegfx/test
diff options
context:
space:
mode:
Diffstat (limited to 'basegfx/test')
-rw-r--r--basegfx/test/basegfx1d.cxx75
-rw-r--r--basegfx/test/basegfx2d.cxx1463
-rw-r--r--basegfx/test/basegfx3d.cxx224
-rw-r--r--basegfx/test/basegfxtools.cxx112
-rw-r--r--basegfx/test/boxclipper.cxx421
-rw-r--r--basegfx/test/clipstate.cxx180
-rw-r--r--basegfx/test/export.map34
-rw-r--r--basegfx/test/genericclipper.cxx161
-rw-r--r--basegfx/test/makefile.mk87
-rw-r--r--basegfx/test/testtools.cxx235
-rw-r--r--basegfx/test/testtools.hxx98
11 files changed, 3090 insertions, 0 deletions
diff --git a/basegfx/test/basegfx1d.cxx b/basegfx/test/basegfx1d.cxx
new file mode 100644
index 000000000000..9b189bd8b236
--- /dev/null
+++ b/basegfx/test/basegfx1d.cxx
@@ -0,0 +1,75 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "cppunit/plugin/TestPlugIn.h"
+#include "postextstl.h"
+
+namespace basegfx1d
+{
+
+class b1drange : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b1drange);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b1drange
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx1d::b1drange);
+} // namespace basegfx1d
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/basegfx/test/basegfx2d.cxx b/basegfx/test/basegfx2d.cxx
new file mode 100644
index 000000000000..53501d190c03
--- /dev/null
+++ b/basegfx/test/basegfx2d.cxx
@@ -0,0 +1,1463 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/curve/b2dbeziertools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/color/bcolortools.hxx>
+
+#include <basegfx/tools/debugplotter.hxx>
+
+#include <iostream>
+#include <fstream>
+
+using namespace ::basegfx;
+
+
+namespace basegfx2d
+{
+
+class b2dsvgdimpex : public CppUnit::TestFixture
+{
+private:
+ ::rtl::OUString aPath0;
+ ::rtl::OUString aPath1;
+ ::rtl::OUString aPath2;
+ ::rtl::OUString aPath3;
+
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ // simple rectangle
+ aPath0 = ::rtl::OUString::createFromAscii(
+ "M 10 10-10 10-10-10 10-10Z" );
+
+ // simple bezier polygon
+ aPath1 = ::rtl::OUString::createFromAscii(
+ "m11430 0c-8890 3810 5715 6985 5715 6985 "
+ "0 0-17145-1905-17145-1905 0 0 22860-10160 "
+ "16510 6350-6350 16510-3810-11430-3810-11430z" );
+
+ // '@' as a bezier polygon
+ aPath2 = ::rtl::OUString::createFromAscii(
+ "m1917 1114c-89-189-233-284-430-284-167 "
+ "0-306 91-419 273-113 182-170 370-170 564 "
+ "0 145 33 259 98 342 65 84 150 126 257 126 "
+ "77 0 154-19 231-57 77-38 147-97 210-176 63"
+ "-79 99-143 109-190 38-199 76-398 114-598z"
+ "m840 1646c-133 73-312 139-537 197-225 57"
+ "-440 86-644 87-483-1-866-132-1150-392-284"
+ "-261-426-619-426-1076 0-292 67-560 200-803 "
+ "133-243 321-433 562-569 241-136 514-204 821"
+ "-204 405 0 739 125 1003 374 264 250 396 550 "
+ "396 899 0 313-88 576-265 787-177 212-386 318"
+ "-627 318-191 0-308-94-352-281-133 187-315 281"
+ "-546 281-172 0-315-67-428-200-113-133-170-301"
+ "-170-505 0-277 90-527 271-751 181-223 394"
+ "-335 640-335 196 0 353 83 470 250 13-68 26"
+ "-136 41-204 96 0 192 0 288 0-74 376-148 752"
+ "-224 1128-21 101-31 183-31 245 0 39 9 70 26 "
+ "93 17 24 39 36 67 36 145 0 279-80 400-240 121"
+ "-160 182-365 182-615 0-288-107-533-322-734"
+ "-215-201-487-301-816-301-395 0-715 124-960 "
+ "373-245 249-368 569-368 958 0 385 119 685 "
+ "357 900 237 216 557 324 958 325 189-1 389-27 "
+ "600-77 211-52 378-110 503-174 27 70 54 140 81 210z" );
+
+ // first part of 'Hello World' as a line polygon
+ aPath3 = ::rtl::OUString::createFromAscii(
+ "m1598 125h306v2334h-306v-1105h-1293v1105h-305v"
+ "-2334h305v973h1293zm2159 1015 78-44 85 235-91 "
+ "47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102"
+ "-4-97-12-91-19-85-26-40-16-39-18-38-20-36-22-34"
+ "-24-33-26-32-27-30-30-29-31-27-33-25-33-23-36-21"
+ "-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3"
+ "-98 11-94 17-89 24-84 31-79 37-75 22-35 23-34 24"
+ "-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35"
+ "-18 37-17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 "
+ "78 10 37 9 37 9 36 12 35 14 33 15 33 17 32 19 31 "
+ "21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 "
+ "34 18 36 30 74 23 80 17 84 10 89 3 94v78h-1277l6 "
+ "75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 "
+ "23 17 22 19 21 19 20 21 18 21 18 23 16 23 14 24 "
+ "14 26 12 26 11 27 10 28 8 59 13 63 7 67 3 80-3 81"
+ "-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l"
+ "-7-51-11-49-14-46-17-43-21-40-24-38-27-36-31-32"
+ "-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 "
+ "2-46 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32"
+ "-29 34-26 38-23 41-20 44-17 47zm1648-1293h288v"
+ "2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 "
+ "91-4 91 4 85 12 42 8 39 11 39 13 38 14 36 17 35 18 "
+ "34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 23 "
+ "34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100"
+ "-11 95-16 89-24 85-31 80-37 74-21 35-23 35-25 32-26 "
+ "32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17"
+ "-38 14-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9"
+ "-40-10-39-13-37-14-36-17-35-18-34-21-33-22-31-24-30"
+ "-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80"
+ "-24-85-17-89-11-95-3-100 3-101 11-95 17-90 24-85 30"
+ "-79 38-75 21-35 23-35 25-32 26-32 28-30 29-28 30-26 "
+ "31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z" );
+ }
+
+ void tearDown()
+ {
+ }
+
+ void impex()
+ {
+ B2DPolyPolygon aPoly;
+ ::rtl::OUString aExport;
+
+ CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D",
+ tools::importFromSvgD( aPoly,
+ aPath0 ));
+ aExport = tools::exportToSvgD( aPoly );
+ const char* sExportString = "m10 10h-20v-20h20z";
+ CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D",
+ !aExport.compareToAscii(sExportString) );
+ CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip",
+ tools::importFromSvgD( aPoly,
+ aExport ));
+ aExport = tools::exportToSvgD( aPoly );
+ CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D (round-trip)",
+ !aExport.compareToAscii(sExportString));
+
+ CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D",
+ tools::importFromSvgD( aPoly,
+ aPath1 ));
+ aExport = tools::exportToSvgD( aPoly );
+
+ // Adaptions for B2DPolygon bezier change (see #i77162#):
+ //
+ // The import/export of aPath1 does not reproduce aExport again. This is
+ // correct since aPath1 contains a segment with non-used control points
+ // which gets exported now correctly as 'l' and also a point (#4, index 3)
+ // with C2 continuity which produces a 's' staement now.
+ //
+ // The old SVGexport identified nun-used ControlVectors erraneously as bezier segments
+ // because the 2nd vector at the start point was used, even when added
+ // with start point was identical to end point. Exactly for that reason
+ // i reworked the B2DPolygon to use prev, next control points.
+ //
+ // so for correct unit test i add the new exported string here as sExportStringSimpleBezier
+ // and compare to it.
+ const char* sExportStringSimpleBezier =
+ "m11430 0c-8890 3810 5715 6985 5715 6985"
+ "l-17145-1905c0 0 22860-10160 16510 6350"
+ "s-3810-11430-3810-11430z";
+ CPPUNIT_ASSERT_MESSAGE("exporting bezier polygon to SVG-D", !aExport.compareToAscii(sExportStringSimpleBezier));
+
+ // Adaptions for B2DPolygon bezier change (see #i77162#):
+ //
+ // a 2nd good test is that re-importing of aExport has to create the same
+ // B2DPolPolygon again:
+ B2DPolyPolygon aReImport;
+ CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport));
+ CPPUNIT_ASSERT_MESSAGE("re-imported polygon needs to be identical", aReImport == aPoly);
+
+ CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2 ));
+ aExport = tools::exportToSvgD( aPoly );
+
+ // Adaptions for B2DPolygon bezier change (see #i77162#):
+ //
+ // same here, the corrected export with the corrected B2DPolygon is simply more efficient,
+ // so i needed to change the compare string. Also adding the re-import comparison below.
+ const char* sExportString1 =
+ "m1917 1114c-89-189-233-284-430-284-167 0-306 91-419 273s-170 370-17"
+ "0 564c0 145 33 259 98 342 65 84 150 126 257 126q115.5 0 231-57s147-97 210-176 99-143 109-190c38-199 76-398 114"
+ "-598zm840 1646c-133 73-312 139-537 197-225 57-440 86-644 87-483-1-866-132-1150-392-284-261-426-619-426-1076 0-"
+ "292 67-560 200-803s321-433 562-569 514-204 821-204c405 0 739 125 1003 374 264 250 396 550 396 899 0 313-88 576"
+ "-265 787q-265.5 318-627 318c-191 0-308-94-352-281-133 187-315 281-546 281-172 0-315-67-428-200s-170-301-170-50"
+ "5c0-277 90-527 271-751 181-223 394-335 640-335 196 0 353 83 470 250 13-68 26-136 41-204q144 0 288 0c-74 376-14"
+ "8 752-224 1128-21 101-31 183-31 245 0 39 9 70 26 93 17 24 39 36 67 36 145 0 279-80 400-240s182-365 182-615c0-2"
+ "88-107-533-322-734s-487-301-816-301c-395 0-715 124-960 373s-368 569-368 958q0 577.5 357 900c237 216 557 324 95"
+ "8 325 189-1 389-27 600-77 211-52 378-110 503-174q40.5 105 81 210z";
+ CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport));
+ CPPUNIT_ASSERT_MESSAGE("re-imported '@' needs to be identical", aReImport == aPoly);
+
+ CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D", !aExport.compareToAscii(sExportString1));
+ CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip",
+ tools::importFromSvgD( aPoly,
+ aExport ));
+ aExport = tools::exportToSvgD( aPoly );
+ CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D (round-trip)",
+ !aExport.compareToAscii(sExportString1));
+
+
+ CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D",
+ tools::importFromSvgD( aPoly,
+ aPath3 ));
+ aExport = tools::exportToSvgD( aPoly );
+ const char* sExportString2 =
+ "m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293"
+ "zm2159 1015 78-44 85 235-91 47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102-4-97"
+ "-12-91-19-85-26-40-16-39-18-38-20-36-22-34-24-33-26-32-27-30-30-29-31-27-33-25-3"
+ "3-23-36-21-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3-98 11-94 17-89 24-84 3"
+ "1-79 37-75 22-35 23-34 24-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35-18 37-"
+ "17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 78 10 37 9 37 9 36 12 35 14 33 15 33 1"
+ "7 32 19 31 21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 34 18 36 30 74 23 80 "
+ "17 84 10 89 3 94v78h-1277l6 75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 23 1"
+ "7 22 19 21 19 20 21 18 21 18 23 16 23 14 24 14 26 12 26 11 27 10 28 8 59 13 63 7"
+ " 67 3 80-3 81-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l-7-51-11-49-14-46-1"
+ "7-43-21-40-24-38-27-36-31-32-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 2-4"
+ "6 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32-29 34-26 38-23 41-20 44-17 47zm1648"
+ "-1293h288v2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 91-4 91 4 85 12 42 "
+ "8 39 11 39 13 38 14 36 17 35 18 34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 "
+ "23 34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100-11 95-16 89-24 85-31 80-37"
+ " 74-21 35-23 35-25 32-26 32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17-38 1"
+ "4-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9-40-10-39-13-37-14-36-17-35-18-34-2"
+ "1-33-22-31-24-30-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80-24-85-17-89-"
+ "11-95-3-100 3-101 11-95 17-90 24-85 30-79 38-75 21-35 23-35 25-32 26-32 28-30 29"
+ "-28 30-26 31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z";
+ CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D",
+ !aExport.compareToAscii(sExportString2));
+ CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip",
+ tools::importFromSvgD( aPoly,
+ aExport ));
+ aExport = tools::exportToSvgD( aPoly );
+ CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D (round-trip)",
+ !aExport.compareToAscii(sExportString2));
+
+ const B2DPolygon aRect(
+ tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));
+ aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false);
+
+ const char* sExportStringRect = "M0 0H4000V4000H0Z";
+ CPPUNIT_ASSERT_MESSAGE("exporting to rectangle svg-d string",
+ !aExport.compareToAscii(sExportStringRect));
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dsvgdimpex);
+ CPPUNIT_TEST(impex);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dsvgdimpex
+
+class b2dpolyrange : public CppUnit::TestFixture
+{
+private:
+public:
+ void setUp()
+ {}
+
+ void tearDown()
+ {}
+
+ void check()
+ {
+ B2DPolyRange aRange;
+ aRange.appendElement(B2DRange(0,0,1,1),ORIENTATION_POSITIVE);
+ aRange.appendElement(B2DRange(2,2,3,3),ORIENTATION_POSITIVE);
+
+ CPPUNIT_ASSERT_MESSAGE("simple poly range - count",
+ aRange.count() == 2);
+ CPPUNIT_ASSERT_MESSAGE("simple poly range - first element",
+ aRange.getElement(0).head == B2DRange(0,0,1,1));
+ CPPUNIT_ASSERT_MESSAGE("simple poly range - second element",
+ aRange.getElement(1).head == B2DRange(2,2,3,3));
+
+ // B2DPolyRange relies on correctly orientated rects
+ const B2DRange aRect(0,0,1,1);
+ CPPUNIT_ASSERT_MESSAGE("createPolygonFromRect - correct orientation",
+ tools::getOrientation(
+ tools::createPolygonFromRect(aRect)) == ORIENTATION_POSITIVE );
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dpolyrange);
+ CPPUNIT_TEST(check);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+class b2dbeziertools : public CppUnit::TestFixture
+{
+private:
+ B2DCubicBezier aHalfCircle; // not exactly, but a look-alike
+ B2DCubicBezier aQuarterCircle; // not exactly, but a look-alike
+ B2DCubicBezier aLoop; // identical endpoints, curve goes back to where it started
+ B2DCubicBezier aStraightLineDistinctEndPoints; // truly a line
+ B2DCubicBezier aStraightLineDistinctEndPoints2; // truly a line, with slightly different control points
+ B2DCubicBezier aStraightLineIdenticalEndPoints; // degenerate case of aLoop
+ B2DCubicBezier aStraightLineIdenticalEndPoints2;// degenerate case of aLoop, with slightly different control points
+ B2DCubicBezier aCrossing; // curve self-intersects somewhere in the middle
+ B2DCubicBezier aCusp; // curve has a point of undefined tangency
+
+
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ const B2DPoint a00(0.0, 0.0);
+ const B2DPoint a10(1.0, 0.0);
+ const B2DPoint a11(1.0, 1.0);
+ const B2DPoint a01(0.0, 1.0);
+ const B2DPoint middle( 0.5, 0.5 );
+ const B2DPoint quarterDown( 0.25, 0.25 );
+ const B2DPoint quarterUp( 0.75, 0.75 );
+
+ aHalfCircle = B2DCubicBezier(a00, a01, a11, a10);
+
+ // The spline control points become
+ //
+ // (R * cos(A), R * sin(A))
+ // (R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
+ // (R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
+ // (R * cos(B), R * sin(B))
+ //
+ // where h = 4/3 * R * tan ((B-A)/4)
+ //
+ // with R being the radius, A start angle and B end angle (A < B).
+ //
+ // (This calculation courtesy Carl Worth, himself based on
+ // Michael Goldapp and Dokken/Daehlen)
+
+ // Choosing R=1, A=0, B=pi/2
+ const double h( 4.0/3.0 * tan(M_PI/8.0) );
+ aQuarterCircle = B2DCubicBezier(a10 + B2DPoint(1.0,0.0),
+ B2DPoint(B2DPoint( 1.0, h ) + B2DPoint(1.0,0.0)),
+ B2DPoint(B2DPoint( h, 1.0) + B2DPoint(1.0,0.0)),
+ a01 + B2DPoint(1.0,0.0));
+
+ aCusp = B2DCubicBezier(a00 + B2DPoint(2.0,0.0),
+ B2DPoint(a11 + B2DPoint(2.0,0.0)),
+ B2DPoint(a01 + B2DPoint(2.0,0.0)),
+ a10 + B2DPoint(2.0,0.0));
+
+ aLoop = B2DCubicBezier(a00 + B2DPoint(3.0,0.0),
+ B2DPoint(a01 + B2DPoint(3.0,0.0)),
+ B2DPoint(a10 + B2DPoint(3.0,0.0)),
+ a00 + B2DPoint(3.0,0.0));
+
+ aStraightLineDistinctEndPoints = B2DCubicBezier(a00 + B2DPoint(4.0,0.0),
+ B2DPoint(middle + B2DPoint(4.0,0.0)),
+ B2DPoint(middle + B2DPoint(4.0,0.0)),
+ a11 + B2DPoint(4.0,0.0));
+
+ aStraightLineDistinctEndPoints2 = B2DCubicBezier(a00 + B2DPoint(5.0,0.0),
+ B2DPoint(quarterDown + B2DPoint(5.0,0.0)),
+ B2DPoint(quarterUp + B2DPoint(5.0,0.0)),
+ a11 + B2DPoint(5.0,0.0));
+
+ aStraightLineIdenticalEndPoints = B2DCubicBezier(a00 + B2DPoint(6.0,0.0),
+ B2DPoint(a11 + B2DPoint(6.0,0.0)),
+ B2DPoint(a11 + B2DPoint(6.0,0.0)),
+ a00 + B2DPoint(6.0,0.0));
+
+ aStraightLineIdenticalEndPoints2 = B2DCubicBezier(a00 + B2DPoint(7.0,0.0),
+ B2DPoint(quarterDown + B2DPoint(7.0,0.0)),
+ B2DPoint(quarterUp + B2DPoint(7.0,0.0)),
+ a00 + B2DPoint(7.0,0.0));
+
+ aCrossing = B2DCubicBezier(a00 + B2DPoint(8.0,0.0),
+ B2DPoint(B2DPoint(2.0,2.0) + B2DPoint(8.0,0.0)),
+ B2DPoint(B2DPoint(-1.0,2.0) + B2DPoint(8.0,0.0)),
+ a10 + B2DPoint(8.0,0.0));
+
+ ::std::ofstream output("bez_testcases.gnuplot");
+ DebugPlotter aPlotter( "Original curves",
+ output );
+
+ aPlotter.plot( aHalfCircle,
+ "half circle" );
+ aPlotter.plot( aQuarterCircle,
+ "quarter circle" );
+ aPlotter.plot( aCusp,
+ "cusp" );
+ aPlotter.plot( aLoop,
+ "loop" );
+ aPlotter.plot( aStraightLineDistinctEndPoints,
+ "straight line 0" );
+ aPlotter.plot( aStraightLineDistinctEndPoints2,
+ "straight line 1" );
+ aPlotter.plot( aStraightLineIdenticalEndPoints,
+ "straight line 2" );
+ aPlotter.plot( aStraightLineIdenticalEndPoints2,
+ "straight line 3" );
+ aPlotter.plot( aCrossing,
+ "crossing" );
+
+ // break up a complex bezier (loopy, spiky or self intersecting)
+ // into simple segments (left to right)
+ B2DCubicBezier aSegment = aCrossing;
+ double fExtremePos(0.0);
+
+ aPlotter.plot( aSegment, "segment" );
+ while(aSegment.getMinimumExtremumPosition(fExtremePos))
+ {
+ aSegment.split(fExtremePos, 0, &aSegment);
+ aPlotter.plot( aSegment, "segment" );
+ }
+ }
+
+ void tearDown()
+ {
+ }
+
+ void adaptiveByDistance()
+ {
+ ::std::ofstream output("bez_adaptiveByDistance.gnuplot");
+ DebugPlotter aPlotter( "distance-adaptive subdivision",
+ output );
+
+ const double fBound( 0.0001 );
+ B2DPolygon result;
+
+ aHalfCircle.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "half circle"); result.clear();
+
+ aQuarterCircle.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "quarter circle"); result.clear();
+
+ aLoop.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "loop"); result.clear();
+
+ aStraightLineDistinctEndPoints.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 0"); result.clear();
+
+ aStraightLineDistinctEndPoints2.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 1"); result.clear();
+
+ aStraightLineIdenticalEndPoints.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 2"); result.clear();
+
+ aStraightLineIdenticalEndPoints2.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 3"); result.clear();
+
+ aCrossing.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 4"); result.clear();
+
+ aCusp.adaptiveSubdivideByDistance(result, fBound);
+ aPlotter.plot(result,
+ "straight line 5"); result.clear();
+
+ CPPUNIT_ASSERT_MESSAGE("adaptiveByDistance", true );
+ }
+
+ void adaptiveByAngle()
+ {
+ const double fBound( 5.0 );
+ B2DPolygon result;
+
+ ::std::ofstream output("bez_adaptiveByAngle.gnuplot");
+ DebugPlotter aPlotter( "angle-adaptive subdivision",
+ output );
+
+ aHalfCircle.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "half circle"); result.clear();
+
+ aQuarterCircle.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "quarter cirle"); result.clear();
+
+ aLoop.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "loop"); result.clear();
+
+ aStraightLineDistinctEndPoints.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 0"); result.clear();
+
+ aStraightLineDistinctEndPoints2.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 1"); result.clear();
+
+ aStraightLineIdenticalEndPoints.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 2"); result.clear();
+
+ aStraightLineIdenticalEndPoints2.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 3"); result.clear();
+
+ aCrossing.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 4"); result.clear();
+
+ aCusp.adaptiveSubdivideByAngle(result, fBound, true);
+ aPlotter.plot(result,
+ "straight line 5"); result.clear();
+
+ CPPUNIT_ASSERT_MESSAGE("adaptiveByAngle", true );
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dbeziertools);
+ CPPUNIT_TEST(adaptiveByDistance); // TODO: add tests for quadratic bezier (subdivide and degree reduction)
+ CPPUNIT_TEST(adaptiveByAngle);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dcubicbezier
+
+
+class b2dcubicbezier : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ // this is demonstration code
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dcubicbezier);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dcubicbezier
+
+
+class b2dhommatrix : public CppUnit::TestFixture
+{
+private:
+ B2DHomMatrix maIdentity;
+ B2DHomMatrix maScale;
+ B2DHomMatrix maTranslate;
+ B2DHomMatrix maShear;
+ B2DHomMatrix maAffine;
+ B2DHomMatrix maPerspective;
+
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ // setup some test matrices
+ maIdentity.identity(); // force compact layout
+ maIdentity.set(0,0, 1.0);
+ maIdentity.set(0,1, 0.0);
+ maIdentity.set(0,2, 0.0);
+ maIdentity.set(1,0, 0.0);
+ maIdentity.set(1,1, 1.0);
+ maIdentity.set(1,2, 0.0);
+
+ maScale.identity(); // force compact layout
+ maScale.set(0,0, 2.0);
+ maScale.set(1,1, 20.0);
+
+ maTranslate.identity(); // force compact layout
+ maTranslate.set(0,2, 20.0);
+ maTranslate.set(1,2, 2.0);
+
+ maShear.identity(); // force compact layout
+ maShear.set(0,1, 3.0);
+ maShear.set(1,0, 7.0);
+ maShear.set(1,1, 22.0);
+
+ maAffine.identity(); // force compact layout
+ maAffine.set(0,0, 1.0);
+ maAffine.set(0,1, 2.0);
+ maAffine.set(0,2, 3.0);
+ maAffine.set(1,0, 4.0);
+ maAffine.set(1,1, 5.0);
+ maAffine.set(1,2, 6.0);
+
+ maPerspective.set(0,0, 1.0);
+ maPerspective.set(0,1, 2.0);
+ maPerspective.set(0,2, 3.0);
+ maPerspective.set(1,0, 4.0);
+ maPerspective.set(1,1, 5.0);
+ maPerspective.set(1,2, 6.0);
+ maPerspective.set(2,0, 7.0);
+ maPerspective.set(2,1, 8.0);
+ maPerspective.set(2,2, 9.0);
+ }
+
+ void tearDown()
+ {
+ }
+
+ void equal()
+ {
+ B2DHomMatrix aIdentity;
+ B2DHomMatrix aScale;
+ B2DHomMatrix aTranslate;
+ B2DHomMatrix aShear;
+ B2DHomMatrix aAffine;
+ B2DHomMatrix aPerspective;
+
+ // setup some test matrices
+ aIdentity.identity(); // force compact layout
+ aIdentity.set(0,0, 1.0);
+ aIdentity.set(0,1, 0.0);
+ aIdentity.set(0,2, 0.0);
+ aIdentity.set(1,0, 0.0);
+ aIdentity.set(1,1, 1.0);
+ aIdentity.set(1,2, 0.0);
+
+ aScale.identity(); // force compact layout
+ aScale.set(0,0, 2.0);
+ aScale.set(1,1, 20.0);
+
+ aTranslate.identity(); // force compact layout
+ aTranslate.set(0,2, 20.0);
+ aTranslate.set(1,2, 2.0);
+
+ aShear.identity(); // force compact layout
+ aShear.set(0,1, 3.0);
+ aShear.set(1,0, 7.0);
+ aShear.set(1,1, 22.0);
+
+ aAffine.identity(); // force compact layout
+ aAffine.set(0,0, 1.0);
+ aAffine.set(0,1, 2.0);
+ aAffine.set(0,2, 3.0);
+ aAffine.set(1,0, 4.0);
+ aAffine.set(1,1, 5.0);
+ aAffine.set(1,2, 6.0);
+
+ aPerspective.set(0,0, 1.0);
+ aPerspective.set(0,1, 2.0);
+ aPerspective.set(0,2, 3.0);
+ aPerspective.set(1,0, 4.0);
+ aPerspective.set(1,1, 5.0);
+ aPerspective.set(1,2, 6.0);
+ aPerspective.set(2,0, 7.0);
+ aPerspective.set(2,1, 8.0);
+ aPerspective.set(2,2, 9.0);
+
+ CPPUNIT_ASSERT_MESSAGE("operator==: identity matrix", aIdentity == maIdentity);
+ CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale == maScale);
+ CPPUNIT_ASSERT_MESSAGE("operator==: translate matrix", aTranslate == maTranslate);
+ CPPUNIT_ASSERT_MESSAGE("operator==: shear matrix", aShear == maShear);
+ CPPUNIT_ASSERT_MESSAGE("operator==: affine matrix", aAffine == maAffine);
+ CPPUNIT_ASSERT_MESSAGE("operator==: perspective matrix", aPerspective == maPerspective);
+ }
+
+ void identity()
+ {
+ B2DHomMatrix ident;
+
+ CPPUNIT_ASSERT_MESSAGE("identity", maIdentity == ident);
+ }
+
+ void scale()
+ {
+ B2DHomMatrix mat;
+ mat.scale(2.0,20.0);
+ CPPUNIT_ASSERT_MESSAGE("scale", maScale == mat);
+ }
+
+ void translate()
+ {
+ B2DHomMatrix mat;
+ mat.translate(20.0,2.0);
+ CPPUNIT_ASSERT_MESSAGE("translate", maTranslate == mat);
+ }
+
+ void shear()
+ {
+ B2DHomMatrix mat;
+ mat.shearX(3.0);
+ mat.shearY(7.0);
+ CPPUNIT_ASSERT_MESSAGE("translate", maShear == mat);
+ }
+
+ void multiply()
+ {
+ B2DHomMatrix affineAffineProd;
+
+ affineAffineProd.set(0,0, 9);
+ affineAffineProd.set(0,1, 12);
+ affineAffineProd.set(0,2, 18);
+ affineAffineProd.set(1,0, 24);
+ affineAffineProd.set(1,1, 33);
+ affineAffineProd.set(1,2, 48);
+
+ B2DHomMatrix affinePerspectiveProd;
+
+ affinePerspectiveProd.set(0,0, 30);
+ affinePerspectiveProd.set(0,1, 36);
+ affinePerspectiveProd.set(0,2, 42);
+ affinePerspectiveProd.set(1,0, 66);
+ affinePerspectiveProd.set(1,1, 81);
+ affinePerspectiveProd.set(1,2, 96);
+ affinePerspectiveProd.set(2,0, 7);
+ affinePerspectiveProd.set(2,1, 8);
+ affinePerspectiveProd.set(2,2, 9);
+
+ B2DHomMatrix perspectiveAffineProd;
+
+ perspectiveAffineProd.set(0,0, 9);
+ perspectiveAffineProd.set(0,1, 12);
+ perspectiveAffineProd.set(0,2, 18);
+ perspectiveAffineProd.set(1,0, 24);
+ perspectiveAffineProd.set(1,1, 33);
+ perspectiveAffineProd.set(1,2, 48);
+ perspectiveAffineProd.set(2,0, 39);
+ perspectiveAffineProd.set(2,1, 54);
+ perspectiveAffineProd.set(2,2, 78);
+
+ B2DHomMatrix perspectivePerspectiveProd;
+
+ perspectivePerspectiveProd.set(0,0, 30);
+ perspectivePerspectiveProd.set(0,1, 36);
+ perspectivePerspectiveProd.set(0,2, 42);
+ perspectivePerspectiveProd.set(1,0, 66);
+ perspectivePerspectiveProd.set(1,1, 81);
+ perspectivePerspectiveProd.set(1,2, 96);
+ perspectivePerspectiveProd.set(2,0, 102);
+ perspectivePerspectiveProd.set(2,1, 126);
+ perspectivePerspectiveProd.set(2,2, 150);
+
+ B2DHomMatrix temp;
+
+ temp = maAffine;
+ temp*=maAffine;
+ CPPUNIT_ASSERT_MESSAGE("multiply: both compact", temp == affineAffineProd);
+
+ temp = maPerspective;
+ temp*=maAffine;
+ CPPUNIT_ASSERT_MESSAGE("multiply: first compact", temp == affinePerspectiveProd);
+
+ temp = maAffine;
+ temp*=maPerspective;
+ CPPUNIT_ASSERT_MESSAGE("multiply: second compact", temp == perspectiveAffineProd);
+
+ temp = maPerspective;
+ temp*=maPerspective;
+ CPPUNIT_ASSERT_MESSAGE("multiply: none compact", temp == perspectivePerspectiveProd);
+ }
+
+ void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, double fRotate)
+ {
+ // fill rSource with a linear combination of scale, shear and rotate
+ rSource.identity();
+ rSource.scale(fScaleX, fScaleY);
+ rSource.shearX(fShearX);
+ rSource.rotate(fRotate);
+ }
+
+ bool impDecomposeComposeTest(double fScaleX, double fScaleY, double fShearX, double fRotate)
+ {
+ // linear combine matrix with given values
+ B2DHomMatrix aSource;
+ impFillMatrix(aSource, fScaleX, fScaleY, fShearX, fRotate);
+
+ // decompose that matrix
+ B2DTuple aDScale;
+ B2DTuple aDTrans;
+ double fDRot;
+ double fDShX;
+ bool bWorked = aSource.decompose(aDScale, aDTrans, fDRot, fDShX);
+
+ // linear combine another matrix with decomposition results
+ B2DHomMatrix aRecombined;
+ impFillMatrix(aRecombined, aDScale.getX(), aDScale.getY(), fDShX, fDRot);
+
+ // if decomposition worked, matrices need to be the same
+ return bWorked && aSource == aRecombined;
+ }
+
+ void decompose()
+ {
+ // test matrix decompositions. Each matrix decomposed and rebuilt
+ // using the decompose result should be the same as before. Test
+ // with all ranges of values. Translations are not tested since these
+ // are just the two rightmost values and uncritical
+ static double fSX(10.0);
+ static double fSY(12.0);
+ static double fR(45.0 * F_PI180);
+ static double fS(15.0 * F_PI180);
+
+ // check all possible scaling combinations
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test A1", impDecomposeComposeTest(fSX, fSY, 0.0, 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test A2", impDecomposeComposeTest(-fSX, fSY, 0.0, 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test A3", impDecomposeComposeTest(fSX, -fSY, 0.0, 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test A4", impDecomposeComposeTest(-fSX, -fSY, 0.0, 0.0));
+
+ // check all possible scaling combinations with positive rotation
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test B1", impDecomposeComposeTest(fSX, fSY, 0.0, fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test B2", impDecomposeComposeTest(-fSX, fSY, 0.0, fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test B3", impDecomposeComposeTest(fSX, -fSY, 0.0, fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test B4", impDecomposeComposeTest(-fSX, -fSY, 0.0, fR));
+
+ // check all possible scaling combinations with negative rotation
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test C1", impDecomposeComposeTest(fSX, fSY, 0.0, -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test C2", impDecomposeComposeTest(-fSX, fSY, 0.0, -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test C3", impDecomposeComposeTest(fSX, -fSY, 0.0, -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test C4", impDecomposeComposeTest(-fSX, -fSY, 0.0, -fR));
+
+ // check all possible scaling combinations with positive shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test D1", impDecomposeComposeTest(fSX, fSY, tan(fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test D2", impDecomposeComposeTest(-fSX, fSY, tan(fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test D3", impDecomposeComposeTest(fSX, -fSY, tan(fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test D4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), 0.0));
+
+ // check all possible scaling combinations with negative shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test E1", impDecomposeComposeTest(fSX, fSY, tan(-fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test E2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test E3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), 0.0));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test E4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), 0.0));
+
+ // check all possible scaling combinations with positive rotate and positive shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test F1", impDecomposeComposeTest(fSX, fSY, tan(fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test F2", impDecomposeComposeTest(-fSX, fSY, tan(fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test F3", impDecomposeComposeTest(fSX, -fSY, tan(fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test F4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), fR));
+
+ // check all possible scaling combinations with negative rotate and positive shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test G1", impDecomposeComposeTest(fSX, fSY, tan(fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test G2", impDecomposeComposeTest(-fSX, fSY, tan(fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test G3", impDecomposeComposeTest(fSX, -fSY, tan(fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test G4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), -fR));
+
+ // check all possible scaling combinations with positive rotate and negative shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test H1", impDecomposeComposeTest(fSX, fSY, tan(-fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test H2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test H3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test H4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), fR));
+
+ // check all possible scaling combinations with negative rotate and negative shear
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test I1", impDecomposeComposeTest(fSX, fSY, tan(-fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test I2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test I3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), -fR));
+ CPPUNIT_ASSERT_MESSAGE("decompose: error test I4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), -fR));
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dhommatrix);
+ CPPUNIT_TEST(equal);
+ CPPUNIT_TEST(identity);
+ CPPUNIT_TEST(scale);
+ CPPUNIT_TEST(translate);
+ CPPUNIT_TEST(shear);
+ CPPUNIT_TEST(multiply);
+ CPPUNIT_TEST(decompose);
+ CPPUNIT_TEST_SUITE_END();
+
+}; // class b2dhommatrix
+
+
+class b2dhompoint : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dhompoint);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dhompoint
+
+
+class b2dpoint : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dpoint);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpoint
+
+
+class b2dpolygon : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void testBasics()
+ {
+ B2DPolygon aPoly;
+
+ aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
+
+ CPPUNIT_ASSERT_MESSAGE("#1 first polygon point wrong",
+ aPoly.getB2DPoint(0) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("#1 first control point wrong",
+ aPoly.getPrevControlPoint(0) == B2DPoint(2,2));
+ CPPUNIT_ASSERT_MESSAGE("#1 second control point wrong",
+ aPoly.getNextControlPoint(0) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("next control point not used",
+ aPoly.isNextControlPointUsed(0) == false);
+
+ aPoly.setNextControlPoint(0,B2DPoint(4,4));
+ CPPUNIT_ASSERT_MESSAGE("#1.1 second control point wrong",
+ aPoly.getNextControlPoint(0) == B2DPoint(4,4));
+ CPPUNIT_ASSERT_MESSAGE("next control point used",
+ aPoly.isNextControlPointUsed(0) == true);
+ CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong",
+ aPoly.areControlPointsUsed() == true);
+ CPPUNIT_ASSERT_MESSAGE("getContinuityInPoint() wrong",
+ aPoly.getContinuityInPoint(0) == CONTINUITY_C2);
+
+ aPoly.resetControlPoints();
+ CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
+ aPoly.getB2DPoint(0) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
+ aPoly.getPrevControlPoint(0) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
+ aPoly.getNextControlPoint(0) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong #2",
+ aPoly.areControlPointsUsed() == false);
+
+ aPoly.clear();
+ aPoly.append(B2DPoint(0,0));
+ aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
+
+ CPPUNIT_ASSERT_MESSAGE("#2 first polygon point wrong",
+ aPoly.getB2DPoint(0) == B2DPoint(0,0));
+ CPPUNIT_ASSERT_MESSAGE("#2 first control point wrong",
+ aPoly.getPrevControlPoint(0) == B2DPoint(0,0));
+ CPPUNIT_ASSERT_MESSAGE("#2 second control point wrong",
+ aPoly.getNextControlPoint(0) == B2DPoint(1,1));
+ CPPUNIT_ASSERT_MESSAGE("#2 third control point wrong",
+ aPoly.getPrevControlPoint(1) == B2DPoint(2,2));
+ CPPUNIT_ASSERT_MESSAGE("#2 fourth control point wrong",
+ aPoly.getNextControlPoint(1) == B2DPoint(3,3));
+ CPPUNIT_ASSERT_MESSAGE("#2 second polygon point wrong",
+ aPoly.getB2DPoint(1) == B2DPoint(3,3));
+ }
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dpolygon);
+ CPPUNIT_TEST(testBasics);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpolygon
+
+
+class b2dpolygontools : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void testIsRectangle()
+ {
+ B2DPolygon aRect1(
+ tools::createPolygonFromRect(
+ B2DRange(0,0,1,1) ) );
+
+ B2DPolygon aRect2;
+ aRect2.append( B2DPoint(0,0) );
+ aRect2.append( B2DPoint(1,0) );
+ aRect2.append( B2DPoint(1,.5));
+ aRect2.append( B2DPoint(1,1) );
+ aRect2.append( B2DPoint(0,1) );
+ aRect2.setClosed(true);
+
+ B2DPolygon aNonRect1;
+ aNonRect1.append( B2DPoint(0,0) );
+ aNonRect1.append( B2DPoint(1,0) );
+ aNonRect1.append( B2DPoint(1,1) );
+ aNonRect1.append( B2DPoint(0.5,1) );
+ aNonRect1.append( B2DPoint(0.5,0) );
+ aNonRect1.setClosed(true);
+
+ B2DPolygon aNonRect2;
+ aNonRect2.append( B2DPoint(0,0) );
+ aNonRect2.append( B2DPoint(1,1) );
+ aNonRect2.append( B2DPoint(1,0) );
+ aNonRect2.append( B2DPoint(0,1) );
+ aNonRect2.setClosed(true);
+
+ B2DPolygon aNonRect3;
+ aNonRect3.append( B2DPoint(0,0) );
+ aNonRect3.append( B2DPoint(1,0) );
+ aNonRect3.append( B2DPoint(1,1) );
+ aNonRect3.setClosed(true);
+
+ B2DPolygon aNonRect4;
+ aNonRect4.append( B2DPoint(0,0) );
+ aNonRect4.append( B2DPoint(1,0) );
+ aNonRect4.append( B2DPoint(1,1) );
+ aNonRect4.append( B2DPoint(0,1) );
+
+ B2DPolygon aNonRect5;
+ aNonRect5.append( B2DPoint(0,0) );
+ aNonRect5.append( B2DPoint(1,0) );
+ aNonRect5.append( B2DPoint(1,1) );
+ aNonRect5.append( B2DPoint(0,1) );
+ aNonRect5.setControlPoints(1,B2DPoint(1,0),B2DPoint(-11,0));
+ aNonRect5.setClosed(true);
+
+ CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 1",
+ tools::isRectangle( aRect1 ));
+ CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 2",
+ tools::isRectangle( aRect2 ));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 1",
+ !tools::isRectangle( aNonRect1 ));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 2",
+ !tools::isRectangle( aNonRect2 ));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 3",
+ !tools::isRectangle( aNonRect3 ));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 4",
+ !tools::isRectangle( aNonRect4 ));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 5",
+ !tools::isRectangle( aNonRect5 ));
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dpolygontools);
+ CPPUNIT_TEST(testIsRectangle);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpolygontools
+
+
+class b2dpolypolygon : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dpolypolygon);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpolypolygon
+
+
+class b2dquadraticbezier : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dquadraticbezier);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dquadraticbezier
+
+
+class b2drange : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2drange);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2drange
+
+
+class b2dtuple : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dtuple);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dtuple
+
+
+class b2dvector : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b2dvector);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dvector
+
+class bcolor : public CppUnit::TestFixture
+{
+ BColor maWhite;
+ BColor maBlack;
+ BColor maRed;
+ BColor maGreen;
+ BColor maBlue;
+ BColor maYellow;
+ BColor maMagenta;
+ BColor maCyan;
+
+public:
+ bcolor() :
+ maWhite(1,1,1),
+ maBlack(0,0,0),
+ maRed(1,0,0),
+ maGreen(0,1,0),
+ maBlue(0,0,1),
+ maYellow(1,1,0),
+ maMagenta(1,0,1),
+ maCyan(0,1,1)
+ {}
+
+
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void hslTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("white",
+ tools::rgb2hsl(maWhite) == BColor(0,0,1));
+ CPPUNIT_ASSERT_MESSAGE("black",
+ tools::rgb2hsl(maBlack) == BColor(0,0,0));
+ CPPUNIT_ASSERT_MESSAGE("red",
+ tools::rgb2hsl(maRed) == BColor(0,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("green",
+ tools::rgb2hsl(maGreen) == BColor(120,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("blue",
+ tools::rgb2hsl(maBlue) == BColor(240,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("yellow",
+ tools::rgb2hsl(maYellow) == BColor(60,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("magenta",
+ tools::rgb2hsl(maMagenta) == BColor(300,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("cyan",
+ tools::rgb2hsl(maCyan) == BColor(180,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("third hue case",
+ tools::rgb2hsl(BColor(0,0.5,1)) == BColor(210,1,0.5));
+
+ CPPUNIT_ASSERT_MESSAGE("roundtrip white",
+ tools::hsl2rgb(tools::rgb2hsl(maWhite)) == maWhite);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip black",
+ tools::hsl2rgb(tools::rgb2hsl(maBlack)) == maBlack);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip red",
+ tools::hsl2rgb(tools::rgb2hsl(maRed)) == maRed);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip green",
+ tools::hsl2rgb(tools::rgb2hsl(maGreen)) == maGreen);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip blue",
+ tools::hsl2rgb(tools::rgb2hsl(maBlue)) == maBlue);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip yellow",
+ tools::hsl2rgb(tools::rgb2hsl(maYellow)) == maYellow);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip magenta",
+ tools::hsl2rgb(tools::rgb2hsl(maMagenta)) == maMagenta);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip cyan",
+ tools::hsl2rgb(tools::rgb2hsl(maCyan)) == maCyan);
+
+ CPPUNIT_ASSERT_MESSAGE("grey10",
+ tools::rgb2hsl(maWhite*.1) == BColor(0,0,.1));
+ CPPUNIT_ASSERT_MESSAGE("grey90",
+ tools::rgb2hsl(maWhite*.9) == BColor(0,0,.9));
+ CPPUNIT_ASSERT_MESSAGE("red/2",
+ tools::rgb2hsl(maRed*.5) == BColor(0,1,0.25));
+ CPPUNIT_ASSERT_MESSAGE("green/2",
+ tools::rgb2hsl(maGreen*.5) == BColor(120,1,0.25));
+ CPPUNIT_ASSERT_MESSAGE("blue/2",
+ tools::rgb2hsl(maBlue*.5) == BColor(240,1,0.25));
+ CPPUNIT_ASSERT_MESSAGE("yellow/2",
+ tools::rgb2hsl(maYellow*.5) == BColor(60,1,0.25));
+ CPPUNIT_ASSERT_MESSAGE("magenta/2",
+ tools::rgb2hsl(maMagenta*.5) == BColor(300,1,0.25));
+ CPPUNIT_ASSERT_MESSAGE("cyan/2",
+ tools::rgb2hsl(maCyan*.5) == BColor(180,1,0.25));
+
+ CPPUNIT_ASSERT_MESSAGE("pastel",
+ tools::rgb2hsl(BColor(.75,.25,.25)) == BColor(0,.5,.5));
+ }
+
+ // insert your test code here.
+ void hsvTest()
+ {
+ CPPUNIT_ASSERT_MESSAGE("white",
+ tools::rgb2hsv(maWhite) == BColor(0,0,1));
+ CPPUNIT_ASSERT_MESSAGE("black",
+ tools::rgb2hsv(maBlack) == BColor(0,0,0));
+ CPPUNIT_ASSERT_MESSAGE("red",
+ tools::rgb2hsv(maRed) == BColor(0,1,1));
+ CPPUNIT_ASSERT_MESSAGE("green",
+ tools::rgb2hsv(maGreen) == BColor(120,1,1));
+ CPPUNIT_ASSERT_MESSAGE("blue",
+ tools::rgb2hsv(maBlue) == BColor(240,1,1));
+ CPPUNIT_ASSERT_MESSAGE("yellow",
+ tools::rgb2hsv(maYellow) == BColor(60,1,1));
+ CPPUNIT_ASSERT_MESSAGE("magenta",
+ tools::rgb2hsv(maMagenta) == BColor(300,1,1));
+ CPPUNIT_ASSERT_MESSAGE("cyan",
+ tools::rgb2hsv(maCyan) == BColor(180,1,1));
+
+ CPPUNIT_ASSERT_MESSAGE("roundtrip white",
+ tools::hsv2rgb(tools::rgb2hsv(maWhite)) == maWhite);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip black",
+ tools::hsv2rgb(tools::rgb2hsv(maBlack)) == maBlack);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip red",
+ tools::hsv2rgb(tools::rgb2hsv(maRed)) == maRed);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip green",
+ tools::hsv2rgb(tools::rgb2hsv(maGreen)) == maGreen);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip blue",
+ tools::hsv2rgb(tools::rgb2hsv(maBlue)) == maBlue);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip yellow",
+ tools::hsv2rgb(tools::rgb2hsv(maYellow)) == maYellow);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip magenta",
+ tools::hsv2rgb(tools::rgb2hsv(maMagenta)) == maMagenta);
+ CPPUNIT_ASSERT_MESSAGE("roundtrip cyan",
+ tools::hsv2rgb(tools::rgb2hsv(maCyan)) == maCyan);
+
+ CPPUNIT_ASSERT_MESSAGE("grey10",
+ tools::rgb2hsv(maWhite*.1) == BColor(0,0,.1));
+ CPPUNIT_ASSERT_MESSAGE("grey90",
+ tools::rgb2hsv(maWhite*.9) == BColor(0,0,.9));
+ CPPUNIT_ASSERT_MESSAGE("red/2",
+ tools::rgb2hsv(maRed*.5) == BColor(0,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("green/2",
+ tools::rgb2hsv(maGreen*.5) == BColor(120,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("blue/2",
+ tools::rgb2hsv(maBlue*.5) == BColor(240,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("yellow/2",
+ tools::rgb2hsv(maYellow*.5) == BColor(60,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("magenta/2",
+ tools::rgb2hsv(maMagenta*.5) == BColor(300,1,0.5));
+ CPPUNIT_ASSERT_MESSAGE("cyan/2",
+ tools::rgb2hsv(maCyan*.5) == BColor(180,1,0.5));
+
+ CPPUNIT_ASSERT_MESSAGE("pastel",
+ tools::rgb2hsv(BColor(.5,.25,.25)) == BColor(0,.5,.5));
+ }
+
+ void ciexyzTest()
+ {
+ tools::rgb2ciexyz(maWhite);
+ tools::rgb2ciexyz(maBlack);
+ tools::rgb2ciexyz(maRed);
+ tools::rgb2ciexyz(maGreen);
+ tools::rgb2ciexyz(maBlue);
+ tools::rgb2ciexyz(maYellow);
+ tools::rgb2ciexyz(maMagenta);
+ tools::rgb2ciexyz(maCyan);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(bcolor);
+ CPPUNIT_TEST(hslTest);
+ CPPUNIT_TEST(hsvTest);
+ CPPUNIT_TEST(ciexyzTest);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dvector
+
+// -----------------------------------------------------------------------------
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dsvgdimpex);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolyrange);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dcubicbezier);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhommatrix);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhompoint);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpoint);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygon);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygontools);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolypolygon);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dquadraticbezier);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2drange);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dtuple);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dvector);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::bcolor);
+} // namespace basegfx2d
+
+
+// -----------------------------------------------------------------------------
+
+// this macro creates an empty function, which will called by the RegisterAllFunctions()
+// to let the user the possibility to also register some functions by hand.
+// NOADDITIONAL;
+
diff --git a/basegfx/test/basegfx3d.cxx b/basegfx/test/basegfx3d.cxx
new file mode 100644
index 000000000000..4871dcbd16c4
--- /dev/null
+++ b/basegfx/test/basegfx3d.cxx
@@ -0,0 +1,224 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+namespace basegfx3d
+{
+
+class b3dhommatrix : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3dhommatrix);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3dhommatrix
+
+
+class b3dhompoint : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3dhompoint);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3dhompoint
+
+
+class b3dpoint : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3dpoint);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3dpoint
+
+
+class b3drange : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3drange);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3drange
+
+
+class b3dtuple : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ // this is only demonstration code
+ void EmptyMethod()
+ {
+ // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3dtuple);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3dtuple
+
+
+class b3dvector : public CppUnit::TestFixture
+{
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ }
+
+ void tearDown()
+ {
+ }
+
+ // insert your test code here.
+ void EmptyMethod()
+ {
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(b3dvector);
+ CPPUNIT_TEST(EmptyMethod);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b3dvector
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dhommatrix);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dhompoint);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dpoint);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3drange);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dtuple);
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx3d::b3dvector);
+} // namespace basegfx3d
+
+
+// -----------------------------------------------------------------------------
+
+// this macro creates an empty function, which will called by the RegisterAllFunctions()
+// to let the user the possibility to also register some functions by hand.
+// NOADDITIONAL;
+
diff --git a/basegfx/test/basegfxtools.cxx b/basegfx/test/basegfxtools.cxx
new file mode 100644
index 000000000000..7e385f1eb78c
--- /dev/null
+++ b/basegfx/test/basegfxtools.cxx
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+#include <basegfx/tools/keystoplerp.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/tuple/tuple.hpp>
+
+using namespace ::basegfx;
+using namespace ::boost::tuples;
+
+namespace basegfxtools
+{
+
+class KeyStopLerpTest : public CppUnit::TestFixture
+{
+ tools::KeyStopLerp maKeyStops;
+
+ static std::vector<double> getTestVector()
+ {
+ std::vector<double> aStops(3);
+ aStops[0] = 0.1;
+ aStops[1] = 0.5;
+ aStops[2] = 0.9;
+ return aStops;
+ }
+
+public:
+ KeyStopLerpTest() :
+ maKeyStops(getTestVector())
+ {}
+
+ void setUp()
+ {}
+
+ void tearDown()
+ {}
+
+ void test()
+ {
+ double fAlpha;
+ std::ptrdiff_t nIndex;
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(-1.0);
+ CPPUNIT_ASSERT_MESSAGE("-1.0", nIndex==0 && fAlpha==0.0);
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(0.1);
+ CPPUNIT_ASSERT_MESSAGE("0.1", nIndex==0 && fAlpha==0.0);
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(0.3);
+ CPPUNIT_ASSERT_MESSAGE("0.3", nIndex==0 && fTools::equal(fAlpha,0.5));
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(0.5);
+ CPPUNIT_ASSERT_MESSAGE("0.5", nIndex==0 && fTools::equal(fAlpha,1.0));
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(0.51);
+ CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fTools::equal(fAlpha,0.025));
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(0.9);
+ CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fTools::equal(fAlpha,1.0));
+
+ tie(nIndex,fAlpha) = maKeyStops.lerp(1.0);
+ CPPUNIT_ASSERT_MESSAGE("0.51", nIndex==1 && fAlpha==1.0);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(KeyStopLerpTest);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfxtools::KeyStopLerpTest);
+} // namespace basegfxtools
diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx
new file mode 100644
index 000000000000..b1e08087136f
--- /dev/null
+++ b/basegfx/test/boxclipper.cxx
@@ -0,0 +1,421 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/curve/b2dbeziertools.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/bind.hpp>
+
+using namespace ::basegfx;
+
+
+namespace basegfx2d
+{
+/// Gets a random ordinal [0,n)
+inline double getRandomOrdinal( const ::std::size_t n )
+{
+ // use this one when displaying polygons in OOo, which still sucks
+ // great rocks when trying to import non-integer svg:d attributes
+ // return sal_Int64(double(n) * rand() / (RAND_MAX + 1.0));
+ return double(n) * rand() / (RAND_MAX + 1.0);
+}
+
+inline bool compare(const B2DPoint& left, const B2DPoint& right)
+{
+ return left.getX()<right.getX()
+ || (left.getX()==right.getX() && left.getY()<right.getY());
+}
+
+
+class boxclipper : public CppUnit::TestFixture
+{
+private:
+ B2DPolyRange aDisjunctRanges;
+ B2DPolyRange aEqualRanges;
+ B2DPolyRange aIntersectionN;
+ B2DPolyRange aIntersectionE;
+ B2DPolyRange aIntersectionS;
+ B2DPolyRange aIntersectionW;
+ B2DPolyRange aIntersectionNE;
+ B2DPolyRange aIntersectionSE;
+ B2DPolyRange aIntersectionSW;
+ B2DPolyRange aIntersectionNW;
+ B2DPolyRange aRingIntersection;
+ B2DPolyRange aRingIntersection2;
+ B2DPolyRange aRingIntersectExtraStrip;
+ B2DPolyRange aComplexIntersections;
+ B2DPolyRange aRandomIntersections;
+
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ B2DRange aCenter(100, 100, -100, -100);
+ B2DRange aOffside(800, 800, 1000, 1000);
+ B2DRange aNorth(100, 0, -100, -200);
+ B2DRange aSouth(100, 200, -100, 0);
+ B2DRange aEast(0, 100, 200, -100);
+ B2DRange aWest(-200, 100, 0, -100);
+ B2DRange aNorthEast(0, 0, 200, -200);
+ B2DRange aSouthEast(0, 0, 200, 200);
+ B2DRange aSouthWest(0, 0, -200, 200);
+ B2DRange aNorthWest(0, 0, -200, -200);
+
+ B2DRange aNorth2(-150, 50, 150, 350);
+ B2DRange aSouth2(-150, -50, 150, -350);
+ B2DRange aEast2 (50, -150, 350, 150);
+ B2DRange aWest2 (-50, -150,-350, 150);
+
+ aDisjunctRanges.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aDisjunctRanges.appendElement( aOffside, ORIENTATION_NEGATIVE );
+
+ aEqualRanges.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aEqualRanges.appendElement( aCenter, ORIENTATION_NEGATIVE );
+
+ aIntersectionN.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionN.appendElement( aNorth, ORIENTATION_NEGATIVE );
+
+ aIntersectionE.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionE.appendElement( aEast, ORIENTATION_NEGATIVE );
+
+ aIntersectionS.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionS.appendElement( aSouth, ORIENTATION_NEGATIVE );
+
+ aIntersectionW.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionW.appendElement( aWest, ORIENTATION_NEGATIVE );
+
+ aIntersectionNE.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionNE.appendElement( aNorthEast, ORIENTATION_NEGATIVE );
+
+ aIntersectionSE.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionSE.appendElement( aSouthEast, ORIENTATION_NEGATIVE );
+
+ aIntersectionSW.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionSW.appendElement( aSouthWest, ORIENTATION_NEGATIVE );
+
+ aIntersectionNW.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aIntersectionNW.appendElement( aNorthWest, ORIENTATION_NEGATIVE );
+
+ aRingIntersection.appendElement( aNorth2, ORIENTATION_NEGATIVE );
+ aRingIntersection.appendElement( aEast2, ORIENTATION_NEGATIVE );
+ aRingIntersection.appendElement( aSouth2, ORIENTATION_NEGATIVE );
+
+ aRingIntersection2 = aRingIntersection;
+ aRingIntersection2.appendElement( aWest2, ORIENTATION_NEGATIVE );
+
+ aRingIntersectExtraStrip = aRingIntersection2;
+ aRingIntersectExtraStrip.appendElement( B2DRange(0, -25, 200, 25),
+ ORIENTATION_NEGATIVE );
+
+ aComplexIntersections.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aOffside, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aCenter, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aNorth, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aEast, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aSouth, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aWest, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aNorthEast, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aSouthEast, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aSouthWest, ORIENTATION_NEGATIVE );
+ aComplexIntersections.appendElement( aNorthWest, ORIENTATION_NEGATIVE );
+
+#ifdef GENERATE_RANDOM
+ for( int i=0; i<800; ++i )
+ {
+ B2DRange aRandomRange(
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ) );
+
+ aRandomIntersections.appendElement( aRandomRange, ORIENTATION_NEGATIVE );
+ }
+#else
+ const char* randomSvg="m394 783h404v57h-404zm-197-505h571v576h-571zm356-634h75v200h-75zm-40-113h403v588h-403zm93-811h111v494h-111zm-364-619h562v121h-562zm-134-8h292v27h-292zm110 356h621v486h-621zm78-386h228v25h-228zm475-345h201v201h-201zm-2-93h122v126h-122zm-417-243h567v524h-567zm-266-738h863v456h-863zm262-333h315v698h-315zm-328-826h43v393h-43zm830-219h120v664h-120zm-311-636h221v109h-221zm-500 137h628v19h-628zm681-94h211v493h-211zm-366-646h384v355h-384zm-189-199h715v247h-715zm165-459h563v601h-563zm258-479h98v606h-98zm270-517h65v218h-65zm-44-259h96v286h-96zm-599-202h705v468h-705zm216-803h450v494h-450zm-150-22h26v167h-26zm-55-599h50v260h-50zm190-278h490v387h-490zm-290-453h634v392h-634zm257 189h552v300h-552zm-151-690h136v455h-136zm12-597h488v432h-488zm501-459h48v39h-48zm-224-112h429v22h-429zm-281 102h492v621h-492zm519-158h208v17h-208zm-681-563h56v427h-56zm126-451h615v392h-615zm-47-410h598v522h-598zm-32 316h79v110h-79zm-71-129h18v127h-18zm126-993h743v589h-743zm211-430h428v750h-428zm61-554h100v220h-100zm-353-49h658v157h-658zm778-383h115v272h-115zm-249-541h119v712h-119zm203 86h94v40h-94z";
+ B2DPolyPolygon randomPoly;
+ tools::importFromSvgD(
+ randomPoly,
+ rtl::OUString::createFromAscii(randomSvg));
+ std::for_each(randomPoly.begin(),
+ randomPoly.end(),
+ boost::bind(
+ &B2DPolyRange::appendElement,
+ boost::ref(aRandomIntersections),
+ boost::bind(
+ &B2DPolygon::getB2DRange,
+ _1),
+ ORIENTATION_NEGATIVE,
+ 1));
+#endif
+ }
+
+ void tearDown()
+ {
+ }
+
+ B2DPolyPolygon normalizePoly( const B2DPolyPolygon& rPoly )
+ {
+ B2DPolyPolygon aRes;
+ for( sal_uInt32 i=0; i<rPoly.count(); ++i )
+ {
+ B2DPolygon aTmp=rPoly.getB2DPolygon(i);
+ if( ORIENTATION_NEGATIVE == tools::getOrientation(aTmp) )
+ aTmp.flip();
+
+ aTmp=tools::removeNeutralPoints(aTmp);
+
+ B2DPoint* pSmallest=0;
+ for(B2DPoint* pCurr=aTmp.begin(); pCurr!=aTmp.end(); ++pCurr)
+ {
+ if( ! pSmallest || compare(*pCurr, *pSmallest) )
+ {
+ pSmallest=pCurr;
+ }
+ }
+
+ if( pSmallest )
+ std::rotate(aTmp.begin(),pSmallest,aTmp.end());
+
+ aRes.append(aTmp);
+ }
+
+ // boxclipper & generic clipper disagree slightly on area-less
+ // polygons (one or two points only)
+ aRes = tools::stripNeutralPolygons(aRes);
+
+ // now, sort all polygons with increasing 0th point
+ std::sort(aRes.begin(),
+ aRes.end(),
+ boost::bind(
+ &compare,
+ boost::bind(
+ &B2DPolygon::getB2DPoint,
+ _1,0),
+ boost::bind(
+ &B2DPolygon::getB2DPoint,
+ _2,0)));
+
+ return aRes;
+ }
+
+ void verifyPoly(const char* sName, const char* sSvg, const B2DPolyRange& toTest)
+ {
+ B2DPolyPolygon aTmp1;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ tools::importFromSvgD(
+ aTmp1,
+ rtl::OUString::createFromAscii(sSvg)));
+
+ const rtl::OUString aSvg=
+ tools::exportToSvgD(toTest.solveCrossovers());
+ B2DPolyPolygon aTmp2;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ tools::importFromSvgD(
+ aTmp2,
+ aSvg));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ sName,
+ normalizePoly(aTmp2) == normalizePoly(aTmp1));
+ }
+
+ void verifyPoly()
+ {
+ const char* disjunct="m100 100v-200h-200v200zm1100 900v-200h-200v200z";
+ const char* equal="m100 100v-200h-200v200zm200 0v-200h-200v200h200z";
+ const char* intersectionN="m100 0v-100h-200v100zm200 100v-200-100h-200v100 200z";
+ const char* intersectionE="m100 100v-200h-100v200zm200 0v-200h-200-100v200h100z";
+ const char* intersectionS="m100 100v-200h-200v200 100h200v-100zm0 0v-100h-200v100z";
+ const char* intersectionW="m0 100v-200h-100v200zm200 0v-200h-200-100v200h100z";
+ const char* intersectionNE="m100 0v-100h-100v100zm200 0v-200h-200v100h-100v200h200v-100z";
+ const char* intersectionSE="m200 200v-200h-100v-100h-200v200h100v100zm100-100v-100h-100v100z";
+ const char* intersectionSW="m0 100v-100h-100v100zm200 0v-200h-200v100h-100v200h200v-100z";
+ const char* intersectionNW="m100 100v-200h-100v-100h-200v200h100v100zm100-100v-100h-100v100z";
+ const char* ringIntersection="m150 150v-100h-100v100zm300 0v-300h-200v-200h-300v300h200v100h-200v300h300v-200zm0-200v-100h-100v100z";
+ const char* ringIntersection2="m-50-50v-100h-100v100zm100 200v-100h-100v100zm500 0v-300h-200v-200h-300v200h-200v300h200v200h300v-200zm-200-100v-100h100v100zm100-100v-100h-100v100zm100 200v-100h-100v100z";
+ const char* ringIntersectExtraStrip="m-50-50v-100h-100v100zm100 200v-100h-100v100zm500 0v-300h-200v-200h-300v200h-200v300h200v200h300v-200zm-200-100v-100h100v25h-50v50h50v25zm150-25v-50h-150v50zm100-75v-100h-100v100zm100 200v-100h-100v100z";
+ // TODO: old clipper impl. debug difference
+ //const char* complexIntersections="m100 0h-100v-100 100h-100 100v100-100zm0 0zm200 0h-100v-100h-100v-100 100h-100v100h-100 100v100h100v100-100h100v-100zm0 0h-100v-100 100h-100 100v100-100h100zm0 0v-100h-100-100v100 100h100 100v-100zm100 0v-100h-100v-100h-100-100v100h-100v100 100h100v100h100 100v-100h100v-100zm-200 0zm100 0v-100h-100-100v100 100h100 100v-100zm100 100v-200-100h-200-100-100v100 200 100h100 100 200v-100zm-200-100zm1000 1000v-200h-200v200z";
+ const char* complexIntersections="m0 0zm0 0zm0 0zm0 0v-100 100h-100 100v100-100h100zm-100 0v-100 100h-100 100v100-100h100zm0 0v-100h-100-100v100 100h100 100v-100zm0 0v-100h-100-100v100 100h100 100v-100zm0 0v-100h-100v-100 100h-100v100h-100 100v100h100v100-100h100v-100h100zm-100-100v-100h-100-100v100h-100v100 100h100v100h100 100v-100h100v-100-100zm0 0v-100h-200-100-100v100 200 100h100 100 200v-100-200zm600 900v200h200v-200z";
+ const char* randomIntersections="m63 457v-393h-43v393zm114 63v-8h-48v8zm-14 477v-127h-18v127zm693-923v-5h-119v5zm-260 457v-1h-14v1zm-220-375v-27h-8v27zm78 755v-22h-7v22zm203-774v-8h-158v8zm-108 375v-17h23v17zm813-19v-189h-21v-12h-26v-54h-17v-69h-25v-22h-62v-73h104v-5h-104-15v-17h-49v-1h-8v-16h-119v16h-386v18h-38-24v34h-23v26h-23v-26h-8v26h-18v27h18v339h8v-339h23v339h8v17h-8v13h8v5h-8v1h8v42h15v20h17v94h18 3v224h165v39h130v2h75v4h98v-4h153v-2h77v-20h4v-28h11v-218h-11v-27h3v-1h8v-17h-8v-63h8v-51h18v-32zm-581 32v-13h-14v13zm-78-78v-7h-32v7zm124 14v-21h-14v21zm595 32v-189h-26v-12h-4v-9h-13v-45h-13v-10h-12v-59h-62v-22h-26v-10h11v-63h15v-5h-15-49v-17h-8v-1h-119v1h-107v17h-279-38v34h-24v26h-23v27h23v284h-15v55h15v17h-15v13h15v5h-15v1h15v42h17v20h18v94h3 14v62h8v48h90v32h18v61h35v21h8v2h122v37h75v2h98v-2h153v-20h77v-28h4v-29h5v-40h-5v-149h-1v-27h1v-1h3v-17h-3v-46h3v-17-51h8v-32zm-563 2v-13h-14v13zm198 30v-13h-39v13zm204-43v-21h3v21zm-168-21v-21h-39v21zm306 0v-21h-5v21zm178 115v-272h-20v-12h-2v-54h-21v-164h1v-22h-27v-48h-743v47h-23v18h-71v24h-8v419h-39v19h60v156h66 32v202h-72v110h79v-88h11v39h3v48h621v-14h96v-82h35v-326zm-570-420v-4h-156v4zm63 481v-18h-11v18zm72 0v-25h-14v25zm465-112v-13h-5v13zm-46-43v-21h1v21zm-37-21v-21h-12v21zm-352 21v-21h23v21zm-23 30v-17h23v17zm-23 18v-5h23v5zm-23 82v-19h23v19zm272 75v-3h-35v3zm-76-192v-13h-39v13zm150 30v-13h-35v13zm-76 6v-1h-39v1zm11 106v-25h-11v25zm150 160v-14h-75v14zm318-304v-11h-13v-43h-2v-2h-10v-37h-4v37h-27v3h-31v-3-37h-5v37h-43v3h-2v21h2v21h-2v30h-1v-30h-8v-21h8v-21h-8v-3h-5v-62h5v-11h-5v-29h-8v-52h-15v-17-38h-15v-52h-89v16h-22v36h-175v55h-15v1h-25v51h-23v-41h-14v41h-2v105h-4v21h4v21h-4v13h4v17h-4-18v13h18v5h-18v1h18v42h4v11h2v9h14v-9h23v9h40v19h-40v25h40v2h82v2h75v43h-75v3h75 40v60h35v-60h23 34 12 15v-3h-15v-43h15v-48h10v-37h11v-31h1v1h45v30h5v-30h20v-1h11v1h8v30h19v20h3v-20h1v-30h10v-1h2v-32zm-146-329v-1h-2v1zm-117 211v-11 11zm-76 0v-11h-13v11zm13 65v-65h1v65zm-1 42v-21h1v16h35v5zm-36 30v-17h36v17zm-36 18v-5h36v5zm180-5v-13h-13v-17h5v-13h-5v-21h5v-21h-5v-3h-8v-62h8v-11h-8v-29h-9v-51h-6v-1-17h-15v-38h-54v-36h-35v36h-22v38h-67v17h-108v1h-15v51h-25v105h-23v-105h-14v105h-2v21h2v21h-2v13h2v17h-2-4v13h4v5h-4v1h4v42h2v11h14v-11h23v11h40v9h82v19h-82v25h82v2h75v2h40v43h-40v3h40 35 23v-3h-23v-43h23v-2h34v2h12v-2h6v-46h9v-20h8v-17h2v-26h-2v-5zm-127-64v-21 21zm89 51v-17h3v17zm-57-17v-13h-35v13zm58 61v-26h-19v-5h19v-13h-23v-17h23v-13h-23v-21h23v-21h-23v-65h23v-11h-23v-14h-35v-15 15h-22v14h-18v11h18v65h-18v21h18v16h22v5h-22v13h22v17h-22-18v13h18v5h-18v1h18v25h22v17h35v-17zm0-25v-1h-35v1zm-22-390v6h-175v5h-31v-15h228v4zm344 352v-189h-2v-12h-21v-54h-26v-164h26v-5h-26v-17h-119v-36h-562v35h-62v18h-23v34h-23v-10h-48v419h-8v8h8v5h71v5h-58v1h58v42h8v114h32 18v224h3v39h165v34h456v-32h77v-2h4v-20h11v-28h4v-218h-4v-28h36v-17h-36v-63h39v-83zm-50 0v-11h-1v-43h-3v-2h-6v-39h-4v-34h-13v-60h-12v-12h-31v72h-31v-72-9h-59v-17-38h-5v-59h-8v-5h8v-1h-8v-16h-2v16h-13v-11h-15v-5h-89v5h-22v11h-175v6h-15v7h-25v16h-43v36h-18v66h-54v-107h-32v107h-4v41h-8v105h-6v7h6v14h8v21h-8v13h8v17h-8-14v13h14v5h-14v1h14v42h8v20h90v19h-34v7h-15v68h26v-50h23v50h18 4v62h16v-62h15v110h8v10h3v22h119v11h75v50h75v-50h23v-11h34v11h48v-11h30v-22h21v-120h20v-3h11v3h30v-3h13-13v-27h13v-1h17v-17h-17v-46h17v-17h6v-51h3v-32zm-256-32v-21h-35v-65h35v-11h-35v-14 14h-22v11h22v65h-22v21h22v16-16zm89 69v-5h3v5zm-3 26v-26h-31v-5h31v-13h-31v-17h31v-13h-31v-21h31v-21h-31v-65h31v-11h-31v-14h-23v-15h-35v-51 51h-22v15h-18v14h-35v11h35v65h-35v21h35v16h18v5h-18v13h18v17h-18-36-39-61v13h61v5h-61v1h61v25h39v-25h36v25h18v17h22v11h35v-11h23v-17zm-19-25v-1h-4v-5h4v-13h-4-35-22v13h22v5h-22v1h22v25h35v-25zm23 252v-36h34v36zm-34-99v-43h34v43zm35-128v-26h-8v-5h8v-13h-8v-17h8v-13h-8v-21h8v-21h-8v-3h-9v-62h9v-11h-9v-29h-6v-51-1h-15v-17h-54v-38h-35v38h-22v11h-53v6h-14v1h-108v51h-15v105h-25v21h25v21h-25v13h25v17h-25-23-14-2v13h2v5h-2v1h2v42h14v-42h23v42h40v11h82v9h75v46h40v2h35v-2h23v-4h31v-42h3v46h12v-46h6v-20h9v-17zm-15-61v-13h-12v13zm12 30v-13h-12v13zm12 31v-26h-12v26zm12 131v-3h-12v3zm12 110v-14h-12v14zm27-241v-26h-9v-5h9v-13h-9v-17h9v-13h-9v-21h9v-21h-9v-3h-6v-62h6v-11h-6v-29-51h-15v-1h-54v-17h-35v11h-22v6h-53v1h-14v51h-108v105h-15v21h15v21h-15v13h15v17h-15-25v13h25v5h-25v1h25v25h15v17h21v6h61v5h75v9h18v42h22v4h35v-4h23v-42h31v-9h3v9h12v-9-11h6v-17zm0 0v-26h-6v-5h6v-13h-6v-17h6v-13h-6v-21h6v-21h-6v-3-62-11-29h-15v-51h-54v-1h-35v-6 6h-22v1h-53v51h-14v24h-87v81h-21v21h21v21h-21v13h21v17h-21-15v13h15v5h-15v1h15v25h21v17h61v6h39v-6h36v11h18v9h22v42h35v-42h23v-9h31v-11h3v11h12v-11-17zm0 0v-26-5-13-17-13-21-21-3h-12v3h-3v-65h15v-11h-15v-29h-54v-51h-35v-1 1h-22v51h-53v29h-1v-5h-13v5h-26v76h-61v21h61v21h-61v13h61v17h-61-21v13h21v5h-21v1h21v25h61v17h39v-17h36v17h18v11h22v9h35v-9h23v-11h31v-17h3v17h12v-17zm15-419v-12h-2v12zm186 356v-56h-8v-133h-4v-12h-13v-9h-13v-45h-12v-10h-62v-59-6h-26v-16h-33v-10h33v-12h-33v-22h-5v-29h49v-5h-49-8v-17h-119v17h-107-279v34h-38v26h-24v27h24v179h-7v105h-17v55h17v17h-17v13h17v5h-17v1h17v42h18v20h3v94h14 8v62h41v37h26v-37h23v48h18v32h35v61h8v21h122v2h75v37h98v-37h34v17h119v-57h11v29h66v-29h4v-40h-4v-26h3v-123h-3v-27h3v-1h1v-17h-1v-46h1v-17h3v-51-32zm0 0v-54h-4v-2h-3v-73h-10v-60h-13v-12h-12v-9h-31v9h-31v-9-55h-59v-59h-5v-5h5v-1h-5v-16h-8v-10h8v-12h-8v-22h-119v34h117v10h-28v-6h-89v6h-22v5h-175v11h-40v13h-147v11h-4v107h-8v41h-6v105h-22v21h28v21h-17v13h17v17h-14-3v13h3v5h-3v1h3v42h14v20h8v94h41 26 23 18v62h4v48h31v10h8v22h3v11h119v50h75v21h98v-71h34v71h48v-71h30v-11h21v-22h20v-120h11v120h43v-123h17-17v-27h17v-1h6v-17h-6v-46h6v-17h3v-51h1v-32zm-4 0v-11h-6v-43h-4v-2h-13v-39h-12v-34h-4v34h-27v2h-31v-2-34h-48v36h-2v37h-1v-73h-8v-29-52h-5v-17h-8v-38h-15v-59h-15v-6h-89v6h-22v7h-175v16h-15v36h-25v55h-39v11h-4v41h-18v105h-54v-105h-32v105h-4v7h4v14h86v21h-86v13h86v17h-86-4v13h4v5h-4v1h4v42h86v11h18v9h4v19h-4v25h4v50h16v-48h23v45h-8v3h8 122v96h-119v14h119v10h75v22h75v-22h23v-10h34v10h48v-24h-36v-36h15v-60h21v-3h-11v-43h2v15h9v-15h46v15h5v-15h20v-2h-20v-46h20v-37h11v37h8v46h-8v2h8v15h22v-15h1v-2h-1v-46h1v-17h12v-20h13v-31h4v-32zm-142 148v-2h-9v2zm9-2v-46h46v46zm-46 45v-28h46v28zm67-191v-11h-1v-42h-3v42h-19v11h19v32h3v-32zm-61 0v-11h-5v11zm96 0v-11h-4v-43h-13v-2h-2v-37h-10v-2h-4v2h-27v37h-31v-37-2h-5v2h-43v37h-2v3h-1v-3h-8v-62-11-29h-5v-52h-8v-17h-15v-38-52h-15v-7h-89v7h-22v16h-175v36h-15v55h-25v1h-37v10h-2v41h-4v105h-18v21h18v21h-18v13h18v17h-18-86v13h86v5h-86v1h86v42h18v11h4v9h2v19h-2v25h2v2h14v-2h23v2h40v2h82v43h-122v3h122 75v96h-75v14h75v10h75v-10h23v-14h-23v-36h23v-60h34v60h12v-60h15 10v-3h-10v-43h10v-48h11v-37h46v37h5v-37h20v-30h11v30h8v37h22v-17h1v-20h12v-31h13v-32zm-13 0v-11h-2v-43h-10v-2h-4v2h-19v1h-8v42h-31v-21-21-3h-5v3h-43v21h43v21h-43v11h43v19h-45v13h45v1h5v-1h20v-13h-20v-19h31v32h8v1h19v30h3v-30h1v-1h10v-32zm-72 148v-2h-5v2zm5 43h-5zm66-191v-11h-3v11zm-38 146v-46h11v46zm-11 45v-28h11v28zm-11 149v-4h11v4zm-11 40v-40h-8v40zm92-380v-54-2h-4v-133h-13v-12h-13v-9h-12v-45h-31v45h-31v-55-59h-59v-5h33v-1h-33v-16h-5v-10h5v-12h-5v-22h-8v-29h8v-5h-8-119-107v5h107v29h-386v26h-38v27h40v20h-4v11h-14v148h-22v105h-7v55h18v17h-18v13h18v5h-18v1h18v42h3v20h14v94h8 41v62h26v-62h23v62h18v48h4v10h31v22h8v61h122v21h75v2h98v-2h34v2h99v-84h20v-22h11v22h43v-22h23v-123h-6v-27h6v-1h3v-17h-3v-46h3v-17h1v-51h3v-32zm-43 148v-2h-22v2zm22 43h-30zm66 189v-40h-66v40zm41-380v-11h-10v-43h-4v1h-19v42h-8v11h8v32h19v1h3v-1h1v-32zm38 0v-11h-3v-43h-6v-2h-4v-39h-13v-34h-12v-60h-4v60h-27v34h-31v-34-72h-48v72h-3v-29h-8v-52-17h-5v-38h-8v-59h-15v-6h-15v-11h-89v11h-22v6h-175v7h-15v16h-25v36h-43v66h-18v41h-54v-41h-32v41h-4v105h-8v7h8v14h4v21h-4v13h4v17h-4-8v13h8v5h-8v1h8v42h4v11h86v9h18v19h-18v25h18v50h4 16 15 8v110h3v10h119v22h75v11h75v-11h23v-22h34v22h48v-22h30v-24h-30v-96h51v-3h20-20v-28h20v-15h11v15h8v1h22v-1h13v-17h-12v-46h12v-17h17v-51h6v-32z";
+
+ verifyPoly("disjunct", disjunct, aDisjunctRanges);
+ verifyPoly("equal", equal, aEqualRanges);
+ verifyPoly("intersectionN", intersectionN, aIntersectionN);
+ verifyPoly("intersectionE", intersectionE, aIntersectionE);
+ verifyPoly("intersectionS", intersectionS, aIntersectionS);
+ verifyPoly("intersectionW", intersectionW, aIntersectionW);
+ verifyPoly("intersectionNE", intersectionNE, aIntersectionNE);
+ verifyPoly("intersectionSE", intersectionSE, aIntersectionSE);
+ verifyPoly("intersectionSW", intersectionSW, aIntersectionSW);
+ verifyPoly("intersectionNW", intersectionNW, aIntersectionNW);
+ verifyPoly("ringIntersection", ringIntersection, aRingIntersection);
+ verifyPoly("ringIntersection2", ringIntersection2, aRingIntersection2);
+ verifyPoly("ringIntersectExtraStrip", ringIntersectExtraStrip, aRingIntersectExtraStrip);
+ verifyPoly("complexIntersections", complexIntersections, aComplexIntersections);
+ verifyPoly("randomIntersections", randomIntersections, aRandomIntersections);
+ }
+
+ void dumpSvg(const char* pName,
+ const ::basegfx::B2DPolyPolygon& rPoly)
+ {
+ (void)pName; (void)rPoly;
+#if defined(VERBOSE)
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(rPoly),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+ }
+
+ void getPolyPolygon()
+ {
+ dumpSvg("disjunct",aDisjunctRanges.solveCrossovers());
+ dumpSvg("equal",aEqualRanges.solveCrossovers());
+ dumpSvg("intersectionN",aIntersectionN.solveCrossovers());
+ dumpSvg("intersectionE",aIntersectionE.solveCrossovers());
+ dumpSvg("intersectionS",aIntersectionS.solveCrossovers());
+ dumpSvg("intersectionW",aIntersectionW.solveCrossovers());
+ dumpSvg("intersectionNE",aIntersectionNE.solveCrossovers());
+ dumpSvg("intersectionSE",aIntersectionSE.solveCrossovers());
+ dumpSvg("intersectionSW",aIntersectionSW.solveCrossovers());
+ dumpSvg("intersectionNW",aIntersectionNW.solveCrossovers());
+ dumpSvg("ringIntersection",aRingIntersection.solveCrossovers());
+ dumpSvg("ringIntersection2",aRingIntersection2.solveCrossovers());
+ dumpSvg("aRingIntersectExtraStrip",aRingIntersectExtraStrip.solveCrossovers());
+ dumpSvg("complexIntersections",aComplexIntersections.solveCrossovers());
+ dumpSvg("randomIntersections",aRandomIntersections.solveCrossovers());
+
+ CPPUNIT_ASSERT_MESSAGE("getPolyPolygon", true );
+ }
+
+ void validatePoly( const char* pName, const B2DPolyRange& rRange )
+ {
+ B2DPolyPolygon genericClip;
+ const sal_uInt32 nCount=rRange.count();
+ for( sal_uInt32 i=0; i<nCount; ++i )
+ {
+ B2DPolygon aRect=tools::createPolygonFromRect(
+ rRange.getElement(i).head);
+ if( rRange.getElement(i).tail.head == ORIENTATION_NEGATIVE )
+ aRect.flip();
+
+ genericClip.append(aRect);
+ }
+
+#if defined(VERBOSE)
+ fprintf(stderr, "%s input - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(
+ genericClip),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ const B2DPolyPolygon boxClipResult=rRange.solveCrossovers();
+ const rtl::OUString boxClipSvg(
+ basegfx::tools::exportToSvgD(
+ normalizePoly(
+ boxClipResult)));
+#if defined(VERBOSE)
+ fprintf(stderr, "%s boxclipper - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ boxClipSvg,
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ genericClip = tools::solveCrossovers(genericClip);
+ const rtl::OUString genericClipSvg(
+ basegfx::tools::exportToSvgD(
+ normalizePoly(
+ genericClip)));
+#if defined(VERBOSE)
+ fprintf(stderr, "%s genclipper - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ genericClipSvg,
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ CPPUNIT_ASSERT_MESSAGE(pName,
+ genericClipSvg == boxClipSvg);
+ }
+
+ void validatePoly()
+ {
+ validatePoly("disjunct", aDisjunctRanges);
+ validatePoly("equal", aEqualRanges);
+ validatePoly("intersectionN", aIntersectionN);
+ validatePoly("intersectionE", aIntersectionE);
+ validatePoly("intersectionS", aIntersectionS);
+ validatePoly("intersectionW", aIntersectionW);
+ validatePoly("intersectionNE", aIntersectionNE);
+ validatePoly("intersectionSE", aIntersectionSE);
+ validatePoly("intersectionSW", aIntersectionSW);
+ validatePoly("intersectionNW", aIntersectionNW);
+ // subtle differences on Solaris Intel, comparison not smart enough
+ // (due to floating point inaccuracies)
+ //validatePoly("ringIntersection", aRingIntersection);
+ //validatePoly("ringIntersection2", aRingIntersection2);
+ //validatePoly("ringIntersectExtraStrip", aRingIntersectExtraStrip);
+ // generic clipper buggy here, likely
+ //validatePoly("complexIntersections", aComplexIntersections);
+ //validatePoly("randomIntersections", aRandomIntersections);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(boxclipper);
+ CPPUNIT_TEST(validatePoly);
+ CPPUNIT_TEST(verifyPoly);
+ CPPUNIT_TEST(getPolyPolygon);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::boxclipper);
+} // namespace basegfx2d
diff --git a/basegfx/test/clipstate.cxx b/basegfx/test/clipstate.cxx
new file mode 100644
index 000000000000..48c1e5967260
--- /dev/null
+++ b/basegfx/test/clipstate.cxx
@@ -0,0 +1,180 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+#include <basegfx/tools/b2dclipstate.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/bind.hpp>
+
+using namespace ::basegfx;
+
+
+namespace basegfx2d
+{
+
+class clipstate : public CppUnit::TestFixture
+{
+private:
+ tools::B2DClipState aUnion1;
+ tools::B2DClipState aUnion2;
+ tools::B2DClipState aIntersect;
+ tools::B2DClipState aXor;
+ tools::B2DClipState aSubtract;
+
+public:
+ void setUp()
+ {
+ B2DRange aCenter(100, 100, -100, -100);
+ B2DRange aNorth(-10, -110, 10, -90);
+ B2DRange aWest(-110, -10, -90, 10);
+ B2DRange aSouth(-10, 110, 10, 90);
+ B2DRange aEast(110, -10, 90, 10);
+
+ aUnion1.unionRange(aCenter);
+ aUnion1.unionRange(aNorth);
+ aUnion1.unionRange(aWest);
+ aUnion1.unionRange(aSouth);
+ aUnion1.unionRange(aEast);
+
+ aUnion2.makeNull();
+ aUnion2.unionRange(aCenter);
+ aUnion2.unionRange(aNorth);
+ aUnion2.unionRange(aWest);
+ aUnion2.unionRange(aSouth);
+ aUnion2.unionRange(aEast);
+
+ aIntersect.intersectRange(aCenter);
+ aIntersect.intersectRange(aNorth);
+ aIntersect.intersectRange(aWest);
+ aIntersect.intersectRange(aSouth);
+ aIntersect.intersectRange(aEast);
+
+ aXor.makeNull();
+ aXor.xorRange(aCenter);
+ aXor.xorRange(aNorth);
+ aXor.xorRange(aWest);
+ aXor.xorRange(aSouth);
+ aXor.xorRange(aEast);
+
+ aSubtract.intersectRange(aCenter);
+ aSubtract.subtractRange(aNorth);
+ aSubtract.subtractRange(aWest);
+ aSubtract.subtractRange(aSouth);
+ aSubtract.subtractRange(aEast);
+ }
+
+ void tearDown()
+ {}
+
+ void verifyPoly(const char* sName, const char* sSvg, const tools::B2DClipState& toTest)
+ {
+#if defined(VERBOSE)
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ sName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(toTest.getClipPoly()),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ B2DPolyPolygon aTmp1;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ tools::importFromSvgD(
+ aTmp1,
+ rtl::OUString::createFromAscii(sSvg)));
+
+ const rtl::OUString aSvg=
+ tools::exportToSvgD(toTest.getClipPoly());
+ B2DPolyPolygon aTmp2;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ tools::importFromSvgD(
+ aTmp2,
+ aSvg));
+
+ CPPUNIT_ASSERT_MESSAGE(
+ sName,
+ aTmp2 == aTmp1);
+ }
+
+ void verifySimpleRange()
+ {
+ const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+ const char* intersectSvg="m-100 10v-20h10v20zm80 90v-10h20v10zm-20-190v-10h20v10zm80 100v-20h10v20z";
+ const char* xorSvg="m-100 10h10v-20h-10zm90 110h20v-10h-20zm0-180h20v-10h-20zm100 110h10v-20h-10zm10 20v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+ const char* subtractSvg="m-90 10v-20h-10v-90h90v10h20v-10h90v90h-10v20h10v90h-90v-10h-20v10h-90v-90z";
+
+ CPPUNIT_ASSERT_MESSAGE("cleared clip stays empty under union operation",
+ aUnion1.isCleared());
+ verifyPoly("union", unionSvg, aUnion2);
+ verifyPoly("intersect", intersectSvg, aIntersect);
+ verifyPoly("xor", xorSvg, aXor);
+ verifyPoly("subtract", subtractSvg, aSubtract);
+ }
+
+ void verifyMixedClips()
+ {
+ tools::B2DClipState aMixedClip;
+
+ const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+
+ B2DPolyPolygon aTmp1;
+ tools::importFromSvgD(
+ aTmp1,
+ rtl::OUString::createFromAscii(unionSvg));
+
+ aMixedClip.intersectPolyPolygon(aTmp1);
+ aMixedClip.subtractRange(B2DRange(-20,-150,20,0));
+ aMixedClip.subtractRange(B2DRange(-150,-20,0,20));
+ aMixedClip.xorRange(B2DRange(-150,-150,150,150));
+
+ const char* mixedClipSvg="m0 0v20h-100v80h90v10h20v-10h90v-90h10v-20h-10v-90h-80v100zm-40-20v-80h-80v80zm-50 170v-300h300v300z";
+ verifyPoly("mixed clip", mixedClipSvg, aMixedClip);
+ }
+
+ CPPUNIT_TEST_SUITE(clipstate);
+ CPPUNIT_TEST(verifySimpleRange);
+ CPPUNIT_TEST(verifyMixedClips);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::clipstate);
+} // namespace basegfx2d
diff --git a/basegfx/test/export.map b/basegfx/test/export.map
new file mode 100644
index 000000000000..3308588ef6f8
--- /dev/null
+++ b/basegfx/test/export.map
@@ -0,0 +1,34 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+UDK_3_0_0 {
+ global:
+ cppunitTestPlugIn;
+
+ local:
+ *;
+};
diff --git a/basegfx/test/genericclipper.cxx b/basegfx/test/genericclipper.cxx
new file mode 100644
index 000000000000..d6c97c0567dc
--- /dev/null
+++ b/basegfx/test/genericclipper.cxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+// autogenerated file with codegen.pl
+
+#include "preextstl.h"
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+#include "postextstl.h"
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/curve/b2dbeziertools.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+#include <boost/bind.hpp>
+
+using namespace ::basegfx;
+
+
+namespace basegfx2d
+{
+
+class genericclipper : public CppUnit::TestFixture
+{
+private:
+ B2DPolygon aSelfIntersecting;
+ B2DPolygon aShiftedRectangle;
+
+public:
+ // initialise your test code values here.
+ void setUp()
+ {
+ aSelfIntersecting.append(B2DPoint(0, 0));
+ aSelfIntersecting.append(B2DPoint(0, 100));
+ aSelfIntersecting.append(B2DPoint(75, 100));
+ aSelfIntersecting.append(B2DPoint(75, 50));
+ aSelfIntersecting.append(B2DPoint(25, 50));
+ aSelfIntersecting.append(B2DPoint(25, 150));
+ aSelfIntersecting.append(B2DPoint(100,150));
+ aSelfIntersecting.append(B2DPoint(100,0));
+ aSelfIntersecting.setClosed(true);
+
+ aShiftedRectangle = tools::createPolygonFromRect(
+ B2DRange(0,90,20,150));
+ }
+
+ void tearDown()
+ {}
+
+ void validate(const char* pName,
+ const char* pValidSvgD,
+ B2DPolyPolygon (*pFunc)(const B2DPolyPolygon&, const B2DPolyPolygon&))
+ {
+ const B2DPolyPolygon aSelfIntersect(
+ tools::prepareForPolygonOperation(aSelfIntersecting));
+ const B2DPolyPolygon aRect(
+ tools::prepareForPolygonOperation(aShiftedRectangle));
+#if defined(VERBOSE)
+ fprintf(stderr, "%s input LHS - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(
+ aSelfIntersect),
+ RTL_TEXTENCODING_UTF8).getStr() );
+ fprintf(stderr, "%s input RHS - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(
+ aRect),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ const B2DPolyPolygon aRes=
+ pFunc(aSelfIntersect, aRect);
+
+#if defined(VERBOSE)
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ pName, rtl::OUStringToOString(
+ basegfx::tools::exportToSvgD(aRes),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ rtl::OUString aValid=rtl::OUString::createFromAscii(pValidSvgD);
+
+ CPPUNIT_ASSERT_MESSAGE(pName,
+ basegfx::tools::exportToSvgD(aRes) == aValid);
+ }
+
+ void validateOr()
+ {
+ const char* pValid="m0 0h100v150h-75v-50h-5v50h-20v-50-10zm75 10v-50h-50v50z";
+ validate("validateOr", pValid, &tools::solvePolygonOperationOr);
+ }
+
+ void validateXor()
+ {
+ const char* pValid="m0 0h100v150h-75v-50h-5v50h-20v-50-10zm0 10h20v-10h-20zm75 10v-50h-50v50z";
+ validate("validateXor", pValid, &tools::solvePolygonOperationXor);
+ }
+
+ void validateAnd()
+ {
+ const char* pValid="m0 100v-10h20v10z";
+ validate("validateAnd", pValid, &tools::solvePolygonOperationAnd);
+ }
+
+ void validateDiff()
+ {
+ const char* pValid="m0 90v-90h100v150h-75v-50h-5v-10zm55 10v-50h-50v50z";
+ validate("validateDiff", pValid, &tools::solvePolygonOperationDiff);
+ }
+
+ // Change the following lines only, if you add, remove or rename
+ // member functions of the current class,
+ // because these macros are need by auto register mechanism.
+
+ CPPUNIT_TEST_SUITE(genericclipper);
+ CPPUNIT_TEST(validateOr);
+ CPPUNIT_TEST(validateXor);
+ CPPUNIT_TEST(validateAnd);
+ CPPUNIT_TEST(validateDiff);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+// -----------------------------------------------------------------------------
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::genericclipper);
+} // namespace basegfx2d
diff --git a/basegfx/test/makefile.mk b/basegfx/test/makefile.mk
new file mode 100644
index 000000000000..09d8b805f9f5
--- /dev/null
+++ b/basegfx/test/makefile.mk
@@ -0,0 +1,87 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..
+
+PRJNAME=basegfx
+TARGET=tests
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+#building with stlport, but cppunit was not built with stlport
+.IF "$(USE_SYSTEM_STL)"!="YES"
+.IF "$(SYSTEM_CPPUNIT)"=="YES"
+CFLAGSCXX+=-DADAPT_EXT_STL
+.ENDIF
+.ENDIF
+
+CFLAGSCXX += $(CPPUNIT_CFLAGS)
+
+# --- Common ----------------------------------------------------------
+
+SHL1OBJS= \
+ $(SLO)$/basegfx1d.obj \
+ $(SLO)$/basegfx2d.obj \
+ $(SLO)$/basegfx3d.obj \
+ $(SLO)$/boxclipper.obj \
+ $(SLO)$/basegfxtools.obj \
+ $(SLO)$/clipstate.obj \
+ $(SLO)$/genericclipper.obj \
+ $(SLO)$/testtools.obj
+
+SHL1TARGET= basegfx_tests
+SHL1STDLIBS= \
+ $(BASEGFXLIB) \
+ $(SALLIB) \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(CPPUNITLIB)
+
+SHL1IMPLIB= i$(SHL1TARGET)
+
+DEF1NAME =$(SHL1TARGET)
+SHL1VERSIONMAP = export.map
+SHL1RPATH = NONE
+
+# END ------------------------------------------------------------------
+
+#------------------------------- All object files -------------------------------
+# do this here, so we get right dependencies
+SLOFILES=$(SHL1OBJS)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+.INCLUDE : _cppunit.mk
+
+.IF "$(verbose)"!="" || "$(VERBOSE)"!=""
+CDEFS+= -DVERBOSE
+.ENDIF
diff --git a/basegfx/test/testtools.cxx b/basegfx/test/testtools.cxx
new file mode 100644
index 000000000000..e96eb4d8edce
--- /dev/null
+++ b/basegfx/test/testtools.cxx
@@ -0,0 +1,235 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basegfx.hxx"
+
+#include "testtools.hxx"
+
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/vector/b2dvector.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+#include <algorithm>
+
+
+namespace basegfx
+{
+ namespace testtools
+ {
+ Plotter::Plotter( ::std::ostream& rOutputStream ) :
+ mrOutputStream(rOutputStream),
+ maPoints(),
+ mbFirstElement( true )
+ {
+ // output gnuplot setup. We switch gnuplot to parametric
+ // mode, therefore every plot has at least _two_
+ // functions: one for the x and one for the y value, both
+ // depending on t.
+ mrOutputStream << "#!/usr/bin/gnuplot -persist" << ::std::endl
+ << "#" << ::std::endl
+ << "# automatically generated by basegfx::testtools::Plotter, don't change!" << ::std::endl
+ << "#" << ::std::endl
+ << "set parametric" << ::std::endl
+ // This function plots a cubic bezier curve. P,q,r,s
+ // are the control point elements of the corresponding
+ // output coordinate component (i.e. x components for
+ // the x plot, and y components for the y plot)
+ << "cubicBezier(p,q,r,s,t) = p*(1-t)**3+q*3*(1-t)**2*t+r*3*(1-t)*t**2+s*t**3" << ::std::endl
+
+ // This function plots the derivative of a cubic
+ // bezier curve. P,q,r,s are the control point
+ // components of the _original_ curve
+ << "cubicBezDerivative(p,q,r,s,t) = 3*(q-p)*(1-t)**2+6*(r-q)*(1-t)*t+3*(s-r)*t**2" << ::std::endl
+
+ // Plot a line's x component of a line in implicit
+ // form ax + by + c = 0
+ << "implicitLineX(a,b,c,t) = a*-c + t*-b" << ::std::endl
+
+ // Plot a line's y component of a line in implicit
+ // form ax + by + c = 0
+ << "implicitLineY(a,b,c,t) = b*-c + t*a" << ::std::endl
+
+ // Plot a line's component of a line between a and b
+ // (where a and b should be the corresponding
+ // components of the line's start and end point,
+ // respectively)
+ << "line(a,b,t) = a*(1-t) + b*t" << ::std::endl << ::std::endl
+ << "# end of setup" << ::std::endl << ::std::endl
+
+ // Start the actual plot line
+ << "plot [t=0:1] ";
+ }
+
+ namespace
+ {
+ class PointWriter
+ {
+ public:
+ PointWriter( ::std::ostream& rOutputStream ) :
+ mrOutputStream( rOutputStream )
+ {
+ }
+
+ void operator()( const B2DPoint& rPoint ) const
+ {
+ mrOutputStream << rPoint.getX() << "\t" << rPoint.getY() << ::std::endl;
+ mrOutputStream << "e" << ::std::endl;
+ }
+
+ private:
+ ::std::ostream& mrOutputStream;
+ };
+ }
+
+ Plotter::~Plotter()
+ {
+ // End the plot line
+ mrOutputStream << ::std::endl;
+
+ // write stored data points. Cannot write before, since
+ // this is an inline dataset, which must be after the plot <...>
+ // line
+ ::std::for_each( maPoints.begin(), maPoints.end(), PointWriter(mrOutputStream) );
+ }
+
+ void Plotter::plot( const B2DPolygon& rPoly )
+ {
+ const sal_uInt32 pointCount( rPoly.count() );
+
+ if( pointCount < 1 )
+ return;
+
+ if( pointCount == 1 )
+ {
+ plot( rPoly.getB2DPoint(0) );
+ return;
+ }
+
+ sal_uInt32 i;
+ for( i=0; i<pointCount-1; ++i )
+ {
+ if(rPoly.isNextControlPointUsed(i) || rPoly.isPrevControlPointUsed(i + 1))
+ {
+ const B2DCubicBezier aBezierPlot(
+ rPoly.getB2DPoint(i), rPoly.getNextControlPoint(i),
+ rPoly.getPrevControlPoint(i + 1), rPoly.getB2DPoint(i + 1));
+
+ plot(aBezierPlot);
+ }
+ else
+ {
+ plot( rPoly.getB2DPoint(i), rPoly.getB2DPoint(i+1) );
+ }
+ }
+ }
+
+ void Plotter::plot( const B2DPolyPolygon& rPolyPoly )
+ {
+ const sal_uInt32 nPolyCount( rPolyPoly.count() );
+
+ sal_uInt32 i;
+ for( i=0; i<nPolyCount; ++i )
+ {
+ plot( rPolyPoly.getB2DPolygon(i) );
+ }
+ }
+
+ void Plotter::plot( const B2DPoint& rPoint )
+ {
+ maPoints.push_back( rPoint );
+ writeSeparator();
+ mrOutputStream << "'-' using ($1):($2) title \"Point " << maPoints.size() << "\" with points";
+ }
+
+ void Plotter::plot( const B2DRange& rRect )
+ {
+ // TODO: do that also as a data file plot. maPoints must
+ // then become polymorph, but WTF.
+
+ // decompose into four lines
+ plot( B2DPoint(rRect.getMinX(),
+ rRect.getMinY()),
+ B2DPoint(rRect.getMaxX(),
+ rRect.getMinY()) );
+ plot( B2DPoint(rRect.getMaxX(),
+ rRect.getMinY()),
+ B2DPoint(rRect.getMaxX(),
+ rRect.getMaxY()) );
+ plot( B2DPoint(rRect.getMaxX(),
+ rRect.getMaxY()),
+ B2DPoint(rRect.getMinX(),
+ rRect.getMaxY()) );
+ plot( B2DPoint(rRect.getMinX(),
+ rRect.getMaxY()),
+ B2DPoint(rRect.getMinX(),
+ rRect.getMinY()) );
+ }
+
+ void Plotter::plot( const B2DPoint& rStartPoint, const B2DPoint& rEndPoint )
+ {
+ writeSeparator();
+ mrOutputStream << "line(" << rStartPoint.getX()
+ << "," << rEndPoint.getX()
+ << ",t), "
+ << "line(" << rStartPoint.getY()
+ << "," << rEndPoint.getY()
+ << ",t)";
+ }
+
+ void Plotter::plot( const B2DCubicBezier& rCurve )
+ {
+ writeSeparator();
+ mrOutputStream << "cubicBezier(" << rCurve.getStartPoint().getX()
+ << "," << rCurve.getControlPointA().getX()
+ << "," << rCurve.getControlPointB().getX()
+ << "," << rCurve.getEndPoint().getX()
+ << ",t), "
+ << "cubicBezier(" << rCurve.getStartPoint().getY()
+ << "," << rCurve.getControlPointA().getY()
+ << "," << rCurve.getControlPointB().getY()
+ << "," << rCurve.getEndPoint().getY()
+ << ",t)";
+ }
+
+ void Plotter::writeSeparator()
+ {
+ if( mbFirstElement )
+ {
+ mbFirstElement = false;
+ }
+ else
+ {
+ mrOutputStream << ", ";
+ }
+ }
+
+ }
+}
diff --git a/basegfx/test/testtools.hxx b/basegfx/test/testtools.hxx
new file mode 100644
index 000000000000..1837f9f31a89
--- /dev/null
+++ b/basegfx/test/testtools.hxx
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _BASEGFX_TESTTOOLS_HXX
+#define _BASEGFX_TESTTOOLS_HXX
+
+#include <basegfx/point/b2dpoint.hxx>
+
+#include <vector>
+#include <iostream>
+
+
+namespace basegfx
+{
+ class B2DCubicBezier;
+ class B2DPolygon;
+ class B2DPolyPolygon;
+ class B2DRange;
+
+ namespace testtools
+ {
+ class Plotter
+ {
+ public:
+ /** Create a plotter for the given output stream
+
+ This class can be used to generate gnuplot scripts for
+ a number of basegfx graphics primitives, useful for
+ debugging, regression-testing and comparing basegfx.
+ */
+ Plotter( ::std::ostream& rOutputStream );
+
+ /** Delete the plotter
+
+ This implicitely flushes all potential pending writes
+ to the output stream
+ */
+ ~Plotter();
+
+ /** Plot a 2d polygon into the current graph
+ */
+ void plot( const B2DPolygon& rPoly );
+
+ /** Plot a 2d polyPolygon into the current graph
+ */
+ void plot( const B2DPolyPolygon& rPolyPoly );
+
+ /** Plot a 2d point into the current graph
+ */
+ void plot( const B2DPoint& rPoint );
+
+ /** Plot a 2d rectangle into the current graph
+ */
+ void plot( const B2DRange& rRect );
+
+ /** Plot a 2d line into the current graph
+ */
+ void plot( const B2DPoint& rStartPoint, const B2DPoint& rEndPoint );
+
+ /** Plot a 2d cubic bezier curve into the current graph
+ */
+ void plot( const B2DCubicBezier& rCurve );
+
+ private:
+ void writeSeparator();
+
+ ::std::ostream& mrOutputStream;
+ ::std::vector< B2DPoint > maPoints;
+ bool mbFirstElement;
+ };
+ }
+}
+
+#endif /* _BASEGFX_TESTTOOLS_HXX */