From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- basegfx/test/boxclipper.cxx | 407 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 basegfx/test/boxclipper.cxx (limited to 'basegfx/test/boxclipper.cxx') diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx new file mode 100644 index 000000000..47d3584df --- /dev/null +++ b/basegfx/test/boxclipper.cxx @@ -0,0 +1,407 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "boxclipper.hxx" + +using namespace ::basegfx; + +namespace basegfx2d +{ +/// Gets a random ordinal [0,n) +double getRandomOrdinal( const std::size_t n ) +{ + // use this one when displaying polygons in OOo, which still sucks + // great rocks when trying to import non-integer svg:d attributes + return comphelper::rng::uniform_size_distribution(0, n-1); +} + +static bool compare(const B2DPoint& left, const B2DPoint& right) +{ + return left.getX() aTmp2(aTmp.count()); + for(sal_uInt32 j=0; j::iterator pSmallest=aTmp2.end(); + for(std::vector::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(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: */ -- cgit v1.2.3