/**************************************************************
 *
 * 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)
