--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/smilengine/engine/parser/smilparser.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1561 @@
+/*
+* 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: smilparser implementation
+*
+*/
+
+
+
+#include "smilparser.h"
+
+#include "smilsequence.h"
+#include "smilparallel.h"
+#include "smilexclusive.h"
+#include "smilmedia.h"
+#include "smilregion.h"
+#include "smilrootregion.h"
+#include "smilpresentation.h"
+#include "smilanchor.h"
+#include "smilarea.h"
+#include "smila.h"
+#include "smiltransition.h"
+#include "smilprefetch.h"
+
+#include "smilmediafactoryinterface.h"
+
+#include "smilliterals.h"
+#include "smillinkedlist.h"
+
+// maximum number of elements allowed in the timegraph
+#define MAX_TIMEGRAPH_SIZE 80
+
+// what it says. only used for resolving the content control attribute
+#define SYSTEM_SCREEN_DEPTH 16
+
+//#define PARSER_DEBUG
+
+// defined elsewhere
+void ParseXmlL( CSmilParser* parser, const TDesC& aSource );
+void ParseDomL( CSmilParser* parser, CMDXMLDocument* aSource );
+
+
+// ----------------------------------------------------------------------------
+// CSmilParser::CSmilParser
+// ----------------------------------------------------------------------------
+//
+CSmilParser::CSmilParser()
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::~CSmilParser
+// ----------------------------------------------------------------------------
+//
+CSmilParser::~CSmilParser()
+ {
+ delete iSwitchStack;
+ delete iCurrent; // not yet part of a presentation!
+ delete iCurrentRegion;
+
+ if ( iNamespaces )
+ {
+ CLinkedList<Namespace>::Iter nsi( *iNamespaces );
+ while( nsi.HasMore() )
+ {
+ Namespace& ns = nsi.Next();
+ delete ns.name;
+ delete ns.uri;
+ }
+ }
+
+ delete iNamespaces;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::NewL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CSmilParser* CSmilParser::NewL( MSmilPlayer* aPlayer )
+ {
+ CSmilParser* self = new( ELeave ) CSmilParser();
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aPlayer );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::ConstructL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::ConstructL( MSmilPlayer* aPlayer )
+ {
+ iPlayer = aPlayer;
+
+ iCurrent = 0;
+ iCurrentRegion = 0;
+ iSwitchStack = new( ELeave ) CLinkedList<Switch>();
+ iNamespaces = new( ELeave ) CLinkedList<Namespace>();
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::Init
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::Init()
+ {
+ iState = EInitial;
+
+ delete iCurrent; //might be some leftovers from a failed parsi
+ iCurrent = 0;
+
+ iTimeContainer = 0;
+
+ delete iCurrentRegion;
+ iCurrentRegion = 0;
+
+ iCurrentTransition = 0;
+
+ if ( iAnchor )
+ {
+ iAnchor->Close();
+ iAnchor = 0;
+ }
+
+ CLinkedList<Namespace>::Iter nsi( *iNamespaces );
+ while ( nsi.HasMore() )
+ {
+ Namespace& ns = nsi.Next();
+ delete ns.name;
+ delete ns.uri;
+ }
+ iNamespaces->Empty();
+
+ iArea = 0;
+
+ iIgnoreDepth = 0;
+ iDepth = 0;
+ iSwitchStack->Empty();
+ iSkipContent = ETrue;
+ iUnknownElement = EFalse;
+ iTag.Set( TPtrC() );
+ iParamName.Set( TPtrC() );
+ iParamValue.Set( TPtrC() );
+ iTimegraphSize = 0;
+ }
+
+
+// ---------------------------------------------------------
+// CSmilParser::ParseL
+//
+// ---------------------------------------------------------
+//
+EXPORT_C CSmilPresentation* CSmilParser::ParseL( const TDesC& /*aSmil*/,
+ const TDesC& /*aBaseUrl*/ )
+ {
+#if 0
+ // can't parse descriptor with current Symbian DOM parser!!!
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("ParseL(): %S"), &aSmil);
+#endif
+
+ Init();
+
+ CSmilPresentation* tempPresentationPointer = CSmilPresentation::NewL( iPlayer );
+
+ // Everything constructed during parsing is owned by the presentation
+ // (directly or indirectly) and added there immediatly after construction.
+ // Thus it is enough to take care that the presentation gets deleted if
+ // a leave occurs.
+
+ CleanupStack::PushL( tempPresentationPointer );
+
+ tempPresentationPointer->SetBaseUrlL( aBaseUrl );
+ tempPresentationPointer->SetMaxDownUpScaling( iDown, iUp );
+ iPlayer->GetMediaFactory(tempPresentationPointer)->SetBaseUrlL( aBaseUrl );
+
+ iPresentation = tempPresentationPointer;
+ TBool ok = ParseXml( this, aSmil ); //parse! (see smilparser_cxml.cpp etc.)
+
+ if ( ok && iState == ESmilFinished )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("Parsed succesfully"));
+#endif
+ tempPresentationPointer->Ready();
+
+#ifdef PARSER_DEBUG
+ tempPresentationPointer->PrintDebug();
+
+#endif
+ CleanupStack::Pop(); // tempPresentationPointer
+ }
+ else
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("Parsing failed, leaving"));
+#endif
+ User::Leave( KErrUnknown );
+ }
+ return tempPresentationPointer;
+
+#endif
+ return 0;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::ParseL
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CSmilPresentation* CSmilParser::ParseL( const CMDXMLDocument* aSmilDoc,
+ const TDesC& aBaseUrl )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("ParseL(): parsing DOM"));
+#endif
+
+ Init();
+
+ CSmilPresentation* tempPresentationPointer = CSmilPresentation::NewL( iPlayer );
+
+ // Everything constructed during parsing is owned by the presentation
+ // (directly or indirectly) and added there immediatly after construction.
+ // Thus it is enough to take care that the presentation gets deleted if
+ // a leave occurs.
+
+ CleanupStack::PushL( tempPresentationPointer );
+
+ tempPresentationPointer->SetBaseUrlL( aBaseUrl );
+ tempPresentationPointer->SetMaxDownUpScaling( iDown, iUp );
+ iPlayer->GetMediaFactory(tempPresentationPointer)->SetBaseUrlL( aBaseUrl );
+
+ iPresentation = tempPresentationPointer;
+
+ ParseDomL( this, const_cast<CMDXMLDocument*>( aSmilDoc ) ); //parse! (see smilparser_dom.cpp)
+
+ if ( iState == ESmilFinished )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("Parsed succesfully"));
+#endif
+ tempPresentationPointer->ReadyL();
+
+#ifdef PARSER_DEBUG
+ tempPresentationPointer->PrintDebug();
+#endif
+ CleanupStack::Pop(); // tempPresentationPointer
+ }
+ else
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("Parsing failed, leaving"));
+#endif
+ User::Leave( KErrUnknown );
+ }
+
+ return tempPresentationPointer;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::BeginElementL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::BeginElementL( const TDesC& aName )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("BeginElement: %S"), &aName);
+#endif
+
+ iDepth++;
+
+ if ( iIgnoreDepth > 0 )
+ {
+ iIgnoreDepth++;
+ return;
+ }
+
+ if ( !iSwitchStack->IsEmpty() &&
+ iSwitchStack->Peek().depth == iDepth - 1 &&
+ iSwitchStack->Peek().done )
+ {
+ iIgnoreDepth = 1;
+ return;
+ }
+
+ if ( aName.CompareF( KSmilTag ) == 0 )
+ {
+ if ( iState != EInitial )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iState = ESmil;
+ iTag.Set( KSmilTag );
+
+ // we need root layout even if there is no <layout> element
+ CSmilRootRegion* root = CSmilRootRegion::NewL( iPresentation );
+ iPresentation->SetLayout( root );
+ }
+ else if ( aName.CompareF( KRegionTag ) == 0 )
+ {
+ if ( iState != ELayout )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iTag.Set( KRegionTag );
+ CSmilRegion* r = CSmilRegion::NewL( iPresentation );
+ iCurrentRegion = r;
+ }
+ else if ( aName.CompareF( KHeadTag ) == 0 )
+ {
+ if (iState != ESmil)
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iState = EHead;
+ iTag.Set( KHeadTag );
+ }
+ else if ( aName.CompareF( KLayoutTag ) == 0 )
+ {
+ if ( iState != EHead )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iState = ELayout;
+ iTag.Set( KLayoutTag );
+ iPresentation->GetLayout()->SetDefaultLayout( EFalse );
+ }
+ else if ( aName.CompareF( KRootLayoutTag ) == 0 &&
+ iState == ELayout )
+ {
+ if ( iState != ELayout )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iTag.Set( KRootLayoutTag );
+ iCurrentRegion = iPresentation->GetLayout();
+ }
+ else if ( aName.CompareF( KBodyTag ) == 0 )
+ {
+ if ( iState != ESmil &&
+ iState != EHeadFinished )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iTag.Set( KBodyTag );
+ CSmilSequence* body = CSmilSequence::NewL( iPresentation );
+ iPresentation->SetTimegraph( body );
+ iCurrent = body;
+
+ iState = EBody;
+ }
+ else if ( aName.CompareF( KSeqTag ) == 0 )
+ {
+ if ( iState != EBody )
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ iTag.Set( KSeqTag );
+ iCurrent = CSmilSequence::NewL( iPresentation );
+ }
+ else if ( aName.CompareF( KParTag ) == 0 )
+ {
+ if ( iState != EBody )
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ iTag.Set( KParTag );
+ iCurrent = CSmilParallel::NewL( iPresentation );
+ }
+ else if ( aName.CompareF( KExclTag ) == 0 )
+ {
+ if ( iState != EBody )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iTag.Set( KExclTag );
+ iCurrent = CSmilExclusive::NewL( iPresentation );
+ }
+ else if ( aName.CompareF( KTransitionTag ) == 0 )
+ {
+ if ( iState != EHead &&
+ iState != ELayoutFinished )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ iTag.Set( KTransitionTag );
+
+ iCurrentTransition = new (ELeave) CSmilTransition();
+ iPresentation->AddTransitionL( iCurrentTransition );
+ }
+ else if ( aName.CompareF( KImageTag ) == 0 ||
+ aName.CompareF( KTextTag ) == 0 ||
+ aName.CompareF( KAudioTag ) == 0 ||
+ aName.CompareF( KRefTag ) == 0 ||
+ aName.CompareF( KTextStreamTag ) == 0 ||
+ aName.CompareF( KAnimationTag ) == 0 ||
+ aName.CompareF( KVideoTag ) == 0 )
+ {
+ if ( iState != EBody )
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ iTag.Set( KRefTag );
+ iCurrent = CSmilMedia::NewL( iPresentation );
+
+ if ( iAnchor )
+ {
+ iCurrent->SetAnchor( iAnchor );
+ }
+ }
+ else if ( aName.CompareF( KParamTag ) == 0 )
+ {
+ iTag.Set( KParamTag );
+ }
+ else if ( aName.CompareF( KSwitchTag ) == 0 )
+ {
+ iTag.Set( KSwitchTag );
+
+ Switch sw;
+ sw.depth = iDepth;
+ sw.done = EFalse;
+ iSwitchStack->PushL( sw );
+ }
+ else if ( aName.CompareF( KATag ) == 0 )
+ {
+ iTag.Set( KATag );
+
+ if ( iAnchor )
+ {
+ iAnchor->Close();
+ iAnchor = 0;
+ }
+
+ iAnchor = new( ELeave ) CSmilAnchor();
+ }
+ else if ( aName.CompareF( KAreaTag ) == 0 ||
+ aName.CompareF( KAnchorTag ) == 0)
+ {
+ iTag.Set( KAreaTag );
+
+ iArea = CSmilArea::NewL( iPresentation );
+ iArea->SetTimeContainer( iTimeContainer );
+ iCurrent = iArea;
+ }
+ else if ( aName.CompareF( KPrefetchTag ) == 0 )
+ {
+ if ( iState != EBody )
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ iTag.Set( KPrefetchTag );
+ iCurrent = CSmilPrefetch::NewL( iPresentation );
+ }
+ else
+ {
+ if ( iState != EInitial )
+ {
+ iUnknownElement = ETrue;
+ }
+ }
+
+ return;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::EndElementL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::EndElementL( const TDesC& aName )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print( _L( "EndElement: %S" ), &aName );
+#endif
+
+ iDepth--;
+
+ if ( iIgnoreDepth > 0 )
+ {
+ iIgnoreDepth--;
+ return;
+ }
+
+ if ( aName.CompareF( KSmilTag ) == 0 )
+ {
+ if ( iPresentation &&
+ iPresentation->GetTimegraph() &&
+ iPresentation->GetLayout() )
+ {
+ iState = ESmilFinished;
+ }
+ }
+ else if ( aName.CompareF( KHeadTag ) == 0 )
+ {
+ iState = EHeadFinished;
+ }
+ else if ( aName.CompareF( KTransitionTag ) == 0 )
+ {
+ iCurrentTransition = 0;
+ }
+ else if ( aName.CompareF( KLayoutTag ) == 0 )
+ {
+ iState = ELayoutFinished;
+ iCurrentRegion = 0;
+ }
+ else if ( aName.CompareF( KSwitchTag ) == 0 )
+ {
+ if ( !iSwitchStack->IsEmpty() )
+ {
+ iSwitchStack->Pop();
+ }
+ }
+ else if ( aName.CompareF( KBodyTag ) == 0 )
+ {
+ iState = EBodyFinished;
+
+ iCurrent = 0;
+ iTimeContainer = 0;
+ }
+
+ else if ( aName.CompareF( KATag ) == 0 )
+ {
+ if ( iAnchor )
+ {
+ if (iAnchor->AccessCount()==1 && iTimeContainer)
+ {
+ // empty <a> element, we'll create a place holder SmilObject
+ CSmilA* a = CSmilA::NewL( iPresentation );
+ a->SetAnchor( iAnchor );
+ iTimeContainer->AddChild( a );
+ a->AttachedL();
+ }
+ iAnchor->Close();
+ iAnchor = 0;
+ }
+ }
+
+ else if ( aName.CompareF( KParamTag ) == 0 )
+ {
+ iParamName.Set( TPtrC() );
+ iParamValue.Set( TPtrC() );
+ }
+
+ else if ( ( aName.CompareF( KParTag ) == 0 ||
+ aName.CompareF( KSeqTag ) == 0 ||
+ aName.CompareF( KExclTag ) == 0 ) &&
+ iTimeContainer )
+ {
+ iTimeContainer = iTimeContainer->ParentObject();
+ }
+
+ else if ( ( aName.CompareF( KImageTag ) == 0 ||
+ aName.CompareF( KTextTag ) == 0 ||
+ aName.CompareF( KAudioTag ) == 0 ||
+ aName.CompareF( KRefTag ) == 0 ||
+ aName.CompareF( KTextStreamTag ) == 0 ||
+ aName.CompareF( KAnimationTag ) == 0 ||
+ aName.CompareF( KVideoTag ) == 0 ) &&
+ iTimeContainer )
+ {
+ iTimeContainer = iTimeContainer->ParentObject();
+ }
+
+ return;
+ }
+
+// ----------------------------------------------------------------------------
+// StripWhitespace
+// ----------------------------------------------------------------------------
+//
+TPtrC StripWhitespace( const TDesC& aStr )
+ {
+ // strip leading and trailing spaces from a string
+ TInt b = 0;
+ TInt e = aStr.Length() - 1;
+ while ( b < aStr.Length() && aStr[b] == ' ' )
+ {
+ b++;
+ }
+ while ( e >= 0 && aStr[e] == ' ' )
+ {
+ e--;
+ }
+
+ if ( e >= b )
+ {
+ return aStr.Mid( b, e - b + 1 );
+ }
+ else
+ {
+ return TPtrC();
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::AttributeValueL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::AttributeValueL( const TDesC& aName, const TDesC& aAttrValue )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print( _L( "attrib: %S=%S" ), &aName, &aValue );
+#endif
+
+ if ( iIgnoreDepth > 0 )
+ {
+ return;
+ }
+
+ const TPtrC aValue = StripWhitespace( aAttrValue );
+
+ if ( aName.Length() == 0 )
+ {
+ return;
+ }
+
+ if ( CheckSystemAttribute( aName, aValue ) )
+ {
+ return;
+ }
+
+ if ( aName.CompareF( KSkipContentAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KTrueVal ) == 0 )
+ {
+ iSkipContent = ETrue;
+ }
+ else if ( aValue.CompareF( KFalseVal ) == 0 )
+ {
+ iSkipContent = EFalse;
+ }
+ }
+
+ switch ( iState )
+ {
+ case EBody:
+ {
+ if ( ( iAnchor && iTag == KATag ) ||
+ ( iArea && iTag == KAreaTag ) )
+ {
+ CSmilAnchor* a = iArea ? iArea->Anchor() : iAnchor;
+
+ if ( aName.CompareF( KHrefAttr ) == 0 )
+ {
+ a->SetHrefL( aValue );
+ }
+ else if ( aName.CompareF( KAltAttr ) == 0 )
+ {
+ a->SetAltL( aValue );
+ }
+ else if ( aName.CompareF( KTargetAttr ) == 0 )
+ {
+ a->SetTargetL( aValue );
+ }
+ else if ( aName.CompareF( KTabindexAttr ) == 0 )
+ {
+ a->iTabIndex = StringToIntValue( aValue,0 );
+ }
+ else if (aName.CompareF( KActuateAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KOnLoadVal ) == 0 )
+ {
+ a->iActuate = CSmilAnchor::EOnLoad;
+ }
+ }
+ else if ( aName.CompareF( KAccesskeyAttr ) == 0 )
+ {
+ if ( aValue.Length() > 0 )
+ {
+ a->iAccessKey = aValue[0];
+ }
+ }
+ else if ( iArea )
+ {
+ if ( aName.CompareF( KShapeAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KCircleVal ) == 0 )
+ {
+ iArea->iShape = CSmilArea::ECircle;
+ }
+ else if ( aValue.CompareF( KPolyVal ) == 0 )
+ {
+ iArea->iShape = CSmilArea::EPoly;
+ }
+ else if ( aValue.CompareF( KRectVal ) == 0 )
+ {
+ iArea->iShape = CSmilArea::ERect;
+ }
+ }
+ else if ( aName.CompareF( KCoordsAttr ) == 0 )
+ {
+ TInt b = 0;
+ TInt e = 0;
+
+ while ( e < aValue.Length() )
+ {
+ while ( e < aValue.Length() && aValue[e] != ',' )
+ {
+ e++;
+ }
+
+ while ( aValue[b] == ' ' )
+ {
+ b++;
+ }
+
+ TPtrC val = aValue.Mid( b, e - b );
+
+ iArea->iCoords->AddL( TSmilLength( val ) );
+
+ e++;
+ b = e;
+ }
+ }
+ }
+
+ if ( !iArea )
+ {
+ return;
+ }
+ }
+
+ else if (iTag == KParamTag )
+ {
+ if ( aName.CompareF( KNameAttr ) == 0 )
+ {
+ iParamName.Set( aValue );
+ }
+ else if ( aName.CompareF( KValueAttr ) == 0 )
+ {
+ iParamValue.Set( aValue );
+ }
+
+ return;
+ }
+
+ if ( !iCurrent )
+ {
+ return;
+ }
+
+ if ( aName.CompareF( KDurAttr ) == 0 )
+ {
+ iCurrent->SetDuration( TSmilTime( aValue ) );
+ }
+ else if ( aName.CompareF( KBeginAttr ) == 0 )
+ {
+ ParseTimeListL( aValue, ETrue );
+ }
+ else if ( aName.CompareF( KEndAttr ) == 0 )
+ {
+ ParseTimeListL( aValue, EFalse );
+ }
+ else if ( aName.CompareF( KRepeatDurAttr ) == 0 )
+ {
+ iCurrent->SetRepeatDur( TSmilTime( aValue ) );
+ }
+ else if ( aName.CompareF( KMinAttr ) == 0 )
+ {
+ iCurrent->SetMin( TSmilTime( aValue ) );
+ }
+ else if ( aName.CompareF( KMaxAttr ) == 0 )
+ {
+ iCurrent->SetMax( TSmilTime( aValue ) );
+ }
+ else if ( aName.CompareF( KFillAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KRemoveVal ) == 0 )
+ {
+ iCurrent->SetFill( EFillRemove );
+ }
+ else if ( aValue.CompareF( KFreezeVal ) == 0 )
+ {
+ iCurrent->SetFill( EFillFreeze );
+ }
+ else if (aValue.CompareF( KHoldVal ) == 0 )
+ {
+ iCurrent->SetFill( EFillHold );
+ }
+ else if ( aValue.CompareF( KTransitionVal ) == 0 )
+ {
+ iCurrent->SetFill( EFillTransition );
+ }
+ }
+ else if ( aName.CompareF( KEndsyncAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KFirstVal ) == 0 )
+ {
+ iCurrent->SetEndsyncL( EEndsyncFirst );
+ }
+ else if (aValue.CompareF( KLastVal ) == 0 )
+ {
+ iCurrent->SetEndsyncL( EEndsyncLast );
+ }
+ else if (aValue.CompareF( KAllVal ) == 0 )
+ {
+ iCurrent->SetEndsyncL( EEndsyncAll );
+ }
+ else
+ {
+ iCurrent->SetEndsyncL( EEndsyncId, aValue );
+ }
+ }
+ else if ( aName.CompareF( KRestartAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KNeverVal ) == 0 )
+ {
+ iCurrent->SetRestart( ERestartNever );
+ }
+ else if (aValue.CompareF( KWhenNotActiveVal ) == 0 )
+ {
+ iCurrent->SetRestart( ERestartWhenNotActive );
+ }
+ else
+ {
+ iCurrent->SetRestart(ERestartAlways);
+ }
+ }
+ else if ( aName.CompareF( KRepeatCountAttr ) == 0 ||
+ aName.CompareF( KRepeatAttr ) == 0 )
+ {
+ TReal32 rc = StringToRealValue( aValue, 1 );
+
+ if ( aValue.CompareF( KIndefiniteVal ) == 0 )
+ {
+ iCurrent->SetRepeatCount( KFloatIndefinite );
+ }
+ else if ( rc > 0 )
+ {
+ iCurrent->SetRepeatCount( rc );
+ }
+ }
+ else if ( aName.CompareF( KIdAttr ) == 0 )
+ {
+ iCurrent->SetIdL( aValue );
+ }
+ else if ( iCurrent->IsMedia() )
+ {
+ CSmilMedia* m = static_cast<CSmilMedia*>( iCurrent );
+ if ( aName.CompareF( KRegionAttr ) == 0 )
+ {
+ if ( iPresentation->GetLayout() )
+ {
+ CSmilRegion* r = iPresentation->GetLayout()->FindRegion( aValue );
+ if ( r )
+ {
+ m->SetRegion( r );
+ }
+ }
+ }
+ else if ( aName.CompareF( KSrcAttr ) == 0 )
+ {
+ m->SetSrcL( aValue );
+ }
+ else if ( aName.CompareF( KAltAttr ) == 0 )
+ {
+ m->SetAltL( aValue );
+ }
+ else if ( aName.CompareF( KTransInAttr ) == 0 )
+ {
+ m->iTransitionIn = iPresentation->FindTransition( aValue );
+ }
+ else if ( aName.CompareF( KTransOutAttr ) == 0 )
+ {
+ m->iTransitionOut = iPresentation->FindTransition( aValue );
+ }
+ else if ( aName.CompareF( KClipBeginAttr ) == 0 ||
+ aName.CompareF( KClipBegin2Attr ) == 0 )
+ {
+ TSmilTime tmp( aValue );
+ if ( tmp.IsFinite() )
+ {
+ m->iClipBegin = tmp;
+ }
+
+ // SMTP values
+ }
+ else if ( aName.CompareF( KClipEndAttr ) == 0 ||
+ aName.CompareF( KClipEnd2Attr ) == 0 )
+ {
+ TSmilTime tmp( aValue );
+ if ( tmp.IsFinite() )
+ {
+ m->iClipEnd = tmp;
+ }
+ //### SMTP values
+ }
+ else if ( aName.CompareF( KTypeAttr ) == 0 )
+ {
+ m->SetTypeL(aValue);
+ }
+ }
+
+ break;
+ }
+ case ELayout:
+ {
+ if ( !iCurrentRegion )
+ {
+ return;
+ }
+
+ if ( aName.CompareF( KWidthAttr ) == 0 )
+ {
+ iCurrentRegion->iWidth = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KHeightAttr ) == 0 )
+ {
+ iCurrentRegion->iHeight = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KTopAttr ) == 0 )
+ {
+ iCurrentRegion->iTop = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KBottomAttr ) == 0 )
+ {
+ iCurrentRegion->iBottom = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KLeftAttr ) == 0 )
+ {
+ iCurrentRegion->iLeft = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KRightAttr ) == 0 )
+ {
+ iCurrentRegion->iRight = TSmilLength( aValue );
+ }
+ else if ( aName.CompareF( KIdAttr ) == 0 )
+ {
+ iCurrentRegion->SetId( aValue );
+ }
+ else if ( aName.CompareF( KRegionNameAttr ) == 0 )
+ {
+ iCurrentRegion->SetName( aValue );
+ }
+ else if ( aName.CompareF( KZIndexAttr ) == 0 )
+ {
+ iCurrentRegion->iZIndex = StringToIntValue( aValue, 0 );
+ }
+ else if ( aName.CompareF( KShowBackgroundAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KAlwaysVal ) == 0 )
+ {
+ iCurrentRegion->iBackgroundMode = MSmilRegion::EAlways;
+ }
+ else if ( aValue.CompareF( KWhenActiveVal ) == 0 )
+ {
+ iCurrentRegion->iBackgroundMode = MSmilRegion::EWhenActive;
+ }
+ }
+ else if ( aName.CompareF( KBackgroundColorAttr ) == 0 ||
+ aName.CompareF( KBackgroundColor2Attr ) == 0 )
+ {
+ TBool transparent;
+ iCurrentRegion->iBackground = ParseColor( aValue, transparent );
+ iCurrentRegion->iTransparent = transparent;
+ }
+ else if ( aName.CompareF( KFitAttr ) == 0 )
+ {
+ if ( aValue.CompareF( KMeetVal ) == 0 )
+ {
+ iCurrentRegion->iFit = MSmilRegion::EMeet;
+ }
+ else if ( aValue.CompareF( KSliceVal ) == 0 )
+ {
+ iCurrentRegion->iFit = MSmilRegion::ESlice;
+ }
+ else if ( aValue.CompareF( KFillVal ) == 0 )
+ {
+ iCurrentRegion->iFit = MSmilRegion::EFill;
+ }
+ else if ( aValue.CompareF( KHiddenVal ) == 0 )
+ {
+ iCurrentRegion->iFit = MSmilRegion::EHidden;
+ }
+ else if ( aValue.CompareF( KScrollVal ) == 0 )
+ {
+ iCurrentRegion->iFit = MSmilRegion::EScroll;
+ }
+ }
+ break;
+ }
+ case EHead:
+ case ELayoutFinished:
+ {
+ if ( !iCurrentTransition )
+ {
+ return;
+ }
+
+ if ( aName.CompareF( KIdAttr ) == 0 )
+ {
+ iCurrentTransition->SetId( aValue );
+ }
+ else if ( aName.CompareF( KTypeAttr ) == 0 )
+ {
+ iCurrentTransition->SetType( aValue );
+ }
+ else if ( aName.CompareF( KSubtypeAttr ) == 0 )
+ {
+ iCurrentTransition->SetSubtype( aValue );
+ }
+ else if ( aName.CompareF( KDurAttr ) == 0 )
+ {
+ iCurrentTransition->iDur = TSmilTime( aValue );
+ }
+ else if ( aName.CompareF( KFadeColorAttr ) == 0 )
+ {
+ TBool b;
+ iCurrentTransition->iFadeColor = ParseColor( aValue, b );
+ }
+ else if ( aName.CompareF( KDirectionAttr ) == 0 )
+ {
+ iCurrentTransition->iReverse = ( aValue.CompareF( KReverseVal ) == 0 );
+ }
+ else if ( aName.CompareF( KStartProgressAttr ) == 0 )
+ {
+ iCurrentTransition->iStartProgress = (TInt8)( 100 * StringToRealValue( aValue, 0 ) );
+ }
+ else if ( aName.CompareF( KEndProgressAttr ) == 0 )
+ {
+ iCurrentTransition->iEndProgress = (TInt8)( 100 * StringToRealValue( aValue, 1 ) );
+ }
+ break;
+ }
+ case ESmil:
+ {
+ if ( aName.Left(6).CompareF( KXmlnsAttr2 ) == 0 &&
+ aName.Length() > 6 &&
+ aValue.Length() > 0 )
+ {
+ Namespace ns;
+ ns.name = aName.Mid(6).AllocL();
+ ns.uri = aValue.AllocL();
+ iNamespaces->AddL(ns);
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::AttributesEndL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::AttributesEndL( TInt /*aCount*/ )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("AttributesEnd"));
+#endif
+
+ if ( !iSwitchStack->IsEmpty() &&
+ iSwitchStack->Peek().depth == iDepth - 1 &&
+ iIgnoreDepth == 0 )
+ {
+ iSwitchStack->Peek().done = ETrue;
+ }
+
+ //unknown element, start ignoring if skip-content="true" (default)
+ if ( iUnknownElement )
+ {
+ if ( iSkipContent && !iIgnoreDepth )
+ {
+ iIgnoreDepth = 1;
+ }
+ iUnknownElement = EFalse;
+ }
+ // timing element
+ else if ( iState == EBody && iCurrent )
+ {
+ if ( iIgnoreDepth == 0 && iTimegraphSize < MAX_TIMEGRAPH_SIZE )
+ {
+ if ( iTimeContainer )
+ {
+ iTimeContainer->AddChild( iCurrent );
+ }
+
+ if ( iCurrent->IsTimeContainer() )
+ {
+ iTimeContainer = static_cast<CSmilTimeContainer*>( iCurrent );
+ }
+
+ iCurrent->AttachedL();
+ iCurrent = 0;
+ iTimegraphSize++;
+ }
+ else
+ {
+ delete iCurrent;
+ iCurrent = 0;
+ }
+ }
+ // other
+ else
+ {
+ if ( iTag == KParamTag && iTimeContainer && iTimeContainer->IsMedia() )
+ {
+ if ( iParamName.Length() > 0 && iParamValue.Length() > 0 )
+ {
+ static_cast<CSmilMedia*>(iTimeContainer)->AddParamL( iParamName, iParamValue );
+ }
+ }
+ else if ( iCurrentRegion && iCurrentRegion != iPresentation->GetLayout() )
+ {
+ if ( iIgnoreDepth == 0 )
+ {
+ iPresentation->GetLayout()->AddChild( iCurrentRegion );
+
+ iCurrentRegion = 0;
+ }
+ else
+ {
+ delete iCurrentRegion;
+ iCurrentRegion = 0;
+ }
+ }
+ else
+ {
+ iCurrentRegion = 0;
+ }
+ }
+
+ iArea = 0;
+
+ iTag.Set( TPtrC() );
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::CheckSystemAttribute
+// ----------------------------------------------------------------------------
+//
+TBool CSmilParser::CheckSystemAttribute(const TDesC& aName, const TDesC& aValue)
+ {
+ if ( !( aName.Left( 6 ) == KSystemAttr ) )
+ {
+ return EFalse;
+ }
+
+ if ( iIgnoreDepth > 0 )
+ {
+ return ETrue;
+ }
+
+ if ( aName == KSystemRequiredAttr )
+ {
+ TInt b = 0;
+ TInt e = 0;
+ while ( e < aValue.Length() )
+ {
+ while ( e < aValue.Length() && aValue[e] != '+' )
+ {
+ e++;
+ }
+
+ TPtrC item = aValue.Mid( b, e - b );
+ TBool found = EFalse;
+ CLinkedList<Namespace>::Iter nsi(*iNamespaces);
+
+ while( nsi.HasMore() )
+ {
+ Namespace ns = nsi.Next();
+ if ( *(ns.name) == item )
+ {
+ found = EFalse;
+ for ( TInt n = 0; KSystemReqValue[n]; n++ )
+ {
+ if ( *(ns.uri) == TPtrC( KSystemReqValue[n] ) )
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ iIgnoreDepth = 1;
+ }
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ break;
+ }
+
+ e++;
+ b = e;
+ }
+ }
+ else if ( aName == KSystemScreenSizeAttr )
+ {
+ TInt n = 0;
+ for ( ; n < aValue.Length(); n++ )
+ {
+ if ( aValue[n] == 'x' || aValue[n] == 'X' )
+ {
+ break;
+ }
+ }
+
+ if ( n > 0 && n < aValue.Length() - 1 )
+ {
+ TInt w, h;
+ TLex lex( aValue.Left( n ) );
+ lex.Val( h );
+ lex = TLex( aValue.Mid( n + 1, aValue.Length() - n - 1 ) );
+ lex.Val( w );
+
+ TRect s = iPlayer->GetDimensions( iPresentation );
+ if ( w > s.Width() || h > s.Height() )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+ }
+ else if ( aName == KSystemScreenDepthAttr )
+ {
+ TInt d;
+ TLex lex( aValue );
+ TBool r =lex.Val( d );
+
+ // Hardcoded bitdepth. This should be a callback.
+ // Querying system would be bad idea though, as it would
+ // introduce new lib depedencies.
+ if (r && d > SYSTEM_SCREEN_DEPTH )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+ else if ( aName == KSystemCPUAttr )
+ {
+ if ( aValue != KCPUVal )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+
+ else if ( aName == KSystemOperatingSystemAttr )
+ {
+ if ( aValue != KOSVal )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+ else if ( aName == KSystemComponentAttr &&
+ aValue.Left( 12 ) == KContentTypeVal )
+ {
+ MSmilMediaFactory* f = iPlayer->GetMediaFactory( iPresentation );
+ if ( aValue.Length() >= 13 )
+ {
+ // strip off the scheme part from "ContentType:image/gif"
+ // call with "image/gif" only
+ if ( f->QueryContentType( aValue.Mid( 12 ) ) == EFalse )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+ }
+/* else if (aName==KSystemContentTypeAttr)
+ {
+ MSmilMediaFactory* f = iPlayer->GetMediaFactory(iPresentation);
+ if (f->QueryContentType(aValue)==EFalse)
+ iIgnoreDepth = 1;
+ }*/
+ else
+ {
+ if ( iPlayer->EvaluateContentControlAttribute( aName, aValue ) == EFalse )
+ {
+ iIgnoreDepth = 1;
+ }
+ }
+
+ return ETrue;
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::ParseTimeListL
+// ----------------------------------------------------------------------------
+//
+void CSmilParser::ParseTimeListL( const TDesC& aString, TBool aBegin )
+ {
+ TInt itemindex = 0;
+
+ HBufC* list = HBufC::NewL( aString.Length() );
+ CleanupStack::PushL( list );
+ TPtrC listitem;
+ TPtr buf( list->Des() );
+ buf.Copy( aString );
+ TBool last = EFalse;
+ while( buf.Length() > 0 && !last )
+ {
+ TSmilCondition condition;
+
+ buf.TrimLeft();
+
+ itemindex = buf.Locate(';');
+ if( itemindex > 0 )
+ listitem.Set( buf.Left( itemindex ) );
+ else
+ {
+ listitem.Set( buf.Right( buf.Length() - itemindex ) );
+ last = ETrue;
+ }
+
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("timelist: %S"),&listitem);
+#endif
+
+ condition.iOffset = TSmilTime( listitem ) ;
+
+ if (condition.iOffset.IsUnresolved())
+ {
+ condition.iOffset = 0;
+ // ### FIXME!
+ TInt colindex = listitem.Locate( '.' );
+
+ TInt offindex = listitem.Locate( ' ' );
+ if (offindex==KErrNotFound)
+ offindex = listitem.Locate( '+' );
+ if (offindex==KErrNotFound)
+ offindex = listitem.Locate( '-' );
+
+ if (colindex!=KErrNotFound)
+ {
+ condition.SetEventSourceL(listitem.Left(colindex));
+ if (offindex==KErrNotFound)
+ condition.SetEventClassL(listitem.Mid(colindex+1));
+ else
+ condition.SetEventClassL(listitem.Mid(colindex+1, offindex-colindex-1));
+
+ }
+ else
+ {
+ if (offindex==KErrNotFound)
+ condition.SetEventClassL(listitem);
+ else
+ condition.SetEventClassL(listitem.Left(offindex));
+ }
+
+ if (offindex!=KErrNotFound)
+ {
+ condition.iOffset = TSmilTime(listitem.Mid(offindex));
+ if (!condition.iOffset.IsFinite())
+ condition.iOffset = 0;
+ }
+
+
+ }
+
+ iCurrent->AddConditionL( condition, aBegin );
+
+ buf.Delete( 0, itemindex + 1 );
+ }
+ CleanupStack::PopAndDestroy(); //list
+ }
+
+
+// ---------------------------------------------------------
+// CMediaObject::StringToRealValue
+// Convert a descriptor to TReal32
+// ---------------------------------------------------------
+//
+TReal32 CSmilParser::StringToRealValue( const TDesC& aString, TReal32 aDefault )
+ {
+ TReal32 value = aDefault;
+ if( aString.Length() != 0 )
+ {
+ TLex lex( aString );
+ if (lex.Val( value ) != KErrNone)
+ {
+ value = aDefault;
+ }
+ }
+ return value;
+ }
+
+// ---------------------------------------------------------
+// CMediaObject::SetBeginString
+// Convert a descriptor to TInt
+// ---------------------------------------------------------
+//
+TInt CSmilParser::StringToIntValue( const TDesC& aString, TInt aDefault )
+ {
+ TInt value = aDefault;
+ if( aString.Length() != 0 )
+ {
+ TLex lex( aString );
+ if (lex.Val( value ) != KErrNone)
+ {
+ value = aDefault;
+ }
+ }
+ return value;
+ }
+
+
+// ----------------------------------------------------------------------------
+// CSmilParser::ParseTimeListL
+// Parser for css2 color values. Should be somewhere else
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TRgb CSmilParser::ParseColor( const TDesC& aStr, TBool& aTransparent )
+ {
+ aTransparent = ETrue;
+ TRgb res;
+ if (aStr.Length()>256)
+ return res;
+ TBuf<256> aString = aStr;
+ aString.LowerCase();
+ if (aString.Length()>1 )
+ {
+ _LIT(KRgbO,"rgb(");
+ TUint32 val;
+ if (aString[0]=='#')
+ {
+ TLex lexer (aString.Mid(1));
+ if (aString.Length()==4)
+ {
+ // #a3b notation (==#aa33bb)
+ if (lexer.Val( val, EHex, TUint(0x00000fff) )==KErrNone )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("color=%x"), val);
+#endif
+ res = TRgb (((val&0xf00)>>8)|((val&0xf00)>>4),
+ ((val&0x0f0)>>4)|(val&0x0f0),
+ (val&0xf)|((val&0xf)<<4));
+ aTransparent = EFalse;
+ }
+ }
+ else
+ {
+ // #aa33bb notation
+ if (lexer.Val( val, EHex, TUint(0x00ffffff) )==KErrNone )
+ {
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("color=%x"), val);
+#endif
+
+ res = TRgb ((val&0x00ff0000)>>16, (val&0x0000ff00)>>8, (val&0x000000ff));
+ aTransparent = EFalse;
+ }
+ }
+ }
+ else if (aString.Left(4)==KRgbO)
+ {
+ // rgb(123,33,167) notation and rgb(40%,10%,70%) notation
+ TInt rgb[3];
+ TInt count=0;
+ TInt b = 4;
+ TInt e = 4;
+ TBool percent = EFalse;
+ while (e<aString.Length())
+ {
+ while (e<aString.Length() && aString[e]==' ')
+ e++;
+ b=e;
+ while (e<aString.Length() && aString[e]!=',' && aString[e]!=')')
+ e++;
+ TInt te = e-1;
+ while (te>b && aString[te]==' ')
+ te--;
+ if (te>=b)
+ {
+ if (aString[te]=='%')
+ {
+ percent = ETrue;
+ te--;
+ }
+ TPtrC num = aString.Mid(b,te-b+1);
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("rgb num=%S"),&num);
+#endif
+ rgb[count] = StringToIntValue(num,0);
+ TInt max = 255;
+ if (percent) max=100;
+ if (rgb[count]<0) rgb[count]=0;
+ if (rgb[count]>max) rgb[count]=max;
+
+ count++;
+ if (count==3)
+ break;
+ }
+ e++;
+ }
+ if (count==3)
+ {
+ if (percent)
+ res = TRgb(rgb[0]*255/100, rgb[1]*255/100, rgb[2]*255/100);
+ else
+ res = TRgb(rgb[0], rgb[1], rgb[2]);
+ aTransparent = EFalse;
+ }
+ }
+ else if (aString==KTransparentVal)
+ {
+ aTransparent = ETrue;
+ }
+ else
+ {
+ for (int n=0; KColorNames[n]; n++)
+ {
+ if (aString == TPtrC(KColorNames[n]))
+ {
+ res = KColorValues[n];
+#ifdef PARSER_DEBUG
+ RDebug::Print(_L("color=%x (%S)"), res.Value(), &aString);
+#endif
+
+ aTransparent = EFalse;
+ break;
+ }
+
+ }
+ }
+ // ### FIXME add system colors!
+
+ }
+
+ return res;
+
+ }
+
+// ----------------------------------------------------------------------------
+// CSmilParser::SetMaxDownUpScaling
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CSmilParser::SetMaxDownUpScaling( TReal32 aDown, TReal32 aUp )
+ {
+ iDown = aDown;
+ iUp = aUp;
+ }