diff -r 000000000000 -r 88edb906c587 svgtopt/SVG/SVGEngine/src/SVGEngineImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/svgtopt/SVG/SVGEngine/src/SVGEngineImpl.cpp Wed Nov 03 18:56:10 2010 +0200 @@ -0,0 +1,3190 @@ +/* +* 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 +#endif + +#include +#include + +#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 +const TInt KClosingTextTagLength = 7; +// Length of +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,""); +_LIT(KClosingTextAreaTag,""); +_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 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& aBoundingBoxes, + RArray& aTexts, + RArray& 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 textElements; + iSvgDocument->FindAllElements( (CSvgElementImpl* )iSvgDocument->RootElement(), + KSvgTextElement, textElements ); + // Himanshu: Find all animation elements + RPointerArray 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& aBoundingBoxes, + RArray& aTexts, + RArray& aElementIds, + TBool aCaseSensitive ) +{ + if ( iSvgDocument == NULL ) + return; + + // Find all text elements + RPointerArray 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 elements if first time + RPointerArray 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 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 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 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& aElements, +// --------------------------------------------------------------------------- +void CSvgEngineImpl::NotifyMousePressed( RPointerArray& 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& aElements, +// --------------------------------------------------------------------------- +void CSvgEngineImpl::NotifyMouseReleased( RPointerArray& 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& aElements, +// --------------------------------------------------------------------------- +void CSvgEngineImpl::NotifyMouseEntered( RPointerArray& 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& aElements, +// --------------------------------------------------------------------------- +void CSvgEngineImpl::NotifyMouseExited( RPointerArray& 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& aElements, +// --------------------------------------------------------------------------- +void CSvgEngineImpl::NotifyMouseMoved( RPointerArray& 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& aElements, TInt aX, TInt aY ) +// --------------------------------------------------------------------------- +void CSvgEngineImpl::GetViewableElementsAtPoint( CSvgDocumentImpl* aSvgDocument, RPointerArray& 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 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& 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& 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 ( !iSvgDocument ) + { + return; + } + // Locate all the active audio elements + RPointerArray 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(); + } + +// -------------------------------------------------------------------------- +// 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 + // Hello + // + // eg. of an incomplete text tag + // + + 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 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 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 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