/**************************************************************
 * 
 * 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 <com/sun/star/rendering/XSimpleCanvas.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/PanoseLetterForm.hpp>
#include <com/sun/star/rendering/PanoseWeight.hpp>
#include <com/sun/star/lang/XServiceName.hpp>

#include <o3tl/lazy_update.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/compbase2.hxx>
#include <cppuhelper/basemutex.hxx>

#include <comphelper/servicedecl.hxx>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

#include "canvas/canvastools.hxx"

#include <boost/bind.hpp>

#define SERVICE_NAME "com.sun.star.rendering.SimpleCanvas"

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

namespace
{
    inline uno::Sequence< double > color2Sequence( sal_Int32 const& nColor  	)
    {
        // TODO(F3): Color management
        uno::Sequence< double > aRes( 4 );
        
        aRes[0] = static_cast<sal_uInt8>( (nColor&0xFF000000U) >> 24U ) / 255.0; 
        aRes[1] = static_cast<sal_uInt8>( (nColor&0x00FF0000U) >> 16U ) / 255.0; 
        aRes[2] = static_cast<sal_uInt8>( (nColor&0x0000FF00U) >>  8U ) / 255.0; 
        aRes[3] = static_cast<sal_uInt8>( (nColor&0x000000FFU) )        / 255.0; 
        
        return aRes;
    }

    inline uno::Reference< rendering::XPolyPolygon2D > rect2Poly( uno::Reference<rendering::XGraphicDevice> const& xDevice,
                                                                  geometry::RealRectangle2D const&                 rRect )
    {
        uno::Sequence< geometry::RealPoint2D > rectSequence( 4 );
        geometry::RealPoint2D* pOutput = rectSequence.getArray();
        pOutput[0] = geometry::RealPoint2D( rRect.X1, rRect.Y1 );
        pOutput[1] = geometry::RealPoint2D( rRect.X2, rRect.Y1 );
        pOutput[2] = geometry::RealPoint2D( rRect.X2, rRect.Y2 );
        pOutput[3] = geometry::RealPoint2D( rRect.X1, rRect.Y2 );

        uno::Sequence< uno::Sequence< geometry::RealPoint2D > > sequenceSequence( 1 );
        sequenceSequence[0] = rectSequence;

        uno::Reference< rendering::XPolyPolygon2D > xRes(
            xDevice->createCompatibleLinePolyPolygon( sequenceSequence ),
            uno::UNO_QUERY );
        if( xRes.is() ) 
            xRes->setClosed( 0, sal_True );
        return xRes;
    }

    struct SimpleRenderState
    {
        o3tl::LazyUpdate<sal_Int32,
                         uno::Sequence<double>,
                         o3tl::LAZYUPDATE_FUNCTION_TAG >              m_aPenColor;
        o3tl::LazyUpdate<sal_Int32,
                         uno::Sequence<double>,
                         o3tl::LAZYUPDATE_FUNCTION_TAG >              m_aFillColor;
        o3tl::LazyUpdate<geometry::RealRectangle2D,
                         uno::Reference< rendering::XPolyPolygon2D >,
                         o3tl::LAZYUPDATE_FUNCTOR_TAG >               m_aRectClip;
        geometry::AffineMatrix2D                                      m_aTransformation;

        explicit SimpleRenderState( uno::Reference<rendering::XGraphicDevice> const& xDevice ) :
            m_aPenColor( &color2Sequence),
            m_aFillColor( &color2Sequence ),
            m_aRectClip( boost::bind( &rect2Poly,
                                      xDevice,
                                      _1 )),
            m_aTransformation()
        {
            tools::setIdentityAffineMatrix2D( m_aTransformation );
        }
    };


    typedef ::cppu::WeakComponentImplHelper2< ::com::sun::star::rendering::XSimpleCanvas,
                                              ::com::sun::star::lang::XServiceName >	SimpleCanvasBase;

    class SimpleCanvasImpl : private cppu::BaseMutex,
                             public SimpleCanvasBase
    {
    private:
        bool isStrokingEnabled() const
        {
            return maRenderState.m_aPenColor.getInValue() && sal_Int32(0xFF) != 0;
        }

        rendering::RenderState createStrokingRenderState() const
        { 
            return rendering::RenderState(maRenderState.m_aTransformation,
                                          *maRenderState.m_aRectClip,
                                          *maRenderState.m_aPenColor,
                                          rendering::CompositeOperation::OVER);
        }

        bool isFillingEnabled() const
        {
            return maRenderState.m_aFillColor.getInValue() && sal_Int32(0xFF) != 0;
        }

        rendering::RenderState createFillingRenderState() const
        { 
            return rendering::RenderState(maRenderState.m_aTransformation,
                                          *maRenderState.m_aRectClip,
                                          *maRenderState.m_aFillColor,
                                          rendering::CompositeOperation::OVER);
        }

        static uno::Reference<rendering::XCanvas> grabCanvas( uno::Sequence<uno::Any> const& rArgs )
        {
            uno::Reference<rendering::XCanvas> xRet;

            // can't do much without an XCanvas, can't we?
            if( rArgs.getLength() < 1 )
                throw lang::IllegalArgumentException();

            xRet.set( rArgs[0], uno::UNO_QUERY );

            // can't do much without an XCanvas, can't we?
            if( !xRet.is() )
                throw lang::IllegalArgumentException();

            return xRet;
        }

    public:
        SimpleCanvasImpl( const uno::Sequence< uno::Any >&                aArguments,
                          const uno::Reference< uno::XComponentContext >&  ) :
            SimpleCanvasBase( m_aMutex ),
            mxCanvas( grabCanvas(aArguments) ),
            maFont(boost::bind( &rendering::XCanvas::createFont,
                                boost::cref(mxCanvas),
                                _1, 
                                uno::Sequence< beans::PropertyValue >(),
                                geometry::Matrix2D() )),
            maViewState(),
            maRenderState( mxCanvas->getDevice() )
        {
            tools::initViewState(maViewState);
        }

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

    private:
        // Ifc XServiceName
        virtual ::rtl::OUString SAL_CALL getServiceName(  ) throw (uno::RuntimeException)
        {
            return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
        }

        // Ifc XSimpleCanvas
        virtual void SAL_CALL selectFont( const ::rtl::OUString& sFontName, 
                                          double                 size, 
                                          ::sal_Bool             bold, 
                                          ::sal_Bool             italic ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            
            maFont->FontDescription.FamilyName = sFontName;
            maFont->CellSize = size;
            maFont->FontDescription.FontDescription.Weight = 
                bold ? rendering::PanoseWeight::BOLD : rendering::PanoseWeight::MEDIUM;
            maFont->FontDescription.FontDescription.Letterform = 
                italic ? rendering::PanoseLetterForm::OBLIQUE_CONTACT : rendering::PanoseLetterForm::ANYTHING;
        }

        virtual void SAL_CALL setPenColor( ::sal_Int32 nsRgbaColor ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            *(maRenderState.m_aPenColor) = nsRgbaColor;
        }

        virtual void SAL_CALL setFillColor( ::sal_Int32 nsRgbaColor ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            *(maRenderState.m_aFillColor) = nsRgbaColor;
        }

        virtual void SAL_CALL setRectClip( const geometry::RealRectangle2D& aRect ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            *(maRenderState.m_aRectClip) = aRect;
        }

        virtual void SAL_CALL setTransformation( const geometry::AffineMatrix2D& aTransform ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            maRenderState.m_aTransformation = aTransform;
        }

        virtual void SAL_CALL drawPixel( const geometry::RealPoint2D& aPoint ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            mxCanvas->drawPoint(aPoint,
                                maViewState,
                                createFillingRenderState());
        }

        virtual void SAL_CALL drawLine( const geometry::RealPoint2D& aStartPoint, 
                                        const geometry::RealPoint2D& aEndPoint ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            mxCanvas->drawLine(aStartPoint,
                               aEndPoint,
                               maViewState,
                               createStrokingRenderState());
        }

        virtual void SAL_CALL drawRect( const geometry::RealRectangle2D& aRect ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            uno::Reference< rendering::XPolyPolygon2D > xPoly(
                rect2Poly( mxCanvas->getDevice(),
                           aRect));

            if( isFillingEnabled() )
                mxCanvas->drawPolyPolygon(xPoly,
                                          maViewState,
                                          createFillingRenderState());
            if( isStrokingEnabled() )
                mxCanvas->drawPolyPolygon(xPoly,
                                          maViewState,
                                          createStrokingRenderState());
        }

        virtual void SAL_CALL drawPolyPolygon( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );

            if( isFillingEnabled() )
                mxCanvas->drawPolyPolygon(xPolyPolygon,
                                          maViewState,
                                          createFillingRenderState());
            if( isStrokingEnabled() )
                mxCanvas->drawPolyPolygon(xPolyPolygon,
                                          maViewState,
                                          createStrokingRenderState());
        }

        virtual void SAL_CALL drawText( const rendering::StringContext& aText, 
                                        const geometry::RealPoint2D&    aOutPos, 
                                        ::sal_Int8                      nTextDirection ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aOutPos.X,aOutPos.Y));
            rendering::RenderState aRenderState( createStrokingRenderState() );
            tools::appendToRenderState(aRenderState, offsetTransform);

            mxCanvas->drawText(aText,
                               maFont.getOutValue(),
                               maViewState,
                               aRenderState,
                               nTextDirection);
        }

        virtual void SAL_CALL drawBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, 
                                          const geometry::RealPoint2D&                aLeftTop ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            const basegfx::B2DHomMatrix offsetTransform(basegfx::tools::createTranslateB2DHomMatrix(aLeftTop.X,aLeftTop.Y));
            rendering::RenderState aRenderState( createStrokingRenderState() );
            tools::appendToRenderState(aRenderState, offsetTransform);

            mxCanvas->drawBitmap(xBitmap,maViewState,aRenderState);
        }

        virtual uno::Reference< rendering::XGraphicDevice > SAL_CALL getDevice(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return mxCanvas->getDevice();
        }

        virtual uno::Reference< rendering::XCanvas > SAL_CALL getCanvas(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return mxCanvas;
        }

        virtual rendering::FontMetrics SAL_CALL getFontMetrics(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maFont.getOutValue()->getFontMetrics();
        }

        virtual uno::Reference< rendering::XCanvasFont > SAL_CALL getCurrentFont(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maFont.getOutValue();
        }

        virtual ::sal_Int32 SAL_CALL getCurrentPenColor(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maRenderState.m_aPenColor.getInValue();
        }

        virtual ::sal_Int32 SAL_CALL getCurrentFillColor(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maRenderState.m_aFillColor.getInValue();
        }

        virtual geometry::RealRectangle2D SAL_CALL getCurrentClipRect(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maRenderState.m_aRectClip.getInValue();
        }

        virtual geometry::AffineMatrix2D SAL_CALL getCurrentTransformation(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maRenderState.m_aTransformation;
        }

        virtual rendering::ViewState SAL_CALL getCurrentViewState(  ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            return maViewState;
        }

        virtual rendering::RenderState SAL_CALL getCurrentRenderState( sal_Bool bUseFillColor ) throw (uno::RuntimeException)
        {
            ::osl::MutexGuard aGuard( m_aMutex );
            if( bUseFillColor )
                return createFillingRenderState();
            else
                return createStrokingRenderState();
        }

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

        typedef o3tl::LazyUpdate<
            rendering::FontRequest,
            uno::Reference< rendering::XCanvasFont >,
            o3tl::LAZYUPDATE_FUNCTOR_TAG > SimpleFont;

        uno::Reference<rendering::XCanvas> mxCanvas;
        SimpleFont                         maFont;
        rendering::ViewState               maViewState;   
        SimpleRenderState                  maRenderState;
    };

    namespace sdecl = comphelper::service_decl;
#if defined (__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ <= 3)
    sdecl::class_<SimpleCanvasImpl, sdecl::with_args<true> > serviceImpl;
    const sdecl::ServiceDecl simpleCanvasDecl(
        serviceImpl,
#else
    const sdecl::ServiceDecl simpleCanvasDecl(
        sdecl::class_<SimpleCanvasImpl, sdecl::with_args<true> >(),
#endif
        "com.sun.star.comp.rendering.SimpleCanvas",
        SERVICE_NAME );
}

// The C shared lib entry points
COMPHELPER_SERVICEDECL_EXPORTS1(simpleCanvasDecl)
