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

#include <svx/svdotext.hxx>
#include <svx/svdoutl.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
#include <basegfx/range/b2drange.hxx>
#include <editeng/editstat.hxx>
#include <vcl/salbtype.hxx>
#include <svx/sdtfchim.hxx>
#include <svl/itemset.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <drawinglayer/animation/animationtiming.hxx>
#include <basegfx/color/bcolor.hxx>
#include <vcl/svapp.hxx>
#include <editeng/eeitemid.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/svxenum.hxx>
#include <editeng/flditem.hxx>
#include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
#include <vcl/metaact.hxx>
#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
#include <svx/unoapi.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <editeng/outlobj.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>

//////////////////////////////////////////////////////////////////////////////
// helpers

namespace
{
    drawinglayer::primitive2d::Primitive2DSequence impConvertVectorToPrimitive2DSequence(const std::vector< drawinglayer::primitive2d::BasePrimitive2D* >& rPrimitiveVector)
    {
		const sal_Int32 nCount(rPrimitiveVector.size());
		drawinglayer::primitive2d::Primitive2DSequence aRetval(nCount);

	    for(sal_Int32 a(0L); a < nCount; a++)
	    {
		    aRetval[a] = drawinglayer::primitive2d::Primitive2DReference(rPrimitiveVector[a]);
	    }

        return aRetval;
    }

    class impTextBreakupHandler
	{
    private:
		std::vector< drawinglayer::primitive2d::BasePrimitive2D* >	maTextPortionPrimitives;
		std::vector< drawinglayer::primitive2d::BasePrimitive2D* >	maLinePrimitives;
		std::vector< drawinglayer::primitive2d::BasePrimitive2D* >	maParagraphPrimitives;

		SdrOutliner&												mrOutliner;
		basegfx::B2DHomMatrix										maNewTransformA;
		basegfx::B2DHomMatrix										maNewTransformB;

        // the visible area for contour text decomposition
        basegfx::B2DVector                                          maScale;

		// #SJ# ClipRange for BlockText decomposition; only text portions completely
		// inside are to be accepted, so this is different from geometric clipping
		// (which would allow e.g. upper parts of portions to remain). Only used for 
		// BlockText (see there)
		basegfx::B2DRange                                           maClipRange;

		DECL_LINK(decomposeContourTextPrimitive, DrawPortionInfo* );
		DECL_LINK(decomposeBlockTextPrimitive, DrawPortionInfo* );
		DECL_LINK(decomposeStretchTextPrimitive, DrawPortionInfo* );

		DECL_LINK(decomposeContourBulletPrimitive, DrawBulletInfo* );
		DECL_LINK(decomposeBlockBulletPrimitive, DrawBulletInfo* );
		DECL_LINK(decomposeStretchBulletPrimitive, DrawBulletInfo* );

		bool impIsUnderlineAbove(const Font& rFont) const;
		void impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo);
    	drawinglayer::primitive2d::BasePrimitive2D* impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) const;
        void impFlushTextPortionPrimitivesToLinePrimitives();
        void impFlushLinePrimitivesToParagraphPrimitives();
		void impHandleDrawPortionInfo(const DrawPortionInfo& rInfo);
		void impHandleDrawBulletInfo(const DrawBulletInfo& rInfo);

	public:
		impTextBreakupHandler(SdrOutliner& rOutliner)
		:	maTextPortionPrimitives(),
			maLinePrimitives(),
			maParagraphPrimitives(),
			mrOutliner(rOutliner),
			maNewTransformA(),
			maNewTransformB(),
			maScale(),
			maClipRange()
		{
		}

		void decomposeContourTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB, const basegfx::B2DVector& rScale)
		{
            maScale = rScale;
			maNewTransformA = rNewTransformA;
			maNewTransformB = rNewTransformB;
			mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeContourTextPrimitive));
			mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeContourBulletPrimitive));
			mrOutliner.StripPortions();
			mrOutliner.SetDrawPortionHdl(Link());
			mrOutliner.SetDrawBulletHdl(Link());
		}

		void decomposeBlockTextPrimitive(
			const basegfx::B2DHomMatrix& rNewTransformA,
			const basegfx::B2DHomMatrix& rNewTransformB,
			const basegfx::B2DRange& rClipRange)
		{
			maNewTransformA = rNewTransformA;
			maNewTransformB = rNewTransformB;
			maClipRange = rClipRange;
			mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeBlockTextPrimitive));
			mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeBlockBulletPrimitive));
			mrOutliner.StripPortions();
			mrOutliner.SetDrawPortionHdl(Link());
			mrOutliner.SetDrawBulletHdl(Link());
		}

		void decomposeStretchTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB)
		{
			maNewTransformA = rNewTransformA;
			maNewTransformB = rNewTransformB;
			mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeStretchTextPrimitive));
			mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeStretchBulletPrimitive));
			mrOutliner.StripPortions();
			mrOutliner.SetDrawPortionHdl(Link());
			mrOutliner.SetDrawBulletHdl(Link());
		}

		drawinglayer::primitive2d::Primitive2DSequence getPrimitive2DSequence();
	};

	bool impTextBreakupHandler::impIsUnderlineAbove(const Font& rFont) const
	{
		if(!rFont.IsVertical())
		{
			return false;
		}

		if((LANGUAGE_JAPANESE == rFont.GetLanguage()) || (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage()))
		{
			// the underline is right for Japanese only
			return true;
		}

		return false;
	}

	void impTextBreakupHandler::impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo)
	{
		if(rInfo.mrText.Len() && rInfo.mnTextLen)
		{
			basegfx::B2DVector aFontScaling;
			drawinglayer::attribute::FontAttribute aFontAttribute(
                drawinglayer::primitive2d::getFontAttributeFromVclFont(
                    aFontScaling,
                    rInfo.mrFont,
                    rInfo.IsRTL(),
                    false));
			basegfx::B2DHomMatrix aNewTransform;

            // add font scale to new transform
			aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY());

			// look for proportional font scaling, evtl scale accordingly
            if(100 != rInfo.mrFont.GetPropr())
			{
				const double fFactor(rInfo.mrFont.GetPropr() / 100.0);
				aNewTransform.scale(fFactor, fFactor);
			}

			// apply font rotate
			if(rInfo.mrFont.GetOrientation())
			{
				aNewTransform.rotate(-rInfo.mrFont.GetOrientation() * F_PI1800);
			}

			// look for escapement, evtl translate accordingly
			if(rInfo.mrFont.GetEscapement())
			{
				sal_Int16 nEsc(rInfo.mrFont.GetEscapement());

				if(DFLT_ESC_AUTO_SUPER == nEsc)
				{
					nEsc = 33;
				}
				else if(DFLT_ESC_AUTO_SUB == nEsc)
				{
					nEsc = -20;
				}

				if(nEsc > 100)
				{
					nEsc = 100;
				}
				else if(nEsc < -100)
				{
					nEsc = -100;
				}

				const double fEscapement(nEsc / -100.0);
				aNewTransform.translate(0.0, fEscapement * aFontScaling.getY());
			}

			// apply transformA
			aNewTransform *= maNewTransformA;

			// apply local offset
			aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y());

			// also apply embedding object's transform
			aNewTransform *= maNewTransformB;

			// prepare DXArray content. To make it independent from font size (and such from
			// the text transformation), scale it to unit coordinates
			::std::vector< double > aDXArray;
			static bool bDisableTextArray(false);

			if(!bDisableTextArray && rInfo.mpDXArray && rInfo.mnTextLen)
			{
				aDXArray.reserve(rInfo.mnTextLen);

                for(xub_StrLen a(0); a < rInfo.mnTextLen; a++)
			    {
				    aDXArray.push_back((double)rInfo.mpDXArray[a]);
			    }
			}

			// create complex text primitive and append
			const Color aFontColor(rInfo.mrFont.GetColor());
            const basegfx::BColor aBFontColor(aFontColor.getBColor());

			// prepare wordLineMode (for underline and strikeout)
			// NOT for bullet texts. It is set (this may be an error by itself), but needs to be suppressed to hinder e.g. '1)'
			// to be splitted which would not look like the original
			const bool bWordLineMode(rInfo.mrFont.IsWordLineMode() && !rInfo.mbEndOfBullet);

			// prepare new primitive
			drawinglayer::primitive2d::BasePrimitive2D* pNewPrimitive = 0;
			const bool bDecoratedIsNeeded(
				   UNDERLINE_NONE != rInfo.mrFont.GetOverline()
				|| UNDERLINE_NONE != rInfo.mrFont.GetUnderline()
				|| STRIKEOUT_NONE != rInfo.mrFont.GetStrikeout()
				|| EMPHASISMARK_NONE != (rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_STYLE)
				|| RELIEF_NONE != rInfo.mrFont.GetRelief()
				|| rInfo.mrFont.IsShadow()
                || bWordLineMode);

			if(bDecoratedIsNeeded)
			{
				// TextDecoratedPortionPrimitive2D needed, prepare some more data
				// get overline and underline color. If it's on automatic (0xffffffff) use FontColor instead
                const Color aUnderlineColor(rInfo.maTextLineColor);
                const basegfx::BColor aBUnderlineColor((0xffffffff == aUnderlineColor.GetColor()) ? aBFontColor : aUnderlineColor.getBColor());
                const Color aOverlineColor(rInfo.maOverlineColor);
                const basegfx::BColor aBOverlineColor((0xffffffff == aOverlineColor.GetColor()) ? aBFontColor : aOverlineColor.getBColor());

                // prepare overline and underline data
                const drawinglayer::primitive2d::TextLine eFontOverline(
					drawinglayer::primitive2d::mapFontUnderlineToTextLine(rInfo.mrFont.GetOverline()));
                const drawinglayer::primitive2d::TextLine eFontUnderline(
					drawinglayer::primitive2d::mapFontUnderlineToTextLine(rInfo.mrFont.GetUnderline()));

                // check UndelineAbove
				const bool bUnderlineAbove(
					drawinglayer::primitive2d::TEXT_LINE_NONE != eFontUnderline && impIsUnderlineAbove(rInfo.mrFont));

				// prepare strikeout data
				const drawinglayer::primitive2d::TextStrikeout eTextStrikeout(
					drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rInfo.mrFont.GetStrikeout()));

				// prepare emphasis mark data
				drawinglayer::primitive2d::TextEmphasisMark eTextEmphasisMark(drawinglayer::primitive2d::TEXT_EMPHASISMARK_NONE);

				switch(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_STYLE)
				{
					case EMPHASISMARK_DOT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DOT; break;
					case EMPHASISMARK_CIRCLE : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_CIRCLE; break;
					case EMPHASISMARK_DISC : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_DISC; break;
					case EMPHASISMARK_ACCENT : eTextEmphasisMark = drawinglayer::primitive2d::TEXT_EMPHASISMARK_ACCENT; break;
				}

				const bool bEmphasisMarkAbove(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_POS_ABOVE);
				const bool bEmphasisMarkBelow(rInfo.mrFont.GetEmphasisMark() & EMPHASISMARK_POS_BELOW);

				// prepare font relief data
				drawinglayer::primitive2d::TextRelief eTextRelief(drawinglayer::primitive2d::TEXT_RELIEF_NONE);

				switch(rInfo.mrFont.GetRelief())
				{
					case RELIEF_EMBOSSED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_EMBOSSED; break;
					case RELIEF_ENGRAVED : eTextRelief = drawinglayer::primitive2d::TEXT_RELIEF_ENGRAVED; break;
					default : break; // RELIEF_NONE, FontRelief_FORCE_EQUAL_SIZE
				}

				// prepare shadow/outline data
				const bool bShadow(rInfo.mrFont.IsShadow());

				// TextDecoratedPortionPrimitive2D is needed, create one
                pNewPrimitive = new drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D(
	                
					// attributes for TextSimplePortionPrimitive2D
					aNewTransform,
					rInfo.mrText, 
					rInfo.mnTextStart, 
					rInfo.mnTextLen,
					aDXArray,
					aFontAttribute,
					rInfo.mpLocale ? *rInfo.mpLocale : ::com::sun::star::lang::Locale(),
					aBFontColor,

					// attributes for TextDecoratedPortionPrimitive2D
                    aBOverlineColor,
                    aBUnderlineColor,
                    eFontOverline,
                    eFontUnderline,
					bUnderlineAbove,
					eTextStrikeout,
					bWordLineMode,
					eTextEmphasisMark,
					bEmphasisMarkAbove,
					bEmphasisMarkBelow,
					eTextRelief,
					bShadow);
			}
			else
			{
				// TextSimplePortionPrimitive2D is enough
				pNewPrimitive = new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
					aNewTransform,
					rInfo.mrText, 
					rInfo.mnTextStart, 
					rInfo.mnTextLen,
					aDXArray,
					aFontAttribute,
					rInfo.mpLocale ? *rInfo.mpLocale : ::com::sun::star::lang::Locale(),
					aBFontColor);
			}

            if(rInfo.mbEndOfBullet)
            {
                // embed in TextHierarchyBulletPrimitive2D
	            const drawinglayer::primitive2d::Primitive2DReference aNewReference(pNewPrimitive);
	            const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(&aNewReference, 1);
			    pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(aNewSequence);
            }

            if(rInfo.mpFieldData)
            {
                pNewPrimitive = impCheckFieldPrimitive(pNewPrimitive, rInfo);
            }

            maTextPortionPrimitives.push_back(pNewPrimitive);

            // support for WrongSpellVector. Create WrongSpellPrimitives as needed
            if(rInfo.mpWrongSpellVector && !aDXArray.empty())
            {
                const sal_uInt32 nSize(rInfo.mpWrongSpellVector->size());
                const sal_uInt32 nDXCount(aDXArray.size());
                const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded

                for(sal_uInt32 a(0); a < nSize; a++)
                {
                    const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a];

                    if(rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart && rCandidate.nEnd > rCandidate.nStart)
                    {
                        const sal_uInt32 nStart(rCandidate.nStart - rInfo.mnTextStart);
                        const sal_uInt32 nEnd(rCandidate.nEnd - rInfo.mnTextStart);
                        double fStart(0.0);
                        double fEnd(0.0);

                        if(nStart > 0 && nStart - 1 < nDXCount)
                        {
                            fStart = aDXArray[nStart - 1];
                        }

                        if(nEnd > 0 && nEnd - 1 < nDXCount)
                        {
                            fEnd = aDXArray[nEnd - 1];
                        }

                        if(!basegfx::fTools::equal(fStart, fEnd))
                        {
                            if(rInfo.IsRTL())
                            {
                                // #i98523#
                                // When the portion is RTL, mirror the redlining using the
                                // full portion width
                                const double fTextWidth(aDXArray[aDXArray.size() - 1]);

                                fStart = fTextWidth - fStart;
                                fEnd = fTextWidth - fEnd;
                            }

                            // need to take FontScaling out of values; it's already part of
                            // aNewTransform and would be double applied
                            const double fFontScaleX(aFontScaling.getX());
                            
                            if(!basegfx::fTools::equal(fFontScaleX, 1.0) 
                                && !basegfx::fTools::equalZero(fFontScaleX))
                            {
                                fStart /= fFontScaleX;
                                fEnd /= fFontScaleX;
                            }

                            maTextPortionPrimitives.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D(
                                aNewTransform,
                                fStart,
                                fEnd,
                                aSpellColor));
                        }
                    }
                }
            }
		}
	}

	drawinglayer::primitive2d::BasePrimitive2D* impTextBreakupHandler::impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) const
    {
        if(rInfo.mpFieldData)
        {
            // Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D
			// which holds the field type and evtl. the URL
            const SvxURLField* pURLField = dynamic_cast< const SvxURLField* >(rInfo.mpFieldData);
            const SvxPageField* pPageField = dynamic_cast< const SvxPageField* >(rInfo.mpFieldData);

			// embed current primitive to a sequence
            drawinglayer::primitive2d::Primitive2DSequence aSequence;

			if(pPrimitive)
			{
				aSequence.realloc(1);
				aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive);
			}

			if(pURLField)
			{
				pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_URL, pURLField->GetURL());
			}
			else if(pPageField)
			{
				pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_PAGE, String());
			}
			else
			{
				pPrimitive = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(aSequence, drawinglayer::primitive2d::FIELD_TYPE_COMMON, String());
			}
        }

        return pPrimitive;
    }

    void impTextBreakupHandler::impFlushTextPortionPrimitivesToLinePrimitives()
    {
		// only create a line primitive when we had content; there is no need for
		// empty line primitives (contrary to paragraphs, see below).
		if(!maTextPortionPrimitives.empty())
		{
	        drawinglayer::primitive2d::Primitive2DSequence aLineSequence(impConvertVectorToPrimitive2DSequence(maTextPortionPrimitives));
		    maTextPortionPrimitives.clear();
			maLinePrimitives.push_back(new drawinglayer::primitive2d::TextHierarchyLinePrimitive2D(aLineSequence));
		}
    }

    void impTextBreakupHandler::impFlushLinePrimitivesToParagraphPrimitives()
    {
		// ALWAYS create a paragraph primitive, even when no content was added. This is done to
		// have the correct paragraph count even with empty paragraphs. Those paragraphs will
		// have an empty sub-PrimitiveSequence.
        drawinglayer::primitive2d::Primitive2DSequence aParagraphSequence(impConvertVectorToPrimitive2DSequence(maLinePrimitives));
        maLinePrimitives.clear();
        maParagraphPrimitives.push_back(new drawinglayer::primitive2d::TextHierarchyParagraphPrimitive2D(aParagraphSequence));
    }

    void impTextBreakupHandler::impHandleDrawPortionInfo(const DrawPortionInfo& rInfo)
    {
        impCreateTextPortionPrimitive(rInfo);

        if(rInfo.mbEndOfLine || rInfo.mbEndOfParagraph)
        {
            impFlushTextPortionPrimitivesToLinePrimitives();
        }

        if(rInfo.mbEndOfParagraph)
        {
            impFlushLinePrimitivesToParagraphPrimitives();
        }
    }

    void impTextBreakupHandler::impHandleDrawBulletInfo(const DrawBulletInfo& rInfo)
    {
		basegfx::B2DHomMatrix aNewTransform;

		// add size to new transform
		aNewTransform.scale(rInfo.maBulletSize.getWidth(), rInfo.maBulletSize.getHeight());

		// apply transformA
		aNewTransform *= maNewTransformA;

		// apply local offset
		aNewTransform.translate(rInfo.maBulletPosition.X(), rInfo.maBulletPosition.Y());

		// also apply embedding object's transform
		aNewTransform *= maNewTransformB;

        // prepare empty GraphicAttr
        const GraphicAttr aGraphicAttr;

        // create GraphicPrimitive2D
        const drawinglayer::primitive2d::Primitive2DReference aNewReference(new drawinglayer::primitive2d::GraphicPrimitive2D(
			aNewTransform,
            rInfo.maBulletGraphicObject,
            aGraphicAttr));

        // embed in TextHierarchyBulletPrimitive2D
        const drawinglayer::primitive2d::Primitive2DSequence aNewSequence(&aNewReference, 1);
	    drawinglayer::primitive2d::BasePrimitive2D* pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(aNewSequence);

        // add to output
        maTextPortionPrimitives.push_back(pNewPrimitive);
    }

	IMPL_LINK(impTextBreakupHandler, decomposeContourTextPrimitive, DrawPortionInfo*, pInfo)
	{
        // for contour text, ignore (clip away) all portions which are below
        // the visible area given by maScale
		if(pInfo && (double)pInfo->mrStartPos.Y() < maScale.getY())
		{
            impHandleDrawPortionInfo(*pInfo);
		}

		return 0;
	}

	IMPL_LINK(impTextBreakupHandler, decomposeBlockTextPrimitive, DrawPortionInfo*, pInfo)
	{
		if(pInfo)
		{
			// #SJ# Is clipping wanted? This is text clipping; only accept a portion
			// if it's completely in the range
			if(!maClipRange.isEmpty())
			{
				// Test start position first; this allows to not get the text range at
				// all if text is far outside
				const basegfx::B2DPoint aStartPosition(pInfo->mrStartPos.X(), pInfo->mrStartPos.Y());

				if(!maClipRange.isInside(aStartPosition))
				{
					return 0;
				}

				// Start position is inside. Get TextBoundRect and TopLeft next
				drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice;
				aTextLayouterDevice.setFont(pInfo->mrFont);

				const basegfx::B2DRange aTextBoundRect(
					aTextLayouterDevice.getTextBoundRect(
						pInfo->mrText, pInfo->mnTextStart, pInfo->mnTextLen));
				const basegfx::B2DPoint aTopLeft(aTextBoundRect.getMinimum() + aStartPosition);

				if(!maClipRange.isInside(aTopLeft))
				{
					return 0;
				}

				// TopLeft is inside. Get BottomRight and check
				const basegfx::B2DPoint aBottomRight(aTextBoundRect.getMaximum() + aStartPosition);

				if(!maClipRange.isInside(aBottomRight))
				{
					return 0;
				}

				// all inside, clip was successful
			}
            impHandleDrawPortionInfo(*pInfo);
		}

		return 0;
	}

	IMPL_LINK(impTextBreakupHandler, decomposeStretchTextPrimitive, DrawPortionInfo*, pInfo)
	{
		if(pInfo)
		{
            impHandleDrawPortionInfo(*pInfo);
		}

		return 0;
	}

	IMPL_LINK(impTextBreakupHandler, decomposeContourBulletPrimitive, DrawBulletInfo*, pInfo)
	{
		if(pInfo)
		{
            impHandleDrawBulletInfo(*pInfo);
		}

		return 0;
	}

	IMPL_LINK(impTextBreakupHandler, decomposeBlockBulletPrimitive, DrawBulletInfo*, pInfo)
	{
		if(pInfo)
		{
            impHandleDrawBulletInfo(*pInfo);
		}

		return 0;
	}

	IMPL_LINK(impTextBreakupHandler, decomposeStretchBulletPrimitive, DrawBulletInfo*, pInfo)
	{
		if(pInfo)
		{
            impHandleDrawBulletInfo(*pInfo);
		}

		return 0;
	}

    drawinglayer::primitive2d::Primitive2DSequence impTextBreakupHandler::getPrimitive2DSequence()
	{
        if(!maTextPortionPrimitives.empty())
        {
            // collect non-closed lines
            impFlushTextPortionPrimitivesToLinePrimitives();
        }

        if(!maLinePrimitives.empty())
        {
            // collect non-closed paragraphs
            impFlushLinePrimitivesToParagraphPrimitives();
        }

        return impConvertVectorToPrimitive2DSequence(maParagraphPrimitives);
	}
} // end of anonymous namespace

//////////////////////////////////////////////////////////////////////////////
// primitive decompositions

void SdrTextObj::impDecomposeContourTextPrimitive(
	drawinglayer::primitive2d::Primitive2DSequence& rTarget,
	const drawinglayer::primitive2d::SdrContourTextPrimitive2D& rSdrContourTextPrimitive,
	const drawinglayer::geometry::ViewInformation2D& aViewInformation) const
{
    // decompose matrix to have position and size of text
	basegfx::B2DVector aScale, aTranslate;
	double fRotate, fShearX;
	rSdrContourTextPrimitive.getObjectTransform().decompose(aScale, aTranslate, fRotate, fShearX);

	// prepare contour polygon, force to non-mirrored for layouting
	basegfx::B2DPolyPolygon aPolyPolygon(rSdrContourTextPrimitive.getUnitPolyPolygon());
	aPolyPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(fabs(aScale.getX()), fabs(aScale.getY())));

	// prepare outliner
	SdrOutliner& rOutliner = ImpGetDrawOutliner();
	const Size aNullSize;
	rOutliner.SetPaperSize(aNullSize);
	rOutliner.SetPolygon(aPolyPolygon);
	rOutliner.SetUpdateMode(true);
	rOutliner.SetText(rSdrContourTextPrimitive.getOutlinerParaObject());

	// set visualizing page at Outliner; needed e.g. for PageNumberField decomposition
	rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));

	// prepare matrices to apply to newly created primitives
	basegfx::B2DHomMatrix aNewTransformA;

	// mirroring. We are now in the polygon sizes. When mirroring in X and Y,
	// move the null point which was top left to bottom right.
	const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0));
	const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0));

	// in-between the translations of the single primitives will take place. Afterwards,
	// the object's transformations need to be applied
	const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
		bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0,
		fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));

	// now break up text primitives.
	impTextBreakupHandler aConverter(rOutliner);
	aConverter.decomposeContourTextPrimitive(aNewTransformA, aNewTransformB, aScale);

	// cleanup outliner
	rOutliner.Clear();
	rOutliner.setVisualizedPage(0);

	rTarget = aConverter.getPrimitive2DSequence();
}

void SdrTextObj::impDecomposeBlockTextPrimitive(
	drawinglayer::primitive2d::Primitive2DSequence& rTarget,
	const drawinglayer::primitive2d::SdrBlockTextPrimitive2D& rSdrBlockTextPrimitive,
	const drawinglayer::geometry::ViewInformation2D& aViewInformation) const
{
    // decompose matrix to have position and size of text
	basegfx::B2DVector aScale, aTranslate;
	double fRotate, fShearX;
	rSdrBlockTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX);

	// use B2DRange aAnchorTextRange for calculations
	basegfx::B2DRange aAnchorTextRange(aTranslate);
	aAnchorTextRange.expand(aTranslate + aScale);

	// prepare outliner
	const bool bIsCell(rSdrBlockTextPrimitive.getCellText());
	SdrOutliner& rOutliner = ImpGetDrawOutliner();
	SdrTextHorzAdjust eHAdj = rSdrBlockTextPrimitive.getSdrTextHorzAdjust();
	SdrTextVertAdjust eVAdj = rSdrBlockTextPrimitive.getSdrTextVertAdjust();
	const sal_uInt32 nOriginalControlWord(rOutliner.GetControlWord());
	const Size aNullSize;

	// set visualizing page at Outliner; needed e.g. for PageNumberField decomposition
	rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));
	rOutliner.SetFixedCellHeight(rSdrBlockTextPrimitive.isFixedCellHeight());
	rOutliner.SetControlWord(nOriginalControlWord|EE_CNTRL_AUTOPAGESIZE);
	rOutliner.SetMinAutoPaperSize(aNullSize);
	rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));

	// add one to rage sizes to get back to the old Rectangle and outliner measurements
	const sal_uInt32 nAnchorTextWidth(FRound(aAnchorTextRange.getWidth() + 1L));
	const sal_uInt32 nAnchorTextHeight(FRound(aAnchorTextRange.getHeight() + 1L));
	const bool bVerticalWritintg(rSdrBlockTextPrimitive.getOutlinerParaObject().IsVertical());
	const Size aAnchorTextSize(Size(nAnchorTextWidth, nAnchorTextHeight));

	if(bIsCell)
	{
		// cell text is formated neither like a text object nor like a object
		// text, so use a special setup here
		rOutliner.SetMaxAutoPaperSize(aAnchorTextSize);

        // #i106214# To work with an unchangeable PaperSize (CellSize in
        // this case) Set(Min|Max)AutoPaperSize and SetPaperSize have to be used.
        // #i106214# This was not completely correct; to still measure the real 
        // text height to allow vertical adjust (and vice versa for VerticalWritintg)
        // only one aspect has to be set, but the other one to zero
        if(bVerticalWritintg)
        {
            // measure the horizontal text size
    		rOutliner.SetMinAutoPaperSize(Size(0, aAnchorTextSize.Height()));
        }
        else
        {
            // measure the vertical text size
    		rOutliner.SetMinAutoPaperSize(Size(aAnchorTextSize.Width(), 0));
        }

        rOutliner.SetPaperSize(aAnchorTextSize);
		rOutliner.SetUpdateMode(true);
		rOutliner.SetText(rSdrBlockTextPrimitive.getOutlinerParaObject());
	}
	else
	{
	    // check if block text is used (only one of them can be true)
	    const bool bHorizontalIsBlock(SDRTEXTHORZADJUST_BLOCK == eHAdj && !bVerticalWritintg);
	    const bool bVerticalIsBlock(SDRTEXTVERTADJUST_BLOCK == eVAdj && bVerticalWritintg);

        // set minimal paper size hor/ver if needed
	    if(bHorizontalIsBlock)
	    {
		    rOutliner.SetMinAutoPaperSize(Size(nAnchorTextWidth, 0));
	    }
	    else if(bVerticalIsBlock)
	    {
		    rOutliner.SetMinAutoPaperSize(Size(0, nAnchorTextHeight));
	    }

        if((rSdrBlockTextPrimitive.getWordWrap() || IsTextFrame()) && !rSdrBlockTextPrimitive.getUnlimitedPage())
		{
            // #i103454# maximal paper size hor/ver needs to be limited to text
            // frame size. If it's block text, still allow the 'other' direction
            // to grow to get a correct real text size when using GetPaperSize(). 
            // When just using aAnchorTextSize as maximum, GetPaperSize()
            // would just return aAnchorTextSize again: this means, the wanted 
            // 'measurement' of the real size of block text would not work
        	Size aMaxAutoPaperSize(aAnchorTextSize);

		    if(bHorizontalIsBlock)
		    {
                // allow to grow vertical for horizontal blocks
                aMaxAutoPaperSize.setHeight(1000000);
		    }
		    else if(bVerticalIsBlock)
		    {
                // allow to grow horizontal for vertical blocks
                aMaxAutoPaperSize.setWidth(1000000);
		    }
            
            rOutliner.SetMaxAutoPaperSize(aMaxAutoPaperSize);
		}

		rOutliner.SetPaperSize(aNullSize);
		rOutliner.SetUpdateMode(true);
		rOutliner.SetText(rSdrBlockTextPrimitive.getOutlinerParaObject());
	}

    rOutliner.SetControlWord(nOriginalControlWord);

	// now get back the layouted text size from outliner
	const Size aOutlinerTextSiz(rOutliner.GetPaperSize());
	const basegfx::B2DVector aOutlinerScale(aOutlinerTextSiz.Width(), aOutlinerTextSiz.Height());
	basegfx::B2DVector aAdjustTranslate(0.0, 0.0);

	// For draw objects containing text correct hor/ver alignment if text is bigger
	// than the object itself. Without that correction, the text would always be
	// formatted to the left edge (or top edge when vertical) of the draw object.
	if(!IsTextFrame() && !bIsCell)
	{
		if(aAnchorTextRange.getWidth() < aOutlinerScale.getX() && !bVerticalWritintg)
		{
			// Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
			// else the alignment is wanted.
			if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
			{
				eHAdj = SDRTEXTHORZADJUST_CENTER;
			}
		}

		if(aAnchorTextRange.getHeight() < aOutlinerScale.getY() && bVerticalWritintg)
		{
			// Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
			// else the alignment is wanted.
			if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
			{
				eVAdj = SDRTEXTVERTADJUST_CENTER;
			}
		}
	}

	// correct horizontal translation using the now known text size
	if(SDRTEXTHORZADJUST_CENTER == eHAdj || SDRTEXTHORZADJUST_RIGHT == eHAdj)
	{
		const double fFree(aAnchorTextRange.getWidth() - aOutlinerScale.getX());

		if(SDRTEXTHORZADJUST_CENTER == eHAdj)
		{
			aAdjustTranslate.setX(fFree / 2.0);
		}

		if(SDRTEXTHORZADJUST_RIGHT == eHAdj)
		{
			aAdjustTranslate.setX(fFree);
		}
	}

	// correct vertical translation using the now known text size
	if(SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj)
	{
		const double fFree(aAnchorTextRange.getHeight() - aOutlinerScale.getY());

		if(SDRTEXTVERTADJUST_CENTER == eVAdj)
		{
			aAdjustTranslate.setY(fFree / 2.0);
		}
		
		if(SDRTEXTVERTADJUST_BOTTOM == eVAdj)
		{
			aAdjustTranslate.setY(fFree);
		}
	}

	// prepare matrices to apply to newly created primitives. aNewTransformA
	// will get coordinates in aOutlinerScale size and positive in X, Y.
	// Translate relative to given primitive to get same rotation and shear
	// as the master shape we are working on. For vertical, use the top-right
	// corner
	const double fStartInX(bVerticalWritintg ? aAdjustTranslate.getX() + aOutlinerScale.getX() : aAdjustTranslate.getX());
	const basegfx::B2DTuple aAdjOffset(fStartInX, aAdjustTranslate.getY());
    basegfx::B2DHomMatrix aNewTransformA(basegfx::tools::createTranslateB2DHomMatrix(aAdjOffset.getX(), aAdjOffset.getY()));

	// mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y,
	// move the null point which was top left to bottom right.
	const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0));
	const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0));

	// in-between the translations of the single primitives will take place. Afterwards,
	// the object's transformations need to be applied
	const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
		bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0,
		fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));

	// #SJ# create ClipRange (if needed)
	basegfx::B2DRange aClipRange;

	if(rSdrBlockTextPrimitive.getClipOnBounds())
	{
		aClipRange.expand(-aAdjOffset);
		aClipRange.expand(basegfx::B2DTuple(aAnchorTextSize.Width(), aAnchorTextSize.Height()) - aAdjOffset);
	}

	// now break up text primitives.
	impTextBreakupHandler aConverter(rOutliner);
	aConverter.decomposeBlockTextPrimitive(aNewTransformA, aNewTransformB, aClipRange);

	// cleanup outliner
	rOutliner.Clear();
	rOutliner.setVisualizedPage(0);

	rTarget = aConverter.getPrimitive2DSequence();
}

void SdrTextObj::impDecomposeStretchTextPrimitive(
	drawinglayer::primitive2d::Primitive2DSequence& rTarget, 
	const drawinglayer::primitive2d::SdrStretchTextPrimitive2D& rSdrStretchTextPrimitive,
	const drawinglayer::geometry::ViewInformation2D& aViewInformation) const
{
    // decompose matrix to have position and size of text
	basegfx::B2DVector aScale, aTranslate;
	double fRotate, fShearX;
	rSdrStretchTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX);

	// use non-mirrored B2DRange aAnchorTextRange for calculations
	basegfx::B2DRange aAnchorTextRange(aTranslate);
	aAnchorTextRange.expand(aTranslate + aScale);

	// prepare outliner
	SdrOutliner& rOutliner = ImpGetDrawOutliner();
	const sal_uInt32 nOriginalControlWord(rOutliner.GetControlWord());
	const Size aNullSize;

	rOutliner.SetControlWord(nOriginalControlWord|EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE);
	rOutliner.SetFixedCellHeight(rSdrStretchTextPrimitive.isFixedCellHeight());
	rOutliner.SetMinAutoPaperSize(aNullSize);
	rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
	rOutliner.SetPaperSize(aNullSize);
	rOutliner.SetUpdateMode(true);
	rOutliner.SetText(rSdrStretchTextPrimitive.getOutlinerParaObject());

	// set visualizing page at Outliner; needed e.g. for PageNumberField decomposition
	rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));

	// now get back the layouted text size from outliner
	const Size aOutlinerTextSiz(rOutliner.CalcTextSize());
	const basegfx::B2DVector aOutlinerScale(
		basegfx::fTools::equalZero(aOutlinerTextSiz.Width()) ? 1.0 : aOutlinerTextSiz.Width(), 
		basegfx::fTools::equalZero(aOutlinerTextSiz.Height()) ? 1.0 : aOutlinerTextSiz.Height());

	// prepare matrices to apply to newly created primitives
	basegfx::B2DHomMatrix aNewTransformA;

    // #i101957# Check for vertical text. If used, aNewTransformA
    // needs to translate the text initially around object width to orient
    // it relative to the topper right instead of the topper left
    const bool bVertical(rSdrStretchTextPrimitive.getOutlinerParaObject().IsVertical());

    if(bVertical)
    {
	    aNewTransformA.translate(aScale.getX(), 0.0);
    }

    // calculate global char stretching scale parameters. Use non-mirrored sizes
	// to layout without mirroring
	const double fScaleX(fabs(aScale.getX()) / aOutlinerScale.getX());
	const double fScaleY(fabs(aScale.getY()) / aOutlinerScale.getY());
	rOutliner.SetGlobalCharStretching((sal_Int16)FRound(fScaleX * 100.0), (sal_Int16)FRound(fScaleY * 100.0));

	// mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y,
	// move the null point which was top left to bottom right.
	const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0));
	const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0));

	// in-between the translations of the single primitives will take place. Afterwards,
	// the object's transformations need to be applied
	const basegfx::B2DHomMatrix aNewTransformB(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
		bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0,
		fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));

	// now break up text primitives.
	impTextBreakupHandler aConverter(rOutliner);
	aConverter.decomposeStretchTextPrimitive(aNewTransformA, aNewTransformB);

	// cleanup outliner
	rOutliner.SetControlWord(nOriginalControlWord);
	rOutliner.Clear();
	rOutliner.setVisualizedPage(0);

	rTarget = aConverter.getPrimitive2DSequence();
}

//////////////////////////////////////////////////////////////////////////////
// timing generators
#define ENDLESS_LOOP	(0xffffffff)
#define ENDLESS_TIME	((double)0xffffffff)
#define PIXEL_DPI		(96.0)

void SdrTextObj::impGetBlinkTextTiming(drawinglayer::animation::AnimationEntryList& rAnimList) const
{
	if(SDRTEXTANI_BLINK == GetTextAniKind())
	{
		// get values
		const SfxItemSet& rSet = GetObjectItemSet();
		const sal_uInt32 nRepeat((sal_uInt32)((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue());
		bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue());
		double fDelay((double)((SdrTextAniDelayItem&)rSet.Get(SDRATTR_TEXT_ANIDELAY)).GetValue());

		if(0.0 == fDelay)
		{
			// use default
			fDelay = 250.0;
		}

		// prepare loop and add
		drawinglayer::animation::AnimationEntryLoop  aLoop(nRepeat ? nRepeat : ENDLESS_LOOP);
        drawinglayer::animation::AnimationEntryFixed aStart(fDelay, 0.0);
		aLoop.append(aStart);
        drawinglayer::animation::AnimationEntryFixed aEnd(fDelay, 1.0);
		aLoop.append(aEnd);
		rAnimList.append(aLoop);

		// add stopped state if loop is not endless
		if(0L != nRepeat)
		{
            drawinglayer::animation::AnimationEntryFixed aStop(ENDLESS_TIME, bVisisbleWhenStopped ? 0.0 : 1.0);
			rAnimList.append(aStop);
		}
	}
}

void impCreateScrollTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, bool bForward, double fTimeFullPath, double fFrequency)
{
	bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue());
	bool bVisisbleWhenStarted(((SdrTextAniStartInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE )).GetValue());
	const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue());

	if(bVisisbleWhenStarted)
	{
		// move from center to outside
        drawinglayer::animation::AnimationEntryLinear aInOut(fTimeFullPath * 0.5, fFrequency, 0.5, bForward ? 1.0 : 0.0);
		rAnimList.append(aInOut);
	}

	// loop. In loop, move through
	if(nRepeat || 0L == nRepeat)
	{
		drawinglayer::animation::AnimationEntryLoop aLoop(nRepeat ? nRepeat : ENDLESS_LOOP);
        drawinglayer::animation::AnimationEntryLinear aThrough(fTimeFullPath, fFrequency, bForward ? 0.0 : 1.0, bForward ? 1.0 : 0.0);
		aLoop.append(aThrough);
		rAnimList.append(aLoop);
	}

	if(0L != nRepeat && bVisisbleWhenStopped)
	{
		// move from outside to center
        drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, bForward ? 0.0 : 1.0, 0.5);
		rAnimList.append(aOutIn);

		// add timing for staying at the end
        drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5);
		rAnimList.append(aEnd);
	}
}

void impCreateAlternateTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, double fRelativeTextLength, bool bForward, double fTimeFullPath, double fFrequency)
{
	if(basegfx::fTools::more(fRelativeTextLength, 0.5))
	{
		// this is the case when fTextLength > fFrameLength, text is bigger than animation frame.
		// In that case, correct direction
		bForward = !bForward;
	}

	const double fStartPosition(bForward ? fRelativeTextLength : 1.0 - fRelativeTextLength);
	const double fEndPosition(bForward ? 1.0 - fRelativeTextLength : fRelativeTextLength);
	bool bVisisbleWhenStopped(((SdrTextAniStopInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE)).GetValue());
	bool bVisisbleWhenStarted(((SdrTextAniStartInsideItem&)rSet.Get(SDRATTR_TEXT_ANISTOPINSIDE )).GetValue());
	const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue());

	if(!bVisisbleWhenStarted)
	{
		// move from outside to center
        drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, bForward ? 0.0 : 1.0, 0.5);
		rAnimList.append(aOutIn);
	}

	// loop. In loop, move out and in again. fInnerMovePath may be negative when text is bigger then frame,
	// so use absolute value
	const double fInnerMovePath(fabs(1.0 - (fRelativeTextLength * 2.0)));
	const double fTimeForInnerPath(fTimeFullPath * fInnerMovePath);
	const double fHalfInnerPath(fTimeForInnerPath * 0.5);
	const sal_uInt32 nDoubleRepeat(nRepeat / 2L);

	if(nDoubleRepeat || 0L == nRepeat)
	{
		// double forth and back loop
		drawinglayer::animation::AnimationEntryLoop aLoop(nDoubleRepeat ? nDoubleRepeat : ENDLESS_LOOP);
        drawinglayer::animation::AnimationEntryLinear aTime0(fHalfInnerPath, fFrequency, 0.5, fEndPosition);
		aLoop.append(aTime0);
        drawinglayer::animation::AnimationEntryLinear aTime1(fTimeForInnerPath, fFrequency, fEndPosition, fStartPosition);
		aLoop.append(aTime1);
        drawinglayer::animation::AnimationEntryLinear aTime2(fHalfInnerPath, fFrequency, fStartPosition, 0.5);
		aLoop.append(aTime2);
		rAnimList.append(aLoop);
	}

	if(nRepeat % 2L)
	{
		// repeat is uneven, so we need one more forth and back to center
        drawinglayer::animation::AnimationEntryLinear aTime0(fHalfInnerPath, fFrequency, 0.5, fEndPosition);
		rAnimList.append(aTime0);
        drawinglayer::animation::AnimationEntryLinear aTime1(fHalfInnerPath, fFrequency, fEndPosition, 0.5);
		rAnimList.append(aTime1);
	}

	if(0L != nRepeat)
	{
		if(bVisisbleWhenStopped)
		{
			// add timing for staying at the end
            drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5);
			rAnimList.append(aEnd);
		}
		else
		{
			// move from center to outside
            drawinglayer::animation::AnimationEntryLinear aInOut(fTimeFullPath * 0.5, fFrequency, 0.5, bForward ? 1.0 : 0.0);
			rAnimList.append(aInOut);
		}
	}
}

void impCreateSlideTiming(const SfxItemSet& rSet, drawinglayer::animation::AnimationEntryList& rAnimList, bool bForward, double fTimeFullPath, double fFrequency)
{
	// move in from outside, start outside
	const double fStartPosition(bForward ? 0.0 : 1.0);
	const sal_uInt32 nRepeat(((SdrTextAniCountItem&)rSet.Get(SDRATTR_TEXT_ANICOUNT)).GetValue());

	// move from outside to center
    drawinglayer::animation::AnimationEntryLinear aOutIn(fTimeFullPath * 0.5, fFrequency, fStartPosition, 0.5);
	rAnimList.append(aOutIn);

	// loop. In loop, move out and in again
	if(nRepeat > 1L || 0L == nRepeat)
	{
		drawinglayer::animation::AnimationEntryLoop aLoop(nRepeat ? nRepeat - 1L : ENDLESS_LOOP);
        drawinglayer::animation::AnimationEntryLinear aTime0(fTimeFullPath * 0.5, fFrequency, 0.5, fStartPosition);
		aLoop.append(aTime0);
        drawinglayer::animation::AnimationEntryLinear aTime1(fTimeFullPath * 0.5, fFrequency, fStartPosition, 0.5);
		aLoop.append(aTime1);
		rAnimList.append(aLoop);
	}

	// always visible when stopped, so add timing for staying at the end when not endless
	if(0L != nRepeat)
	{
        drawinglayer::animation::AnimationEntryFixed aEnd(ENDLESS_TIME, 0.5);
		rAnimList.append(aEnd);
	}
}

void SdrTextObj::impGetScrollTextTiming(drawinglayer::animation::AnimationEntryList& rAnimList, double fFrameLength, double fTextLength) const
{
	const SdrTextAniKind eAniKind(GetTextAniKind());

	if(SDRTEXTANI_SCROLL == eAniKind || SDRTEXTANI_ALTERNATE == eAniKind || SDRTEXTANI_SLIDE == eAniKind)
	{
		// get data. Goal is to calculate fTimeFullPath which is the time needed to
		// move animation from (0.0) to (1.0) state
		const SfxItemSet& rSet = GetObjectItemSet();
		double fAnimationDelay((double)((SdrTextAniDelayItem&)rSet.Get(SDRATTR_TEXT_ANIDELAY)).GetValue());
		double fSingleStepWidth((double)((SdrTextAniAmountItem&)rSet.Get(SDRATTR_TEXT_ANIAMOUNT)).GetValue());
		const SdrTextAniDirection eDirection(GetTextAniDirection());
		const bool bForward(SDRTEXTANI_RIGHT == eDirection || SDRTEXTANI_DOWN == eDirection);

		if(basegfx::fTools::equalZero(fAnimationDelay))
		{
			// default to 1/20 second
			fAnimationDelay = 50.0;
		}

		if(basegfx::fTools::less(fSingleStepWidth, 0.0))
		{
			// data is in pixels, convert to logic. Imply PIXEL_DPI dpi.
			// It makes no sense to keep the view-transformation centered
			// definitions, so get rid of them here.
			fSingleStepWidth = (-fSingleStepWidth * (2540.0 / PIXEL_DPI));
		}

		if(basegfx::fTools::equalZero(fSingleStepWidth))
		{
			// default to 1 milimeter
			fSingleStepWidth = 100.0;
		}

		// use the length of the full animation path and the number of steps
		// to get the full path time
		const double fFullPathLength(fFrameLength + fTextLength);
		const double fNumberOfSteps(fFullPathLength / fSingleStepWidth);
		double fTimeFullPath(fNumberOfSteps * fAnimationDelay);

		if(fTimeFullPath < fAnimationDelay)
		{
			fTimeFullPath = fAnimationDelay;
		}

		switch(eAniKind)
		{
			case SDRTEXTANI_SCROLL :
			{
				impCreateScrollTiming(rSet, rAnimList, bForward, fTimeFullPath, fAnimationDelay);
				break;
			}
			case SDRTEXTANI_ALTERNATE :
			{
				double fRelativeTextLength(fTextLength / (fFrameLength + fTextLength));
				impCreateAlternateTiming(rSet, rAnimList, fRelativeTextLength, bForward, fTimeFullPath, fAnimationDelay);
				break;
			}
			case SDRTEXTANI_SLIDE :
			{
				impCreateSlideTiming(rSet, rAnimList, bForward, fTimeFullPath, fAnimationDelay);
				break;
			}
			default : break; // SDRTEXTANI_NONE, SDRTEXTANI_BLINK
		}
	}
}

//////////////////////////////////////////////////////////////////////////////
// eof
