svgtopt/SVG/SVGImpl/src/SVGAnimateTransformElementImpl.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:46:06 +0200
changeset 2 0c844a8549ae
parent 0 d46562c3d99d
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* 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 "SVGAnimateTransformElementImpl.h"

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

#include "SVGPointLexer.h"
#include "SVGStringTokenizer.h"

#include "GfxAffineTransform.h"

_LIT( SEMICOLON, ";" );


// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateTransformElementImpl* CSvgAnimateTransformElementImpl::NewL(  const TUint8 aElemID,
																		CSvgDocumentImpl* aDoc )
	{
	CSvgAnimateTransformElementImpl*self    = new ( ELeave )
											  CSvgAnimateTransformElementImpl( aDoc );

	CleanupStack::PushL( self );
	self->ConstructL(  aElemID );
	CleanupStack::Pop();

	return self;
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateTransformElementImpl* CSvgAnimateTransformElementImpl::NewLC(  const TUint8 aElemID,
																		 CSvgDocumentImpl* aDoc )
	{
	CSvgAnimateTransformElementImpl*self    = new ( ELeave )
											  CSvgAnimateTransformElementImpl( aDoc );

	CleanupStack::PushL( self );
	self->ConstructL(  aElemID );

	return self;
	}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::ConstructL(  const TUint8 aElemID)
	{
	CSvgAnimationBase::ConstructL( aElemID );

	// Initial length of values is 2 (from and to)
	iTransformValues = new ( ELeave ) RArray<TMatrixData>( 2 );
    TMatrixData mtrx;
    iTransformValues->AppendL( mtrx );
    iTransformValues->AppendL( mtrx );

    iOrgTransformValues = new ( ELeave ) RArray<TMatrixData>( 2 );

    iOrgTransformValues->AppendL( mtrx );
    iOrgTransformValues->AppendL( mtrx );


	iAccumMatrixData.iData[0] = 0;
	iAccumMatrixData.iData[1] = 0;
	iAccumMatrixData.iData[2] = 0;

	iReqAttrFlag=KSVG_ANIMATETRANSFORM_ELEMFLAG;



	}




// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateTransformElementImpl::~CSvgAnimateTransformElementImpl()
    {
    if ( iTransformValues )
		{
        iTransformValues->Close();
	    delete iTransformValues;
	    iTransformValues = NULL;
		}
	if ( iOrgTransformValues )
		{
        iOrgTransformValues->Close();
	    delete iOrgTransformValues;
	    iOrgTransformValues = NULL;

		}
    }

// ---------------------------------------------------------------------------
// Private


// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CSvgAnimateTransformElementImpl::CSvgAnimateTransformElementImpl( CSvgDocumentImpl* aDoc ) : CSvgAnimationBase( aDoc ),

                                                                                             iMatrixDataSize( 2 ),
																							 iMultipleRendering (EFalse)
    {
    iDataType = KSvgTypeTranslate;
    }

// ---------------------------------------------------------------------------
// From MSvgEventReceiver
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::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 CSvgAnimateTransformElementImpl::SetAttributeL( const TDesC& aName,
                                                     const TDesC& aValue )
    {
    _LIT( KTmpAttrName, "attributeName" );
    _LIT( KTmpTransform, "transform" );
    _LIT( KTmpFrom, "from" );
    _LIT( KTmpTo, "to" );
    _LIT( KTmpBy, "by" );
    _LIT( KTmpType, "type" );
    _LIT( KTmpScale, "scale" );
    _LIT( KTmpRotate, "rotate" );
    _LIT( KTmpSkewX, "skewX" );
    _LIT( KTmpSkewY, "skewY" );
    _LIT( KTmpValues, "values" );
    _LIT( KTmpGradientTransform, "gradientTransform");

    	if ( !iTargetSet )
			{
			iTargetElement = ( CSvgElementImpl * ) ParentNode();// default is parent element
			iTargetSet = ETrue;
			}
		   	TUint16 lElementId = 0;
		if (iTargetElement)
		    lElementId = iTargetElement->ElemID();
       if ( aName == KTmpAttrName )
	        {

			if(iReqAttrFlag == KAtrSVGTrf)
				{
				iReqAttrFlag = KAtrType;
				}
			else
				{
				iReqAttrFlag = 0;
				}
	    	if( aValue == KTmpTransform &&
				!(lElementId == KSvgRadialGradientElement || lElementId
				 == KSvgLinearGradientElement)
				 )
				{
				iAttrId = KAtrAnimateTransformAttrId;
	       		return KErrNone;
				}
			else if (aValue == KTmpGradientTransform &&
				(lElementId == KSvgRadialGradientElement || lElementId
				 == KSvgLinearGradientElement))
				{
				 iAttrId = KAtrAnimateTransformAttrId;
	       		 return KErrNone;
				}
			else if(aValue == KTmpGradientTransform) // Specifically for Xlink:href case
				{
				 iAttrId = KAtrGradientTransform;
				 return KErrNone;
				}
			else
	            {
	            // value must be not be 'transform'
	            iAttrId = 0xffff;
	            return KErrNone;
	            }
	        }
    else if ( aName == KTmpType )
        {

		if(iReqAttrFlag == KAtrSVGTrf)
			{
			iReqAttrFlag = KAtrAttributeName;
			}
		else
			{
			iReqAttrFlag = 0;
			}

        // Use iDataType to keep transformation type
        if ( aValue == KTmpScale )
            {
            iDataType = KSvgTypeScale;
            iMatrixDataSize = 2;
            }
        else if ( aValue == KTmpRotate )
            {
            iDataType = KSvgTypeRotate;
            iMatrixDataSize = 3;
            }
        else if ( aValue == KTmpSkewX )
            {
            iDataType = KSvgTypeSkewX;
            iMatrixDataSize = 1;
            }
        else if ( aValue == KTmpSkewY )
            {
            iDataType = KSvgTypeSkewY;
            iMatrixDataSize = 1;
            }
        else
            {
            iDataType = KSvgTypeTranslate;  // default transformation
            iMatrixDataSize = 2;
            }
        return KErrNone;
        }
    else if ( aName == KTmpFrom )
        {
        iNoFrom = EFalse;
        // Processing for semi-colon separated data is needed
        DesToMatrixData( aValue, ( *iTransformValues )[0] );
        return KErrNone;
        }
    else if ( aName == KTmpTo )
        {
        iHaveTo = ETrue;

        if ( iNoFrom )
            {
            iAdditive = KAdditiveSum;
            iAdditiveOrg = KAdditiveSum;
            }

        // Processing for semi-colon separated data is needed
        DesToMatrixData( aValue, ( *iTransformValues )[1] );
		iAccumMatrixData.iData[0] = (*iTransformValues)[1].iData[0];
		iAccumMatrixData.iData[1] = (*iTransformValues)[1].iData[1];
		iAccumMatrixData.iData[2] = (*iTransformValues)[1].iData[2];
        return KErrNone;
        }
    else if ( aName == KTmpBy )
        {
        if ( !iHaveTo )
            {
            TInt32  i;
            DesToMatrixData( aValue, ( *iTransformValues )[1] );
            iHaveBy = ETrue;

            if(iNoFrom)
                {
                iAdditive = KAdditiveSum;
                iAdditiveOrg = KAdditiveSum;
                }
            for ( i = 0; i < 3; i++ )
                {
                ( *iTransformValues )[1].iData[i] = ( *iTransformValues )[1].iData[i] +
                                                    ( *iTransformValues )[0].iData[i];
                }

            }
        return KErrNone;
        }
    else if ( aName == KTmpValues )
        {
        TStringTokenizer    tkn ( aValue, SEMICOLON );
        iTransformValues->Reset();

   		iHaveValues = ETrue;

        iNoFrom = EFalse;

        while ( tkn.HasMoreTokens() )
            {
            TMatrixData mtrx;
            DesToMatrixData( tkn.NextToken(), mtrx );
            iTransformValues->AppendL( mtrx );
            }
        TInt lTransformValuesCount = iTransformValues->Count();
		if(lTransformValuesCount > 0)
			{
			iAccumMatrixData.iData[0] = (*iTransformValues)[lTransformValuesCount - 1].iData[0];
			iAccumMatrixData.iData[1] = (*iTransformValues)[lTransformValuesCount - 1].iData[1];
			iAccumMatrixData.iData[2] = (*iTransformValues)[lTransformValuesCount - 1].iData[2];
			}

        return KErrNone;
        }

    return CSvgAnimationBase::SetAttributeL( aName, aValue );
    }

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

// ---------------------------------------------------------------------------
// From CSvgAnimationBase
// ---------------------------------------------------------------------------

TBool CSvgAnimateTransformElementImpl::AnimProcL( MSvgTimerEvent* aEvent )

    {


  if((iAnimStatus != KAnimActive) || iDoFreeze)
	   {
	   if(iFill== KAnimFillFreeze && !iDoFreeze && iAnimStatus == KAnimFinished)
	   		{

	   		}
	   else
		   {
		   CSvgAnimationBase::CheckForEndTimesAndFreezeL(this );
		   return EFalse;
		   }
	   }
    // No animation if 'from' or 'to' is not available
    if ( iTransformValues->Count() < 2 )
		{
        return EFalse;
		}

    // Calc alpha from time [0-255]
    TInt32  alpha;
    TInt32  valix1, valix2, subanimtime;
    TMatrixData mdata;

    iAnimTime->GetAnimTime((aEvent->Time()-iNegativeBeginTime), alpha, valix1, subanimtime );

 // check for the range of valix
	if ( valix1 >= iTransformValues->Count() )
		{
        valix1 = iTransformValues->Count() - 1;
		}


    if ( iNoFrom && !iHaveBy ) //. This is to emulate Adobe.
        {
        if ( alpha > ( KTimeMax >> 1 ) )
            {
            subanimtime = KTimeMax;
            }
        else
            {
            subanimtime = 0;
            return ETrue;
            }
        }

    if ( valix1 >= iTransformValues->Count() - 1 )
		{
        valix2 = valix1;
		}

    else
		{
        valix2 = valix1 + 1;
		}

	mdata.iData[0] = BlendFloat( subanimtime,
							   ( *iTransformValues )[valix1].iData[0],
							   ( *iTransformValues )[valix2].iData[0] );
	mdata.iData[1] = BlendFloat( subanimtime,
							   ( *iTransformValues )[valix1].iData[1],
							   ( *iTransformValues )[valix2].iData[1] );
	mdata.iData[2] = BlendFloat( subanimtime,
							   ( *iTransformValues )[valix1].iData[2],
							   ( *iTransformValues )[valix2].iData[2] );
    // Additive
    /*
     * !!!! Additive="replace" is not supported
     * !!!! Additional implementation needed in MSvgTransformList
     */

    // Set value
    TGfxAffineTransform deltaTr;
    switch ( iDataType )
        {
        case KSvgTypeTranslate:
        deltaTr = TGfxAffineTransform::GetTranslateInstance( mdata.iData[0],
                                                             mdata.iData[1] );
        break;
        case KSvgTypeScale:
        deltaTr = TGfxAffineTransform::GetScaleInstance( mdata.iData[0],
                                                         mdata.iData[1] );
        break;
        case KSvgTypeRotate:
        deltaTr = TGfxAffineTransform::GetRotateInstance( ( TReal32 )
                                                          mdata.iData[0] * 3.1415926f /
                                                          180.0f,
                                                          mdata.iData[1],
                                                          mdata.iData[2] );
        break;
        case KSvgTypeSkewX:
        deltaTr = TGfxAffineTransform::GetShearInstance( ( TReal32 )
                                                         mdata.iData[0]* 3.1415926f /
                                                         180.0f,
                                                         0.0f );
        break;
        case KSvgTypeSkewY:
        deltaTr = TGfxAffineTransform::GetShearInstance( 0.0f,
                                                         ( TReal32 )
                                                         mdata.iData[0]* 3.1415926f /
                                                         180.0f );
        break;
        }
    MSvgTransformList*  trList;
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );
    TInt32 matrixIndex;
    ( ( CSvgElementImpl * ) iTargetElement )->GetAttributeIntL( KAtrAnimTransformMatrixIndex, matrixIndex );
   if ( iAdditive == KAdditiveSum ) //.
        {
        if(iNoFrom && subanimtime == KTimeMax && !iHaveBy)
	        {
	        iTargetElement->SetOverwriteTransforms( ETrue );
	        }
		/*else
	        {
	        //if additive = sum and there is a from or a by then dont overwrite the transform
	        iTargetElement->iOverwriteTransforms = EFalse;
	        }*/
	    if(iHaveTo && iNoFrom)
	    {
	    	iTargetElement->SetOverwriteTransforms(ETrue);
	    	trList->ReplaceItem(deltaTr, matrixIndex);
	    }
	    else 
	    {
        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate( deltaTr );
        trList->ReplaceItem( curMatrix, matrixIndex );
	    }

        }
    else
        {
        iTargetElement->SetOverwriteTransforms( ETrue );
        trList->ReplaceItem( deltaTr, matrixIndex );

        }
    if(iFill == KAnimFillFreeze)
	    {
	    iEndMatrix = deltaTr;
	    }
	CSvgAnimationBase::CheckForEndTimesAndFreezeL(this );
    return ETrue;
    }

//
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::SetFillValueL()
    {
    MSvgTransformList*  trList;
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );
     TInt32              matrixIndex;
     iTargetElement->GetAttributeIntL( KAtrAnimTransformMatrixIndex, matrixIndex );
    iFillMatrix = trList->GetItem(matrixIndex);
    }

//
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::SetToOriginalL()
    {
    MSvgTransformList*  trList;
	TInt32 matrixIndex;
	iTargetElement->GetAttributeIntL( KAtrAnimTransformMatrixIndex, matrixIndex );
    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );

    trList->ReplaceItem( iFillMatrix /*TGfxAffineTransform()*/,
                             matrixIndex );
    iTargetElement->SetOverwriteTransforms( EFalse );
    }

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

    if( iAdditive == KAdditiveSum)
    	{

        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate(iFillMatrix);
       	trList->ReplaceItem( curMatrix, matrixIndex );
    	}
    else
    	{
    //	iTargetElement->iOverwriteTransforms = ETrue;
         trList->ReplaceItem( iFillMatrix, matrixIndex );
    	}


    }

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

	 if( iAdditive == KAdditiveSum)
    	{
		if(iNoFrom &&  !iHaveBy)
	        {
	        iTargetElement->SetOverwriteTransforms( ETrue );
	        }
	        if(iHaveTo && iNoFrom)
	        {
	        	iTargetElement->SetOverwriteTransforms(ETrue);
	        	trList->ReplaceItem(iEndMatrix, matrixIndex);
	        }
            else 
            {
        TGfxAffineTransform curMatrix = trList->GetItem( matrixIndex );
        curMatrix.Concatenate(iEndMatrix);
       	trList->ReplaceItem( curMatrix, matrixIndex );
            }
    	}
    else
    	{
    	iTargetElement->SetOverwriteTransforms( ETrue );
        trList->ReplaceItem( iEndMatrix, matrixIndex );
    	}

  }

//
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::InitAnimationL()
    {

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

	if (!iHaveValues)
		{
		if (!iHaveTo && !iHaveBy)
			{
			((CSvgDocumentImpl*)iOwnerDocument)->RemoveFromEventReceiverList(this );
            ((CSvgDocumentImpl*)iOwnerDocument)->Engine()->UpdatePresentation(1);
			}
		}


    CSvgAnimationBase::InitAnimationL();

	if(iMultipleRendering)
		{
		return;
		}

    // Set keytime
	iValuesFloat->Reset();
    TInt count = iTransformValues->Count();
    for ( TInt i = 0; i < count; i++ )
        {
        iValuesFloat->AppendL( TFloatFixPt( i ) ); // create dummy scalar array
        }
    if(!iKeyTimesPresent)
    iAnimTime->CreateKeyTime( iValuesFloat->Count() );
    iAnimTime->PrepareTimeL( iValuesFloat );
	SetFillValueL();

    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::SetAccumulateValues()
    {

	if ( !iNoFrom)
        {

        if (  iHaveBy )
	        {
	        TMatrixData delta;

			//0
	        delta.iData[0] = ( *iTransformValues )[1].iData[0] -
	                             ( *iTransformValues )[0].iData[0];

	        ( *iTransformValues )[0].iData[0] = ( *iTransformValues )[1].iData[0];

	        ( *iTransformValues )[1].iData[0] += delta.iData[0];

			//1
	        delta.iData[1] = ( *iTransformValues )[1].iData[1] -
	                             ( *iTransformValues )[0].iData[1];

	        ( *iTransformValues )[0].iData[1] = ( *iTransformValues )[1].iData[1];

	        ( *iTransformValues )[1].iData[1] += delta.iData[1];

			//2
	        delta.iData[2] = ( *iTransformValues )[1].iData[2] -
	                             ( *iTransformValues )[0].iData[2];

	        ( *iTransformValues )[0].iData[2] = ( *iTransformValues )[1].iData[2];

	        ( *iTransformValues )[1].iData[2] += delta.iData[2];

	        }
	        else
		        {
				TInt lTransformValuesCount = (*iTransformValues).Count();
				for(int i=0;i<lTransformValuesCount;i++)
					{
					(*iTransformValues)[i].iData[0] += iAccumMatrixData.iData[0];
					(*iTransformValues)[i].iData[1] += iAccumMatrixData.iData[1];
					(*iTransformValues)[i].iData[2] += iAccumMatrixData.iData[2];
					}
				}
        }
	else
		{
		if (  iHaveBy )
	        {
	        TMatrixData delta;

			//0
	        delta.iData[0] = ( *iTransformValues )[1].iData[0] -
	                             ( *iTransformValues )[0].iData[0];

	        ( *iTransformValues )[0].iData[0] = ( *iTransformValues )[1].iData[0];

	        ( *iTransformValues )[1].iData[0] += delta.iData[0];

			//1
	        delta.iData[1] = ( *iTransformValues )[1].iData[1] -
	                             ( *iTransformValues )[0].iData[1];

	        ( *iTransformValues )[0].iData[1] = ( *iTransformValues )[1].iData[1];

	        ( *iTransformValues )[1].iData[1] += delta.iData[1];

			//2
	        delta.iData[2] = ( *iTransformValues )[1].iData[2] -
	                             ( *iTransformValues )[0].iData[2];

	        ( *iTransformValues )[0].iData[2] = ( *iTransformValues )[1].iData[2];

	        ( *iTransformValues )[1].iData[2] += delta.iData[2];

	        }

		}

    }


// *******************************************************
// AnimateTransformElementImpl specific methods
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::DesToMatrixData( const TDesC& aDes,
                                                       TMatrixData& aMatrixData )
    {
    TSvgPointLexer  svgplex ( aDes );
    TInt            i       = 0;

    while ( !svgplex.IsDone() && i < 3 )
        {
        TChar   com;
        TFloatFixPt  data;
        TInt32  rslt    = svgplex.GetNext( com, data );
        if ( rslt != KErrNone )
            break;
        aMatrixData.iData[i] = data;
        i++;
        }
    svgplex.Cleanup();

    // Support shortened data expression
    if ( i < iMatrixDataSize )
        {
        TFloatFixPt  zero    ( 0 );
        switch ( iDataType )
            {
            case KSvgTypeTranslate:
            aMatrixData.iData[1] = zero;
            break;
            case KSvgTypeScale:
            aMatrixData.iData[1] = aMatrixData.iData[0];
            break;
            case KSvgTypeRotate:

            if ( (i + 1) < iMatrixDataSize )
				{
                aMatrixData.iData[1] = zero;
				}

            aMatrixData.iData[2] = zero;
            break;
            }
        }
     if( i > iMatrixDataSize)
     	{
     	// reset back everything. this is invalid value.
     	TFloatFixPt  zero    ( 0 );
     	aMatrixData.iData[0] = zero;
     	aMatrixData.iData[1] = zero;
     	aMatrixData.iData[2] = zero;
     	}
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::ResetAnimationL()
    {
    }

// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------

void  CSvgAnimateTransformElementImpl::SetMatrixDataSize(TUint8 aValue)
	{
	iMatrixDataSize= aValue;
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TBool  CSvgAnimateTransformElementImpl::SetMatrixData( TInt aIndex, TMatrixData& aMatrix)
	{
	if ( iTransformValues && aIndex < iTransformValues->Count() )
		{
		for (TInt i=0; i<3; i++)
			{
			(iTransformValues->operator[](aIndex)).iData[i]= aMatrix.iData[i];
			}
		return ETrue;
		}
	else
		{
		return EFalse;
		}
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
void  CSvgAnimateTransformElementImpl::SetTransformValues(RArray<TMatrixData>*&	aValues)
	{
	if (iTransformValues)
		{
		iTransformValues->Close();
		delete iTransformValues;
		iTransformValues= NULL;
		}
	iTransformValues= aValues;
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateTransformElementImpl::SetAttributeIntL( const TInt aNameId,const TInt32 aValue )
	{
	if(aNameId == KAtrType)
		{
		if ( aValue == KSvgTypeScale )
            {
            iDataType = KSvgTypeScale;
            iMatrixDataSize = 2;
            }
        else if ( aValue == KSvgTypeRotate )
            {
            iDataType = KSvgTypeRotate;
            iMatrixDataSize = 3;
            }
        else if ( aValue == KSvgTypeSkewX )
            {
            iDataType = KSvgTypeSkewX;
            iMatrixDataSize = 1;
            }
        else if ( aValue == KSvgTypeSkewY )
            {
            iDataType = KSvgTypeSkewY;
            iMatrixDataSize = 1;
            }
        else
            {
            iDataType = KSvgTypeTranslate;  // default transformation
            iMatrixDataSize = 2;
            }
		return KErrNone;
		}
	return CSvgAnimationBase::SetAttributeIntL(aNameId,aValue);
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateTransformElementImpl::GetAttributeIntL( const TInt aNameId, TInt32& aValue )
	{
	if(aNameId == KAtrType)
		{
		aValue = iDataType;
		return KErrNone;
		}
	return CSvgAnimationBase::GetAttributeIntL(aNameId,aValue);
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateTransformElementImpl::GetAttributeFloat(const TInt aNameId,TFloatFixPt& aValue )
{
	return CSvgAnimationBase::GetAttributeFloat(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
TInt CSvgAnimateTransformElementImpl::SetAttributeFloatL(const TInt aNameId,TFloatFixPt aValue )
{
	return CSvgAnimationBase::SetAttributeFloatL(aNameId,aValue);
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
// this function is for binary discrepancies
void CSvgAnimateTransformElementImpl::SetAccumMatrix()
{
	if(iHaveTo)
		{
		iAccumMatrixData.iData[0] = (*iTransformValues)[1].iData[0];
		iAccumMatrixData.iData[1] = (*iTransformValues)[1].iData[1];
		iAccumMatrixData.iData[2] = (*iTransformValues)[1].iData[2];
		}
	else
		{
		if(!iNoFrom)
			{
			TInt lTransformValuesCount = iTransformValues->Count();
			if(lTransformValuesCount > 0)
				{
				iAccumMatrixData.iData[0] = (*iTransformValues)[lTransformValuesCount - 1].iData[0];
				iAccumMatrixData.iData[1] = (*iTransformValues)[lTransformValuesCount - 1].iData[1];
				iAccumMatrixData.iData[2] = (*iTransformValues)[lTransformValuesCount - 1].iData[2];
				}
			}
		}
}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::ReInitializeAnimation()
    {

	if ( iAttrId == 0xffff )
        return;

    // Do not set Multiple Rendering flag if animation is not
    // initialised. This allows the Key Times array in the anim
    // time controller to be set correctly so that the 
    // interpolation happens correctly.
    if ( iInitDone )
        {
	    iMultipleRendering=  ETrue;        
        }

	if( iCurrentRepeatCount > 0 && iAccumulate == KAccumSum )
		{
		SetTransValues_DOMReuse();
		}


	CSvgAnimationBase::ReInitializeAnimation();

    if(iTargetElement)
	{
		TInt32 matrixIndex = -1;
		MSvgTransformList*  trList;
		( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );

		TGfxAffineTransform affineTransform;
 		TRAPD(error,iTargetElement->GetAttributeIntL( KAtrAnimTransformMatrixIndex, matrixIndex ));
	    if(error == KErrNone)
		    {
		    ( ( CSvgElementImpl * ) iTargetElement )->GetTransform( trList );
			if( trList && (trList->NumberOfItems() >  matrixIndex) )
				{
				trList->ReplaceItem(affineTransform,matrixIndex);
				}
			}

		}

		iFillMatrix= TGfxAffineTransform();

	}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void  CSvgAnimateTransformElementImpl::SetTransValues_DOMReuse()
	{
	if(iOrgTransformValues && iTransformValues)
		{
        iTransformValues->Reset();
        
        TInt orgTransformValCnt = iOrgTransformValues->Count();
		for(TInt i=0; i<orgTransformValCnt; i++)
			{
			 TMatrixData lMatrix;
			lMatrix.iData[0] = (*iOrgTransformValues)[i].iData[0];
     		lMatrix.iData[1] = (*iOrgTransformValues)[i].iData[1];
			lMatrix.iData[2] = (*iOrgTransformValues)[i].iData[2];

			iTransformValues->Append((TMatrixData) lMatrix);
			}
		}
	}
// ---------------------------------------------------------------------------
// Functions used by Decoder
// ---------------------------------------------------------------------------
void  CSvgAnimateTransformElementImpl::SetOriginalValues_DOMReuse()
	{

	if(  iAccumulate == KAccumSum )
		{
		if(iTransformValues && iOrgTransformValues)
			{
			iOrgTransformValues->Reset();
			
			TInt transformValCnt = iTransformValues->Count();
			for(TInt i=0; i<transformValCnt; i++)
				{
				 TMatrixData lMatrix;
				lMatrix.iData[0] = (*iTransformValues)[i].iData[0];
     			lMatrix.iData[1] = (*iTransformValues)[i].iData[1];
				lMatrix.iData[2] = (*iTransformValues)[i].iData[2];

				iOrgTransformValues->Append((TMatrixData) lMatrix);
				}
			}
		}

    // calling base class function.
	CSvgAnimationBase::SetOriginalValues_DOMReuse();
	}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
CGfxGeneralPath* CSvgAnimateTransformElementImpl::GetPathAttribute(TInt aAttributeId)
	{
	return CSvgAnimationBase::GetPathAttribute(aAttributeId);

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

		CSvgAnimationBase::SetPathAttribute(aAttributeId, aPathHandle);

}
// ---------------------------------------------------------------------------
// Set the values in the dom .
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::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* CSvgAnimateTransformElementImpl::CloneL(MXmlElement*
aParentElement)
	{

		CSvgAnimateTransformElementImpl* newElement = CSvgAnimateTransformElementImpl::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 CSvgAnimateTransformElementImpl::CopyL(CSvgAnimateTransformElementImpl* aDestElement )
    {
    // copy stuff from superclass
    if(aDestElement)
    {


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

	aDestElement->iMultipleRendering = this->iMultipleRendering;
	aDestElement->iMatrixDataSize = this->iMatrixDataSize;
	aDestElement->iFillMatrix = this->iFillMatrix;
	aDestElement->iEndMatrix = this->iEndMatrix;
	TMatrixData lTemp;

	TInt count = this->iTransformValues->Count() ;
	aDestElement->iTransformValues->Reset();
	for(TInt i=0; i<count; i++)
		{
        aDestElement->iTransformValues->AppendL(lTemp);
		aDestElement->iTransformValues->operator[](i).iData[0] =
this->iTransformValues->operator[](i).iData[0];
		aDestElement->iTransformValues->operator[](i).iData[1] =
this->iTransformValues->operator[](i).iData[1];
		aDestElement->iTransformValues->operator[](i).iData[2] =
this->iTransformValues->operator[](i).iData[2];
		}
	TInt count2 = this->iOrgTransformValues->Count();
	aDestElement->iOrgTransformValues->Reset();
	for(TInt i=0; i<count2; i++)
        {
        aDestElement->iOrgTransformValues->AppendL(lTemp);
        aDestElement->iOrgTransformValues->operator[](i).iData[0] =
this->iOrgTransformValues->operator[](i).iData[0];
		aDestElement->iOrgTransformValues->operator[](i).iData[1] =
this->iOrgTransformValues->operator[](i).iData[1];
		aDestElement->iOrgTransformValues->operator[](i).iData[2] =
this->iOrgTransformValues->operator[](i).iData[2];
		}
	aDestElement->iAccumMatrixData.iData[0] = this->iAccumMatrixData.iData[0];
	aDestElement->iAccumMatrixData.iData[1] = this->iAccumMatrixData.iData[1];
	aDestElement->iAccumMatrixData.iData[2] = this->iAccumMatrixData.iData[2];
    }
   }

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

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

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void CSvgAnimateTransformElementImpl::SetAccumulateValuesForSetMediaTime()
{
if(iAccumulate == KAccumSum )
		{

		SetTransValues_DOMReuse();

		SetAccumMatrix();
		TInt i=0;
		while(i < iCurrentRepeatCount )
			{
			// take care of the accum = sum.
			SetAccumulateValues();
			i++;
			}
		}
}

void CSvgAnimateTransformElementImpl::Print( TBool aIsEncodeOn )
{
	if (!aIsEncodeOn)
	{
		#ifdef _DEBUG
		RDebug::Printf("<animateTransform attributeName=\"hmm\" attributeType=\"hmm\" type=\"%d\" from=\"%d\" to=\"%d\" dur=\"hmm\" additive=\"hmm\" />",
		/*iDataType,*/ (int)iFromFloat, (int)iToFloat /*,iAccumulate*/);
		#endif
	}
}