/**************************************************************
 *
 * 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_drawinglayer.hxx"

#include <drawinglayer/texture/texture.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/tools/gradienttools.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvx::GeoTexSvx()
        {
        }

        GeoTexSvx::~GeoTexSvx()
        {
        }

        bool GeoTexSvx::operator==(const GeoTexSvx& /*rGeoTexSvx*/) const
        {
            // default implementation says yes (no data -> no difference)
            return true;
        }

        void GeoTexSvx::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            // base implementation creates random color (for testing only, may also be pure virtual)
            rBColor.setRed((rand() & 0x7fff) / 32767.0);
            rBColor.setGreen((rand() & 0x7fff) / 32767.0);
            rBColor.setBlue((rand() & 0x7fff) / 32767.0);
        }

        void GeoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
        {
            // base implementation uses inverse of luminance of solved color (for testing only, may also be pure virtual)
            basegfx::BColor aBaseColor;
            modifyBColor(rUV, aBaseColor, rfOpacity);
            rfOpacity = 1.0 - aBaseColor.luminance();
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradient::GeoTexSvxGradient(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 /* nSteps */,
            double fBorder)
        :   GeoTexSvx(),
            maGradientInfo(),
            maDefinitionRange(rDefinitionRange),
            maStart(rStart),
            maEnd(rEnd),
            mfBorder(fBorder)
        {
        }

        GeoTexSvxGradient::~GeoTexSvxGradient()
        {
        }

        bool GeoTexSvxGradient::operator==(const GeoTexSvx& rGeoTexSvx) const
        {
            const GeoTexSvxGradient* pCompare = dynamic_cast< const GeoTexSvxGradient* >(&rGeoTexSvx);

            return (pCompare
                && maGradientInfo == pCompare->maGradientInfo
                && maDefinitionRange == pCompare->maDefinitionRange
                && mfBorder == pCompare->mfBorder);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientLinear::GeoTexSvxGradientLinear(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::B2DRange& rOutputRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fAngle)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder),
            mfUnitMinX(0.0),
            mfUnitWidth(1.0),
            mfUnitMaxY(1.0)
        {
            maGradientInfo = basegfx::tools::createLinearODFGradientInfo(
                rDefinitionRange,
                nSteps,
                fBorder,
                fAngle);

            if(rDefinitionRange != rOutputRange)
            {
                basegfx::B2DRange aInvOutputRange(rOutputRange);

                aInvOutputRange.transform(maGradientInfo.getBackTextureTransform());
                mfUnitMinX = aInvOutputRange.getMinX();
                mfUnitWidth = aInvOutputRange.getWidth();
                mfUnitMaxY = aInvOutputRange.getMaxY();
            }
        }

        GeoTexSvxGradientLinear::~GeoTexSvxGradientLinear()
        {
        }

        void GeoTexSvxGradientLinear::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maStart;

            if(maGradientInfo.getSteps())
            {
                const double fStripeWidth(1.0 / maGradientInfo.getSteps());
                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
                basegfx::B2DHomMatrix aPattern;

                // bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
                aPattern.scale(0.5, 0.5);
                aPattern.translate(0.5, 0.5);

                // scale and translate in X
                aPattern.scale(mfUnitWidth, 1.0);
                aPattern.translate(mfUnitMinX, 0.0);

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    const double fPos(fStripeWidth * a);
                    basegfx::B2DHomMatrix aNew(aPattern);

                    // scale and translate in Y
                    double fHeight(1.0 - fPos);

                    if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0)
                    {
                        fHeight += mfUnitMaxY - 1.0;
                    }

                    aNew.scale(1.0, fHeight);
                    aNew.translate(0.0, fPos);

                    // set at target
                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew;

                    // interpolate and set color
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));

                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getLinearGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientAxial::GeoTexSvxGradientAxial(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::B2DRange& rOutputRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fAngle)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder),
            mfUnitMinX(0.0),
            mfUnitWidth(1.0)
        {
            maGradientInfo = basegfx::tools::createAxialODFGradientInfo(
                rDefinitionRange,
                nSteps,
                fBorder,
                fAngle);

            if(rDefinitionRange != rOutputRange)
            {
                basegfx::B2DRange aInvOutputRange(rOutputRange);

                aInvOutputRange.transform(maGradientInfo.getBackTextureTransform());
                mfUnitMinX = aInvOutputRange.getMinX();
                mfUnitWidth = aInvOutputRange.getWidth();
            }
        }

        GeoTexSvxGradientAxial::~GeoTexSvxGradientAxial()
        {
        }

        void GeoTexSvxGradientAxial::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maEnd;

            if(maGradientInfo.getSteps())
            {
                const double fStripeWidth(1.0 / maGradientInfo.getSteps());
                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    const double fPos(fStripeWidth * a);
                    basegfx::B2DHomMatrix aNew;

                    // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1]
                    aNew.scale(0.5, 1.0);
                    aNew.translate(0.5, 0.0);

                    // scale/translate in X
                    aNew.scale(mfUnitWidth, 1.0);
                    aNew.translate(mfUnitMinX, 0.0);

                    // already centerd in Y on X-Axis, just scale in Y
                    aNew.scale(1.0, 1.0 - fPos);

                    // set at target
                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew;

                    // interpolate and set color
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1));

                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getAxialGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientRadial::GeoTexSvxGradientRadial(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fOffsetX,
            double fOffsetY)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder)
        {
            maGradientInfo = basegfx::tools::createRadialODFGradientInfo(
                rDefinitionRange,
                basegfx::B2DVector(fOffsetX,fOffsetY),
                nSteps,
                fBorder);
        }

        GeoTexSvxGradientRadial::~GeoTexSvxGradientRadial()
        {
        }

        void GeoTexSvxGradientRadial::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maStart;

            if(maGradientInfo.getSteps())
            {
                const double fStepSize(1.0 / maGradientInfo.getSteps());
                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    const double fSize(1.0 - (fStepSize * a));
                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize);
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getRadialGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientElliptical::GeoTexSvxGradientElliptical(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fOffsetX,
            double fOffsetY,
            double fAngle)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder)
        {
            maGradientInfo = basegfx::tools::createEllipticalODFGradientInfo(
                rDefinitionRange,
                basegfx::B2DVector(fOffsetX,fOffsetY),
                nSteps,
                fBorder,
                fAngle);
        }

        GeoTexSvxGradientElliptical::~GeoTexSvxGradientElliptical()
        {
        }

        void GeoTexSvxGradientElliptical::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maStart;

            if(maGradientInfo.getSteps())
            {
                double fWidth(1.0);
                double fHeight(1.0);
                double fIncrementX(0.0);
                double fIncrementY(0.0);

                if(maGradientInfo.getAspectRatio() > 1.0)
                {
                    fIncrementY = fHeight / maGradientInfo.getSteps();
                    fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
                }
                else
                {
                    fIncrementX = fWidth / maGradientInfo.getSteps();
                    fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
                }

                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    // next step
                    fWidth -= fIncrementX;
                    fHeight -= fIncrementY;

                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight);
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getEllipticalGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientSquare::GeoTexSvxGradientSquare(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fOffsetX,
            double fOffsetY,
            double fAngle)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder)
        {
            maGradientInfo = basegfx::tools::createSquareODFGradientInfo(
                rDefinitionRange,
                basegfx::B2DVector(fOffsetX,fOffsetY),
                nSteps,
                fBorder,
                fAngle);
        }

        GeoTexSvxGradientSquare::~GeoTexSvxGradientSquare()
        {
        }

        void GeoTexSvxGradientSquare::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maStart;

            if(maGradientInfo.getSteps())
            {
                const double fStepSize(1.0 / maGradientInfo.getSteps());
                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    const double fSize(1.0 - (fStepSize * a));
                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fSize, fSize);
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getSquareGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxGradientRect::GeoTexSvxGradientRect(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::BColor& rStart,
            const basegfx::BColor& rEnd,
            sal_uInt32 nSteps,
            double fBorder,
            double fOffsetX,
            double fOffsetY,
            double fAngle)
        :   GeoTexSvxGradient(rDefinitionRange, rStart, rEnd, nSteps, fBorder)
        {
            maGradientInfo = basegfx::tools::createRectangularODFGradientInfo(
                rDefinitionRange,
                basegfx::B2DVector(fOffsetX,fOffsetY),
                nSteps,
                fBorder,
                fAngle);
        }

        GeoTexSvxGradientRect::~GeoTexSvxGradientRect()
        {
        }

        void GeoTexSvxGradientRect::appendTransformationsAndColors(
            std::vector< B2DHomMatrixAndBColor >& rEntries,
            basegfx::BColor& rOuterColor)
        {
            rOuterColor = maStart;

            if(maGradientInfo.getSteps())
            {
                double fWidth(1.0);
                double fHeight(1.0);
                double fIncrementX(0.0);
                double fIncrementY(0.0);

                if(maGradientInfo.getAspectRatio() > 1.0)
                {
                    fIncrementY = fHeight / maGradientInfo.getSteps();
                    fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
                }
                else
                {
                    fIncrementX = fWidth / maGradientInfo.getSteps();
                    fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
                }

                B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;

                for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++)
                {
                    // next step
                    fWidth -= fIncrementX;
                    fHeight -= fIncrementY;

                    aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::tools::createScaleB2DHomMatrix(fWidth, fHeight);
                    aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1));
                    rEntries.push_back(aB2DHomMatrixAndBColor);
                }
            }
        }

        void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            const double fScaler(basegfx::tools::getRectangularGradientAlpha(rUV, maGradientInfo));

            rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxHatch::GeoTexSvxHatch(
            const basegfx::B2DRange& rDefinitionRange,
            const basegfx::B2DRange& rOutputRange,
            double fDistance,
            double fAngle)
        :   maOutputRange(rOutputRange),
            maTextureTransform(),
            maBackTextureTransform(),
            mfDistance(0.1),
            mfAngle(fAngle),
            mnSteps(10),
            mbDefinitionRangeEqualsOutputRange(rDefinitionRange == rOutputRange)
        {
            double fTargetSizeX(rDefinitionRange.getWidth());
            double fTargetSizeY(rDefinitionRange.getHeight());
            double fTargetOffsetX(rDefinitionRange.getMinX());
            double fTargetOffsetY(rDefinitionRange.getMinY());

            fAngle = -fAngle;

            // add object expansion
            if(0.0 != fAngle)
            {
                const double fAbsCos(fabs(cos(fAngle)));
                const double fAbsSin(fabs(sin(fAngle)));
                const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin);
                const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin);
                fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0;
                fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0;
                fTargetSizeX = fNewX;
                fTargetSizeY = fNewY;
            }

            // add object scale before rotate
            maTextureTransform.scale(fTargetSizeX, fTargetSizeY);

            // add texture rotate after scale to keep perpendicular angles
            if(0.0 != fAngle)
            {
                basegfx::B2DPoint aCenter(0.5, 0.5);
                aCenter *= maTextureTransform;

                maTextureTransform = basegfx::tools::createRotateAroundPoint(aCenter, fAngle)
                    * maTextureTransform;
            }

            // add object translate
            maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY);

            // prepare height for texture
            const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0);
            mnSteps = basegfx::fround(fSteps + 0.5);
            mfDistance = 1.0 / fSteps;
        }

        GeoTexSvxHatch::~GeoTexSvxHatch()
        {
        }

        bool GeoTexSvxHatch::operator==(const GeoTexSvx& rGeoTexSvx) const
        {
            const GeoTexSvxHatch* pCompare = dynamic_cast< const GeoTexSvxHatch* >(&rGeoTexSvx);
            return (pCompare
                && maOutputRange == pCompare->maOutputRange
                && maTextureTransform == pCompare->maTextureTransform
                && mfDistance == pCompare->mfDistance
                && mfAngle == pCompare->mfAngle
                && mnSteps == pCompare->mnSteps);
        }

        void GeoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
        {
            if(mbDefinitionRangeEqualsOutputRange)
            {
                // simple hatch where the definition area equals the output area
                for(sal_uInt32 a(1); a < mnSteps; a++)
                {
                    // create matrix
                    const double fOffset(mfDistance * (double)a);
                    basegfx::B2DHomMatrix aNew;
                    aNew.set(1, 2, fOffset);
                    rMatrices.push_back(maTextureTransform * aNew);
                }
            }
            else
            {
                // output area is different from definition area, back-transform to get
                // the output area in unit coordinates and fill this with hatch lines
                // using the settings derived from the definition area
                basegfx::B2DRange aBackUnitRange(maOutputRange);

                aBackUnitRange.transform(getBackTextureTransform());

                // calculate vertical start value and a security maximum integer value to avoid death loops
                double fStart(basegfx::snapToNearestMultiple(aBackUnitRange.getMinY(), mfDistance));
                const sal_uInt32 nNeededIntegerSteps(basegfx::fround((aBackUnitRange.getHeight() / mfDistance) + 0.5));
                sal_uInt32 nMaxIntegerSteps(::std::min(nNeededIntegerSteps, sal_uInt32(10000)));

                while(fStart < aBackUnitRange.getMaxY() && nMaxIntegerSteps)
                {
                    // create new transform for
                    basegfx::B2DHomMatrix aNew;

                    // adapt x scale and position
                    //aNew.scale(aBackUnitRange.getWidth(), 1.0);
                    //aNew.translate(aBackUnitRange.getMinX(), 0.0);
                    aNew.set(0, 0, aBackUnitRange.getWidth());
                    aNew.set(0, 2, aBackUnitRange.getMinX());

                    // adapt y position to current step
                    aNew.set(1, 2, fStart);
                    //aNew.translate(0.0, fStart);

                    // add new transformation
                    rMatrices.push_back(maTextureTransform * aNew);

                    // next step
                    fStart += mfDistance;
                    nMaxIntegerSteps--;
                }
            }
        }

        double GeoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const
        {
            const basegfx::B2DPoint aCoor(getBackTextureTransform() * rUV);
            return fmod(aCoor.getY(), mfDistance);
        }

        const basegfx::B2DHomMatrix& GeoTexSvxHatch::getBackTextureTransform() const
        {
            if(maBackTextureTransform.isIdentity())
            {
                const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform = maTextureTransform;
                const_cast< GeoTexSvxHatch* >(this)->maBackTextureTransform.invert();
            }

            return maBackTextureTransform;
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxTiled::GeoTexSvxTiled(
            const basegfx::B2DRange& rRange,
            double fOffsetX,
            double fOffsetY)
        :   maRange(rRange),
            mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)),
            mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0))
        {
            if(!basegfx::fTools::equalZero(mfOffsetX))
            {
                mfOffsetY = 0.0;
            }
        }

        GeoTexSvxTiled::~GeoTexSvxTiled()
        {
        }

        bool GeoTexSvxTiled::operator==(const GeoTexSvx& rGeoTexSvx) const
        {
            const GeoTexSvxTiled* pCompare = dynamic_cast< const GeoTexSvxTiled* >(&rGeoTexSvx);

            return (pCompare
                && maRange == pCompare->maRange
                && mfOffsetX == pCompare->mfOffsetX
                && mfOffsetY == pCompare->mfOffsetY);
        }

        void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
        {
            const double fWidth(maRange.getWidth());

            if(!basegfx::fTools::equalZero(fWidth))
            {
                const double fHeight(maRange.getHeight());

                if(!basegfx::fTools::equalZero(fHeight))
                {
                    double fStartX(maRange.getMinX());
                    double fStartY(maRange.getMinY());
                    sal_Int32 nPosX(0);
                    sal_Int32 nPosY(0);

                    if(basegfx::fTools::more(fStartX, 0.0))
                    {
                        const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1);

                        nPosX -= nDiff;
                        fStartX -= nDiff * fWidth;
                    }

                    if(basegfx::fTools::less(fStartX + fWidth, 0.0))
                    {
                        const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth)));

                        nPosX += nDiff;
                        fStartX += nDiff * fWidth;
                    }

                    if(basegfx::fTools::more(fStartY, 0.0))
                    {
                        const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1);

                        nPosY -= nDiff;
                        fStartY -= nDiff * fHeight;
                    }

                    if(basegfx::fTools::less(fStartY + fHeight, 0.0))
                    {
                        const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight)));

                        nPosY += nDiff;
                        fStartY += nDiff * fHeight;
                    }

                    if(!basegfx::fTools::equalZero(mfOffsetY))
                    {
                        for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth, nPosX++)
                        {
                            for(double fPosY(nPosX % 2 ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY);
                                basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight)
                            {
                                rMatrices.push_back(
                                    basegfx::tools::createScaleTranslateB2DHomMatrix(
                                        fWidth,
                                        fHeight,
                                        fPosX,
                                        fPosY));
                            }
                        }
                    }
                    else
                    {
                        for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight, nPosY++)
                        {
                            for(double fPosX(nPosY % 2 ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX);
                                basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth)
                            {
                                rMatrices.push_back(
                                    basegfx::tools::createScaleTranslateB2DHomMatrix(
                                        fWidth,
                                        fHeight,
                                        fPosX,
                                        fPosY));
                            }
                        }
                    }
                }
            }
        }
    } // end of namespace texture
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////
// eof
