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

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

#include <rtl/logfile.hxx>

#include <com/sun/star/rendering/PathCapType.hpp>
#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/XCanvas.hpp>
#include <com/sun/star/rendering/XCanvasFont.hpp>

#include <basegfx/numeric/ftools.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/vector/b2dsize.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

#include <tools/gen.hxx>
#include <vcl/canvastools.hxx>
#include <vcl/virdev.hxx>

#include <basegfx/tools/canvastools.hxx>
#include <canvas/canvastools.hxx>

#include <boost/scoped_array.hpp>
#include <boost/bind.hpp>
#include <boost/utility.hpp>

#include "textaction.hxx"
#include "outdevstate.hxx"
#include "mtftools.hxx"


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

namespace cppcanvas
{
    namespace internal
    {
        namespace
        {
            void init( rendering::RenderState&					o_rRenderState,
                       const ::basegfx::B2DPoint&				rStartPoint,
                       const OutDevState& 						rState,
                       const CanvasSharedPtr& 					rCanvas		 )
            {
                tools::initRenderState(o_rRenderState,rState);

                // #i36950# Offset clip back to origin (as it's also moved
                // by rStartPoint)
                // #i53964# Also take VCL font rotation into account,
                // since this, opposed to the FontMatrix rotation
                // elsewhere, _does_ get incorporated into the render
                // state transform.
                tools::modifyClip( o_rRenderState,
                                   rState,
                                   rCanvas,
                                   rStartPoint,
                                   NULL,
                                   &rState.fontRotation );

                basegfx::B2DHomMatrix aLocalTransformation(basegfx::tools::createRotateB2DHomMatrix(rState.fontRotation));
                aLocalTransformation.translate( rStartPoint.getX(),
                                                rStartPoint.getY() );
                ::canvas::tools::appendToRenderState( o_rRenderState,
                                                      aLocalTransformation );

                o_rRenderState.DeviceColor = rState.textColor;
            }

            void init( rendering::RenderState&					o_rRenderState,
                       const ::basegfx::B2DPoint&				rStartPoint,
                       const OutDevState& 						rState,
                       const CanvasSharedPtr& 					rCanvas,
                       const ::basegfx::B2DHomMatrix&			rTextTransform	)
            {
                init( o_rRenderState, rStartPoint, rState, rCanvas );

                // TODO(F2): Also inversely-transform clip with
                // rTextTransform (which is actually rather hard, as the
                // text transform is _prepended_ to the render state)!

                // prepend extra font transform to render state
                // (prepend it, because it's interpreted in the unit
                // rect coordinate space)
                ::canvas::tools::prependToRenderState( o_rRenderState,
                                                       rTextTransform );
            }

            void init( rendering::RenderState&						o_rRenderState,
                       uno::Reference< rendering::XCanvasFont >&	o_rFont,
                       const ::basegfx::B2DPoint&					rStartPoint,
                       const OutDevState& 							rState,
                       const CanvasSharedPtr& 						rCanvas		 )
            {
                // ensure that o_rFont is valid. It is possible that
                // text actions are generated without previously
                // setting a font. Then, just take a default font
                if( !o_rFont.is() )
                {
                    // Use completely default FontRequest
                    const rendering::FontRequest aFontRequest;

                    geometry::Matrix2D aFontMatrix;
                    ::canvas::tools::setIdentityMatrix2D( aFontMatrix );

                    o_rFont = rCanvas->getUNOCanvas()->createFont(
                        aFontRequest,
                        uno::Sequence< beans::PropertyValue >(),
                        aFontMatrix );
                }

                init( o_rRenderState,
                      rStartPoint,
                      rState,
                      rCanvas );
            }

            void init( rendering::RenderState&						o_rRenderState,
                       uno::Reference< rendering::XCanvasFont >&	o_rFont,
                       const ::basegfx::B2DPoint&					rStartPoint,
                       const OutDevState& 							rState,
                       const CanvasSharedPtr& 						rCanvas,
                       const ::basegfx::B2DHomMatrix&				rTextTransform	)
            {
                init( o_rRenderState, o_rFont, rStartPoint, rState, rCanvas );

                // TODO(F2): Also inversely-transform clip with
                // rTextTransform (which is actually rather hard, as the
                // text transform is _prepended_ to the render state)!

                // prepend extra font transform to render state
                // (prepend it, because it's interpreted in the unit
                // rect coordinate space)
                ::canvas::tools::prependToRenderState( o_rRenderState,
                                                       rTextTransform );
            }

            ::basegfx::B2DPolyPolygon textLinesFromLogicalOffsets( const uno::Sequence< double >&	rOffsets,
                                                                   const tools::TextLineInfo&		rTextLineInfo )
            {
                return tools::createTextLinesPolyPolygon(
                    0.0,
                    // extract character cell furthest to the right
                    *(::std::max_element(
                          rOffsets.getConstArray(),
                          rOffsets.getConstArray() + rOffsets.getLength() )),
                    rTextLineInfo );
            }

            uno::Sequence< double > setupDXArray( const sal_Int32*	 pCharWidths,
                                                  sal_Int32			 nLen,
                                                  const OutDevState& rState )
            {
                // convert character widths from logical units
                uno::Sequence< double > aCharWidthSeq( nLen );
                double*					pOutputWidths( aCharWidthSeq.getArray() );

                // #143885# maintain (nearly) full precision of DX
                // array, by circumventing integer-based
                // OutDev-mapping
                const double nScale( rState.mapModeTransform.get(0,0) );
                for( int i = 0; i < nLen; ++i )
                {
                    // TODO(F2): use correct scale direction
                    *pOutputWidths++ = *pCharWidths++ * nScale;
                }

                return aCharWidthSeq;
            }

            uno::Sequence< double > setupDXArray( const ::String& 	 rText,
                                                  sal_Int32			 nStartPos,
                                                  sal_Int32			 nLen,
                                                  VirtualDevice&	 rVDev,
                                                  const OutDevState& rState )
            {
                // no external DX array given, create one from given
                // string
                ::boost::scoped_array< sal_Int32 > pCharWidths( new sal_Int32[nLen] );

                rVDev.GetTextArray( rText, pCharWidths.get(),
                                    static_cast<sal_uInt16>(nStartPos),
                                    static_cast<sal_uInt16>(nLen) );

                return setupDXArray( pCharWidths.get(), nLen, rState );
            }

            ::basegfx::B2DPoint adaptStartPoint( const ::basegfx::B2DPoint&		rStartPoint,
                                                 const OutDevState& 			rState,
                                                 const uno::Sequence< double >& rOffsets )
            {
                ::basegfx::B2DPoint aLocalPoint( rStartPoint );

                if( rState.textAlignment )
                {
                    // text origin is right, not left. Modify start point
                    // accordingly, because XCanvas::drawTextLayout()
                    // always aligns left!

                    const double nOffset( rOffsets[ rOffsets.getLength()-1 ] );

                    // correct start point for rotated text: rotate around
                    // former start point
                    aLocalPoint.setX( aLocalPoint.getX() + cos( rState.fontRotation )*nOffset );
                    aLocalPoint.setY( aLocalPoint.getY() + sin( rState.fontRotation )*nOffset );
                }

                return aLocalPoint;
            }

            /** Perform common setup for array text actions

            	This method creates the XTextLayout object and
            	initializes it, e.g. with the logical advancements.
             */
            void initArrayAction( rendering::RenderState&					o_rRenderState,
                                  uno::Reference< rendering::XTextLayout >& o_rTextLayout,
                                  const ::basegfx::B2DPoint&				rStartPoint,
                                  const ::rtl::OUString&					rText,
                                  sal_Int32 								nStartPos,
                                  sal_Int32 								nLen,
                                  const uno::Sequence< double >&			rOffsets,
                                  const CanvasSharedPtr&					rCanvas,
                                  const OutDevState&						rState,
                                  const ::basegfx::B2DHomMatrix*			pTextTransform )
            {
                ENSURE_OR_THROW( rOffsets.getLength(),
                                  "::cppcanvas::internal::initArrayAction(): zero-length DX array" );

                const ::basegfx::B2DPoint aLocalStartPoint(
                    adaptStartPoint( rStartPoint, rState, rOffsets ) );

                uno::Reference< rendering::XCanvasFont > xFont( rState.xFont );

                if( pTextTransform )
                    init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas, *pTextTransform );
                else
                    init( o_rRenderState, xFont, aLocalStartPoint, rState, rCanvas );

                o_rTextLayout = xFont->createTextLayout(
                    rendering::StringContext( rText, nStartPos, nLen ),
                    rState.textDirection,
                    0 );

                ENSURE_OR_THROW( o_rTextLayout.is(),
                                  "::cppcanvas::internal::initArrayAction(): Invalid font" );

                o_rTextLayout->applyLogicalAdvancements( rOffsets );
            }

            double getLineWidth( ::VirtualDevice&                rVDev,
                                 const OutDevState&              rState,
                                 const rendering::StringContext& rStringContext )
            {
                // TODO(F2): use correct scale direction
                const ::basegfx::B2DSize aSize( rVDev.GetTextWidth( rStringContext.Text,
                                                                    static_cast<sal_uInt16>(rStringContext.StartPosition),
                                                                    static_cast<sal_uInt16>(rStringContext.Length) ),
                                    0 );

                return (rState.mapModeTransform * aSize).getX();
            }

            uno::Sequence< double >
            	calcSubsetOffsets( rendering::RenderState&							io_rRenderState,
                                   double&											o_rMinPos,
                                   double&											o_rMaxPos,
                                   const uno::Reference< rendering::XTextLayout >&	rOrigTextLayout,
                                   const ::cppcanvas::internal::Action::Subset&		rSubset )
            {
                ENSURE_OR_THROW( rSubset.mnSubsetEnd > rSubset.mnSubsetBegin,
                                  "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );

                uno::Sequence< double > aOrigOffsets( rOrigTextLayout->queryLogicalAdvancements() );
                const double*			pOffsets( aOrigOffsets.getConstArray() );

                ENSURE_OR_THROW( aOrigOffsets.getLength() >= rSubset.mnSubsetEnd,
                                  "::cppcanvas::internal::calcSubsetOffsets(): invalid subset range range" );

                // TODO(F3): It currently seems that for RTL text, the
                // DX offsets are nevertheless increasing in logical
                // text order (I'd expect they are decreasing,
                // mimicking the fact that the text is output
                // right-to-left). This breaks text effects for ALL
                // RTL languages.

                // determine leftmost position in given subset range -
                // as the DX array contains the output positions
                // starting with the second character (the first is
                // assumed to have output position 0), correct begin
                // iterator.
                const double nMinPos( rSubset.mnSubsetBegin <= 0 ? 0 :
                                      *(::std::min_element( pOffsets+rSubset.mnSubsetBegin-1,
                                                            pOffsets+rSubset.mnSubsetEnd )) );

                // determine rightmost position in given subset range
                // - as the DX array contains the output positions
                // starting with the second character (the first is
                // assumed to have output position 0), correct begin
                // iterator.
                const double nMaxPos(
                    *(::std::max_element( pOffsets + (rSubset.mnSubsetBegin <= 0 ?
                                                      0 : rSubset.mnSubsetBegin-1),
                                          pOffsets + rSubset.mnSubsetEnd )) );


                // adapt render state, to move text output to given offset
                // -------------------------------------------------------

                // TODO(F1): Strictly speaking, we also have to adapt
                // the clip here, which normally should _not_ move
                // with the output offset. Neglected for now, as it
                // does not matter for drawing layer output

                if( rSubset.mnSubsetBegin > 0 )
                {
                    ::basegfx::B2DHomMatrix aTranslation;
                    if( rOrigTextLayout->getFont()->getFontRequest().FontDescription.IsVertical )
                    {
                        // vertical text -> offset in y direction
                        aTranslation.translate( 0.0, nMinPos );
                    }
                    else
                    {
                        // horizontal text -> offset in x direction
                        aTranslation.translate( nMinPos, 0.0 );
                    }

                    ::canvas::tools::appendToRenderState( io_rRenderState,
                                                          aTranslation );
                }


                // reduce DX array to given substring
                // ----------------------------------

                const sal_Int32			nNewElements( rSubset.mnSubsetEnd - rSubset.mnSubsetBegin );
                uno::Sequence< double > aAdaptedOffsets( nNewElements );
                double*					pAdaptedOffsets( aAdaptedOffsets.getArray() );

                // move to new output position (subtract nMinPos,
                // which is the new '0' position), copy only the range
                // as given by rSubset.
                ::std::transform( pOffsets + rSubset.mnSubsetBegin,
                                  pOffsets + rSubset.mnSubsetEnd,
                                  pAdaptedOffsets,
                                  ::boost::bind( ::std::minus<double>(),
                                                 _1,
                                                 nMinPos ) );

                o_rMinPos = nMinPos;
                o_rMaxPos = nMaxPos;

                return aAdaptedOffsets;
            }

            uno::Reference< rendering::XTextLayout >
	            createSubsetLayout( const rendering::StringContext&					rOrigContext,
                                    const ::cppcanvas::internal::Action::Subset&	rSubset,
                                    const uno::Reference< rendering::XTextLayout >&	rOrigTextLayout )
            {
                // create temporary new text layout with subset string
                // ---------------------------------------------------

                const sal_Int32 nNewStartPos( rOrigContext.StartPosition + ::std::min(
                                                  rSubset.mnSubsetBegin, rOrigContext.Length-1 ) );
                const sal_Int32 nNewLength( ::std::max(
                                                ::std::min(
                                                    rSubset.mnSubsetEnd - rSubset.mnSubsetBegin,
                                                    rOrigContext.Length ),
                                                sal_Int32( 0 ) ) );

                const rendering::StringContext aContext( rOrigContext.Text,
                                                         nNewStartPos,
                                                         nNewLength );

                uno::Reference< rendering::XTextLayout > xTextLayout(
                    rOrigTextLayout->getFont()->createTextLayout( aContext,
                                                                  rOrigTextLayout->getMainTextDirection(),
                                                                  0 ),
                    uno::UNO_QUERY_THROW );

                return xTextLayout;
            }

            /** Setup subset text layout

            	@param io_rTextLayout
                Must contain original (full set) text layout on input,
                will contain subsetted text layout (or empty
                reference, for empty subsets) on output.

                @param io_rRenderState
                Must contain original render state on input, will
                contain shifted render state concatenated with
                rTransformation on output.

                @param rTransformation
                Additional transformation, to be prepended to render
                state

                @param rSubset
                Subset to prepare
             */
            void createSubsetLayout( uno::Reference< rendering::XTextLayout >&	io_rTextLayout,
                                     rendering::RenderState&					io_rRenderState,
                                     double&									o_rMinPos,
                                     double&									o_rMaxPos,
                                     const ::basegfx::B2DHomMatrix&				rTransformation,
                                     const Action::Subset&						rSubset )
            {
                ::canvas::tools::prependToRenderState(io_rRenderState, rTransformation);

                if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
                {
                     // empty range, empty layout
                    io_rTextLayout.clear();

                    return;
                }

                ENSURE_OR_THROW( io_rTextLayout.is(),
                                  "createSubsetLayout(): Invalid input layout" );

                const rendering::StringContext& rOrigContext( io_rTextLayout->getText() );

                if( rSubset.mnSubsetBegin == 0 &&
                    rSubset.mnSubsetEnd == rOrigContext.Length )
                {
                    // full range, no need for subsetting
                    return;
                }

                uno::Reference< rendering::XTextLayout > xTextLayout(
                    createSubsetLayout( rOrigContext, rSubset, io_rTextLayout ) );

                if( xTextLayout.is() )
                {
                    xTextLayout->applyLogicalAdvancements(
                        calcSubsetOffsets( io_rRenderState,
                                           o_rMinPos,
                                           o_rMaxPos,
                                           io_rTextLayout,
                                           rSubset ) );
                }

                io_rTextLayout = xTextLayout;
            }


            /** Interface for renderEffectText functor below.

            	This is interface is used from the renderEffectText()
            	method below, to call the client implementation.
             */
            class TextRenderer
            {
            public:
                virtual ~TextRenderer() {}

                /// Render text with given RenderState
                virtual bool operator()( const rendering::RenderState& rRenderState ) const = 0;
            };

            /** Render effect text.

            	@param rRenderer
                Functor object, will be called to render the actual
                part of the text effect (the text itself and the means
                to render it are unknown to this method)
             */
            bool renderEffectText( const TextRenderer& 							rRenderer,
                                   const rendering::RenderState&				rRenderState,
                                   const rendering::ViewState&			 		/*rViewState*/,
                                   const uno::Reference< rendering::XCanvas >&	xCanvas,
                                   const ::Color&								rShadowColor,
                                   const ::basegfx::B2DSize&					rShadowOffset,
                                   const ::Color&								rReliefColor,
                                   const ::basegfx::B2DSize&					rReliefOffset )
            {
                ::Color aEmptyColor( COL_AUTO );
                uno::Reference<rendering::XColorSpace> xColorSpace(
                    xCanvas->getDevice()->getDeviceColorSpace() );

                // draw shadow text, if enabled
                if( rShadowColor != aEmptyColor )
                {
                    rendering::RenderState aShadowState( rRenderState );
                    ::basegfx::B2DHomMatrix aTranslate;

                    aTranslate.translate( rShadowOffset.getX(),
                                          rShadowOffset.getY() );

                    ::canvas::tools::appendToRenderState(aShadowState, aTranslate);

                    aShadowState.DeviceColor =
                        ::vcl::unotools::colorToDoubleSequence( rShadowColor,
                                                                xColorSpace );

                    rRenderer( aShadowState );
                }

                // draw relief text, if enabled
                if( rReliefColor != aEmptyColor )
                {
                    rendering::RenderState aReliefState( rRenderState );
                    ::basegfx::B2DHomMatrix aTranslate;

                    aTranslate.translate( rReliefOffset.getX(),
                                          rReliefOffset.getY() );

                    ::canvas::tools::appendToRenderState(aReliefState, aTranslate);

                    aReliefState.DeviceColor =
                        ::vcl::unotools::colorToDoubleSequence( rReliefColor,
                                                                xColorSpace );

                    rRenderer( aReliefState );
                }

                // draw normal text
                rRenderer( rRenderState );

                return true;
            }


            ::basegfx::B2DRange calcEffectTextBounds( const ::basegfx::B2DRange& 	rTextBounds,
                                                      const ::basegfx::B2DRange& 	rLineBounds,
                                                      const ::basegfx::B2DSize&		rReliefOffset,
                                                      const ::basegfx::B2DSize&		rShadowOffset,
                                                      const rendering::RenderState&	rRenderState,
                                                      const rendering::ViewState&   rViewState )
            {
                ::basegfx::B2DRange aBounds( rTextBounds );

                // add extends of text lines
                aBounds.expand( rLineBounds );

                // TODO(Q3): Provide this functionality at the B2DRange
                ::basegfx::B2DRange aTotalBounds( aBounds );
                aTotalBounds.expand(
                    ::basegfx::B2DRange( aBounds.getMinX() + rReliefOffset.getX(),
                                         aBounds.getMinY() + rReliefOffset.getY(),
                                         aBounds.getMaxX() + rReliefOffset.getX(),
                                         aBounds.getMaxY() + rReliefOffset.getY() ) );
                aTotalBounds.expand(
                    ::basegfx::B2DRange( aBounds.getMinX() + rShadowOffset.getX(),
                                         aBounds.getMinY() + rShadowOffset.getY(),
                                         aBounds.getMaxX() + rShadowOffset.getX(),
                                         aBounds.getMaxY() + rShadowOffset.getY() ) );

                return tools::calcDevicePixelBounds( aTotalBounds,
                                                     rViewState,
                                                     rRenderState );
            }

            void initEffectLinePolyPolygon( ::basegfx::B2DSize& 							o_rOverallSize,
                                            uno::Reference< rendering::XPolyPolygon2D >&	o_rTextLines,
                                            const CanvasSharedPtr&							rCanvas,
                                            const uno::Sequence< double >&					rOffsets,
                                            const tools::TextLineInfo						rLineInfo	)
            {
                const ::basegfx::B2DPolyPolygon aPoly(
                    textLinesFromLogicalOffsets(
                        rOffsets,
                        rLineInfo ) );

                o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();

                o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
                    rCanvas->getUNOCanvas()->getDevice(),
                    aPoly );
            }

            void initEffectLinePolyPolygon( ::basegfx::B2DSize& 							o_rOverallSize,
                                            uno::Reference< rendering::XPolyPolygon2D >&	o_rTextLines,
                                            const CanvasSharedPtr&							rCanvas,
                                            double                                          nLineWidth,
                                            const tools::TextLineInfo						rLineInfo	)
            {
                const ::basegfx::B2DPolyPolygon aPoly(
                    tools::createTextLinesPolyPolygon( 0.0, nLineWidth,
                                                       rLineInfo ) );

                o_rOverallSize = ::basegfx::tools::getRange( aPoly ).getRange();

                o_rTextLines = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
                    rCanvas->getUNOCanvas()->getDevice(),
                    aPoly );
            }


            // -------------------------------------------------------------------------

            class TextAction : public Action, private ::boost::noncopyable
            {
            public:
                TextAction( const ::basegfx::B2DPoint& 	rStartPoint,
                            const ::rtl::OUString&		rString,
                            sal_Int32 					nStartPos,
                            sal_Int32 					nLen,
                            const CanvasSharedPtr&		rCanvas,
                            const OutDevState&			rState );

                TextAction( const ::basegfx::B2DPoint& 		rStartPoint,
                            const ::rtl::OUString&			rString,
                            sal_Int32 						nStartPos,
                            sal_Int32 						nLen,
                            const CanvasSharedPtr&			rCanvas,
                            const OutDevState&				rState,
                            const ::basegfx::B2DHomMatrix&	rTextTransform );

                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
                                     const Subset&					rSubset ) const;

                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					rSubset ) const;

                virtual sal_Int32 getActionCount() const;

            private:
                // TODO(P2): This is potentially a real mass object
                // (every character might be a separate TextAction),
                // thus, make it as lightweight as possible. For
                // example, share common RenderState among several
                // TextActions, maybe using maOffsets for the
                // translation.

                uno::Reference< rendering::XCanvasFont >	mxFont;
                const rendering::StringContext			  	maStringContext;
                const CanvasSharedPtr						mpCanvas;
                rendering::RenderState						maState;
                const sal_Int8								maTextDirection;
            };

            TextAction::TextAction( const ::basegfx::B2DPoint& 	rStartPoint,
                                    const ::rtl::OUString&		rString,
                                    sal_Int32 					nStartPos,
                                    sal_Int32 					nLen,
                                    const CanvasSharedPtr&		rCanvas,
                                    const OutDevState&			rState	) :
                mxFont( rState.xFont ),
                maStringContext( rString, nStartPos, nLen ),
                mpCanvas( rCanvas ),
                maState(),
                maTextDirection( rState.textDirection )
            {
                init( maState, mxFont,
                      rStartPoint,
                      rState, rCanvas );

                ENSURE_OR_THROW( mxFont.is(),
                                  "::cppcanvas::internal::TextAction(): Invalid font" );
            }

            TextAction::TextAction( const ::basegfx::B2DPoint& 		rStartPoint,
                                    const ::rtl::OUString&			rString,
                                    sal_Int32 						nStartPos,
                                    sal_Int32 						nLen,
                                    const CanvasSharedPtr&			rCanvas,
                                    const OutDevState&				rState,
                                    const ::basegfx::B2DHomMatrix&	rTextTransform ) :
                mxFont( rState.xFont ),
                maStringContext( rString, nStartPos, nLen ),
                mpCanvas( rCanvas ),
                maState(),
                maTextDirection( rState.textDirection )
            {
                init( maState, mxFont,
                      rStartPoint,
                      rState, rCanvas, rTextTransform );

                ENSURE_OR_THROW( mxFont.is(),
                                  "::cppcanvas::internal::TextAction(): Invalid font" );
            }

            bool TextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextAction::render()" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextAction: 0x%X", this );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                mpCanvas->getUNOCanvas()->drawText( maStringContext, mxFont,
                                                    mpCanvas->getViewState(), aLocalState, maTextDirection );

                return true;
            }

            bool TextAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
                                     const Subset&					/*rSubset*/ ) const
            {
                OSL_ENSURE( false,
                            "TextAction::render(): Subset not supported by this object" );

                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // _subsettable_ text
                return render( rTransformation );
            }

            ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                // create XTextLayout, to have the
                // XTextLayout::queryTextBounds() method available
                uno::Reference< rendering::XTextLayout > xTextLayout(
                    mxFont->createTextLayout(
                        maStringContext,
                        maTextDirection,
                        0 ) );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                         xTextLayout->queryTextBounds() ),
                                                     mpCanvas->getViewState(),
                                                     aLocalState );
            }

            ::basegfx::B2DRange TextAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					/*rSubset*/ ) const
            {
                OSL_ENSURE( false,
                            "TextAction::getBounds(): Subset not supported by this object" );

                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // _subsettable_ text
                return getBounds( rTransformation );
            }

            sal_Int32 TextAction::getActionCount() const
            {
                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // _subsettable_ text
                return 1;
            }


            // -------------------------------------------------------------------------

            class EffectTextAction :
                public Action,
                public TextRenderer,
                private ::boost::noncopyable
            {
            public:
                EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
                                  const ::basegfx::B2DSize&	 rReliefOffset,
                                  const ::Color&			 rReliefColor,
                                  const ::basegfx::B2DSize&	 rShadowOffset,
                                  const ::Color&			 rShadowColor,
                                  const ::rtl::OUString& 	 rText,
                                  sal_Int32 				 nStartPos,
                                  sal_Int32 				 nLen,
                                  VirtualDevice&			 rVDev,
                                  const CanvasSharedPtr&	 rCanvas,
                                  const OutDevState& 		 rState );

                EffectTextAction( const ::basegfx::B2DPoint&        rStartPoint,
                                  const ::basegfx::B2DSize&			rReliefOffset,
                                  const ::Color&					rReliefColor,
                                  const ::basegfx::B2DSize&			rShadowOffset,
                                  const ::Color&					rShadowColor,
                                  const ::rtl::OUString& 			rText,
                                  sal_Int32 						nStartPos,
                                  sal_Int32 						nLen,
                                  VirtualDevice&					rVDev,
                                  const CanvasSharedPtr&			rCanvas,
                                  const OutDevState& 				rState,
                                  const ::basegfx::B2DHomMatrix&	rTextTransform );

                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
                                     const Subset&					rSubset ) const;

                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					rSubset ) const;

                virtual sal_Int32 getActionCount() const;

            private:
                /// Interface TextRenderer
                virtual bool operator()( const rendering::RenderState& rRenderState ) const;

                // TODO(P2): This is potentially a real mass object
                // (every character might be a separate TextAction),
                // thus, make it as lightweight as possible. For
                // example, share common RenderState among several
                // TextActions, maybe using maOffsets for the
                // translation.

                uno::Reference< rendering::XCanvasFont >	mxFont;
                const rendering::StringContext			  	maStringContext;
                const CanvasSharedPtr						mpCanvas;
                rendering::RenderState						maState;
                const tools::TextLineInfo					maTextLineInfo;
                ::basegfx::B2DSize							maLinesOverallSize;
                const double								mnLineWidth;
                uno::Reference< rendering::XPolyPolygon2D >	mxTextLines;
                const ::basegfx::B2DSize					maReliefOffset;
                const ::Color								maReliefColor;
                const ::basegfx::B2DSize					maShadowOffset;
                const ::Color								maShadowColor;
                const sal_Int8								maTextDirection;
            };

            EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint& rStartPoint,
                                                const ::basegfx::B2DSize&  rReliefOffset,
                                                const ::Color&             rReliefColor,
                                                const ::basegfx::B2DSize&  rShadowOffset,
                                                const ::Color&             rShadowColor,
                                                const ::rtl::OUString&     rText,
                                                sal_Int32                  nStartPos,
                                                sal_Int32                  nLen,
                                                VirtualDevice&             rVDev,
                                                const CanvasSharedPtr&     rCanvas,
                                                const OutDevState&         rState ) :
                mxFont( rState.xFont ),
                maStringContext( rText, nStartPos, nLen ),
                mpCanvas( rCanvas ),
                maState(),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor ),
                maTextDirection( rState.textDirection )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           mnLineWidth,
                                           maTextLineInfo );

                init( maState, mxFont,
                      rStartPoint,
                      rState, rCanvas );

                ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
                                  "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
            }

            EffectTextAction::EffectTextAction( const ::basegfx::B2DPoint&		rStartPoint,
                                                const ::basegfx::B2DSize&		rReliefOffset,
                                                const ::Color&					rReliefColor,
                                                const ::basegfx::B2DSize&		rShadowOffset,
                                                const ::Color&					rShadowColor,
                                                const ::rtl::OUString& 			rText,
                                                sal_Int32 						nStartPos,
                                                sal_Int32 						nLen,
                                                VirtualDevice&					rVDev,
                                                const CanvasSharedPtr&			rCanvas,
                                                const OutDevState& 				rState,
                                                const ::basegfx::B2DHomMatrix&	rTextTransform ) :
                mxFont( rState.xFont ),
                maStringContext( rText, nStartPos, nLen ),
                mpCanvas( rCanvas ),
                maState(),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                mnLineWidth( getLineWidth( rVDev, rState, maStringContext ) ),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor ),
                maTextDirection( rState.textDirection )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           mnLineWidth,
                                           maTextLineInfo );

                init( maState, mxFont,
                      rStartPoint,
                      rState, rCanvas, rTextTransform );

                ENSURE_OR_THROW( mxFont.is() && mxTextLines.is(),
                                  "::cppcanvas::internal::EffectTextAction(): Invalid font or lines" );
            }

            bool EffectTextAction::operator()( const rendering::RenderState& rRenderState ) const
            {
                const rendering::ViewState& rViewState( mpCanvas->getViewState() );
                const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );

                rCanvas->fillPolyPolygon( mxTextLines,
                                          rViewState,
                                          rRenderState );

                rCanvas->drawText( maStringContext, mxFont,
                                   rViewState,
                                   rRenderState,
                                   maTextDirection );

                return true;
            }

            bool EffectTextAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextAction::render()" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextAction: 0x%X", this );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return renderEffectText( *this,
                                         aLocalState,
                                         mpCanvas->getViewState(),
                                         mpCanvas->getUNOCanvas(),
                                         maShadowColor,
                                         maShadowOffset,
                                         maReliefColor,
                                         maReliefOffset );
            }

            bool EffectTextAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
                                           const Subset&					/*rSubset*/ ) const
            {
                OSL_ENSURE( false,
                            "EffectTextAction::render(): Subset not supported by this object" );

                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // subsettable text
                return render( rTransformation );
            }

            ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                // create XTextLayout, to have the
                // XTextLayout::queryTextBounds() method available
                uno::Reference< rendering::XTextLayout > xTextLayout(
                    mxFont->createTextLayout(
                        maStringContext,
                        maTextDirection,
                        0 ) );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                 xTextLayout->queryTextBounds() ),
                                             ::basegfx::B2DRange( 0,0,
                                                                  maLinesOverallSize.getX(),
                                                                  maLinesOverallSize.getY() ),
                                             maReliefOffset,
                                             maShadowOffset,
                                             aLocalState,
                                             mpCanvas->getViewState() );
            }

            ::basegfx::B2DRange EffectTextAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                             const Subset&					/*rSubset*/ ) const
            {
                OSL_ENSURE( false,
                            "EffectTextAction::getBounds(): Subset not supported by this object" );

                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // _subsettable_ text
                return getBounds( rTransformation );
            }

            sal_Int32 EffectTextAction::getActionCount() const
            {
                // TODO(P1): Retrieve necessary font metric info for
                // TextAction from XCanvas. Currently, the
                // TextActionFactory does not generate this object for
                // subsettable text
                return 1;
            }


            // -------------------------------------------------------------------------

            class TextArrayAction : public Action, private ::boost::noncopyable
            {
            public:
                TextArrayAction( const ::basegfx::B2DPoint& 	rStartPoint,
                                 const ::rtl::OUString&			rString,
                                 sal_Int32 						nStartPos,
                                 sal_Int32 						nLen,
                                 const uno::Sequence< double >&	rOffsets,
                                 const CanvasSharedPtr&			rCanvas,
                                 const OutDevState&				rState );

                TextArrayAction( const ::basegfx::B2DPoint& 	rStartPoint,
                                 const ::rtl::OUString&			rString,
                                 sal_Int32 						nStartPos,
                                 sal_Int32 						nLen,
                                 const uno::Sequence< double >&	rOffsets,
                                 const CanvasSharedPtr&			rCanvas,
                                 const OutDevState&				rState,
                                 const ::basegfx::B2DHomMatrix&	rTextTransform );

                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
                                     const Subset&					rSubset ) const;

                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					rSubset ) const;

                virtual sal_Int32 getActionCount() const;

            private:
                // TODO(P2): This is potentially a real mass object
                // (every character might be a separate TextAction),
                // thus, make it as lightweight as possible. For
                // example, share common RenderState among several
                // TextActions, maybe using maOffsets for the
                // translation.

                uno::Reference< rendering::XTextLayout >	mxTextLayout;
                const CanvasSharedPtr						mpCanvas;
                rendering::RenderState						maState;
            };

            TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint& 		rStartPoint,
                                              const ::rtl::OUString&			rString,
                                              sal_Int32 						nStartPos,
                                              sal_Int32 						nLen,
                                              const uno::Sequence< double >&	rOffsets,
                                              const CanvasSharedPtr&			rCanvas,
                                              const OutDevState&				rState ) :
                mxTextLayout(),
                mpCanvas( rCanvas ),
                maState()
            {
                initArrayAction( maState,
                                 mxTextLayout,
                                 rStartPoint,
                                 rString,
                                 nStartPos,
                                 nLen,
                                 rOffsets,
                                 rCanvas,
                                 rState, NULL );
            }

            TextArrayAction::TextArrayAction( const ::basegfx::B2DPoint& 		rStartPoint,
                                              const ::rtl::OUString&			rString,
                                              sal_Int32 						nStartPos,
                                              sal_Int32 						nLen,
                                              const uno::Sequence< double >&	rOffsets,
                                              const CanvasSharedPtr&			rCanvas,
                                              const OutDevState&				rState,
                                              const ::basegfx::B2DHomMatrix&	rTextTransform ) :
                mxTextLayout(),
                mpCanvas( rCanvas ),
                maState()
            {
                initArrayAction( maState,
                                 mxTextLayout,
                                 rStartPoint,
                                 rString,
                                 nStartPos,
                                 nLen,
                                 rOffsets,
                                 rCanvas,
                                 rState,
                                 &rTextTransform );
            }

            bool TextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::render()" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

#ifdef SPECIAL_DEBUG
                aLocalState.Clip.clear();
                aLocalState.DeviceColor =
                    ::vcl::unotools::colorToDoubleSequence( mpCanvas->getUNOCanvas()->getDevice(),
                                                            ::Color( 0x80FF0000 ) );

                if( maState.Clip.is() )
                    mpCanvas->getUNOCanvas()->drawPolyPolygon( maState.Clip,
                                                               mpCanvas->getViewState(),
                                                               aLocalState );

                aLocalState.DeviceColor = maState.DeviceColor;
#endif

                mpCanvas->getUNOCanvas()->drawTextLayout( mxTextLayout,
                                                          mpCanvas->getViewState(),
                                                          aLocalState );

                return true;
            }

            bool TextArrayAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
                                          const Subset&						rSubset ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::render( subset )" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );

                rendering::RenderState 						aLocalState( maState );
                uno::Reference< rendering::XTextLayout >	xTextLayout( mxTextLayout );

                double nDummy0, nDummy1;
                createSubsetLayout( xTextLayout,
                                    aLocalState,
                                    nDummy0,
                                    nDummy1,
                                    rTransformation,
                                    rSubset );

                if( !xTextLayout.is() )
                    return true; // empty layout, render nothing

                mpCanvas->getUNOCanvas()->drawTextLayout( xTextLayout,
                                                          mpCanvas->getViewState(),
                                                          aLocalState );

                return true;
            }

            ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                         mxTextLayout->queryTextBounds() ),
                                                     mpCanvas->getViewState(),
                                                     aLocalState );
            }

            ::basegfx::B2DRange TextArrayAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                            const Subset&					rSubset ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::TextArrayAction::getBounds( subset )" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::TextArrayAction: 0x%X", this );

                rendering::RenderState 						aLocalState( maState );
                uno::Reference< rendering::XTextLayout >	xTextLayout( mxTextLayout );

                double nDummy0, nDummy1;
                createSubsetLayout( xTextLayout,
                                    aLocalState,
                                    nDummy0,
                                    nDummy1,
                                    rTransformation,
                                    rSubset );

                if( !xTextLayout.is() )
                    return ::basegfx::B2DRange(); // empty layout, empty bounds

                return tools::calcDevicePixelBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                         xTextLayout->queryTextBounds() ),
                                                     mpCanvas->getViewState(),
                                                     aLocalState );
            }

            sal_Int32 TextArrayAction::getActionCount() const
            {
                const rendering::StringContext& rOrigContext( mxTextLayout->getText() );

                return rOrigContext.Length;
            }


            // -------------------------------------------------------------------------

            class EffectTextArrayAction :
                public Action,
                public TextRenderer,
                private ::boost::noncopyable
            {
            public:
                EffectTextArrayAction( const ::basegfx::B2DPoint&		rStartPoint,
                                       const ::basegfx::B2DSize&		rReliefOffset,
                                       const ::Color&					rReliefColor,
                                       const ::basegfx::B2DSize&		rShadowOffset,
                                       const ::Color&					rShadowColor,
                                       const ::rtl::OUString& 			rText,
                                       sal_Int32 						nStartPos,
                                       sal_Int32 						nLen,
                                       const uno::Sequence< double >&	rOffsets,
                                       VirtualDevice&					rVDev,
                                       const CanvasSharedPtr&			rCanvas,
                                       const OutDevState& 				rState	);
                EffectTextArrayAction( const ::basegfx::B2DPoint&		rStartPoint,
                                       const ::basegfx::B2DSize&		rReliefOffset,
                                       const ::Color&					rReliefColor,
                                       const ::basegfx::B2DSize&		rShadowOffset,
                                       const ::Color&					rShadowColor,
                                       const ::rtl::OUString& 			rText,
                                       sal_Int32 						nStartPos,
                                       sal_Int32 						nLen,
                                       const uno::Sequence< double >&	rOffsets,
                                       VirtualDevice&					rVDev,
                                       const CanvasSharedPtr&			rCanvas,
                                       const OutDevState& 				rState,
                                       const ::basegfx::B2DHomMatrix&	rTextTransform );

                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
                                     const Subset&					rSubset ) const;

                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					rSubset ) const;

                virtual sal_Int32 getActionCount() const;

            private:
                // TextRenderer interface
                virtual bool operator()( const rendering::RenderState& rRenderState ) const;

                // TODO(P2): This is potentially a real mass object
                // (every character might be a separate TextAction),
                // thus, make it as lightweight as possible. For
                // example, share common RenderState among several
                // TextActions, maybe using maOffsets for the
                // translation.

                uno::Reference< rendering::XTextLayout >		mxTextLayout;
                const CanvasSharedPtr							mpCanvas;
                rendering::RenderState							maState;
                const tools::TextLineInfo						maTextLineInfo;
                ::basegfx::B2DSize								maLinesOverallSize;
                uno::Reference< rendering::XPolyPolygon2D >		mxTextLines;
                const ::basegfx::B2DSize						maReliefOffset;
                const ::Color									maReliefColor;
                const ::basegfx::B2DSize						maShadowOffset;
                const ::Color									maShadowColor;
            };

            EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint&		rStartPoint,
                                                          const ::basegfx::B2DSize&			rReliefOffset,
                                                          const ::Color&					rReliefColor,
                                                          const ::basegfx::B2DSize&			rShadowOffset,
                                                          const ::Color&					rShadowColor,
                                                          const ::rtl::OUString& 			rText,
                                                          sal_Int32 						nStartPos,
                                                          sal_Int32 						nLen,
                                                          const uno::Sequence< double >&	rOffsets,
                                                          VirtualDevice&					rVDev,
                                                          const CanvasSharedPtr&			rCanvas,
                                                          const OutDevState& 				rState	) :
                mxTextLayout(),
                mpCanvas( rCanvas ),
                maState(),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           rOffsets,
                                           maTextLineInfo );

                initArrayAction( maState,
                                 mxTextLayout,
                                 rStartPoint,
                                 rText,
                                 nStartPos,
                                 nLen,
                                 rOffsets,
                                 rCanvas,
                                 rState, NULL );
            }

            EffectTextArrayAction::EffectTextArrayAction( const ::basegfx::B2DPoint&		rStartPoint,
                                                          const ::basegfx::B2DSize&			rReliefOffset,
                                                          const ::Color&					rReliefColor,
                                                          const ::basegfx::B2DSize&			rShadowOffset,
                                                          const ::Color&					rShadowColor,
                                                          const ::rtl::OUString& 			rText,
                                                          sal_Int32 						nStartPos,
                                                          sal_Int32 						nLen,
                                                          const uno::Sequence< double >&	rOffsets,
                                                          VirtualDevice&					rVDev,
                                                          const CanvasSharedPtr&			rCanvas,
                                                          const OutDevState& 				rState,
                                                          const ::basegfx::B2DHomMatrix&	rTextTransform ) :
                mxTextLayout(),
                mpCanvas( rCanvas ),
                maState(),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           rOffsets,
                                           maTextLineInfo );

                initArrayAction( maState,
                                 mxTextLayout,
                                 rStartPoint,
                                 rText,
                                 nStartPos,
                                 nLen,
                                 rOffsets,
                                 rCanvas,
                                 rState,
                                 &rTextTransform );
            }

            bool EffectTextArrayAction::operator()( const rendering::RenderState& rRenderState ) const
            {
                const rendering::ViewState& rViewState( mpCanvas->getViewState() );
                const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );

                rCanvas->fillPolyPolygon( mxTextLines,
                                          rViewState,
                                          rRenderState );

                rCanvas->drawTextLayout( mxTextLayout,
                                         rViewState,
                                         rRenderState );

                return true;
            }

            bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return renderEffectText( *this,
                                         aLocalState,
                                         mpCanvas->getViewState(),
                                         mpCanvas->getUNOCanvas(),
                                         maShadowColor,
                                         maShadowOffset,
                                         maReliefColor,
                                         maReliefOffset );
            }

            class EffectTextArrayRenderHelper : public TextRenderer
            {
            public:
                EffectTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >&		rCanvas,
                                             const uno::Reference< rendering::XTextLayout >& 	rTextLayout,
                                             const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
                                             const rendering::ViewState&			 			rViewState ) :
                    mrCanvas( rCanvas ),
                    mrTextLayout( rTextLayout ),
                    mrLinePolygon( rLinePolygon ),
                    mrViewState( rViewState )
                {
                }

                // TextRenderer interface
                virtual bool operator()( const rendering::RenderState& rRenderState ) const
                {
                    mrCanvas->fillPolyPolygon( mrLinePolygon,
                                               mrViewState,
                                               rRenderState );

                    mrCanvas->drawTextLayout( mrTextLayout,
                                              mrViewState,
                                              rRenderState );

                    return true;
                }

            private:
                const uno::Reference< rendering::XCanvas >&			mrCanvas;
                const uno::Reference< rendering::XTextLayout >&		mrTextLayout;
                const uno::Reference< rendering::XPolyPolygon2D >&	mrLinePolygon;
                const rendering::ViewState&			 				mrViewState;
            };

            bool EffectTextArrayAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                const Subset&					rSubset ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render( subset )" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );

                rendering::RenderState 					 aLocalState( maState );
                uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
                const geometry::RealRectangle2D          aTextBounds( mxTextLayout->queryTextBounds() );

                double nMinPos(0.0);
                double nMaxPos(aTextBounds.X2 - aTextBounds.X1);

                createSubsetLayout( xTextLayout,
                                    aLocalState,
                                    nMinPos,
                                    nMaxPos,
                                    rTransformation,
                                    rSubset );

                if( !xTextLayout.is() )
                    return true; // empty layout, render nothing


                // create and setup local line polygon
                // ===================================

                uno::Reference< rendering::XCanvas > xCanvas( mpCanvas->getUNOCanvas() );
                const rendering::ViewState&			 rViewState( mpCanvas->getViewState() );

                uno::Reference< rendering::XPolyPolygon2D > xTextLines(
                    ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
                        xCanvas->getDevice(),
                        tools::createTextLinesPolyPolygon(
                            0.0, nMaxPos - nMinPos,
                            maTextLineInfo ) ) );


                // render everything
                // =================

                return renderEffectText(
                    EffectTextArrayRenderHelper( xCanvas,
                                                 xTextLayout,
                                                 xTextLines,
                                                 rViewState ),
                    aLocalState,
                    rViewState,
                    xCanvas,
                    maShadowColor,
                    maShadowOffset,
                    maReliefColor,
                    maReliefOffset );
            }

            ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                 mxTextLayout->queryTextBounds() ),
                                             ::basegfx::B2DRange( 0,0,
                                                                  maLinesOverallSize.getX(),
                                                                  maLinesOverallSize.getY() ),
                                             maReliefOffset,
                                             maShadowOffset,
                                             aLocalState,
                                             mpCanvas->getViewState() );
            }

            ::basegfx::B2DRange EffectTextArrayAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                                  const Subset&						rSubset ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::getBounds( subset )" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );

                rendering::RenderState 					 aLocalState( maState );
                uno::Reference< rendering::XTextLayout > xTextLayout( mxTextLayout );
                const geometry::RealRectangle2D          aTextBounds( mxTextLayout->queryTextBounds() );

                double nMinPos(0.0);
                double nMaxPos(aTextBounds.X2 - aTextBounds.X1);

                createSubsetLayout( xTextLayout,
                                    aLocalState,
                                    nMinPos,
                                    nMaxPos,
                                    rTransformation,
                                    rSubset );

                if( !xTextLayout.is() )
                    return ::basegfx::B2DRange(); // empty layout, empty bounds


                // create and setup local line polygon
                // ===================================

                const ::basegfx::B2DPolyPolygon aPoly(
                    tools::createTextLinesPolyPolygon(
                        0.0, nMaxPos - nMinPos,
                        maTextLineInfo ) );

                return calcEffectTextBounds( ::basegfx::unotools::b2DRectangleFromRealRectangle2D(
                                                 xTextLayout->queryTextBounds() ),
                                             ::basegfx::tools::getRange( aPoly ),
                                             maReliefOffset,
                                             maShadowOffset,
                                             aLocalState,
                                             mpCanvas->getViewState() );
            }

            sal_Int32 EffectTextArrayAction::getActionCount() const
            {
                const rendering::StringContext& rOrigContext( mxTextLayout->getText() );

                return rOrigContext.Length;
            }


            // -------------------------------------------------------------------------

            class OutlineAction :
                public Action,
                public TextRenderer,
                private ::boost::noncopyable
            {
            public:
                OutlineAction( const ::basegfx::B2DPoint&							rStartPoint,
                               const ::basegfx::B2DSize&							rReliefOffset,
                               const ::Color&										rReliefColor,
                               const ::basegfx::B2DSize&							rShadowOffset,
                               const ::Color&										rShadowColor,
                               const ::basegfx::B2DRectangle&						rOutlineBounds,
                               const uno::Reference< rendering::XPolyPolygon2D >&	rTextPoly,
                               const ::std::vector< sal_Int32 >& 					rPolygonGlyphMap,
                               const uno::Sequence< double >&						rOffsets,
                               VirtualDevice&										rVDev,
                               const CanvasSharedPtr&								rCanvas,
                               const OutDevState& 									rState	);
                OutlineAction( const ::basegfx::B2DPoint&							rStartPoint,
                               const ::basegfx::B2DSize&							rReliefOffset,
                               const ::Color&										rReliefColor,
                               const ::basegfx::B2DSize&							rShadowOffset,
                               const ::Color&										rShadowColor,
                               const ::basegfx::B2DRectangle&						rOutlineBounds,
                               const uno::Reference< rendering::XPolyPolygon2D >&	rTextPoly,
                               const ::std::vector< sal_Int32 >& 					rPolygonGlyphMap,
                               const uno::Sequence< double >&						rOffsets,
                               VirtualDevice&										rVDev,
                               const CanvasSharedPtr&								rCanvas,
                               const OutDevState& 									rState,
                               const ::basegfx::B2DHomMatrix&						rTextTransform );

                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual bool render( const ::basegfx::B2DHomMatrix& rTransformation,
                                     const Subset&					rSubset ) const;

                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const;
                virtual ::basegfx::B2DRange getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                       const Subset&					rSubset ) const;

                virtual sal_Int32 getActionCount() const;

            private:
                // TextRenderer interface
                virtual bool operator()( const rendering::RenderState& rRenderState ) const;

                // TODO(P2): This is potentially a real mass object
                // (every character might be a separate TextAction),
                // thus, make it as lightweight as possible. For
                // example, share common RenderState among several
                // TextActions, maybe using maOffsets for the
                // translation.

                uno::Reference< rendering::XPolyPolygon2D >			mxTextPoly;

                /** This vector denotes the index of the start polygon
                    for the respective glyph sequence.

                    To get a polygon index range for a given character
                    index i, take [ maPolygonGlyphMap[i],
                    maPolygonGlyphMap[i+1] ). Note that this is wrong
                    for BiDi
                 */
                const ::std::vector< sal_Int32 > 					maPolygonGlyphMap;
                const uno::Sequence< double >						maOffsets;
                const CanvasSharedPtr								mpCanvas;
                rendering::RenderState								maState;
                double												mnOutlineWidth;
                const uno::Sequence< double >						maFillColor;
                const tools::TextLineInfo							maTextLineInfo;
                ::basegfx::B2DSize									maLinesOverallSize;
                const ::basegfx::B2DRectangle						maOutlineBounds;
                uno::Reference< rendering::XPolyPolygon2D >			mxTextLines;
                const ::basegfx::B2DSize							maReliefOffset;
                const ::Color										maReliefColor;
                const ::basegfx::B2DSize							maShadowOffset;
                const ::Color										maShadowColor;
            };

            double calcOutlineWidth( const OutDevState& rState,
                                     VirtualDevice&     rVDev )
            {
                const ::basegfx::B2DSize aFontSize( 0,
                                                    rVDev.GetFont().GetHeight() / 64.0 );

                const double nOutlineWidth(
                    (rState.mapModeTransform * aFontSize).getY() );

                return nOutlineWidth < 1.0 ? 1.0 : nOutlineWidth;
            }

            OutlineAction::OutlineAction( const ::basegfx::B2DPoint&							rStartPoint,
                                          const ::basegfx::B2DSize&								rReliefOffset,
                                          const ::Color&										rReliefColor,
                                          const ::basegfx::B2DSize&								rShadowOffset,
                                          const ::Color&										rShadowColor,
                                          const ::basegfx::B2DRectangle&						rOutlineBounds,
                                          const uno::Reference< rendering::XPolyPolygon2D >& 	rTextPoly,
                                          const ::std::vector< sal_Int32 >& 					rPolygonGlyphMap,
                                          const uno::Sequence< double >&						rOffsets,
                                          VirtualDevice&										rVDev,
                                          const CanvasSharedPtr&								rCanvas,
                                          const OutDevState& 									rState	) :
                mxTextPoly( rTextPoly ),
                maPolygonGlyphMap( rPolygonGlyphMap ),
                maOffsets( rOffsets ),
                mpCanvas( rCanvas ),
                maState(),
                mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
                maFillColor(
                    ::vcl::unotools::colorToDoubleSequence(
                        ::Color( COL_WHITE ),
                        rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                maOutlineBounds( rOutlineBounds ),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           rOffsets,
                                           maTextLineInfo );

                init( maState,
                      rStartPoint,
                      rState,
                      rCanvas );
            }

            OutlineAction::OutlineAction( const ::basegfx::B2DPoint&							rStartPoint,
                                          const ::basegfx::B2DSize&								rReliefOffset,
                                          const ::Color&										rReliefColor,
                                          const ::basegfx::B2DSize&								rShadowOffset,
                                          const ::Color&										rShadowColor,
                                          const ::basegfx::B2DRectangle&						rOutlineBounds,
                                          const uno::Reference< rendering::XPolyPolygon2D >& 	rTextPoly,
                                          const ::std::vector< sal_Int32 >& 					rPolygonGlyphMap,
                                          const uno::Sequence< double >&						rOffsets,
                                          VirtualDevice&										rVDev,
                                          const CanvasSharedPtr&								rCanvas,
                                          const OutDevState& 									rState,
                                          const ::basegfx::B2DHomMatrix&						rTextTransform ) :
                mxTextPoly( rTextPoly ),
                maPolygonGlyphMap( rPolygonGlyphMap ),
                maOffsets( rOffsets ),
                mpCanvas( rCanvas ),
                maState(),
                mnOutlineWidth( calcOutlineWidth(rState,rVDev) ),
                maFillColor(
                    ::vcl::unotools::colorToDoubleSequence(
                        ::Color( COL_WHITE ),
                        rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() )),
                maTextLineInfo( tools::createTextLineInfo( rVDev, rState ) ),
                maLinesOverallSize(),
                maOutlineBounds( rOutlineBounds ),
                mxTextLines(),
                maReliefOffset( rReliefOffset ),
                maReliefColor( rReliefColor ),
                maShadowOffset( rShadowOffset ),
                maShadowColor( rShadowColor )
            {
                initEffectLinePolyPolygon( maLinesOverallSize,
                                           mxTextLines,
                                           rCanvas,
                                           rOffsets,
                                           maTextLineInfo );

                init( maState,
                      rStartPoint,
                      rState,
                      rCanvas,
                      rTextTransform );
            }

            bool OutlineAction::operator()( const rendering::RenderState& rRenderState ) const
            {
                const rendering::ViewState& 				rViewState( mpCanvas->getViewState() );
                const uno::Reference< rendering::XCanvas >& rCanvas( mpCanvas->getUNOCanvas() );

                rendering::StrokeAttributes aStrokeAttributes;

                aStrokeAttributes.StrokeWidth  = mnOutlineWidth;
                aStrokeAttributes.MiterLimit   = 1.0;
                aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
                aStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
                aStrokeAttributes.JoinType     = rendering::PathJoinType::MITER;

                rendering::RenderState aLocalState( rRenderState );
                aLocalState.DeviceColor = maFillColor;

                // TODO(P1): implement caching

                // background of text
                rCanvas->fillPolyPolygon( mxTextPoly,
                                          rViewState,
                                          aLocalState );

                // border line of text
                rCanvas->strokePolyPolygon( mxTextPoly,
                                            rViewState,
                                            rRenderState,
                                            aStrokeAttributes );

                // underlines/strikethrough - background
                rCanvas->fillPolyPolygon( mxTextLines,
                                          rViewState,
                                          aLocalState );
                // underlines/strikethrough - border
                rCanvas->strokePolyPolygon( mxTextLines,
                                            rViewState,
                                            rRenderState,
                                            aStrokeAttributes );

                return true;
            }

            bool OutlineAction::render( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::EffectTextArrayAction::render()" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::EffectTextArrayAction: 0x%X", this );

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return renderEffectText( *this,
                                         aLocalState,
                                         mpCanvas->getViewState(),
                                         mpCanvas->getUNOCanvas(),
                                         maShadowColor,
                                         maShadowOffset,
                                         maReliefColor,
                                         maReliefOffset );
            }

            class OutlineTextArrayRenderHelper : public TextRenderer
            {
            public:
                OutlineTextArrayRenderHelper( const uno::Reference< rendering::XCanvas >&		 rCanvas,
                                              const uno::Reference< rendering::XPolyPolygon2D >& rTextPolygon,
                                              const uno::Reference< rendering::XPolyPolygon2D >& rLinePolygon,
                                              const rendering::ViewState&			 			 rViewState,
                                              double											 nOutlineWidth ) :
                    maFillColor(
                        ::vcl::unotools::colorToDoubleSequence(
                            ::Color( COL_WHITE ),
                            rCanvas->getDevice()->getDeviceColorSpace() )),
                    mnOutlineWidth( nOutlineWidth ),
                    mrCanvas( rCanvas ),
                    mrTextPolygon( rTextPolygon ),
                    mrLinePolygon( rLinePolygon ),
                    mrViewState( rViewState )
                {
                }

                // TextRenderer interface
                virtual bool operator()( const rendering::RenderState& rRenderState ) const
                {
                    rendering::StrokeAttributes aStrokeAttributes;

                    aStrokeAttributes.StrokeWidth  = mnOutlineWidth;
                    aStrokeAttributes.MiterLimit   = 1.0;
                    aStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
                    aStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
                    aStrokeAttributes.JoinType     = rendering::PathJoinType::MITER;

                    rendering::RenderState aLocalState( rRenderState );
                    aLocalState.DeviceColor = maFillColor;

                    // TODO(P1): implement caching

                    // background of text
                    mrCanvas->fillPolyPolygon( mrTextPolygon,
                                               mrViewState,
                                               aLocalState );

                    // border line of text
                    mrCanvas->strokePolyPolygon( mrTextPolygon,
                                                 mrViewState,
                                                 rRenderState,
                                                 aStrokeAttributes );

                    // underlines/strikethrough - background
                    mrCanvas->fillPolyPolygon( mrLinePolygon,
                                               mrViewState,
                                               aLocalState );
                    // underlines/strikethrough - border
                    mrCanvas->strokePolyPolygon( mrLinePolygon,
                                                 mrViewState,
                                                 rRenderState,
                                                 aStrokeAttributes );

                    return true;
                }

            private:
                const uno::Sequence< double >						maFillColor;
                double												mnOutlineWidth;
                const uno::Reference< rendering::XCanvas >&			mrCanvas;
                const uno::Reference< rendering::XPolyPolygon2D >&	mrTextPolygon;
                const uno::Reference< rendering::XPolyPolygon2D >&	mrLinePolygon;
                const rendering::ViewState&			 				mrViewState;
            };

            bool OutlineAction::render( const ::basegfx::B2DHomMatrix&	rTransformation,
                                        const Subset&					rSubset ) const
            {
                RTL_LOGFILE_CONTEXT( aLog, "::cppcanvas::internal::OutlineAction::render( subset )" );
                RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::cppcanvas::internal::OutlineAction: 0x%X", this );

                if( rSubset.mnSubsetBegin == rSubset.mnSubsetEnd )
                    return true; // empty range, render nothing

#if 1
                // TODO(F3): Subsetting NYI for outline text!
                return render( rTransformation );
#else
                const rendering::StringContext rOrigContext( mxTextLayout->getText() );

                if( rSubset.mnSubsetBegin == 0 &&
                    rSubset.mnSubsetEnd == rOrigContext.Length )
                {
                    // full range, no need for subsetting
                    return render( rTransformation );
                }

                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);


                // create and setup local Text polygon
                // ===================================

                uno::Reference< rendering::XPolyPolygon2D > xTextPolygon();

                // TODO(P3): Provide an API method for that!

                if( !xTextLayout.is() )
                    return false;

                // render everything
                // =================

                return renderEffectText(
                    OutlineTextArrayRenderHelper(
                        xCanvas,
                        mnOutlineWidth,
                        xTextLayout,
                        xTextLines,
                        rViewState ),
                    aLocalState,
                    rViewState,
                    xCanvas,
                    maShadowColor,
                    maShadowOffset,
                    maReliefColor,
                    maReliefOffset );
#endif
            }

            ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix& rTransformation ) const
            {
                rendering::RenderState aLocalState( maState );
                ::canvas::tools::prependToRenderState(aLocalState, rTransformation);

                return calcEffectTextBounds( maOutlineBounds,
                                             ::basegfx::B2DRange( 0,0,
                                                                  maLinesOverallSize.getX(),
                                                                  maLinesOverallSize.getY() ),
                                             maReliefOffset,
                                             maShadowOffset,
                                             aLocalState,
                                             mpCanvas->getViewState() );
            }

            ::basegfx::B2DRange OutlineAction::getBounds( const ::basegfx::B2DHomMatrix&	rTransformation,
                                                          const Subset&						/*rSubset*/ ) const
            {
                OSL_ENSURE( false,
                            "OutlineAction::getBounds(): Subset not yet supported by this object" );

                return getBounds( rTransformation );
            }

            sal_Int32 OutlineAction::getActionCount() const
            {
                // TODO(F3): Subsetting NYI for outline text!
                return maOffsets.getLength();
            }


            // ======================================================================
            //
            // Action factory methods
            //
            // ======================================================================

            /** Create an outline action

            	This method extracts the polygonal outline from the
            	text, and creates a properly setup OutlineAction from
            	it.
             */
            ActionSharedPtr createOutline( const ::basegfx::B2DPoint&		rStartPoint,
                                           const ::basegfx::B2DSize&		rReliefOffset,
                                           const ::Color&					rReliefColor,
                                           const ::basegfx::B2DSize&        rShadowOffset,
                                           const ::Color&					rShadowColor,
                                           const String& 					rText,
                                           sal_Int32 						nStartPos,
                                           sal_Int32 						nLen,
                                           const sal_Int32*					pDXArray,
                                           VirtualDevice&					rVDev,
                                           const CanvasSharedPtr&			rCanvas,
                                           const OutDevState& 				rState,
                                           const Renderer::Parameters& 		rParms	)
            {
                // operate on raw DX array here (in logical coordinate
                // system), to have a higher resolution
                // PolyPolygon. That polygon is then converted to
                // device coordinate system.

                // #i68512# Temporarily switch off font rotation
                // (which is already contained in the render state
                // transformation matrix - otherwise, glyph polygons
                // will be rotated twice)
                const ::Font aOrigFont( rVDev.GetFont() );
                ::Font       aUnrotatedFont( aOrigFont );
                aUnrotatedFont.SetOrientation(0);
                rVDev.SetFont( aUnrotatedFont );

                // TODO(F3): Don't understand parameter semantics of
                // GetTextOutlines()
                ::basegfx::B2DPolyPolygon aResultingPolyPolygon;
                PolyPolyVector aVCLPolyPolyVector;
                const bool bHaveOutlines( rVDev.GetTextOutlines( aVCLPolyPolyVector, rText,
                                                                 static_cast<sal_uInt16>(nStartPos),
                                                                 static_cast<sal_uInt16>(nStartPos),
                                                                 static_cast<sal_uInt16>(nLen),
                                                                 sal_True, 0, pDXArray ) );
                rVDev.SetFont(aOrigFont);

                if( !bHaveOutlines )
                    return ActionSharedPtr();

                ::std::vector< sal_Int32 > aPolygonGlyphMap;

                // first glyph starts at polygon index 0
                aPolygonGlyphMap.push_back( 0 );

                // remove offsetting from mapmode transformation
                // (outline polygons must stay at origin, only need to
                // be scaled)
                ::basegfx::B2DHomMatrix aMapModeTransform(
                    rState.mapModeTransform );
                aMapModeTransform.set(0,2, 0.0);
                aMapModeTransform.set(1,2, 0.0);

                PolyPolyVector::const_iterator 		 aIter( aVCLPolyPolyVector.begin() );
                const PolyPolyVector::const_iterator aEnd( aVCLPolyPolyVector.end() );
                for( ; aIter!= aEnd; ++aIter )
                {
                    ::basegfx::B2DPolyPolygon aPolyPolygon;

                    aPolyPolygon = aIter->getB2DPolyPolygon();
                    aPolyPolygon.transform( aMapModeTransform );

                    // append result to collecting polypoly
                    for( sal_uInt32 i=0; i<aPolyPolygon.count(); ++i )
                    {
                        // #i47795# Ensure closed polygons (since
                        // FreeType returns the glyph outlines
                        // open)
                        const ::basegfx::B2DPolygon& rPoly( aPolyPolygon.getB2DPolygon( i ) );
                        const sal_uInt32 nCount( rPoly.count() );
                        if( nCount<3 ||
                            rPoly.isClosed() )
                        {
                            // polygon either degenerate, or
                            // already closed.
                            aResultingPolyPolygon.append( rPoly );
                        }
                        else
                        {
                            ::basegfx::B2DPolygon aPoly(rPoly);
                            aPoly.setClosed(true);

                            aResultingPolyPolygon.append( aPoly );
                        }
                    }

                    // TODO(F3): Depending on the semantics of
                    // GetTextOutlines(), this here is wrong!

                    // calc next glyph index
                    aPolygonGlyphMap.push_back( aResultingPolyPolygon.count() );
                }

                const uno::Sequence< double > aCharWidthSeq(
                    pDXArray ?
                    setupDXArray( pDXArray, nLen, rState ) :
                    setupDXArray( rText,
                                  nStartPos,
                                  nLen,
                                  rVDev,
                                  rState ));
                const uno::Reference< rendering::XPolyPolygon2D > xTextPoly(
                    ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
                        rCanvas->getUNOCanvas()->getDevice(),
                        aResultingPolyPolygon ) );

                if( rParms.maTextTransformation.is_initialized() )
                {
                    return ActionSharedPtr(
                        new OutlineAction(
                            rStartPoint,
                            rReliefOffset,
                            rReliefColor,
                            rShadowOffset,
                            rShadowColor,
                            ::basegfx::tools::getRange(aResultingPolyPolygon),
                            xTextPoly,
                            aPolygonGlyphMap,
                            aCharWidthSeq,
                            rVDev,
                            rCanvas,
                            rState,
                            *rParms.maTextTransformation ) );
                }
                else
                {
                    return ActionSharedPtr(
                        new OutlineAction(
                            rStartPoint,
                            rReliefOffset,
                            rReliefColor,
                            rShadowOffset,
                            rShadowColor,
                            ::basegfx::tools::getRange(aResultingPolyPolygon),
                            xTextPoly,
                            aPolygonGlyphMap,
                            aCharWidthSeq,
                            rVDev,
                            rCanvas,
                            rState	) );
                }
            }

        } // namespace


        // ---------------------------------------------------------------------------------

		ActionSharedPtr TextActionFactory::createTextAction( const ::Point&					rStartPoint,
                                                             const ::Size&					rReliefOffset,
                                                             const ::Color&					rReliefColor,
                                                             const ::Size&					rShadowOffset,
                                                             const ::Color&					rShadowColor,
                                                             const String& 					rText,
                                                             sal_Int32 						nStartPos,
                                                             sal_Int32 						nLen,
                                                             const sal_Int32*				pDXArray,
                                                             VirtualDevice&					rVDev,
                                                             const CanvasSharedPtr&			rCanvas,
                                                             const OutDevState& 			rState,
                                                             const Renderer::Parameters& 	rParms,
                                                             bool							bSubsettable	)
		{
            const ::Size  aBaselineOffset( tools::getBaselineOffset( rState,
                                                                     rVDev ) );
            // #143885# maintain (nearly) full precision positioning,
            // by circumventing integer-based OutDev-mapping
            const ::basegfx::B2DPoint aStartPoint(
                rState.mapModeTransform *
                ::basegfx::B2DPoint(rStartPoint.X() + aBaselineOffset.Width(),
                                    rStartPoint.Y() + aBaselineOffset.Height()) );

            const ::basegfx::B2DSize aReliefOffset(
                rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rReliefOffset ) );
            const ::basegfx::B2DSize aShadowOffset(
                rState.mapModeTransform * ::vcl::unotools::b2DSizeFromSize( rShadowOffset ) );

            if( rState.isTextOutlineModeSet )
            {
                return createOutline(
                    		aStartPoint,
                            aReliefOffset,
                            rReliefColor,
                            aShadowOffset,
                            rShadowColor,
                            rText,
                            nStartPos,
                            nLen,
                            pDXArray,
                            rVDev,
                            rCanvas,
                            rState,
                            rParms );
            }

            // convert DX array to device coordinate system (and
            // create it in the first place, if pDXArray is NULL)
            const uno::Sequence< double > aCharWidths(
                pDXArray ?
                setupDXArray( pDXArray, nLen, rState ) :
                setupDXArray( rText,
                              nStartPos,
                              nLen,
                              rVDev,
                              rState ));

            // determine type of text action to create
            // =======================================

            const ::Color aEmptyColor( COL_AUTO );

            // no DX array, and no need to subset - no need to store
            // DX array, then.
            if( !pDXArray && !bSubsettable )
            {
                // effects, or not?
                if( !rState.textOverlineStyle &&
                    !rState.textUnderlineStyle &&
                    !rState.textStrikeoutStyle &&
                    rReliefColor == aEmptyColor &&
                    rShadowColor == aEmptyColor )
                {
                    // nope
                    if( rParms.maTextTransformation.is_initialized() )
                    {
                        return ActionSharedPtr( new TextAction(
                                                    aStartPoint,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    rCanvas,
                                                    rState,
                                                    *rParms.maTextTransformation ) );
                    }
                    else
                    {
                        return ActionSharedPtr( new TextAction(
                                                    aStartPoint,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    rCanvas,
                                                    rState ) );
                    }
                }
                else
                {
                    // at least one of the effects requested
                    if( rParms.maTextTransformation.is_initialized() )
                        return ActionSharedPtr( new EffectTextAction(
                                                    aStartPoint,
                                                    aReliefOffset,
                                                    rReliefColor,
                                                    aShadowOffset,
                                                    rShadowColor,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    rVDev,
                                                    rCanvas,
                                                    rState,
                                                    *rParms.maTextTransformation ) );
                    else
                        return ActionSharedPtr( new EffectTextAction(
                                                    aStartPoint,
                                                    aReliefOffset,
                                                    rReliefColor,
                                                    aShadowOffset,
                                                    rShadowColor,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    rVDev,
                                                    rCanvas,
                                                    rState ) );
                }
            }
            else
            {
                // DX array necessary - any effects?
                if( !rState.textOverlineStyle &&
                    !rState.textUnderlineStyle &&
                    !rState.textStrikeoutStyle &&
                    rReliefColor == aEmptyColor &&
                    rShadowColor == aEmptyColor )
                {
                    // nope
                    if( rParms.maTextTransformation.is_initialized() )
                        return ActionSharedPtr( new TextArrayAction(
                                                    aStartPoint,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    aCharWidths,
                                                    rCanvas,
                                                    rState,
                                                    *rParms.maTextTransformation ) );
                    else
                        return ActionSharedPtr( new TextArrayAction(
                                                    aStartPoint,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    aCharWidths,
                                                    rCanvas,
                                                    rState ) );
                }
                else
                {
                    // at least one of the effects requested
                    if( rParms.maTextTransformation.is_initialized() )
                        return ActionSharedPtr( new EffectTextArrayAction(
                                                    aStartPoint,
                                                    aReliefOffset,
                                                    rReliefColor,
                                                    aShadowOffset,
                                                    rShadowColor,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    aCharWidths,
                                                    rVDev,
                                                    rCanvas,
                                                    rState,
                                                    *rParms.maTextTransformation ) );
                    else
                        return ActionSharedPtr( new EffectTextArrayAction(
                                                    aStartPoint,
                                                    aReliefOffset,
                                                    rReliefColor,
                                                    aShadowOffset,
                                                    rShadowColor,
                                                    rText,
                                                    nStartPos,
                                                    nLen,
                                                    aCharWidths,
                                                    rVDev,
                                                    rCanvas,
                                                    rState ) );
                }
            }
#if defined __GNUC__
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 1
            // Unreachable; to avoid bogus warning:
            return ActionSharedPtr();
#endif
#endif
        }
    }
}
