summaryrefslogtreecommitdiffstats
path: root/basegfx/test
diff options
context:
space:
mode:
Diffstat (limited to 'basegfx/test')
-rw-r--r--basegfx/test/B1DRangeTest.cxx96
-rw-r--r--basegfx/test/B2DHomMatrixTest.cxx562
-rw-r--r--basegfx/test/B2DPointTest.cxx180
-rw-r--r--basegfx/test/B2DPolyPolygonCutterTest.cxx103
-rw-r--r--basegfx/test/B2DPolyPolygonTest.cxx81
-rw-r--r--basegfx/test/B2DPolyRangeTest.cxx65
-rw-r--r--basegfx/test/B2DPolygonTest.cxx111
-rw-r--r--basegfx/test/B2DPolygonToolsTest.cxx84
-rw-r--r--basegfx/test/B2DRangeTest.cxx71
-rw-r--r--basegfx/test/B2DTupleTest.cxx230
-rw-r--r--basegfx/test/B2IBoxTest.cxx62
-rw-r--r--basegfx/test/B2IRangeTest.cxx47
-rw-r--r--basegfx/test/B2XRangeTest.cxx69
-rw-r--r--basegfx/test/B3DTupleTest.cxx194
-rwxr-xr-xbasegfx/test/BColorModifierTest.cxx188
-rw-r--r--basegfx/test/BColorTest.cxx150
-rw-r--r--basegfx/test/SvgPathImportExport.cxx241
-rw-r--r--basegfx/test/VectorTest.cxx85
-rw-r--r--basegfx/test/basegfx3d.cxx123
-rw-r--r--basegfx/test/basegfxtools.cxx89
-rw-r--r--basegfx/test/boxclipper.cxx407
-rw-r--r--basegfx/test/boxclipper.hxx31
-rw-r--r--basegfx/test/clipstate.cxx153
-rw-r--r--basegfx/test/genericclipper.cxx188
24 files changed, 3610 insertions, 0 deletions
diff --git a/basegfx/test/B1DRangeTest.cxx b/basegfx/test/B1DRangeTest.cxx
new file mode 100644
index 000000000..22cf662de
--- /dev/null
+++ b/basegfx/test/B1DRangeTest.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/range/b1drange.hxx>
+
+namespace basegfx
+{
+class b1Xrange : public CppUnit::TestFixture
+{
+public:
+ template <class Type> void implCheck()
+ {
+ // test interval axioms
+ // (http://en.wikipedia.org/wiki/Interval_%28mathematics%29)
+ Type aRange;
+ CPPUNIT_ASSERT_MESSAGE("default ctor - empty range", aRange.isEmpty());
+ CPPUNIT_ASSERT_MESSAGE("center - get cop-out value since range is empty",
+ aRange.getCenter() == 0);
+
+ // degenerate interval
+ aRange.expand(1);
+ CPPUNIT_ASSERT_MESSAGE("degenerate range - still, not empty!", !aRange.isEmpty());
+ CPPUNIT_ASSERT_MESSAGE("degenerate range - size of 0", aRange.getRange() == 0);
+ CPPUNIT_ASSERT_MESSAGE("same value as degenerate range - is inside range",
+ aRange.isInside(1));
+ CPPUNIT_ASSERT_MESSAGE("center - must be the single range value", aRange.getCenter() == 1);
+
+ // proper interval
+ aRange.expand(2);
+ CPPUNIT_ASSERT_MESSAGE("proper range - size of 1", aRange.getRange() == 1);
+ CPPUNIT_ASSERT_MESSAGE("smaller value of range - is inside *closed* range",
+ aRange.isInside(1));
+ CPPUNIT_ASSERT_MESSAGE("larger value of range - is inside *closed* range",
+ aRange.isInside(2));
+
+ // center for proper interval that works for ints, too
+ aRange.expand(3);
+ CPPUNIT_ASSERT_MESSAGE("center - must be half of the range", aRange.getCenter() == 2);
+
+ // check overlap
+ Type aRange2(0, 1);
+ CPPUNIT_ASSERT_MESSAGE("range overlapping *includes* upper bound",
+ aRange.overlaps(aRange2));
+ CPPUNIT_ASSERT_MESSAGE("range overlapping *includes* upper bound, but only barely",
+ !aRange.overlapsMore(aRange2));
+
+ Type aRange3(0, 2);
+ CPPUNIT_ASSERT_MESSAGE("range overlapping is fully overlapping now",
+ aRange.overlapsMore(aRange3));
+
+ // check intersect
+ Type aRange4(3, 4);
+ aRange.intersect(aRange4);
+ CPPUNIT_ASSERT_MESSAGE("range intersection is yielding empty range!", !aRange.isEmpty());
+
+ Type aRange5(5, 6);
+ aRange.intersect(aRange5);
+ CPPUNIT_ASSERT_MESSAGE("range intersection is yielding nonempty range!", aRange.isEmpty());
+ }
+
+ void check() { implCheck<B1DRange>(); }
+
+ // 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(b1Xrange);
+ CPPUNIT_TEST(check);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b1Xrange
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b1Xrange);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DHomMatrixTest.cxx b/basegfx/test/B2DHomMatrixTest.cxx
new file mode 100644
index 000000000..bd6b1f8c8
--- /dev/null
+++ b/basegfx/test/B2DHomMatrixTest.cxx
@@ -0,0 +1,562 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/range/b2drange.hxx>
+
+namespace basegfx
+{
+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() override
+ {
+ // 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 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.operator==(maIdentity));
+ CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale.operator==(maScale));
+ CPPUNIT_ASSERT_MESSAGE("operator==: translate matrix", aTranslate.operator==(maTranslate));
+ CPPUNIT_ASSERT_MESSAGE("operator==: shear matrix", aShear.operator==(maShear));
+ CPPUNIT_ASSERT_MESSAGE("operator==: affine matrix", aAffine.operator==(maAffine));
+ CPPUNIT_ASSERT_MESSAGE("operator==: perspective matrix",
+ aPerspective.operator==(maPerspective));
+ }
+
+ void identity()
+ {
+ B2DHomMatrix ident;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("identity", maIdentity, ident);
+ }
+
+ void scale()
+ {
+ B2DHomMatrix mat;
+ mat.scale(2.0, 20.0);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("scale", maScale, mat);
+ }
+
+ void rotate()
+ {
+ B2DHomMatrix mat;
+ mat.rotate(M_PI_2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", 0.0, mat.get(0, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", -1.0, mat.get(0, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", 0.0, mat.get(0, 2),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", 1.0, mat.get(1, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", 0.0, mat.get(1, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi/2 yields exact matrix", 0.0, mat.get(1, 2),
+ 1E-12);
+ mat.rotate(M_PI_2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", -1.0, mat.get(0, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", 0.0, mat.get(0, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", 0.0, mat.get(0, 2),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", 0.0, mat.get(1, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", -1.0, mat.get(1, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate pi yields exact matrix", 0.0, mat.get(1, 2),
+ 1E-12);
+ mat.rotate(M_PI_2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", 0.0,
+ mat.get(0, 0), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", 1.0,
+ mat.get(0, 1), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", 0.0,
+ mat.get(0, 2), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", -1.0,
+ mat.get(1, 0), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", 0.0,
+ mat.get(1, 1), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 3/2 pi yields exact matrix", 0.0,
+ mat.get(1, 2), 1E-12);
+ mat.rotate(M_PI_2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 1.0, mat.get(0, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 0.0, mat.get(0, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 0.0, mat.get(0, 2),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 0.0, mat.get(1, 0),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 1.0, mat.get(1, 1),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("rotate 2 pi yields exact matrix", 0.0, mat.get(1, 2),
+ 1E-12);
+ }
+
+ void translate()
+ {
+ B2DHomMatrix mat;
+ mat.translate(20.0, 2.0);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("translate", maTranslate, mat);
+ }
+
+ void shear()
+ {
+ B2DHomMatrix mat;
+ mat.shearX(3.0);
+ mat.shearY(7.0);
+ CPPUNIT_ASSERT_EQUAL_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_EQUAL_MESSAGE("multiply: both compact", affineAffineProd, temp);
+
+ temp = maPerspective;
+ temp *= maAffine;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: first compact", affinePerspectiveProd, temp);
+
+ temp = maAffine;
+ temp *= maPerspective;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: second compact", perspectiveAffineProd, temp);
+
+ temp = maPerspective;
+ temp *= maPerspective;
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: none compact", perspectivePerspectiveProd, temp);
+ }
+
+ void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX,
+ double fRotate) const
+ {
+ // 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) const
+ {
+ // 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 const double fSX(10.0);
+ static const double fSY(12.0);
+ static const double fR(M_PI_4);
+ static const double fS(deg2rad(15.0));
+
+ // 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));
+
+ // cover special case of 180 degree rotation
+ B2DHomMatrix aTest
+ = utils::createScaleShearXRotateTranslateB2DHomMatrix(6425, 3938, 0, M_PI, 10482, 4921);
+ // decompose that matrix
+ B2DTuple aDScale;
+ B2DTuple aDTrans;
+ double fDRot;
+ double fDShX;
+ aTest.decompose(aDScale, aDTrans, fDRot, fDShX);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("decompose: error test J1", 6425.0, aDScale.getX(),
+ 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("decompose: error test J1", 3938.0, aDScale.getY(),
+ 1E-12);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("decompose: error test J1", 10482.0, aDTrans.getX());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("decompose: error test J1", 4921.0, aDTrans.getY());
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("decompose: error test J1", M_PI, fDRot, 1E-12);
+ }
+
+ void testCreate_abcdef()
+ {
+ B2DHomMatrix aB2DMatrix(00, 01, 02, 10, 11, 12);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(00, aB2DMatrix.a(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(10, aB2DMatrix.b(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(01, aB2DMatrix.c(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(11, aB2DMatrix.d(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(02, aB2DMatrix.e(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(12, aB2DMatrix.f(), 1E-12);
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(0, 0), aB2DMatrix.a(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(1, 0), aB2DMatrix.b(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(0, 1), aB2DMatrix.c(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(1, 1), aB2DMatrix.d(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(0, 2), aB2DMatrix.e(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(aB2DMatrix.get(1, 2), aB2DMatrix.f(), 1E-12);
+ }
+
+ void testMultiplyWithAnotherMatrix()
+ {
+ B2DHomMatrix aB2DMatrix(00, 01, 02, 10, 11, 12);
+ B2DHomMatrix aNewB2DMatrix = B2DHomMatrix::abcdef(1, 2, 3, 4, 5, 6);
+
+ aB2DMatrix *= aNewB2DMatrix;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(30, aB2DMatrix.get(0, 0), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(40, aB2DMatrix.get(1, 0), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(34, aB2DMatrix.get(0, 1), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(46, aB2DMatrix.get(1, 1), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(43, aB2DMatrix.get(0, 2), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(58, aB2DMatrix.get(1, 2), 1E-12);
+ }
+
+ void testTransformPoint()
+ {
+ B2DHomMatrix aNewB2DMatrix = B2DHomMatrix::abcdef(1, 2, 3, 4, 5, 6);
+
+ B2DPoint aPoint(1, 2);
+ aPoint *= aNewB2DMatrix;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(12, aPoint.getX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(16, aPoint.getY(), 1E-12);
+ }
+
+ void testTransformRange()
+ {
+ B2DHomMatrix aNewB2DMatrix = B2DHomMatrix::abcdef(1, 2, 3, 4, 5, 6);
+
+ B2DRange aRange(2, 1, 4, 3);
+ aRange *= aNewB2DMatrix;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(10, aRange.getMinX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(18, aRange.getMaxX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(14, aRange.getMinY(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(26, aRange.getMaxY(), 1E-12);
+ }
+
+ void testCoordinateSystemConversion()
+ {
+ // Use case when we convert
+
+ B2DRange aWindow(50, 50, 150, 150);
+
+ B2DRange aSubPage(0, 0, 2000, 2000);
+
+ B2DHomMatrix aB2DMatrix;
+ aB2DMatrix.scale(aWindow.getWidth() / aSubPage.getWidth(),
+ aWindow.getHeight() / aSubPage.getHeight());
+ aB2DMatrix.translate(aWindow.getMinX(), aWindow.getMinY());
+
+ B2DPoint aPoint1(0, 0);
+ aPoint1 *= aB2DMatrix;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(50, aPoint1.getX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(50, aPoint1.getY(), 1E-12);
+
+ B2DPoint aPoint2(1000, 1000);
+ aPoint2 *= aB2DMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(100, aPoint2.getX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(100, aPoint2.getY(), 1E-12);
+
+ B2DPoint aPoint3(2000, 2000);
+ aPoint3 *= aB2DMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(150, aPoint3.getX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(150, aPoint3.getY(), 1E-12);
+ }
+
+ // 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(rotate);
+ CPPUNIT_TEST(shear);
+ CPPUNIT_TEST(multiply);
+ CPPUNIT_TEST(decompose);
+ CPPUNIT_TEST(testCreate_abcdef);
+ CPPUNIT_TEST(testMultiplyWithAnotherMatrix);
+ CPPUNIT_TEST(testTransformPoint);
+ CPPUNIT_TEST(testTransformRange);
+ CPPUNIT_TEST(testCoordinateSystemConversion);
+
+ CPPUNIT_TEST_SUITE_END();
+
+}; // class b2dhommatrix
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dhommatrix);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPointTest.cxx b/basegfx/test/B2DPointTest.cxx
new file mode 100644
index 000000000..29b73aebc
--- /dev/null
+++ b/basegfx/test/B2DPointTest.cxx
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <cmath>
+#include <sstream>
+
+class B2DPointTest : public CppUnit::TestFixture
+{
+public:
+ void testCreation();
+ void testSet();
+ void testTimesEquals();
+ void testMultipy();
+ void testAssignment();
+ void testGetEmptyPoint();
+ void testOutputOperator();
+
+ CPPUNIT_TEST_SUITE(B2DPointTest);
+ CPPUNIT_TEST(testCreation);
+ CPPUNIT_TEST(testSet);
+ CPPUNIT_TEST(testTimesEquals);
+ CPPUNIT_TEST(testMultipy);
+ CPPUNIT_TEST(testAssignment);
+ CPPUNIT_TEST(testGetEmptyPoint);
+ CPPUNIT_TEST(testOutputOperator);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void B2DPointTest::testCreation()
+{
+ basegfx::B2DPoint aPointDefault;
+ CPPUNIT_ASSERT_EQUAL(0.0, aPointDefault.getX());
+ CPPUNIT_ASSERT_EQUAL(0.0, aPointDefault.getY());
+
+ basegfx::B2DPoint aPoint1(5.0, 2.0);
+ CPPUNIT_ASSERT_EQUAL(5.0, aPoint1.getX());
+ CPPUNIT_ASSERT_EQUAL(2.0, aPoint1.getY());
+
+ basegfx::B2DPoint aPointCopy(aPoint1);
+ CPPUNIT_ASSERT_EQUAL(5.0, aPointCopy.getX());
+ CPPUNIT_ASSERT_EQUAL(2.0, aPointCopy.getY());
+
+ basegfx::B2DPoint aPoint2 = { 5.0, 2.0 };
+ CPPUNIT_ASSERT_EQUAL(5.0, aPoint2.getX());
+ CPPUNIT_ASSERT_EQUAL(2.0, aPoint2.getY());
+
+ basegfx::B2IPoint aPointI1(1, 2);
+ basegfx::B2DPoint aPointFromI(aPointI1);
+ CPPUNIT_ASSERT_EQUAL(1.0, aPointFromI.getX());
+ CPPUNIT_ASSERT_EQUAL(2.0, aPointFromI.getY());
+
+ basegfx::B2DTuple aTuple(3.5, 4.5);
+ basegfx::B2DPoint aPointFromTuple(aTuple);
+ CPPUNIT_ASSERT_EQUAL(3.5, aPointFromTuple.getX());
+ CPPUNIT_ASSERT_EQUAL(4.5, aPointFromTuple.getY());
+
+ std::vector<basegfx::B2DPoint> aPointVector{
+ { 5.0, 2.0 },
+ { 4.0, 3.0 },
+ };
+ CPPUNIT_ASSERT_EQUAL(5.0, aPointVector[0].getX());
+ CPPUNIT_ASSERT_EQUAL(2.0, aPointVector[0].getY());
+ CPPUNIT_ASSERT_EQUAL(4.0, aPointVector[1].getX());
+ CPPUNIT_ASSERT_EQUAL(3.0, aPointVector[1].getY());
+}
+
+void B2DPointTest::testSet()
+{
+ basegfx::B2DPoint aPoint;
+ aPoint.setX(1.1);
+ aPoint.setY(2.2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.1, aPoint.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.2, aPoint.getY(), 0.0000001);
+}
+
+void B2DPointTest::testTimesEquals()
+{
+ basegfx::B2DPoint aPoint1(1.1, 2.2);
+ basegfx::B2DPoint aPoint2(3.0, 4.0);
+ aPoint1 *= aPoint2;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(3.3, aPoint1.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8.8, aPoint1.getY(), 0.0000001);
+
+ aPoint2 *= 1.5;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4.5, aPoint2.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0, aPoint2.getY(), 0.0000001);
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.identity();
+ aPoint1 *= aMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(3.3, aPoint1.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8.8, aPoint1.getY(), 0.0000001);
+
+ aMatrix.translate(1.0, 2.0);
+ aPoint1 *= aMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4.3, aPoint1.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(10.8, aPoint1.getY(), 0.0000001);
+
+ aMatrix.identity();
+ aMatrix.rotate(-M_PI_4);
+ aPoint1.setX(1.0);
+ aPoint1.setY(1.0);
+ aPoint1 *= aMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.0), aPoint1.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aPoint1.getY(), 0.0000001);
+
+ aMatrix.identity();
+ aMatrix.translate(0.0, 1.0);
+ aMatrix.rotate(M_PI_4);
+ aMatrix.scale(2.0, 2.0);
+ aMatrix.shearX(2.0);
+ aMatrix.shearY(3.0);
+ aPoint1.setX(0);
+ aPoint1.setY(0);
+ aPoint1 *= aMatrix;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(sqrt(2.0), aPoint1.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4.0 * sqrt(2.0), aPoint1.getY(), 0.0000001);
+}
+void B2DPointTest::testMultipy()
+{
+ basegfx::B2DPoint aPoint(1, 2);
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.identity();
+ aMatrix.rotate(M_PI);
+ basegfx::B2DPoint aResult = aMatrix * aPoint;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-1, aResult.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-2, aResult.getY(), 0.0000001);
+}
+
+void B2DPointTest::testAssignment()
+{
+ basegfx::B2DTuple aTuple(2.5, 5.5);
+ basegfx::B2DPoint aPoint(0, 0);
+ aPoint = aTuple;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.5, aPoint.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.5, aPoint.getY(), 0.0000001);
+
+ basegfx::B2DPoint aPoint2(3.2, 6.2);
+ aPoint = aPoint2;
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(3.2, aPoint.getX(), 0.0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6.2, aPoint.getY(), 0.0000001);
+}
+void B2DPointTest::testGetEmptyPoint()
+{
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, basegfx::B2DPoint::getEmptyPoint().getX(), .0000001);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, basegfx::B2DPoint::getEmptyPoint().getY(), .0000001);
+}
+
+void B2DPointTest::testOutputOperator()
+{
+ std::ostringstream aOut;
+ basegfx::B2DPoint aPoint(2.0, 3.0);
+ aOut << aPoint;
+ std::string aResult = aOut.str();
+ CPPUNIT_ASSERT_EQUAL(std::string("(2,3)"), aResult);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(B2DPointTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPolyPolygonCutterTest.cxx b/basegfx/test/B2DPolyPolygonCutterTest.cxx
new file mode 100644
index 000000000..b111bf469
--- /dev/null
+++ b/basegfx/test/B2DPolyPolygonCutterTest.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+
+namespace basegfx
+{
+class b2dpolypolygoncutter : public CppUnit::TestFixture
+{
+public:
+ void testMergeToSinglePolyPolygon()
+ {
+ { // Adjacent polygons merged to one, closed manually.
+ B2DPolygon poly1{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, { 0, 0 } };
+ B2DPolygon poly2{ { 0, 1 }, { 1, 1 }, { 1, 2 }, { 0, 2 }, { 0, 1 } };
+ B2DPolyPolygon expected(
+ B2DPolygon{ { 1, 0 }, { 1, 1 }, { 1, 2 }, { 0, 2 }, { 0, 1 }, { 0, 0 } });
+ expected.setClosed(true);
+ B2DPolyPolygon result
+ = utils::mergeToSinglePolyPolygon({ B2DPolyPolygon(poly1), B2DPolyPolygon(poly2) });
+ CPPUNIT_ASSERT_EQUAL(expected, result);
+ }
+
+ { // Adjacent polygons merged to one, closed using setClosed().
+ B2DPolygon poly1{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
+ B2DPolygon poly2{ { 0, 1 }, { 1, 1 }, { 1, 2 }, { 0, 2 } };
+ poly1.setClosed(true);
+ poly2.setClosed(true);
+ B2DPolyPolygon expected(
+ B2DPolygon{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }, { 0, 2 }, { 0, 1 } });
+ expected.setClosed(true);
+ B2DPolyPolygon result
+ = utils::mergeToSinglePolyPolygon({ B2DPolyPolygon(poly1), B2DPolyPolygon(poly2) });
+ CPPUNIT_ASSERT_EQUAL(expected, result);
+ }
+
+ { // Non-adjacent polygons, no merge.
+ B2DPolygon poly1{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
+ B2DPolygon poly2{ { 0, 2 }, { 1, 3 }, { 1, 3 }, { 0, 3 } };
+ poly1.setClosed(true);
+ poly2.setClosed(true);
+ B2DPolyPolygon expected;
+ expected.append(poly1);
+ expected.append(poly2);
+ B2DPolyPolygon result
+ = utils::mergeToSinglePolyPolygon({ B2DPolyPolygon(poly1), B2DPolyPolygon(poly2) });
+ CPPUNIT_ASSERT_EQUAL(expected, result);
+ }
+
+ { // Horizontal and vertical rectangle that together form a cross.
+ B2DPolygon poly1{ { 1, 0 }, { 2, 0 }, { 2, 3 }, { 1, 3 } };
+ B2DPolygon poly2{ { 0, 1 }, { 3, 1 }, { 3, 2 }, { 0, 2 } };
+ poly1.setClosed(true);
+ poly2.setClosed(true);
+ B2DPolyPolygon expected(B2DPolygon{ { 1, 0 },
+ { 2, 0 },
+ { 2, 1 },
+ { 3, 1 },
+ { 3, 2 },
+ { 2, 2 },
+ { 2, 3 },
+ { 1, 3 },
+ { 1, 2 },
+ { 0, 2 },
+ { 0, 1 },
+ { 1, 1 } });
+ expected.setClosed(true);
+ B2DPolyPolygon result
+ = utils::mergeToSinglePolyPolygon({ B2DPolyPolygon(poly1), B2DPolyPolygon(poly2) });
+ CPPUNIT_ASSERT_EQUAL(expected, result);
+ }
+ }
+
+ CPPUNIT_TEST_SUITE(b2dpolypolygoncutter);
+ CPPUNIT_TEST(testMergeToSinglePolyPolygon);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dpolypolygoncutter);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPolyPolygonTest.cxx b/basegfx/test/B2DPolyPolygonTest.cxx
new file mode 100644
index 000000000..1fef45328
--- /dev/null
+++ b/basegfx/test/B2DPolyPolygonTest.cxx
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dtrapezoid.hxx>
+
+#include "boxclipper.hxx"
+
+namespace basegfx
+{
+using ::basegfx2d::getRandomOrdinal;
+
+class b2dpolypolygon : public CppUnit::TestFixture
+{
+public:
+ // insert your test code here.
+ void testTrapezoidHelper()
+ {
+ B2DPolygon aPolygon;
+ // provoke the PointBlockAllocator to exercise the freeIfLast path
+ for (int i = 0; i < 16 * 10; i++)
+ {
+ B2DPoint aPoint(getRandomOrdinal(1000), getRandomOrdinal(1000));
+ aPolygon.append(aPoint);
+ }
+ // scatter some duplicate points in to stress things more.
+ for (int i = 0; i < 16 * 10; i++)
+ {
+ aPolygon.insert(getRandomOrdinal(aPolygon.count() - 1),
+ aPolygon.getB2DPoint(getRandomOrdinal(aPolygon.count() - 1)));
+ }
+ B2DPolygon aPolygonOffset;
+ // duplicate the polygon and offset it slightly.
+ for (size_t i = 0; i < aPolygon.count(); i++)
+ {
+ B2DPoint aPoint(aPolygon.getB2DPoint(i));
+ aPoint += B2DPoint(0.5 - getRandomOrdinal(1), 0.5 - getRandomOrdinal(1));
+ aPolygonOffset.append(aPoint);
+ }
+ B2DPolyPolygon aPolyPolygon;
+ aPolyPolygon.append(aPolygon);
+ aPolyPolygon.append(aPolygonOffset);
+ B2DTrapezoidVector aVector;
+ basegfx::utils::trapezoidSubdivide(aVector, aPolyPolygon);
+ CPPUNIT_ASSERT_MESSAGE("more than zero sub-divided trapezoids", !aVector.empty());
+ }
+
+ // 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(testTrapezoidHelper);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpolypolygon
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dpolypolygon);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPolyRangeTest.cxx b/basegfx/test/B2DPolyRangeTest.cxx
new file mode 100644
index 000000000..84e66fa24
--- /dev/null
+++ b/basegfx/test/B2DPolyRangeTest.cxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2dpolyrange.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+namespace basegfx
+{
+class b2dpolyrange : public CppUnit::TestFixture
+{
+private:
+public:
+ void check()
+ {
+ B2DPolyRange aRange;
+ aRange.appendElement(B2DRange(0, 0, 1, 1), B2VectorOrientation::Positive);
+ aRange.appendElement(B2DRange(2, 2, 3, 3), B2VectorOrientation::Positive);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("simple poly range - count", sal_uInt32(2), aRange.count());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("simple poly range - first element", B2DRange(0, 0, 1, 1),
+ std::get<0>(aRange.getElement(0)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("simple poly range - second element", B2DRange(2, 2, 3, 3),
+ std::get<0>(aRange.getElement(1)));
+
+ // B2DPolyRange relies on correctly orientated rects
+ const B2DRange aRect(0, 0, 1, 1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("createPolygonFromRect - correct orientation",
+ B2VectorOrientation::Positive,
+ utils::getOrientation(utils::createPolygonFromRect(aRect)));
+ }
+
+ // 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();
+};
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dpolyrange);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPolygonTest.cxx b/basegfx/test/B2DPolygonTest.cxx
new file mode 100644
index 000000000..581108b96
--- /dev/null
+++ b/basegfx/test/B2DPolygonTest.cxx
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+namespace basegfx
+{
+class b2dpolygon : public CppUnit::TestFixture
+{
+public:
+ void testCubicBezier()
+ {
+ B2DPolygon aPoly;
+
+ aPoly.appendBezierSegment(B2DPoint(1, 1), B2DPoint(2, 2), B2DPoint(3, 3));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#1 first polygon point wrong", B2DPoint(3, 3),
+ aPoly.getB2DPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#1 first control point wrong", B2DPoint(2, 2),
+ aPoly.getPrevControlPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#1 second control point wrong", B2DPoint(3, 3),
+ aPoly.getNextControlPoint(0));
+ CPPUNIT_ASSERT_MESSAGE("next control point not used", !aPoly.isNextControlPointUsed(0));
+
+ aPoly.setNextControlPoint(0, B2DPoint(4, 4));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#1.1 second control point wrong", B2DPoint(4, 4),
+ aPoly.getNextControlPoint(0));
+ CPPUNIT_ASSERT_MESSAGE("next control point used", aPoly.isNextControlPointUsed(0));
+ CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong", aPoly.areControlPointsUsed());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("getContinuityInPoint() wrong", B2VectorContinuity::C2,
+ aPoly.getContinuityInPoint(0));
+
+ aPoly.resetControlPoints();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("resetControlPoints() did not clear", B2DPoint(3, 3),
+ aPoly.getB2DPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("resetControlPoints() did not clear", B2DPoint(3, 3),
+ aPoly.getPrevControlPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("resetControlPoints() did not clear", B2DPoint(3, 3),
+ aPoly.getNextControlPoint(0));
+ CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong #2", !aPoly.areControlPointsUsed());
+
+ aPoly.clear();
+ aPoly.append(B2DPoint(0, 0));
+ aPoly.appendBezierSegment(B2DPoint(1, 1), B2DPoint(2, 2), B2DPoint(3, 3));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 first polygon point wrong", B2DPoint(0, 0),
+ aPoly.getB2DPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 first control point wrong", B2DPoint(0, 0),
+ aPoly.getPrevControlPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 second control point wrong", B2DPoint(1, 1),
+ aPoly.getNextControlPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 third control point wrong", B2DPoint(2, 2),
+ aPoly.getPrevControlPoint(1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 fourth control point wrong", B2DPoint(3, 3),
+ aPoly.getNextControlPoint(1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("#2 second polygon point wrong", B2DPoint(3, 3),
+ aPoly.getB2DPoint(1));
+ }
+
+ void testQuadraticBezier()
+ {
+ B2DPolygon aPoly;
+
+ aPoly.appendQuadraticBezierSegment(B2DPoint(0, 0), B2DPoint(3, 3));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("polygon size is wrong", sal_uInt32(1), aPoly.count());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("first polygon point wrong", B2DPoint(3, 3),
+ aPoly.getB2DPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("first control point wrong", B2DPoint(1, 1),
+ aPoly.getPrevControlPoint(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("second control point wrong", B2DPoint(3, 3),
+ aPoly.getNextControlPoint(0));
+ CPPUNIT_ASSERT_MESSAGE("next control point not used", !aPoly.isNextControlPointUsed(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(b2dpolygon);
+ CPPUNIT_TEST(testCubicBezier);
+ CPPUNIT_TEST(testQuadraticBezier);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2dpolygon
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dpolygon);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DPolygonToolsTest.cxx b/basegfx/test/B2DPolygonToolsTest.cxx
new file mode 100644
index 000000000..8d9ae4e64
--- /dev/null
+++ b/basegfx/test/B2DPolygonToolsTest.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+namespace basegfx
+{
+class b2dpolygontools : public CppUnit::TestFixture
+{
+public:
+ // insert your test code here.
+ // this is only demonstration code
+ void testIsRectangle()
+ {
+ B2DPolygon aRect1(utils::createPolygonFromRect(B2DRange(0, 0, 1, 1)));
+
+ B2DPolygon aRect2{ { 0, 0 }, { 1, 0 }, { 1, 0.5 }, { 1, 1 }, { 0, 1 } };
+ aRect2.setClosed(true);
+
+ B2DPolygon aNonRect1{ { 0, 0 }, { 1, 0 }, { 0.5, 1 }, { 0.5, 0 } };
+ aNonRect1.setClosed(true);
+
+ B2DPolygon aNonRect2{ { 0, 0 }, { 1, 1 }, { 1, 0 }, { 0, 1 } };
+ aNonRect2.setClosed(true);
+
+ B2DPolygon aNonRect3{ { 0, 0 }, { 1, 0 }, { 1, 1 } };
+ aNonRect3.setClosed(true);
+
+ B2DPolygon aNonRect4{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
+
+ B2DPolygon aNonRect5{ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 } };
+ aNonRect5.setControlPoints(1, B2DPoint(1, 0), B2DPoint(-11, 0));
+ aNonRect5.setClosed(true);
+
+ CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 1",
+ utils::isRectangle(aRect1));
+ CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 2",
+ utils::isRectangle(aRect2));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 1",
+ !utils::isRectangle(aNonRect1));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 2",
+ !utils::isRectangle(aNonRect2));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 3",
+ !utils::isRectangle(aNonRect3));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 4",
+ !utils::isRectangle(aNonRect4));
+ CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 5",
+ !utils::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
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2dpolygontools);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DRangeTest.cxx b/basegfx/test/B2DRangeTest.cxx
new file mode 100644
index 000000000..862fe7e5b
--- /dev/null
+++ b/basegfx/test/B2DRangeTest.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+
+class B2DRangeTest : public CppUnit::TestFixture
+{
+ void testCreation()
+ {
+ basegfx::B2DRange aRange(1.2, 2.3, 3.5, 4.8);
+ CPPUNIT_ASSERT_EQUAL(1.2, aRange.getMinX());
+ CPPUNIT_ASSERT_EQUAL(3.5, aRange.getMaxX());
+ CPPUNIT_ASSERT_EQUAL(2.3, aRange.getMinY());
+ CPPUNIT_ASSERT_EQUAL(4.8, aRange.getMaxY());
+
+ CPPUNIT_ASSERT_EQUAL(2.3, aRange.getWidth());
+ CPPUNIT_ASSERT_EQUAL(2.5, aRange.getHeight());
+ }
+
+ void testRound()
+ {
+ basegfx::B2DRange aRange(1.2, 2.3, 3.5, 4.8);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("simple range rounding from double to integer",
+ basegfx::B2IRange(1, 2, 4, 5), fround(aRange));
+ }
+
+ void testCenter()
+ {
+ basegfx::B2DRange aRange(1.0, 2.0, 2.0, 3.0);
+ CPPUNIT_ASSERT_EQUAL(1.5, aRange.getCenterX());
+ CPPUNIT_ASSERT_EQUAL(2.5, aRange.getCenterY());
+ }
+
+ // 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(B2DRangeTest);
+ CPPUNIT_TEST(testCreation);
+ CPPUNIT_TEST(testRound);
+ CPPUNIT_TEST(testCenter);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(B2DRangeTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2DTupleTest.cxx b/basegfx/test/B2DTupleTest.cxx
new file mode 100644
index 000000000..100808fe8
--- /dev/null
+++ b/basegfx/test/B2DTupleTest.cxx
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/tuple/b2dtuple.hxx>
+#include <basegfx/tuple/b2ituple.hxx>
+#include <basegfx/tuple/b2i64tuple.hxx>
+
+namespace basegfx
+{
+class B2DTupleTest : public CppUnit::TestFixture
+{
+public:
+ void testEmpty()
+ {
+ B2DTuple aTuple;
+ CPPUNIT_ASSERT_EQUAL(true, aTuple.equalZero());
+
+ B2ITuple aTupleInteger;
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInteger.equalZero());
+
+ B2I64Tuple aTupleLong;
+ CPPUNIT_ASSERT_EQUAL(true, aTupleLong.equalZero());
+ }
+
+ void testEquals()
+ {
+ B2DTuple aTuple(1.0, 1.0);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple.equal({ 1.0, 1.0 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple.equal({ 0.99, 0.99 }));
+
+ B2ITuple aTupleInteger(1, 1);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInteger.equal({ 1, 1 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInteger.equal({ 1, 0 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInteger.equal({ 0, 1 }));
+
+ B2I64Tuple aTupleLong(1, 1);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleLong.equal({ 1, 1 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleLong.equal({ 1, 0 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleLong.equal({ 0, 1 }));
+ }
+
+ void testOperatorAddition()
+ {
+ B2DTuple aTuple(4.0, 8.0);
+ aTuple += { 2.0, 3.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(11.0, aTuple.getY(), 1e-2);
+
+ B2ITuple aTupleInt(4, 8);
+ aTupleInt += { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(11), aTupleInt.getY());
+
+ B2I64Tuple aTuple64(4, 8);
+ aTuple64 += { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(6), aTuple64.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(11), aTuple64.getY());
+ }
+
+ void testOperatorSubstraction()
+ {
+ B2DTuple aTuple(4.0, 8.0);
+ aTuple -= { 2.0, 3.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, aTuple.getY(), 1e-2);
+
+ B2ITuple aTupleInt(4, 8);
+ aTupleInt -= { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aTupleInt.getY());
+
+ B2I64Tuple aTuple64(4, 8);
+ aTuple64 -= { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(2), aTuple64.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(5), aTuple64.getY());
+ }
+
+ void testOperatorMultiply()
+ {
+ B2DTuple aTuple(4.0, 8.0);
+ aTuple *= { 2.0, 3.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(24.0, aTuple.getY(), 1e-2);
+
+ aTuple *= 2.0;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(16.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(48.0, aTuple.getY(), 1e-2);
+
+ B2ITuple aTupleInt(4, 8);
+ aTupleInt *= { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(24), aTupleInt.getY());
+
+ aTupleInt *= 2.0;
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(16), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(48), aTupleInt.getY());
+
+ B2I64Tuple aTuple64(4, 8);
+ aTuple64 *= { 2, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(8), aTuple64.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(24), aTuple64.getY());
+
+ aTuple64 *= 2.0;
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(16), aTuple64.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(48), aTuple64.getY());
+ }
+
+ void testOperatorDivide()
+ {
+ B2DTuple aTuple(4.0, 8.0);
+ aTuple /= { 2.0, 8.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aTuple.getY(), 1e-2);
+
+ B2ITuple aTupleInt(4, 8);
+ aTupleInt /= { 2, 8 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aTupleInt.getY());
+
+ B2I64Tuple aTuple64(4, 8);
+ aTuple64 /= { 2, 8 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(2), aTuple64.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(1), aTuple64.getY());
+ }
+
+ void testOperatorEqualUnequal()
+ {
+ B2DTuple aTuple(4.0, 8.0);
+ B2DTuple aTuple2 = aTuple;
+
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == aTuple);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == aTuple2);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == B2DTuple(4.0, 8.0));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple == B2DTuple(4.0, 7.99));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple == B2DTuple(3.99, 8.0));
+
+ B2ITuple aTupleInt(4, 8);
+ B2ITuple aTupleInt2 = aTupleInt;
+
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == aTupleInt);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == aTupleInt2);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == B2ITuple(4, 8));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt == B2ITuple(4, 7));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt == B2ITuple(3, 8));
+
+ B2I64Tuple aTuple64(4, 8);
+ B2I64Tuple aTuple64_2 = aTuple64;
+
+ CPPUNIT_ASSERT_EQUAL(true, aTuple64 == aTuple64);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple64 == aTuple64_2);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple64 == B2I64Tuple(4, 8));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple64 == B2I64Tuple(4, 7));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple64 == B2I64Tuple(3, 8));
+ }
+
+ void testOperatorMinus()
+ {
+ B2DTuple aTupleMinus = -B2DTuple(4.0, 8.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-4.0, aTupleMinus.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-8.0, aTupleMinus.getY(), 1e-2);
+ B2DTuple aTupleZero = -B2DTuple(0.0, 0.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aTupleZero.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aTupleZero.getY(), 1e-2);
+
+ B2ITuple aTupleIntMinus = -B2ITuple(4, 8);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-4), aTupleIntMinus.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-8), aTupleIntMinus.getY());
+ B2ITuple aTupleIntZero = -B2ITuple(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aTupleIntZero.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aTupleIntZero.getY());
+
+ B2I64Tuple aTuple64Minus = -B2I64Tuple(4, 8);
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(-4), aTuple64Minus.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(-8), aTuple64Minus.getY());
+ B2I64Tuple aTuple64Zero = -B2I64Tuple(0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(0), aTuple64Zero.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int64(0), aTuple64Zero.getY());
+ }
+
+ CPPUNIT_TEST_SUITE(B2DTupleTest);
+ CPPUNIT_TEST(testEmpty);
+ CPPUNIT_TEST(testEquals);
+ CPPUNIT_TEST(testOperatorAddition);
+ CPPUNIT_TEST(testOperatorSubstraction);
+ CPPUNIT_TEST(testOperatorMultiply);
+ CPPUNIT_TEST(testOperatorDivide);
+ CPPUNIT_TEST(testOperatorEqualUnequal);
+ CPPUNIT_TEST(testOperatorMinus);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::B2DTupleTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2IBoxTest.cxx b/basegfx/test/B2IBoxTest.cxx
new file mode 100644
index 000000000..f236308ae
--- /dev/null
+++ b/basegfx/test/B2IBoxTest.cxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/range/b2ibox.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/utils/rectcliptools.hxx>
+
+namespace basegfx
+{
+class b2ibox : public CppUnit::TestFixture
+{
+public:
+ void TestBox()
+ {
+ // cohen sutherland clipping
+ B2IBox aBox(0, 0, 10, 10);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(0,0) is outside range!", sal_uInt32(0),
+ utils::getCohenSutherlandClipFlags(B2IPoint(0, 0), aBox));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(-1,-1) is inside range!",
+ utils::RectClipFlags::LEFT | utils::RectClipFlags::TOP,
+ utils::getCohenSutherlandClipFlags(B2IPoint(-1, -1), aBox));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(9,9) is outside range!", sal_uInt32(0),
+ utils::getCohenSutherlandClipFlags(B2IPoint(9, 9), aBox));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("(10,10) is inside range!",
+ utils::RectClipFlags::RIGHT | utils::RectClipFlags::BOTTOM,
+ utils::getCohenSutherlandClipFlags(B2IPoint(10, 10), aBox));
+ }
+
+ // 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(b2ibox);
+ CPPUNIT_TEST(TestBox);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2ibox
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2ibox);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2IRangeTest.cxx b/basegfx/test/B2IRangeTest.cxx
new file mode 100644
index 000000000..89d0d029f
--- /dev/null
+++ b/basegfx/test/B2IRangeTest.cxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <basegfx/range/b2irange.hxx>
+
+class B2IRangeTest : public CppUnit::TestFixture
+{
+ void testCreation()
+ {
+ basegfx::B2IRange aRange(1, 2, 3, 4);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aRange.getMinX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aRange.getMaxX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRange.getMinY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aRange.getMaxY());
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRange.getWidth());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aRange.getHeight());
+ }
+
+ void testCenter()
+ {
+ basegfx::B2IRange aRange(1, 2, 2, 3);
+ CPPUNIT_ASSERT_EQUAL(1.5, aRange.getCenterX());
+ CPPUNIT_ASSERT_EQUAL(2.5, aRange.getCenterY());
+ }
+
+ CPPUNIT_TEST_SUITE(B2IRangeTest);
+ CPPUNIT_TEST(testCreation);
+ CPPUNIT_TEST(testCenter);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(B2IRangeTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B2XRangeTest.cxx b/basegfx/test/B2XRangeTest.cxx
new file mode 100644
index 000000000..0a7c9930e
--- /dev/null
+++ b/basegfx/test/B2XRangeTest.cxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/utils/rectcliptools.hxx>
+
+namespace basegfx
+{
+class b2Xrange : public CppUnit::TestFixture
+{
+public:
+ template <class Type> void implCheck()
+ {
+ // cohen sutherland clipping
+ Type aRange(0, 0, 10, 10);
+
+ CPPUNIT_ASSERT_MESSAGE("(0,0) is outside range!",
+ utils::getCohenSutherlandClipFlags(B2IPoint(0, 0), aRange) == 0);
+ CPPUNIT_ASSERT_MESSAGE("(-1,-1) is inside range!",
+ utils::getCohenSutherlandClipFlags(B2IPoint(-1, -1), aRange)
+ == (utils::RectClipFlags::LEFT | utils::RectClipFlags::TOP));
+ CPPUNIT_ASSERT_MESSAGE("(10,10) is outside range!",
+ utils::getCohenSutherlandClipFlags(B2IPoint(10, 10), aRange) == 0);
+ CPPUNIT_ASSERT_MESSAGE("(11,11) is inside range!",
+ utils::getCohenSutherlandClipFlags(B2IPoint(11, 11), aRange)
+ == (utils::RectClipFlags::RIGHT | utils::RectClipFlags::BOTTOM));
+ }
+
+ void check()
+ {
+ implCheck<B2DRange>();
+ implCheck<B2IRange>();
+ }
+
+ // 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(b2Xrange);
+ CPPUNIT_TEST(check);
+ CPPUNIT_TEST_SUITE_END();
+}; // class b2Xrange
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::b2Xrange);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/B3DTupleTest.cxx b/basegfx/test/B3DTupleTest.cxx
new file mode 100644
index 000000000..cb8607ea9
--- /dev/null
+++ b/basegfx/test/B3DTupleTest.cxx
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/tuple/b3dtuple.hxx>
+#include <basegfx/tuple/b3ituple.hxx>
+
+namespace basegfx
+{
+class B3DTupleTest : public CppUnit::TestFixture
+{
+public:
+ void testEmpty()
+ {
+ B3DTuple aTuple;
+ CPPUNIT_ASSERT_EQUAL(true, aTuple.equalZero());
+ }
+
+ void testEquals()
+ {
+ B3DTuple aTuple(1.0, 1.0, 1.0);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple.equal({ 1.0, 1.0, 1.0 }));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple.equal({ 0.99, 0.99, 0.99 }));
+ }
+
+ void testOperatorAddition()
+ {
+ B3DTuple aTuple(4.0, 8.0, 1.0);
+ aTuple += { 2.0, 3.0, 4.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(11.0, aTuple.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, aTuple.getZ(), 1e-2);
+
+ B3ITuple aTupleInt(4, 8, 1);
+ aTupleInt += { 2, 3, 4 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(11), aTupleInt.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aTupleInt.getZ());
+ }
+
+ void testOperatorSubstraction()
+ {
+ B3DTuple aTuple(4.0, 8.0, 1.0);
+ aTuple -= { 2.0, 3.0, 4.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, aTuple.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-3.0, aTuple.getZ(), 1e-2);
+
+ B3ITuple aTupleInt(4, 8, 1);
+ aTupleInt -= { 2, 3, 4 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aTupleInt.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-3), aTupleInt.getZ());
+ }
+
+ void testOperatorMultiply()
+ {
+ B3DTuple aTuple(4.0, 8.0, 1.0);
+ aTuple *= { 2.0, 3.0, 4.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(24.0, aTuple.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(4.0, aTuple.getZ(), 1e-2);
+
+ aTuple *= 2.0;
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(16.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(48.0, aTuple.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(8.0, aTuple.getZ(), 1e-2);
+
+ B3ITuple aTupleInt(4, 8, 1);
+ aTupleInt *= { 2, 3, 4 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(24), aTupleInt.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aTupleInt.getZ());
+
+ aTupleInt *= 2.0;
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(16), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(48), aTupleInt.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aTupleInt.getZ());
+ }
+
+ void testOperatorDivide()
+ {
+ B3DTuple aTuple(4.0, 8.0, 9.0);
+ aTuple /= { 2.0, 8.0, 3.0 };
+
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aTuple.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aTuple.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(3.0, aTuple.getZ(), 1e-2);
+
+ B3ITuple aTupleInt(4, 8, 9);
+ aTupleInt /= { 2, 8, 3 };
+
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aTupleInt.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aTupleInt.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aTupleInt.getZ());
+ }
+
+ void testOperatorEqualUnequal()
+ {
+ B3DTuple aTuple(4.0, 8.0, 9.0);
+ B3DTuple aTuple2 = aTuple;
+
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == aTuple);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == aTuple2);
+ CPPUNIT_ASSERT_EQUAL(true, aTuple == B3DTuple(4.0, 8.0, 9.0));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple == B3DTuple(4.0, 7.99, 9.0));
+ CPPUNIT_ASSERT_EQUAL(false, aTuple == B3DTuple(3.99, 8.0, 9.0));
+
+ CPPUNIT_ASSERT_EQUAL(false, aTuple != aTuple);
+ CPPUNIT_ASSERT_EQUAL(false, aTuple != aTuple2);
+ CPPUNIT_ASSERT_EQUAL(false, aTuple != B3DTuple(4.0, 8.0, 9.0));
+ CPPUNIT_ASSERT_EQUAL(true, aTuple != B3DTuple(4.0, 7.99, 9.0));
+ CPPUNIT_ASSERT_EQUAL(true, aTuple != B3DTuple(3.99, 8.0, 9.0));
+
+ B3ITuple aTupleInt(4, 8, 9);
+ B3ITuple aTupleInt2 = aTupleInt;
+
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == aTupleInt);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == aTupleInt2);
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt == B3ITuple(4, 8, 9));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt == B3ITuple(4, 7, 9));
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt == B3ITuple(3, 8, 9));
+
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt != aTupleInt);
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt != aTupleInt2);
+ CPPUNIT_ASSERT_EQUAL(false, aTupleInt != B3ITuple(4, 8, 9));
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt != B3ITuple(4, 7, 9));
+ CPPUNIT_ASSERT_EQUAL(true, aTupleInt != B3ITuple(3, 8, 9));
+ }
+
+ void testOperatorMinus()
+ {
+ B3DTuple aTupleMinus = -B3DTuple(4.0, 8.0, 1.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-4.0, aTupleMinus.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-8.0, aTupleMinus.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, aTupleMinus.getZ(), 1e-2);
+ B3DTuple aTupleZero = -B3DTuple(0.0, 0.0, 0.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aTupleZero.getX(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aTupleZero.getY(), 1e-2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aTupleZero.getZ(), 1e-2);
+
+ B3ITuple aTupleIntMinus = -B3ITuple(4, 8, 1);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-4), aTupleIntMinus.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-8), aTupleIntMinus.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), aTupleIntMinus.getZ());
+ B3ITuple aTupleIntZero = -B3ITuple(0, 0, 0);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aTupleIntZero.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aTupleIntZero.getY());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aTupleIntZero.getZ());
+ }
+
+ CPPUNIT_TEST_SUITE(B3DTupleTest);
+ CPPUNIT_TEST(testEmpty);
+ CPPUNIT_TEST(testEquals);
+ CPPUNIT_TEST(testOperatorAddition);
+ CPPUNIT_TEST(testOperatorSubstraction);
+ CPPUNIT_TEST(testOperatorMultiply);
+ CPPUNIT_TEST(testOperatorDivide);
+ CPPUNIT_TEST(testOperatorEqualUnequal);
+ CPPUNIT_TEST(testOperatorMinus);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::B3DTupleTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/BColorModifierTest.cxx b/basegfx/test/BColorModifierTest.cxx
new file mode 100755
index 000000000..237154266
--- /dev/null
+++ b/basegfx/test/BColorModifierTest.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/color/bcolormodifier.hxx>
+
+namespace basegfx
+{
+class bcolormodifier : public CppUnit::TestFixture
+{
+ BColor maWhite;
+ BColor maBlack;
+ BColor maRed;
+ BColor maGreen;
+ BColor maBlue;
+ BColor maYellow;
+ BColor maMagenta;
+ BColor maCyan;
+ BColor maGray;
+
+public:
+ bcolormodifier()
+ : 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)
+ , maGray(.5, .5, .5)
+ {
+ }
+
+ void testGray()
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_gray>();
+
+ CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack));
+
+ BColor aGrayedRed(77.0 / 256.0, 77.0 / 256.0, 77.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedRed, aBColorModifier->getModifiedColor(maRed));
+ BColor aGrayedGreen(151.0 / 256.0, 151.0 / 256.0, 151.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedGreen, aBColorModifier->getModifiedColor(maGreen));
+ BColor aGrayedBlue(28.0 / 256.0, 28.0 / 256.0, 28.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedBlue, aBColorModifier->getModifiedColor(maBlue));
+ // 77 + 151 = 228
+ BColor aGrayedYellow(228.0 / 256.0, 228.0 / 256.0, 228.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedYellow, aBColorModifier->getModifiedColor(maYellow));
+ // 77 + 28 = 105
+ BColor aGrayedMagenta(105.0 / 256.0, 105.0 / 256.0, 105.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedMagenta, aBColorModifier->getModifiedColor(maMagenta));
+ // 151 + 28 = 179
+ BColor aGrayedCyan(179.0 / 256.0, 179.0 / 256.0, 179.0 / 256.0);
+ CPPUNIT_ASSERT_EQUAL(aGrayedCyan, aBColorModifier->getModifiedColor(maCyan));
+
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier));
+ const basegfx::BColorModifierSharedPtr aBColorModifierInvert
+ = std::make_shared<basegfx::BColorModifier_invert>();
+ CPPUNIT_ASSERT(*aBColorModifier != *aBColorModifierInvert);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier2
+ = std::make_shared<basegfx::BColorModifier_gray>();
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2));
+ }
+
+ void testInvert()
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifier
+ = std::make_shared<basegfx::BColorModifier_invert>();
+
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray));
+ CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maBlack));
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifier->getModifiedColor(maCyan));
+ CPPUNIT_ASSERT_EQUAL(maCyan, aBColorModifier->getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maMagenta));
+ CPPUNIT_ASSERT_EQUAL(maMagenta, aBColorModifier->getModifiedColor(maGreen));
+ CPPUNIT_ASSERT_EQUAL(maBlue, aBColorModifier->getModifiedColor(maYellow));
+ CPPUNIT_ASSERT_EQUAL(maYellow, aBColorModifier->getModifiedColor(maBlue));
+ CPPUNIT_ASSERT_EQUAL(BColor(.8, .7, .6),
+ aBColorModifier->getModifiedColor(BColor(.2, .3, .4)));
+
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier));
+ const basegfx::BColorModifierSharedPtr aBColorModifierGray
+ = std::make_shared<basegfx::BColorModifier_gray>();
+ CPPUNIT_ASSERT(*aBColorModifier != *aBColorModifierGray);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifier2
+ = std::make_shared<basegfx::BColorModifier_invert>();
+ CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2));
+ }
+
+ void testReplace()
+ {
+ const basegfx::BColorModifierSharedPtr aBColorModifierRed
+ = std::make_shared<basegfx::BColorModifier_replace>(maRed);
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifierRed->getModifiedColor(maCyan));
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifierRed->getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifierRed->getModifiedColor(maMagenta));
+ CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifierRed->getModifiedColor(maGreen));
+
+ const basegfx::BColorModifierSharedPtr aBColorModifierBlack
+ = std::make_shared<basegfx::BColorModifier_replace>(maBlack);
+
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifierBlack->getModifiedColor(maCyan));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifierBlack->getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifierBlack->getModifiedColor(maMagenta));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifierBlack->getModifiedColor(maGreen));
+
+ CPPUNIT_ASSERT(aBColorModifierRed->operator==(*aBColorModifierRed));
+ CPPUNIT_ASSERT(aBColorModifierBlack->operator==(*aBColorModifierBlack));
+ CPPUNIT_ASSERT(*aBColorModifierRed != *aBColorModifierBlack);
+
+ const basegfx::BColorModifierSharedPtr aBColorModifierGray
+ = std::make_shared<basegfx::BColorModifier_gray>();
+ CPPUNIT_ASSERT(*aBColorModifierRed != *aBColorModifierGray);
+ }
+
+ void testStack()
+ {
+ BColorModifierStack aStack1;
+ sal_uInt32 expected = 0;
+ CPPUNIT_ASSERT_EQUAL(expected, aStack1.count());
+ CPPUNIT_ASSERT_EQUAL(maRed, aStack1.getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maWhite, aStack1.getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maBlue, aStack1.getModifiedColor(maBlue));
+
+ aStack1.push(std::make_shared<basegfx::BColorModifier_invert>());
+ expected = 1;
+ CPPUNIT_ASSERT_EQUAL(expected, aStack1.count());
+ CPPUNIT_ASSERT_EQUAL(maCyan, aStack1.getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aStack1.getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maYellow, aStack1.getModifiedColor(maBlue));
+
+ aStack1.push(std::make_shared<basegfx::BColorModifier_gray>());
+ expected = 2;
+ CPPUNIT_ASSERT_EQUAL(expected, aStack1.count());
+ BColor aInvertedGrayedRed(1 - (77.0 / 256.0), 1 - (77.0 / 256.0), 1 - (77.0 / 256.0));
+ BColor aInvertedGrayedBlue(1 - (28.0 / 256.0), 1 - (28.0 / 256.0), 1 - (28.0 / 256.0));
+ CPPUNIT_ASSERT_EQUAL(aInvertedGrayedRed, aStack1.getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aStack1.getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(aInvertedGrayedBlue, aStack1.getModifiedColor(maBlue));
+
+ aStack1.pop();
+ expected = 1;
+ CPPUNIT_ASSERT_EQUAL(expected, aStack1.count());
+ CPPUNIT_ASSERT_EQUAL(maCyan, aStack1.getModifiedColor(maRed));
+ CPPUNIT_ASSERT_EQUAL(maBlack, aStack1.getModifiedColor(maWhite));
+ CPPUNIT_ASSERT_EQUAL(maYellow, aStack1.getModifiedColor(maBlue));
+ }
+
+ CPPUNIT_TEST_SUITE(bcolormodifier);
+ CPPUNIT_TEST(testGray);
+ CPPUNIT_TEST(testInvert);
+ CPPUNIT_TEST(testReplace);
+ CPPUNIT_TEST(testStack);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::bcolormodifier);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/BColorTest.cxx b/basegfx/test/BColorTest.cxx
new file mode 100644
index 000000000..647078f33
--- /dev/null
+++ b/basegfx/test/BColorTest.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/color/bcolortools.hxx>
+
+namespace basegfx
+{
+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)
+ {
+ }
+
+ // insert your test code here.
+ void hslTest()
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("white", BColor(0, 0, 1), utils::rgb2hsl(maWhite));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("black", BColor(0, 0, 0), utils::rgb2hsl(maBlack));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("red", BColor(0, 1, 0.5), utils::rgb2hsl(maRed));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("green", BColor(120, 1, 0.5), utils::rgb2hsl(maGreen));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("blue", BColor(240, 1, 0.5), utils::rgb2hsl(maBlue));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow", BColor(60, 1, 0.5), utils::rgb2hsl(maYellow));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta", BColor(300, 1, 0.5), utils::rgb2hsl(maMagenta));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("cyan", BColor(180, 1, 0.5), utils::rgb2hsl(maCyan));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("third hue case", BColor(210, 1, 0.5),
+ utils::rgb2hsl(BColor(0, 0.5, 1)));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip white", maWhite,
+ utils::hsl2rgb(utils::rgb2hsl(maWhite)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip black", maBlack,
+ utils::hsl2rgb(utils::rgb2hsl(maBlack)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip red", maRed, utils::hsl2rgb(utils::rgb2hsl(maRed)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip green", maGreen,
+ utils::hsl2rgb(utils::rgb2hsl(maGreen)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip blue", maBlue,
+ utils::hsl2rgb(utils::rgb2hsl(maBlue)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip yellow", maYellow,
+ utils::hsl2rgb(utils::rgb2hsl(maYellow)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip magenta", maMagenta,
+ utils::hsl2rgb(utils::rgb2hsl(maMagenta)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip cyan", maCyan,
+ utils::hsl2rgb(utils::rgb2hsl(maCyan)));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("grey10", BColor(0, 0, .1), utils::rgb2hsl(maWhite * .1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("grey90", BColor(0, 0, .9), utils::rgb2hsl(maWhite * .9));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("red/2", BColor(0, 1, 0.25), utils::rgb2hsl(maRed * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("green/2", BColor(120, 1, 0.25), utils::rgb2hsl(maGreen * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("blue/2", BColor(240, 1, 0.25), utils::rgb2hsl(maBlue * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow/2", BColor(60, 1, 0.25),
+ utils::rgb2hsl(maYellow * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta/2", BColor(300, 1, 0.25),
+ utils::rgb2hsl(maMagenta * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("cyan/2", BColor(180, 1, 0.25), utils::rgb2hsl(maCyan * .5));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("pastel", BColor(0, .5, .5),
+ utils::rgb2hsl(BColor(.75, .25, .25)));
+ }
+
+ // insert your test code here.
+ void hsvTest()
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("white", BColor(0, 0, 1), utils::rgb2hsv(maWhite));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("black", BColor(0, 0, 0), utils::rgb2hsv(maBlack));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("red", BColor(0, 1, 1), utils::rgb2hsv(maRed));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("green", BColor(120, 1, 1), utils::rgb2hsv(maGreen));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("blue", BColor(240, 1, 1), utils::rgb2hsv(maBlue));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow", BColor(60, 1, 1), utils::rgb2hsv(maYellow));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta", BColor(300, 1, 1), utils::rgb2hsv(maMagenta));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("cyan", BColor(180, 1, 1), utils::rgb2hsv(maCyan));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip white", maWhite,
+ utils::hsv2rgb(utils::rgb2hsv(maWhite)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip black", maBlack,
+ utils::hsv2rgb(utils::rgb2hsv(maBlack)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip red", maRed, utils::hsv2rgb(utils::rgb2hsv(maRed)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip green", maGreen,
+ utils::hsv2rgb(utils::rgb2hsv(maGreen)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip blue", maBlue,
+ utils::hsv2rgb(utils::rgb2hsv(maBlue)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip yellow", maYellow,
+ utils::hsv2rgb(utils::rgb2hsv(maYellow)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip magenta", maMagenta,
+ utils::hsv2rgb(utils::rgb2hsv(maMagenta)));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("roundtrip cyan", maCyan,
+ utils::hsv2rgb(utils::rgb2hsv(maCyan)));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("grey10", BColor(0, 0, .1), utils::rgb2hsv(maWhite * .1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("grey90", BColor(0, 0, .9), utils::rgb2hsv(maWhite * .9));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("red/2", BColor(0, 1, 0.5), utils::rgb2hsv(maRed * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("green/2", BColor(120, 1, 0.5), utils::rgb2hsv(maGreen * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("blue/2", BColor(240, 1, 0.5), utils::rgb2hsv(maBlue * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("yellow/2", BColor(60, 1, 0.5), utils::rgb2hsv(maYellow * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("magenta/2", BColor(300, 1, 0.5),
+ utils::rgb2hsv(maMagenta * .5));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("cyan/2", BColor(180, 1, 0.5), utils::rgb2hsv(maCyan * .5));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("pastel", BColor(0, .5, .5),
+ utils::rgb2hsv(BColor(.5, .25, .25)));
+ }
+
+ CPPUNIT_TEST_SUITE(bcolor);
+ CPPUNIT_TEST(hslTest);
+ CPPUNIT_TEST(hsvTest);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::bcolor);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/SvgPathImportExport.cxx b/basegfx/test/SvgPathImportExport.cxx
new file mode 100644
index 000000000..955c47b23
--- /dev/null
+++ b/basegfx/test/SvgPathImportExport.cxx
@@ -0,0 +1,241 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+
+namespace basegfx
+{
+
+class SvgPathImportExport : public CppUnit::TestFixture
+{
+private:
+ OUString aPath0;
+ OUString aPath1;
+ OUString aPath2;
+ OUString aPath3;
+
+public:
+ // initialise your test code values here.
+ void setUp() override
+ {
+ // simple rectangle
+ aPath0 = "M 10 10-10 10-10-10 10-10Z";
+
+ // simple bezier polygon
+ aPath1 = "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 = "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 = "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 testImportExport()
+ {
+ B2DPolyPolygon aPoly;
+ OUString aExport;
+
+ CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D",
+ utils::importFromSvgD( aPoly, aPath0, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+ static constexpr OUStringLiteral sExportString = u"m10 10h-20v-20h20z";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting rectangle to SVG-D",
+ OUString(sExportString), aExport );
+ CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip",
+ utils::importFromSvgD( aPoly, aExport, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting rectangle to SVG-D (round-trip)",
+ OUString(sExportString), aExport);
+
+ CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D",
+ utils::importFromSvgD( aPoly, aPath1, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+
+ // Adaptations 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' statement now.
+
+ // The old SVGexport identified nun-used ControlVectors erroneously 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.
+ static constexpr OUStringLiteral sExportStringSimpleBezier =
+ u"m11430 0c-8890 3810 5715 6985 5715 6985"
+ "l-17145-1905c0 0 22860-10160 16510 6350"
+ "s-3810-11430-3810-11430z";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting bezier polygon to SVG-D", OUString(sExportStringSimpleBezier), aExport);
+
+ // Adaptations 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", utils::importFromSvgD( aReImport, aExport, false, nullptr));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("re-imported polygon needs to be identical", aPoly, aReImport);
+
+ CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", utils::importFromSvgD( aPoly, aPath2, false, nullptr));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+
+ // Adaptations 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.
+ static constexpr OUStringLiteral sExportString1 =
+ u"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", utils::importFromSvgD( aReImport, aExport, false, nullptr));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("re-imported '@' needs to be identical", aPoly, aReImport);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting '@' to SVG-D", OUString(sExportString1), aExport);
+ CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip",
+ utils::importFromSvgD( aPoly, aExport, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting '@' to SVG-D (round-trip)",
+ OUString(sExportString1), aExport);
+
+ CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D",
+ utils::importFromSvgD( aPoly, aPath3, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+ static constexpr OUStringLiteral sExportString2 =
+ u"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_EQUAL_MESSAGE("exporting complex polygon to SVG-D",
+ OUString(sExportString2), aExport);
+ CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip",
+ utils::importFromSvgD( aPoly, aExport, false, nullptr ));
+ aExport = utils::exportToSvgD( aPoly, true, true, false );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting complex polygon to SVG-D (round-trip)",
+ OUString(sExportString2), aExport);
+
+ const B2DPolygon aRect(
+ utils::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));
+ aExport = utils::exportToSvgD( B2DPolyPolygon(aRect), false, false, false );
+
+ static constexpr OUStringLiteral sExportStringRect = u"M0 0H4000V4000H0Z";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting to rectangle svg-d string",
+ OUString(sExportStringRect), aExport);
+ }
+
+ // 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(SvgPathImportExport);
+ CPPUNIT_TEST(testImportExport);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::SvgPathImportExport);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/VectorTest.cxx b/basegfx/test/VectorTest.cxx
new file mode 100644
index 000000000..680a42123
--- /dev/null
+++ b/basegfx/test/VectorTest.cxx
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/vector/b2dvector.hxx>
+
+namespace basegfx
+{
+class VectorTest : public CppUnit::TestFixture
+{
+public:
+ void testCross()
+ {
+ B2DVector aVector(1.0, 1.0);
+ double aResult = aVector.cross(B2DVector(1.0, 1.0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aResult, 1E-12);
+ }
+
+ void testScalar()
+ {
+ {
+ B2DVector aVector(1.0, 1.0);
+ double aResult = aVector.scalar(B2DVector(1.0, 1.0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult, 1E-12);
+ }
+ {
+ B2IVector aVector(1, 1);
+ double aResult = aVector.scalar(B2IVector(1, 1));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aResult, 1E-12);
+ }
+ }
+
+ void testSetLength()
+ {
+ {
+ B2DVector aVector(1.0, 1.0);
+ aVector = aVector.setLength(std::sqrt(2.0));
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aVector.getX(), 1E-12);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aVector.getY(), 1E-12);
+ }
+ {
+ B2IVector aVector(1, 1);
+ aVector = aVector.setLength(std::sqrt(2.0));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aVector.getX());
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aVector.getY());
+ }
+ }
+
+ void testGetLength()
+ {
+ B2DVector aVector(1.0, 1.0);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(std::sqrt(2.0), aVector.getLength(), 1E-12);
+ }
+
+ CPPUNIT_TEST_SUITE(VectorTest);
+ CPPUNIT_TEST(testCross);
+ CPPUNIT_TEST(testScalar);
+ CPPUNIT_TEST(testSetLength);
+ CPPUNIT_TEST(testGetLength);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+} // namespace basegfx
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::VectorTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/basegfx3d.cxx b/basegfx/test/basegfx3d.cxx
new file mode 100644
index 000000000..b03560d65
--- /dev/null
+++ b/basegfx/test/basegfx3d.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace basegfx3d
+{
+class b3dhommatrix : public CppUnit::TestFixture
+{
+public:
+ // 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 b3dpoint : public CppUnit::TestFixture
+{
+public:
+ // 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:
+ // 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:
+ // 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:
+ // 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::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;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/basegfxtools.cxx b/basegfx/test/basegfxtools.cxx
new file mode 100644
index 000000000..9c6075919
--- /dev/null
+++ b/basegfx/test/basegfxtools.cxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/utils/keystoplerp.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
+using namespace ::basegfx;
+
+namespace basegfxtools
+{
+class KeyStopLerpTest : public CppUnit::TestFixture
+{
+ utils::KeyStopLerp maKeyStops;
+
+ static std::vector<double> getTestVector() { return { 0.1, 0.5, 0.9 }; }
+
+public:
+ KeyStopLerpTest()
+ : maKeyStops(getTestVector())
+ {
+ }
+
+ void test()
+ {
+ double fAlpha;
+ std::ptrdiff_t nIndex;
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(-1.0);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("-1.0", std::ptrdiff_t(0), nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("-1.0", 0.0, fAlpha);
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.1", std::ptrdiff_t(0), nIndex);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.1", 0.0, fAlpha);
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.3);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.3", std::ptrdiff_t(0), nIndex);
+ CPPUNIT_ASSERT_MESSAGE("0.3", fTools::equal(fAlpha, 0.5));
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.5);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.5", std::ptrdiff_t(0), nIndex);
+ CPPUNIT_ASSERT_MESSAGE("0.5", fTools::equal(fAlpha, 1.0));
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.51);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.51", std::ptrdiff_t(1), nIndex);
+ CPPUNIT_ASSERT_MESSAGE("0.51", fTools::equal(fAlpha, 0.025));
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(0.9);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.51", std::ptrdiff_t(1), nIndex);
+ CPPUNIT_ASSERT_MESSAGE("0.51", fTools::equal(fAlpha, 1.0));
+
+ std::tie(nIndex, fAlpha) = maKeyStops.lerp(1.0);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("0.51", std::ptrdiff_t(1), nIndex);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("0.51", 1.0, fAlpha, 1E-12);
+ }
+
+ // 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx
new file mode 100644
index 000000000..b65f25bae
--- /dev/null
+++ b/basegfx/test/boxclipper.cxx
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#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/b2dpolypolygon.hxx>
+#include <comphelper/random.hxx>
+#include <rtl/math.hxx>
+
+#include "boxclipper.hxx"
+
+using namespace ::basegfx;
+
+namespace basegfx2d
+{
+/// Gets a random ordinal [0,n)
+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 comphelper::rng::uniform_size_distribution(0, n-1);
+}
+
+static bool compare(const B2DPoint& left, const B2DPoint& right)
+{
+ return left.getX()<right.getX()
+ || (rtl::math::approxEqual(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() override
+ {
+ 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, B2VectorOrientation::Negative );
+ aDisjunctRanges.appendElement( aOffside, B2VectorOrientation::Negative );
+
+ aEqualRanges.appendElement( aCenter, B2VectorOrientation::Negative );
+ aEqualRanges.appendElement( aCenter, B2VectorOrientation::Negative );
+
+ aIntersectionN.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionN.appendElement( aNorth, B2VectorOrientation::Negative );
+
+ aIntersectionE.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionE.appendElement( aEast, B2VectorOrientation::Negative );
+
+ aIntersectionS.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionS.appendElement( aSouth, B2VectorOrientation::Negative );
+
+ aIntersectionW.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionW.appendElement( aWest, B2VectorOrientation::Negative );
+
+ aIntersectionNE.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionNE.appendElement( aNorthEast, B2VectorOrientation::Negative );
+
+ aIntersectionSE.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionSE.appendElement( aSouthEast, B2VectorOrientation::Negative );
+
+ aIntersectionSW.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionSW.appendElement( aSouthWest, B2VectorOrientation::Negative );
+
+ aIntersectionNW.appendElement( aCenter, B2VectorOrientation::Negative );
+ aIntersectionNW.appendElement( aNorthWest, B2VectorOrientation::Negative );
+
+ aRingIntersection.appendElement( aNorth2, B2VectorOrientation::Negative );
+ aRingIntersection.appendElement( aEast2, B2VectorOrientation::Negative );
+ aRingIntersection.appendElement( aSouth2, B2VectorOrientation::Negative );
+
+ aRingIntersection2 = aRingIntersection;
+ aRingIntersection2.appendElement( aWest2, B2VectorOrientation::Negative );
+
+ aRingIntersectExtraStrip = aRingIntersection2;
+ aRingIntersectExtraStrip.appendElement( B2DRange(0, -25, 200, 25),
+ B2VectorOrientation::Negative );
+
+ aComplexIntersections.appendElement( aCenter, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aOffside, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aCenter, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aNorth, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aEast, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aSouth, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aWest, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aNorthEast, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aSouthEast, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aSouthWest, B2VectorOrientation::Negative );
+ aComplexIntersections.appendElement( aNorthWest, B2VectorOrientation::Negative );
+
+#ifdef GENERATE_RANDOM
+ for( int i=0; i<800; ++i )
+ {
+ B2DRange aRandomRange(
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ),
+ getRandomOrdinal( 1000 ) );
+
+ aRandomIntersections.appendElement( aRandomRange, B2VectorOrientation::Negative );
+ }
+#else
+ static constexpr OUStringLiteral randomSvg=u"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;
+ CPPUNIT_ASSERT(utils::importFromSvgD(randomPoly, randomSvg, false, nullptr));
+ for (auto const& aPolygon : std::as_const(randomPoly))
+ aRandomIntersections.appendElement(aPolygon.getB2DRange(), B2VectorOrientation::Negative);
+#endif
+ }
+
+ B2DPolyPolygon normalizePoly( const B2DPolyPolygon& rPoly ) const
+ {
+ B2DPolyPolygon aRes;
+ for( sal_uInt32 i=0; i<rPoly.count(); ++i )
+ {
+ B2DPolygon aTmp=rPoly.getB2DPolygon(i);
+ if( utils::getOrientation(aTmp) == B2VectorOrientation::Negative )
+ aTmp.flip();
+
+ aTmp=utils::removeNeutralPoints(aTmp);
+ std::vector<B2DPoint> aTmp2(aTmp.count());
+ for(sal_uInt32 j=0; j<aTmp.count(); ++j)
+ aTmp2[j] = aTmp.getB2DPoint(j);
+
+ std::vector<B2DPoint>::iterator pSmallest=aTmp2.end();
+ for(std::vector<B2DPoint>::iterator pCurr=aTmp2.begin(); pCurr!=aTmp2.end(); ++pCurr)
+ {
+ if( pSmallest == aTmp2.end() || compare(*pCurr, *pSmallest) )
+ {
+ pSmallest=pCurr;
+ }
+ }
+
+ if( pSmallest != aTmp2.end() )
+ std::rotate(aTmp2.begin(),pSmallest,aTmp2.end());
+
+ aTmp.clear();
+ for(const auto& rCurr : aTmp2)
+ aTmp.append(rCurr);
+
+ aRes.append(aTmp);
+ }
+
+ // boxclipper & generic clipper disagree slightly on area-less
+ // polygons (one or two points only)
+ aRes = utils::stripNeutralPolygons(aRes);
+
+ // now, sort all polygons with increasing 0th point
+ std::sort(aRes.begin(),
+ aRes.end(),
+ [](const B2DPolygon& aPolygon1, const B2DPolygon& aPolygon2) {
+ return compare(aPolygon1.getB2DPoint(0),
+ aPolygon2.getB2DPoint(0)); } );
+
+ return aRes;
+ }
+
+ void verifyPoly(const char* sName, const char* sSvg, const B2DPolyRange& toTest) const
+ {
+ B2DPolyPolygon aTmp1;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ utils::importFromSvgD(
+ aTmp1, OUString::createFromAscii(sSvg), false, nullptr));
+
+ const OUString aSvg=
+ utils::exportToSvgD(toTest.solveCrossovers(), true, true, false);
+ B2DPolyPolygon aTmp2;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ utils::importFromSvgD(
+ aTmp2, aSvg, false, nullptr));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ sName,
+ normalizePoly(aTmp1), normalizePoly(aTmp2));
+ }
+
+ void verifyPoly()
+ {
+ const char* const disjunct="m-100-100v200h200v-200zm900 900v200h200v-200z";
+ const char* const equal="m-100-100v200h200v-200zm200 0h-200v200h200v-200z";
+ const char* const intersectionN="m-100-100v100h200v-100zm200 0v-100h-200v100 200h200v-200z";
+ const char* const intersectionE="m0-100v200h100v-200zm0 0h-100v200h100 200v-200z";
+ const char* const intersectionS="m-100 0v100h200v-100zm0-100v200 100h200v-100-200z";
+ const char* const intersectionW="m-100-100v200h100v-200zm0 0h-100v200h100 200v-200z";
+ const char* const intersectionNE="m0-100v100h100v-100zm0-100v100h-100v200h200v-100h100v-200z";
+ const char* const intersectionSE="m0 0v100h100v-100zm100 0v-100h-200v200h100v100h200v-200z";
+ const char* const intersectionSW="m-100 0v100h100v-100zm0-100v100h-100v200h200v-100h100v-200z";
+ const char* const intersectionNW="m-100-100v100h100v-100zm100 0v-100h-200v200h100v100h200v-200z";
+ const char* const ringIntersection="m50-150v100h100v-100zm0 200v100h100v-100zm100-200v-200h-300v300h200v100h-200v300h300v-200h200v-300z";
+ const char* const ringIntersection2="m-150 50v100h100v-100zm0-200v100h100v-100zm100 200v-100h100v100z"
+ "m100-200v100h100v-100zm0 200v100h100v-100zm100-200v-200h-300v200h-200v300h200v200h300v-200h200v-300z";
+ const char* const ringIntersectExtraStrip="m-150 50v100h100v-100zm0-200v100h100v-100zm100 200v-100h100v25h-50v50h50v25z"
+ "m100-200v100h100v-100zm0 200v100h100v-100zm0-75v50h150v-50z"
+ "m100-125v-200h-300v200h-200v300h200v200h300v-200h200v-300z";
+ const char* const complexIntersections="m0 0zm0 0zm0 0zm0 0v-100 100h-100 100v100-100h100zm0 0v-100 100h-100 100v100-100h100z"
+ "m100 0v-100h-100-100v100 100h100 100v-100zm0 0v-100h-100-100v100 100h100 100v-100z"
+ "m0 0v-100h-100v-100 100h-100v100h-100 100v100h100v100-100h100v-100h100z"
+ "m0-100v-100h-100-100v100h-100v100 100h100v100h100 100v-100h100v-100-100z"
+ "m100 0v-100h-200-100-100v100 200 100h100 100 200v-100-200zm600 900v200h200v-200z";
+ const char* const randomIntersections="m20-4515v393h43v-393zm34-8690v127h18v-127zm24 674v427h56v-427zm126-451v16-16z"
+ "m22 3470v260h50v-260zm55 599v167h26v-167zm-49-1831v455h136v-455z"
+ "m10 8845v19h158v-19zm54-38v25h228v-25zm156-13245v108h100v-108z"
+ "m101 14826v200h75v-200zm-205-3000v365h315v-365zm-309-1877v19h628v-19z"
+ "m549-1398v127h98v-127zm18 5351v215h111v-215zm-362-10061v152h488v-152z"
+ "m488 0v-469h-492v621h4v280h488v-432zm-378 5368v48h384v-48zm274-10182v712h119v-712z"
+ "m-424 3173v-94h-47v110h47v96h551v-112zm-105-2249v157h353v112h100v-112h205v-157z"
+ "m284 5177v203h377v-203zm337 4727v66h40v-66zm-326 6110v57h374v-57zm351-12583v39h48v-39z"
+ "m23 12583v-505h-571v576h571v-14h30v-57zm-368-2682v-8h-292v27h134v102h562v-121z"
+ "m-9-12299v320h428v-320zm364 1216v-410h-598v316h-32v110h32v96h47v280h615v-392z"
+ "m-537 11431v486h388v279h111v-279h122v-486zm112-4621v142h550v-142zm101-2719v494h450v-494z"
+ "m340 6609v33h120v-33zm-85-4349v-479h-98v479h-258v459h-165v247h189v307h384v-307h142v-105h13v-601z"
+ "m-270-3159v36h490v-36zm442 2163v7h52v-7zm-345 7158v588h403v-588zm378-1813v-93h-122v126h2v155h148v-188z"
+ "m19-5345v-259h-96v266h44v20h52v-20h10v-7zm-91-6571v-430h-428v430h-211v589h743v-589z"
+ "m101 6571v-461h-705v468h599v20h44v191h65v-218zm-89-8442v40h94v-40zm-71 10742v-43h-221v109h181v427h211v-493z"
+ "m0-4727v-189h-634v392h257v97h33v351h490v-351h29v-300zm-97 6698v-333h-315v333h-262v456h863v-456z"
+ "m-142-8556v22h429v-22zm238-56v17h208v-17zm91 7234v664h120v-664zm69 2452v-336h-567v524h419v13h201v-201z"
+ "m-42-13332v272h115v-272z";
+
+ 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) const
+ {
+ (void)pName; (void)rPoly;
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ basegfx::utils::exportToSvgD(rPoly, , true, true, false),
+ 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 ) const
+ {
+ B2DPolyPolygon genericClip;
+ const sal_uInt32 nCount=rRange.count();
+ for( sal_uInt32 i=0; i<nCount; ++i )
+ {
+ B2DPolygon aRect=utils::createPolygonFromRect(std::get<0>(rRange.getElement(i)));
+ if( std::get<1>(rRange.getElement(i)) == B2VectorOrientation::Negative )
+ aRect.flip();
+
+ genericClip.append(aRect);
+ }
+
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s input - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ basegfx::utils::exportToSvgD(
+ genericClip, , true, true, false),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ const B2DPolyPolygon boxClipResult=rRange.solveCrossovers();
+ const OUString boxClipSvg(
+ basegfx::utils::exportToSvgD(
+ normalizePoly(boxClipResult), true, true, false));
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s boxclipper - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ boxClipSvg,
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ genericClip = utils::solveCrossovers(genericClip);
+ const OUString genericClipSvg(
+ basegfx::utils::exportToSvgD(
+ normalizePoly(genericClip), true, true, false));
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s genclipper - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ genericClipSvg,
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pName,
+ boxClipSvg, genericClipSvg);
+ }
+
+ 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/boxclipper.hxx b/basegfx/test/boxclipper.hxx
new file mode 100644
index 000000000..03aad0d2b
--- /dev/null
+++ b/basegfx/test/boxclipper.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <cstddef>
+
+namespace basegfx2d
+{
+double getRandomOrdinal(const std::size_t n);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/clipstate.cxx b/basegfx/test/clipstate.cxx
new file mode 100644
index 000000000..94cb6b3a2
--- /dev/null
+++ b/basegfx/test/clipstate.cxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/utils/b2dclipstate.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+using namespace ::basegfx;
+
+namespace basegfx2d
+{
+
+class clipstate : public CppUnit::TestFixture
+{
+private:
+ utils::B2DClipState aUnion1;
+ utils::B2DClipState aUnion2;
+ utils::B2DClipState aIntersect;
+ utils::B2DClipState aXor;
+ utils::B2DClipState aSubtract;
+
+public:
+ void setUp() override
+ {
+ 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 verifyPoly(const char* sName, const char* sSvg, const utils::B2DClipState& toTest) const
+ {
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ sName, OUStringToOString(
+ basegfx::utils::exportToSvgD(toTest.getClipPoly(), true, true, false),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ B2DPolyPolygon aTmp1;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ utils::importFromSvgD(
+ aTmp1, OUString::createFromAscii(sSvg), false, nullptr));
+
+ const OUString aSvg=
+ utils::exportToSvgD(toTest.getClipPoly(), true, true, false);
+ B2DPolyPolygon aTmp2;
+ CPPUNIT_ASSERT_MESSAGE(sName,
+ utils::importFromSvgD(
+ aTmp2, aSvg, false, nullptr));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ sName,
+ aTmp1, aTmp2);
+ }
+
+ void verifySimpleRange()
+ {
+ const char* const unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+ const char* const intersectSvg="m-100 10v-20h10v20zm90 90v-10h20v10zm0-190v-10h20v10zm100 100v-20h10v20z";
+ const char* const xorSvg="m-100 10h10v-20h-10zm90 90h20v-10h-20zm0-190h20v-10h-20zm100 100h10v-20h-10z"
+ "m10 0v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+ const char* const 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()
+ {
+ utils::B2DClipState aMixedClip;
+
+ static constexpr OUStringLiteral unionSvg=u"m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
+
+ B2DPolyPolygon aTmp1;
+ CPPUNIT_ASSERT(utils::importFromSvgD(aTmp1, unionSvg, false, nullptr));
+
+ 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* const mixedClipSvg="m0 0v20h-100v80h90v10h20v-10h90v-90h10v-20h-10v-90h-80v100zm-20-20v-80h-80v80zm-130 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
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/genericclipper.cxx b/basegfx/test/genericclipper.cxx
new file mode 100644
index 000000000..af88a66ba
--- /dev/null
+++ b/basegfx/test/genericclipper.cxx
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+using namespace ::basegfx;
+
+namespace basegfx2d
+{
+
+class genericclipper : public CppUnit::TestFixture
+{
+private:
+ B2DPolygon aSelfIntersecting;
+ B2DPolygon aShiftedRectangle;
+
+public:
+ // initialise your test code values here.
+ void setUp() override
+ {
+ 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 = utils::createPolygonFromRect(
+ B2DRange(0,90,20,150));
+ }
+
+
+ void validate(const char* pName,
+ const char* pValidSvgD,
+ B2DPolyPolygon (*pFunc)(const B2DPolyPolygon&, const B2DPolyPolygon&)) const
+ {
+ const B2DPolyPolygon aSelfIntersect(
+ utils::prepareForPolygonOperation(aSelfIntersecting));
+ const B2DPolyPolygon aRect(
+ utils::prepareForPolygonOperation(aShiftedRectangle));
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s input LHS - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ basegfx::utils::exportToSvgD(
+ aSelfIntersect, true, true, false),
+ RTL_TEXTENCODING_UTF8).getStr() );
+ fprintf(stderr, "%s input RHS - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ basegfx::utils::exportToSvgD(
+ aRect, true, true, false),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ const B2DPolyPolygon aRes=
+ pFunc(aSelfIntersect, aRect);
+
+#if OSL_DEBUG_LEVEL > 2
+ fprintf(stderr, "%s - svg:d=\"%s\"\n",
+ pName, OUStringToOString(
+ basegfx::utils::exportToSvgD(aRes, true, true, false),
+ RTL_TEXTENCODING_UTF8).getStr() );
+#endif
+
+ OUString aValid=OUString::createFromAscii(pValidSvgD);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pName,
+ aValid, basegfx::utils::exportToSvgD(aRes, true, true, false));
+ }
+
+ void validateOr()
+ {
+ const char* const pValid="m0 0h100v150h-75v-50h-5v50h-20v-50-10zm75 100v-50h-50v50z";
+ validate("validateOr", pValid, &utils::solvePolygonOperationOr);
+ }
+
+ void validateXor()
+ {
+ const char* const pValid="m0 0h100v150h-75v-50h-5v50h-20v-50-10zm0 100h20v-10h-20zm75 0v-50h-50v50z";
+ validate("validateXor", pValid, &utils::solvePolygonOperationXor);
+ }
+
+ void validateAnd()
+ {
+ const char* const pValid="m0 100v-10h20v10z";
+ validate("validateAnd", pValid, &utils::solvePolygonOperationAnd);
+ }
+
+ void validateDiff()
+ {
+ const char* const pValid="m0 90v-90h100v150h-75v-50h-5v-10zm75 10v-50h-50v50z";
+ validate("validateDiff", pValid, &utils::solvePolygonOperationDiff);
+ }
+
+ void validateCrossover(const char* pName,
+ const char* pInputSvgD,
+ const char* pValidSvgD) const
+ {
+ OUString aInput=OUString::createFromAscii(pInputSvgD);
+ OUString aValid=OUString::createFromAscii(pValidSvgD);
+ B2DPolyPolygon aInputPoly, aValidPoly;
+
+ CPPUNIT_ASSERT(utils::importFromSvgD(aInputPoly, aInput, false, nullptr));
+ CPPUNIT_ASSERT(utils::importFromSvgD(aValidPoly, aValid, false, nullptr));
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ pName,
+ aValid,
+ basegfx::utils::exportToSvgD(
+ utils::solveCrossovers(aInputPoly), true, true, false));
+ }
+
+ void checkCrossoverSolver()
+ {
+ // partially intersecting polygons, with a common subsection
+ validateCrossover(
+ "partially intersecting",
+ "m0 0 v 5 h 3 h 1 h 1 h 1 v -2 v -3 z"
+ "m3 7 v -2 h 1 h 1 h 1 v -2 h 1 v 3 z",
+ "m0 0v5h3 1 1 1v-2-3zm3 7v-2h1 1 1v-2h1v3z");
+
+ // first polygon is identical to subset of second polygon
+ validateCrossover(
+ "full subset",
+ "m0 0 v 5 h 3 h 1 h 1 v -5 z"
+ "m3 10 v -5 h 1 h 1 v -5 h -5 v 5 h 3 z",
+ "m0 0v5h3 1 1v-5zm3 10v-5zm1-5h1v-5h-5v5h3z");
+
+ // first polygon is identical to subset of second polygon, but
+ // oriented in the opposite direction
+ validateCrossover(
+ "full subset, opposite direction",
+ "m0 0 v 5 h 3 h 1 h 1 v -5 z"
+ "m3 10 v -5 h -1 h -1 h -1 v -5 h 5 v 5 h 2 z",
+ "m0 0v5h1 1 1-1-1-1v-5h5v5-5zm4 5h1 2l-4 5v-5z");
+
+ // first polygon is identical to subset of second polygon, and
+ // has a curve segment (triggers different code path)
+ validateCrossover(
+ "full subset, plus curves",
+ "m0 0 v 5 h 3 h 1 h 1 c 2 0 2 0 0 -5 z"
+ "m3 10 v -5 h 1 h 1 c 2 0 2 0 0 -5 h -5 v 5 h 3 z",
+ "m0 0v5h3 1 1c2 0 2 0 0-5zm3 10v-5zm1-5h1c2 0 2 0 0-5h-5v5h3z");
+ }
+
+ // 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(checkCrossoverSolver);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::genericclipper);
+} // namespace basegfx2d
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */