diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiFxEffectParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiFxEffectParser.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1215 @@ +/* +* Copyright (c) 2008 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: +* +*/ + + + +#include "HuiFxEffectParser.h" + +#include +#include +#include +#include +#include +#include +#include +#include "HuiFxConstants.h" +#include "HuiFxFilter.h" +#include "HuiFxGroupLayer.h" +#include "HuiFxFilterLayer.h" +#include "HuiFxVisualLayer.h" +#include "HuiFxEffect.h" +#include "HuiFxParameter.h" +#include "HuiFxScalarParameter.h" +#include "HuiFxColorParameter.h" +#include "uiacceltk/HuiVisual.h" // Class definition +#include "alflogger.h" +#include "huieffectable.h" +#include + +//#define _HUI_FX_PARSER_LOGGING // Enable this, if you need to debug the xml parsing. otherwise leave this out, because the logging breaks the timing of effects +// Debugging macros +#if !defined(NDEBUG) +#define FAIL(CODE, MSG) FailL(CODE, MSG) +#define FAIL1(CODE, MSG, P1) FailL(CODE, MSG, P1) +#else +#define FAIL(CODE, MSG) +#define FAIL1(CODE, MSG, P1) +#endif + +CHuiFxEffectParser* CHuiFxEffectParser::NewL(CHuiFxEngine& aEngine, MHuiEffectable* aVisual) + { + CHuiFxEffectParser* self = NewLC(aEngine, aVisual); + CleanupStack::Pop(self); + return self; + } + +CHuiFxEffectParser* CHuiFxEffectParser::NewLC(CHuiFxEngine& aEngine, MHuiEffectable* aVisual) + { + CHuiFxEffectParser* self = new (ELeave) CHuiFxEffectParser( aEngine, aVisual ); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +void CHuiFxEffectParser::ConstructL() + { + iParser = CMDXMLParser::NewL( this ) ; + User::LeaveIfError( iFs.Connect() ); + CActiveScheduler::Add( this ); + } + +CHuiFxEffectParser::CHuiFxEffectParser( CHuiFxEngine& aEngine, MHuiEffectable* aVisual ) : + CActive( EPriorityHigh ), + iEngine( aEngine ), + iVisual( aVisual ), + iParsingEndedObserver( NULL ), iParsingEndedHandle(0) + { + __ALFFXLOGSTRING2("CHuiFxEffectParser::CHuiFxEffectParser - this: 0x%x aVisual 0x%x", this, aVisual); + } + +CHuiFxEffectParser::~CHuiFxEffectParser() + { + Cancel(); + + delete iParser; + iParser = NULL; + + delete iDoc; + iDoc = NULL; + + delete iEffect; + iEffect = NULL; + + iFs.Close(); + __ALFFXLOGSTRING1("CHuiFxEffectParser::~CHuiFxEffectParser - 0x%x ", this); +} + +void CHuiFxEffectParser::ParseFileCompleteL() + { + TRequestStatus* status = &iStatus; + TInt err = KErrNone; // We don't get any error from the caller. + if ( iIsCancelled ) + { + err = KErrCancel; + } + User::RequestComplete( status, err ); + __ALFFXLOGSTRING1("CHuiFxEffectParser::ParseFileCompleteL - 0x%x",this); + } + +void CHuiFxEffectParser::RunL() + { + __ALFFXLOGSTRING2("CHuiFxEffectParser::RunL - this 0x%x, status: %d", this, iStatus.Int()); + // RunL will only be called once after the parsing completes + if ( iStatus.Int() == KErrNone ) + { + BuildEffectL(); + iEffect->SetEffectFlags( iFlags ); + iFlags = 0; + // As soon as the visual gets the effect, it kills this effect parser. + // Therefore the effect must be stored into a temporary variable + // and the member of the parser set to null to prevent the fresly released visual + // from being destroyed immediately. + // CHuiVisual::SetEffect does dot leave, it just stores the pointer to its own data area, + // so this is a safe trick, and the boat does not leak. + if (iParsingEndedObserver) + { + iParsingEndedObserver->ParsingEnded(iParsingEndedHandle); + } + +#ifndef HUIFX_EFFECTCACHE_ENABLED + CHuiFxEffect* tempEffect = iEffect; +#endif + iEffect = NULL; + if (iVisual) + { + iVisual->EffectSetOpacity(1.0f); +#ifndef HUIFX_EFFECTCACHE_ENABLED + iVisual->SetEffect( tempEffect ); +#endif + } + } + else if ( iStatus.Int() != KErrCancel ) + { + // some error during parsing - delete possible incomplete effect + // and set the effect in the visual to NULL as we did not succeed in creating + // a decent effect + if (iParsingEndedObserver) + { + iParsingEndedObserver->ParsingEnded(iParsingEndedHandle); + } + delete iEffect; + iEffect = NULL; + if (iVisual) + { + iVisual->EffectSetOpacity(1.0f); + iVisual->EffectSetEffect( NULL ); + } + } + else // We got cancelled + { + delete iEffect; + iEffect = NULL; + } + delete this; + // MUST NOT DO ANYTHING AFTER THE delete this -line! + } + +TInt CHuiFxEffectParser::RunError( TInt /*aError*/ ) + { + // we signal that we handled the error + delete iEffect; + iEffect = NULL; + if ( iVisual ) + { + iVisual->EffectSetEffect( NULL ); + } + return KErrNone; + } + +void CHuiFxEffectParser::DoCancel() + { + // cancel the parsing. + // + iIsCancelled = ETrue; + iParser->Cancel(); + // parser should now call our ParseFileCompleteL() + // Unfortunately it will not tell us any error code. + // Therefore we must remember that we were cancelled. + // We can only be cancelled when CHuiFxEffectParser is deleted. + // We do not call iVisual->SetEffect any more in that case + // because in that case the parser gets deleted anyway. + // We don't want to be deleted twice - though setting the parser to NULL after + // deleting should take care of that anyway. + + // Actually it seems that parser will not necessarily call us, + // so we must ensure ourselves that we are completed (but only once!) + // Otherwise then whole system will hang waiting for an event + + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrCancel ); + __ALFFXLOGSTRING1("CHuiFxEffectParser::DoCancel - 0x%x",this); + } + +void CHuiFxEffectParser::ParseL( const TDesC& aFile, TRect aExtRect ) + { + __ALFFXLOGSTRING2("CHuiFxEffectParser::ParseL - 0x%x %S",this, &aFile); + iIsCancelled = EFalse; + iExtRect = aExtRect; + TInt err = iParser->ParseFile( iFs, aFile ); + if ( err != KErrNone ) + { + // If parsing fails, give up immediately + iVisual->EffectSetEffect( NULL ); + User::Leave( err ); + } + iStatus = KRequestPending; + SetActive(); + // BuildEffectL is called in RunL when parser calls our callback which completes us. + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseL - activated "); + } + +void CHuiFxEffectParser::Effect( CHuiFxEffect*& aEffect ) + { + aEffect = iEffect; + iEffect = NULL; + } + +void CHuiFxEffectParser::SetEffectEndObserver( MAlfGfxEffectObserver* aEffectEndObserver, TInt aHandle ) + { + iEffectEndObserver = aEffectEndObserver; + iHandle = aHandle; + } + +void CHuiFxEffectParser::SetParsingEndedObserver( MHuiFxParsingEndedObserver *aObserver, TInt aHandle ) + { + iParsingEndedObserver = aObserver; + iParsingEndedHandle = aHandle; + } + + +void CHuiFxEffectParser::SetEffectFlags( TInt aFlags ) + { + iFlags = aFlags; + } + +void CHuiFxEffectParser::BuildEffectL() + { + __ALFFXLOGSTRING1("CHuiFxEffectParser::BuildEffectL - 0x%x",this); + iEffect = CHuiFxEffect::NewL( iEngine ); + iEffect->SetEffectEndObserver( iEffectEndObserver, iHandle ); + iEffectEndObserver = NULL; + iHandle = 0; + iDoc = iParser->DetachXMLDoc(); + User::LeaveIfNull( iDoc ); + CMDXMLElement* root = iDoc->DocumentElement(); + User::LeaveIfNull( root ); + CMDXMLNode* node = root->FirstChild(); + if( node->NodeName().Compare( KLitLayers ) != 0 ) + { + FAIL(KErrGeneral, _L("Layer list not found")); + } + for (node = node->FirstChild(); node; node = node->NextSibling()) + { + ParseNodeL( node, NULL ); + } + __ALFFXLOGSTRING("CHuiFxEffectParser::BuildEffectL - complete "); + } + +void CHuiFxEffectParser::ParseNodeL( CMDXMLNode* aNode, CHuiFxLayer* aLayer) + { + switch( ResolveNode( aNode ) ) + { + case ENodeTypeUnknown: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeUnknown"); +#endif + FAIL(KErrGeneral, _L("Unknown node type")); + break; + } + + case ENodeTypeGroup: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeGroup"); +#endif + // can't have group layers inside group layer + if (aLayer && aLayer->Type() == ELayerTypeGroup) + { + FAIL(KErrGeneral, _L("Nested group layers not supported")); + } + + CHuiFxGroupLayer* group = CHuiFxGroupLayer::NewL(); + CleanupStack::PushL( group ); + for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling()) + { + ParseNodeL( node, group ); + } + iEffect->AddLayerL( group ); // ownership transferred + CleanupStack::Pop( group ); + break; + } + + case ENodeTypeFilter: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeFilter"); +#endif + THuiFxFilterType filterType = GetFilterTypeL( aNode ); + CHuiFxFilter* filter = iEngine.CreateFilterL( filterType ); + CleanupStack::PushL( filter ); + CHuiFxFilterLayer* filterLayer = CHuiFxFilterLayer::NewL( filter ); + CleanupStack::Pop( filter ); + CleanupStack::PushL( filterLayer ); + if (aLayer && aLayer->Type() == ELayerTypeGroup) + { + CHuiFxGroupLayer* group = reinterpret_cast(aLayer); + group->AddLayerL( filterLayer ); // ownership transferred + } + else + { + iEffect->AddLayerL( filterLayer ); // ownership transferred + } + CleanupStack::Pop( filterLayer ); + + if (filterType == EFilterTypeTransform) + { + filterLayer->SetTransformed(ETrue); + } + + for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling()) + { + ParseNodeL( node, filterLayer ); + } + break; + } + + case ENodeTypeVisual: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeVisual"); +#endif + TPtrC16 extBitmap; + THuiFxVisualSrcType srcType = GetSrcTypeL( aNode, extBitmap ); + CHuiFxVisualLayer* visual = CHuiFxVisualLayer::NewL( *iVisual ); + CleanupStack::PushL( visual ); + visual->SetSourceType( srcType ); + if ( srcType == EVisualSrcBitmap && extBitmap.Length() > 0 ) + { + visual->SetExtBitmapFileL( extBitmap ); + } + if (aLayer && aLayer->Type() == ELayerTypeGroup) + { + CHuiFxGroupLayer* group = reinterpret_cast(aLayer); + group->AddLayerL( visual ); // ownership transferred + } + else + { + iEffect->AddLayerL( visual ); // ownership transferred + } + for (CMDXMLNode* node = aNode->FirstChild(); node; node = node->NextSibling()) + { + ParseNodeL( node, visual ); + } + CleanupStack::Pop( visual ); + break; + } + + case ENodeTypeBlending: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeBlending"); +#endif + CMDXMLNode* blendingNode = aNode->FirstChild(); + if( blendingNode->NodeType() != CMDXMLNode::ETextNode ) + { + FAIL(KErrGeneral, _L("Bad blending mode")); + } + TPtrC modePtr( ((CMDXMLText *)blendingNode)->Data() ); + + // set replace as default blending mode + THuiFxBlendingMode blendingMode = EBlendingModeReplace; + if( modePtr.Compare( KLitReplace ) == 0 ) + { + blendingMode = EBlendingModeReplace; + } + else if( modePtr.Compare( KLitOver ) == 0 ) + { + blendingMode = EBlendingModeOver; + } + else if( modePtr.Compare( KLitMultiply ) == 0 ) + { + blendingMode = EBlendingModeMultiply; + } + else if( modePtr.Compare( KLitAdditive ) == 0 ) + { + blendingMode = EBlendingModeAdditive; + } + else if( modePtr.Compare( KLitDarken ) == 0 ) + { + blendingMode = EBlendingModeDarken; + } + else if( modePtr.Compare( KLitLighten ) == 0 ) + { + blendingMode = EBlendingModeLighten; + } + else + { + FAIL(KErrGeneral, _L("Bad blending mode")); + } + + if (aLayer && aLayer->Type() == ELayerTypeGroup) + { + aLayer->SetBlendingMode( blendingMode ); + } + else + { + // TODO: should other layers have a blending mode? + FAIL(KErrGeneral, _L("Blending mode can only be set for a group layer")); + } + break; + } + + case ENodeTypeParam: + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - ENodeTypeParam"); +#endif + ResolveParamL(aNode, aLayer); + break; + } + + default: + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseNodeL - default??"); + break; + } + + } + +CHuiFxEffectParser::TNodeType CHuiFxEffectParser::ResolveNode( CMDXMLNode* aNode ) + { + TPtrC nodeName( aNode->NodeName() ); + if( nodeName.Compare( KLitLayerGroup ) == 0 ) + { + return ENodeTypeGroup; + } + else if( nodeName.Compare( KLitFilter ) == 0 ) + { + return ENodeTypeFilter; + } + else if( nodeName.Compare( KLitVisual ) == 0 ) + { + return ENodeTypeVisual; + } + else if( nodeName.Compare( KLitBlending ) == 0 ) + { + return ENodeTypeBlending; + } + else if( nodeName.Compare( KLitParam ) == 0 ) + { + return ENodeTypeParam; + } + else if( nodeName.Compare( KLitStyle ) == 0 ) + { + return ENodeTypeStyle; + } + else if( nodeName.Compare( KLitDuration ) == 0 ) + { + return ENodeTypeDuration; + } + else if( nodeName.Compare( KLitKeyFrame ) == 0 ) + { + return ENodeTypeKeyFrame; + } + else if( nodeName.Compare( KLitMarker ) == 0 ) + { + return ENodeTypeMarker; + } + else if( nodeName.Compare( KLitStart ) == 0 ) + { + return ENodeTypeStart; + } + else if( nodeName.Compare( KLitEnd ) == 0 ) + { + return ENodeTypeEnd; + } + else + { + return ENodeTypeUnknown; + } + } + +// not locale dependent float parser +static TReal32 ParseFloatVal(TPtrC valuePtr) + { + HBufC8 *buf = HBufC8::New(valuePtr.Length()+1); + if (!buf) return 0.0; + CleanupStack::PushL(buf); + buf->Des().Copy(valuePtr); + + TUint8 *buf2 = new TUint8[valuePtr.Length()+1]; + if (!buf2) return 0.0; + int s = valuePtr.Length(); + int i = 0; + for(;ioperator[](i); + buf2[i] = 0; + + TReal32 v = atof((const char*)buf2); + delete [] buf2; + CleanupStack::PopAndDestroy(buf); + return v; + } + +TReal32 CHuiFxEffectParser::ParseFloatAttributeL(CMDXMLNode* aNode, const TDesC& aName, TBool aMustExist) + { + TInt index = ((CMDXMLElement*)aNode)->FindIndex(aName); + if( index == KErrNotFound ) + { + if (aMustExist) + { + FAIL1(KErrGeneral, _L("Attribute not found: %S"), &aName); // leaves + return 0.0f; // never reached. For completeness + } + else + { + return 0.0f; + } + } + + TPtrC attributeValue; + TPtrC attributeName; + TReal32 value = 0.0f; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( index, attributeName, attributeValue )); + + value = ParseFloatVal(attributeValue); + return value; + } + +TReal32 CHuiFxEffectParser::ParseFloatValueL(CMDXMLNode* aNode) + { + if ( !aNode || aNode->NodeType() != CMDXMLNode::ETextNode ) + { + FAIL(KErrGeneral, _L("Text node expected while parsing a floating point value")); + } + + TPtrC valuePtr( ((CMDXMLText *)aNode)->Data() ); + TReal32 v = ParseFloatVal(valuePtr); + return v; + } + +TRgb CHuiFxEffectParser::ParseColorValueL(CMDXMLNode* aNode) + { + // Parse color definition in HTML notation (#aarrggbb) + if ( !aNode || aNode->NodeType() != CMDXMLNode::ETextNode ) + { + FAIL(KErrGeneral, _L("Text node expected while parsing a color value")); // leaves + return KRgbBlack; // never reached. For completeness + } + + TPtrC valuePtr( ((CMDXMLText *)aNode)->Data() ); + TLex parser(valuePtr); + + if (parser.Get() != '#') + { + FAIL(KErrGeneral, _L("Invalid color specification")); // leaves + return KRgbBlack; // never reached. For completeness + } + + TUint32 color; + parser.Val(color, EHex); + // Opaque alpha by default + if (valuePtr.Length() <= 7) + { + color |= 0xff000000; + } + + TUint32 r = (color & 0x00ff0000) >> 16; + TUint32 g = (color & 0x0000ff00) >> 8; + TUint32 b = (color & 0x000000ff); + TUint32 a = (color & 0xff000000) >> 24; + + return TRgb(r, g, b, a); + } + +template <> +TReal32 CHuiFxEffectParser::ParseAnimationKeyFrameValueL(CMDXMLNode* aNode, RHuiFxScalarTimeLine& /*aTimeLine*/) + { + return ParseFloatValueL(aNode); + } + +template <> +TRgb CHuiFxEffectParser::ParseAnimationKeyFrameValueL(CMDXMLNode* aNode, RHuiFxColorTimeLine& /*aTimeLine*/) + { + return ParseColorValueL(aNode); + } + +template +void CHuiFxEffectParser::ParseAnimationNodeL(CMDXMLNode* aNode, PARAM_TYPE& aParam, TIMELINE_TYPE& aTimeLine) + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING1("CHuiFxEffectParser::ParseAnimationNodeL - 0x%x", this); +#endif + switch( ResolveNode( aNode ) ) + { + case ENodeTypeDuration: + { + aTimeLine.SetDuration(ParseFloatValueL(aNode->FirstChild())); + } + break; + case ENodeTypeStyle: + { + CMDXMLNode* styleNode = aNode->FirstChild(); + if (styleNode->NodeType() != CMDXMLNode::ETextNode) + { + FAIL(KErrGeneral, _L("Text node expected while parsing an interpolation mode")); + } + TPtrC modePtr( ((CMDXMLText *)styleNode)->Data() ); + + if( modePtr.Compare( KLitHold ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeHold); + } + else if( modePtr.Compare( KLitLinear ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeLinear); + } + else if( modePtr.Compare( KLitInQuad ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeInQuad); + } + else if( modePtr.Compare( KLitOutQuad ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeOutQuad); + } + else if( modePtr.Compare( KLitInOutQuad ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeInOutQuad); + } + else if( modePtr.Compare( KLitOutInQuad ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeOutInQuad); + } + else if( modePtr.Compare( KLitInBack ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeInBack); + } + else if( modePtr.Compare( KLitOutBack ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeOutBack); + } + else if( modePtr.Compare( KLitInOutBack ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeInOutBack); + } + else if( modePtr.Compare( KLitOutInBack ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeOutInBack); + } + else if( modePtr.Compare( KLitQuadraticBezier ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeQuadraticBezier); + } + else if( modePtr.Compare( KLitCubicBezier ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeCubicBezier); + } +/* + else if( modePtr.Compare( KLitDeclerate ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeDecelerate); + } + else if( modePtr.Compare( KLitAccelerate ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeAccelerate); + } + else if( modePtr.Compare( KLitImpulse ) == 0 ) + { + aTimeLine.SetInterpolationMode(EInterpolationModeImpulse); + } +*/ + else + { + // unknown (unsupported) interpolation modes default to linear + // (at least during testing when we add modes) + aTimeLine.SetInterpolationMode(EInterpolationModeLinear); +// FAIL(KErrGeneral, _L("Unknown interpolation mode")); + } + break; + } + case ENodeTypeMarker: + { + TReal32 time = ParseFloatAttributeL(aNode, KLitAt); + TInt typeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitType ); + + if (typeIndex == KErrNotFound) + { + FAIL(KErrGeneral, _L("Marker name not found")); + } + + TPtrC attributeValue; + TPtrC attributeName; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( typeIndex, attributeName, attributeValue )); + + // TODO: Should this be controllable? + aTimeLine.SetLoopingMode(ELoopingModeRepeat); + + if (attributeValue.Compare(KLitLoopStart) == 0) + { + aTimeLine.SetLoopStart(time); + } + else if (attributeValue.Compare(KLitLoopEnd) == 0) + { + aTimeLine.SetLoopEnd(time); + } + else + { + FAIL(KErrGeneral, _L("Unsupported marker type")); + } + break; + } + case ENodeTypeKeyFrame: + { + TReal32 time = ParseFloatAttributeL(aNode, KLitAt); + TReal32 aux1 = ParseFloatAttributeL(aNode, KLitAux1, EFalse); + TReal32 aux2 = ParseFloatAttributeL(aNode, KLitAux2, EFalse); + VALUE_TYPE value = ParseAnimationKeyFrameValueL(aNode->FirstChild(), aTimeLine); + TRAPD(err, aTimeLine.AppendKeyFrameL(time, value, aux1, aux2)); + if (err != KErrNone) + { + FAIL(KErrGeneral, _L("Unable to append new key frame to timeline")); + } + } + break; + case ENodeTypeStart: + { + TInt refIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitRef ); + TReal32 refValue = 0; + TBool needRefValue = EFalse; + THuiFxReferencePoint ref = EReferencePointUndefined; + if ( refIndex != KErrNotFound ) + { + ref = GetReferencePointL( aNode, refValue, needRefValue ); + } + aParam.SetStartReference( ref ); + if ( needRefValue ) + { + aParam.SetStartValue( refValue ); + } + if ( aParam.StartReference() != EReferencePointUndefined && + aParam.EndReference() != EReferencePointUndefined ) + { + aParam.SetReferencePoint( EReferencePointUndefined ); + } + float value = ParseFloatValueL(aNode->FirstChild()); + aParam.SetStartMultiplier( value ); + + } + break; + case ENodeTypeEnd: + { + TInt refIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitRef ); + TReal32 refValue = 0; + TBool needRefValue = EFalse; + THuiFxReferencePoint ref = EReferencePointUndefined; + if ( refIndex != KErrNotFound ) + { + ref = GetReferencePointL( aNode, refValue, needRefValue ); + } + aParam.SetEndReference( ref ); + if ( needRefValue ) + { + aParam.SetEndValue( refValue ); + } + if ( aParam.StartReference() != EReferencePointUndefined && + aParam.EndReference() != EReferencePointUndefined ) + { + aParam.SetReferencePoint( EReferencePointUndefined ); + } + float value = ParseFloatValueL(aNode->FirstChild()); + aParam.SetEndMultiplier( value ); + + } + break; + } +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ParseAnimationNodeL - out"); +#endif + } + + +void CHuiFxEffectParser::ResolveParamL( CMDXMLNode* aNode, CHuiFxLayer* aLayer ) + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING1("CHuiFxEffectParser::ResolveParamL - 0x%x",this); +#endif + ASSERT(aNode->NodeType() == CMDXMLNode::EElementNode); + + TInt nameIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitName ); + TInt typeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitType ); + TInt refIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitRef ); + if( nameIndex == KErrNotFound ) + { + FAIL(KErrGeneral, _L("Parameter name not found")); + } + + THuiFxReferencePoint ref = EReferencePointIdentity; + TBool isAnimated = EFalse; + TPtrC paramName; + TPtrC attributeName; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails(nameIndex, attributeName, paramName)); + + if (typeIndex != KErrNotFound) + { + TPtrC paramType; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails(typeIndex, attributeName, paramType)); + + if( paramType.Compare( KLitAnim ) == 0 ) + { + isAnimated = ETrue; + aLayer->SetAnimated(ETrue); + } + else + { + FAIL(KErrGeneral, _L("Unsupported parameter type")); + } + } + + TReal32 refValue; + TBool needRefValue = EFalse; + + + if ( refIndex != KErrNotFound ) + { + ref = GetReferencePointL( aNode, refValue, needRefValue ); + if ( ref == EReferencePointUndefined ) + { + // For the parameters an undefined reference point means no value for the change + ref = EReferencePointIdentity; + } + } + + MHuiFxParameter* param = NULL; + if (aLayer && aLayer->Type() == ELayerTypeFilter) + { + CHuiFxFilterLayer* filterLayer = reinterpret_cast(aLayer); + // We must check if we really have a filter. + // If the filter type was incorrect, a filter was not created + // We should not crash or panic even if the effect file is not syntactically correct. + // An incorrect file should simply produce no effect. + CHuiFxFilter& filter = filterLayer->Filter(); + + if ( &filter ) + { + param = filter.Parameter( paramName ); + } + } + else if (aLayer && aLayer->Type() == ELayerTypeVisual) + { + CHuiFxVisualLayer* visualLayer = reinterpret_cast(aLayer); + param = visualLayer->Parameter(paramName); + } + + if (!param) + { + FAIL(KErrNotFound, _L("Parameter name not recognized")); // leaves + return; // never reached. For completeness + } + + param->SetReferencePoint(ref); + if ( needRefValue ) + { + param->SetReferenceValue( refValue ); + } + + if (isAnimated) + { + // Collect animation keyframes and other parameters + switch (param->Type()) + { + case EParameterTypeScalar: + { + RHuiFxScalarTimeLine* t = new (ELeave) RHuiFxScalarTimeLine(); + CHuiFxScalarParameter* p = static_cast(param); + CleanupStack::PushL(t); + for (CMDXMLNode* child = aNode->FirstChild(); child; child = child->NextSibling()) + { + ParseAnimationNodeL(child, *p, *t); + } + CleanupStack::Pop(t); + p->SetTimeLine(t); + if ( p->ReferencePoint() == EReferencePointUndefined ) + { + if ( paramName.Compare( KLitScaleX ) == 0 ) + { + p->SetReferencePoint( EReferencePointVisualWidth ); + } + else if ( paramName.Compare( KLitScaleY ) == 0 ) + { + p->SetReferencePoint( EReferencePointVisualHeight ); + } + else + { + p->SetReferencePoint( EReferencePointIdentity ); + } + } + break; + } + case EParameterTypeColor: + { + RHuiFxColorTimeLine* t = new (ELeave) RHuiFxColorTimeLine(); + CHuiFxColorParameter* p = static_cast(param); + CleanupStack::PushL(t); + for (CMDXMLNode* child = aNode->FirstChild(); child; child = child->NextSibling()) + { + ParseAnimationNodeL(child, *p, *t); + } + CleanupStack::Pop(t); + p->SetTimeLine(t); + if ( p->ReferencePoint() == EReferencePointUndefined ) + { + p->SetReferencePoint( EReferencePointIdentity ); + } + break; + } + } + } + else + { + switch (param->Type()) + { + case EParameterTypeScalar: + { + CHuiFxScalarParameter* p = static_cast(param); + p->SetValue(ParseFloatValueL(aNode->FirstChild())); + break; + } + case EParameterTypeColor: + { + CHuiFxColorParameter* p = static_cast(param); + p->SetValue(ParseColorValueL(aNode->FirstChild())); + break; + } + } + } +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING("CHuiFxEffectParser::ResolveParamL - out "); +#endif + } + +THuiFxFilterType CHuiFxEffectParser::GetFilterTypeL( CMDXMLNode* aNode ) + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING1("CHuiFxEffectParser::GetFilterTypeL - 0x%x",this); +#endif + if (aNode->NodeType() != CMDXMLNode::EElementNode) + { + FAIL(KErrGeneral, _L("Text node expected while reading filter type")); + } + + TInt attributeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitType ); + + if (attributeIndex == KErrNotFound) + { + FAIL(KErrGeneral, _L("Filter type not found")); + } + + TPtrC attributeValue; + TPtrC attributeName; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( attributeIndex, attributeName, attributeValue)); + + if( attributeValue.Compare( KLitDesaturate ) == 0 ) + { + return EFilterTypeDesaturate; + } + else if( attributeValue.Compare( KLitBlur ) == 0 ) + { + return EFilterTypeBlur; + } + else if( attributeValue.Compare( KLitGlow ) == 0 ) + { + return EFilterTypeGlow; + } + else if( attributeValue.Compare( KLitBrightnessContrast ) == 0 ) + { + return EFilterTypeBrightnessContrast; + } + else if( attributeValue.Compare( KlitHSL ) == 0 ) + { + return EFilterTypeHSL; + } + else if( attributeValue.Compare( KlitColorize ) == 0 ) + { + return EFilterTypeColorize; + } + else if( attributeValue.Compare( KlitOutline ) == 0 ) + { + return EFilterTypeOutline; + } + else if( attributeValue.Compare( KLitDropShadow ) == 0 ) + { + // drop shadow is generated using outline filter + return EFilterTypeOutline; + } + else if( attributeValue.Compare( KlitBevel ) == 0 ) + { + return EFilterTypeBevel; + } + else if ( attributeValue.Compare ( KlitTransform ) == 0 ) + { + return EFilterTypeTransform; + } + else + { + return EFilterTypeUnknown; + } + } + +THuiFxReferencePoint CHuiFxEffectParser::GetReferencePointL( CMDXMLNode* aNode, TReal32& aRefValue, TBool& aNeedRefValue ) + { + __ALFFXLOGSTRING1("CHuiFxEffectParser::GetReferencePointL - 0x%x",this); + if (aNode->NodeType() != CMDXMLNode::EElementNode) + { + FAIL(KErrGeneral, _L("Text node expected while reading ref type")); + } + + TInt attributeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitRef ); + + THuiFxReferencePoint ref = EReferencePointIdentity; + if (attributeIndex == KErrNotFound) + { + ref = EReferencePointUndefined; + return ref; + } + aRefValue = 0; + + TPtrC attributeName; + TPtrC paramRef; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( attributeIndex, attributeName, paramRef)); + TReal32 refValue = 0; + TBool needRefValue = EFalse; + + if ( paramRef.Compare( KLitVisualWidth ) == 0 ) + { + ref = EReferencePointVisualWidth; + } + else if ( paramRef.Compare( KLitVisualHeight ) == 0 ) + { + ref = EReferencePointVisualHeight; + } + else if ( paramRef.Compare( KLitVisualTop ) == 0 ) + { + ref = EReferencePointVisualTop; + } + else if ( paramRef.Compare( KLitVisualBottom ) == 0 ) + { + ref = EReferencePointVisualBottom; + } + else if ( paramRef.Compare( KLitVisualLeft ) == 0 ) + { + ref = EReferencePointVisualLeft; + } + else if ( paramRef.Compare( KLitVisualRight ) == 0 ) + { + ref = EReferencePointVisualRight; + } + else if ( paramRef.Compare( KLitDisplayWidth ) == 0 ) + { + ref = EReferencePointDisplayWidth; + } + else if ( paramRef.Compare( KLitDisplayHeight ) == 0 ) + { + ref = EReferencePointDisplayHeight; + } + else if ( paramRef.Compare( KLitDisplayTop ) == 0 ) + { + ref = EReferencePointDisplayTop; + } + else if ( paramRef.Compare( KLitDisplayBottom ) == 0 ) + { + ref = EReferencePointDisplayBottom; + } + else if ( paramRef.Compare( KLitDisplayLeft ) == 0 ) + { + ref = EReferencePointDisplayLeft; + } + else if ( paramRef.Compare( KLitDisplayRight ) == 0 ) + { + ref = EReferencePointDisplayRight; + } + else if ( paramRef.Compare( KLitExtRectWidth ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectWidth; + refValue = iExtRect.Width(); + } + else if ( paramRef.Compare( KLitExtRectHeight ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectHeight; + refValue = iExtRect.Height(); + } + else if ( paramRef.Compare( KLitExtRectTop ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectTop; + refValue = iExtRect.iTl.iY; + } + else if ( paramRef.Compare( KLitExtRectBottom ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectBottom; + refValue = iExtRect.iBr.iY; + } + else if ( paramRef.Compare( KLitExtRectLeft ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectLeft; + refValue = iExtRect.iTl.iX; + } + else if ( paramRef.Compare( KLitExtRectRight ) == 0 ) + { + needRefValue = ETrue; + ref = EReferencePointExtRectRight; + refValue = iExtRect.iBr.iX; + } + // these are deprecated + else if (paramRef.Compare(KLitVisualWidth1) == 0) + { + ref = EReferencePointVisualWidth; + } + else if (paramRef.Compare(KLitVisualHeight1) == 0) + { + ref = EReferencePointVisualHeight; + } + else if (paramRef.Compare(KLitDisplayWidth1) == 0) + { + ref = EReferencePointDisplayWidth; + } + else if (paramRef.Compare(KLitDisplayHeight1) == 0) + { + ref = EReferencePointDisplayHeight; + } + else + { + FAIL(KErrGeneral, _L("Unsupported parameter reference point")); + } + aRefValue = refValue; + aNeedRefValue = needRefValue; +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING1("CHuiFxEffectParser::GetReferencePointL - return %d",ref); +#endif + return ref; + } + +THuiFxVisualSrcType CHuiFxEffectParser::GetSrcTypeL( CMDXMLNode* aNode, TPtrC16& aBitmap ) + { +#ifdef _HUI_FX_PARSER_LOGGING + __ALFFXLOGSTRING1("CHuiFxEffectParser::GetSrcTypeL - 0x%x ",this); +#endif + if (aNode->NodeType() != CMDXMLNode::EElementNode) + { + FAIL(KErrGeneral, _L("Text node expected while reading visual source type")); + } + TInt attributeIndex = ((CMDXMLElement*)aNode)->FindIndex( KLitSrc ); + + if (attributeIndex == KErrNotFound) + { + // If src not found, the source defaults to visual itself + return EVisualSrcVisual; + } + + TPtrC attributeValue; + TPtrC attributeName; + User::LeaveIfError(((CMDXMLElement*)aNode)->AttributeDetails( attributeIndex, attributeName, attributeValue )); + + if( attributeValue.Compare( KLitItem ) == 0 ) + { + return EVisualSrcVisual; + } + else if ( attributeValue.Compare( KLitInput1 ) == 0 ) + { + // This means that the source is given as a parameter to the effect + return EVisualSrcInput1; + } + else if ( attributeValue.Compare( KLitInput2 ) == 0 ) + { + // This means that the source is given as a parameter to the effect + return EVisualSrcInput2; + } + else + { + // if nothing else is defined, the src represents an external file (bitmap) + aBitmap.Set( attributeValue ); + return EVisualSrcBitmap; + } + + } + + +void CHuiFxEffectParser::FailL(TInt aCode, TRefByValue aFormat, ...) + { + TBuf<512> message; + VA_LIST args; + VA_START(args, aFormat); + message.Append(_L("CHuiFxEffectParser::Fail(): ")); + message.AppendFormatList(aFormat, args); + VA_END(args); + __ALFFXLOGSTRING1("CHuiFxEffectParser::FailL %S", &message); + User::InfoPrint( message ); + User::Leave(aCode); + }