svgtopt/SVG/SVGImpl/src/SVGAnimateMotionElementImpl.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 07 Jan 2010 16:19:02 +0200
changeset 0 d46562c3d99d
permissions -rw-r--r--
Revision: 200951 Kit: 201001

/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  SVG Implementation source file
 *
*/


#if !defined(__E32BASE_H__)
#include <e32base.h>
#endif
#include <e32math.h>

#include "SVGAnimateMotionElementImpl.h"

#include "SVGElementImpl.h"
#include "SVGDocumentImpl.h"
#include "SVGSchemaData.h"

#include "GfxGeneralPath.h"
#include "GfxFlatteningPathIterator.h"
#include "SVGPathDataParser.h"
#include "SVGPointLexer.h"
#include "SVGStringTokenizer.h"

_LIT( AUTO, "auto" );
_LIT( AUTOREVERSE, "auto-reverse" );
_LIT( SEMICOLON, ";" );

// *******************************************************
// Constructor/deconstructor

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateMotionElementImpl* CSvgAnimateMotionElementImpl::NewL(  const TUint8 aElemID,
																  CSvgDocumentImpl* aDoc )
	{
	CSvgAnimateMotionElementImpl*   self    = new ( ELeave )
											  CSvgAnimateMotionElementImpl( aDoc );
	CleanupStack::PushL( self );
	self->ConstructL(  aElemID );
	CleanupStack::Pop();

	return self;
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateMotionElementImpl* CSvgAnimateMotionElementImpl::NewLC(  const TUint8 aElemID,
																   CSvgDocumentImpl* aDoc )
	{
	CSvgAnimateMotionElementImpl* self = new ( ELeave )
											  CSvgAnimateMotionElementImpl( aDoc );
	CleanupStack::PushL( self );
	self->ConstructL(  aElemID );

	return self;
	}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::ConstructL(  const TUint8 aElemID )
	{
	CSvgAnimationBase::ConstructL( aElemID );

	iMotionPath = CGfxGeneralPath::NewL();
	iAnimTime->SetCalMode( KAnimCalcModePaced ); // animateMotion has differenr default
	iReqAttrFlag=KSVG_AMINATEMO_ELEMFLAG;
	}



// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateMotionElementImpl::~CSvgAnimateMotionElementImpl()
    {
	if ( iMotionPath )
		{
		delete iMotionPath;
		iMotionPath = NULL;
		}
	if ( iPathIterator )
		{
		delete iPathIterator;
		iPathIterator = NULL;
		}
    }

// *******************************************************
// Private


// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateMotionElementImpl::CSvgAnimateMotionElementImpl( CSvgDocumentImpl* aDoc ) : CSvgAnimationBase( aDoc ),
                                                                                       iCurrentSeg( 0,
                                                                                                    0,
                                                                                                    0,
                                                                                                    0 ),
                                                                                       //iIsValues( EFalse ),
                                                                                       iPrevRotate(0)
                                                                                       
    {
    iAttrId = KAtrTransform;
    }

// *******************************************************
// From SVG DOM


// *******************************************************
// SVG Implementation


// *******************************************************
// From MSvgEventReceiver
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::ResetReferenceElementL()
    {
    if(iTargetElement != NULL )
    	{
    	if( ((iTargetElement->iAnimateAttrSet == NULL) ||
    	    (iTargetElement->iAnimateAttrSet->Find(iAttrId) == KErrNotFound) ) )
    		{
    		if ( iInitDone )
    			{
    			iCheckFirstAnim= ETrue;
    			SetToOriginalL();
    			if( !(iTargetElement->iAnimateAttrSet) )
    				{
                    iTargetElement->iAnimateAttrSet = new (ELeave) RArray<TUint32>(1);
                    }
                iTargetElement->iAnimateAttrSet->AppendL((TUint32)iAttrId);
    			}
    		}
        }
    }
// *******************************************************
// From MXmlElement

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::SetAttributeL( const TDesC& aName,
                                                  const TDesC& aValue )
    {
    _LIT( KTmpAttrName, "attributeName" );
    _LIT( KTmpPath, "path" );
    _LIT( KTmpRotate, "rotate" );
    _LIT( KTmpFrom, "from" );
    _LIT( KTmpTo, "to" );
    _LIT( KTmpValues, "values" );
    _LIT( KTmpBy, "by" );


    if ( aName == KTmpAttrName )
        {
        // Ignore 'attributeName' attribute
        }
    else if ( aName == KTmpPath )
        {
        iMotionPath->Reset();
		TSvgPathDataParser::ParsePathData( aValue, iMotionPath );

        CGfxPathIterator*   itr;
        TFloatFixPt              tmpcoords[6];
        iMotionPath->GetPathIteratorL( &iIdentTransform, itr );
        CleanupStack::PushL( itr );

        while ( !itr->IsDone() )
            {
            switch ( itr->CurrentSegment( tmpcoords ) )
                {
                case EGfxSegMoveTo:
                iToFloatX = tmpcoords[0];
                iToFloatY = tmpcoords[1];
                break;
                case EGfxSegLineTo:
                iToFloatX = tmpcoords[0];
                iToFloatY = tmpcoords[1];
                break;
                case EGfxSegQuadTo:
                iToFloatX = tmpcoords[2];
                iToFloatY = tmpcoords[3];
                break;
                case EGfxSegCubicTo:
                iToFloatX = tmpcoords[4];
                iToFloatY = tmpcoords[5];
                break;
                case EGfxSegClose:
                iToFloatX = tmpcoords[0]; //.
                iToFloatY = tmpcoords[1];
                }

            itr->NextL();
            }
        iPathSeen = ETrue;
        CleanupStack::PopAndDestroy();
		if(iReqAttrFlag == KAtrSVGAmo && (iMotionPath->PointTypeArray())->Count() != 0 )
			{
			iReqAttrFlag = 0;
			}
        }
	else if ( aName == KTmpRotate )
		{
		if ( aValue == AUTO )
			{
			iAnimMotionRotate = KAnimMotionRotateAuto;
			}
		else if ( aValue == AUTOREVERSE )
			{
			iAnimMotionRotate = KAnimMotionRotateAutoReverse;
			}
		else
			{
			TLex    lString ( aValue );
			if (lString.Val( iAnimMotionRotate )!= KErrNone)
				{
				iAnimMotionRotate= 0;
				}
			if ( iAnimMotionRotate < 0 )
				{
					// Note: A problem may occur if the value is less than -3600
	        iAnimMotionRotate += 3600;
				}
			iAnimMotionRotate %= 360;
			}
		}
    else if ( aName == KTmpFrom )
	    {
		if ( ! iHaveValues )
			{
			iNoFrom = EFalse;
			iMotionPath->Reset();
			TSvgPointLexer  svgplex ( aValue );
			TChar           com;
			TFloatFixPt          x, y;

            svgplex.GetNextPoint( com, x, y );
            svgplex.Cleanup();

			iOrgFromFloatX = iFromFloatX = x;
			iOrgFromFloatY = iFromFloatY = y;
			iMotionPath->MoveToL( x, y, ETrue );  // 'from' -> MoveTo
			}

		if(iReqAttrFlag == KAtrSVGAmo)
			{
			iReqAttrFlag = KAtrToBy;
			}
		else
			{
			iReqAttrFlag = 0;
			}
		}
    else if ( aName == KTmpBy )
	    {
		if ( !iHaveTo )
			{
			iHaveBy = ETrue;
			if(iReqAttrFlag == KAtrSVGAmo || iReqAttrFlag == KAtrToBy)
				{
				iReqAttrFlag = 0;
				}
		    if ( !iHaveValues )
			    {
	               TSvgPointLexer  svgplex ( aValue );
	            TChar           com;
		        TFloatFixPt          x, y;

                svgplex.GetNextPoint( com, x, y );
                svgplex.Cleanup();

                if ( iNoFrom )
	                {
		            iToFloatX = x;
			        iToFloatY = y;
				    iNoFrom = EFalse;
				    // this is taken from animate transforms.
				   iAdditive = KAdditiveSum;
				   iAdditiveOrg = KAdditiveSum;
					}
                else
	                {
		            iToFloatX = iFromFloatX + x;
			        iToFloatY = iFromFloatY + y;
				    }

	            CGfxPathIterator*   itr;
		        iMotionPath->GetPathIteratorL( &iIdentTransform, itr );
			    CleanupStack::PushL( itr );

				if ( itr->IsDone() )
					{
					TFloatFixPt lZero;
					// If the animation path is empty, fill with default value.
					iMotionPath->MoveToL( lZero, lZero, ETrue );
					}
				CleanupStack::PopAndDestroy( 1 ); // itr
				iMotionPath->LineToL( x, y, ETrue );  // 'by' -> LineTo
				}
			}

		if(iReqAttrFlag == KAtrSVGAmo && (iMotionPath->PointTypeArray())->Count() != 0 )
			{
			iReqAttrFlag = 0;
			}
	    }
	else if ( aName == KTmpTo )
		{
		if ( !iHaveValues )
			{

			// this is taken from animate transforms.
			if ( iNoFrom )
               {
	           iAdditive = KAdditiveSum;
			   iAdditiveOrg = KAdditiveSum;
			   }
			TSvgPointLexer  svgplex ( aValue );
			TChar           com;
			TFloatFixPt          x, y;
			iHaveTo = ETrue;
            svgplex.GetNextPoint( com, x, y );
            svgplex.Cleanup();

            iToFloatX = x;
			iToFloatY = y;
			CGfxPathIterator*   itr;
			iMotionPath->GetPathIteratorL( &iIdentTransform, itr );
			CleanupStack::PushL( itr );
			if ( itr->IsDone() )
				{
				TFloatFixPt lZero;
				// If the animation path is empty, fill with default value.
				// should this default be zero or object position
				iMotionPath->MoveToL( lZero, lZero, ETrue );
				}
			CleanupStack::PopAndDestroy( 1 ); // itr
			iMotionPath->LineToL( x, y, ETrue );  // 'to' -> LineTo
			}

		if(iReqAttrFlag == KAtrSVGAmo || iReqAttrFlag == KAtrToBy)
			{
			iReqAttrFlag = 0;
			}
		}
	else if ( aName == KTmpValues )
		{
		// Process only if Path values have not been seen
		if ( !iPathSeen )
		    {
    		TStringTokenizer    tkn     ( aValue, SEMICOLON );
    		TBool               first   = ETrue;
    		iHaveValues = ETrue;
    		iNoFrom = EFalse; //.
    		iMotionPath->Reset();
    		while ( tkn.HasMoreTokens() ) // 'values' is a set of coordinates
    			{
    			TSvgPointLexer  svgplex ( tkn.NextToken() );
    			TChar           com;
    			TFloatFixPt          x, y;
                svgplex.GetNextPoint( com, x, y );
                svgplex.Cleanup();

    			if ( first )
    				{
    				iMotionPath->MoveToL( x, y, ETrue );
    				iOrgFromFloatX = iFromFloatX = x; //.
    				iOrgFromFloatY = iFromFloatY = y;
    				first = EFalse;
    				}
    			else
    				{
    				iMotionPath->LineToL( x, y, ETrue );
    				}
    			iToFloatX = x; //.
    			iToFloatY = y;
    			}

    		if(iReqAttrFlag == KAtrSVGAmo || iReqAttrFlag == KAtrToBy)
    			{
    			iReqAttrFlag = 0;
    			}
		    }
		}
    else
	    {
		return CSvgAnimationBase::SetAttributeL( aName, aValue );
		}

	return KErrNone;
    }

// ---------------------------------------------------------------------------
// From MSvgEventReceiver
// ---------------------------------------------------------------------------
TBool CSvgAnimateMotionElementImpl::ReceiveEventL( MSvgEvent* aEvent )
    {
    return CSvgAnimationBase::ReceiveEventProcL( aEvent, this );
    }

// ---------------------------------------------------------------------------
// From CSvgAnimationBase
// ---------------------------------------------------------------------------
//
TBool CSvgAnimateMotionElementImpl::AnimProcL( MSvgTimerEvent* aEvent )

    {


  if((iAnimStatus != KAnimActive) || iDoFreeze)
	   {
	   if(iFill== KAnimFillFreeze && !iDoFreeze && iAnimStatus == KAnimFinished)
	   		{
	   		// calculate the freeze value.
	   		}
	   else
		   {
		   CSvgAnimationBase::CheckForEndTimesAndFreezeL(this);
		   return EFalse;
		   }
	   }
    if ( ( iPathIterator == NULL ) || ( iPathIterator->IsDone() ) )
		{
        return EFalse;  // Already end of path. Nothing to do any more.
		}

    TFloatFixPt  nextPos, diff;
    TFloatFixPt  zero    ( 0 );

    // Get next position in [0..255] range
    TInt32  animatetime; // Not used...
    TInt32  valix, subanimtime;
    iAnimTime->GetAnimTime( (aEvent->Time()-iNegativeBeginTime), animatetime, valix, subanimtime );

    // Get next position in actual length
    TFloatFixPt  v2;
    if ( valix >= iValuesFloat->Count() - 1 )
		{
		valix= iValuesFloat->Count() - 1;
        v2 = ( *iValuesFloat )[valix];
		}
    else
		{
        v2 = ( *iValuesFloat )[valix + 1];
		}
    nextPos = CSvgAnimationBase::BlendFloat( subanimtime,
                                             ( *iValuesFloat )[valix],
                                             v2 );

    diff = nextPos - iCurrentPos;
    TGfxSegType SegType;

    while ( iSubPos + diff > iSubLength && !iPathIterator->IsDone() )
        {
        if ( iSubLength < zero )
			{
            iSubLength = zero;
			}
        TFloatFixPt  tmpcoords[6];
        diff -= iSubLength - iSubPos;
        iPathIterator->NextL();
        SegType = iPathIterator->CurrentSegment( tmpcoords );
        iCurrentSeg.iX1 = iCurrentSeg.iX2;
        iCurrentSeg.iY1 = iCurrentSeg.iY2;
        iCurrentSeg.iX2 = tmpcoords[0];
        iCurrentSeg.iY2 = tmpcoords[1];

        if ( SegType == EGfxSegMoveTo )
			{
            iSubLength = zero;
			}
        else
			{
            iSubLength = iCurrentSeg.Length();
			}

        iSubPos = zero;
        }
    iSubPos += diff;

    // Calcualate or set rotation
    TReal32 rot = 0.0f;
    if ( iAnimMotionRotate < 0 )
        {
        TFloatFixPt  dx  = iCurrentSeg.iX1 - iCurrentSeg.iX2;
        if ( dx == zero )
        {

			if( iAnimMotionRotate == KAnimMotionRotateAuto )
			{
				if(iPrevRotate == 0 || iPrevRotate >= 3.1415926f)
					rot = 3.1415926f + 1.5707963f;
				else
					rot = 1.5707963f; // pi/2
			}
			else // AutoReverse
			{
				if(iPrevRotate >= 0 )
					rot = 1.5707963f;
				else
					rot = -1.5707963f;

            }
		}
        else
            {
            TReal   atan;
            Math::ATan( atan, ( TReal32 )( iCurrentSeg.iY1 - iCurrentSeg.iY2 ), ( TReal32 )dx );
            rot = ( TReal32 ) atan;
			if ( iAnimMotionRotate == KAnimMotionRotateAuto )
				{
				rot += 3.1415926f;
				}

			}
		iPrevRotate = rot;
        }
    else
        {
        rot = iAnimMotionRotate * 3.1415926f / 180.0f;
        }

    // Create transform
    MSvgTransformList*  trList;
    TInt32              matrixIndex;
    iTargetElement->GetTransform( trList );
    iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex );
    // new position
    TInt32  subalpha;
    if ( iSubLength == zero )
		{
        subalpha = 0;
		}
    else
		{
        subalpha = ( TInt32 ) ( iSubPos / iSubLength * TFloatFixPt( 255 ) );  // need to make sure value does not exceed 0x7fff
		}
    if ( subalpha > 0xff )
		{
        subalpha = 0xff;
		}
    if ( subalpha < 0 )
		{
        subalpha = 0;
		}

    TFloatFixPt  trnsx, trnsy;
    trnsx = CSvgAnimationBase::BlendFloat( subalpha,
                                           iCurrentSeg.iX1,
                                           iCurrentSeg.iX2 );
    trnsy = CSvgAnimationBase::BlendFloat( subalpha,
                                           iCurrentSeg.iY1,
                                           iCurrentSeg.iY2 );

    TGfxAffineTransform deltaTr = TGfxAffineTransform::GetTranslateInstance( trnsx,
                                                                             trnsy );
    if ( rot != 0.0f )
        {
        deltaTr.Rotate( rot );
        }

    // Set transform

    if ( iAccumulate == KAccumSum ) //.
        {
        TGfxAffineTransform accumulateDeltaTr = TGfxAffineTransform::GetTranslateInstance( iFromFloatX - iOrgFromFloatX, iFromFloatY - iOrgFromFloatY);
        deltaTr.Concatenate( accumulateDeltaTr );
        }

    if ( iAdditive == KAdditiveSum ) //.
        {
        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate( deltaTr );
        trList->ReplaceItem( curMatrix, matrixIndex );
        }
    else
        {
        trList->ReplaceItem( deltaTr, matrixIndex );

        }
	if(iFill== KAnimFillFreeze)
		{
	 	iEndMatrix = deltaTr;
		}
    // update current position
    iCurrentPos = nextPos;

	 	CSvgAnimationBase::CheckForEndTimesAndFreezeL(this);
    return ETrue;
    }


//
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::ResetAnimationL()
    {
    TFloatFixPt  tmpcoords[6];

    // Path iterator
    if ( iPathIterator )
        {
        delete iPathIterator;
        iPathIterator = NULL;
        }

    iPathIterator = CGfxFlatteningPathIterator::NewL( iMotionPath,
                                                      &iIdentTransform,
                                                      3 );


    // path length
    iPathIterator->CurrentSegment( tmpcoords );
    iCurrentSeg.iX1 = tmpcoords[0];
    iCurrentSeg.iY1 = tmpcoords[1];
    iCurrentSeg.iX2 = tmpcoords[0];
    iCurrentSeg.iY2 = tmpcoords[1];

    iSubLength = -1;
    iCurrentPos = 0;
    iSubPos = 0;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::InitAnimationL()
    {
	if(!iTargetElement)
		{
		// if target element is not found then remove it.
		((CSvgDocumentImpl*)iOwnerDocument)->RemoveFromEventReceiverList(this);
		((CSvgDocumentImpl*)iOwnerDocument)->Engine()->UpdatePresentation(1);
		return;
		}

    TFloatFixPt len;
    TFloatFixPt lx, ly;
    TFloatFixPt dx, dy, int0x7f( KMAXFLOATFIX );
    // Create values of distance from start point on motion path
    TFloatFixPt  tmpcoords[6];
        {
        CGfxGeneralPath*    path    = CGfxGeneralPath::NewLC();
        CGfxPathIterator*   itr;
        iMotionPath->GetPathIteratorL( &iIdentTransform, itr );

        CleanupStack::PushL( itr );
        TFloatFixPt  length;
		iValuesFloat->Reset();
        while ( !itr->IsDone() )
            {
            switch ( itr->CurrentSegment( tmpcoords ) )
                {
                case EGfxSegMoveTo:
                path->MoveToL( tmpcoords[0], tmpcoords[1], ETrue );
                lx = tmpcoords[0];
                ly = tmpcoords[1];
                len = TSvgPathDataParser::PathLengthL( path );
                break;
                case EGfxSegLineTo:
                path->LineToL( tmpcoords[0], tmpcoords[1], ETrue );
                dx = lx - tmpcoords[0];
                dy = ly - tmpcoords[1];
                if ( dx > int0x7f || dy > int0x7f )
                    {
                    // calculate as integer
                    TInt32 tmplen, tx, ty;
                    tx = ( TInt32 ) dx;
                    ty = ( TInt32 ) dy;
	#ifdef SVG_FLOAT_BUILD
                    tmplen = TFloatFixPt::Sqrt(tx * tx + ty * ty);
	#else
                    tmplen = TFloatFixPt::FixedSqrtGeneral( tx * tx + ty * ty, 0 );
	#endif
                    len += TFloatFixPt( tmplen );
                    }
                else
                    {
                    // calculate as TFixPt
	
                    len += TFloatFixPt::Sqrt( dx * dx + dy * dy );
                    }
                lx = tmpcoords[0];
                ly = tmpcoords[1];

                break;
                case EGfxSegQuadTo:
                path->QuadToL( tmpcoords[0],
                               tmpcoords[1],
                               tmpcoords[2],
                               tmpcoords[3],
                               ETrue );
                len = TSvgPathDataParser::PathLengthL( path );
                break;
                case EGfxSegCubicTo:
                path->CubicToL( tmpcoords[0],
                                tmpcoords[1],
                                tmpcoords[2],
                                tmpcoords[3],
                                tmpcoords[4],
                                tmpcoords[5],
                                ETrue );
                len = TSvgPathDataParser::PathLengthL( path );
                break;
                case EGfxSegClose:
                path->LineToL( tmpcoords[0], tmpcoords[1], ETrue );
                len = TSvgPathDataParser::PathLengthL( path );
				break;
                }

            length = len;
            //length = TSvgPathDataParser::PathLengthL( path );
            iValuesFloat->AppendL( length );
            itr->NextL();
            }
        CleanupStack::PopAndDestroy( 2 ); // path, itr
        }

    CSvgAnimationBase::InitAnimationL();
    if(!iKeyTimesPresent)
    iAnimTime->CreateKeyTime( iMotionPath->PointTypeArray()->Count() );
    iAnimTime->PrepareTimeL( iValuesFloat );
	SetFillValueL();
    this->ResetAnimationL();
    }


// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetFillValueL()
    {
    iPrevRotate = 0;
    MSvgTransformList* trList = NULL;
    if ( iTargetElement )
        {
        ((CSvgElementImpl*)iTargetElement)->GetTransform( trList );
        TInt32 matrixIndex = -1;
        iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex );
        ((CSvgElementImpl*)iTargetElement)->GetTransform( trList );
        if ( trList && matrixIndex != -1 )
            {
            iFillMatrix = trList->GetItem(matrixIndex);
            }
        }
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetToOriginalL()
    {
    MSvgTransformList*  trList;
    TInt32              matrixIndex;
	if (iTargetElement == NULL)
		{
		return;
		}
    iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex );
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );


        trList->ReplaceItem( iFillMatrix, matrixIndex );


    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetToInitialValueL()
    {
    MSvgTransformList*  trList;
    TInt32              matrixIndex;
    iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex );
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );

    if( iAdditive == KAdditiveSum)
    	{
        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate(iFillMatrix);
       	trList->ReplaceItem( curMatrix, matrixIndex );
    	}
    else
    	{
         trList->ReplaceItem( iFillMatrix, matrixIndex );
    	}
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetToEndValueL()
    {
    MSvgTransformList*  trList;
    TInt32              matrixIndex;
    iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex );
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );

	 if( iAdditive == KAdditiveSum)
    	{
        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate(iEndMatrix);
       	trList->ReplaceItem( curMatrix, matrixIndex );
    	}
    else
    	{
         trList->ReplaceItem( iEndMatrix, matrixIndex );
    	}
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetAccumulateValues()
    {
    TFloatFixPt              lDelta;
	if(iHaveBy)
		{

		lDelta = iToFloatX - iFromFloatX;
	    iToFloatX = iToFloatX + lDelta;
	    iFromFloatX = iFromFloatX + lDelta;

	    lDelta = iToFloatY - iFromFloatY;
	    iToFloatY = iToFloatY + lDelta;
	    iFromFloatY = iFromFloatY + lDelta;

		}
	else
		{
	    lDelta = iToFloatX - iFromFloatX;
	    iFromFloatX = iToFloatX + iOrgFromFloatX;
	    iToFloatX = iFromFloatX + lDelta;

	    lDelta = iToFloatY - iFromFloatY;
	    iFromFloatY = iToFloatY + iOrgFromFloatY;
	    iToFloatY = iFromFloatY + lDelta;
	    }
    }

// ---------------------------------------------------------------------------
// From MXmlElementOpt
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::GetAttributePath( const TInt /* aNameId */,
                                                     CGfxGeneralPath*& /* aValue */ )
    {
    return KErrNoAttribute;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::SetAttributePathL( const TInt aNameId,
                                                      CGfxGeneralPath* aValue )
    {
    if ( aNameId == KAtrData )
        {
        iMotionPath->Reset();
        CGfxPathIterator*   lIter   = NULL;
        aValue->GetPathIteratorL( &iIdentTransform, lIter );
        CleanupStack::PushL( lIter );
        iMotionPath->AppendL( lIter );
        CleanupStack::PopAndDestroy( 1 ); //lIter
        }

    return KErrNone;
    }


// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::SetAttributePathRef( const TInt aNameId,
                                              CGfxGeneralPath*&  aValue  )
    {
	iIsMotionPath= EFalse;
    if ( aNameId == KAtrAnimateMotion )
        {
		if(iMotionPath)
			{
			delete iMotionPath;
			iMotionPath= NULL;
			}
		iMotionPath= aValue;

		if((iMotionPath->PointTypeArray())->Count() != 0 )
			{
			CGfxPathIterator*   itr = NULL;
			TFloatFixPt              tmpcoords[6];
			TRAPD( error,iMotionPath->GetPathIteratorL( &iIdentTransform, itr ) );
			if (error!= KErrNone)
				{
				return error;
				}



			while ( !itr->IsDone() )
				{
				switch ( itr->CurrentSegment( tmpcoords ) )
					{
					case EGfxSegMoveTo:
					iToFloatX = tmpcoords[0];
					iToFloatY = tmpcoords[1];
					break;
					case EGfxSegLineTo:
					iToFloatX = tmpcoords[0];
					iToFloatY = tmpcoords[1];
					break;
					case EGfxSegQuadTo:
					iToFloatX = tmpcoords[2];
					iToFloatY = tmpcoords[3];
					break;
					case EGfxSegCubicTo:
					iToFloatX = tmpcoords[4];
					iToFloatY = tmpcoords[5];
					break;
					case EGfxSegClose:
					iToFloatX = tmpcoords[0];
					iToFloatY = tmpcoords[1];
                    }

                TRAPD( error, itr->NextL() );
                if ( error != KErrNone )
                    {
                    delete itr;
                    return KErrNone;
                    }
                }

            delete itr;
            itr= NULL;


     		RArray<TFloatFixPt>* lArrayFix;
			lArrayFix= iMotionPath->PointCoordsArrayAll();
			if (lArrayFix)
				{
				iOrgFromFloatX = iFromFloatX = lArrayFix->operator[](0);
				iOrgFromFloatY = iFromFloatY = lArrayFix->operator[](1);
				}

			}
		}

    else
        {
        return KErrNoAttribute;
        }

    return KErrNone;
    }
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetAnimRotate(TInt16 aRotate)
	{
	iAnimMotionRotate= aRotate;
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::SetAttributeIntL( const TInt aNameId, const TInt32 aValue)
{
	if(aNameId == KAtrRotate)
		{
		iAnimMotionRotate = (TInt16)aValue;
		return KErrNone;
		}
	return CSvgAnimationBase::SetAttributeIntL(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::GetAttributeIntL( const TInt aNameId, TInt32& aValue )
{
	if(aNameId == KAtrRotate)
		{
		aValue = (TInt)(iAnimMotionRotate);
		return KErrNone;
		}
	return CSvgAnimationBase::GetAttributeIntL(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::SetAttributeFloatL(const TInt aNameId, TFloatFixPt aValue )
{
	return CSvgAnimationBase::SetAttributeFloatL(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateMotionElementImpl::GetAttributeFloat(const TInt aNameId, TFloatFixPt& aValue )
{
	return CSvgAnimationBase::GetAttributeFloat(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::ReInitializeAnimation()
    {

	if ( iAttrId == 0xffff )
        return;

	if( iCurrentRepeatCount > 0 && iAccumulate == KAccumSum )
		{
		iFromFloatX= iOrgFromFloatX;
		iFromFloatY= iOrgFromFloatY;
		iToFloatX= iOrgToFloatX;
		iToFloatY= iOrgToFloatY;
		}

    CSvgAnimationBase::ReInitializeAnimation();

	iCurrentSeg.iX1 = (TFloatFixPt) 0;
	iCurrentSeg.iX2 = (TFloatFixPt) 0;
	iCurrentSeg.iY1 = (TFloatFixPt) 0;
	iCurrentSeg.iY2 = (TFloatFixPt) 0;
	MSvgTransformList*  trList;
	TInt32              matrixIndex = 0;

	if (iTargetElement)
		{
		TRAPD(error ,iTargetElement->GetAttributeIntL( KAtrAnimMotionMatrixIndex, matrixIndex ));
		if ( error != KErrNone )
		   {
		   // ignore trap error
	      }
		( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );
		if( trList && (trList->NumberOfItems() >  matrixIndex) )
			{
			trList->ReplaceItem( TGfxAffineTransform(), matrixIndex );

			trList->SetAdditive( iAdditive, matrixIndex );
			}
		}
	iFillMatrix= TGfxAffineTransform();
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void  CSvgAnimateMotionElementImpl::SetOriginalValues_DOMReuse()
	{
	iOrgToFloatX= iToFloatX;
	iOrgToFloatY= iToFloatY;
    // calling base class function.
	CSvgAnimationBase::SetOriginalValues_DOMReuse();
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
CGfxGeneralPath* CSvgAnimateMotionElementImpl::GetPathAttribute(TInt aAttributeId)
	{
	if(aAttributeId == KAtrPath)
		{
		return iMotionPath;
		}
	else
		{
		return CSvgAnimationBase::GetPathAttribute(aAttributeId);
		}
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetPathAttribute(TInt aAttributeId, CGfxGeneralPath* aPathHandle)
{

	if(aAttributeId == KAtrPath)
		{
		if(iMotionPath == aPathHandle)
			{
			return;
			}
		delete iMotionPath;
		iMotionPath = aPathHandle;

		CGfxPathIterator*   itr = NULL;
        TFloatFixPt              tmpcoords[6];
        TRAPD(error ,iMotionPath->GetPathIteratorL( &iIdentTransform, itr ));
        if ( error != KErrNone )
		   {
		   // ignore trap error
	       }

		if(itr)
			{
        while ( !itr->IsDone() )
            {
            switch ( itr->CurrentSegment( tmpcoords ) )
                {
                case EGfxSegMoveTo:
                iToFloatX = tmpcoords[0];
                iToFloatY = tmpcoords[1];
                break;
                case EGfxSegLineTo:
                iToFloatX = tmpcoords[0];
                iToFloatY = tmpcoords[1];
                break;
                case EGfxSegQuadTo:
                iToFloatX = tmpcoords[2];
                iToFloatY = tmpcoords[3];
                break;
                case EGfxSegCubicTo:
                iToFloatX = tmpcoords[4];
                iToFloatY = tmpcoords[5];
                break;
                case EGfxSegClose:
                iToFloatX = tmpcoords[0]; //.
                iToFloatY = tmpcoords[1];
                    }
                TRAPD( error, itr->NextL() );
                if ( error != KErrNone )
                    {
                    delete itr;
                    return;
                    }
                }

			delete itr;
			}

		RArray<TFloatFixPt>* lArrayFix;
		lArrayFix= iMotionPath->PointCoordsArrayAll();
		if (lArrayFix)
			{
			iOrgFromFloatX = iFromFloatX = lArrayFix->operator[](0);
			iOrgFromFloatY = iFromFloatY = lArrayFix->operator[](1);
			}

		}
	else
		{
		CSvgAnimationBase::SetPathAttribute(aAttributeId, aPathHandle);
		}
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::Reset(MSvgEvent* aEvent)
{
	iIsUserSeek = ETrue;
	// first call the animation base function.
	TSvgTimerEvent* timerEvent  = ( TSvgTimerEvent* ) aEvent;
	if((TInt32)timerEvent->Time() < iAbsoluteBeginTime)
		{
		// let it come to initial position.
		((CSvgDocumentImpl*)iOwnerDocument)->iInitialDrawFlag = ETrue;
		ReInitializeAnimation();
		return;
		}
	TRAPD(error,CSvgAnimationBase::ResetL( aEvent, this));

	if (error != KErrNone)
	{
		// error processing not processed
		return;
	}
}


/////////////////////////////////////////////
MXmlElement* CSvgAnimateMotionElementImpl::CloneL(MXmlElement*
aParentElement)
	{
	CSvgAnimateMotionElementImpl* newElement = CSvgAnimateMotionElementImpl::NewL(  this->ElemID(),
																((CSvgDocumentImpl*)iOwnerDocument) );
	CleanupStack::PushL( newElement );
	newElement->iParentNode = aParentElement;
	// copy the data
	// end copying data from this class.
	// this will get cloned setting the parent element to aParentElement;
	newElement->iOwnerDocument = this->iOwnerDocument;
	// set the target element this needs to be modified.
	newElement->iTargetElement = (CSvgElementImpl*)aParentElement;
	this->CopyL(newElement);
	CleanupStack::Pop();
	return newElement;
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::CopyL(CSvgAnimateMotionElementImpl* aDestElement )
    {
	if(aDestElement)
	{


    // copy stuff from superclass
    this->CSvgAnimationBase::CopyL(aDestElement);

    // copy the reference to idoc (CSvgDocumentImpl)
    aDestElement->iOwnerDocument = this->iOwnerDocument;

    /*Need to check Test whether Copying is proper*/

	aDestElement->iFillMatrix = this->iFillMatrix;
	if(this->iMotionPath)
		{
		/*Motion Path and iPathIterator assignment needs to be checked.*/
        aDestElement->iMotionPath->Reset();
        aDestElement->iMotionPath->SetPointCoordsArrayL(this->iMotionPath->PointCoordsArrayAll());
        aDestElement->iMotionPath->SetPointTypeArrayL(this->iMotionPath->PointTypeArray());
        }
	aDestElement->iIdentTransform = this->iIdentTransform;
    aDestElement->iSubLength = this->iSubLength;
    aDestElement->iCurrentPos = this->iCurrentPos;
    aDestElement->iSubPos = this->iSubPos;
    aDestElement->iCurrentSeg = this->iCurrentSeg;
    aDestElement->iAnimMotionRotate = this->iAnimMotionRotate;
    aDestElement->iEndMatrix = this->iEndMatrix;
    //aDestElement->iIsValues = this->iIsValues;
    aDestElement->iToFloatX = this->iToFloatX;
    aDestElement->iToFloatY = this->iToFloatY;
    aDestElement->iFromFloatX = this->iFromFloatX;
    aDestElement->iFromFloatY = this->iFromFloatY;
    aDestElement->iOrgFromFloatX = this->iOrgFromFloatX;
    aDestElement->iOrgFromFloatY = this->iOrgFromFloatY;
		// for DOM Reuse
	aDestElement->iOrgToFloatX = this->iOrgToFloatX;
    aDestElement->iOrgToFloatY = this->iOrgToFloatY;
	aDestElement->iIsMotionPath = this->iIsMotionPath;

	if(this->iPathIterator)
		{
		aDestElement->ResetAnimationL();
		}
	}
   }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::DeactivateAnimation()
{
CSvgAnimationBase::DeactivateAnimation(this);
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
TBool CSvgAnimateMotionElementImpl::DoAnimProcL(MSvgEvent* aEvent)
{
return this->AnimProcL((MSvgTimerEvent*)aEvent);
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::SetAccumulateValuesForSetMediaTime()
{
if(iAccumulate == KAccumSum )
		{
		iFromFloatX= iOrgFromFloatX;
		iFromFloatY= iOrgFromFloatY;
		iToFloatX= iOrgToFloatX;
		iToFloatY= iOrgToFloatY;

		TInt i=0;
		while(i < iCurrentRepeatCount )
			{
			SetAccumulateValues();
			i++;
			}
		}
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateMotionElementImpl::Print( TBool aIsEncodeOn )
{
	if (!aIsEncodeOn)
	{
		#ifdef _DEBUG
		RDebug::Printf("<animateMotion calcMode=\"hmm\" xlink:href=\"hmm\" path=\"hmm\" keyPoints=\"hmm\" rotate=\"%d\"/>",
		/*Href(),*/ (int)iAnimMotionRotate);
		#endif
	}
}