/**************************************************************
 *
 * 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/texture3d.hxx>
#include <vcl/bmpacc.hxx>
#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>

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

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxMono::GeoTexSvxMono(
            const basegfx::BColor& rSingleColor,
            double fOpacity)
        :	maSingleColor(rSingleColor),
            mfOpacity(fOpacity)
        {
        }

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

            return (pCompare
                && maSingleColor == pCompare->maSingleColor
                && mfOpacity == pCompare->mfOpacity);
        }

        void GeoTexSvxMono::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
        {
            rBColor = maSingleColor;
        }

        void GeoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& /*rUV*/, double& rfOpacity) const
        {
            rfOpacity = mfOpacity;
        }
    } // end of namespace texture
} // end of namespace drawinglayer

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

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxBitmapEx::GeoTexSvxBitmapEx(
            const BitmapEx& rBitmapEx,
            const basegfx::B2DRange& rRange)
        :	maBitmapEx(rBitmapEx),
            mpReadBitmap(0),
            maTransparence(),
            mpReadTransparence(0),
            maTopLeft(rRange.getMinimum()),
            maSize(rRange.getRange()),
            mfMulX(0.0),
            mfMulY(0.0),
            mbIsAlpha(false),
            mbIsTransparent(maBitmapEx.IsTransparent())
        {
            // #121194# Todo: use alpha channel, too (for 3d)
            mpReadBitmap = maBitmapEx.GetBitmap().AcquireReadAccess();
            OSL_ENSURE(mpReadBitmap, "GeoTexSvxBitmapEx: Got no read access to Bitmap (!)");

            if(mbIsTransparent)
            {
                if(maBitmapEx.IsAlpha())
                {
                    mbIsAlpha = true;
                    maTransparence = rBitmapEx.GetAlpha().GetBitmap();
                }
                else
                {
                    maTransparence = rBitmapEx.GetMask();
                }

                mpReadTransparence = maTransparence.AcquireReadAccess();
            }

            mfMulX = (double)mpReadBitmap->Width() / maSize.getX();
            mfMulY = (double)mpReadBitmap->Height() / maSize.getY();

            if(maSize.getX() <= 1.0)
            {
                maSize.setX(1.0);
            }

            if(maSize.getY() <= 1.0)
            {
                maSize.setY(1.0);
            }
        }

        GeoTexSvxBitmapEx::~GeoTexSvxBitmapEx()
        {
            delete mpReadTransparence;
            delete mpReadBitmap;
        }

        sal_uInt8 GeoTexSvxBitmapEx::impGetTransparence(sal_Int32& rX, sal_Int32& rY) const
        {
            switch(maBitmapEx.GetTransparentType())
            {
                case TRANSPARENT_NONE:
                {
                    break;
                }
                case TRANSPARENT_COLOR:
                {
                    const BitmapColor aBitmapColor(mpReadBitmap->GetColor(rY, rX));

                    if(maBitmapEx.GetTransparentColor() == aBitmapColor.operator Color())
                    {
                        return 255;
                    }

                    break;
                }
                case TRANSPARENT_BITMAP:
                {
                    OSL_ENSURE(mpReadTransparence, "OOps, transparence type Bitmap, but no read access created in the constructor (?)");
                    const BitmapColor aBitmapColor(mpReadTransparence->GetPixel(rY, rX));

                    if(mbIsAlpha)
                    {
                        return aBitmapColor.GetIndex();
                    }
                    else
                    {
                        if(0x00 != aBitmapColor.GetIndex())
                        {
                            return 255;
                        }
                    }
                    break;
                }
            }

            return 0;
        }

        bool GeoTexSvxBitmapEx::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const
        {
            if(mpReadBitmap)
            {
                rX = (sal_Int32)((rUV.getX() - maTopLeft.getX()) * mfMulX);

                if(rX >= 0L && rX < mpReadBitmap->Width())
                {
                    rY = (sal_Int32)((rUV.getY() - maTopLeft.getY()) * mfMulY);

                    return (rY >= 0L && rY < mpReadBitmap->Height());
                }
            }

            return false;
        }

        void GeoTexSvxBitmapEx::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
        {
            sal_Int32 nX, nY;

            if(impIsValid(rUV, nX, nY))
            {
                const double fConvertColor(1.0 / 255.0);
                const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
                const basegfx::BColor aBSource(
                    (double)aBMCol.GetRed() * fConvertColor,
                    (double)aBMCol.GetGreen() * fConvertColor,
                    (double)aBMCol.GetBlue() * fConvertColor);

                rBColor = aBSource;

                if(mbIsTransparent)
                {
                    // when we have a transparence, make use of it
                    const sal_uInt8 aLuminance(impGetTransparence(nX, nY));

                    rfOpacity = ((double)(0xff - aLuminance) * (1.0 / 255.0));
                }
                else
                {
                    rfOpacity = 1.0;
                }
            }
            else
            {
                rfOpacity = 0.0;
            }
        }

        void GeoTexSvxBitmapEx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
        {
            sal_Int32 nX, nY;

            if(impIsValid(rUV, nX, nY))
            {
                if(mbIsTransparent)
                {
                    // this texture has an alpha part, use it
                    const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
                    const double fNewOpacity((double)(0xff - aLuminance) * (1.0 / 255.0));

                    rfOpacity = 1.0 - ((1.0 - fNewOpacity) * (1.0 - rfOpacity));
                }
                else
                {
                    // this texture is a color bitmap used as transparence map
                    const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
                    const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue());

                    rfOpacity = ((double)(0xff - aColor.GetLuminance()) * (1.0 / 255.0));
                }
            }
            else
            {
                rfOpacity = 0.0;
            }
        }
    } // end of namespace texture
} // end of namespace drawinglayer

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

namespace drawinglayer
{
    namespace texture
    {
        basegfx::B2DPoint GeoTexSvxBitmapExTiled::impGetCorrected(const basegfx::B2DPoint& rUV) const
        {
            double fX(rUV.getX() - maTopLeft.getX());
            double fY(rUV.getY() - maTopLeft.getY());

            if(mbUseOffsetX)
            {
                const sal_Int32 nCol(static_cast< sal_Int32 >((fY < 0.0 ? maSize.getY() -fY : fY) / maSize.getY()));

                if(nCol % 2)
                {
                    fX += mfOffsetX * maSize.getX();
                }
            }
            else if(mbUseOffsetY)
            {
                const sal_Int32 nRow(static_cast< sal_Int32 >((fX < 0.0 ? maSize.getX() -fX : fX) / maSize.getX()));

                if(nRow % 2)
                {
                    fY += mfOffsetY * maSize.getY();
                }
            }

            fX = fmod(fX, maSize.getX());
            fY = fmod(fY, maSize.getY());

            if(fX < 0.0)
            {
                fX += maSize.getX();
            }

            if(fY < 0.0)
            {
                fY += maSize.getY();
            }

            return basegfx::B2DPoint(fX + maTopLeft.getX(), fY + maTopLeft.getY());
        }

        GeoTexSvxBitmapExTiled::GeoTexSvxBitmapExTiled(
            const BitmapEx& rBitmapEx,
            const basegfx::B2DRange& rRange,
            double fOffsetX,
            double fOffsetY)
        :	GeoTexSvxBitmapEx(rBitmapEx, rRange),
            mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)),
            mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0)),
            mbUseOffsetX(!basegfx::fTools::equalZero(mfOffsetX)),
            mbUseOffsetY(!mbUseOffsetX && !basegfx::fTools::equalZero(mfOffsetY))
        {
        }

        void GeoTexSvxBitmapExTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
        {
            if(mpReadBitmap)
            {
                GeoTexSvxBitmapEx::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity);
            }
        }

        void GeoTexSvxBitmapExTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
        {
            if(mpReadBitmap)
            {
                GeoTexSvxBitmapEx::modifyOpacity(impGetCorrected(rUV), rfOpacity);
            }
        }
    } // end of namespace texture
} // end of namespace drawinglayer

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

namespace drawinglayer
{
    namespace texture
    {
        GeoTexSvxMultiHatch::GeoTexSvxMultiHatch(
            const primitive3d::HatchTexturePrimitive3D& rPrimitive,
            double fLogicPixelSize)
        :	mfLogicPixelSize(fLogicPixelSize),
            mp0(0L),
            mp1(0L),
            mp2(0L)
        {
            const attribute::FillHatchAttribute& rHatch(rPrimitive.getHatch());
            const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
            const double fAngleA(rHatch.getAngle());
            maColor = rHatch.getColor();
            mbFillBackground = rHatch.isFillBackground();
            mp0 = new GeoTexSvxHatch(
                aOutlineRange,
                aOutlineRange,
                rHatch.getDistance(),
                fAngleA);

            if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
            {
                mp1 = new GeoTexSvxHatch(
                    aOutlineRange,
                    aOutlineRange,
                    rHatch.getDistance(),
                    fAngleA + F_PI2);
            }

            if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
            {
                mp2 = new GeoTexSvxHatch(
                    aOutlineRange,
                    aOutlineRange,
                    rHatch.getDistance(),
                    fAngleA + F_PI4);
            }
        }

        GeoTexSvxMultiHatch::~GeoTexSvxMultiHatch()
        {
            delete mp0;
            delete mp1;
            delete mp2;
        }

        bool GeoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const
        {
            if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize)
            {
                return true;
            }

            if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize)
            {
                return true;
            }

            if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize)
            {
                return true;
            }

            return false;
        }

        void GeoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
        {
            if(impIsOnHatch(rUV))
            {
                rBColor = maColor;
            }
            else if(!mbFillBackground)
            {
                rfOpacity = 0.0;
            }
        }

        void GeoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
        {
            if(mbFillBackground || impIsOnHatch(rUV))
            {
                rfOpacity = 1.0;
            }
            else
            {
                rfOpacity = 0.0;
            }
        }
    } // end of namespace texture
} // end of namespace drawinglayer

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