breakdeps/SVGEngineImpl.cpp
author Tom Pritchard <tomp@symbian.org>
Tue, 19 Oct 2010 13:20:42 +0100
changeset 85 ee5d5928b136
parent 56 865fbeda552a
permissions -rw-r--r--
Cleaning up the tidying up of the startup

/*
* 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 Engine source file
 *
*/




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

#include <utf.h>
#include <s32mem.h>

#include "SVGDOMImplementationImpl.h"
#include "SVGElementImpl.h"
#include "SVGDocumentImpl.h"
#include "SVGSvgElementImpl.h"
#include "SVGUseElementImpl.h"
#include "SVGAnimationElementImpl.h"
#include "SVGTextElementImpl.h"

//#include "SVGAudioElementImpl.h"


#include "Gfx2dGcOpenVG.h"

#include "SVGSchemaData.h"
#include "SVGPathElementImpl.h"
#include "SVGAnimationBase.h"
#include "SVGElementTimeControl.h"

#include "SVGRequestObserver.h"
#include "SVGHyperlinkListener.h"
#include "SVGListener.h"
#include "SVGAnimationListener.h"
#include "SVGAElementImpl.h"
#include "SVGTextAreaElementImpl.h"

#include "SVGTimer.h"
#include "SVGEventHandler.h"
#include "SVGEngineImpl.h"
#include "SVGErrorImpl.h"

#include "SVGFloatCssValueImpl.h"
#include "SVGTimeContainer.h"
#include "SVGMediaAnimationElementImpl.h"

// Constants
// length of </text>
const TInt KClosingTextTagLength = 7;
// Length of </textArea>
const TInt KClosingTextAreaTagLength = 11;
// Length of <
const TInt KClosingBracesLength = 1;
// Number of chars to be converted at a time to Unicode
const TInt KMaxConversionChars = 20;
_LIT(KClosingTextTag,"</text>");
_LIT(KClosingTextAreaTag,"</textArea>");
_LIT(KClosingBraces,">");

// ---------------------------------------------------------------------------
// Two phase constructor for this class
// JSR 226 API
// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewL(CSvgBitmapFontProvider *aSvgBitmapFontProvider)
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl();
    CleanupStack::PushL( self );
    self->ConstructL(aSvgBitmapFontProvider);
    CleanupStack::Pop();
    return self;
    }


// --------------------------------------------------------------------------
// CSvgEngineImpl* CSvgEngineImpl::NewLC()
// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewLC(CSvgBitmapFontProvider *aSvgBitmapFontProvider)
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl();
    CleanupStack::PushL( self );
    self->ConstructL(aSvgBitmapFontProvider);
    return self;
    }

// --------------------------------------------------------------------------
// CSvgEngineImpl::CSvgEngineImpl() : iTextAreaHandle( NULL ),
// ---------------------------------------------------------------------------
CSvgEngineImpl::CSvgEngineImpl() : iTextAreaHandle( NULL ),
                                   iRequestObserver( NULL ),
                                   iFrameBuffer( NULL ),
                                   iFrameBufferSize(TSize(0,0)),
                                   iFontHashMap ( NULL ),
                                   iSvgDocument( NULL ),
                                   iBackgroundColor(0x00000000),
                                   iShowDebugInfo( EFalse ),
                                   iSvgEngineState(ESVGEngineNotStarted),
                                   iTimeoutSeconds( 0 ),
                                   iRenderQuality(2), // Set To Rendering quality "high"
                                   iCustomOption( ETrue ),
                                   iFrameBufferOverridesViewport( EFalse ),
                                   iClientDefinedViewPort(EFalse)
                                   
    {
    }


// --------------------------------------------------------------------------
// void CSvgEngineImpl::ConstructL()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ConstructL(CSvgBitmapFontProvider *aSvgBitmapFontProvider)
    {
    iGfxContext = NULL;

	iSvgBitmapFontProvider = aSvgBitmapFontProvider ; 
    // create CSvgErrorImpl object
    iSvgError = CSvgErrorImpl::NewL();

    iFontHashMap = CSvgFontHashMap::NewL();

    SetIgnoreUpdateScreen( EFalse );

   // The iCustomOption need to be initialized for JSR

	iCustomOption = ETrue;

    }



// ---------------------------------------------------------------------------
// Two phase constructor for this class
// Accepts a frame buffer and a MSvgRequestObserver object from the client
// Buffer is used for rasterization of SVG content
// Observer object, if provided, is used for notifying the client on updates
// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewL( CFbsBitmap* aFrameBuffer,
                                      MSvgRequestObserver* aReqObserver, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider )
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl( aFrameBuffer,
                                                             aReqObserver );
    CleanupStack::PushL( self );
    self->ConstructL(aFontSpec, aSvgBitmapFontProvider);
    CleanupStack::Pop();

    return self;
    }


// ---------------------------------------------------------------------------
// Two phase constructor for this class
// Accepts a frame buffer and a MSvgRequestObserver object from the client
// Buffer is used for rasterization of SVG content
// Observer object, if provided, is used for notifying the client on updates
// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewLC( CFbsBitmap* aFrameBuffer,
                                       MSvgRequestObserver* aReqObserver, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider )
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl( aFrameBuffer, aReqObserver );
    CleanupStack::PushL( self );
    self->ConstructL(aFontSpec, aSvgBitmapFontProvider);

    return self;
    }

// ---------------------------------------------------------------------------
// Symbian style private method that is used to construct heap objects
// Builds the Graphics device objects with the client's frame buffer info
// Builds the event handler object
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ConstructL( TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider)
    {
    iBitmapFontSpec = aFontSpec;
// iGfxContext is created through CSvgEngineInterfaceImpl::ConstructL
   // iGfxContext = CGfx2dGcVGR::NewL( iFrameBuffer->SizeInPixels(), iBitmapFontSpec );
    iSvgBitmapFontProvider = aSvgBitmapFontProvider ; 

    iGfxContext = CGfx2dGcOpenVG::NewL( iFrameBuffer->SizeInPixels(), iBitmapFontSpec, iSvgBitmapFontProvider );
    // create CSvgErrorImpl object
    iSvgError = CSvgErrorImpl::NewL();
    iFontHashMap = CSvgFontHashMap::NewL();
    iSvgNames = new (ELeave) CDesC16ArrayFlat(5);
    }

// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewL( CFbsBitmap* aFrameBuffer,
                                      MSvgRequestObserver* aReqObserver, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider ,SVGRendererId aRendererType)
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl( aFrameBuffer,
                                                             aReqObserver );
    CleanupStack::PushL( self );
    self->ConstructL(aFontSpec, aSvgBitmapFontProvider,aRendererType);
    CleanupStack::Pop();
	
    return self;
    }


// ---------------------------------------------------------------------------
// Two phase constructor for this class
// Accepts a frame buffer and a MSvgRequestObserver object from the client
// Buffer is used for rasterization of SVG content
// Observer object, if provided, is used for notifying the client on updates.
//This contains the renderer selector parameter
// ---------------------------------------------------------------------------
CSvgEngineImpl* CSvgEngineImpl::NewLC( CFbsBitmap* aFrameBuffer,
                                       MSvgRequestObserver* aReqObserver, TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider,SVGRendererId aRendererType )
    {
    CSvgEngineImpl* self    = new ( ELeave ) CSvgEngineImpl( aFrameBuffer, aReqObserver );
    CleanupStack::PushL( self );
    self->ConstructL(aFontSpec, aSvgBitmapFontProvider,aRendererType);

    return self;
    }

// ---------------------------------------------------------------------------
// Symbian style private method that is used to construct heap objects
// Builds the Graphics device objects with the client's frame buffer info
// Builds the event handler object.
//This contains the renderer selector parameter NGA
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ConstructL( TFontSpec& aFontSpec, CSvgBitmapFontProvider* aSvgBitmapFontProvider,SVGRendererId aRendererType)
    {
    iBitmapFontSpec = aFontSpec;
// iGfxContext is created through CSvgEngineInterfaceImpl::ConstructL
   // iGfxContext = CGfx2dGcVGR::NewL( iFrameBuffer->SizeInPixels(), iBitmapFontSpec );
    iSvgBitmapFontProvider = aSvgBitmapFontProvider ; 

    iGfxContext = CGfx2dGcOpenVG::NewL( iFrameBufferSize, iBitmapFontSpec, iSvgBitmapFontProvider ,aRendererType);
    // create CSvgErrorImpl object
    iSvgError = CSvgErrorImpl::NewL();
    iFontHashMap = CSvgFontHashMap::NewL();
    iSvgNames = new (ELeave) CDesC16ArrayFlat(5);
    }


// ---------------------------------------------------------------------------
// Private constructor
// Initializes private attributes
// ---------------------------------------------------------------------------
CSvgEngineImpl::CSvgEngineImpl( CFbsBitmap* aFrameBuffer,
                                MSvgRequestObserver* aReqObserver ) : iTextAreaHandle( NULL ),
                                                                      iRequestObserver( aReqObserver ),
                                                                      iFrameBuffer( aFrameBuffer ),
                                                                      iFrameBufferSize(TSize(0,0)),
                                                                      iFontHashMap ( NULL),
                                                                      iSvgDocument( NULL ),
                                                                      iBackgroundColor(0x00000000),
                                                                      iShowDebugInfo( EFalse ),
                                                                      iSvgEngineState(ESVGEngineNotStarted),
                                                                      iCustomOption( ETrue ),
                                                                      iFrameBufferOverridesViewport( EFalse )
                                                                      

    {
        if(aFrameBuffer && aFrameBuffer->Handle()>0)
            {
                iFrameBufferSize = aFrameBuffer->SizeInPixels();
            }
    }

// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
CSvgEngineImpl::~CSvgEngineImpl()
    {
    Destroy();

    if ( iFontHashMap )
    {
		delete iFontHashMap;
		iFontHashMap = NULL;
    }

	iSvgTextBoundingBoxes.ResetAndDestroy();
	iSvgTextBoundingBoxes.Close();

    if ( iGfxContext )
        {
        delete iGfxContext;
        iGfxContext = NULL;
        }
    if ( iSvgError )
        {
        delete iSvgError;
        iSvgError = NULL;
        }
    if (iTextAreaHandle)
    {
    delete iTextAreaHandle;
    iTextAreaHandle = NULL;
    }

    iTextAreaListeners.Close();
    iTextListeners.Close();
    iHyperlinkListeners.Close();
    iAnimationListeners.Close();
    iSvgMouseListeners.Close();
    iInteractiveElementListeners.Close();
    delete iSvgNames;
    }

// ---------------------------------------------------------------------------
// Draws aRootElement and calls itself for children.
// Handles switch element differently, as it only draws one of its children.
// ---------------------------------------------------------------------------

void CSvgEngineImpl::DrawElementsL( CSvgElementImpl* aRootElement)
    {
    if ( aRootElement != NULL)
        {
        TInt32 displayValue = 0;
        //  while we have next elements
        CSvgElementImpl* newElement = aRootElement;
        while( newElement != NULL )
            {
		    if(newElement->GetAttributeIntL( KCSS_ATTR_DISPLAY, displayValue ) == KErrNoAttribute)
		        {
		        newElement = ( CSvgElementImpl* ) newElement->FirstChild();
		        while ( newElement != NULL )
		            {
		            DrawElementsL( newElement );
		            newElement = ( CSvgElementImpl * ) newElement->NextSibling();
		            }
		            return;
		         }

            if(displayValue != KDisplayEnumNone) // is it a hidden element
                {
                CCssValue*  CssValue = NULL;
                TReal32 opacity = 1;

                // check visisbility
                TInt32  visbilityValue = 0;
                TInt visibility = newElement->GetAttributeIntL( KCSS_ATTR_VISIBILITY, visbilityValue );

                newElement->FindProperty( KCSS_ATTR_GROUP_OPACITY, CssValue, newElement );
                if ( CssValue )
                    {
                    opacity = ((CFloatCssValueImpl*)CssValue)->Value();
                    }

                if( opacity != 1 && !newElement->IsInherited( KCSS_ATTR_GROUP_OPACITY ) )
                    {
                    iGfxContext->BindToImageL();
                    // Group opacity
                    if ( newElement->ElemID() == KSvgGElement && newElement->FirstChild() )
                        {
                        // recurse with right context.
                        DrawElementsL( ( CSvgElementImpl* )newElement->FirstChild());
                        }
                    // Element opacity
                    else
                        {
                        TBool canDraw = ETrue;
                        if( (visibility == KErrNone) && (visbilityValue == 0) )
                            {
                            canDraw = newElement->DrawL( iGfxContext, NULL ) ;
                             }
                        if( canDraw && newElement->FirstChild() )
                            {
                            DrawElementsL( ( CSvgElementImpl* )newElement->FirstChild() );
                            }
                        }

                    // Blend opacity context buffer with parent's gfx context buffer
                    iGfxContext->UnbindFromImageL( opacity );
                    }
                else // no opacity or is inherited from above....
                    {
                    TBool canDraw = ETrue;
                    if( (visibility == KErrNone) && (visbilityValue == 0) )
                        {
                        canDraw = newElement->DrawL(iGfxContext, NULL );
                        }
                    if( canDraw && newElement->FirstChild() )
                        {
                        DrawElementsL( ( CSvgElementImpl* )newElement->FirstChild());
                        }
                    }
				}
            newElement = ( CSvgElementImpl * )newElement->NextSibling();

            }// end while....
        }
    }

//--------------------------------------------------------------------
//CFbsBitmap* CSvgEngineImpl::CreateOpacityFrameBufferL()
//--------------------------------------------------------------------
CFbsBitmap* CSvgEngineImpl::CreateOpacityFrameBufferL()
{
    CFbsBitmap* bitmap = new ( ELeave ) CFbsBitmap();

    if ( iFrameBuffer != NULL )
        {
/*NGA reverse*/if ( bitmap->Create( iFrameBufferSize, EColor16MU ) != KErrNone )
            {
            delete bitmap;
            bitmap = NULL;
            }
        }
    return bitmap;
    }

// ---------------------------------------------------------------------------
// Copy 32-bit buffer
// ---------------------------------------------------------------------------

void CSvgEngineImpl::CopyBuffer( TUint32* aSrc, TUint32* aDest, const TSize aSize )
    {
    if ( aSrc && aDest )
        {
        Mem::Copy( aDest, aSrc, aSize.iWidth * aSize.iHeight * sizeof( TUint32 ) );
        }
    }

// ---------------------------------------------------------------------------
// Positions the root element and calls itself (recursively) for all the
// descendant elements
// CTM stands for 'Current Transformation Matrix'.
// ---------------------------------------------------------------------------
void CSvgEngineImpl::UpdateCTM(CSvgDocumentImpl* aSvgDocument)
    {

    if (aSvgDocument)
    {
        ((CSvgElementImpl*)aSvgDocument->RootElement())->UpdateCTM();
    }


    }

// ---------------------------------------------------------------------------
// Initializes the SVG Engine primarily with width and height informtion
// This is based on the attribute specifications for the root 'svg' element
// ---------------------------------------------------------------------------
void CSvgEngineImpl::InitializeEngineL()
    {
    // VIEWBOX
    // If x, y, w, h of outmost svg not defined, then put default values: 0 0 100% 100%
    // return;
    // Set locale, so that there is no thousands separator

    if( !iSvgDocument )
        return;

    iSvgDocument->iInitialDrawFlag = ETrue;
    if(!((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iIsWidthSet)
    {
        ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iIsWidthSet = ETrue;
    }
    if(!((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iIsHeightSet)
    {
        ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iIsHeightSet = ETrue;
    }

    TLocale locale; // locale object
    locale.SetCurrencyTriadsAllowed( EFalse ); // change setting
    TSize   lSize   = GetSize();
    iSvgDocument->iReqExReqFtrSysLTested = EFalse;
    if ( iSvgDocument->RootElement() != NULL &&
         ((CSvgElementImpl*)iSvgDocument->RootElement())->ElemID() == KSvgSvgElement )

        {
        // Scale width & height to fit to screen size
        CSvgSvgElementImpl*     el      = ( CSvgSvgElementImpl* )
                                          (iSvgDocument->RootElement());
        TFloatFixPt                  width, height;
        TInt                    widthInt, heightInt;
        TFloatFixPt scrnW( lSize.iWidth ), scrnH( lSize.iHeight );
        TFloatFixPt                  zero    ( 0 );
        
        if ( iFrameBufferOverridesViewport )
        {
        		//special case for Aknicon
    				//the don't care what the contents viewport is they just want it to scale to the framebuffer's size
        		width = scrnW;
        		height= scrnH;
        }
        else
        {
            //bitmap from the client overrides width height specified in svg
      
            if(iViewPortListener != NULL)
            {
                TInt tempWidth=0,tempHeight=0;
                iViewPortListener->GetViewPort(
                ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iWidthInUserCoordinate, 
                ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iHeightInUserCoordinate, 
                ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iWidthInPercentage, 
                ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iHeightInPercentage,
                tempWidth,
                tempHeight);
            
                width = (TFloatFixPt) tempWidth;
                height = (TFloatFixPt) tempHeight;
                
                //used in SetWindowViewportTrans of svgSvgElementImpl
                iClientDefinedViewPort = ETrue;
                     
            }
        else
            {
        
                TReal32 per = 100;
                if(((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iWidthInPercentage)
                {   
                    width = ( TFloatFixPt ) (( lSize.iWidth/per ) * ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iWidthInUserCoordinate);
                }
                else
                {   
                    width  = (TFloatFixPt)  (((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iWidthInUserCoordinate);
                }
        
                if(((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iHeightInPercentage)
                {
                    height = ( TFloatFixPt ) (( lSize.iHeight/per ) * ((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iHeightInUserCoordinate);
                }
                else
                {
                    height  = (TFloatFixPt)  (((CSvgSvgElementImpl *)(iSvgDocument->RootElement()))->iHeightInUserCoordinate);
            }
        
        //default to XmidYmid_meet
        TSvgPreserveAspectAlignType lPreserverAspectAlignment = ESvgPreserveAspectRatio_XmidYmid;
  			TSvgMeetOrSliceType lMeetOrSlice = ESvgMeetOrSlice_Meet;
  		
  		MSvgPreserveAspectRatio* aPreserveAspectRatio;
        el->GetPreserveAspectRatio(aPreserveAspectRatio);
        
        if (aPreserveAspectRatio)
        {
        	lPreserverAspectAlignment = aPreserveAspectRatio->GetAlign();
        	lMeetOrSlice = aPreserveAspectRatio->GetMeetOrSlice();
        	
        	//el->SetPreserveAspectRatioL(  lPreserverAspectAlignment, lMeetOrSlice);
        	if( lPreserverAspectAlignment == ESvgPreserveAspectRatio_None && lMeetOrSlice == ESvgMeetOrSlice_Meet )
        	{
            width = scrnW;
            height = scrnH;
        	}
        }
            
        if( lMeetOrSlice == ESvgMeetOrSlice_Meet && !(lPreserverAspectAlignment == ESvgPreserveAspectRatio_None) )
            {
            widthInt = ( TInt ) width;
            heightInt = ( TInt ) height;

            // to avoid division by zero.
            TInt    rh  = lSize.iWidth ;
            if (widthInt != 0)
                {
                rh  = heightInt* lSize.iWidth / widthInt;
                }

            if ( rh <= lSize.iHeight )
                {
                width = scrnW;
                height = TFloatFixPt( rh );
                }
            else
                {
                // to avoid division by zero.
                if (heightInt != 0)
                    {
                    width = TFloatFixPt( ((TReal32)(widthInt * lSize.iHeight)) / heightInt );
                    }
                height = scrnH;
                }
            }
        else if( lMeetOrSlice == ESvgMeetOrSlice_Slice )
            {
            widthInt = ( TInt ) width;
            heightInt = ( TInt ) height;

            // to avoid division by zero.
            TInt    rh  = lSize.iWidth ;
            if (widthInt != 0)
                {
                rh  = heightInt* lSize.iWidth / widthInt;
                }

            if ( rh <= lSize.iHeight )
                {
                // to avoid division by zero.
                if (heightInt != 0)
                    {
                    width = TFloatFixPt( ((TReal32)(widthInt * lSize.iHeight)) / heightInt );
                    }
                height = scrnH;

                }
            else
                {
                width = scrnW;
                height = TFloatFixPt( rh );
                }
            }
        else
            {
            }
            }//Normal viewer| end of else
        }

        if ( ( width <= zero ) || ( height <= zero ) ) //.
        {
            width = 0;
            height = 0;
            return;
        }
        // Set initial viewport
        el->SetAttributeFloatL( KAtrX, zero );
        el->SetAttributeFloatL( KAtrY, zero );
        el->SetAttributeFloatL( KAtrWidth, width );
        el->SetAttributeFloatL( KAtrHeight, height );
        }
    }





// ---------------------------------------------------------------------------
// This method is called after the SVG file is read and all elements are
// constructed
// It also looks for rendering properties such as Anti Aliasing at this
// point
// It calibrates the system for rasterization quality based on contents
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::StartFrameLoopL()
    {
    if( iRequestObserver != NULL )
        {
        if(iSvgDocument != NULL && iSvgDocument->iEventHandler != NULL)
            {
            iRequestObserver->UpdatePresentation(
                         iSvgDocument->iEventHandler->AnimationElementsCount());
            }
        }
    if(iSvgDocument != NULL)
        {
        if ( iSvgDocument->RootElement() )
            {
            InitializeEngineL(); // set the viewport and viewbox
            return ETrue;
            }
        }
    return EFalse;
    }
// ---------------------------------------------------------------------------
// UpdatePresentation()
// ---------------------------------------------------------------------------
void  CSvgEngineImpl::UpdatePresentation(const TInt32& aParam)
    {
    if( iRequestObserver != NULL )
        {
        iRequestObserver->UpdatePresentation (aParam);
        }
    }
    
    
//---------------------------------------------------------------------------
// SetRenderingQuality
//
// @param : aRenderQuality
// The function is called from JSR226 API. Specific to M2G/JSR226 only.
//---------------------------------------------------------------------------
void  CSvgEngineImpl::SetRenderingQuality( const TInt32 aRenderQuality)
{
	// Bydefault iRenderQuality is set to 2 i.e. Rendering Quality high.
	
	if( iRenderQuality != aRenderQuality )
	{
		iRenderQuality = aRenderQuality;
		
		if( iGfxContext )
		{
			iGfxContext->SetAntialiasingMode( iRenderQuality );
		}
	}
}


// ---------------------------------------------------------------------------
// Invalidate the current raster (and frame buffer) and
// update the buffer with new  raster.
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RedrawL()
    {
    // Clear the frame buffer
    if( iGfxContext && iSvgDocument)
        {
        // Set Clipping rectangle
        CSvgSvgElementImpl* el  = ( CSvgSvgElementImpl* ) (iSvgDocument->RootElement());
        if ( !el )
            {
            return; // No DOM tree, nothing to draw.
            }
            
            
        
     	// If viewBox has been set and width or height is zero
     	// Do not render the content    
        TGfxRectangle2D viewBoxRect;    
        if(el->GetViewBox(viewBoxRect))
            {
                if(viewBoxRect.iWidth == TFloatFixPt(0) || 
                    viewBoxRect.iHeight == TFloatFixPt(0))
                    {
                    return;
                    }
            }
           
        iGfxContext->SetupContextL();
        iGfxContext->Clear(iBackgroundColor);
        iGfxContext->SetFillOpacity( 1.0f );
        iGfxContext->SetStrokeOpacity( 1.0f );

        TFloatFixPt  width, height;
        el->GetAttributeFloat( KAtrWidth, width );
        el->GetAttributeFloat( KAtrHeight, height );
        TGfxRectangle2D clipRect    ( 0, 0, width, height );
        iGfxContext->SetClip( clipRect );
        iClipRect = clipRect;

        UpdateCTM(iSvgDocument);

        iSvgDocument->iIsRendering = ETrue;
        DrawElementsL( (CSvgElementImpl*)iSvgDocument->RootElement());
        iSvgDocument->iIsRendering = EFalse;

        iGfxContext->Flush();

        // Get the redering result onto CFbsBitmap.
        if(iFrameBufferSize.iWidth > 0)
            iGfxContext->UpdateFramebufferL( iFrameBuffer, iMask,iFrameBufferSize,iRenderDspMode,iMaskDspMode );    
        else
         iGfxContext->UpdateFramebufferL( iFrameBuffer, iMask );

        if ( !iIgnoreUpdateScreen && iRequestObserver != NULL )
            {
            iRequestObserver->UpdateScreen();
            }
        if ( iSvgDocument->iInitSortList )
            {
            iSvgDocument->SortEventList();
            }
        else
            {
            iSvgDocument->iInitSortList=EFalse;
            }
        }
    }

// ---------------------------------------------------------------------------
// Delete the objects associated with the last loaded SVG file
// ---------------------------------------------------------------------------
void CSvgEngineImpl::Destroy()
    {
    //if ( iSvgDocument )    
    //    {
        // Stop timer and reset time
    //    iSvgDocument->TimeContainer()->UserStop();
    //    iSvgDocument->TimeContainer()->UserResetTime();
    //    }
    }


// ---------------------------------------------------------------------------
// Set the URI information
// ---------------------------------------------------------------------------
void CSvgEngineImpl::LinkRequest( const TDesC& aUri )
    {
    iLinkUri.Set( aUri );
    }
// ---------------------------------------------------------------------------
// Set the Link:Show information
// ---------------------------------------------------------------------------


void CSvgEngineImpl::LinkRequestWithShow(const TDesC& aUri ,const TDesC& aLinkShow )
    {
    iLinkUri.Set( aUri );
    iLinkShow.Set( aLinkShow );
    }

// ---------------------------------------------------------------------------
// Initiate the process of getting an svg font from the client
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::FetchFont( const TDesC& aUri, RFs& aSession, RFile& aFileHandle )
    {
		if ( iRequestObserver == NULL )
        {
        return EFalse;
        }
    else
        {
        if (iRequestObserver->FetchFont( aUri, aSession, aFileHandle ) == KErrNone)
        {
            return ETrue;
        }
            return EFalse;
        }
    }

// ---------------------------------------------------------------------------
// Initiate the process of getting an embedded image from the client
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::FetchImage( const TDesC& aUri, RFs& aSession, RFile& aFileHandle )
    {
    if ( iRequestObserver == NULL )
        {
        return EFalse;
        }
    else
        {
        if (iRequestObserver->FetchImage( aUri, aSession, aFileHandle ) == KErrNone)
        {
            return ETrue;
        }
            return EFalse;
        }
    }

// ---------------------------------------------------------------------------
// Accessor for Graphics Context object
// ---------------------------------------------------------------------------
CGfx2dGc* CSvgEngineImpl::GraphicsContext()
    {
    return iGfxContext;
    }

// ---------------------------------------------------------------------------
// Accessor for the Engine's current time
// ---------------------------------------------------------------------------
TInt32 CSvgEngineImpl::CurrentTIme()
    {
    if ( iSvgDocument )
        {
        return iSvgDocument->CurrentTime();        
        }
    return KErrGeneral;
    }


// --------------------------------------------------------------------------
// void CSvgEngineImpl::ImageLoadingCompleted( TInt /* aErrorStatus */ )
// ---------------------------------------------------------------------------
// ImageLoadingObserver interface
void CSvgEngineImpl::ImageLoadingCompleted( TInt /* aErrorStatus */ )
{
    TRAP_IGNORE(RedrawL());
    //aErrorStatus = 0;
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::UpdatePath( CGfxGeneralPath* hPath, CSvgElementImpl* hElement )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::UpdatePath( CGfxGeneralPath* hPath, CSvgElementImpl* hElement )
{
    if ((hElement != NULL) && (hElement->ElemID() == KSvgPathElement))
    {
        TRAPD(error,hElement->SetAttributePathL(KAtrData, hPath));
        if ( error != KErrNone )
           {
            // Error Processing
            return;
           }
    }

}

// ---------------------------------------------------------------------------
// Accessor for the document object for the currently loaded SVG source
// ---------------------------------------------------------------------------
CSvgDocumentImpl* CSvgEngineImpl::Document()
    {
    return iSvgDocument;
    }

// ---------------------------------------------------------------------------
// Restrict Thumbnail documents
// Do not render to frame buffer when is in thumbnail mode and
// frame buffer size width or height is larger than 80x80.
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::PassesThumbNailRestriction()
{
    if ( iSvgDocument && iFrameBuffer && iSvgDocument->IsThumbNailOnly() )
    {
        TSize size = iFrameBuffer->SizeInPixels();
        if ( size.iWidth > 80 || size.iHeight > 80 )
        {
           return EFalse;
        }
    }
    return ETrue;
}

//***************************************************************
// Event handling
// ---------------------------------------------------------------------------
// Initiate the process of handling an event from the client for the
// SVG source
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ProcessEventL( CSvgDocumentImpl* aSvgDocument, 
    MSvgEvent* aEvent, TBool aRedraw )
    {
    // Check for Thumbnail restrictions
    if ( !PassesThumbNailRestriction() )
    {
        return;
    }

    // Timer event
    //if(!aEvent || !iGfxContext)
    if(!aEvent)
    return;
    if ( aEvent->EventType() == ESvgEngineEventTimer )
        {
        // Update current time
        if ( aSvgDocument )
            {
            aSvgDocument->SetCurrentTime( 
                ( ( MSvgTimerEvent * ) aEvent )->Time() );
            }
        }

    if( aSvgDocument &&  aSvgDocument->iEventHandler)
        {
        if (( aSvgDocument->iEventHandler->ProcessEventL( aEvent ) ||
              aSvgDocument->iInitialDrawFlag) && aEvent->EventType() == ESvgEngineEventTimer )
        {

      if(aSvgDocument->iInitSortList)
            {
            aSvgDocument->SortEventList();
            aSvgDocument->iInitSortList = EFalse;
            }
        aSvgDocument->iInitialDrawFlag = EFalse;
        aSvgDocument->iEventHandler->DoAnimProcL(aEvent);

        if (aRedraw)
            {
        	// Redraw is performed for iSvgDocument
            RedrawL();
            }
        }
        else
            {
        // this is to keep the dom in its final state.
            if(aEvent->EventType() == ESvgEngineEventTimer)
                {
                aSvgDocument->iEventHandler->DoAnimProcL(aEvent);
                }

            }

    // Process Link
    if ( aEvent->EventMask() == KSvgEventMaskExternalUI )
            {
            if ( iLinkUri.Length() > 0 )
                {
                DoHyperLinkingL();
                // reset link description
                iLinkUri.Set( NullString );
                }
            }
        }

// Show FPS debug info. note. only write data to STI port
#ifdef _DEBUG

    if ( aEvent->EventType() == ESvgEngineInternalEvent )
        {
        MSvgInternalEvent*  evt = ( MSvgInternalEvent* ) aEvent;
        if (evt->SvgEvent() == ESvgEventEndEvent)
            {
            iAnimationState = KAnimFinished;
            return;
            }
        else
        if (evt->SvgEvent() == ESvgEventBeginEvent)
            {
            iAnimationState = KAnimActive;
            return;
            }

        }

    // time display for debug
    if ( iShowDebugInfo && iGfxContext && aEvent->EventType() == ESvgEngineEventTimer
        && iAnimationState != KAnimFinished /*&& iTimer*/)
        {
        TInt fps = iSvgDocument->TimeContainer()->UserFps() / 10; //iTimer->Fps() / 10;
        _LIT(msg, "\n%3d.%d\n");
        RDebug::Print(msg, fps, iSvgDocument->TimeContainer()->UserFps()
             - fps * 10 );

        }
#endif //_DEBUG

    }


// ---------------------------------------------------------------------------
// This method is for future extension, in which an external script engine
// could be used to evaluate a script description.
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::ScriptCall( const TDesC& aScript,
                                  CSvgElementImpl* aCallerElement )
    {
    if ( iRequestObserver == NULL )
        {
        return EFalse;
        }
    else
        {
        return iRequestObserver->ScriptCall( aScript, aCallerElement );
        }
    }


//***************************************************************
//
// ---------------------------------------------------------------------------
// Obtain the longest duration for an animation given document
// NULL will assume the attached document.
// ---------------------------------------------------------------------------
TUint32 CSvgEngineImpl::Duration( CSvgDocumentImpl* aDocument )
    {
    if ( aDocument == NULL )
        {
        if ( iSvgDocument == NULL )
            {
            return 0;
            }
        return iSvgDocument->AnimationDuration();
        }
    return aDocument->AnimationDuration();
    }

//*******************************************************/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::SwitchDebugInfo()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SwitchDebugInfo(TBool debug)
    {
    iShowDebugInfo = debug;
    }

void CSvgEngineImpl::CustomOption(TBool aCustomOption )
    {
        iCustomOption = aCustomOption;
        delete iGfxContext;
        iGfxContext = NULL;
        
/*NGA reverse*/  TRAP_IGNORE( iGfxContext = CGfx2dGcOpenVG::NewL( iFrameBufferSize, iBitmapFontSpec, iSvgBitmapFontProvider ));            
            
           
    }




// ---------------------------------------------------------------------------
// Initiate the process of opening and reading an embedded hyperlink
// ---------------------------------------------------------------------------
void CSvgEngineImpl::DoHyperLinkingL()
    {

    if( iSvgDocument == NULL )
        return;

    // Not full support of XPointer

    _LIT( KTmpHttp, "http:" );
    _LIT( KTmpFile, "file:" );
    _LIT( KTmpHash, "#" );
    _LIT( KTmpSvgView, "SvgView" );
    if ( iLinkUri.Left( 1 ) == KTmpHash )
        {
        // internal linking
        // Extract id
        TLex    lex ( iLinkUri );
        lex.Inc();  // skip '#'
        lex.Mark();
        while ( !lex.Eos() && lex.Peek().IsAlpha() )
            lex.Inc();
        TPtrC   targetId    = lex.MarkedToken();
        if ( targetId == KTmpSvgView )
            {
            // need to parse next token = {viewBoxSpec| preserveAspectRatioSpec
            // |transformSpec|zoomAndPanSpec|viewTargetSpec}

            // Not yet supported
            }
        else
            {

            CSvgElementImpl*targetElement   = ( CSvgElementImpl* )
                                              iSvgDocument->GetElementById( targetId );
            if ( targetElement == NULL )
                return;
            
            if  (   targetElement->IsAnimatedElement( ) )
                {
                // start animation
                ( ( CSvgAnimationBase * ) targetElement )->BeginElementL();
                }
            else
                {
                }
            }
        }
    else if ( iLinkUri.Length() >= 5 )
        {
        if ( iLinkUri.Left( 5 ) == KTmpHttp || iLinkUri.Left( 5 ) == KTmpFile )
            {
            // notify observer of desire to follow http link
            NotifyHyperlinkActivated( iLinkUri );
            }
        else
            {
            // notify observer of desire to follow link
            if ( iLinkShow.Length() > 0 )
                NotifyHyperlinkActivatedWithShow( iLinkUri, iLinkShow );
            else
                NotifyHyperlinkActivated( iLinkUri );
            }
        }
    else if ( iLinkUri.Length() > 0 )
        {
        // notify observer of desire to follow link
        if ( iLinkShow.Length() > 0 )
            NotifyHyperlinkActivatedWithShow( iLinkUri, iLinkShow );
        else
            NotifyHyperlinkActivated( iLinkUri );
        }
    }

// ---------------------------------------------------------------------------
// Dump a completed raster to the off screen buffer provided by the
// client
// ---------------------------------------------------------------------------
TInt CSvgEngineImpl::RenderFileToBuffer( const TDesC8& aSvgData,
                                           CFbsBitmap* aFrameBuffer,
                                           CFbsBitmap* aMask,
                                           TBool aPreserveAspectRatio )
    {
    if ( !iGfxContext )
        {
        return EFalse;
        }

    CFbsBitmap* OrgFrameBuffer;
    CFbsBitmap* OrgMask;
	OrgFrameBuffer = iFrameBuffer;
	OrgMask = iMask;
	CSvgDocumentImpl* lsvgorgdoc = iSvgDocument;
	// We have moved all the leaving functions into RenderFileL 
	TRAPD(err,RenderFileL(aSvgData,aFrameBuffer,aMask,aPreserveAspectRatio));
	// No matter what...whether the RenderFileL returns properly or leave we need to set the 
	//GDI context back to the original frame buffer and mask... and set back the engine to
	//how it was before all this happened..
	
    SetDocument(lsvgorgdoc);
    lsvgorgdoc->SetEngine(this);
	// the setGDIContextL error is a very serious error and if it occurs then 
	// there is no way of recovery. 
	TRAP_IGNORE(SetGdiContextL(OrgFrameBuffer,OrgMask));
	//So we are propagating the more probable error of the two which is the leaving of 
	// RenderFileL.
    return err;
    }
    
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Helper leaving function for the function RenderFileToBuffer.
// The actual rendering happens in this function..while the calling function uses this to
// render the file.
// ---------------------------------------------------------------------------
    

void CSvgEngineImpl::RenderFileL( const TDesC8& aSvgData,
                                           CFbsBitmap* aFrameBuffer,
                                           CFbsBitmap* aMask,
                                           TBool aPreserveAspectRatio)
   
{
    CFont *lFont = iGfxContext->Font();
    TFontSpec lFontSpec = lFont->FontSpecInTwips();
		
    TSize imageSize;
    imageSize = aFrameBuffer->SizeInPixels();
	//iFrameBuffer = aFrameBuffer;

    SetGdiContextL(aFrameBuffer, aMask);
    CSvgDocumentImpl* lSvgDocument = CSvgDocumentImpl::NewLC(iSvgBitmapFontProvider);
    SetDocument(lSvgDocument);
    lSvgDocument->SetEngine(this);

    // fileHandle is valid from client
    lSvgDocument->Load( aSvgData, *iSvgError );
    if ( iSvgError->HasError() && !iSvgError->IsWarning() )
        {
        CleanupStack::PopAndDestroy(1);
        return;
        }

    StartFrameLoopL();
    CSvgSvgElementImpl* lRoot = (CSvgSvgElementImpl*)lSvgDocument->RootElement();
    _LIT( KPreserveAspectRatio, "preserveAspectRatio" );

    if(lRoot)
        {
        if ( aPreserveAspectRatio )
            {
            _LIT( KXMidYMid, "xMidYMid" );
            lRoot->SetAttributeL( KPreserveAspectRatio, KXMidYMid );
            lRoot->SetWidth( imageSize.iWidth );
            lRoot->SetHeight( imageSize.iHeight );
            }
        else {
            _LIT( KNone, "none" );
            lRoot->SetAttributeL( KPreserveAspectRatio, KNone );
            lRoot->SetWidth( imageSize.iWidth );
            lRoot->SetHeight( imageSize.iHeight );
            }
        RedrawL();
        }
    CleanupStack::PopAndDestroy( 1 );
}
    

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Generate a mask bitmap from alpha channel of the framebuffer.
// ---------------------------------------------------------------------------
void CSvgEngineImpl::GenerateMask(CFbsBitmap* aMask)
    {
    if ( iGfxContext )
        {
        iGfxContext->GenerateMask( aMask );
        }
    }

//
// ---------------------------------------------------------------------------
// set background color
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SetBackgroundColor(TUint32 aRGBA8888Color)
    {
    iBackgroundColor = aRGBA8888Color;
    }

//
// ---------------------------------------------------------------------------
// Get Size of render buffer
// ---------------------------------------------------------------------------
TSize CSvgEngineImpl::GetSize()
    {
    	  return iFrameBufferSize;
    	  

        
    }


//
// ---------------------------------------------------------------------------
// Return SVG Engine State
// ---------------------------------------------------------------------------

TSvgEngineState CSvgEngineImpl::SVGEngineState()
    {
    return iSvgEngineState;
    }

//
// ---------------------------------------------------------------------------
// Set SVG Engine State
// ---------------------------------------------------------------------------

void CSvgEngineImpl::SetSVGEngineState(TSvgEngineState aState)
    {
    iSvgEngineState = aState;
    if( iSvgEngineState == ESVGEnginePaused )
        {
        if ( iSvgDocument )
        	{
            iSvgDocument->TimeContainer()->UserPause();
            NotifyAnimationPaused();
        	}
        }
    else if( iSvgEngineState == ESVGEngineRunning )
        {
        if (iSvgDocument && iSvgDocument->IsAnimationFile())
            {
           	iSvgDocument->TimeContainer()->UserResume();	
            }
        }
    else if(iSvgEngineState == ESVGEngineStopped ) 
        {
            if ( iSvgDocument )
            {
                iSvgDocument->TimeContainer()->UserStop();
       	    }
     
        }   
    }

void CSvgEngineImpl::SeekEngine( TUint32 aTime)
    {
    iSvgEngineState = ESVGEngineRunning;
    if ( iSvgDocument )
    	{
    	iSvgDocument->TimeContainer()->UserSeek( aTime );
    	}
    }

void CSvgEngineImpl::ResetTimer()
    {
    if ( iSvgDocument )
        {
        iSvgDocument->TimeContainer()->UserResetTime();
        }
    }

// ---------------------------------------------------------------------------
// SetGdiContext File
// ---------------------------------------------------------------------------

void CSvgEngineImpl::SetGdiContextL(CFbsBitmap* aCurrentBitmap, CFbsBitmap* aMask)
    {
    // Handle for both Non-NULL and NULL parameter
    iFrameBuffer = aCurrentBitmap;
    iMask = aMask;

    if ( aCurrentBitmap )
        {
        if ( !iGfxContext )
            {
                iGfxContext = CGfx2dGcOpenVG::NewL( iFrameBuffer->SizeInPixels(), iBitmapFontSpec, iSvgBitmapFontProvider );
                
                // The API is called Only in case of JSR226. Incase if the midlet developer
                // has changed the RedenderQuality of the midlet.ByDefualt the value of 
                // iRenderQuality is 2 i.e. VG_RENDERING_QUALITY_BETTER.
                iGfxContext->SetAntialiasingMode( iRenderQuality );
            }
        else
            {
            iGfxContext->ChangeBufferSizeL( iFrameBuffer->SizeInPixels() );
            }
        }
    else if ( iGfxContext )
        {
        iGfxContext->ChangeBufferSizeL( TSize( 0,0 ) );
        }
    }

// ---------------------------------------------------------------------------
// void CSvgEngineImpl::StartEngine(CSvgErrorImpl* aError)
// ---------------------------------------------------------------------------

void CSvgEngineImpl::StartEngine(CSvgErrorImpl* aError)
    {
    if ( !iFrameBuffer || !iSvgDocument )
        {
        return;
        }

    iMouseoverElement = NULL;
    if ( ((iFrameBufferSize.iHeight <= 0 )||(iFrameBufferSize.iWidth <= 0 )) &&(( iFrameBuffer->SizeInPixels().iWidth == 0 ) ||
         ( iFrameBuffer->SizeInPixels().iHeight == 0) ))
        {
        return;
        }

    TBool initialized = EFalse;

    TRAPD( initError, initialized = StartFrameLoopL() );

    if ( initError != KErrNone || !initialized )
        {
        return;
        }

    // Get the Engine State to Running
    SetSVGEngineState(ESVGEngineRunning);

    // Document is an animation
    if( iSvgDocument->IsAnimationFile() )
        {
            { // Atleast first frame should get drawn
                TRAPD(error, RedrawL() );
                {
                    if ( error != KErrNone && aError != NULL )
                    {
                       if( error == KErrNoMemory )
                       {
                           CSvgDocumentImpl::PrepareError( *aError, ESvgNoMemory, error,
                           _L( "Unable to Draw: " ),
                           _L( "" ) );  
                           return;  
                       }
                       
                       CSvgDocumentImpl::PrepareError( *aError, ESvgUnknown, error,
                       _L( "Unable to Draw: " ),
                       _L( "" ) );  
                       return;
                    }
                }
            
            }
            
        iSvgDocument->TimeContainer()->UserPlay();
        iSvgDocument->iAnimationResetNeeded = ETrue;
        }
    // Static svg file
    else
        {
            TRAPD(error, RedrawL() );
            {
                if ( error != KErrNone && aError != NULL )
                {
                   if( error == KErrNoMemory )
                   {
                       CSvgDocumentImpl::PrepareError( *aError, ESvgNoMemory, error,
                       _L( "Unable to Draw: " ),
                       _L( "" ) );  
                       return;  
                   }
                   
                   CSvgDocumentImpl::PrepareError( *aError, ESvgUnknown, error,
                   _L( "Unable to Draw: " ),
                   _L( "" ) );  
                   return;
                }
            }
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RenderFrame( TUint aCurrentTime )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RenderFrame( TUint aCurrentTime )
    {
    if ( !iFrameBuffer || !iSvgDocument ||
         iFrameBuffer->SizeInPixels().iWidth == 0 || iFrameBuffer->SizeInPixels().iHeight == 0 )
        {
        return;
        }

    if ( aCurrentTime == 0 )
        {
        SeekEngine( 0 );
        }

    iMouseoverElement = NULL;

     	CSvgSvgElementImpl* rootElement = (CSvgSvgElementImpl*)iSvgDocument->RootElement();

     	if (rootElement == NULL)
     	{
     		return;
     	}

     	TGfxRectangle2D viewBoxRect;
     	if (rootElement->GetViewBox(viewBoxRect))
     	{
     		//viewbox has been defined or set already
   			if (viewBoxRect.iWidth == TFloatFixPt(0) || viewBoxRect.iHeight == TFloatFixPt(0))
   			{
   				//viewbox has no area so dont render
   				return;
   			}
   		}

    if( iRequestObserver && iSvgDocument->iEventHandler )
        {
        iRequestObserver->UpdatePresentation( iSvgDocument->iEventHandler->AnimationElementsCount() );
        }

    iSvgDocument->iInitialDrawFlag = ETrue;

    // Fix for animation element for testApp   
    TSvgTick lTick;
    lTick.iRealTimeTick = aCurrentTime;
    lTick.iParentTcTick = 0;
    iSvgDocument->TimeContainer()->ParentTimeContainerTick(lTick) ;
    // Fix for animation element for testApp   
    }


// ---------------------------------------------------------------------------
// Set SvgEngine Document
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SetDocument(CSvgDocumentImpl* aDocument)
    {
    iSvgDocument = aDocument;
    }


// ---------------------------------------------------------------------------
// Change the duration of the timer
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ChangeDuration( TUint32 aTimerDuration )
    {
    if ( iSvgDocument )
        {
        iSvgDocument->TimeContainer()->UserChangeFrameDuration( 
            aTimerDuration );
        
        // Check if there is animation element in the parent svg
    RPointerArray<CSvgElementImpl> lAnimationEleList;
    iSvgDocument->FindAllElements((CSvgElementImpl* )iSvgDocument->RootElement(),
               KSvgMediaAnimationElement, lAnimationEleList );
    TInt lAnimationEleCnt = lAnimationEleList.Count();    
    for ( TInt lCurAnimationEle = 0; 
             lCurAnimationEle < lAnimationEleCnt; lCurAnimationEle++ )
        {
        CSvgMediaAnimationElementImpl* lAnimationElement = 
            (CSvgMediaAnimationElementImpl* )lAnimationEleList[ lCurAnimationEle ];
        CSvgDocumentImpl* lChildDoc = lAnimationElement->GetChildDocument();
        if ( lChildDoc )
            {
            lChildDoc->TimeContainer()->UserChangeFrameDuration( 
            aTimerDuration ); // Change Frame duration for child svg
            }
        }
        lAnimationEleList.Close();     
    	}	   
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::Resume(TInt32 aTime)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::Resume(TInt32 aTime)
    {
    if ( iSvgDocument )
        {
        iSvgDocument->TimeContainer()->UserResume( aTime );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::FindBBoxesForRotatedText( const TDesC& aSearchString,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::FindBBoxesForRotatedText( const TDesC& aSearchString,
                           RPointerArray<MRect>& aBoundingBoxes,
                                        RArray<TPtrC>& aTexts,
                                        RArray<TInt>& aElementIds,
                                        TBool aCaseSensitive )
{
    if ( iSvgDocument == NULL )
        return;

    if ( iSvgTextBoundingBoxes.Count() > 0 )
    {
    	iSvgTextBoundingBoxes.ResetAndDestroy();
    }

    // Find all text elements
	HBufC* searchStr = aSearchString.AllocLC();    
	TPtr searchStrPtr = searchStr->Des();
    RPointerArray<CSvgElementImpl> textElements;
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                     KSvgTextElement, textElements );
    // Himanshu: Find all animation elements
    RPointerArray<CSvgElementImpl> lAllAnimationElements;                                
    iSvgDocument->FindAllElements( (CSvgElementImpl*)iSvgDocument->RootElement(),
                                KSvgMediaAnimationElement,
                                lAllAnimationElements );                                
    TInt lAllAnimationEleCnt = lAllAnimationElements.Count();                            
    for ( TInt i = 0; i < lAllAnimationEleCnt; i++ )
        {
          CSvgMediaAnimationElementImpl* element = (CSvgMediaAnimationElementImpl*)lAllAnimationElements[i];
          CSvgDocumentImpl* ldoc = element->GetChildDocument();
            if(ldoc)
            {
                // Find all text elements in child document
                ldoc->FindAllElements( (CSvgElementImpl*)ldoc->RootElement(),
                                KSvgTextElement,
                                textElements );  
            }
          
        }
        lAllAnimationElements.Close();

    TSvgFourPointRect boundingBox;
    TInt textEleCnt = textElements.Count();
    for ( TInt i = 0; i < textEleCnt; i++ )
    {
        CSvgTextElementImpl* textElement = (CSvgTextElementImpl*)textElements[i];
        TPtrC remainder( textElement->GetText() );

        TInt index = ( aCaseSensitive ) ? remainder.Find( aSearchString ) :
                                          remainder.FindF( aSearchString );

        // continue to next element if nothing found
        if ( index == KErrNotFound )
            continue;

		searchStrPtr.Copy( remainder.Mid(index,aSearchString.Length()) );
        // Get the bounding box for the whole text element
        textElement->GetFourPointBBox( boundingBox );

        // Get bounding box for every occurrence
        TReal32 textAdvance = (TReal32)(textElement->TextAdvance( *searchStr, index ));
        TReal32 leftAdvance = 0.0f;
        //TReal32 aHeight = textElement->Ascent() + textElement->Descent();

        while ( index != KErrNotFound )
        {
            // Calculate boundingbox for searched-text
            // indeterminate results with a string only one character long
            leftAdvance = leftAdvance + (TReal32)(textElement->TextAdvance( remainder.Left( index )));

            // need to setup slope calculation here to determine where the new
            // four point rect should be for partial pieces of text

            // need to do something for both vertical and horizontal text 0 and na slopes

            TReal32 dy = (TReal32)boundingBox.iPoint2.iY - (TReal32)boundingBox.iPoint1.iY;
            TReal32 dx = (TReal32)boundingBox.iPoint2.iX - (TReal32)boundingBox.iPoint1.iX;

            double aSlopeRan;
            Math::ATan(aSlopeRan, dy, dx);

            double aSinVal;
            Math::Sin(aSinVal, aSlopeRan);

            double aCosVal;
            Math::Cos(aCosVal, aSlopeRan);


            TReal32 x1 = aCosVal * leftAdvance + (TReal32)boundingBox.iPoint1.iX;
            TReal32 x3 = aCosVal * leftAdvance + (TReal32)boundingBox.iPoint3.iX;
            TReal32 y1 = aSinVal * leftAdvance + (TReal32)boundingBox.iPoint1.iY;
            TReal32 y3 = aSinVal * leftAdvance + (TReal32)boundingBox.iPoint3.iY;

            TReal32 x2 = aCosVal * textAdvance + x1;
            TReal32 x4 = aCosVal * textAdvance + x3;

            TReal32 y2 = aSinVal * textAdvance + y1;
            TReal32 y4 = aSinVal * textAdvance + y3;

			TSvgFourPointRect* bbox = NULL;

            TRAP_IGNORE( bbox = new (ELeave) TSvgFourPointRect( TPoint(x1, y1),
                        TPoint(x2, y2),
                        TPoint(x3, y3),
                        TPoint(x4, y4)) );

            if ( !bbox )
            {
            	#ifdef _DEBUG
            		RDebug::Printf("Four Point Rect Failed: Out of Memory");
            	#endif
            	return;
            }

            // store bound box pointers to go back to client
            aBoundingBoxes.Append( (MRect*)bbox );

            iSvgTextBoundingBoxes.Append( bbox );

            // store point to text
            aTexts.Append( TPtrC( textElement->GetText() ) );
            aElementIds.Append( (TInt)textElement );

            remainder.Set( remainder.Right( remainder.Length() - index - aSearchString.Length() ) );
            leftAdvance = leftAdvance + textAdvance;
            index = ( aCaseSensitive ) ? remainder.Find( aSearchString ) :
                                         remainder.FindF( aSearchString );
        }
    }
    CleanupStack::PopAndDestroy(searchStr);
    textElements.Close();
}

//this is the old 2point rect way that only works for horizontal text
/*void CSvgEngineImpl::FindBBoxesForHorizontalText( const TDesC& aSearchString,
                           RArray<TRect>& aBoundingBoxes,
                                        RArray<TPtrC>& aTexts,
                                        RArray<TInt>& aElementIds,
                                        TBool aCaseSensitive                                        )
{
    if ( iSvgDocument == NULL )
        return;

    // Find all text elements
    RPointerArray<CSvgElementImpl> textElements;
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                     KSvgTextElement, textElements );

    TGfxRectangle2D boundingBox;
    for ( TInt i = 0; i < textElements.Count(); i++ )
    {
        CSvgTextElementImpl* textElement = (CSvgTextElementImpl*)textElements[i];
        TPtrC remainder( textElement->GetText() );

        TInt index = ( aCaseSensitive ) ? remainder.Find( aSearchString ) :
                                          remainder.FindF( aSearchString );

        // continue to next element if nothing found
        if ( index == KErrNotFound )
            continue;

        // Get the bounding box for the whole text element
        textElement->GetBBox( boundingBox );

        // Get bounding box for every occurrence
        TFloatFixPt textAdvance = textElement->TextAdvance( aSearchString, index );
        TFloatFixPt leftAdvance = 0.0f;
        while ( index != KErrNotFound )
        {
            // Calculate boundingbox for searched-text
            leftAdvance = leftAdvance + textElement->TextAdvance( remainder.Left( index ), index );

            TRect bbox( (TInt)boundingBox.iX + (TInt)leftAdvance,
                        (TInt)boundingBox.iY,
                        (TInt)boundingBox.iX + (TInt)leftAdvance + (TInt)textAdvance,
                        (TInt)boundingBox.iY + (TInt)boundingBox.iHeight );

            // store bound box
            aBoundingBoxes.Append( bbox );

            // store point to text
            aTexts.Append( TPtrC( textElement->GetText() ) );
            aElementIds.Append( (TInt)textElement );

            remainder.Set( remainder.Right( remainder.Length() - index - aSearchString.Length() ) );
            leftAdvance = leftAdvance + textAdvance;
            index = ( aCaseSensitive ) ? remainder.Find( aSearchString ) :
                                         remainder.FindF( aSearchString );
        }
    }
    textElements.Close();
}
*/

/************************ HyperLinking Functions ***********************/

// --------------------------------------------------------------------------
// void CSvgEngineImpl::CheckForHyperlinkMouseover( TInt aX, TInt aY )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::CheckForHyperlinkMouseover( TInt aX, TInt aY )
{
   if ( iHyperlinkListeners.Count() == 0 )
        return;

    if ( iSvgDocument == NULL )
        return;

    // Gather <a> elements if first time
    RPointerArray<CSvgElementImpl> iAElementList;
    if ( iAElementList.Count() == 0 )
        {
        iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                         KSvgAElement, iAElementList );
        }

    // find the bounding box containing point
    TGfxPoint2D point( aX, aY );
    TGfxRectangle2D boundingBox;
    TInt aEleListCnt = iAElementList.Count();
    for ( TInt i = 0; i < aEleListCnt; i++ )
        {
        CSvgElementImpl* element = iAElementList[i];
        CSvgGElementImpl::GetGroupBounding( boundingBox, element );
        if ( boundingBox.Contains( point ) )
            {
            // no existing mouse over element: notify HyperlinkEntered
            if ( iMouseoverElement == NULL )
                {
                NotifyHyperlinkEntered( element->Href() );
                }
            // otherwise: notify HyperlinkExited, HyperlinkEntered
            else if ( iMouseoverElement != element )
                {
                NotifyHyperlinkExited( iMouseoverElement->Href() );
                NotifyHyperlinkEntered( element->Href() );
                }
            iMouseoverElement = element;
            return;
            }
        }

    // no bounding box containing point: notify HyperlinkExited
    if ( iMouseoverElement != NULL )
    {
        NotifyHyperlinkExited( iMouseoverElement->Href() );
        iMouseoverElement = NULL;
    }

    iAElementList.Close();
}

/*-------------------------Animation Listeners-----------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddAnimationListener( MSvgAnimationListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddAnimationListener( MSvgAnimationListener* aListener )
{
    if ( aListener != NULL && iAnimationListeners.Find( aListener ) == KErrNotFound )
        iAnimationListeners.Append( aListener );

}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveAnimationListener( MSvgAnimationListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveAnimationListener( MSvgAnimationListener* aListener )
{
    TInt index = iAnimationListeners.Find( aListener );
    if ( index != KErrNotFound )
        iAnimationListeners.Remove( index );
}

/*-------------------------Animation listener notification to client-------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyAnimationStarted()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyAnimationStarted()
{

    TBool isAnimationIndefinite = EFalse;
    if ( ( iSvgDocument == NULL ) || ( iSvgDocument->RootElement() == NULL ) ||
         ( iAnimationListeners.Count() == 0 ) )
    {
        return;
    }

    RPointerArray<CSvgElementImpl> AnimationElementList;

    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgSetElement, AnimationElementList );
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateElement, AnimationElementList );
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateMotionElement, AnimationElementList );
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateTransformElement, AnimationElementList );
    iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateColorElement, AnimationElementList );

    if ( AnimationElementList.Count() != 0 )
    {
    	TInt animationEleListCnt = AnimationElementList.Count();
        for ( TInt i=0; i < animationEleListCnt; i++ )
        {
             CSvgElementImpl * element = AnimationElementList[i];
              if ( ((CSvgAnimationBase *)element)->CompleteDuration() == KTimeIndefinite )  
                {
                 isAnimationIndefinite = ETrue;
                 break;
                }
        }

    }
   AnimationElementList.Close();

   TInt animationListenersCnt = iAnimationListeners.Count();
   for ( TInt i = 0; i < animationListenersCnt; i++ )
        iAnimationListeners[i]->AnimationStarted( isAnimationIndefinite );


}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyAnimationPaused()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyAnimationPaused()
{
	TInt animationListenersCnt = iAnimationListeners.Count();
    for ( TInt i = 0; i < animationListenersCnt; i++ )
        iAnimationListeners[i]->AnimationPaused();
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyAnimationEnded()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyAnimationEnded()
{
    if ( ( iSvgDocument == NULL ) || ( iSvgDocument->RootElement() == NULL ) ||
         ( iAnimationListeners.Count() == 0 ) )
    {
        return;
    }
 #if 0
    RPointerArray<CSvgElementImpl> AnimationElementList;

    FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgSetElement, AnimationElementList );
    FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateElement, AnimationElementList );
    FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateMotionElement, AnimationElementList );
    FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateTransformElement, AnimationElementList );
    FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                                 KSvgAnimateColorElement, AnimationElementList );

    if ( AnimationElementList.Count() != 0 )
    {
    	TInt animationEleListCnt = AnimationElementList.Count();
        for ( TInt i=0; i < animationEleListCnt; i++ )
        {
        CSvgElementImpl * element = AnimationElementList[i];
        if ( ((CSvgAnimationBase *)element)->iAnimStatus == KAnimActive )
            {
             AnimationElementList.Close();
             return;
            }
        }

    }
     AnimationElementList.Close();
#endif

	TInt animationListenersCnt = iAnimationListeners.Count();
    for ( TInt i = 0; i < animationListenersCnt; i++ )
        iAnimationListeners[i]->AnimationEnded();

}

/*------------------Register Client Text Area listeners----------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddTextAreaListener( MSvgTextAreaListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddTextAreaListener( MSvgTextAreaListener* aListener )
{
    if ( aListener != NULL && iTextAreaListeners.Find( aListener ) == KErrNotFound )
    {
        iTextAreaListeners.Append( aListener );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveTextAreaListener( MSvgTextAreaListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveTextAreaListener( MSvgTextAreaListener* aListener )
{
    TInt index = iTextAreaListeners.Find( aListener );
    if ( index != KErrNotFound )
    {
        iTextAreaListeners.Remove( index );
    }
}

/*----------------Text Area listener notification to client--------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextAreaEntered( CSvgTextAreaElementImpl* aTextAreaHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextAreaEntered( CSvgTextAreaElementImpl* aTextAreaHandle )
{
	TInt textAreaListenersCnt = iTextAreaListeners.Count();
    for (TInt i=0; i < textAreaListenersCnt; i++)
    {
        iTextAreaListeners[i]->TextAreaEntered( (TInt)aTextAreaHandle);
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextAreaExited( CSvgTextAreaElementImpl* aTextAreaHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextAreaExited( CSvgTextAreaElementImpl* aTextAreaHandle )
{
	TInt textAreaListenersCnt = iTextAreaListeners.Count();
    for (TInt i=0; i < textAreaListenersCnt; i++)
    {
        iTextAreaListeners[i]->TextAreaExited( (TInt)aTextAreaHandle);
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextAreaActivated( CSvgTextAreaElementImpl* aTextAreaHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextAreaActivated( CSvgTextAreaElementImpl* aTextAreaHandle )
{
	TInt textAreaListenersCnt = iTextAreaListeners.Count();
	for (TInt i=0; i < textAreaListenersCnt; i++)
    {
        iTextAreaListeners[i]->TextAreaActivated( (TInt)aTextAreaHandle );
    }
}

/*------------------Register Client Text listeners----------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddTextListener( MSvgTextListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddTextListener( MSvgTextListener* aListener )
{
    if ( aListener != NULL && iTextListeners.Find( aListener ) == KErrNotFound )
    {
        iTextListeners.Append( aListener );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveTextListener( MSvgTextListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveTextListener( MSvgTextListener* aListener )
{
    TInt index = iTextListeners.Find( aListener );
    if ( index != KErrNotFound )
    {
        iTextListeners.Remove( index );
    }
}

/*----------------Text listener notification to client--------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextEntered( CSvgTextElementImpl* aTextHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextEntered( CSvgTextElementImpl* aTextHandle )
{
	TInt textListenersCnt = iTextListeners.Count();
    for (TInt i=0; i < textListenersCnt; i++)
    {
        iTextListeners[i]->TextEntered( (TInt)aTextHandle);
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextExited( CSvgTextElementImpl* aTextHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextExited( CSvgTextElementImpl* aTextHandle )
{
	TInt textListenersCnt = iTextListeners.Count();
    for (TInt i=0; i < textListenersCnt; i++)
    {
        iTextListeners[i]->TextExited( (TInt)aTextHandle);
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyTextActivated( CSvgTextElementImpl* aTextHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyTextActivated( CSvgTextElementImpl* aTextHandle )
{
	TInt textListenersCnt = iTextListeners.Count();
    for (TInt i=0; i < textListenersCnt; i++)
    {
        iTextListeners[i]->TextActivated( (TInt)aTextHandle );
    }
}

/*---------------------Register Client Hyperlink listeners----------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddHyperlinkListener( MSvgHyperlinkListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddHyperlinkListener( MSvgHyperlinkListener* aListener )
{
    if ( aListener != NULL && iHyperlinkListeners.Find( aListener ) == KErrNotFound )
        iHyperlinkListeners.Append( aListener );
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveHyperlinkListener( MSvgHyperlinkListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveHyperlinkListener( MSvgHyperlinkListener* aListener )
{
    TInt index = iHyperlinkListeners.Find( aListener );
    if ( index != KErrNotFound )
        iHyperlinkListeners.Remove( index );
}

void CSvgEngineImpl::AddViewPortListener(MSvgViewPortListener* aListener)
{
    if ( aListener != NULL )
    {
        iViewPortListener = aListener ;
    }
        
}
  
        
void CSvgEngineImpl::RemoveViewPortListener(MSvgViewPortListener* 
        /* aListener */ )
{
    if(iViewPortListener != NULL)
    {
        iViewPortListener = NULL;
    }
}
/*----------------Hyperlink listener notification to client--------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkEntered( CSvgAElementImpl* aAElementHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkEntered( CSvgAElementImpl* aAElementHandle )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        if (aAElementHandle)
        {
            iHyperlinkListeners[i]->LinkEntered( aAElementHandle->Href() );
        }
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkEntered( const TDesC& aUri )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkEntered( const TDesC& aUri )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        iHyperlinkListeners[i]->LinkEntered( aUri );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkExited( CSvgAElementImpl* aAElementHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkExited( CSvgAElementImpl* aAElementHandle )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        if (aAElementHandle)
        {
            iHyperlinkListeners[i]->LinkExited( aAElementHandle->Href() );
        }
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkExited( const TDesC& aUri )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkExited( const TDesC& aUri )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        iHyperlinkListeners[i]->LinkExited( aUri );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkActivated( CSvgAElementImpl* aAElementHandle )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkActivated( CSvgAElementImpl* aAElementHandle )
{
    if ( !aAElementHandle ||
          aAElementHandle->Href().Length() == 0 ||
          aAElementHandle->Href()[0] == '#' )
        {
        return;
        }

	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        iHyperlinkListeners[i]->LinkActivated( aAElementHandle->Href() );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkActivated( const TDesC& aUri )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkActivated( const TDesC& aUri )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
    {
        iHyperlinkListeners[i]->LinkActivated( aUri );
    }
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyHyperlinkActivatedWithShow( const TDesC& aUri, const TDesC& aShow )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyHyperlinkActivatedWithShow( const TDesC& aUri, const TDesC& aShow )
{
	TInt hyperLinkListenersCnt = iHyperlinkListeners.Count();
    for ( TInt i = 0; i < hyperLinkListenersCnt; i++ )
        iHyperlinkListeners[i]->LinkActivatedWithShow( aUri, aShow );
}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyElementActivatedLinkEntered( CSvgElementImpl* aElement)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyElementActivatedLinkEntered( CSvgElementImpl* aElement)
    {
      if(iMouseoverElement  == NULL)
        {
        const TDesC* myId = aElement->Id();

        if (myId)
        NotifyHyperlinkEntered( *(myId));
        iMouseoverElement = aElement;
        }
    }
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyElementActivatedLinkExited(  CSvgElementImpl* aElement)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyElementActivatedLinkExited(  CSvgElementImpl* aElement)
    {
        if(iMouseoverElement == aElement )
        {
        const TDesC* myId = aElement->Id();

        if (myId)
        NotifyHyperlinkExited( *(myId));
        iMouseoverElement  = NULL;
        }
    }
void CSvgEngineImpl::GetViewPort(TInt getWidth, TInt getHeight, TBool isWidthInPer, TBool isHeightInPer, TInt &setWidth, TInt &setHeight)
{
    if(iViewPortListener != NULL)
    {
        iViewPortListener->GetViewPort(getWidth, getHeight, isWidthInPer, isHeightInPer, setWidth, setHeight);
    }
}

/*------------------Register Client Interactive Element listeners------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddInteractiveElementListener( 
//                                  MSvgInteractiveElementListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddInteractiveElementListener( 
                                    MSvgInteractiveElementListener* aListener )
    {
    if ( 
        aListener != NULL &&
        iInteractiveElementListeners.Find( aListener ) == KErrNotFound )
        {
        iInteractiveElementListeners.Append( aListener );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveInteractiveElementListener( 
//                                  MSvgInteractiveElementListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveInteractiveElementListener( 
                                    MSvgInteractiveElementListener* aListener )
    {
    TInt index = iInteractiveElementListeners.Find( aListener );
    if ( index != KErrNotFound )
        {
        iInteractiveElementListeners.Remove( index );
        }
    }

/*-----------Interactive Element listener notification to client------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyInteractiveElementEntered(CSvgElementImpl* aElement)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyInteractiveElementEntered(
                        CSvgElementImpl* aElement)
    {
    TUint16 lsubeventmask=0; 
    TBool linteractivity;
    linteractivity=this->iSvgDocument->iEventHandler->
    CheckInteractivityAndGetSubEventMask(aElement,lsubeventmask);
    if(linteractivity)
        {
        TInt linteractiveElementListenersCnt = iInteractiveElementListeners.Count();
        for ( TInt i = 0; i < linteractiveElementListenersCnt; i++ )
            {
            const TDesC* myId = aElement->Id();
            TPtrC16 ptr;
            if(myId)
                {
                ptr.Set(*myId);               
                }
            else
                {
                _LIT(KEmptyString,"");
                ptr.Set( KEmptyString);                      
                }
            iInteractiveElementListeners[i]->InteractiveElementEntered( 
                                               ptr,lsubeventmask  ); 
            }
        }
    }
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyInteractiveElementExited(CSvgElementImpl* aElement)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyInteractiveElementExited(CSvgElementImpl* aElement)
    {
	TInt linteractiveElementListenersCnt = iInteractiveElementListeners.Count();
    for ( TInt i = 0; i < linteractiveElementListenersCnt; i++ )
        {
        const TDesC* myId = aElement->Id();
        TPtrC16 ptr;
        if(myId)
            {            
            ptr.Set(*myId);
            }
        else
            {
            _LIT(KEmptyString,"");
            ptr.Set(KEmptyString);
            }               
        iInteractiveElementListeners[i]->InteractiveElementExited(ptr);
        }
	}

// ---------------------------------------------------------------------------
// Set SVG Dimension to frame buffer size
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SetSvgDimensionToFrameBufferL(TUint aWidth, TUint aHeight)
    {
     if (iSvgDocument == NULL )   return;
     if (iSvgDocument->RootElement() != NULL)
         {
         CSvgElementImpl* theElement = (CSvgElementImpl*)(iSvgDocument->RootElement());
         ((CSvgSvgElementImpl*)theElement)->iWidthInUserCoordinate = 0;
         ((CSvgSvgElementImpl*)theElement)->iHeightInUserCoordinate = 0;
         TFloatFixPt wFix( (TInt)aWidth );
         TFloatFixPt hFix( (TInt)aHeight );
         theElement->SetAttributeFloatL(KAtrWidth, wFix );
         theElement->SetAttributeFloatL(KAtrHeight, hFix );
         }

    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::SetMediaTime(TUint32 aTimeInMilliSeconds)
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SetMediaTime(TUint32 aTimeInMilliSeconds)
    {
    // Set Current Time in the document
    if(iSvgDocument != NULL)
        {
        //iSvgDocument->SetCurrentTime( aTimeInMilliSeconds );
        
        iSvgDocument->iAnimationResetNeeded = ETrue;
        }
    if(this->iSvgDocument && this->iSvgDocument->iEventHandler)
        {
        this->iSvgDocument->iEventHandler->SetCurrentTime(aTimeInMilliSeconds);
        }
   // Find all animation elements in the document    
    RPointerArray<CSvgElementImpl> lAnimationEleList;
    if(iSvgDocument)
	    {
    iSvgDocument->FindAllElements((CSvgElementImpl* )iSvgDocument->RootElement(),
               KSvgMediaAnimationElement, lAnimationEleList );
    TInt lAnimationEleCnt = lAnimationEleList.Count();    
    for ( TInt lCurAnimationEle = 0; 
             lCurAnimationEle < lAnimationEleCnt; lCurAnimationEle++ )
        {
        CSvgMediaAnimationElementImpl* lAnimationElement = 
            (CSvgMediaAnimationElementImpl* )lAnimationEleList[ lCurAnimationEle ];
        CSvgDocumentImpl* lChildDoc = lAnimationElement->GetChildDocument();
        if ( lChildDoc )
            {
            lChildDoc->iAnimationResetNeeded = ETrue;
            if ( lChildDoc->iEventHandler )    
                {
                lChildDoc->iEventHandler->SetCurrentTime(aTimeInMilliSeconds); 
                }
            
            }
        }
    lAnimationEleList.Close();     
	    	
	    }
    this->SetSVGEngineState(ESVGEnginePaused);
    this->SeekEngine(aTimeInMilliSeconds);

    }

// --------------------------------------------------------------------------
// TBool CSvgEngineImpl::IsElementVisible( TInt aElementId )
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::IsElementVisible( TInt aElementId )
    {
    if ( aElementId == 0 || iFrameBuffer == NULL )
        {
        return EFalse;
        }

    CSvgElementImpl* element = (CSvgElementImpl*)aElementId;

    TInt32 visibleAttribute = -1;

    TRAPD(error,element->GetAttributeIntL( KCSS_ATTR_VISIBILITY, visibleAttribute ));
    if (error != KErrNone)
       {
       // error processing
       }


    return visibleAttribute == 0;
    }

// Set whether to call request observer's UpdateScreen method
// --------------------------------------------------------------------------
// void CSvgEngineImpl::SetIgnoreUpdateScreen( TBool aBool )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SetIgnoreUpdateScreen( TBool aBool )
{
    iIgnoreUpdateScreen = aBool;
}

/*---------------------------MouseListener---------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::AddMouseListener( const MSvgMouseListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::AddMouseListener( const MSvgMouseListener* aListener )
    {
    TInt index = iSvgMouseListeners.Find( aListener );
    if ( aListener != NULL && index == KErrNotFound )
        {
        iSvgMouseListeners.Append( aListener );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::RemoveMouseListener( const MSvgMouseListener* aListener )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::RemoveMouseListener( const MSvgMouseListener* aListener )
    {
    TInt index = iSvgMouseListeners.Find( aListener );
    if ( index != KErrNotFound )
        {
        iSvgMouseListeners.Remove( index );
        }
    }

// --------------------------------------------------------------------------
// TInt CSvgEngineImpl::MouseListenerCount()
// ---------------------------------------------------------------------------
TInt CSvgEngineImpl::MouseListenerCount()
    {
    return iSvgMouseListeners.Count();
    }

/*-------------MouseListener Notifications back to client---------------------------*/
// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyMousePressed( RPointerArray<CSvgElementImpl>& aElements,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyMousePressed( RPointerArray<CSvgElementImpl>& aElements,
                                          TInt aX, TInt aY )
    {
    TInt svgMouseListenersCnt = iSvgMouseListeners.Count();
    for ( TInt i = 0; i < svgMouseListenersCnt; i++ )
        {
        iSvgMouseListeners[i]->MousePressed( aElements, aX, aY );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyMouseReleased( RPointerArray<CSvgElementImpl>& aElements,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyMouseReleased( RPointerArray<CSvgElementImpl>& aElements,
                                          TInt aX, TInt aY )
    {
    TInt svgMouseListenersCnt = iSvgMouseListeners.Count();
    for ( TInt i = 0; i < svgMouseListenersCnt; i++ )
        {
        iSvgMouseListeners[i]->MouseReleased( aElements, aX, aY );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyMouseEntered( RPointerArray<CSvgElementImpl>& aElements,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyMouseEntered( RPointerArray<CSvgElementImpl>& aElements,
                                          TInt aX, TInt aY )
    {
    TInt svgMouseListenersCnt = iSvgMouseListeners.Count();
    for ( TInt i = 0; i < svgMouseListenersCnt; i++ )
        {
        iSvgMouseListeners[i]->MouseEntered( aElements, aX, aY );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyMouseExited( RPointerArray<CSvgElementImpl>& aElements,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyMouseExited( RPointerArray<CSvgElementImpl>& aElements,
                                          TInt aX, TInt aY )
    {
    TInt svgMouseListenersCnt = iSvgMouseListeners.Count();
    for ( TInt i = 0; i < svgMouseListenersCnt; i++ )
        {
        iSvgMouseListeners[i]->MouseExited( aElements, aX, aY );
        }
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::NotifyMouseMoved( RPointerArray<CSvgElementImpl>& aElements,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::NotifyMouseMoved( RPointerArray<CSvgElementImpl>& aElements,
                                       TInt aX, TInt aY )
    {
    TInt svgMouseListenersCnt = iSvgMouseListeners.Count();
    for ( TInt i = 0; i < svgMouseListenersCnt; i++ )
        {
        iSvgMouseListeners[i]->MouseMoved( aElements, aX, aY );
        }
    }

/*---------------------------------------------------------------------*/

// --------------------------------------------------------------------------
// void CSvgEngineImpl::GetViewableElementsAtPoint( RPointerArray<CSvgElementImpl>& aElements, TInt aX, TInt aY )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::GetViewableElementsAtPoint( CSvgDocumentImpl* aSvgDocument, RPointerArray<CSvgElementImpl>& aElements, TInt aX, TInt aY )
    {
   if ( aSvgDocument == NULL )
        return;

	//JSR226 Change this could slow down event handling but it seems to be required to work
   UpdateCTM(aSvgDocument);

    // Gather all "viewable" elements
    RPointerArray<CSvgElementImpl> iViewableElementList;
    if ( iViewableElementList.Count() == 0 )
        {
        FindAllViewableElements( (CSvgElementImpl* )aSvgDocument->RootElement(),
                                 iViewableElementList );
        }

    // find the bounding box containing point
    TGfxPoint2D point( aX, aY );
    TGfxRectangle2D boundingBox;
    TInt viewableEleListCnt =  iViewableElementList.Count();
    for ( TInt i = 0; i < viewableEleListCnt; i++ )
        {
        CSvgElementImpl* element = iViewableElementList[i];
        element->GetBBox( boundingBox );
        if ( boundingBox.Contains( point ) )
            {
            aElements.Append( element );
            }
        }
    // Display of list
    iViewableElementList.Close();
    }

// Return all viewable elements
// --------------------------------------------------------------------------
// void CSvgEngineImpl::FindAllViewableElements( CSvgElementImpl* aStartElement,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::FindAllViewableElements( CSvgElementImpl* aStartElement,
                                              RPointerArray<CSvgElementImpl>& iElementList )
    {
    if ( aStartElement == NULL )
        return;
    // The child elements of the defs element should not be viewable. skip the
    // tree traversing if the element id is defs element
    if(aStartElement->ElemID() == KSvgDefsElement)
        return;

    CSvgElementImpl* child = (CSvgElementImpl*)aStartElement->FirstChild();
    while ( child != NULL )
        {
        // add to list if child is found
        TInt32 displayValue = 0;
        TRAP_IGNORE(child->GetAttributeIntL( KCSS_ATTR_DISPLAY, displayValue ));
        if ( child->IsViewable() && child->IsVisible() && displayValue != KDisplayEnumNone )
            {
				//JSR226 CHANGE do we care if multiple signals are sent to some elements - would be faster without this check
            	if ( iElementList.Find( child ) == KErrNotFound )
            	{
            		iElementList.Append( child );
				}
			}
        // find in grandchildren
        FindAllViewableElements( child, iElementList );
        child = (CSvgElementImpl*)child->NextSibling();
        }
    }

// Return all non-viewable elements
// --------------------------------------------------------------------------
// void CSvgEngineImpl::FindAllNonViewableElements( CSvgElementImpl* aStartElement,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::FindAllNonViewableElements( CSvgElementImpl* aStartElement,
                                                 RPointerArray<CSvgElementImpl>& iElementList )
    {
    if ( aStartElement == NULL )
        return;

    CSvgElementImpl* child = (CSvgElementImpl*)aStartElement->FirstChild();
    while ( child != NULL )
        {
        // add to list if child is found
        if ( !child->IsViewable() && !child->IsVisible() )
            iElementList.Append( child );

        // find in grandchildren
        FindAllNonViewableElements( child, iElementList );
        child = (CSvgElementImpl*)child->NextSibling();
        }
    }

/**
 * Return the data pointed to by the given URI string,
 * from an external source.
 */
// --------------------------------------------------------------------------
// HBufC8* CSvgEngineImpl::FetchExternalDataL( const TDesC& aUri )
// ---------------------------------------------------------------------------
HBufC8* CSvgEngineImpl::FetchExternalDataL( const TDesC& aUri )
    {
    if ( iRequestObserver == NULL )
        {
        #ifdef _DEBUG
        RDebug::Printf("CSvgEngineImpl::FetchExternalData--requestobserver is NULL\n");
        #endif //_DEBUG
        return NULL;
        }
    // Connect session
    RFs session;
    TInt connectError = session.Connect();
    if ( connectError != KErrNone )
        {
        #ifdef _DEBUG
        RDebug::Printf("CSvgEngineImpl::FetchExternalData--session.Connect() failed: %d\n", connectError );
        #endif //_DEBUG
        return NULL;
        }

    RFile fileHandle;
    // Check for FetchImage error code
    TInt fetchError = iRequestObserver->FetchImage( aUri, session, fileHandle );
    if ( fetchError != KErrNone )
        {
        #ifdef _DEBUG
        RDebug::Printf("CSvgEngineImpl::FetchExternalData--FetchImage error: %d\n", fetchError );
        #endif //_DEBUG
        session.Close();
        return NULL;
        }

    // Read file size
    TInt fileSize = 0;
    TInt sizeError = fileHandle.Size( fileSize );
    if ( sizeError != KErrNone )
        {
        #ifdef _DEBUG
        RDebug::Printf("CSvgEngineImpl::FetchExternalData--fileHandle.Size error: %d\n", sizeError );
        #endif //_DEBUG
        session.Close();
        return NULL;
        }

    // Allocate memory for file
    HBufC8* data = HBufC8::NewL( fileSize );
    TPtr8 des = data->Des();
    TInt readError = fileHandle.Read( des );
    if ( readError != KErrNone )
        {
        #ifdef _DEBUG
        RDebug::Printf("CSvgEngineImpl::FetchExternalData--fileHandle.Read error: %d\n", readError );
        #endif //_DEBUG
        session.Close();
        delete data;
        return NULL;
        }

    // Successful
    session.Close();
    return data;
    }
// --------------------------------------------------------------------------
// void CSvgEngineImpl::SetAudioVolume( TInt aPercentage );
// --------------------------------------------------------------------------
void CSvgEngineImpl::SetAudioVolume( TInt aPercentage )
    {
#if 0    
    if ( !iSvgDocument )
        {
        return;
        }
    // Locate all the active audio elements
    RPointerArray<CSvgElementImpl> lAudioElementList;
    
    iSvgDocument->FindAllElements( 
            (CSvgElementImpl* )iSvgDocument->RootElement(),
            KSvgAudioElement, lAudioElementList );
    // Set the volume on each audio element
    TInt lAudEleCnt = lAudioElementList.Count();
    for ( TInt lCurAudioEle = 0; lCurAudioEle < lAudEleCnt; lCurAudioEle++ )
        {
        CSvgAudioElementImpl* lAudioElement = (CSvgAudioElementImpl*)lAudioElementList[ lCurAudioEle ];
        lAudioElement->SetVolume( aPercentage );
        }
    lAudioElementList.Close();
#endif
    }

// --------------------------------------------------------------------------
// TBool CSvgEngineImpl::ReadyToRender()
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::ReadyToRender()
    {
    return iSvgDocument != NULL;
    }

// --------------------------------------------------------------------------
// TBool CSvgEngineImpl::IsEndedWithCompleteTextTag( TDes &BufferPtr,
//                                                   TInt EndOffset)
// ---------------------------------------------------------------------------
TBool CSvgEngineImpl::IsEndedWithCompleteTextTag(TDes &aBufferPtr,TInt aEndOffset)
    {
    TChar KOpeningBrace = '<';
    TChar KSlash = '/';

    // This function searches the buffer in reverse order from the end offset
    // to check whether the last element had a complete text tag.
    // eg. of complete text tags
    //          <text>Hello</text>
    //          <text></text>
    // eg. of an incomplete text tag
    //          <text />

    TPtrC currentSelectionPtr = aBufferPtr.Left( aEndOffset );
    TInt OpeningBracePos = currentSelectionPtr.LocateReverse( KOpeningBrace );
    TInt SlashPos = currentSelectionPtr.LocateReverse( KSlash );
    TBool retVal = EFalse;

    // In case of a complete text tag the opening brace is one position behind
    // slash.
    if ( SlashPos == ( OpeningBracePos + 1 ) )
        {
        retVal = ETrue;
        }

    return retVal;
    }

// --------------------------------------------------------------------------
// void CSvgEngineImpl::SaveSvgL( const TDesC& aFileName )
// ---------------------------------------------------------------------------
void CSvgEngineImpl::SaveSvgL( const TDesC& aFileName )
    {
    RFs  lFs;
    RFileWriteStream  lStream;
    TInt error ;
    TChar KOpeningBrace = '<';
    TChar KSlash = '/';
    // Connect to File Server to write the changed content to a file
    CleanupClosePushL(lFs);
    User::LeaveIfError(lFs.Connect() );

    TBool isOpened = EFalse;
    error = lFs.IsFileOpen( aFileName, isOpened ) ;
    // dont leave if file doesnt exist or there is no error
    if(error!= KErrNone && error!=KErrNotFound)
        {
        //usually will come here with KErrNotFound
        //since file wont exist
        User::Leave(error);
        }

    if ( isOpened )
        {
        #ifdef _DEBUG
        RDebug::Printf( "Cannot SaveSvgL: File is still opened: ");
        RDebug::RawPrint( aFileName );
        #endif
        CleanupStack::PopAndDestroy(1);
        return;
        }

    // Try to create the write stream using the file name
    if ( lStream.Create( lFs, aFileName, EFileWrite ) != KErrNone )
        {
        // If creation fails, file exists already, try to open the
        // existing file
        User::LeaveIfError( lStream.Open(lFs, aFileName, EFileWrite) );
        }
    CleanupClosePushL(lStream);

    // Array to store list of all editable elements
    RPointerArray<CSvgElementImpl> lTextElementList;

    FindEditableElements( (CSvgElementImpl* )iSvgDocument->RootElement(),
                          lTextElementList );
    CleanupClosePushL(lTextElementList);
    TInt index=0, startoffset = 0, endoffset = 0;

    // The content of the file is stored in the root <svg> node
    HBufC*  lBufferContent = ((CSvgSvgElementImpl* )iSvgDocument->RootElement())->iContent;



    // While there are remaining editable elements do
    while(index < lTextElementList.Count())
        {
        TBool EndedWithCompleteTextTag= true;
        TInt OrgLength;

        if ( lTextElementList[index]->ElemID() == KSvgTextElement )
            {
            // If the element is a <text> element invoke element specific function
            // to retrieve the offset and original length
            endoffset = ((CSvgTextElementImpl *)lTextElementList[index])->iOffset;
            OrgLength = ((CSvgTextElementImpl *)lTextElementList[index])->GetOrgLength();
            }
        else
            {
            // If the element is a <textArea> element invoke element specific function
            // to retrieve the offset and original length
            endoffset = ((CSvgTextAreaElementImpl *)lTextElementList[index])->iOffset;
            OrgLength = ((CSvgTextAreaElementImpl *)lTextElementList[index])->GetOrgLength();
            }

        // These are the cases which have to be processed
        //     a. Text Element: No Closing Tag: <text  ... />
        //     b. Text Element: No CData : <text ...></text>
        //     c. Text Element: CData : <text ...>Sample Text</text>
        //     d. TextArea Element: No Closing Tag: <textArea ... />
        //     e. TextArea Element: No CData: <textArea ...></textArea>
        //     f. TextArea Element: CData: <textArea ...>Sample TextArea</textArea>
        //     -> for a,b,d,e the endoffset represents the offset after the closing braces.
        //        for e.g.  <text ... />
        //                              ^
        //        <text></text>
        //                     ^
        //     -> for c,f the EndOffset represents the offset to the first character in
        //        content.
        //        <text>Hello</text>
        //
        //              ^
        if(!OrgLength)
            {
            //case a,b,d,e
            TPtr BufferPtr=lBufferContent->Des();
            EndedWithCompleteTextTag = IsEndedWithCompleteTextTag(BufferPtr,endoffset);
            if ( EndedWithCompleteTextTag )
                {
                // case b,e
                if(endoffset < startoffset)
                    {
                    User::Leave(KErrNotFound);
                    }
                TPtrC lPtrtoPresentText = lBufferContent->Mid( startoffset, ( endoffset - startoffset ) );
                //end offset modified ot point to <text></text>
                //                                      ^
                endoffset = startoffset + lPtrtoPresentText.LocateReverse( KOpeningBrace );
                }
            else
                {
                //case a,d
                if(endoffset < startoffset)
                    {
                    User::Leave(KErrNotFound);
                    }
                TPtrC lPtrtoPresentText = lBufferContent->Mid( startoffset, ( endoffset - startoffset ) );
                 endoffset = startoffset + lPtrtoPresentText.LocateReverse( KSlash );
                //end offset modified ot point to <text/>
                //                                     ^
                }
            }
        if(endoffset < startoffset)
            {
            User::Leave(KErrNotFound);
            }
        TPtrC lPtrtoWrBuffer = lBufferContent->Mid( startoffset, ( endoffset - startoffset ) );
        TInt lWrBufLength = lPtrtoWrBuffer .Length();
        User::LeaveIfError(WriteToStream(lStream,lPtrtoWrBuffer));
        // If it was a text element ...
        if ( lTextElementList[index]->ElemID() == KSvgTextElement )
            {
            HBufC *lBufTextContent= NULL;
            //make startoffset point to opening tag '<' or '/' in case of a,d
            TPtrC lPtrtoTextContent= ( (CSvgTextElementImpl* ) lTextElementList[ index ] )->GetText();
            startoffset = endoffset + ( (CSvgTextElementImpl* ) lTextElementList[ index ] )->iOrgLength;
            lBufTextContent = TextTagProcessingL(&lPtrtoTextContent,
                                    startoffset,OrgLength,EndedWithCompleteTextTag);
            CleanupStack::PushL(lBufTextContent);
            TPtr lTempPtr(lBufTextContent->Des());
            lPtrtoTextContent.Set(lTempPtr);
            User::LeaveIfError(WriteToStream(lStream,lPtrtoTextContent));
            CleanupStack::PopAndDestroy(lBufTextContent);
            }
       else
            {
            HBufC *lBufTextAreaContent= NULL;
            HBufC* lBufPresentText = NULL;
            TInt textlength = ((CSvgTextAreaElementImpl *)lTextElementList[index])->GetLength();
            lBufTextAreaContent = HBufC::NewLC( textlength );

            TPtr lPtrtoGetTextAreaContent = lBufTextAreaContent->Des();
            ((CSvgTextAreaElementImpl *)lTextElementList[index])->GetText( lPtrtoGetTextAreaContent );
            TPtrC lPtrtoTextAreaContent=lPtrtoGetTextAreaContent;
            startoffset = endoffset + ((CSvgTextAreaElementImpl *)lTextElementList[index])->iOrgLength;
            lBufPresentText = TextAreaTagProcessingL(&lPtrtoTextAreaContent,startoffset,OrgLength,EndedWithCompleteTextTag);
            CleanupStack::PushL(lBufPresentText);
            TPtr lTempPtr(lBufPresentText->Des());
            lPtrtoTextAreaContent.Set(lTempPtr);
            User::LeaveIfError(WriteToStream(lStream,lPtrtoTextAreaContent));
            CleanupStack::PopAndDestroy(lBufPresentText);
            CleanupStack::PopAndDestroy(lBufTextAreaContent);
            }
            index++;
        }

    // Done using the list, close the list to avoid a memory leak
    CleanupStack::PopAndDestroy(&lTextElementList);

    // After processing all the editable text elements, are there any characters in the buffer
    if( startoffset < lBufferContent->Length() )
        {
        TPtrC lPtrtoRemainText = lBufferContent->Mid(startoffset,(lBufferContent->Length()-startoffset));
        User::LeaveIfError(WriteToStream(lStream,lPtrtoRemainText));
        }

    // Close the stream
    CleanupStack::PopAndDestroy(&lStream);

    // Close the file server session
    CleanupStack::PopAndDestroy(&lFs);
    }

//-----------------------------------------------------------------------------
//Function to process the text and add tags at the end
//HBufC* CSvgEngineImpl::TextTagProcessing(TPtr* aCData, TInt aStartOffset, TInt aOrgLength,
//                              TBool aEndingWithTag)
//-----------------------------------------------------------------------------

HBufC* CSvgEngineImpl::TextTagProcessingL(TPtrC* aCData,
                    TInt &aStartOffset, TInt aOrgLength,TBool aEndingWithTag)
    {
        HBufC * lTextContentBuffer = NULL;
        TPtrC lPtrToTextContent(*aCData) ;
        //Ending with complete text tag and original length is 0
        if( aEndingWithTag && aOrgLength == 0 )
            {//case b
            lTextContentBuffer = HBufC::NewLC(aCData->Length()
                                    + KClosingTextTagLength );
            TPtr lPtrToTempBuf(lTextContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextTag);//append closing text tag
            aStartOffset += KClosingTextTagLength;
            }
        else if( !aEndingWithTag && aOrgLength == 0 )
            {//case a
            lTextContentBuffer = HBufC::NewLC(aCData->Length()
                                    + KClosingTextTagLength
                                    + KClosingBracesLength );
            TPtr lPtrToTempBuf(lTextContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(KClosingBraces);
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextTag);//append closing text tag
            aStartOffset += 2;// the length of /> which is 2 characters.
            }
        else if(aEndingWithTag && aOrgLength!= 0)
            {
            lTextContentBuffer = HBufC::NewLC(aCData->Length()
                                    + KClosingTextTagLength );
            TPtr lPtrToTempBuf(lTextContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextTag);//append closing text tag
            aStartOffset += KClosingTextTagLength ;
            }
        else
            {
            //i.e !aEndingWithTag && OrgLength!=0
            //this case should never occur
            //becoz there is no possibility of
            //the quoted kind of text content definition in xml as shown below
            //"<text /> this is a text content"
            }
        // Pop the buffer from the cleanup stack as ownership is transferred
        // to caller
        CleanupStack::Pop(lTextContentBuffer);
        return lTextContentBuffer;

    }

//-----------------------------------------------------------------------------
//Function to process the text and add tags at the end
//HBufC* CSvgEngineImpl::TextAreaTagProcessing(TPtr* aCData, TInt aStartOffset, TInt aOrgLength,
//                              TBool aEndingWithTag)
//-----------------------------------------------------------------------------

HBufC* CSvgEngineImpl::TextAreaTagProcessingL(TPtrC* aCData, TInt &aStartOffset, TInt aOrgLength,
                                TBool aEndingWithTag)
    {
        HBufC * lTextAreaContentBuffer = NULL;
        TPtrC lPtrToTextAreaContent(*aCData) ;


        //Ending with complete text tag and original length is 0
        if( aEndingWithTag && aOrgLength == 0 )
            {//case e
            lTextAreaContentBuffer = HBufC::NewLC(aCData->Length()
                                        + KClosingTextAreaTagLength);
            TPtr lPtrToTempBuf(lTextAreaContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextAreaTag);//append closing text tag
            aStartOffset += KClosingTextAreaTagLength;
            }
        else if( !aEndingWithTag && aOrgLength == 0 )
            {//case d
            lTextAreaContentBuffer = HBufC::NewLC(aCData->Length()
                                        + KClosingBracesLength
                                        + KClosingTextAreaTagLength );
            TPtr lPtrToTempBuf(lTextAreaContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(KClosingBraces);
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextAreaTag);//append closing text tag
            aStartOffset += 2;// the length of /> which is 2 characters.
            }
        else if(aEndingWithTag && aOrgLength!= 0)
            {//case f
            lTextAreaContentBuffer = HBufC::NewLC(aCData->Length()
                                        + KClosingTextAreaTagLength );
            TPtr lPtrToTempBuf(lTextAreaContentBuffer->Des());//point to buffer
            lPtrToTempBuf.Append(*aCData);//append cdata
            lPtrToTempBuf.Append(KClosingTextAreaTag);//append closing text tag
            aStartOffset += KClosingTextAreaTagLength;
            }
        else
            {
            //i.e !aEndingWithTag && OrgLength!=0
            //this case should never occur
            //becoz there is no possibility of
            //the quoted kind of text content definition in xml as shown below
            //"<textArea /> this is a text content"
            }
        // Pop the buffer from the cleanup stack as ownership is transferred
        // to caller
        CleanupStack::Pop(lTextAreaContentBuffer);
        return lTextAreaContentBuffer;

    }


//-----------------------------------------------------------------------------
//Function to Write the buffer to the stream.
//In SaveSVGL while editing text - used to write partial buffers into the stream.
//TInt CSvgEngineImpl::WriteToStream(RFileWriteStream* aStream,TPtrC aWriteBuffer)
//-----------------------------------------------------------------------------
TInt CSvgEngineImpl::WriteToStream(RFileWriteStream &aStream,TPtrC aWriteBuffer)
    {
    // Create a small output buffer
    TBuf8<KMaxConversionChars> outputBuffer;

    for(;;) // conversion loop
        {
        // Start conversion. When the output buffer is full, return the
        // number of characters that were not converted
        const TInt returnValue = CnvUtfConverter::ConvertFromUnicodeToUtf8(
            outputBuffer,   // Destination
            aWriteBuffer ); // Source


        // check to see that the descriptor isn’t corrupt - return with
        // err if it is
        if ( returnValue == CnvUtfConverter::EErrorIllFormedInput )
            {
            return( KErrCorrupt );
            }
        else
            {
            if ( returnValue < 0 ) // future-proof against "TError" expanding
                {
                return( KErrGeneral );
                }
            }

        // Store the converted contents of the output buffer into the stream
        TRAPD( err1, aStream.WriteL( outputBuffer ) );
        if ( err1 )
            {
            #ifdef _DEBUG
            RDebug::Printf("CSvgEngineImpl::WriteToStream error trapped=%d", err1);
            return err1;
            #endif
            }

        // Finish conversion if there are no unconverted characters in the
        // remainder buffer
        if ( returnValue == 0 )
            {
            break;
            }

        // Remove the converted source text from the remainder buffer.
        // The remainder buffer is then fed back into loop
        aWriteBuffer.Set( aWriteBuffer.Right( returnValue ));
        }
    return KErrNone;
    }


// --------------------------------------------------------------------------
// void CSvgEngineImpl::FindEditableElements( CSvgElementImpl* aStartElement,
// ---------------------------------------------------------------------------
void CSvgEngineImpl::FindEditableElements( CSvgElementImpl* aStartElement,
                                           RPointerArray<CSvgElementImpl>& aList )
    {
    if ( aStartElement == NULL )
        {
        return;
        }

    CSvgElementImpl* child = (CSvgElementImpl*)aStartElement->FirstChild();
    while ( child != NULL )
    {
        // add to list if child is found
        if ( child->ElemID() == KSvgTextElement || child->ElemID() == KSvgTextAreaElement  )
            aList.Append( child );

        // find in grandchildren if element is not a textArea
        if ( child->ElemID() != KSvgTextAreaElement )
            {
        FindEditableElements( child, aList );
            }
        child = (CSvgElementImpl*)child->NextSibling();
    }
}
TBool CSvgEngineImpl::IsSVGEnginePaused()
{
	return (iSvgEngineState == ESVGEnginePaused );

}

// --------------------------------------------------------------------------
// void CSvgEngineImpl::ResetContext()
// ---------------------------------------------------------------------------
void CSvgEngineImpl::ResetContext()
{
	if( iGfxContext )
		{
		iGfxContext->DestroyContext();
		}
}

void CSvgEngineImpl::SetBitmapHeader(const TDesC* aHeaderData)
    {
    if (iGfxContext)
        {
        ((CGfx2dGcOpenVG *)iGfxContext)->SetBitmapHeader(aHeaderData);
        }
    }
//NGA
// ---------------------------------------------------------------------------
// SetGdiContext File
// ---------------------------------------------------------------------------

void CSvgEngineImpl::SetGdiContextL(CFbsBitmap* aCurrentBitmap, CFbsBitmap* aMask,TSize aCurrentBitmapSize,TDisplayMode aRenderDspMode,TDisplayMode aMaskDspMode)

    {
    // Handle for both Non-NULL and NULL parameter
       iFrameBufferSize = aCurrentBitmapSize;
       iRenderDspMode   = aRenderDspMode;
       iMaskDspMode     = aMaskDspMode; 
       iFrameBuffer     = aCurrentBitmap;
       iMask            = aMask;

    if ( aCurrentBitmapSize.iWidth > 0 && aCurrentBitmapSize.iHeight > 0 )
        {
        if ( !iGfxContext )
            {
                iGfxContext = CGfx2dGcOpenVG::NewL( aCurrentBitmapSize, iBitmapFontSpec, iSvgBitmapFontProvider,1 );
            }
        else
            {
            iGfxContext->ChangeBufferSizeL( aCurrentBitmapSize );
            }
        }
    else if ( iGfxContext )
        {
        iGfxContext->ChangeBufferSizeL( TSize( 1, 1 ) );
        }
    }
const TPtrC8 CSvgEngineImpl::TLVEncodedData() const
    {
    return (iGfxContext->TLVEncodedData());
    }