/**************************************************************
 * 
 * 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 "gtest/gtest.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;

// FIXME:
#define RUN_OLD_FAILING_TESTS 0

namespace basegfx2d
{

class clipstate : public ::testing::Test
{
protected:
    tools::B2DClipState aUnion1; 
    tools::B2DClipState aUnion2; 
    tools::B2DClipState aIntersect; 
    tools::B2DClipState aXor; 
    tools::B2DClipState aSubtract; 

public:
    virtual 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);
    }

    virtual 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;
        ASSERT_TRUE(tools::importFromSvgD(
                               aTmp1, rtl::OUString::createFromAscii(sSvg), false, 0)) << sName;

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

        ASSERT_TRUE(aTmp2 == aTmp1) << sName;
    }
};

TEST_F(clipstate, 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";

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

TEST_F(clipstate, 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";
#if RUN_OLD_FAILING_TESTS
    verifyPoly("mixed clip", mixedClipSvg, aMixedClip);
#endif
}

// -----------------------------------------------------------------------------

} // namespace basegfx2d
