diff options
Diffstat (limited to 'basegfx/test')
24 files changed, 3903 insertions, 0 deletions
diff --git a/basegfx/test/B1DRangeTest.cxx b/basegfx/test/B1DRangeTest.cxx new file mode 100644 index 0000000000..7cc906b7d8 --- /dev/null +++ b/basegfx/test/B1DRangeTest.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/range/b1drange.hxx> + +namespace basegfx +{ +class B1DRangeTest : public CppUnit::TestFixture +{ +public: + void checkIntervalAxioms() + { + // test interval axioms + // (http://en.wikipedia.org/wiki/Interval_%28mathematics%29) + B1DRange aRange; + CPPUNIT_ASSERT_MESSAGE("default ctor - empty range", aRange.isEmpty()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("center - get cop-out value since range is empty", 0.0, + aRange.getCenter()); + + // degenerate interval + aRange.expand(1); + CPPUNIT_ASSERT_EQUAL(B1DRange(1.0, 1.0), aRange); + CPPUNIT_ASSERT_MESSAGE("degenerate range - still, not empty!", !aRange.isEmpty()); + CPPUNIT_ASSERT_EQUAL_MESSAGE("degenerate range - size of 0", 0.0, aRange.getRange()); + CPPUNIT_ASSERT_MESSAGE("same value as degenerate range - is inside range", + aRange.isInside(1.0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("center - must be the single range value", 1.0, + aRange.getCenter()); + + // proper interval + aRange.expand(2.0); + CPPUNIT_ASSERT_EQUAL(B1DRange(1.0, 2.0), aRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("proper range - size of 1", 1.0, aRange.getRange()); + 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.0); + CPPUNIT_ASSERT_EQUAL(B1DRange(1.0, 3.0), aRange); + CPPUNIT_ASSERT_EQUAL_MESSAGE("center - must be half of the range", 2.0, aRange.getCenter()); + } + + void checkOverlap() + { + B1DRange aRange(1.0, 3.0); + B1DRange aRange2(0.0, 1.0); + + 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)); + + B1DRange aRange3(0.0, 2.0); + CPPUNIT_ASSERT_MESSAGE("range overlapping is fully overlapping now", + aRange.overlapsMore(aRange3)); + } + + void checkIntersect() + { + B1DRange aRange(1.0, 3.0); + B1DRange aRange2(3.0, 4.0); + aRange.intersect(aRange2); + CPPUNIT_ASSERT_MESSAGE("range intersection is yielding empty range!", !aRange.isEmpty()); + + B1DRange aRange3(5.0, 6.0); + aRange.intersect(aRange3); + CPPUNIT_ASSERT_MESSAGE("range intersection is yielding nonempty range!", aRange.isEmpty()); + } + + CPPUNIT_TEST_SUITE(B1DRangeTest); + CPPUNIT_TEST(checkIntervalAxioms); + CPPUNIT_TEST(checkOverlap); + CPPUNIT_TEST(checkIntersect); + CPPUNIT_TEST_SUITE_END(); +}; + +} // namespace basegfx + +CPPUNIT_TEST_SUITE_REGISTRATION(basegfx::B1DRangeTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basegfx/test/B2DHomMatrixTest.cxx b/basegfx/test/B2DHomMatrixTest.cxx new file mode 100644 index 0000000000..aace816d3e --- /dev/null +++ b/basegfx/test/B2DHomMatrixTest.cxx @@ -0,0 +1,508 @@ +/* -*- 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); + } + + 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); + + 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 temp; + + temp = maAffine; + temp *= maAffine; + CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: both compact", affineAffineProd, 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 0000000000..97f350c787 --- /dev/null +++ b/basegfx/test/B2DPointTest.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/point/b2dpoint.hxx> +#include <basegfx/vector/b2dsize.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(); + void testOperators(); + + 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(testOperators); + 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); +} + +void B2DPointTest::testOperators() +{ + basegfx::B2DPoint aPoint(2.0, 3.0); + basegfx::B2DSize aSize(1.0, 1.0); + + CPPUNIT_ASSERT_EQUAL(true, basegfx::B2DPoint(3.0, 4.0) == aPoint + basegfx::B2DPoint(aSize)); + CPPUNIT_ASSERT_EQUAL(true, basegfx::B2DPoint(1.0, 2.0) == aPoint - basegfx::B2DPoint(aSize)); + CPPUNIT_ASSERT_EQUAL(true, basegfx::B2DPoint(2.0, 3.0) == aPoint * basegfx::B2DPoint(aSize)); + CPPUNIT_ASSERT_EQUAL(true, basegfx::B2DPoint(2.0, 3.0) == aPoint / basegfx::B2DPoint(aSize)); +} + +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 0000000000..b111bf469d --- /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 0000000000..5319e6b469 --- /dev/null +++ b/basegfx/test/B2DPolyPolygonTest.cxx @@ -0,0 +1,88 @@ +/* -*- 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 <random> + +namespace basegfx +{ +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()); + } + + std::mt19937 rng; // Standard mersenne_twister_engine + + /// Gets a random ordinal [0,n) + ::std::size_t getRandomOrdinal(const ::std::size_t n) + { + std::uniform_int_distribution<size_t> dist(0, n - 1); + return dist(rng); + } + + // 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 0000000000..84e66fa245 --- /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 0000000000..581108b960 --- /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 0000000000..8d9ae4e64b --- /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 0000000000..59384e26b6 --- /dev/null +++ b/basegfx/test/B2DRangeTest.cxx @@ -0,0 +1,93 @@ +/* -*- 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(basegfx::B2DRange(1.2, 2.3, 3.5, 4.8), aRange); + + 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()); + + // wrong order of the interval + basegfx::B2DRange aRange2(1.0, 1.0, 0.0, 0.0); + + CPPUNIT_ASSERT_EQUAL(basegfx::B2DRange(1.0, 1.0, 0.0, 0.0), aRange2); + CPPUNIT_ASSERT_EQUAL(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0), aRange2); + + CPPUNIT_ASSERT_EQUAL(0.0, aRange2.getMinX()); + CPPUNIT_ASSERT_EQUAL(0.0, aRange2.getMinY()); + CPPUNIT_ASSERT_EQUAL(1.0, aRange2.getMaxX()); + CPPUNIT_ASSERT_EQUAL(1.0, aRange2.getMaxY()); + + CPPUNIT_ASSERT_EQUAL(1.0, aRange2.getWidth()); + CPPUNIT_ASSERT_EQUAL(1.0, aRange2.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()); + } + + void testIntersect() + { + basegfx::B2DRange aRange(1.0, 1.0, 4.0, 4.0); + aRange.intersect(basegfx::B2DRange(0.0, 0.0, 2.0, 2.0)); + + CPPUNIT_ASSERT_EQUAL(basegfx::B2DRange(1.0, 1.0, 2.0, 2.0), aRange); + } + + CPPUNIT_TEST_SUITE(B2DRangeTest); + CPPUNIT_TEST(testCreation); + CPPUNIT_TEST(testRound); + CPPUNIT_TEST(testCenter); + CPPUNIT_TEST(testIntersect); + CPPUNIT_TEST_SUITE_END(); +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(B2DRangeTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basegfx/test/B2DSizeTest.cxx b/basegfx/test/B2DSizeTest.cxx new file mode 100644 index 0000000000..42d25c446d --- /dev/null +++ b/basegfx/test/B2DSizeTest.cxx @@ -0,0 +1,108 @@ +/* -*- 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/b2dsize.hxx> + +namespace basegfx +{ +class B2DSizeTest : public CppUnit::TestFixture +{ +public: + void testOperatorAddition() + { + B2DSize aSize(4.0, 8.0); + aSize += { 2.0, 3.0 }; + + CPPUNIT_ASSERT_DOUBLES_EQUAL(6.0, aSize.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(11.0, aSize.getHeight(), 1e-2); + } + + void testOperatorSubstraction() + { + B2DSize aSize(4.0, 8.0); + aSize -= { 2.0, 3.0 }; + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aSize.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(5.0, aSize.getHeight(), 1e-2); + } + + void testOperatorMultiply() + { + B2DSize aSize(4.0, 8.0); + aSize *= { 2.0, 3.0 }; + + CPPUNIT_ASSERT_DOUBLES_EQUAL(8.0, aSize.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(24.0, aSize.getHeight(), 1e-2); + + aSize *= 2.0; + + CPPUNIT_ASSERT_DOUBLES_EQUAL(16.0, aSize.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(48.0, aSize.getHeight(), 1e-2); + } + + void testOperatorDivide() + { + B2DSize aSize(4.0, 8.0); + aSize /= { 2.0, 8.0 }; + + CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, aSize.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0, aSize.getHeight(), 1e-2); + } + + void testOperatorEqualUnequal() + { + B2DSize aSize(4.0, 8.0); + B2DSize aSize2 = aSize; + + CPPUNIT_ASSERT_EQUAL(true, aSize == aSize); + CPPUNIT_ASSERT_EQUAL(true, aSize == aSize2); + CPPUNIT_ASSERT_EQUAL(true, aSize == B2DSize(4.0, 8.0)); + CPPUNIT_ASSERT_EQUAL(false, aSize == B2DSize(4.0, 7.99)); + CPPUNIT_ASSERT_EQUAL(false, aSize == B2DSize(3.99, 8.0)); + } + + void testOperatorMinus() + { + B2DSize aSizeMinus = -B2DSize(4.0, 8.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-4.0, aSizeMinus.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-8.0, aSizeMinus.getHeight(), 1e-2); + + B2DSize aSizeZero = -B2DSize(0.0, 0.0); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSizeZero.getWidth(), 1e-2); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, aSizeZero.getHeight(), 1e-2); + } + + CPPUNIT_TEST_SUITE(B2DSizeTest); + 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::B2DSizeTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basegfx/test/B2DTupleTest.cxx b/basegfx/test/B2DTupleTest.cxx new file mode 100644 index 0000000000..100808fe8a --- /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 0000000000..f236308aea --- /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 0000000000..89d0d029f9 --- /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 0000000000..0a7c9930e7 --- /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 0000000000..cb8607ea97 --- /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 0000000000..4a84c3662a --- /dev/null +++ b/basegfx/test/BColorModifierTest.cxx @@ -0,0 +1,417 @@ +/* -*- 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)); + } + + void testSaturate() + { + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_saturate>(0.5); + + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack)); + + BColor aExpectedRed(0.6065, 0.1065, 0.1065); + CPPUNIT_ASSERT_EQUAL(aExpectedRed, aBColorModifier->getModifiedColor(maRed)); + BColor aExpectedGreen(0.3575, 0.8575, 0.3575); + CPPUNIT_ASSERT_EQUAL(aExpectedGreen, aBColorModifier->getModifiedColor(maGreen)); + BColor aExpectedBlue(0.036, 0.036, 0.536); + CPPUNIT_ASSERT_EQUAL(aExpectedBlue, aBColorModifier->getModifiedColor(maBlue)); + BColor aExpectedYellow(0.964, 0.964, 0.464); + CPPUNIT_ASSERT_EQUAL(aExpectedYellow, aBColorModifier->getModifiedColor(maYellow)); + BColor aExpectedMagenta(0.6425, 0.1425, 0.6425); + CPPUNIT_ASSERT_EQUAL(aExpectedMagenta, aBColorModifier->getModifiedColor(maMagenta)); + BColor aExpectedCyan(0.3935, 0.8935, 0.8935); + CPPUNIT_ASSERT_EQUAL(aExpectedCyan, 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_saturate>(0.5); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testLuminanceToAlpha() + { + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_luminance_to_alpha>(); + + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maBlack)); + + BColor aExpectedRed(0.7875, 0.7875, 0.7875); + CPPUNIT_ASSERT_EQUAL(aExpectedRed, aBColorModifier->getModifiedColor(maRed)); + BColor aExpectedGreen(0.2846, 0.2846, 0.2846); + CPPUNIT_ASSERT_EQUAL(aExpectedGreen, aBColorModifier->getModifiedColor(maGreen)); + BColor aExpectedBlue(0.9279, 0.9279, 0.9279); + CPPUNIT_ASSERT_EQUAL(aExpectedBlue, aBColorModifier->getModifiedColor(maBlue)); + BColor aExpectedYellow(0.0721, 0.0721, 0.0721); + CPPUNIT_ASSERT_EQUAL(aExpectedYellow, aBColorModifier->getModifiedColor(maYellow)); + BColor aExpectedMagenta(0.7154, 0.7154, 0.7154); + CPPUNIT_ASSERT_EQUAL(aExpectedMagenta, aBColorModifier->getModifiedColor(maMagenta)); + BColor aExpectedCyan(0.2125, 0.2125, 0.2125); + CPPUNIT_ASSERT_EQUAL(aExpectedCyan, 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_luminance_to_alpha>(); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testHueRotate() + { + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_hueRotate>(basegfx::deg2rad(180.0)); + + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack)); + + BColor aExpectedRed(0.0, 0.426, 0.426); + CPPUNIT_ASSERT_EQUAL(aExpectedRed, aBColorModifier->getModifiedColor(maRed)); + BColor aExpectedGreen(1.0, 0.43, 1.0); + CPPUNIT_ASSERT_EQUAL(aExpectedGreen, aBColorModifier->getModifiedColor(maGreen)); + BColor aExpectedBlue(0.144, 0.144, 0); + CPPUNIT_ASSERT_EQUAL(aExpectedBlue, aBColorModifier->getModifiedColor(maBlue)); + BColor aExpectedYellow(0.856, 0.856, 1.0); + CPPUNIT_ASSERT_EQUAL(aExpectedYellow, aBColorModifier->getModifiedColor(maYellow)); + BColor aExpectedMagenta(0.0, 0.57, 0.0); + CPPUNIT_ASSERT_EQUAL(aExpectedMagenta, aBColorModifier->getModifiedColor(maMagenta)); + BColor aExpectedCyan(1.0, 0.574, 0.574); + CPPUNIT_ASSERT_EQUAL(aExpectedCyan, 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_hueRotate>(basegfx::deg2rad(180.0)); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testMatrix() + { + // green matrix + // clang-format off + std::vector<double> aVector = {0.0, 0.0, 0.0, 0.0, 0.0, + 1.0, 1.0, 1.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0, 0.0}; + // clang-format on + + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_matrix>(aVector); + + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maBlack)); + + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maRed)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGreen)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maBlue)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maYellow)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maMagenta)); + CPPUNIT_ASSERT_EQUAL(maGreen, 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_matrix>(aVector); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testMatrixShift() + { + // clang-format off + std::vector<double> aVector = {0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 1.0, + 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0, 0.0}; + // clang-format on + + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_matrix>(aVector); + + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maBlack)); + + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maRed)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGreen)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maBlue)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maYellow)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maMagenta)); + CPPUNIT_ASSERT_EQUAL(maGreen, 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_matrix>(aVector); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testIdentityMatrix() + { + // clang-format off + std::vector<double> aVector = {1.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 1.0, 0.0}; + // clang-format on + + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_matrix>(aVector); + + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maGray, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack)); + + CPPUNIT_ASSERT_EQUAL(maRed, aBColorModifier->getModifiedColor(maRed)); + CPPUNIT_ASSERT_EQUAL(maGreen, aBColorModifier->getModifiedColor(maGreen)); + CPPUNIT_ASSERT_EQUAL(maBlue, aBColorModifier->getModifiedColor(maBlue)); + CPPUNIT_ASSERT_EQUAL(maYellow, aBColorModifier->getModifiedColor(maYellow)); + CPPUNIT_ASSERT_EQUAL(maMagenta, aBColorModifier->getModifiedColor(maMagenta)); + CPPUNIT_ASSERT_EQUAL(maCyan, 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_matrix>(aVector); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + void testBlackAndWhite() + { + const basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_black_and_white>(0.5); + + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maWhite)); + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maGray)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlack)); + + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maRed)); + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maGreen)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maBlue)); + CPPUNIT_ASSERT_EQUAL(maWhite, aBColorModifier->getModifiedColor(maYellow)); + CPPUNIT_ASSERT_EQUAL(maBlack, aBColorModifier->getModifiedColor(maMagenta)); + CPPUNIT_ASSERT_EQUAL(maWhite, 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_black_and_white>(0.5); + CPPUNIT_ASSERT(aBColorModifier->operator==(*aBColorModifier2)); + } + + CPPUNIT_TEST_SUITE(bcolormodifier); + CPPUNIT_TEST(testGray); + CPPUNIT_TEST(testInvert); + CPPUNIT_TEST(testReplace); + CPPUNIT_TEST(testStack); + CPPUNIT_TEST(testSaturate); + CPPUNIT_TEST(testLuminanceToAlpha); + CPPUNIT_TEST(testHueRotate); + CPPUNIT_TEST(testMatrix); + CPPUNIT_TEST(testMatrixShift); + CPPUNIT_TEST(testIdentityMatrix); + CPPUNIT_TEST(testBlackAndWhite); + 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 0000000000..647078f338 --- /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 0000000000..b51da1b0dc --- /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 OUString sExportString = u"m10 10h-20v-20h20z"_ustr; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting rectangle to SVG-D", + 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)", + 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 OUString sExportStringSimpleBezier = + u"m11430 0c-8890 3810 5715 6985 5715 6985" + "l-17145-1905c0 0 22860-10160 16510 6350" + "s-3810-11430-3810-11430z"_ustr; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting bezier polygon to SVG-D", 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 OUString 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"_ustr; + 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", 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)", + 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 OUString 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"_ustr; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting complex polygon to SVG-D", + 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)", + 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 OUString sExportStringRect = u"M0 0H4000V4000H0Z"_ustr; + CPPUNIT_ASSERT_EQUAL_MESSAGE("exporting to rectangle svg-d string", + 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 0000000000..680a421231 --- /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 0000000000..b03560d658 --- /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 0000000000..9c60759193 --- /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 0000000000..e4297b782f --- /dev/null +++ b/basegfx/test/boxclipper.cxx @@ -0,0 +1,398 @@ +/* -*- 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> + +using namespace ::basegfx; + +namespace basegfx2d +{ + +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 OUString 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"_ustr; + 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/clipstate.cxx b/basegfx/test/clipstate.cxx new file mode 100644 index 0000000000..245da3b88d --- /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 OUString unionSvg=u"m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z"_ustr; + + 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 0000000000..af88a66ba3 --- /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: */ |