/*
* 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
*
*/
#include "SVGContentHandler.h"
#include "SVGSchemaData.h"
#include "SVGDocumentImpl.h"
#include "SVGEngineImpl.h"
#include "SVGSvgElementImpl.h"
#include "SVGStringTokenizer.h"
#include "SVGUseElementImpl.h"
#include "SVGAnimationElementImpl.h"
#include "rxmlreader.h"
#include "SVGPaintCssValueImpl.h"
#include "SVGPathElementImpl.h"
#include "GfxGeneralPath.h"
#include "SVGUriReferenceImpl.h"
#include "SVGGradientElementImpl.h"
#include "SVGAnimationBase.h"
#include "SVGTextAreaElementImpl.h"
#include "SVGTextElementImpl.h"
#include "SVGScriptElementImpl.h"
#include "SVGImageElementImpl.h"
#include "SVGMediaElementBase.h"
#include "SVGFontFaceElementImpl.h"
#include <languages.hrh>
//#ifdef RD_SVGT_MEDIAANIMATION_SUPPORT
#include "SVGMediaAnimationElementImpl.h"
//#endif
_LIT(WIDTH, "width");
_LIT(HEIGHT, "height");
_LIT(BEGIN, "begin");
_LIT(END, "end");
_LIT(MOUSEDOWN, "mousedown");
_LIT(MOUSEUP, "mouseup");
_LIT(MOUSEOVER, "mouseover");
_LIT(MOUSEMOVE, "mousemove");
_LIT(MOUSEOUT, "mouseout");
_LIT(FOCUSIN, "focusin");
_LIT(FOCUSOUT, "focusout");
_LIT(ACTIVATE, "activate");
_LIT(CLICK, "click");
_LIT(FILL, "fill");
_LIT(STROKE, "stroke");
_LIT(COLOR, "color");
_LIT(STOP_COLOR, "stop-color");
_LIT(ACCESS,"accessKey");
_LIT(OFFSET, "offset");
_LIT(ZEROVALUE, "0");
// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
CSvgContentHandler::CSvgContentHandler() : iRootElement( NULL ),
iIsColorAnim( EFalse ),
iRemoveFalseSwitchElements( ETrue )
{
iCancelRequested = EFalse;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
CSvgContentHandler::~CSvgContentHandler()
{
if(iUseElementArray)
{
iUseElementArray->Reset();
iUseElementArray->Close();
delete iUseElementArray;
iUseElementArray = NULL;
}
if(iAnimRefElementArray)
{
iAnimRefElementArray->Reset();
iAnimRefElementArray->Close();
delete iAnimRefElementArray;
iAnimRefElementArray = NULL;
}
if(iSwitchElementArray)
{
iSwitchElementArray->Reset();
iSwitchElementArray->Close();
delete iSwitchElementArray;
iSwitchElementArray = NULL;
}
if (iReqFetAttSysArray)
{
iReqFetAttSysArray->Reset();
iReqFetAttSysArray->Close();
delete iReqFetAttSysArray;
iReqFetAttSysArray = NULL;
}
if(iAnimationElementArray)
{
iAnimationElementArray->Reset();
iAnimationElementArray->Close();
delete iAnimationElementArray;
}
if(iCData)
{
delete iCData;
iCData = NULL;
}
if ( iSystemLanguage )
{
delete iSystemLanguage;
iSystemLanguage = NULL;
}
iImageElements.Close();
}
// ---------------------------------------------------------------------------
// CSvgContentHandler* CSvgContentHandler::NewL()
// ---------------------------------------------------------------------------
CSvgContentHandler* CSvgContentHandler::NewL( TBool aRemoveFalseSwitchElements )
{
CSvgContentHandler* self = new( ELeave ) CSvgContentHandler();
CleanupStack::PushL( self );
self->ConstructL( aRemoveFalseSwitchElements );
CleanupStack::Pop();
return self;
}
// --------------------------------------------------------------------------
// CSvgContentHandler* CSvgContentHandler::NewLC()
// ---------------------------------------------------------------------------
CSvgContentHandler* CSvgContentHandler::NewLC()
{
CSvgContentHandler* self = new( ELeave ) CSvgContentHandler();
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::ConstructL()
// ---------------------------------------------------------------------------
void CSvgContentHandler::ConstructL( TBool aRemoveFalseSwitchElements )
{
/*Arrays added to support Forward referencing in Animation and Use elements*/
iUseElementArray = new (ELeave)RPointerArray<CSvgElementImpl> (1);
iAnimRefElementArray = new (ELeave)RPointerArray<CSvgElementImpl> (1);
// added to hold switch element handles so we can go back and delete false children of the switch
iSwitchElementArray = new (ELeave)RPointerArray<CSvgElementImpl> (1);
// Arrays added to reset event listeners for animation element
iAnimationElementArray = new (ELeave)RPointerArray<CSvgElementImpl> (1);
//added to hold elements with required features, attributes, or sys language
//so we can go back and delete the ones that dont pass at the start.
iReqFetAttSysArray = new (ELeave)RPointerArray<CSvgElementImpl> (1);
// Create a 1KB buffer for CData -- this will expand as needed
iCData = HBufC::NewL( 1024 );
iSystemLanguage = HBufC::NewL( 5 );
iRemoveFalseSwitchElements = aRemoveFalseSwitchElements;
}
// --------------------------------------------------------------------------
// CSvgElementImpl* CSvgContentHandler::ParseByteData( CSvgDocumentImpl* aDocument,
// const TDesC8& aByteData,
// CSvgErrorImpl& aError )
// ---------------------------------------------------------------------------
CSvgElementImpl* CSvgContentHandler::ParseByteData( CSvgDocumentImpl* aDocument,
const TDesC8& aByteData,
CSvgErrorImpl& aError )
{
iDocument = aDocument;
iSvgError = &aError;
aError.SetErrorCode( ESvgNoError );
// Create XML reader
RXMLReader xmlReader;
TInt error = KErrNone;
TRAP( error, xmlReader.CreateL() );
if ( error != KErrNone )
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetErrorCode( ESvgNoMemory );
aError.SetDescription( OUTMEMORY );
aError.SetIsWarning( EFalse );
return iRootElement;
}
// Parse content
xmlReader.SetContentHandler( this );
TRAPD( parseError, xmlReader.ParseL( aByteData ) );
xmlReader.Destroy();
if ( !iCancelRequested && parseError != KErrNone )
{
if ( iSvgError->HasError() )
return iRootElement;
aError.SetErrorCode( ESvgUnknown );
if ( parseError == -4 )
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetDescription( OUTMEMORY );
}
else
{
_LIT(STRING, "Parsing SVG document failed.");
aError.SetDescription( STRING );
}
aError.SetIsWarning( EFalse );
aError.SetSystemErrorCode( parseError );
return iRootElement;
}
if ( iRootElement == NULL )
{
_LIT(STRING, "Invalid SVG Document.");
aError.SetErrorCode( ESvgDocumentNotValid );
aError.SetDescription( STRING );
aError.SetIsWarning( EFalse );
return iRootElement;
}
else if ( !iCancelRequested )
{
SetForwardReferences(aError);
PostParseProcessing();
}
return iRootElement;
}
// --------------------------------------------------------------------------
// CSvgElementImpl* CSvgContentHandler::Parse16BitData( CSvgDocumentImpl* aDocument,
// const TDesC8& aByteData,
// CSvgErrorImpl& aError )
// ---------------------------------------------------------------------------
CSvgElementImpl* CSvgContentHandler::Parse16BitData( CSvgDocumentImpl* aDocument,
const TDesC16& aSvgString,
CSvgErrorImpl& aError )
{
iDocument = aDocument;
iSvgError = &aError;
aError.SetErrorCode( ESvgNoError );
// Create XML reader
RXMLReader xmlReader;
TInt error = KErrNone;
TRAP( error, xmlReader.CreateL() );
if ( error != KErrNone )
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetErrorCode( ESvgNoMemory );
aError.SetDescription( OUTMEMORY );
aError.SetIsWarning( EFalse );
return iRootElement;
}
// Parse content
xmlReader.SetContentHandler( this );
//-------------------------------------------------------------------
//THIS IS TEMPORARY
//convert to 8 bit here temporary until I get 16 bit parsing method...
//TRAPD( parseError, xmlReader.ParseXML( aSvgString ) );
//convert 16 to 8 bit characters
HBufC8* lString8 = NULL;
lString8 = HBufC8::New( aSvgString.Length() );
if(NULL==lString8)
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetErrorCode( ESvgNoMemory );
aError.SetDescription( OUTMEMORY );
aError.SetIsWarning( EFalse );
return iRootElement;
}
lString8->Des().Copy(aSvgString);
TRAPD( parseError, xmlReader.ParseL( *lString8 ) );
delete lString8 ;
//-------------------------------------------------------------------
xmlReader.Destroy();
if ( !iCancelRequested && parseError != KErrNone )
{
if ( iSvgError->HasError() )
return iRootElement;
aError.SetErrorCode( ESvgUnknown );
if ( parseError == -4 )
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetDescription( OUTMEMORY );
}
else
{
_LIT(STRING, "Parsing SVG document failed.");
aError.SetDescription( STRING );
}
aError.SetIsWarning( EFalse );
aError.SetSystemErrorCode( parseError );
return iRootElement;
}
if ( iRootElement == NULL )
{
_LIT(STRING, "Invalid SVG Document.");
aError.SetErrorCode( ESvgDocumentNotValid );
aError.SetDescription( STRING );
aError.SetIsWarning( EFalse );
return iRootElement;
}
else if ( !iCancelRequested )
{
//POST PARSING PROCESSING
SetForwardReferences(aError);
RemoveFalseElementsOrMakeInvisible();
RemoveFalseSwitchCasesOrMakeInvisible();
if ( !iSvgError->HasError())
{
LoadImages();
}
}
return iRootElement;
}
// --------------------------------------------------------------------------
// CSvgElementImpl* CSvgContentHandler::ParseFile( CSvgDocumentImpl* aDocument,
// ---------------------------------------------------------------------------
CSvgElementImpl* CSvgContentHandler::ParseFile( CSvgDocumentImpl* aDocument,
const TDesC& aFileName,
CSvgErrorImpl& aError )
{
iDocument = aDocument;
iSvgError = &aError;
aError.SetErrorCode( ESvgNoError );
RFs session;
TInt serror = session.Connect ();
if( serror != KErrNone)
{
_LIT(STRING, "Cannot create a session to read the file.");
aError.SetErrorCode ( ESvgUnknown );
aError.SetDescription( STRING );
aError.SetIsWarning( EFalse );
return NULL;
}
// Create XML reader
RXMLReader xmlReader;
TInt error = KErrNone;
TRAP( error, xmlReader.CreateL() );
if ( !iCancelRequested && error != KErrNone )
{
_LIT(OUTMEMORY, "Out of memory");
aError.SetErrorCode( ESvgNoMemory );
aError.SetDescription( OUTMEMORY );
aError.SetIsWarning( EFalse );
return iRootElement;
}
// Parse content
xmlReader.SetContentHandler( this );
TRAP( error, xmlReader.ParseL( session, aFileName) );
xmlReader.Destroy();
if ( error != KErrNone || iRootElement == NULL )
{
_LIT(STRING, "Invalid SVG Document.");
aError.SetErrorCode( ESvgDocumentNotValid );
aError.SetDescription( STRING );
aError.SetIsWarning( EFalse );
}
else if ( !iCancelRequested )
{
SetForwardReferences(aError);
PostParseProcessing();
}
session.Close();
return iRootElement;
}
void CSvgContentHandler::PostParseProcessing()
{
// This situation occurs when parsing is done in a separate thread then the draw thread
// Wait for drawing to complete or invalid element pointer may occur during drawing
if ( iDocument->iIsRendering )
{
TInt waitCount = 0;
// total of 1 seconds
while ( waitCount++ < 200000 && iDocument->iIsRendering )
{
User::After( 50 ); // 50 microseconds
}
// Cannot wait any longer, prevent being stuck here
if ( iDocument->iIsRendering )
{
return;
}
}
iDocument->iIsPruningTree = ETrue;
RemoveFalseElementsOrMakeInvisible();
RemoveFalseSwitchCasesOrMakeInvisible();
iDocument->iIsPruningTree = EFalse;
iDocument->SetImageElementsCount(iImageElements.Count());
if ( (!iSvgError->HasError()) || iSvgError->IsWarning() )
{
LoadImages();
}
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::RemoveInternalReferences( CSvgElementImpl* )
// ---------------------------------------------------------------------------
void CSvgContentHandler::RemoveInternalReferences( CSvgElementImpl* aElement )
{
// Remove the references of aElement in content handler's lists
// Use Elements
TInt lIndex = 0;
if ( aElement->ElemID() == KSvgUseElement )
{
lIndex = iUseElementArray->Find( aElement );
if ( lIndex != KErrNotFound )
{
iUseElementArray->Remove( lIndex );
}
}
else if ( aElement->ElemID() == KSvgImageElement )
{
// Image elements
lIndex = iImageElements.Find( (CSvgImageElementImpl* )aElement );
if ( lIndex != KErrNotFound )
{
iImageElements.Remove( lIndex );
}
}
else if ( aElement->ElemID() == KSvgSwitchElement )
{
// Switch Elements
lIndex = iSwitchElementArray->Find( aElement );
if ( lIndex != KErrNotFound )
{
iSwitchElementArray->Remove( lIndex );
}
}
else if ( aElement->IsAnimatedElement() )
{
// Animation elements include animate* elements, set,
// "animation", audio elements etc.
lIndex = iAnimationElementArray->Find( aElement );
if ( lIndex != KErrNotFound )
{
iAnimationElementArray->Remove( lIndex );
}
lIndex = iAnimRefElementArray->Find( aElement );
if ( lIndex != KErrNotFound )
{
iAnimRefElementArray->Remove( lIndex );
}
}
// Elements with test attributes - requiredFeatures,
// requiredExtensions, systemLanguage
lIndex = iReqFetAttSysArray->Find( aElement );
if ( lIndex != KErrNotFound )
{
iReqFetAttSysArray->Remove( lIndex );
}
// Remove Internal references of subtree elements as well
CSvgElementImpl* lChild = ( CSvgElementImpl* )aElement->FirstChild();
while ( lChild != NULL )
{
RemoveInternalReferences( lChild );
lChild = ( CSvgElementImpl* )lChild->NextSibling();
}
}
/************* Start of MXMLContentHandler methods ************/
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::StartDocument()
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::StartDocument()
{
if ( iCancelRequested )
{
return EFalse;
}
iDocument->NotifyDocumentStart();
iBeginEndAtr = EFalse;
return ETrue;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::EndDocument()
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::EndDocument()
{
if ( iCancelRequested )
{
return EFalse;
}
iDocument->NotifyDocumentEnd();
return ETrue;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::StartElement( TDesC& aURI,
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::StartElement( TDesC& aURI,
TDesC& aLocalName,
TDesC& aName,
MXMLAttributes *aAttributeList )
{
if ( iCancelRequested )
{
return EFalse;
}
// Clear cdata buffer
iCData->Des().Zero();
TInt result = EFalse;
TRAPD( error, result = StartElementL( aURI, aLocalName, aName, aAttributeList ) );
if ( error != KErrNone )
{
_LIT(STRING, "Parsing SVG Content Failed -- Element: ");
iSvgError->SetDescription( STRING, aName );
iSvgError->SetErrorCode( ESvgUnknown );
iSvgError->SetSystemErrorCode( error );
iSvgError->SetIsWarning( EFalse );
return EFalse;
}
return result;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::StartElementL( TDesC& /* aURI */,
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::StartElementL( TDesC& /* aURI */,
TDesC& /* aLocalName */,
TDesC& aName,
MXMLAttributes *aAttributeList )
{
if ( iRootElement == NULL && aName != _L( "svg" ) )
{
iSvgError->SetDescription( _L( "Invalid SVG document: Missing Root <svg> Element." ) );
iSvgError->SetErrorCode( ESvgUnknown );
iSvgError->SetSystemErrorCode( KErrNone );
iSvgError->SetIsWarning( EFalse );
return EFalse;
}
if ( iRootElement != NULL && aName == _L( "svg" ) )
{
iSvgError->SetDescription( _L( "Invalid SVG document: Nested <svg> Element." ) );
iSvgError->SetErrorCode( ESvgUnknown );
iSvgError->SetSystemErrorCode( KErrNone );
iSvgError->SetIsWarning( EFalse );
return EFalse;
}
if ( iIgnoreDepth > 0 )
{
iIgnoreDepth++;
return ETrue;
}
MXmlElement* newElement;
newElement = iDocument->CreateElementL( aName );
if ( newElement != NULL)
{
iIsSvgElement = ETrue;
}
else
{
iDocument->NotifyUnsupportedElement( aName, *aAttributeList );
iIsSvgElement = EFalse;
iIgnoreDepth = 1;
return ETrue;
}
iCurrentElement = ( CSvgElementImpl * ) newElement;
// Set flag to indicate element is incomplete
if ( iDocument->GetLoadingListeners() &&
iDocument->GetLoadingListeners()->Count() > 0 )
{
iCurrentElement->SetAllAttributesAdded( EFalse );
}
_LIT( KElmSvg, "svg" );
if ( aName == KElmSvg && !iRootElement )
{
iDocument->AppendChildL( newElement );
iRootElement = iCurrentElement;
}
// for all other elements
else
{
iCurrentParentElement->AppendChildL( newElement );
}
// create separate lists for names and values
TInt lCount = aAttributeList->GetLength();
for ( TInt i =0 ; i< lCount ;i++)
{
ProcessNConvertAttrL( aName,
aAttributeList->GetName( i ),
aAttributeList->GetValue( i ) );
}
TInt elementID = iCurrentElement->ElemID();
//keep lists so invalid ones can be removed at the end of parsing
//all elements that have required features, extensions, sys language
if (iCurrentElement->HasAnyTests())
{
iReqFetAttSysArray->AppendL(iCurrentElement);
}
else if (elementID == KSvgSwitchElement)
{
iSwitchElementArray->AppendL(iCurrentElement);
}
if ( iBeginEndAtr )
{
((CSvgDocumentImpl*)iDocument)->iIsInteractive = ETrue;
}
if(iIsColorAnim)
{
ProcessColorAttributeL(_L("from"),iFromVal);
ProcessColorAttributeL(_L("to"),iToVal);
ProcessColorAttributeL(_L("by"),iByVal);
}
else
{
if(iFromVal.Length())
{
iCurrentElement->SetAttributeL(_L("from"),iFromVal );
}
if(iToVal.Length())
{
iCurrentElement->SetAttributeL(_L("to"),iToVal );
}
if(iByVal.Length())
{
iCurrentElement->SetAttributeL(_L("by"),iByVal );
}
}
if(iValues.Length())
{
iCurrentElement->SetAttributeL(_L("values"),iValues );
}
if(iTimes.Length())
{
iCurrentElement->SetAttributeL(_L("keyTimes"), iTimes);
}
if(iSplines.Length())
{
iCurrentElement->SetAttributeL(_L("keySplines"), iSplines);
}
if (elementID == KSvgUseElement)
{
((CSvgUseElementImpl *)iCurrentElement)->SetReferenceElementL();
}
// font-face-src is currently not implemented. Hence such a font is removed
// from the font hash-map in order to avoid creating iSvgFont pointer
// while drawing the text.
if (elementID == KSvgFontfacesrcElement )
{
//Get the font-face element which is the parent of font-face-src
CSvgFontFaceElementImpl* currentFontFaceElem =
(CSvgFontFaceElementImpl*)(iCurrentElement)->ParentNode();
const TDesC* lFontFamily=currentFontFaceElem->GetFontFamily();
currentFontFaceElem->RemoveFontFamily(*lFontFamily);
}
// comment out for future AnimationElement
// else if (elementID == KSvgAnimationElement)
// {
// ((CSvgAnimationElementImpl *)iCurrentElement)->SetReferenceElementL();
// if(((CSvgAnimationElementImpl *)iCurrentElement)->RecursionVariable())
// {
// iSvgError->SetErrorCode( ESvgDocumentNotValid );
// iSvgError->SetIsWarning( EFalse );
// iSvgError->SetDescription( _L( "Invalid Document \n" ) );
// iSvgError->AppendDescription( _L("Animation element in loop") );
// return EFalse;
// }
// User::LeaveIfError(iAnimationElementArray->Append(iCurrentElement));
// }
// For DOM reuse
if ( iCurrentElement->IsAnimatedElement() )
{
((CSvgAnimationBase*)iCurrentElement)->SetOriginalValues_DOMReuse() ;
iAnimationElementArray->AppendL(iCurrentElement);
}
if ( elementID >= KSvgLinearGradientElement &&
elementID <= KSvgStopElement )
{
iCurrentElement->SetAttributeIntL(KCSS_ATTR_DISPLAY,0);
}
// special case: <animationMotion> may have <mpath> child instead
// of "path" attribute.
if ( elementID == KSvgMpathElement &&
iCurrentParentElement->ElemID() == KSvgAnimateMotionElement &&
iSvgError->ErrorCode() == ESvgMissingRequiredAttribute &&
iSvgError->IsWarning()
)
{
iSvgError->SetErrorCode( ESvgNoError );
// add to event receiver list will have only one copy
((CSvgDocumentImpl*)iDocument)->AddToEventReceiverListL( iCurrentParentElement, KSvgEventMaskTimer );
}
if ( iCurrentElement->iReqAttrFlag != 0)
{
iSvgError->SetErrorCode( ESvgMissingRequiredAttribute );
iSvgError->SetIsWarning( ETrue );
iSvgError->SetDescription( _L( "Missing required attribute \"" ) );
switch(iCurrentElement->iReqAttrFlag)
{
case KAtrSVGRec:
iSvgError->AppendDescription( WIDTH );
iSvgError->AppendDescription( _L( "\" and \"" ) );
iSvgError->AppendDescription(_L("height"));
break;
case KAtrSVGElp:
iSvgError->AppendDescription( _L("Rx") );
iSvgError->AppendDescription( _L( "\" and \"" ) );
iSvgError->AppendDescription(_L("Ry"));
break;
case KAtrSVGTrf:
iSvgError->AppendDescription( _L("attributeName") );
iSvgError->AppendDescription( _L( "\" and \"" ) );
iSvgError->AppendDescription(_L("type"));
break;
case KSVG_ANIMATE_ELEMFLAG:
iSvgError->AppendDescription( _L("attributeName") );
break;
case KSVG_CIRCLE_ELEMFLAG:
iSvgError->AppendDescription( _L("r") );
break;
case KSVG_HKERN_ELEMFLAG:
iSvgError->AppendDescription( _L("k") );
break;
case KSVG_PATH_ELEMFLAG:
iSvgError->AppendDescription( _L("d") );
break;
case KSVG_POLYLINE_ELEMFLAG:
iSvgError->AppendDescription( _L("points") );
break;
case KAtrType:
iSvgError->AppendDescription( _L("type") );
break;
case KAtrRy:
iSvgError->AppendDescription( _L("Ry") );
break;
case KAtrRx:
iSvgError->AppendDescription( _L("Rx") );
break;
case KAtrWidth:
iSvgError->AppendDescription( _L("width") );
break;
case KAtrHeight:
iSvgError->AppendDescription( _L("height") );
break;
case KAtrXlinkhref:
iSvgError->AppendDescription (_L("Xlink:href"));
break;
case KAtrSVGAmo:
iSvgError->AppendDescription( _L("path") );
((CSvgDocumentImpl*)iDocument)->RemoveFromEventReceiverList( iCurrentElement );
break;
case KAtrToBy:
iSvgError->AppendDescription( _L("to/by") );
((CSvgDocumentImpl*)iDocument)->RemoveFromEventReceiverList( iCurrentElement );
break;
}
iSvgError->AppendDescription( _L( "\" for <" ) );
// access schema data to get the name of the attribute which is missing
// currently the error msg doesnt not report the name of the attribute
iSvgError->AppendDescription( aName );
iSvgError->AppendDescription( _L( ">." ) );
TInt32 displayValue = KDisplayEnumNone;
TInt lRetValue = ((CSvgElementImpl*)iCurrentElement)->GetAttributeIntL( KCSS_ATTR_DISPLAY, displayValue );
// turn off element if the display attribute is not declared OR if declared its value is "!none"
if( (lRetValue == KErrNoAttribute)||(displayValue != KDisplayEnumNone ) )
{
((CSvgElementImpl*)iCurrentElement)->SetPropertyL(KCSS_ATTR_DISPLAY,_L("none"));
// the following boolean is added to show that the element is explicitly
// "turned off" due to the absence of the required attribute for the element,
// this element can again be "turned on" when the required attribute is present.
((CSvgElementImpl*)iCurrentElement)->SetTurnOff( ETrue );
}
}
if ( elementID == KSvgImageElement )
{
iImageElements.Append( (CSvgImageElementImpl*)iCurrentElement );
}
else if ( elementID == KSvgGElement && !((CSvgDocumentImpl*)iDocument)->iHasGroupOpacity)
{
if ( ((CSvgDocumentImpl*)iDocument)->isGroupOpacity( iCurrentElement ))
{
((CSvgDocumentImpl*)iDocument)->iHasGroupOpacity = ETrue;
}
}
// Check for invalid child element of leave elements
if ( KSvgRectElement == elementID && iCurrentElement->ParentNode() &&
KSvgRectElement == ((CSvgElementImpl*)iCurrentElement->ParentNode())->ElemID() )
{
_LIT( KMsg, "Invalid child of <rect> element: " );
iDocument->SetError( KErrNotFound, KMsg, aName );
}
// Notify Loading Listeners of element-start
// Send info if element is <svg> or immediate child of <svg>
TBool isRootOrChild = (elementID == KSvgSvgElement);
if (iCurrentElement->ParentNode())
{
isRootOrChild = (iCurrentElement->ElemID() == KSvgSvgElement) || (((CSvgElementImpl*)iCurrentElement->ParentNode())->ElemID() == KSvgSvgElement);
}
// Update CTM for new element (if there is a LoadingListener)
if ( iDocument->GetLoadingListeners() &&
iDocument->GetLoadingListeners()->Count() > 0 )
{
iCurrentElement->UpdateCTM();
iCurrentElement->SetAllAttributesAdded( ETrue );
}
iDocument->NotifyElementStart( aName, *aAttributeList, isRootOrChild );
// Current element becomes new parent for higher depths
iCurrentParentElement = iCurrentElement;
return ETrue;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::EndElement( TDesC& /* aURI */, TDesC& /* aLocalName */, TDesC& aTagName )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::EndElement( TDesC& /* aURI */, TDesC& /* aLocalName */, TDesC& aTagName )
{
if ( iCancelRequested )
{
return EFalse;
}
// iCurrentElement = NULL; //will do it in ReaderIndex
if ( iIgnoreDepth > 0 )
{
iIgnoreDepth--;
if ( iIgnoreDepth == 0 )
{
iIsSvgElement = ETrue;
}
return ETrue;
}
// Notify Loading Listeners of element-end
// Send info if element is <svg> or immediate child of <svg>
TBool isRootOrChild = ( iRootElement == iCurrentParentElement ) ||
( iRootElement == iCurrentParentElement->ParentNode() );
iDocument->NotifyElementEnd( aTagName, isRootOrChild );
if ( iCurrentParentElement != iRootElement )
{
// Depth is decreased, so the current parent should be one level up
iCurrentParentElement = ( CSvgElementImpl * )
iCurrentParentElement->ParentNode();
}
if( ((CSvgElementImpl*)iCurrentElement->ParentNode()) != NULL )
{
if((((((CSvgElementImpl*)iCurrentElement->ParentNode())->ElemID()) == KSvgRadialGradientElement) ||
((((CSvgElementImpl*)iCurrentElement->ParentNode())->ElemID()) == KSvgLinearGradientElement) ) &&
( ((CSvgElementImpl*)iCurrentElement)->ElemID() == KSvgStopElement))
{
CSvgGradientElementImpl *parent = ((CSvgGradientElementImpl *)iCurrentElement->ParentNode());
if(parent)
{
// Initialize the offset value to 0 if its still -1.
TFloatFixPt lOffsetValue;
TFloatFixPt lDefaultOffsetValue(-1);
TBuf<6> lAttributeName;
TBuf<1> lValueBuffer;
lAttributeName.Append(OFFSET);
lValueBuffer.Append(ZEROVALUE);
((CSvgStopElementImpl*)iCurrentElement)->GetOffset( lOffsetValue );
// Offset Value of -1 indicates that Offset Attribute is not declared in
// stop element.
if( lOffsetValue == lDefaultOffsetValue )
{
// Deliberately calling SetAttributeL in place of SetAttributeFloatL as the latter inturn
// calls UpdateOffsetValues which should be called on any Stop element once it is added to
// to the Stop element array Owned by parent Gradient element.
TRAP_IGNORE( ((CSvgStopElementImpl*)iCurrentElement)->SetAttributeL( lAttributeName, lValueBuffer ) );
}
// The function not only adds the element in Stop element array but also
// adjusts the offset values of all the previously added elements such that
// each gradient offset value is greater than the previous gradient stop's
// offset value. It calls UpdateOffsetValues to adjust the values.
((CSvgGradientElementImpl *)parent)->AddStopElementInArray((CSvgStopElementImpl*)iCurrentElement);
}
}
}
iIsColorAnim = EFalse;
iFromVal.Set( TPtrC() );
iToVal.Set( TPtrC() );
iByVal.Set( TPtrC() );
iValues.Set(TPtrC() );
iTimes.Set( TPtrC() );
iSplines.Set( TPtrC());
return ETrue;
}
// this method is called by xml-parser for cdata
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::Charecters( TDesC& aBuf, TInt aStart , TInt aLength )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::Charecters( TDesC& aBuf, TInt aStart , TInt aLength )
{
if ( iCancelRequested )
{
return EFalse;
}
AppendToCData( aBuf );
if ( !iCurrentElement )
{
return ETrue;
}
TUint8 id = iCurrentElement->ElemID();
if ( id == KSvgTextElement || id == KSvgTextAreaElement || id == KSvgDescElement || id == KSvgTitleElement || id == KSvgMetadataElement)
{
if(id == KSvgTextElement)
{
((CSvgTextElementImpl*)iCurrentElement)->SetFileOffset(aStart);
((CSvgTextElementImpl*)iCurrentElement)->SetOrgLength(aLength);
}
else if (id == KSvgTextAreaElement)
{
// KSvgTextAreaElement
((CSvgTextAreaElementImpl*)iCurrentElement)->SetFileOffset(aStart);
((CSvgTextAreaElementImpl*)iCurrentElement)->SetOrgLength(aLength);
}
//First get the elements previous text & append the new text
TPtrC elementText;
iCurrentElement->GetAttributeDes(KAtrCdata , elementText);
iCData->Des().Zero();
AppendToCData(elementText);
AppendToCData(aBuf);
TRAPD( error, iCurrentElement->SetAttributeDesL( KAtrCdata, *iCData ) );
if (error != KErrNone)
{
//do something here.
}
}
else if ( id == KSvgScriptElement )
{
RDebug::Printf("Calling SetScriptL\n" );
TRAPD( error2, ((CSvgScriptElementImpl*)iCurrentElement)->SetScriptL( *iCData ) );
if (error2 != KErrNone)
{
//do something here
}
}
return ETrue;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::DataBuffer( const TDesC16& aBuf)
// ---------------------------------------------------------------------------
void CSvgContentHandler::DataBuffer( const TDesC16& aBuf)
{
if(iRootElement && !((CSvgSvgElementImpl *)iRootElement)->iContent )
{
((CSvgSvgElementImpl *)iRootElement)->iContent = HBufC::New(aBuf.Length());
if( ((CSvgSvgElementImpl *)iRootElement)->iContent == NULL)
return;
else
((CSvgSvgElementImpl *)iRootElement)->iContent->Des().Copy(aBuf);
}
return;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::Comment( TDesC& /* aComment */ )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::Comment( TDesC& /* aComment */ )
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::ProcessingInstructions( TDesC& /* aTarget */, TDesC& /* aData */ )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::ProcessingInstructions( TDesC& /* aTarget */, TDesC& /* aData */ )
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::IgnoreWhiteSpace( TDesC& /* aString */ )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::IgnoreWhiteSpace( TDesC& /* aString */ )
{
return !iCancelRequested;
}
// ---------------------------------------------------------------------------
// Called by XML parser when a valid '&...;' is encountered
// The entity character must be appended to call previous called of "Charecters"
// & 'StartEntity".
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::StartEntity( TDesC& aName )
{
// Parse entity for possible svg subtree
// ParseEntity return ETrue if it has valid subtree and parsing successful.
// Otherwise append entity as part of CData.
if ( ParseEntity( aName ) )
{
return ETrue;
}
if ( iCancelRequested )
{
return EFalse;
}
// content generated with tool uses 0x2019 for apostrophe
if ( aName.Length() == 1 && aName[0] == 0x2019 )
{
AppendToCData( _L( "'" ) );
}
else
{
AppendToCData( aName );
}
// Set CData attribute
if (!iCurrentElement)
{
return ETrue;
}
TUint8 id = iCurrentElement->ElemID();
if ( (id == KSvgTextElement) || (id == KSvgTextAreaElement) || (id == KSvgTitleElement) || (id == KSvgDescElement) || (id == KSvgMetadataElement))
{
TRAPD( error, iCurrentElement->SetAttributeDesL( KAtrCdata, *iCData ) );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("CSvgContentHandler::StartEntity error occurred.");
#endif
}
}
return ETrue;
}
// ---------------------------------------------------------------------------
// Check to see if entity may be needed for parsing
// If so, attemp to parse it as parse of the document
// Return ETrue if parse was successfull, EFalse otherwise.
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ParseEntity( const TDesC& aEntity )
{
// Look for '<' and '>' to narrow possibility of svg entity
TInt startPos = aEntity.Locate( TChar( '<' ) );
if ( startPos == KErrNotFound )
{
return EFalse;
}
TInt endPos = aEntity.LocateReverse( TChar( '>' ) );
if ( endPos == KErrNotFound || endPos < startPos )
{
return EFalse;
}
// Create XML parser
RXMLReader xmlReader;
TInt error = KErrNone;
TRAP( error, xmlReader.CreateL() );
if ( error != KErrNone )
{
return EFalse;
}
// Copy entity string to byte-array
// Enclosed within <g> element to ensure all elements are parsed
_LIT8( KBeginTag, "<g>" );
_LIT8( KEndTag, "</g>" );
HBufC8* buf8 = NULL;
// create length + room for KBeginTag & KEndTag
buf8 = HBufC8::New( aEntity.Length() + 7 );
if ( buf8 == NULL )
{
xmlReader.Destroy();
return EFalse;
}
TPtr8 des = buf8->Des();
des.Copy( KBeginTag );
des.Append( aEntity );
des.Append( KEndTag );
// Parse content
xmlReader.SetContentHandler( this );
TRAPD( parseError, xmlReader.ParseL( *buf8 ) );
// Cleanup
delete buf8;
xmlReader.Destroy();
return parseError == KErrNone;
}
// ---------------------------------------------------------------------------
// Called by XML parser when a valid '&...;' is encountered
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::EndEntity( TDesC& /*aName*/ )
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::SkippedEntity( TDesC& /*aName*/ )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::SkippedEntity( TDesC& /*aName*/ )
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::StartCDATA()
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::StartCDATA()
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::EndCDATA()
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::EndCDATA()
{
return !iCancelRequested;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::Error( TInt /* aErrorCode */, TInt /* aSeverity */ )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::Error( TInt /* aErrorCode */, TInt /* aSeverity */ )
{
return EFalse;
}
/************* End of MXMLContentHandler methods ************/
// --------------------------------------------------------------------------
// void CSvgContentHandler::AppendToCData( const TDesC& aText )
// ---------------------------------------------------------------------------
void CSvgContentHandler::AppendToCData( const TDesC& aText )
{
// Check to see if appending will overflow
if ( iCData->Des().MaxLength() < iCData->Length() + aText.Length() )
{
HBufC* newBuf = HBufC::NewMax( iCData->Length() + aText.Length() );
// Fail to allocate new buffer
if ( newBuf == NULL )
return;
newBuf->Des().Copy( *iCData );
delete iCData;
iCData = newBuf;
}
iCData->Des().Append( aText );
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ProcessColorAttributeL( const TDesC& aName,
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ProcessColorAttributeL( const TDesC& aName,
const TDesC& aValue )
{
TUint32 tempColor;
if( aValue.Length() )
{
if(aValue == _L("freeze") )
{
iCurrentElement->SetAttributeL( aName, aValue);
return ETrue;
}
if ( aValue == _L( "inherit" ) )
{
return EFalse;
}
if ( aValue != _L( "none" ) && aValue != _L( "currentColor" ) && aValue.Left(3)!=_L("url") )
{
TBufC<24> lColBuf;
TSvgColor tColor(KGfxColorNull);
if ( tColor.GetStringL( aValue, tempColor ) == EFalse )
{
TInt32 defColor = 0;//default color
( ( CSvgElementImpl * ) iCurrentElement->ParentNode() )->GetAttributeIntL( KAtrFill,
defColor );
_LIT( KFixptFormat, "%d" );
( lColBuf.Des() ).Format( KFixptFormat, defColor );
}
else
{
_LIT( KFixptFormat, "%d" );
( lColBuf.Des() ).Format( KFixptFormat, tempColor );
}
iCurrentElement->SetAttributeL( aName, lColBuf);
}
else
{
iCurrentElement->SetAttributeL( aName, aValue);
}
return ETrue;
}
return EFalse;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ProcessStyleL( const TDesC& aValue )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ProcessStyleL( const TDesC& aValue )
{
TPtrC remaining;
remaining.Set( aValue );
TPtrC name;
TPtrC value;
TInt semicolonIndex = remaining.Find( _L( ";" ) );
while ( semicolonIndex != KErrNotFound )
{
// make substring, excluding ';'
TPtrC nameValuePair;
nameValuePair.Set( remaining.Ptr(), semicolonIndex );
// Extract name, value
if ( ExtractStyleValuePair( nameValuePair, name, value ) )
{
// store property
TInt attributeID = (((CSvgDocumentImpl*)iDocument)->SchemaData())->GetPresentationAttributeId( name );
if ( attributeID != KErrNotFound )
iCurrentElement->SetPropertyL( attributeID, value );
else
iCurrentElement->SetAttributeL( name, value );
}
// shorten remaining, start at first character after semicolon
remaining.Set( (TUint16*)&remaining.Ptr()[semicolonIndex+1],
remaining.Length() - nameValuePair.Length() - 1 );
semicolonIndex = remaining.Find( _L( ";" ) );
}
// process remaining pair if exists
if ( ExtractStyleValuePair( remaining, name, value ) )
{
// store property
TInt attributeID = (((CSvgDocumentImpl*)iDocument)->SchemaData())->GetPresentationAttributeId( name );
if ( attributeID != KErrNotFound )
iCurrentElement->SetPropertyL( attributeID, value );
else
iCurrentElement->SetAttributeL( name, value );
}
return ETrue;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ProcessTransformL( const TDesC& /*aName*/,
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ProcessTransformL( const TDesC& /*aName*/,
const TDesC& aValue )
{
_LIT( KCb, ")" );
_LIT(KTransform ,"transform");
// Prepare the style value string for parsing
// Should be like transform=matrix( 1 0 0 1 6 6 )
// Notice the space after and not before ( and the space before )
HBufC* tFinal = HBufC::NewLC( aValue.Length() + 1000 );
TPtr tPf = tFinal->Des();
// 1. Copy to a temp buffer
HBufC* tBufC = HBufC::NewLC( aValue.Length() );// In case we need room for two extra spaces
TPtr tPtr = tBufC->Des();
tPtr.Copy( aValue );
// 2. Replace "funny" chars to spaces
tPtr.TrimAll();
TStringTokenizer lTokenizer ( tPtr, KCb );
while ( lTokenizer.HasMoreTokens() )
{
TPtrC lToken ( lTokenizer.NextToken( KCb ) );
TInt pos;
_LIT( KSp, " " );
HBufC* tBufC2 = HBufC::NewLC( lToken.Length() + 4 );
TPtr tPtr2 = tBufC2->Des();
tPtr2.Copy( lToken );
const TUint16* lValStr = tPtr2.Ptr();
// Remove spaces between transformation type keyword and (
pos = tPtr2.Locate( '(' );
while ( lValStr[pos - 1] == ' ' )
{
tPtr2.Delete( pos - 1, 1 );
lValStr = tPtr2.Ptr();
pos = tPtr2.Locate( '(' );
}
// Add space after (
pos = tPtr2.Locate( '(' );
if ( pos != KErrNotFound &&
pos < ( tPtr2.Length() - 1 ) &&
lValStr[pos + 1] != ' ' )
{
tPtr2.Insert( pos + 1, KSp );
lValStr = tPtr2.Ptr();
}
// Replace ',' with space
pos = tPtr2.Locate( ',' );
while ( pos != KErrNotFound )
{
tPtr2.Replace( pos, 1, KSp );
lValStr = tPtr2.Ptr();
pos = tPtr2.Locate( ',' );
}
// Add space at end
tPtr2.Append( KSp );
// Add ) to end
tPtr2.Append( KCb );
// Add space at end
tPtr2.Append( KSp );
const TUint16* lVal2 = tPtr2.Ptr();
tPf.Append( lVal2, tPtr2.Length() );
CleanupStack::PopAndDestroy( 1 ); // tBufC2
}
iCurrentElement->SetTransform(KTransform,tPf);
CleanupStack::PopAndDestroy( 2 ); // tBufC & TFinal
return ETrue;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ProcessUnitsL( const TDesC& /*aName*/, const TDesC& /*aValue*/ )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ProcessUnitsL( const TDesC& /*aName*/, const TDesC& /*aValue*/ )
{
return ETrue;
}
/************** XML Entity Character Methods ****************/
// --------------------------------------------------------------------------
// void CSvgContentHandler::ConvertEntitiesToCharsL( CDesCArrayFlat& aArray )
// ---------------------------------------------------------------------------
void CSvgContentHandler::ConvertEntitiesToCharsL( CDesCArrayFlat& aArray )
{
TInt lCount = aArray.Count();
for ( TInt i = 0; i < lCount; i++ )
{
HBufC* substituteString = ConvertEntitiesToCharsL( aArray[i] );
if ( substituteString != NULL )
{
CleanupStack::PushL( substituteString );
aArray.Delete( i );
aArray.InsertL( i, *substituteString );
CleanupStack::PopAndDestroy(substituteString);
}
}
}
// --------------------------------------------------------------------------
// HBufC* CSvgContentHandler::ConvertEntitiesToCharsL( const TDesC& aString )
// ---------------------------------------------------------------------------
HBufC* CSvgContentHandler::ConvertEntitiesToCharsL( const TDesC& aString )
{
// no entity, return NULL
TInt pos = Find( aString, 0, '&' );
if ( pos == -1 )
{
return NULL;
}
HBufC* substituteString = HBufC::NewLC( aString.Length() );
TPtr ptr = substituteString->Des();
TInt endPos = 0;
TChar substituteChar = ' ';
while ( pos != -1 )
{
// copy up to pos
Append( ptr, aString, endPos, pos );
// no entity ending character, copy to end of string
endPos = Find( aString, pos, ';' );
if ( endPos == -1 )
{
endPos = aString.Length()-1;
}
endPos++;
HBufC* entity = SubstringL( aString, pos, endPos );
// entity is converted to char
if ( ConvertEntityToChar( substituteChar, *entity ) )
{
ptr.Append( substituteChar );
}
// no such entity, copy original string
else
{
ptr.Append( *entity );
}
delete entity;
pos = Find( aString, endPos, '&' );
}
// check end leftover
if ( endPos < aString.Length() )
{
Append( ptr, aString, endPos, aString.Length() );
}
CleanupStack::Pop( substituteString );
return substituteString;
}
// --------------------------------------------------------------------------
// TInt CSvgContentHandler::Find( const TDesC& aString, TInt aStartIndex, TChar aChar )
// ---------------------------------------------------------------------------
TInt CSvgContentHandler::Find( const TDesC& aString, TInt aStartIndex, TChar aChar )
{
TInt lCount = aString.Length();
for ( TInt i = aStartIndex; i < lCount; i++ )
{
if ( aString[i] == (TUint16)aChar )
{
return i;
}
}
return -1;
}
// --------------------------------------------------------------------------
// HBufC* CSvgContentHandler::SubstringL( const TDesC& aString, TInt aStartIndex, TInt aEndIndex )
// ---------------------------------------------------------------------------
HBufC* CSvgContentHandler::SubstringL( const TDesC& aString, TInt aStartIndex, TInt aEndIndex )
{
HBufC* substring = HBufC::NewL( aEndIndex - aStartIndex );
TPtr ptr = substring->Des();
TInt lCount = aString.Length();
for ( TInt i = aStartIndex; i < aEndIndex && i < lCount ; i++ )
{
ptr.Append( aString[i] );
}
return substring;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::Append( TDes& aDest, const TDesC& aSource, TInt aStartIndex, TInt aEndIndex )
// ---------------------------------------------------------------------------
void CSvgContentHandler::Append( TDes& aDest, const TDesC& aSource, TInt aStartIndex, TInt aEndIndex )
{
TInt lCount = aSource.Length();
for ( TInt i = aStartIndex; i < aEndIndex && i < lCount; i++ )
{
aDest.Append( aSource[i] );
}
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ConvertEntityToChar( TChar& aChar, const TDesC& aString )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ConvertEntityToChar( TChar& aChar, const TDesC& aString )
{
if ( aString == _L( "&" ) )
{
aChar = '&';
}
else if ( aString == _L( """ ) )
{
aChar = '"';
}
else if ( aString == _L( "'" ) )
{
aChar = '\'';
}
else if ( aString == _L( "<" ) )
{
aChar = '<';
}
else if ( aString == _L( ">" ) )
{
aChar = '>';
}
// need to check for '&#xx'
else if ( ConvertHexStringToChar( aChar, aString ) )
{
}
else if ( ConvertDecimalStringToChar( aChar, aString ) )
{
}
return ETrue;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ConvertDecimalStringToChar( TChar& aChar, const TDesC& aString )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ConvertDecimalStringToChar( TChar& aChar, const TDesC& aString )
{
TLex parser( aString );
// skip '&'
parser.Inc();
if ( !parser.Eos() && parser.Peek() == '#' )
{
parser.Inc();
TUint value = 0;
if ( parser.Val( value, EDecimal ) == KErrNone )
{
aChar = value;
return ETrue;
}
}
return EFalse;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ConvertHexStringToChar( TChar& aChar, const TDesC& aString )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ConvertHexStringToChar( TChar& aChar, const TDesC& aString )
{
TLex parser( aString );
// skip '&'
parser.Inc();
if ( !parser.Eos() && parser.Peek() == '#' )
{
parser.Inc();
if ( !parser.Eos() && ( parser.Peek() == 'x' || parser.Peek() == 'X' ) )
{
parser.Inc();
TUint value = 0;
if ( parser.Val( value, EHex ) == KErrNone )
{
aChar = value;
return ETrue;
}
}
}
return EFalse;
}
// ---------------------------------------------------------------------------
// Filter entity characters for cdata characters
// ---------------------------------------------------------------------------
void CSvgContentHandler::FilterCharactersL( TDesC& aString )
{
HBufC* filteredValue = ConvertEntitiesToCharsL( aString );
if ( filteredValue == NULL )
{
iCurrentElement->SetAttributeDesL( KAtrCdata, aString );
}
else
{
CleanupStack::PushL( filteredValue );
iCurrentElement->SetAttributeDesL( KAtrCdata, *filteredValue );
CleanupStack::PopAndDestroy(filteredValue);
}
}
// ---------------------------------------------------------------------------
// File Offset for the closing tag
// ---------------------------------------------------------------------------
void CSvgContentHandler::ReaderIndex(NW_Uint32 aIndex)
{
if ( iCurrentElement )
{
TUint8 id = iCurrentElement->ElemID();
TInt OrgLength;
if ( id == KSvgTextElement || id == KSvgTextAreaElement)
{
if(id==KSvgTextElement)
{
OrgLength = ((CSvgTextElementImpl *)iCurrentElement)->GetOrgLength();
if(!OrgLength)
((CSvgTextElementImpl *)iCurrentElement)->SetFileOffset(aIndex);
}
else
{
OrgLength = ((CSvgTextAreaElementImpl *)iCurrentElement)->GetOrgLength();
if(!OrgLength)
((CSvgTextAreaElementImpl *)iCurrentElement)->SetFileOffset(aIndex);
}
}
}
// Set the current element pointer back to parent as we are
// going up the tree now.
iCurrentElement = iCurrentParentElement;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ProcessNConvertAttrL( const TDesC& aName, const TDesC& aAttrName,const TDesC& aAttrValue )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ProcessNConvertAttrL( const TDesC& aName, const TDesC& aAttrName,const TDesC& aAttrValue )
{
TInt tmpAttrID = 0;
TBool isSvgElement = EFalse ;
if (
(iCurrentElement->ElemID() == KSvgSvgElement)
&& ( aAttrName == WIDTH )
)
{
TInt lFindValue = aAttrValue.Locate('%');
isSvgElement = ETrue ;
if (lFindValue != KErrNotFound)
{
((CSvgSvgElementImpl *)iCurrentElement)->iWidthInPercentage = ETrue;
TLex lLex(aAttrValue);
TReal32 attValue=0;
if (lLex.Val(attValue, '.' ) == KErrNone)
{
((CSvgSvgElementImpl *)iCurrentElement)->iWidthInUserCoordinate = attValue;
}
}
else
{
((CSvgSvgElementImpl *)iCurrentElement)->iWidthInPercentage = EFalse;
}
}
if (
(iCurrentElement->ElemID() == KSvgSvgElement)
&& ( aAttrName == HEIGHT )
)
{
TInt lFindValue = aAttrValue.Locate('%');
isSvgElement = ETrue ;
if (lFindValue != KErrNotFound)
{
((CSvgSvgElementImpl *)iCurrentElement)->iHeightInPercentage = ETrue;
TLex lLex(aAttrValue);
TReal32 attValue=0;
if (lLex.Val(attValue, '.' ) == KErrNone)
{
((CSvgSvgElementImpl *)iCurrentElement)->iHeightInUserCoordinate = attValue;
}
}
else
{
((CSvgSvgElementImpl *)iCurrentElement)->iHeightInPercentage = EFalse;
}
}
//#ifdef RD_SVGT_MEDIAANIMATION_SUPPORT
if (aName ==_L("animation") )
{
_LIT(KX, "x");
_LIT(KY, "y");
if(aAttrName == WIDTH || aAttrName == HEIGHT )
{
TLex lLex(aAttrValue);
TReal32 attValue=0;
if (lLex.Val(attValue, '.' ) == KErrNone)
{
if ( attValue < 0 )//if values are negative then default to 0
attValue = 0;
if( aAttrName == WIDTH )
((CSvgMediaAnimationElementImpl *)iCurrentElement)->SetWidth(attValue);
else
((CSvgMediaAnimationElementImpl *)iCurrentElement)->SetHeight(attValue);
}
return ETrue;
}
if(!(aAttrName == KX) && !(aAttrName == KY ))
{
HBufC* tBufC = HBufC::NewLC( aAttrValue.Length() );
TPtr tPtr ( tBufC->Des() );
tPtr.Copy( aAttrValue );
tPtr.TrimAll();
iCurrentElement->SetAttributeL(aAttrName,tPtr );
CleanupStack::PopAndDestroy( 1 ); // tBufC
return ETrue;
}
}
//endif
if ( !iBeginEndAtr && ( aAttrName == BEGIN || aAttrName == END ) )
{
if ( ( aAttrValue.Find( MOUSEDOWN ) != KErrNotFound ) ||
( aAttrValue.Find( MOUSEUP ) != KErrNotFound ) ||
( aAttrValue.Find( MOUSEOVER ) != KErrNotFound ) ||
( aAttrValue.Find( MOUSEMOVE ) != KErrNotFound ) ||
( aAttrValue.Find( MOUSEOUT ) != KErrNotFound ) ||
( aAttrValue.Find( FOCUSIN ) != KErrNotFound ) ||
( aAttrValue.Find( FOCUSOUT ) != KErrNotFound ) ||
( aAttrValue.Find( ACTIVATE ) != KErrNotFound ) ||
( aAttrValue.Find( CLICK ) != KErrNotFound ) ||
( aAttrValue.Find( ACCESS ) != KErrNotFound ) )
iBeginEndAtr = ETrue;
}
if( iCurrentElement->ElemID() < KSvgAnimateElement || iCurrentElement->ElemID() > KSvgSetElement )
{
tmpAttrID = (( ( CSvgDocumentImpl* ) iDocument )->SchemaData())->GetPresentationAttributeId(aAttrName);
if( tmpAttrID != KErrNotFound )
{
iCurrentElement->SetPropertyL( tmpAttrID, aAttrValue);
return ETrue;
}
}
tmpAttrID = (( ( CSvgDocumentImpl* ) iDocument )->SchemaData())->GetSVGTAttributeId(aAttrName);
if ( iCurrentElement->ElemID() == KSvgTextAreaElement && aAttrName == _L("editable") )
{
((CSvgTextAreaElementImpl*)iCurrentElement)->SetEditable( aAttrValue );
}
if ( iCurrentElement->ElemID() == KSvgTextElement && aAttrName == _L("editable") )
{
((CSvgTextElementImpl*)iCurrentElement)->SetEditable( aAttrValue );
}
if ( iCurrentElement->ElemID() >= KSvgMediaElemsStartIndex &&
iCurrentElement->ElemID() <= KSvgMediaElemsEndIndex )
{
TBool lIsAttrProcessed = ETrue;
switch ( tmpAttrID )
{
case KAtrSyncBehavior:
((CSvgMediaElementBase* )iCurrentElement)->SetSyncBehavior(
aAttrValue );
break;
case KAtrSyncTolerance:
((CSvgMediaElementBase* )iCurrentElement)->SetSyncTolerance(
aAttrValue );
break;
case KAtrSyncMaster:
((CSvgMediaElementBase* )iCurrentElement)->SetSyncMaster(
aAttrValue );
break;
default:
lIsAttrProcessed = EFalse;
}
if ( lIsAttrProcessed )
{
return ETrue;
}
}
if ( iCurrentElement->ElemID() == KSvgSvgElement )
{
TBool lIsAttrProcessed = ETrue;
switch ( tmpAttrID )
{
case KAtrSyncBehaviorDefault:
((CSvgSvgElementImpl* )iCurrentElement)->SetSyncBehaviorDefault(
aAttrValue );
break;
case KAtrSyncToleranceDefault:
((CSvgSvgElementImpl* )iCurrentElement)->SetSyncToleranceDefault(
aAttrValue );
break;
default:
lIsAttrProcessed = EFalse;
}
if ( lIsAttrProcessed )
{
return ETrue;
}
}
if ( iCurrentElement->ElemID() == KSvgMediaAnimationElement &&
tmpAttrID == KAtrInitialVisibility )
{
// Merge with the animation->SetInitialVisibility here.
return ETrue;
}
if((tmpAttrID == KAtrOffset)|| ((tmpAttrID >= KSvgNotHandledAttrsIndex
|| (tmpAttrID==KAtrRotate && iCurrentElement->ElemID()==KSvgAnimateMotionElement)) && (tmpAttrID != KAtrValues )
&& (tmpAttrID != KAtrKeySplines) && ( tmpAttrID != KAtrKeyTimes))
&&(tmpAttrID != KAtrFx)&& (tmpAttrID != KAtrFy)&& (tmpAttrID != KAtrGradientTransform)
&& (aName !=_L("animation") ) )
{
HBufC* tBufC = HBufC::NewLC( aAttrValue.Length() );
TPtr tPtr ( tBufC->Des() );
tPtr.Copy( aAttrValue );
tPtr.TrimAll();
TInt errorCode = iCurrentElement->SetAttributeL(aAttrName,tPtr );
if(errorCode == KErrReferencedElementNotFound)
{
//Error Code returned By USE Element when Forward reference element not Found
iUseElementArray->AppendL(iCurrentElement);
}
if(errorCode == KErrAnimateReferenceElementNotFound )
{
//Error Code returned By Animation Element when Forward reference element not Found
iAnimRefElementArray->AppendL(iCurrentElement);
}
CleanupStack::PopAndDestroy( 1 );
}
else if( tmpAttrID == KAtrAttributeName )
{
if( aAttrValue == FILL || aAttrValue == STROKE || aAttrValue == COLOR
|| aAttrValue == STOP_COLOR )
{
iIsColorAnim = ETrue;
}
HBufC* tBufC = HBufC::NewLC( aAttrValue.Length() );
TPtr tPtr ( tBufC->Des() );
tPtr.Copy( aAttrValue );
tPtr.TrimAll();
iCurrentElement->SetAttributeL(aAttrName,tPtr );
CleanupStack::PopAndDestroy( 1 );
}
else if( tmpAttrID == KAtrValues )
{
iValues.Set(TPtrC( aAttrValue ) );
}
else if( tmpAttrID == KAtrKeyTimes )
{
iTimes.Set(TPtrC( aAttrValue ));
}
else if( tmpAttrID == KAtrKeySplines )
{
iSplines.Set(TPtrC (aAttrValue));
}
else if( tmpAttrID == KAtrTransform &&
(iCurrentElement->ElemID() != KSvgRadialGradientElement && iCurrentElement->ElemID()
!= KSvgLinearGradientElement)
)
{
ProcessTransformL(aAttrName,aAttrValue );
}
//Added the below else-if block to support the % values for X1,Y1,X2,Y2 of LinearGradient element.
else if( tmpAttrID >= KAtrY1 && tmpAttrID <= KAtrX2 && iCurrentElement->ElemID() == KSvgLinearGradientElement )
{
iCurrentElement->SetAttributeL( aAttrName , aAttrValue);
}
else if (tmpAttrID == KAtrGradientTransform &&
(iCurrentElement->ElemID() == KSvgRadialGradientElement || iCurrentElement->ElemID()
== KSvgLinearGradientElement))
{
ProcessTransformL(aAttrName,aAttrValue );
}
else if( tmpAttrID == KAtrStyle )
{
ProcessStyleL(aAttrValue);
}
else if( tmpAttrID == KAtrFrom)
{
iFromVal.Set( TPtrC( aAttrValue ) );
}
else if( tmpAttrID == KAtrTo)
{
iToVal.Set( TPtrC( aAttrValue ) );
}
else if ( tmpAttrID == KAtrBy )
{
iByVal.Set( TPtrC( aAttrValue ) );
}
else if (( tmpAttrID >= KSvgDesAttrsIndex ||
(iCurrentElement->ElemID() == KSvgTextElement &&
(tmpAttrID == KAtrX || tmpAttrID == KAtrY))) && (tmpAttrID != KAtrFx)&& (tmpAttrID != KAtrFy)
&&(aName !=_L("animation") ) )
{
iCurrentElement->SetAttributeDesL( tmpAttrID, aAttrValue);
}
else if ( iCurrentElement->ElemID() == KSvgScriptElement )
{
iCurrentElement->SetAttributeL( aAttrName, aAttrValue);
}
else
{
// check if the datatype is lenth.datatype or coordinate.datatype
TUint8 datatype = ( (TUint8) (tmpAttrID < KSvgCoordAttrStartIndex ? KSVG_LENGTH_TYPE : KSVG_COORDINATE_TYPE) );
TReal32 convertedValue;
if( CSvgAttributeVerifier::ValidAttrValue(aAttrValue, convertedValue, datatype, aAttrName, isSvgElement) )
{
//check for valid width height
//specific checking for svgElement width height
//particularly the case when width height values
//in percentages cannot be greater than 100
if( iCurrentElement->ElemID() == KSvgSvgElement )
{
if(
(aAttrName == WIDTH )
&&(((CSvgSvgElementImpl *)iCurrentElement)->iWidthInPercentage)
)
{
if(convertedValue > 100)
convertedValue = 100;
}
if(
(aAttrName == HEIGHT)
&&(((CSvgSvgElementImpl *)iCurrentElement)->iHeightInPercentage)
)
{
if(convertedValue > 100)
convertedValue = 100;
}
}
if((tmpAttrID < KSvgDesAttrsIndex) || (tmpAttrID == KAtrFy || tmpAttrID == KAtrFx))
{
iCurrentElement->SetAttributeFloatL( tmpAttrID, ((TFloatFixPt) convertedValue));
}
else
{
iCurrentElement->SetAttributeIntL( tmpAttrID, (TInt) convertedValue );
}
}
else
{
//if invalid width height specified then
//set width/height values as zero
if(
( iCurrentElement->ElemID() == KSvgSvgElement )
&&(aAttrName == WIDTH || aAttrName == HEIGHT)
)
{
convertedValue = 0;
iCurrentElement->SetAttributeFloatL( tmpAttrID, (TFloatFixPt) convertedValue );
}
_LIT(STRING1, "Invalid \"");
_LIT(STRING2, "\" value for <");
_LIT(STRING3, "> : \"");
_LIT(STRING4, "\"" );
iSvgError->SetErrorCode( ESvgInvalidAttributeValue );
iSvgError->SetIsWarning( ETrue );
iSvgError->SetDescription( STRING1 );
iSvgError->AppendDescription( aAttrName);
iSvgError->AppendDescription( STRING2 );
iSvgError->AppendDescription( aName );
iSvgError->AppendDescription( STRING3 );
iSvgError->AppendDescription( aAttrValue );
iSvgError->AppendDescription( STRING4 );
}
return ETrue;
}
return ETrue;
}
// --------------------------------------------------------------------------
// TBool CSvgContentHandler::ExtractStyleValuePair( const TDesC& aString, TPtrC& aName, TPtrC& aValue )
// ---------------------------------------------------------------------------
TBool CSvgContentHandler::ExtractStyleValuePair( const TDesC& aString, TPtrC& aName, TPtrC& aValue )
{
// find pair divide char index ":"
TInt colonIndex = aString.Find( _L( ":" ) );
// ':' not found
if ( colonIndex == KErrNotFound )
return EFalse;
// Skip front white spaces
TInt end = aString.Length();
TInt frontIndex = 0;
while ( frontIndex < end && TChar( aString[frontIndex] ).IsSpace() )
frontIndex++;
// skip back white spaces
TInt backIndex = colonIndex - 1;
while ( backIndex > frontIndex && TChar( aString[backIndex] ).IsSpace() )
backIndex--;
aName.Set( (TUint16*)&aString.Ptr()[frontIndex], backIndex - frontIndex + 1 );
// parse for value
// skip front spaces
frontIndex = colonIndex + 1;
while ( frontIndex < end && TChar( aString[frontIndex] ).IsSpace() )
frontIndex++;
// assuming ';' is not passed in at the end
// start from end and skip spaces
backIndex = end - 1;
while ( backIndex > frontIndex && TChar( aString[backIndex] ).IsSpace() )
backIndex--;
aValue.Set( (TUint16*)&aString.Ptr()[frontIndex], backIndex - frontIndex + 1 );
return ETrue;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::SetForwardReferences(CSvgErrorImpl& aError)
// ---------------------------------------------------------------------------
void CSvgContentHandler::SetForwardReferences(CSvgErrorImpl& aError)
{
/*Once the whole DOM is constructed, Forward references need to be set*/
/*For USE elements*/
TInt lCount = iUseElementArray->Count();
TInt lIndex = 0;
TInt error = KErrNone;
while(lIndex < lCount)
{
TPtrC tPtr2 = ((CSvgElementImpl*)iUseElementArray->operator[](lIndex ))->Href();
if(((CSvgUseElementImpl *)iUseElementArray->operator[](lIndex ))->SetRefElemById(tPtr2) != KErrNotFound)
{
TRAP(error ,((CSvgUseElementImpl *)iUseElementArray->operator[](lIndex ))->SetReferenceElementL());
}
else
{
aError.SetErrorCode( ESvgInvalidAttributeValue );
_LIT(STRING1, "Invalid attribute \n");
_LIT(STRING2, "USE element has invalid xlink:href attribute");
aError.SetDescription( STRING1 );
aError.AppendDescription( STRING2 );
aError.SetIsWarning( EFalse );
break;
}
lIndex ++;
}
/*For Animation Elements*/
lCount = iAnimRefElementArray->Count();
lIndex = 0;
while(lIndex < lCount)
{
TPtrC tPtr2 = ((CSvgElementImpl*)iAnimRefElementArray->operator[](lIndex ))->Href();
((CSvgAnimationBase *)iAnimRefElementArray->operator[](lIndex ))->SetRefElemById(tPtr2);
lIndex ++;
}
/*For Animation elements */
lCount = iAnimationElementArray->Count();
lIndex = 0;
while(lIndex < lCount)
{
// ((CSvgAnimationElementImpl *)iAnimationElementArray->operator[](lIndex))->ResetEventListener();
((CSvgAnimationBase *)iAnimationElementArray->operator[](lIndex))->CheckBeginTime();
lIndex ++;
}
}
//---------------------------------------------------
//Removal of elements that dont pass
//required extensions, required features, and system language
//requirements
//will flag as invisible if remove flag not turned on
//switch statement is special case were only the first one
//that passes these requirements will be used so toss the rest
//---------------------------------------------------
void CSvgContentHandler::RemoveFalseElementsOrMakeInvisible()
{
if ( iReqFetAttSysArray == NULL )
{
// Error Case
return;
}
//loop through the list of elements with required features, attributes, or sys language
TInt reqFetAttSysArrayCnt = iReqFetAttSysArray->Count();
// Start processing from the end of the list so to follow the LIFO principle (process
// from leaf node to root of DOM tree).
while ( reqFetAttSysArrayCnt > 0 )
{
// Access the last element in the array
CSvgElementImpl* lCurElement = ( CSvgElementImpl* )
iReqFetAttSysArray->operator[]( reqFetAttSysArrayCnt - 1 );
if ( lCurElement != NULL )
{
// Save the parent node as this would be required for removing
// this element from the DOM tree
CSvgElementImpl* lParent = ( CSvgElementImpl* )
lCurElement->ParentNode();
if ( lParent == NULL )
{
iReqFetAttSysArray->Reset();
return;
}
//just a normal element check it and remove it if it doesnt pass
TBool lResult = EFalse;
TRAPD(error, lResult = VerifyReqExReqFtrSysL( lCurElement ));
if ( error == KErrNone && !lResult )
{
if ( iRemoveFalseSwitchElements )
{
// Remove references of this element in Content Handler
// This function removes the element from the iReqFetAttSysArray as well
RemoveInternalReferences( lCurElement );
lParent->RemoveChild( lCurElement);
delete lCurElement;
lCurElement = NULL;
}
else
{
//if not removing elements then at least set to false
TRAP_IGNORE(
lCurElement->SetAttributeIntL(
KCSS_ATTR_VISIBILITY, 1 ) );
// Remove the element from the iReqFetAttSysArray
iReqFetAttSysArray->Remove( reqFetAttSysArrayCnt - 1 );
} // if ( iRemoveFalseSwitchElements )
}
else
{
// Remove the element from the iReqFetAttSysArray
iReqFetAttSysArray->Remove( reqFetAttSysArrayCnt - 1 );
} // if ( error == KErrNone && !lResult )
}
else
{
// Remove the element from the iReqFetAttSysArray
iReqFetAttSysArray->Remove( reqFetAttSysArrayCnt - 1 );
} // if ( lCurElement != NULL )
// Update the array count
reqFetAttSysArrayCnt = iReqFetAttSysArray->Count();
} // while ( reqFetAttSysArrayCnt > 0 )
// Reset the array as it is no longer required.
iReqFetAttSysArray->Reset();
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::RemoveStyleProperties()
// ---------------------------------------------------------------------------
/*
//MEMORY MANAGER now in charge of style deletion
void CSvgContentHandler::RemoveStyleProperties(CSvgElementImpl* aElement)
{
CSvgElementImpl* child = (CSvgElementImpl*)aElement->FirstChild();
while ( child != NULL )
{
child->DeleteStyleProperties(child);
RemoveStyleProperties( child );
child = (CSvgElementImpl*)child->NextSibling();
}
}
*/
// --------------------------------------------------------------------------
// void CSvgContentHandler::RemoveFalseSwitchCases()
// ---------------------------------------------------------------------------
void CSvgContentHandler::RemoveFalseSwitchCasesOrMakeInvisible()
{
if ( iSwitchElementArray == NULL )
{
// Error Case
return;
}
TInt switchEleArrayCnt = iSwitchElementArray->Count();
while ( switchEleArrayCnt > 0 )
{
TBool foundTrue = EFalse;
CSvgElementImpl* curSwitchElem =
(CSvgElementImpl*)iSwitchElementArray->operator[]( switchEleArrayCnt - 1 );
// Remove the switch element from the array. This is done here as
// below statements could result in iSwitchElementArray getting modified
// in RemoveInternalReferences.
iSwitchElementArray->Remove( switchEleArrayCnt - 1 );
if ( curSwitchElem != NULL )
{
//get the first child...which is where the first
CSvgElementImpl* curCaseElem = (CSvgElementImpl*)curSwitchElem->FirstChild();
while ( curCaseElem != NULL )
{
CSvgElementImpl* nextCaseElem = (CSvgElementImpl*)curCaseElem->NextSibling();
// foundTrue is set to TRUE when an element whose test passes is found. The
// subsequent elements are to be removed.
if ( foundTrue )
{
if ( iRemoveFalseSwitchElements )
{
//already found the true case in the switch delete the rest
// Remove references of this element in Content Handler
// This function removes the element from the
// iSwitchElementArray as well
RemoveInternalReferences( curCaseElem );
curSwitchElem->RemoveChild( curCaseElem );
delete ( CXmlElementImpl* )curCaseElem;
curCaseElem = NULL;
}
else
{
//not removing elements from tree just make invisible
TRAP_IGNORE( curCaseElem->SetAttributeIntL( KCSS_ATTR_VISIBILITY, 1 ) );
}
}
else
{
// Not yet found an element whose test passes,
// perform the test on the current element to check
// whether it does.
TBool result= EFalse;
TRAPD( error, result= VerifyReqExReqFtrSysL( curCaseElem ) );
if ( error == KErrNone )
{
if ( !result )
{
if ( iRemoveFalseSwitchElements )
{
// this element doesnt meet the switch requirements
// delete it and its children
// Remove references of this element in Content Handler
// This function removes the element from the
// iSwitchElementArray as well
RemoveInternalReferences( curCaseElem );
curSwitchElem->RemoveChild( curCaseElem );
delete ( CXmlElementImpl* )curCaseElem;
curCaseElem = NULL;
}
else
{
//not removing elements from tree just make invisible
TRAP_IGNORE( curCaseElem->SetAttributeIntL(
KCSS_ATTR_VISIBILITY, 1 ) );
}
}
else
{
//one evaluated to true so keep it but go ahead and delete the rest in the switch
//should only be one child for switch in end
foundTrue = ETrue;
}
}
} // if ( foundTrue )
// Check the next case element
curCaseElem = nextCaseElem;
} // while ( curCaseElem != NULL )
} // if ( curSwitchElem != NULL )
// Update the count of elements
switchEleArrayCnt = iSwitchElementArray->Count();
} // while ( switchEleArrayCnt > 0 )
// Reset the array as it is no longer required.
iSwitchElementArray->Reset();
}
//---------------------------------------------------
//Check to see
//required extensions, required features, and system language
//requirements
//---------------------------------------------------
TBool CSvgContentHandler::VerifyReqExReqFtrSysL( CSvgElementImpl* aElement )
{
const CDesCArrayFlat* tempTestArray = NULL; // 'const' keyword added due to S60 (CW) build team recommendation
TBool doDraw = ETrue;
// First check for requiredExtensions
aElement->GetRequiredExtensions( tempTestArray );
if ( tempTestArray && tempTestArray->MdcaCount() )
{
// Check for all entries in requiredExtensions
TInt lCount = tempTestArray->MdcaCount();
for ( TInt i = 0; i < lCount; i++ )
{
TPtrC tmpPtr = tempTestArray->MdcaPoint( i );
if ( tmpPtr.Length() )
{
doDraw = EFalse;
break;
}
else if ( aElement->HasExtension( tmpPtr ) == EFalse )
{
doDraw = EFalse;
break;
}
}
}
// Second, check for requiredFeatures
aElement->GetRequiredFeatures( tempTestArray );
if ( tempTestArray && tempTestArray->MdcaCount() && doDraw)
{
// Check for all entries in requiredFeatures
TInt lCount = tempTestArray->MdcaCount();
for ( TInt i = 0; i < lCount; i++ )
{
TPtrC tmpPtr = tempTestArray->MdcaPoint( i );
if ( aElement->HasFeature( tmpPtr ) == EFalse )
{
doDraw = EFalse;
break;
}
}
}
//set up so it only gets it once...
//just fetch it one time...
if (iSystemLanguage->Length() == 0)
{
SystemLanguage( iSystemLanguage->Des() );
}
// Third, check for systemLanguage
// SYSTEM LANGUAGE DOESNT NEED TO BE STORED IN SEPERATE ARRAY INDEXES
// COULD HAVE JUST STORED IT AS ONE BIG STRING AND USE FINDF without the loop
TBool lIsNotEmptyString = aElement->GetSystemLanguage( tempTestArray );
if (!lIsNotEmptyString)
{
//system language was empty string so dont draw
return EFalse;
}
TBool doDrawSystem = EFalse;
if ( tempTestArray && tempTestArray->MdcaCount() && doDraw)
{
TInt lCount = tempTestArray->MdcaCount();
for ( TInt i = 0; i < lCount; i++ )
{
TPtrC tmpPtr = tempTestArray->MdcaPoint( i );
//tmpPtr is the language that was on the element
//match entire content specified string to system systemlanguage
if ( tmpPtr.FindF( iSystemLanguage->Des() ) == 0 )
{
doDrawSystem = ETrue;
break;
}
//match just the prefix of the system systemlanugage to the content specified syslang
if ( iSystemLanguage->Des().Left(2).FindF(tmpPtr) == 0 )
{
doDrawSystem = ETrue;
break;
}
}
if (doDrawSystem == EFalse)
{
doDraw = EFalse;
}
}
return doDraw;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::SystemLanguage( TPtr aValue )
// ---------------------------------------------------------------------------
void CSvgContentHandler::SystemLanguage( TPtr aValue )
{
_LIT( KEn, "en" );
_LIT( KFr, "fr" );
_LIT( KDe, "de" );
_LIT( KEs, "es" );
_LIT( KAf, "af" );
_LIT( KAm, "am" );
_LIT( KAr, "ar" );
_LIT( KBg, "bg" );
_LIT( KBn, "bn" );
_LIT( KBo, "bo" );
_LIT( KCa, "ca" );
_LIT( KCs, "cs" );
_LIT( KCy, "cy" );
_LIT( KDa, "da" );
_LIT( KEl, "el" );
_LIT( KEt, "et" );
_LIT( KFa, "fa" );
_LIT( KFi, "fi" );
_LIT( KGa, "ga" );
_LIT( KGd, "gd" );
_LIT( KGu, "gu" );
_LIT( KHe, "he" );
_LIT( KHi, "hi" );
_LIT( KHu, "hu" );
_LIT( KHr, "hr" );
_LIT( KHy, "hy" );
_LIT( KId, "id" );
_LIT( KIs, "is" );
_LIT( KIt, "it" );
_LIT( KJa, "ja" );
_LIT( KKa, "ka" );
_LIT( KKk, "kk" );
_LIT( KKm, "km" );
_LIT( KKn, "kn" );
_LIT( KKo, "ko" );
_LIT( KLo, "lo" );
_LIT( KLt, "lt" );
_LIT( KLv, "lv" );
_LIT( KMk, "mk" );
_LIT( KMl, "ml" );
_LIT( KMn, "mn" );
_LIT( KMo, "mo" );
_LIT( KMr, "mr" );
_LIT( KMs, "ms" );
_LIT( KMy, "my" );
_LIT( KNo, "no" );
_LIT( KNl, "nl" );
_LIT( KPa, "pa" );
_LIT( KPl, "pl" );
_LIT( KPt, "pt" );
_LIT( KRo, "ro" );
_LIT( KRu, "ru" );
_LIT( KSi, "si" );
_LIT( KSk, "sk" );
_LIT( KSl, "sl" );
_LIT( KSo, "so" );
_LIT( KSr, "sr" );
_LIT( KSq, "sq" );
_LIT( KSv, "sv" );
_LIT( KSw, "sw" );
_LIT( KTa, "ta" );
_LIT( KTe, "te" );
_LIT( KTh, "th" );
_LIT( KTi, "ti" );
_LIT( KTk, "tk" );
_LIT( KTl, "tl" );
_LIT( KTr, "tr" );
_LIT( KUk, "uk" );
_LIT( KUr, "ur" );
_LIT( KVi, "vi" );
//_LIT( KZh, "zh" );
_LIT( KZu, "zu" );
_LIT( KEnB, "en-UK");
_LIT( KEnUS, "en-US");
_LIT( KZhTW, "zh-TW");
_LIT( KZhHK, "zh-HK");
_LIT( KZhCN, "zh-CN");
_LIT( KFrCA, "fr-CA");
_LIT( KPtBR, "pt-BR");
_LIT( KEnTW, "en-TW");
_LIT( KEnHK, "en-HK");
_LIT( KEnCN, "en-CN");
_LIT( KEnJP, "en-JP");
_LIT( KEnTH, "en-TH");
_LIT( KEsAR, "es-AR");
_LIT( KMsAP, "ms-AP");
_LIT( KEnAP, "en-AP" ); // KLangApacEnglish
_LIT( KIdAP, "id-AP" ); // KLangApacIndonesian
_LIT( KEu, "eu" ); // KLangBasque
_LIT( KGl, "gl" ); // KLangGalician
_LIT(KDefault, "qqqqq");
switch ( User::Language() )
{
case ELangTest:
aValue = KEn;
break;
case ELangEnglish:
aValue = KEnB;
break;
case ELangAmerican:
aValue = KEnUS;
break;
case ELangAustralian:
case ELangNewZealand:
case ELangCanadianEnglish:
case ELangSouthAfricanEnglish:
case ELangInternationalEnglish:
aValue = KEn;
break;
case ELangFrench:
case ELangSwissFrench:
case ELangBelgianFrench:
aValue = KFr;
break;
case ELangGerman:
case ELangAustrian:
case ELangSwissGerman:
aValue = KDe;
break;
case ELangSpanish:
case ELangInternationalSpanish:
aValue = KEs;
break;
case ELangLatinAmericanSpanish:
aValue = KEsAR;
break;
case ELangItalian:
case ELangSwissItalian:
aValue = KIt;
break;
case ELangSwedish:
case ELangFinlandSwedish:
aValue = KSv;
break;
case ELangDanish:
aValue = KDa;
break;
case ELangNorwegian:
case ELangNorwegianNynorsk:
aValue = KNo;
break;
case ELangFinnish:
aValue = KFi;
break;
case ELangBrazilianPortuguese:
aValue = KPtBR;
break;
case ELangPortuguese:
aValue = KPt;
break;
case ELangTurkish:
case ELangCyprusTurkish:
aValue = KTr;
break;
case ELangIcelandic:
aValue = KIs;
break;
case ELangRussian:
case ELangBelarussian:
aValue = KRu;
break;
case ELangHungarian:
aValue = KHu;
break;
case ELangDutch:
case ELangBelgianFlemish:
aValue = KNl;
break;
case ELangCzech:
aValue = KCs;
break;
case ELangSlovak:
aValue = KSk;
break;
case ELangPolish:
aValue = KPl;
break;
case ELangSlovenian:
aValue = KSl;
break;
case ELangPrcChinese:
aValue = KZhCN;
break;
case ELangTaiwanChinese:
aValue = KZhTW;
break;
case ELangHongKongChinese:
aValue = KZhHK;
break;
case ELangJapanese:
aValue = KJa;
break;
case ELangThai:
aValue = KTh;
break;
case ELangAfrikaans:
aValue = KAf;
break;
case ELangAlbanian:
aValue = KSq;
break;
case ELangAmharic:
aValue = KAm;
break;
case ELangArabic:
aValue = KAr;
break;
case ELangArmenian:
aValue = KHy;
break;
case ELangTagalog:
aValue = KTl;
break;
case ELangBengali:
aValue = KBn;
break;
case ELangBulgarian:
aValue = KBg;
break;
case ELangBurmese:
aValue = KMy;
break;
case ELangCatalan:
aValue = KCa;
break;
case ELangCroatian:
aValue = KHr;
break;
case ELangEstonian:
aValue = KEt;
break;
case ELangFarsi:
aValue = KFa;
break;
case ELangCanadianFrench:
aValue = KFrCA;
break;
case ELangScotsGaelic:
aValue = KGd;
break;
case ELangGeorgian:
aValue = KKa;
break;
case ELangGreek:
case ELangCyprusGreek:
aValue = KEl;
break;
case ELangGujarati:
aValue = KGu;
break;
case ELangHebrew:
aValue = KHe;
break;
case ELangHindi:
aValue = KHi;
break;
case ELangIndonesian:
aValue = KId;
break;
case ELangIrish:
aValue = KGa;
break;
case ELangKannada :
aValue = KKn;
break;
case ELangKazakh:
aValue = KKk;
break;
case ELangKhmer:
aValue = KKm;
break;
case ELangKorean:
aValue = KKo;
break;
case ELangLao:
aValue = KLo;
break;
case ELangLatvian:
aValue = KLv;
break;
case ELangLithuanian:
aValue = KLt;
break;
case ELangMacedonian:
aValue = KMk;
break;
case ELangMalay:
aValue = KMs;
break;
case ELangMalayalam:
aValue = KMl;
break;
case ELangMarathi:
aValue = KMr;
break;
case ELangMoldavian:
aValue = KMo;
break;
case ELangMongolian:
aValue = KMn;
break;
case ELangPunjabi:
aValue = KPa;
break;
case ELangRomanian:
aValue = KRo;
break;
case ELangSerbian:
aValue = KSr;
break;
case ELangSinhalese:
aValue = KSi;
break;
case ELangSomali:
aValue = KSo;
break;
case ELangSwahili:
aValue = KSw;
break;
case ELangTamil:
aValue = KTa;
break;
case ELangTelugu:
aValue = KTe;
break;
case ELangTibetan:
aValue = KBo;
break;
case ELangTigrinya:
aValue = KTi;
break;
case ELangTurkmen:
aValue = KTk;
break;
case ELangUkrainian:
aValue = KUk;
break;
case ELangUrdu:
aValue = KUr;
break;
case ELangVietnamese:
aValue = KVi;
break;
case ELangWelsh:
aValue = KCy;
break;
case ELangZulu:
aValue = KZu;
break;
// from \\epoc32\\include\\oem\\languages.hrh
case KLangTaiwanEnglish:
aValue = KEnTW;
break;
case KLangHongKongEnglish:
aValue = KEnHK;
break;
case KLangPrcEnglish:
aValue = KEnCN;
break;
case KLangJapaneseEnglish:
aValue = KEnJP;
break;
case KLangThaiEnglish:
aValue = KEnTH;
break;
case KLangApacMalay:
aValue = KMsAP;
break;
case KLangApacEnglish:
{
aValue = KEnAP;
break;
}
case KLangApacIndonesian:
{
aValue = KIdAP;
break;
}
case KLangBasque:
{
aValue = KEu;
break;
}
case KLangGalician:
{
aValue = KGl;
break;
}
// Cingular English
case 6154:
aValue = KEnUS;
break;
default:
{
aValue = KDefault;
}
break;
}
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::CancelParsing()
// ---------------------------------------------------------------------------
void CSvgContentHandler::CancelParsing()
{
iCancelRequested = ETrue;
}
// --------------------------------------------------------------------------
// void CSvgContentHandler::LoadImages()
// ---------------------------------------------------------------------------
void CSvgContentHandler::LoadImages()
{
TInt imageEleCnt = iImageElements.Count();
for ( TInt i = 0; i < imageEleCnt; i++ )
{
TRAPD( error, iImageElements[i]->LoadUriL() );
if ( error != KErrNone )
{
#ifdef _DEBUG
RDebug::Printf("LoadUriL failed: %d\n", error );
#endif
}
}
}