/**************************************************************
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/




// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
// autogenerated file with codegen.pl

#include "preextstl.h"
#include "cppunit/TestAssert.h"
#include "cppunit/TestFixture.h"
#include "cppunit/extensions/HelperMacros.h"
#include "postextstl.h"

#include <basegfx/tools/b2dclipstate.hxx>
#include <basegfx/range/b2dpolyrange.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <boost/bind.hpp>

using namespace ::basegfx;


namespace basegfx2d
{

class clipstate : public CppUnit::TestFixture
{
private:
    tools::B2DClipState aUnion1;
    tools::B2DClipState aUnion2;
    tools::B2DClipState aIntersect;
    tools::B2DClipState aXor;
    tools::B2DClipState aSubtract;

public:
    void setUp()
    {
        B2DRange aCenter(100, 100, -100, -100);
        B2DRange aNorth(-10, -110, 10, -90);
        B2DRange aWest(-110, -10, -90, 10);
        B2DRange aSouth(-10, 110, 10, 90);
        B2DRange aEast(110, -10, 90, 10);

        aUnion1.unionRange(aCenter);
        aUnion1.unionRange(aNorth);
        aUnion1.unionRange(aWest);
        aUnion1.unionRange(aSouth);
        aUnion1.unionRange(aEast);

        aUnion2.makeNull();
        aUnion2.unionRange(aCenter);
        aUnion2.unionRange(aNorth);
        aUnion2.unionRange(aWest);
        aUnion2.unionRange(aSouth);
        aUnion2.unionRange(aEast);

        aIntersect.intersectRange(aCenter);
        aIntersect.intersectRange(aNorth);
        aIntersect.intersectRange(aWest);
        aIntersect.intersectRange(aSouth);
        aIntersect.intersectRange(aEast);

        aXor.makeNull();
        aXor.xorRange(aCenter);
        aXor.xorRange(aNorth);
        aXor.xorRange(aWest);
        aXor.xorRange(aSouth);
        aXor.xorRange(aEast);

        aSubtract.intersectRange(aCenter);
        aSubtract.subtractRange(aNorth);
        aSubtract.subtractRange(aWest);
        aSubtract.subtractRange(aSouth);
        aSubtract.subtractRange(aEast);
    }

    void tearDown()
    {}

    void verifyPoly(const char* sName, const char* sSvg, const tools::B2DClipState& toTest)
    {
#if defined(VERBOSE)
        fprintf(stderr, "%s - svg:d=\"%s\"\n",
                sName, rtl::OUStringToOString(
                    basegfx::tools::exportToSvgD(toTest.getClipPoly(), true, true, false),
                    RTL_TEXTENCODING_UTF8).getStr() );
#endif

        B2DPolyPolygon aTmp1;
        CPPUNIT_ASSERT_MESSAGE(sName,
                               tools::importFromSvgD(
                                   aTmp1, rtl::OUString::createFromAscii(sSvg), false, 0));

        const rtl::OUString aSvg=
            tools::exportToSvgD(toTest.getClipPoly(), true, true, false);
        B2DPolyPolygon aTmp2;
        CPPUNIT_ASSERT_MESSAGE(sName,
                               tools::importFromSvgD(
                                   aTmp2, aSvg, false, 0));

        CPPUNIT_ASSERT_MESSAGE(
            sName,
            aTmp2 == aTmp1);
    }

    void verifySimpleRange()
    {
        const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
        const char* intersectSvg="m-100 10v-20h10v20zm80 90v-10h20v10zm-20-190v-10h20v10zm80 100v-20h10v20z";
        const char* xorSvg="m-100 10h10v-20h-10zm90 110h20v-10h-20zm0-180h20v-10h-20zm100 110h10v-20h-10zm10 20v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";
        const char* subtractSvg="m-90 10v-20h-10v-90h90v10h20v-10h90v90h-10v20h10v90h-90v-10h-20v10h-90v-90z";

        CPPUNIT_ASSERT_MESSAGE("cleared clip stays empty under union operation",
                               aUnion1.isCleared());
        verifyPoly("union", unionSvg, aUnion2);
        verifyPoly("intersect", intersectSvg, aIntersect);
        verifyPoly("xor", xorSvg, aXor);
        verifyPoly("subtract", subtractSvg, aSubtract);
    }

    void verifyMixedClips()
    {
        tools::B2DClipState aMixedClip;

        const char* unionSvg="m100 10v90h-90v10h-20v-10h-90v-90h-10v-20h10v-90h90v-10h20v10h90v90h10v20z";

        B2DPolyPolygon aTmp1;
        tools::importFromSvgD(
            aTmp1, rtl::OUString::createFromAscii(unionSvg), false, 0);

        aMixedClip.intersectPolyPolygon(aTmp1);
        aMixedClip.subtractRange(B2DRange(-20,-150,20,0));
        aMixedClip.subtractRange(B2DRange(-150,-20,0,20));
        aMixedClip.xorRange(B2DRange(-150,-150,150,150));

        const char* mixedClipSvg="m0 0v20h-100v80h90v10h20v-10h90v-90h10v-20h-10v-90h-80v100zm-40-20v-80h-80v80zm-50 170v-300h300v300z";
        verifyPoly("mixed clip", mixedClipSvg, aMixedClip);
    }

    CPPUNIT_TEST_SUITE(clipstate);
    CPPUNIT_TEST(verifySimpleRange);
    CPPUNIT_TEST(verifyMixedClips);
    CPPUNIT_TEST_SUITE_END();
};

// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::clipstate);
} // namespace basegfx2d