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

#include <canvas/debug.hxx>
#include <tools/diagnose_ex.h>

#include <rtl/math.hxx>
#include <rtl/logfile.hxx>

#include <com/sun/star/geometry/RealSize2D.hpp>
#include <com/sun/star/geometry/RealPoint2D.hpp>
#include <com/sun/star/geometry/RealRectangle2D.hpp>
#include <com/sun/star/rendering/RenderState.hpp>
#include <com/sun/star/rendering/XCanvas.hpp>
#include <com/sun/star/rendering/XBitmap.hpp>
#include <com/sun/star/rendering/XPolyPolygon2D.hpp>
#include <com/sun/star/geometry/RealBezierSegment2D.hpp>
#include <com/sun/star/rendering/XIntegerBitmap.hpp>

#include <vcl/salbtype.hxx>
#include <vcl/bmpacc.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/metric.hxx>
#include <vcl/canvastools.hxx>

#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <canvas/canvastools.hxx>

#include "impltools.hxx"
#include "canvasbitmap.hxx"

#include <numeric>


using namespace ::com::sun::star;

namespace vclcanvas
{
    namespace tools
    {
        ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
        {
            // TODO(F3): CanvasCustomSprite should also be tunnelled
            // through (also implements XIntegerBitmap interface)
            CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() );

            if( pBitmapImpl )
            {
                return pBitmapImpl->getBitmap();
            }
            else
            {
                SpriteCanvas* pCanvasImpl = dynamic_cast< SpriteCanvas* >( xBitmap.get() );
                if( pCanvasImpl && pCanvasImpl->getBackBuffer() )
                {
                    // TODO(F3): mind the plain Canvas impl. Consolidate with CWS canvas05
                    const ::OutputDevice& rDev( pCanvasImpl->getBackBuffer()->getOutDev() );
                    const ::Point aEmptyPoint;
                    return rDev.GetBitmapEx( aEmptyPoint,
                                             rDev.GetOutputSizePixel() );
                }

                // TODO(F2): add support for floating point bitmap formats
                uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntBmp( 
                    xBitmap, uno::UNO_QUERY_THROW );

                ::BitmapEx aBmpEx = ::vcl::unotools::bitmapExFromXBitmap( xIntBmp );
                if( !!aBmpEx )
                    return aBmpEx;

                // TODO(F1): extract pixel from XBitmap interface
                ENSURE_OR_THROW( false, 
                                  "bitmapExFromXBitmap(): could not extract bitmap" );
            }
 
            return ::BitmapEx();
        }

        bool setupFontTransform( ::Point&						o_rPoint,
                                 ::Font& 						io_rVCLFont, 
                                 const rendering::ViewState& 	rViewState,
                                 const rendering::RenderState& 	rRenderState,
                                 ::OutputDevice&				rOutDev )
        {
            ::basegfx::B2DHomMatrix aMatrix;
            
            ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
                                                         rViewState,
                                                         rRenderState);

            ::basegfx::B2DTuple aScale;
            ::basegfx::B2DTuple aTranslate;
            double nRotate, nShearX;
            
            aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );

            // #i72417# detecting the 180 degree rotation case manually here.
            if( aScale.getX() < 0.0 && 
                aScale.getY() < 0.0 && 
                basegfx::fTools::equalZero(nRotate) )
            {
                aScale *= -1.0;
                nRotate += M_PI;
            }

            // query font metric _before_ tampering with width and height
            if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) )
            {
                // retrieve true font width
                const sal_Int32 nFontWidth( rOutDev.GetFontMetric( io_rVCLFont ).GetWidth() );

                const sal_Int32 nScaledFontWidth( ::basegfx::fround(nFontWidth * aScale.getX()) );

                if( !nScaledFontWidth )
                {
                    // scale is smaller than one pixel - disable text
                    // output altogether
                    return false;
                }

                io_rVCLFont.SetWidth( nScaledFontWidth );
            }

            if( !::rtl::math::approxEqual(aScale.getY(), 1.0) )
            {
                const sal_Int32 nFontHeight( io_rVCLFont.GetHeight() );
                io_rVCLFont.SetHeight( ::basegfx::fround(nFontHeight * aScale.getY()) );
            }

            io_rVCLFont.SetOrientation( static_cast< short >( ::basegfx::fround(-fmod(nRotate, 2*M_PI)*(1800.0/M_PI)) ) );

            // TODO(F2): Missing functionality in VCL: shearing
            o_rPoint.X() = ::basegfx::fround(aTranslate.getX());
            o_rPoint.Y() = ::basegfx::fround(aTranslate.getY());

            return true;
        }

        bool isRectangle( const PolyPolygon& rPolyPoly )
        {
            // exclude some cheap cases first
            if( rPolyPoly.Count() != 1 )
                return false;

            const ::Polygon& rPoly( rPolyPoly[0] );

            sal_uInt16 nCount( rPoly.GetSize() );
            if( nCount < 4 )
                return false;

            // delegate to basegfx
            return ::basegfx::tools::isRectangle( rPoly.getB2DPolygon() );
        }


        // VCL-Canvas related
        //---------------------------------------------------------------------

        ::Point mapRealPoint2D( const geometry::RealPoint2D& 	rPoint,
                                const rendering::ViewState& 	rViewState,
                                const rendering::RenderState&	rRenderState )
        {
            ::basegfx::B2DPoint aPoint( ::basegfx::unotools::b2DPointFromRealPoint2D(rPoint) );

            ::basegfx::B2DHomMatrix aMatrix;
            aPoint *= ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
                                                                   rViewState,
                                                                   rRenderState);

            return ::vcl::unotools::pointFromB2DPoint( aPoint );
        }

        ::PolyPolygon mapPolyPolygon( const ::basegfx::B2DPolyPolygon& 	rPoly,
                                      const rendering::ViewState& 		rViewState,
                                      const rendering::RenderState&		rRenderState )
        {
            ::basegfx::B2DHomMatrix aMatrix;
            ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
                                                         rViewState,
                                                         rRenderState);

            ::basegfx::B2DPolyPolygon aTemp( rPoly );

            aTemp.transform( aMatrix );

            return ::PolyPolygon( aTemp );
        }

        ::BitmapEx transformBitmap( const BitmapEx& 				rBitmap,
                                    const ::basegfx::B2DHomMatrix& 	rTransform,
                                    const uno::Sequence< double >&	rDeviceColor,
                                    ModulationMode					eModulationMode )
        {
            RTL_LOGFILE_CONTEXT( aLog, "::vclcanvas::tools::transformBitmap()" );
            RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::vclcanvas::tools::transformBitmap: 0x%X", &rBitmap );
            
            // calc transformation and size of bitmap to be
            // generated. Note, that the translational components are
            // deleted from the transformation; this can be handled by
            // an offset when painting the bitmap
            const Size 					aBmpSize( rBitmap.GetSizePixel() );
            ::basegfx::B2DRectangle		aDestRect;
            
            bool bCopyBack( false );

            // calc effective transformation for bitmap
            const ::basegfx::B2DRectangle aSrcRect( 0, 0,
                                                    aBmpSize.Width(),
                                                    aBmpSize.Height() );
            ::canvas::tools::calcTransformedRectBounds( aDestRect, 
                                                        aSrcRect,
                                                        rTransform );

            // re-center bitmap, such that it's left, top border is
            // aligned with (0,0). The method takes the given
            // rectangle, and calculates a transformation that maps
            // this rectangle unscaled to the origin.
            ::basegfx::B2DHomMatrix aLocalTransform;
            ::canvas::tools::calcRectToOriginTransform( aLocalTransform,
                                                        aSrcRect,
                                                        rTransform );

            const bool bModulateColors( eModulationMode == MODULATE_WITH_DEVICECOLOR &&
                                        rDeviceColor.getLength() > 2 );
            const double nRedModulation( bModulateColors ? rDeviceColor[0] : 1.0 );
            const double nGreenModulation( bModulateColors ? rDeviceColor[1] : 1.0 );
            const double nBlueModulation( bModulateColors ? rDeviceColor[2] : 1.0 );
            const double nAlphaModulation( bModulateColors && rDeviceColor.getLength() > 3 ? 
                                           rDeviceColor[3] : 1.0 );

            Bitmap aSrcBitmap( rBitmap.GetBitmap() );
            Bitmap aSrcAlpha;

            // differentiate mask and alpha channel (on-off
            // vs. multi-level transparency)
            if( rBitmap.IsTransparent() )
            {
                if( rBitmap.IsAlpha() )
                    aSrcAlpha = rBitmap.GetAlpha().GetBitmap();
                else
                    aSrcAlpha = rBitmap.GetMask();
            }

            ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(),
                                                aSrcBitmap );
            ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ? 
                                                     aSrcAlpha.AcquireReadAccess() : 
                                                     (BitmapReadAccess*)NULL,
                                                     aSrcAlpha );

            if( pReadAccess.get() == NULL ||
                (pAlphaReadAccess.get() == NULL && rBitmap.IsTransparent()) )
            {
                // TODO(E2): Error handling!
                ENSURE_OR_THROW( false, 
                                  "transformBitmap(): could not access source bitmap" );
            }

            // mapping table, to translate pAlphaReadAccess' pixel
            // values into destination alpha values (needed e.g. for
            // paletted 1-bit masks).
            sal_uInt8 aAlphaMap[256];

            if( rBitmap.IsTransparent() )
            {
                if( rBitmap.IsAlpha() )
                {
                    // source already has alpha channel - 1:1 mapping,
                    // i.e. aAlphaMap[0]=0,...,aAlphaMap[255]=255.
                    sal_uInt8* p = aAlphaMap;
                    for( int n = 0; n < 256; ++n) *(p++) = n;
                }
                else
                {
                    // mask transparency - determine used palette colors
                    const BitmapColor& rCol0( pAlphaReadAccess->GetPaletteColor( 0 ) );
                    const BitmapColor& rCol1( pAlphaReadAccess->GetPaletteColor( 1 ) );

                    // shortcut for true luminance calculation
                    // (assumes that palette is grey-level)
                    aAlphaMap[0] = rCol0.GetRed();
                    aAlphaMap[1] = rCol1.GetRed();
                }
            }
            // else: mapping table is not used

            const Size aDestBmpSize( ::basegfx::fround( aDestRect.getWidth() ), 
                                     ::basegfx::fround( aDestRect.getHeight() ) );

            if( aDestBmpSize.Width() == 0 || aDestBmpSize.Height() == 0 )
                return BitmapEx();

            Bitmap aDstBitmap( aDestBmpSize, aSrcBitmap.GetBitCount(), &pReadAccess->GetPalette() );
            Bitmap aDstAlpha( AlphaMask( aDestBmpSize ).GetBitmap() );

            {
                // just to be on the safe side: let the
                // ScopedAccessors get destructed before
                // copy-constructing the resulting bitmap. This will
                // rule out the possibility that cached accessor data
                // is not yet written back.
                ScopedBitmapWriteAccess pWriteAccess( aDstBitmap.AcquireWriteAccess(),
                                                      aDstBitmap );
                ScopedBitmapWriteAccess pAlphaWriteAccess( aDstAlpha.AcquireWriteAccess(),
                                                           aDstAlpha );

                
                if( pWriteAccess.get() != NULL &&
                    pAlphaWriteAccess.get() != NULL &&
                    rTransform.isInvertible() )
                {
                    // we're doing inverse mapping here, i.e. mapping
                    // points from the destination bitmap back to the
                    // source
                    ::basegfx::B2DHomMatrix aTransform( aLocalTransform );
                    aTransform.invert();
                
                    // for the time being, always read as ARGB 
                    for( int y=0; y<aDestBmpSize.Height(); ++y )
                    {
                        if( bModulateColors )
                        {
                            // TODO(P2): Have different branches for
                            // alpha-only modulation (color
                            // modulations eq. 1.0)

                            // modulate all color channels with given
                            // values

                            // differentiate mask and alpha channel (on-off
                            // vs. multi-level transparency)
                            if( rBitmap.IsTransparent() )
                            {
                                // Handling alpha and mask just the same...
                                for( int x=0; x<aDestBmpSize.Width(); ++x )
                                {
                                    ::basegfx::B2DPoint aPoint(x,y);
                                    aPoint *= aTransform;

                                    const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
                                    const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
                                    if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                                        nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                                    {
                                        pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
                                    }
                                    else
                                    {
                                        // modulate alpha with
                                        // nAlphaModulation. This is a
                                        // little bit verbose, formula
                                        // is 255 - (255-pixAlpha)*nAlphaModulation
                                        // (invert 'alpha' pixel value, 
                                        // to get the standard alpha 
                                        // channel behaviour)
                                        const sal_uInt8 cMappedAlphaIdx = aAlphaMap[ pAlphaReadAccess->GetPixelIndex( nSrcY, nSrcX ) ];
                                        const sal_uInt8 cModulatedAlphaIdx = 255U - static_cast<sal_uInt8>( nAlphaModulation* (255U - cMappedAlphaIdx) + .5 );
                                        pAlphaWriteAccess->SetPixelIndex( y, x, cModulatedAlphaIdx );
                                        BitmapColor aColor( pReadAccess->GetPixel( nSrcY, nSrcX ) );

                                        aColor.SetRed( 
                                            static_cast<sal_uInt8>(
                                                nRedModulation *
                                                aColor.GetRed() + .5 ));
                                        aColor.SetGreen( 
                                            static_cast<sal_uInt8>(
                                                nGreenModulation *
                                                aColor.GetGreen() + .5 ));
                                        aColor.SetBlue( 
                                            static_cast<sal_uInt8>(
                                                nBlueModulation *
                                                aColor.GetBlue() + .5 ));

                                        pWriteAccess->SetPixel( y, x, 
                                                                aColor );
                                    }
                                }
                            }
                            else
                            {
                                for( int x=0; x<aDestBmpSize.Width(); ++x )
                                {
                                    ::basegfx::B2DPoint aPoint(x,y);
                                    aPoint *= aTransform;

                                    const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
                                    const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
                                    if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                                        nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                                    {
                                        pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
                                    }
                                    else
                                    {
                                        // modulate alpha with
                                        // nAlphaModulation. This is a
                                        // little bit verbose, formula
                                        // is 255 - 255*nAlphaModulation
                                        // (invert 'alpha' pixel value, 
                                        // to get the standard alpha 
                                        // channel behaviour)
                                        pAlphaWriteAccess->SetPixel( y, x, 
                                                                     BitmapColor( 
                                                                         255U - 
                                                                         static_cast<sal_uInt8>(
                                                                             nAlphaModulation*255.0
                                                                             + .5 ) ) );

                                        BitmapColor aColor( pReadAccess->GetPixel( nSrcY,
                                                                                   nSrcX ) );

                                        aColor.SetRed( 
                                            static_cast<sal_uInt8>(
                                                nRedModulation *
                                                aColor.GetRed() + .5 ));
                                        aColor.SetGreen( 
                                            static_cast<sal_uInt8>(
                                                nGreenModulation *
                                                aColor.GetGreen() + .5 ));
                                        aColor.SetBlue( 
                                            static_cast<sal_uInt8>(
                                                nBlueModulation *
                                                aColor.GetBlue() + .5 ));

                                        pWriteAccess->SetPixel( y, x, 
                                                                aColor );
                                    }
                                }
                            }
                        }
                        else
                        {
                            // differentiate mask and alpha channel (on-off
                            // vs. multi-level transparency)
                            if( rBitmap.IsTransparent() )
                            {
                                // Handling alpha and mask just the same...
                                for( int x=0; x<aDestBmpSize.Width(); ++x )
                                {
                                    ::basegfx::B2DPoint aPoint(x,y);
                                    aPoint *= aTransform;

                                    const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
                                    const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
                                    if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                                        nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                                    {
                                        pAlphaWriteAccess->SetPixelIndex( y, x, 255 );
                                    }
                                    else
                                    {
                                        const sal_uInt8 cAlphaIdx = pAlphaReadAccess->GetPixelIndex( nSrcY, nSrcX );
                                        pAlphaWriteAccess->SetPixelIndex( y, x, aAlphaMap[ cAlphaIdx ] );
                                        pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY, nSrcX ) );
                                    }
                                }
                            }
                            else
                            {
                                for( int x=0; x<aDestBmpSize.Width(); ++x )
                                {
                                    ::basegfx::B2DPoint aPoint(x,y);
                                    aPoint *= aTransform;

                                    const int nSrcX( ::basegfx::fround( aPoint.getX() ) );
                                    const int nSrcY( ::basegfx::fround( aPoint.getY() ) );
                                    if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
                                        nSrcY < 0 || nSrcY >= aBmpSize.Height() )
                                    {
                                        pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
                                    }
                                    else
                                    {
                                        pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) );
                                        pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
                                                                                             nSrcX ) );
                                    }
                                }
                            }
                        }
                    }

                    bCopyBack = true;
                }
                else
                {
                    // TODO(E2): Error handling!
                    ENSURE_OR_THROW( false, 
                                      "transformBitmap(): could not access bitmap" );
                }
            }

            if( bCopyBack )
                return BitmapEx( aDstBitmap, AlphaMask( aDstAlpha ) );
            else
                return BitmapEx();
        }
    }
}
