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

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

#include <math.h>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/animations/ValuePair.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/awt/FontSlant.hpp>

#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/vector/b2ivector.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/tools/lerp.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

#include <cppcanvas/basegfxfactory.hxx>

#include "unoview.hxx"
#include "smilfunctionparser.hxx"
#include "tools.hxx"

#include <limits>


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

namespace slideshow
{
    namespace internal
    {
        namespace
        {
            class NamedValueStringComparator
            {
            public:
                NamedValueStringComparator( const ::rtl::OUString& rSearchString ) :
                    mrSearchString( rSearchString )
                {
                }

                bool operator()( const beans::NamedValue& rValue )
                {
                    return rValue.Name == mrSearchString;
                }

            private:
                const ::rtl::OUString&		mrSearchString;
            };

            class NamedValueComparator
            {
            public:
                NamedValueComparator( const beans::NamedValue& rKey ) :
                    mrKey( rKey )
                {
                }

                bool operator()( const beans::NamedValue& rValue )
                {
                    return rValue.Name == mrKey.Name && rValue.Value == mrKey.Value;
                }

            private:
                const beans::NamedValue&	mrKey;
            };

            ::basegfx::B2DHomMatrix getAttributedShapeTransformation( const ::basegfx::B2DRectangle&		rShapeBounds,
                                                                      const ShapeAttributeLayerSharedPtr&	pAttr )
            {
                ::basegfx::B2DHomMatrix 	aTransform;
                const ::basegfx::B2DSize&	rSize( rShapeBounds.getRange() );

                const double nShearX( pAttr->isShearXAngleValid() ?
                                      pAttr->getShearXAngle() :
                                      0.0 );
                const double nShearY( pAttr->isShearYAngleValid() ?
                                      pAttr->getShearYAngle() :
                                      0.0 );
                const double nRotation( pAttr->isRotationAngleValid() ?
                                        pAttr->getRotationAngle()*M_PI/180.0 :
                                        0.0 );

                // scale, shear and rotation pivot point is the shape
                // center - adapt origin accordingly
                aTransform.translate( -0.5, -0.5 );

                // ensure valid size (zero size will inevitably lead
                // to a singular transformation matrix)
                aTransform.scale( ::basegfx::pruneScaleValue(
                                      rSize.getX() ),
                                  ::basegfx::pruneScaleValue(
                                      rSize.getY() ) );

                const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
                const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
                const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );

                if( bNeedRotation || bNeedShearX || bNeedShearY )
                {
                    if( bNeedShearX )
                        aTransform.shearX( nShearX );

                    if( bNeedShearY )
                        aTransform.shearY( nShearY );

                    if( bNeedRotation )
                        aTransform.rotate( nRotation );
                }

                // move left, top corner back to position of the
                // shape. Since we've already translated the
                // center of the shape to the origin (the
                // translate( -0.5, -0.5 ) above), translate to
                // center of final shape position here.
                aTransform.translate( rShapeBounds.getCenterX(),
                                      rShapeBounds.getCenterY() );

                return aTransform;
            }
        }

        // Value extraction from Any
        // =========================

        /// extract unary double value from Any
        bool extractValue( double&						o_rValue,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		rShape,
                           const ::basegfx::B2DVector&	rSlideBounds )
        {
            // try to extract numeric value (double, or smaller POD, like float or int)
            if( (rSourceAny >>= o_rValue) )
            {
                // succeeded
                return true;
            }

            // try to extract string
            ::rtl::OUString aString;
            if( !(rSourceAny >>= aString) )
                return false; // nothing left to try

            // parse the string into an ExpressionNode
            try
            {
                // Parse string into ExpressionNode, eval node at time 0.0
                o_rValue = (*SmilFunctionParser::parseSmilValue(
                                aString,
                                calcRelativeShapeBounds(rSlideBounds,
                                                        rShape->getBounds()) ))(0.0);
            }
            catch( ParseError& )
            {
                return false;
            }

            return true;
        }

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int32&						o_rValue,
                           const uno::Any& 					rSourceAny,
                           const ShapeSharedPtr&			/*rShape*/,
                           const ::basegfx::B2DVector&		/*rSlideBounds*/ )
        {
            // try to extract numeric value (int, or smaller POD, like byte)
            if( (rSourceAny >>= o_rValue) )
            {
                // succeeded
                return true;
            }

            // okay, no plain int. Maybe one of the domain-specific enums?
            drawing::FillStyle eFillStyle;
            if( (rSourceAny >>= eFillStyle) )
            {
                o_rValue = sal::static_int_cast<sal_Int16>(eFillStyle);

                // succeeded
                return true;
            }

            drawing::LineStyle eLineStyle;
            if( (rSourceAny >>= eLineStyle) )
            {
                o_rValue = sal::static_int_cast<sal_Int16>(eLineStyle);

                // succeeded
                return true;
            }

            awt::FontSlant eFontSlant;
            if( (rSourceAny >>= eFontSlant) )
            {
                o_rValue = sal::static_int_cast<sal_Int16>(eFontSlant);

                // succeeded
                return true;
            }

            // nothing left to try. Failure
            return false;
        }

        /// extract enum/constant group value from Any
        bool extractValue( sal_Int16&						o_rValue,
                           const uno::Any& 					rSourceAny,
                           const ShapeSharedPtr&			rShape,
                           const ::basegfx::B2DVector&		rSlideBounds )
        {
            sal_Int32 aValue;
            if( !extractValue(aValue,rSourceAny,rShape,rSlideBounds) )
                return false;

            if( std::numeric_limits<sal_Int16>::max() < aValue ||
                std::numeric_limits<sal_Int16>::min() > aValue )
            {
                return false;
            }

            o_rValue = static_cast<sal_Int16>(aValue);

            return true;
        }

        /// extract color value from Any
        bool extractValue( RGBColor&					o_rValue,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		/*rShape*/,
                           const ::basegfx::B2DVector&	/*rSlideBounds*/ )
        {
            // try to extract numeric value (double, or smaller POD, like float or int)
            {
                double nTmp = 0;
                if( (rSourceAny >>= nTmp) )
                {
                    sal_uInt32 aIntColor( static_cast< sal_uInt32 >(nTmp) );

                    // TODO(F2): Handle color values correctly, here
                    o_rValue = unoColor2RGBColor( aIntColor );

                    // succeeded
                    return true;
                }
            }

            // try double sequence
            {
                uno::Sequence< double > aTmp;
                if( (rSourceAny >>= aTmp) )
                {
                    ENSURE_OR_THROW( aTmp.getLength() == 3,
                                      "extractValue(): inappropriate length for RGB color value" );

                    o_rValue = RGBColor( aTmp[0], aTmp[1], aTmp[2] );

                    // succeeded
                    return true;
                }
            }

            // try sal_Int32 sequence
            {
                uno::Sequence< sal_Int32 > aTmp;
                if( (rSourceAny >>= aTmp) )
                {
                    ENSURE_OR_THROW( aTmp.getLength() == 3,
                                      "extractValue(): inappropriate length for RGB color value" );

                    // truncate to byte
                    o_rValue = RGBColor( ::cppcanvas::makeColor(
                                             static_cast<sal_uInt8>(aTmp[0]),
                                             static_cast<sal_uInt8>(aTmp[1]),
                                             static_cast<sal_uInt8>(aTmp[2]),
                                             255 ) );

                    // succeeded
                    return true;
                }
            }

            // try sal_Int8 sequence
            {
                uno::Sequence< sal_Int8 > aTmp;
                if( (rSourceAny >>= aTmp) )
                {
                    ENSURE_OR_THROW( aTmp.getLength() == 3,
                                      "extractValue(): inappropriate length for RGB color value" );

                    o_rValue = RGBColor( ::cppcanvas::makeColor( aTmp[0], aTmp[1], aTmp[2], 255 ) );

                    // succeeded
                    return true;
                }
            }

            // try to extract string
            ::rtl::OUString aString;
            if( !(rSourceAny >>= aString) )
                return false; // nothing left to try

            // TODO(F2): Provide symbolic color values here
            o_rValue = RGBColor( 0.5, 0.5, 0.5 );

            return true;
        }

        /// extract color value from Any
        bool extractValue( HSLColor&					o_rValue,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		/*rShape*/,
                           const ::basegfx::B2DVector&	/*rSlideBounds*/ )
        {
            // try double sequence
            {
                uno::Sequence< double > aTmp;
                if( (rSourceAny >>= aTmp) )
                {
                    ENSURE_OR_THROW( aTmp.getLength() == 3,
                                      "extractValue(): inappropriate length for HSL color value" );

                    o_rValue = HSLColor( aTmp[0], aTmp[1], aTmp[2] );

                    // succeeded
                    return true;
                }
            }

            // try sal_Int8 sequence
            {
                uno::Sequence< sal_Int8 > aTmp;
                if( (rSourceAny >>= aTmp) )
                {
                    ENSURE_OR_THROW( aTmp.getLength() == 3,
                                      "extractValue(): inappropriate length for HSL color value" );

                    o_rValue = HSLColor( aTmp[0]*360.0/255.0, aTmp[1]/255.0, aTmp[2]/255.0 );

                    // succeeded
                    return true;
                }
            }

            return false; // nothing left to try
        }

        /// extract plain string from Any
        bool extractValue( ::rtl::OUString&				o_rValue,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		/*rShape*/,
                           const ::basegfx::B2DVector&	/*rSlideBounds*/ )
        {
            // try to extract string
            if( !(rSourceAny >>= o_rValue) )
                return false; // nothing left to try

            return true;
        }

        /// extract bool value from Any
        bool extractValue( bool&						o_rValue,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		/*rShape*/,
                           const ::basegfx::B2DVector&	/*rSlideBounds*/ )
        {
            sal_Bool nTmp = sal_Bool();
            // try to extract bool value
            if( (rSourceAny >>= nTmp) )
            {
                o_rValue = nTmp;

                // succeeded
                return true;
            }

            // try to extract string
            ::rtl::OUString aString;
            if( !(rSourceAny >>= aString) )
                return false; // nothing left to try

            // we also take the strings "true" and "false",
            // as well as "on" and "off" here
            if( aString.equalsIgnoreAsciiCaseAscii("true") ||
                aString.equalsIgnoreAsciiCaseAscii("on") )
            {
                o_rValue = true;
                return true;
            }
            if( aString.equalsIgnoreAsciiCaseAscii("false") ||
                aString.equalsIgnoreAsciiCaseAscii("off") )
            {
                o_rValue = false;
                return true;
            }

            // ultimately failed.
            return false;
        }

        /// extract double 2-tuple from Any
        bool extractValue( ::basegfx::B2DTuple&			o_rPair,
                           const uno::Any& 				rSourceAny,
                           const ShapeSharedPtr&		rShape,
                           const ::basegfx::B2DVector&	rSlideBounds )
        {
            animations::ValuePair aPair;

            if( !(rSourceAny >>= aPair) )
                return false;

            double nFirst;
            if( !extractValue( nFirst, aPair.First, rShape, rSlideBounds ) )
                return false;

            double nSecond;
            if( !extractValue( nSecond, aPair.Second, rShape, rSlideBounds ) )
                return false;

            o_rPair.setX( nFirst );
            o_rPair.setY( nSecond );

            return true;
        }

        bool findNamedValue( uno::Sequence< beans::NamedValue > const& rSequence,
                             const beans::NamedValue&				rSearchKey )
        {
            const beans::NamedValue* 	pArray = rSequence.getConstArray();
            const size_t 				nLen( rSequence.getLength() );

            if( nLen == 0 )
                return false;

            const beans::NamedValue* pFound = ::std::find_if( pArray,
                                                              pArray + nLen,
                                                              NamedValueComparator( rSearchKey ) );

            if( pFound == pArray + nLen )
                return false;

            return true;
        }

        bool findNamedValue( beans::NamedValue* 						o_pRet,
                             const uno::Sequence< beans::NamedValue >& 	rSequence,
                             const ::rtl::OUString&						rSearchString )
        {
            const beans::NamedValue* 	pArray = rSequence.getConstArray();
            const size_t 				nLen( rSequence.getLength() );

            if( nLen == 0 )
                return false;

            const beans::NamedValue* pFound = ::std::find_if( pArray,
                                                              pArray + nLen,
                                                              NamedValueStringComparator( rSearchString ) );
            if( pFound == pArray + nLen )
                return false;

            if( o_pRet )
                *o_pRet = *pFound;

            return true;
        }

        basegfx::B2DRange calcRelativeShapeBounds( const basegfx::B2DVector& rPageSize,
                                                   const basegfx::B2DRange&  rShapeBounds )
        {
            return basegfx::B2DRange( rShapeBounds.getMinX() / rPageSize.getX(),
                                      rShapeBounds.getMinY() / rPageSize.getY(),
                                      rShapeBounds.getMaxX() / rPageSize.getX(),
                                      rShapeBounds.getMaxY() / rPageSize.getY() );
		}

        // TODO(F2): Currently, the positional attributes DO NOT mirror the XShape properties.
        // First and foremost, this is because we must operate with the shape boundrect,
        // not position and size (the conversion between logic rect, snap rect and boundrect
        // are non-trivial for draw shapes, and I won't duplicate them here). Thus, shapes
        // rotated on the page will still have 0.0 rotation angle, as the metafile
        // representation fetched over the API is our default zero case.

        ::basegfx::B2DHomMatrix getShapeTransformation( const ::basegfx::B2DRectangle&		rShapeBounds,
                                                        const ShapeAttributeLayerSharedPtr&	pAttr )
        {
            if( !pAttr )
            {
                const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
                    rShapeBounds.getWidth(), rShapeBounds.getHeight(),
                    rShapeBounds.getMinX(), rShapeBounds.getMinY()));

                return aTransform;
            }
            else
            {
                return getAttributedShapeTransformation( rShapeBounds,
                                                         pAttr );
            }
        }

        ::basegfx::B2DHomMatrix getSpriteTransformation( const ::basegfx::B2DVector&			rPixelSize,
                                                         const ::basegfx::B2DVector&			rOrigSize,
                                                         const ShapeAttributeLayerSharedPtr&	pAttr )
        {
            ::basegfx::B2DHomMatrix aTransform;

            if( pAttr )
            {
                const double nShearX( pAttr->isShearXAngleValid() ?
                                      pAttr->getShearXAngle() :
                                      0.0 );
                const double nShearY( pAttr->isShearYAngleValid() ?
                                      pAttr->getShearYAngle() :
                                      0.0 );
                const double nRotation( pAttr->isRotationAngleValid() ?
                                        pAttr->getRotationAngle()*M_PI/180.0 :
                                        0.0 );

                // scale, shear and rotation pivot point is the
                // sprite's pixel center - adapt origin accordingly
                aTransform.translate( -0.5*rPixelSize.getX(),
                                      -0.5*rPixelSize.getY() );

                const ::basegfx::B2DSize aSize(
                    pAttr->isWidthValid() ? pAttr->getWidth() : rOrigSize.getX(),
                    pAttr->isHeightValid() ? pAttr->getHeight() : rOrigSize.getY() );

                // ensure valid size (zero size will inevitably lead
                // to a singular transformation matrix).
                aTransform.scale( ::basegfx::pruneScaleValue(
                                      aSize.getX() /
                                      ::basegfx::pruneScaleValue(
                                          rOrigSize.getX() ) ),
                                  ::basegfx::pruneScaleValue(
                                      aSize.getY() /
                                      ::basegfx::pruneScaleValue(
                                          rOrigSize.getY() ) ) );

                const bool bNeedShearX( !::basegfx::fTools::equalZero(nShearX) );
                const bool bNeedShearY( !::basegfx::fTools::equalZero(nShearY) );
                const bool bNeedRotation( !::basegfx::fTools::equalZero(nRotation) );

                if( bNeedRotation || bNeedShearX || bNeedShearY )
                {
                    if( bNeedShearX )
                        aTransform.shearX( nShearX );

                    if( bNeedShearY )
                        aTransform.shearY( nShearY );

                    if( bNeedRotation )
                        aTransform.rotate( nRotation );
                }

                // move left, top corner back to original position of
                // the sprite (we've translated the center of the
                // sprite to the origin above).
                aTransform.translate( 0.5*rPixelSize.getX(),
                                      0.5*rPixelSize.getY() );
            }

            // return identity transform for un-attributed
            // shapes. This renders the sprite as-is, in it's
            // document-supplied size.
            return aTransform;
        }

        ::basegfx::B2DRectangle getShapeUpdateArea( const ::basegfx::B2DRectangle&		rUnitBounds,
                                                    const ::basegfx::B2DHomMatrix&		rShapeTransform,
                                                    const ShapeAttributeLayerSharedPtr&	pAttr )
        {
            ::basegfx::B2DHomMatrix aTransform;

            if( pAttr &&
                pAttr->isCharScaleValid() &&
                fabs(pAttr->getCharScale()) > 1.0 )
            {
                // enlarge shape bounds. Have to consider the worst
                // case here (the text fully fills the shape)

                const double nCharScale( pAttr->getCharScale() );

                // center of scaling is the middle of the shape
                aTransform.translate( -0.5, -0.5 );
                aTransform.scale( nCharScale, nCharScale );
                aTransform.translate( 0.5, 0.5 );
            }

            aTransform *= rShapeTransform;

            ::basegfx::B2DRectangle aRes;

            // apply shape transformation to unit rect
            return ::canvas::tools::calcTransformedRectBounds(
                aRes,
                rUnitBounds,
                aTransform );
        }

        ::basegfx::B2DRange getShapeUpdateArea( const ::basegfx::B2DRange&		rUnitBounds,
                                                    const ::basegfx::B2DRange&		rShapeBounds )
        {
            return ::basegfx::B2DRectangle(
                basegfx::tools::lerp( rShapeBounds.getMinX(),
                                      rShapeBounds.getMaxX(),
                                      rUnitBounds.getMinX() ),
                basegfx::tools::lerp( rShapeBounds.getMinY(),
                                      rShapeBounds.getMaxY(),
                                      rUnitBounds.getMinY() ),
                basegfx::tools::lerp( rShapeBounds.getMinX(),
                                      rShapeBounds.getMaxX(),
                                      rUnitBounds.getMaxX() ),
                basegfx::tools::lerp( rShapeBounds.getMinY(),
                                      rShapeBounds.getMaxY(),
                                      rUnitBounds.getMaxY() ) );
        }

        ::basegfx::B2DRectangle getShapePosSize( const ::basegfx::B2DRectangle&			rOrigBounds,
                                                 const ShapeAttributeLayerSharedPtr&	pAttr )
        {
            // an already empty shape bound need no further
            // treatment. In fact, any changes applied below would
            // actually remove the special empty state, thus, don't
            // change!
            if( !pAttr ||
                rOrigBounds.isEmpty() )
            {
                return rOrigBounds;
            }
            else
            {
                // cannot use maBounds anymore, attributes might have been
                // changed by now.
                // Have to use absolute values here, as negative sizes
                // (aka mirrored shapes) _still_ have the same bounds,
                // only with mirrored content.
                ::basegfx::B2DSize aSize;
                aSize.setX( fabs( pAttr->isWidthValid() ?
                                  pAttr->getWidth() :
                                  rOrigBounds.getWidth() ) );
                aSize.setY( fabs( pAttr->isHeightValid() ?
                                  pAttr->getHeight() :
                                  rOrigBounds.getHeight() ) );

                ::basegfx::B2DPoint aPos;
                aPos.setX( pAttr->isPosXValid() ?
                           pAttr->getPosX() :
                           rOrigBounds.getCenterX() );
                aPos.setY( pAttr->isPosYValid() ?
                           pAttr->getPosY() :
                           rOrigBounds.getCenterY() );

                // the positional attribute retrieved from the
                // ShapeAttributeLayer actually denotes the _middle_
                // of the shape (do it as the PPTs do...)
                return ::basegfx::B2DRectangle( aPos - 0.5*aSize,
                                                aPos + 0.5*aSize );
            }
        }

        RGBColor unoColor2RGBColor( sal_Int32 nColor )
        {
            return RGBColor(
                ::cppcanvas::makeColor(
                    // convert from API color to IntSRGBA color
                    // (0xAARRGGBB -> 0xRRGGBBAA)
                    static_cast< sal_uInt8 >( nColor >> 16U ),
                    static_cast< sal_uInt8 >( nColor >> 8U ),
                    static_cast< sal_uInt8 >( nColor ),
                    static_cast< sal_uInt8 >( nColor >> 24U ) ) );
        }

        sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
        {
            return ::cppcanvas::makeColorARGB(
                // convert from IntSRGBA color to API color
                // (0xRRGGBBAA -> 0xAARRGGBB)
                static_cast< sal_uInt8 >(0),
                ::cppcanvas::getRed(aColor),
                ::cppcanvas::getGreen(aColor),
                ::cppcanvas::getBlue(aColor));
        }

        /*sal_Int32 RGBAColor2UnoColor( ::cppcanvas::Color::IntSRGBA aColor )
        {
            return ::cppcanvas::unMakeColor(
                                                    // convert from IntSRGBA color to API color
                                                    // (0xRRGGBBAA -> 0xAARRGGBB)
                                                    static_cast< sal_uInt8 >(0),
                                                    ::cppcanvas::getRed(aColor),
                                                    ::cppcanvas::getGreen(aColor),
                                                    ::cppcanvas::getBlue(aColor));
        }*/

        sal_Int8 unSignedToSigned(sal_Int8 nInt)
        {
            if(nInt < 0 ){
                sal_Int8 nInt2 = nInt >> 1U;
                return nInt2;
            }else{
                return nInt;
            }
        }

        void fillRect( const ::cppcanvas::CanvasSharedPtr& rCanvas,
                       const ::basegfx::B2DRectangle&	   rRect,
                       ::cppcanvas::Color::IntSRGBA        aFillColor )
        {
            const ::basegfx::B2DPolygon aPoly(
                ::basegfx::tools::createPolygonFromRect( rRect ));

            ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
                ::cppcanvas::BaseGfxFactory::getInstance().createPolyPolygon( rCanvas,
                                                                              aPoly ) );

            if( pPolyPoly )
            {
                pPolyPoly->setRGBAFillColor( aFillColor );
                pPolyPoly->draw();
            }
        }

        void initSlideBackground( const ::cppcanvas::CanvasSharedPtr& rCanvas,
                                  const ::basegfx::B2ISize&			  rSize )
        {
            ::cppcanvas::CanvasSharedPtr pCanvas( rCanvas->clone() );

            // set transformation to identity (->device pixel)
            pCanvas->setTransformation( ::basegfx::B2DHomMatrix() );

            // #i42440# Fill the _full_ background in
            // black. Since we had to extend the bitmap by one
            // pixel, and the bitmap is initialized white,
            // depending on the slide content a one pixel wide
            // line will show to the bottom and the right.
            fillRect( pCanvas,
                      ::basegfx::B2DRectangle( 0.0, 0.0,
                                               rSize.getX(),
                                               rSize.getY() ),
                      0x000000FFU );

            // fill the bounds rectangle in white. Subtract one pixel
            // from both width and height, because the slide size is
            // chosen one pixel larger than given by the drawing
            // layer. This is because shapes with line style, that
            // have the size of the slide would otherwise be cut
            // off. OTOH, every other slide background (solid fill,
            // gradient, bitmap) render one pixel less, thus revealing
            // ugly white pixel to the right and the bottom.
            fillRect( pCanvas,
                      ::basegfx::B2DRectangle( 0.0, 0.0,
                                               rSize.getX()-1,
                                               rSize.getY()-1 ),
                      0xFFFFFFFFU );
        }

        ::basegfx::B2DRectangle getAPIShapeBounds( const uno::Reference< drawing::XShape >& xShape )
        {
            uno::Reference< beans::XPropertySet > xPropSet( xShape,
                                                            uno::UNO_QUERY_THROW );
            // read bound rect
            awt::Rectangle aTmpRect;
            if( !(xPropSet->getPropertyValue(
                      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BoundRect") ) ) >>= aTmpRect) )
            {
                ENSURE_OR_THROW( false,
                                  "getAPIShapeBounds(): Could not get \"BoundRect\" property from shape" );
            }

            return ::basegfx::B2DRectangle( aTmpRect.X,
                                            aTmpRect.Y,
                                            aTmpRect.X+aTmpRect.Width,
                                            aTmpRect.Y+aTmpRect.Height );
        }

        double getAPIShapePrio( const uno::Reference< drawing::XShape >& xShape )
        {
            uno::Reference< beans::XPropertySet > xPropSet( xShape,
                                                            uno::UNO_QUERY_THROW );
            // read prio
            sal_Int32 nPrio(0);
            if( !(xPropSet->getPropertyValue(
                      ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZOrder") ) ) >>= nPrio) )
            {
                ENSURE_OR_THROW( false,
                                  "getAPIShapePrio(): Could not get \"ZOrder\" property from shape" );
            }

            // TODO(F2): Check and adapt the range of possible values here.
            // Maybe we can also take the total number of shapes here
            return nPrio / 65535.0;
        }

        basegfx::B2IVector getSlideSizePixel( const basegfx::B2DVector& rSlideSize,
                                              const UnoViewSharedPtr&   pView )
        {
            ENSURE_OR_THROW(pView, "getSlideSizePixel(): invalid view");

            // determine transformed page bounds
            const basegfx::B2DRange aRect( 0,0,
                                           rSlideSize.getX(),
                                           rSlideSize.getY() );
            basegfx::B2DRange aTmpRect;
            canvas::tools::calcTransformedRectBounds( aTmpRect,
                                                      aRect,
                                                      pView->getTransformation() );

            // #i42440# Returned slide size is one pixel too small, as
            // rendering happens one pixel to the right and below the
            // actual bound rect.
            return basegfx::B2IVector(
                basegfx::fround( aTmpRect.getRange().getX() ) + 1,
                basegfx::fround( aTmpRect.getRange().getY() ) + 1 );
        }
    }
}
