diff -r 000000000000 -r 72b543305e3a messagingappbase/smilengine/engine/parser/smilparser.cpp --- /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::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(); + iNamespaces = new( ELeave ) CLinkedList(); + } + +// ---------------------------------------------------------------------------- +// 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::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( 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 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 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( 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( 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(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::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 (eb && 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; + }