/**************************************************************
 *
 * 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 identitiy (->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 );
        }
    }
}
