/*
* 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());
}