diff -r 000000000000 -r 05e9090e2422 skins/AknSkins/alsrc/AknsAlAnimatorBmp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/skins/AknSkins/alsrc/AknsAlAnimatorBmp.cpp Thu Dec 17 09:14:12 2009 +0200 @@ -0,0 +1,1319 @@ +/* +* Copyright (c) 2004-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: Animates effect queues. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include + +#include + +#include "AknsRlEffectPlugin.h" +#include "AknsRlCommand.h" + +#include "AknsAppSkinInstance.h" +#include "AknsAlAnimatorBmp.h" +#include "AknsAlShared.h" +#include "AknsAlAnimationFactory.h" +#include "AknsAlEffectContext.h" +#include "AknsAlDataAccess.h" +#include // For the animation state enum + +#include "AknsDebug.h" + +// CONSTANTS + +const TInt KAlMaxDeltaTime = 65536; // In milliseconds, ~65 seconds + +// =============================== HELPERS ===================================== +/** +* Utility class for binding size changes to animation value parameters. +*/ +NONSHARABLE_CLASS( CAknsAlSizeBoundParam ): + public CBase, + public MAknsRlParameterIterator + { + private: + // Internal flag indices + enum TFlag + { + EFlagW = 0, + EFlagH = 1, + EFlagIter = 2 + }; + + protected: + CAknsAlSizeBoundParam(); + void ConstructL( MAknsAlAnimationValue* aValue, + const TDesC& aName, TInt aFlags ); + + public: + ~CAknsAlSizeBoundParam(); + static CAknsAlSizeBoundParam* NewL( MAknsAlAnimationValue* aValue, + const TDesC& aName, TInt aFlags ); + void SizeChangedL( const TSize& aNewSize ); + + public: // Implementation of MAknsRlParameterIterator + TBool HasNext(); + const TAknsRlParameterData* NextL(); + + private: + // Referenced only + MAknsAlAnimationValue* iAnimationValue; + // Owned + HBufC* iName; + /// Combines the x, y, xy flags with interator flag. + TBitFlags32 iFlags; + TAknsRlParameterData iIteratorData; + // Stores the current size + TBuf16<2> iSize; + }; + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::CAknsAlSizeBoundParam +// ----------------------------------------------------------------------------- +// +CAknsAlSizeBoundParam::CAknsAlSizeBoundParam() + { + // Derived from CBase -> members are zeroed + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::ConstructL +// ----------------------------------------------------------------------------- +// +void CAknsAlSizeBoundParam::ConstructL( MAknsAlAnimationValue* aValue, + const TDesC& aName, TInt aFlags ) + { + if( NULL == aValue ) + User::Leave( KErrArgument ); + + iAnimationValue = aValue; + iName = aName.AllocL(); + iFlags.SetValue( aFlags ); + + iSize.SetLength( 2 ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::~CAknsAlSizeBoundParam +// ----------------------------------------------------------------------------- +// +CAknsAlSizeBoundParam::~CAknsAlSizeBoundParam() + { + delete iName; //lint + iAnimationValue = NULL; // Removes lint nag + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::NewL +// ----------------------------------------------------------------------------- +// +CAknsAlSizeBoundParam* CAknsAlSizeBoundParam::NewL( + MAknsAlAnimationValue* aValue, + const TDesC& aName, + TInt aFlags ) + { + CAknsAlSizeBoundParam* self = new(ELeave) CAknsAlSizeBoundParam(); + CleanupStack::PushL( self ); + self->ConstructL( aValue, aName, aFlags ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::SizeChangedL +// ----------------------------------------------------------------------------- +// +void CAknsAlSizeBoundParam::SizeChangedL( const TSize& aNewSize ) + { + iSize[0] = TInt16( aNewSize.iWidth ); + iSize[1] = TInt16( aNewSize.iHeight ); + + // Push the changed parameter to animation value + iFlags.Set( EFlagIter ); + iAnimationValue->SetParametersL( *this ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::HasNext +// ----------------------------------------------------------------------------- +// +TBool CAknsAlSizeBoundParam::HasNext() + { + if( !iFlags.IsSet( EFlagIter ) ) + return ETrue; + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CAknsAlSizeBoundParam::NextL +// ----------------------------------------------------------------------------- +// +const TAknsRlParameterData* CAknsAlSizeBoundParam::NextL() + { + if( iFlags.IsSet( EFlagIter ) ) + User::Leave( KErrOverflow ); + + iIteratorData.iName = iName; + + if( iFlags.IsSet( EFlagW ) && iFlags.IsSet( EFlagH ) ) + { + iIteratorData.iType = EAknsRlParameterTypeString; + iIteratorData.iString = &iSize; + } + else if( iFlags.IsSet( EFlagW ) ) + { + iIteratorData.iType = EAknsRlParameterTypeNumber; + iIteratorData.iNumber = iSize[0]; + } + else // Must be EFlagH + { + iIteratorData.iType = EAknsRlParameterTypeNumber; + iIteratorData.iNumber = iSize[1]; + } + + // Mark the iterator flag + iFlags.Set( EFlagIter ); + + return &iIteratorData; + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CAknsAlAnimatorBmp +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CAknsAlAnimatorBmp::CAknsAlAnimatorBmp( MAknsEffectAnimObserver* aObserver ): + iObserver( aObserver ) + { + // Derived from CBase, members zeroed + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::ConstructL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::ConstructL() + { + iState = EAknsAnimStateStopped; + + iTimer = CPeriodic::NewL( CActive::EPriorityIdle ); + + User::LeaveIfError( HAL::Get( HALData::ESystemTickPeriod, iMsPerTick ) ); + // HAL returns microseconds, convert to milliseconds + iMsPerTick = iMsPerTick / 1000; + + iContext = CAknsAlEffectContext::NewL(); + + iLightsClient = CHWRMLight::NewL( this ); + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CAknsAlAnimatorBmp::~CAknsAlAnimatorBmp() + { + /*lint -save -e1551 */ // No exceptions are thrown + // Release effect filters + TInt count = iAnimationCommands.Count(); + for( TInt i=0; i < count; i++ ) + { + // Activate effects + CAknsAlAnimationCommand* cmd = iAnimationCommands[i]; + MAknsRlEffect* effect = cmd->Effect(); + effect->Deactivate(); + effect->Release(); + } + + delete iTimer; + delete iContext; + + iPreprocessCommands.ResetAndDestroy(); + iAnimationCommands.ResetAndDestroy(); + iValueContainers.ResetAndDestroy(); + iTimingModels.ResetAndDestroy(); + iSizeBoundParams.ResetAndDestroy(); + + delete iLightsClient; + /*lint -restore */ + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::NewL +// ----------------------------------------------------------------------------- +// +CAknsAlAnimatorBmp* CAknsAlAnimatorBmp::NewL( MAknsEffectAnimObserver* aObserver ) + { + if( !aObserver ) + User::Leave( KErrArgument ); + + CAknsAlAnimatorBmp* self = new(ELeave) CAknsAlAnimatorBmp( aObserver ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::ConstructFromSkinL +// ----------------------------------------------------------------------------- +// +TBool CAknsAlAnimatorBmp::ConstructFromSkinL( const TAknsItemID& aItemID ) + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + if( NULL == skin ) + User::Leave( KErrBadHandle ); + + // TODO: We need to pass skin server session to bitmap context (it is + // required by ApplyGfx plugin). This is bad style but this is currently + // the only way to do it (without BC break). In ideal case you could query + // the server session via the skin instance interface. Note that by + // referring to AppSkinInstance we create an unwanted dependency to other + // parts of skin library. Fortunately, there is no need to link + // AppSkinInstance as we are using the session member directly. + CAknsAppSkinInstance* appSkin = static_cast(skin); //lint !e1774 dynamic_cast not allowed + iContext->SetSkinSrvSession( &appSkin->iSession ); + + // Query animation instructions from skin + CAknsItemData* item = skin->GetCachedItemData( aItemID, EAknsITAnimation ); + if( !item ) + return EFalse; // Item was not found + + // Querying EAknsITAnimation quarantees that the pointer is of right type + CAknsAnimationItemData* skinData = static_cast( item ); //lint !e1774 dynamic_cast not allowed + + // Morphing animations are not for highlights + if( skinData->Morphing() ) + { + return EFalse; // Item was found, but we ignore morphing animations + } + + iMinimumInterval = skinData->MinInterval(); + + iInputLayerMode = skinData->InputLayerMode(); + iInputLayerIndex = skinData->InputLayer(); + iOutputLayerMode = skinData->OutputLayerMode(); + iOutputLayerIndex = skinData->OutputLayer(); + + CreateTimingModelsL( *skinData ); + CreateAnimationValueContainersL( *skinData ); + CreatePreprocessCommandsL( *skinData ); + CreateAnimationCommandsL( *skinData ); + CreateSizeBoundParamsL( *skinData ); + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::ConstructFromItemL +// Testing time functionality only. +// ----------------------------------------------------------------------------- +// +TBool CAknsAlAnimatorBmp::ConstructFromItemL( const CAknsAnimationItemData& aData, + RAknsSrvSession* aSession ) + { + // Morphing animations are not for highlights + if( aData.Morphing() ) + { + return EFalse; // Item was found, but we ignore morphing animations + } + + iContext->SetSkinSrvSession( aSession ); + + iMinimumInterval = aData.MinInterval(); + + iInputLayerMode = aData.InputLayerMode(); + iInputLayerIndex = aData.InputLayer(); + iOutputLayerMode = aData.OutputLayerMode(); + iOutputLayerIndex = aData.OutputLayer(); + + CreateTimingModelsL( aData ); + CreateAnimationValueContainersL( aData ); + CreatePreprocessCommandsL( aData ); + CreateAnimationCommandsL( aData ); + CreateSizeBoundParamsL( aData ); + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::BeginConfigLayersL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::BeginConfigLayersL( const TSize& aLayerSize, + TDisplayMode aRgbMode ) + { + if( RenderError() ) + User::Leave( iRenderError ); + + // Make sure we have a valid size + if( aLayerSize.iWidth < KAknsAlAnimMinimumWidth || + aLayerSize.iHeight < KAknsAlAnimMinimumHeight ) + User::Leave( KErrArgument ); + + // Configure + iContext->ConfigureL( aLayerSize, aRgbMode, + iInputLayerIndex, + iInputLayerMode ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::EndConfigLayersL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::EndConfigLayersL( TBool aAboutToStart ) + { + // Do the preprocessing step + PreprocessL(); + + // Because layer size may have changed and some layers may have been lost + // we need to restart the animation (while preserving its state). + TInt originalState = iState; + + if( EAknsAnimStateRunning == originalState ) + { + // Starting will also stop animation first + StartAnimationL( EFalse, ETrue ); + User::LeaveIfError( UpdateOutput() ); + } + else // Animation must be stopped, paused or finished + { + // Starting will also stop animation first + StartAnimationL( EFalse, EFalse ); + User::LeaveIfError( UpdateOutput() ); + iState = originalState; + + if( ( EAknsAnimStateStopped == originalState ) && !aAboutToStart ) + { + // Stopping releases input layers and plugins + StopAndRelease( ETrue, ETrue ); + } + } + + // Check if we need to restore idling + if( EAknsAnimStatePaused == iState && iIdling ) + { + // Restart the idle timer + if ( iTimer->IsActive() ) + { + iTimer->Cancel(); + } + iTimer->Start( 0, iIdlingInterval * 1000, TCallBack( TimerTimeoutCallback, this ) ); + } + + iSizeKnown = ETrue; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::StartAnimation +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::StartAnimation() + { + CancelIdling(); + + if( RenderError() ) + { + return iRenderError; + } + + TRAPD( err, StartAnimationL( ETrue, ETrue ) ); + if( err ) + { + StopAndRelease( ETrue, ETrue ); + return err; + } + + iState = EAknsAnimStateRunning; + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::StopAnimation +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::StopAnimation() + { + CancelIdling(); + + if( RenderError() ) + return iRenderError; + + if( EAknsAnimStatePaused == iState || + EAknsAnimStateRunning == iState || + EAknsAnimStateFinished == iState ) + { + // Stopping releases input layers and plugins + StopAndRelease( ETrue, ETrue ); + iState = EAknsAnimStateStopped; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::PauseAnimation +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::PauseAnimation() + { + CancelIdling(); + + if( RenderError() ) + return iRenderError; + + if( EAknsAnimStateRunning == iState ) + { + iTimer->Cancel(); + iState = EAknsAnimStatePaused; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::ContinueAnimationL +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::ContinueAnimation() + { + CancelIdling(); + + if( RenderError() ) + return iRenderError; + + if( EAknsAnimStatePaused == iState ) + { + iLastFrameTicks = User::TickCount(); + + if ( iTimer->IsActive() ) + { + iTimer->Cancel(); + } + iTimer->Start( 0, iMinimumInterval * 1000, TCallBack( TimerTimeoutCallback, this ) ); + iState = EAknsAnimStateRunning; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::State +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::State() const + { + return iState; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::OutputRgb +// ----------------------------------------------------------------------------- +// +CFbsBitmap* CAknsAlAnimatorBmp::OutputRgb() const + { + return iContext->RgbBitmap( iOutputLayerIndex ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::OutputAlpha +// ----------------------------------------------------------------------------- +// +CFbsBitmap* CAknsAlAnimatorBmp::OutputAlpha() const + { + return iContext->AlphaBitmap( iOutputLayerIndex ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::InputRgbGc +// ----------------------------------------------------------------------------- +// +CFbsBitGc* CAknsAlAnimatorBmp::InputRgbGc() const + { + return iContext->RgbGc( iInputLayerIndex ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::InputAlphaGc +// ----------------------------------------------------------------------------- +// +CFbsBitGc* CAknsAlAnimatorBmp::InputAlphaGc() const + { + return iContext->AlphaGc( iInputLayerIndex ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::UpdateOutput +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::UpdateOutput() + { + return Render( EFalse ); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::SetIdling +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::SetIdling( TInt aIntervalMs ) + { + if( EAknsAnimStateRunning == iState || iIdling ) + { + iTimer->Cancel(); + iIdling = ETrue; + iState = EAknsAnimStatePaused; + iIdlingInterval = aIntervalMs; + + if ( iTimer->IsActive() ) + { + iTimer->Cancel(); + } + iTimer->Start( 0, iIdlingInterval * 1000, TCallBack( TimerTimeoutCallback, this ) ); + } + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::IsIdling +// ----------------------------------------------------------------------------- +// +TBool CAknsAlAnimatorBmp::IsIdling() const + { + return iIdling; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CancelIdling +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CancelIdling() + { + if( iIdling ) + { + iTimer->Cancel(); + iIdling = EFalse; + } + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::LayerSize +// ----------------------------------------------------------------------------- +// +TSize CAknsAlAnimatorBmp::LayerSize() const + { + return iContext->LayerSize(); + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::NeedsInputLayer +// ----------------------------------------------------------------------------- +// +TBool CAknsAlAnimatorBmp::NeedsInputLayer() const + { + if( iInputLayerIndex >= 0 && + !iContext->RgbBitmap( iInputLayerIndex ) ) + { + return ETrue; + } + + // input layers created in preprocess step are needed too + for (TInt i = 0; i RgbBitmap( i ) ) + { + return ETrue; + } + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::RenderError +// ----------------------------------------------------------------------------- +// +TBool CAknsAlAnimatorBmp::RenderError() const + { + return (KErrNone != iRenderError) ? ETrue: EFalse; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::StartAnimationL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::StartAnimationL( TBool aReset, TBool aStartTimer ) + { + // Don't release input layers, do release plugins because we will activate + // them here. + StopAndRelease( EFalse, ETrue ); + + TInt i; + if( aReset ) + { + // Make sure animation models are at the beginning of the animation + for( i=0; i < iTimingModels.Count(); i++ ) + iTimingModels[i]->Begin(); + + // Make sure animation values are at the begining of the animation + for( i=0; i < iValueContainers.Count(); i++ ) + iValueContainers[i]->Begin(); + } + + // Resizing causes restart and initially we must apply size bound + // parameters too. + TInt count = iSizeBoundParams.Count(); + for( i=0; i < count; i++ ) + { + CAknsAlSizeBoundParam* param = iSizeBoundParams[i]; + param->SizeChangedL( iContext->LayerSize() ); + } + + // Activate and parametrize effect filters + count = iAnimationCommands.Count(); + for( i=0; i < count; i++ ) + { + // Activate effect + CAknsAlAnimationCommand* cmd = iAnimationCommands[i]; + MAknsRlEffect* effect = cmd->Effect(); + effect->InitializeL(); + effect->ActivateL( iContext ); + + // Parametrize effect + MAknsRlParameterIterator* iter = cmd->ParameterIterator(); + if( iter ) + { + effect->SetParametersL( *iter ); + } + } + + // Start timer + if( aStartTimer ) + { + iLastFrameTicks = User::TickCount(); + if ( iTimer->IsActive() ) + { + iTimer->Cancel(); + } + iTimer->Start( 0, iMinimumInterval * 1000, TCallBack( TimerTimeoutCallback, this ) ); + } + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::StopAndRelease +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::StopAndRelease( TBool aReleaseInputLayers, + TBool aReleasePlugins ) + { + // Stop timer + iTimer->Cancel(); + + // Release effect filters + if( aReleasePlugins ) + { + TInt count = iAnimationCommands.Count(); + for( TInt i=0; i < count; i++ ) + { + // Activate effects + CAknsAlAnimationCommand* cmd = iAnimationCommands[i]; + MAknsRlEffect* effect = cmd->Effect(); + effect->Deactivate(); + effect->Release(); + } + } + + // Release input layers, output layer is still available (even if the + // animation is stopped we must be able to draw the last frame). + if( aReleaseInputLayers ) + { + iContext->ReleaseInputLayers( iOutputLayerIndex ); + } + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::Tick +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::Tick() + { + if( RenderError() ) + return; + + if( iIdling && iObserver ) + { + iObserver->AnimFrameReady( KErrNone, 0 ); + return; + } + + TBool isFinished = EFalse; + TInt i; + + //--------------------------------- + // Check if the animation has been finished + TInt count = iTimingModels.Count(); + for( i=0; i < count; i++ ) + { + isFinished = isFinished | iTimingModels[i]->IsFinished(); + } + + if( isFinished ) + { + // No need to do rendering, animation became finished on the last tick + // -> last rendered frame is valid. Cancelling the timer is enough as + // we don't release input layers or plugins. + iTimer->Cancel(); + iState = EAknsAnimStateFinished; + return; + } + + //--------------------------------- + // Determine the delta time + TInt now = User::TickCount(); + TInt deltaTime = ( now - iLastFrameTicks ) * iMsPerTick; + iLastFrameTicks = now; + + // The range for delta time is (0, 65536]. It cannot be 0 and 65536 is the + // maximum limit caused by the fixed point calculations. + if( deltaTime <= 0 ) + deltaTime = 1; + if( deltaTime > KAlMaxDeltaTime ) + deltaTime = KAlMaxDeltaTime; + + //--------------------------------- + // Update timing models + count = iTimingModels.Count(); + for( i=0; i < count; i++ ) + { + iTimingModels[i]->Tick( deltaTime ); + } + + //--------------------------------- + // Step 2: Tick the animation + count = iValueContainers.Count(); + for( i=0; i < count; i++ ) + { + CAknsAlAnimationValueContainer* container = iValueContainers[i]; + container->Tick( deltaTime ); + } + + // Render the animation (skipped if layers are not ok) + if( iSizeKnown ) + { + TInt err = Render( ETrue ); + if( KErrNone != err ) + { + iRenderError = err; + } + } + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::Render +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::Render( TBool aNotify ) + { + // Cannot render when state is invalid + if( RenderError() ) + { + if( iObserver && aNotify ) + { + iObserver->AnimFrameReady( iRenderError, 0 ); + } + return iRenderError; + } + + // State is valid, we can try rendering + TInt err = ApplyCommands( iAnimationCommands, ETrue ); + + if( KErrNone != err ) + { +#if defined(_DEBUG) + RDebug::Printf("ANIM CAknsAlAnimatorBmp, ApplyCommands failed %d, stopping...", err); +#endif + StopAnimation(); // Failed animation cannot run + } + + // Inform observer about new frame + if( iObserver && aNotify ) + { + iObserver->AnimFrameReady( err, 0 ); + } + + return err; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::PreprocessL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::PreprocessL() + { + TInt i; + TInt count = iPreprocessCommands.Count(); + for( i=0; i < count; i++ ) + { + // Activate effect + CAknsAlAnimationCommand* cmd = iPreprocessCommands[i]; + MAknsRlEffect* effect = cmd->Effect(); + effect->InitializeL(); + effect->ActivateL( iContext ); + + // No untrapped leaves after this line before deactivation & release + + // Parametrize effect + MAknsRlParameterIterator* iter = cmd->ParameterIterator(); + if( iter ) + { + TRAPD( paramErr, effect->SetParametersL( *iter ) ); + if( paramErr ) + { + effect->Deactivate(); + effect->Release(); + AKNS_TRACE_ERROR1("CAknsAlAnimatorBmp::PreprocessL Bad params for effect %d", i); + User::Leave( paramErr ); + } + } + + TAknsRlRenderOpParam opParam = cmd->LayerConfig(); + + TAknsRlEffectCaps caps; + effect->GetCapabilities( caps ); + + TBool opPossible = ETrue; + if( !(caps.iInputLayerASupport&opParam.iInputLayerAStatus) ) + opPossible = EFalse; + if( !(caps.iInputLayerBSupport&opParam.iInputLayerBStatus) ) + opPossible = EFalse; + if( !(caps.iOutputLayerSupport&opParam.iOutputLayerStatus) ) + opPossible = EFalse; + if( opParam.iOutputLayerStatus == KAknsRlLayerNone ) + opPossible = EFalse; + + TInt effectRet = KErrArgument; + + if( opPossible ) + { + effectRet = KAknsRlRenderIncomplete; + while( effectRet == KAknsRlRenderIncomplete ) + { + effectRet = effect->Render( opParam ); + } + } +#if defined(_DEBUG) + else + { + AKNS_TRACE_ERROR1("CAknsAlAnimatorBmp::PreprocessL Effect not executed %d", i); + } +#endif + + // Deactivation, leaves are OK after this + effect->Deactivate(); + effect->Release(); + +#if defined(_DEBUG) + if( effectRet ) + { + AKNS_TRACE_ERROR2("CAknsAlAnimatorBmp::PreprocessL error %d for %d", effectRet, i); + } +#endif + + User::LeaveIfError( effectRet ); + } + + iPreprocessInputLayers = 0; + // we have to save input layers created in preprocess step + for (i = 0; i RgbBitmap( i ) ) + { + iPreprocessInputLayers |= 1 << i; + } + } + } +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::ApplyCommands +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::ApplyCommands( + RPointerArray& aCommands, + TBool aApplyNamedReferences ) const + { + TInt count = aCommands.Count(); + TAknsRlEffectCaps caps; + TBool opPossible = EFalse; + for( TInt i=0; i < count; i++ ) + { + CAknsAlAnimationCommand* cmd = aCommands[i]; + MAknsRlEffect* effect = cmd->Effect(); + + TAknsRlRenderOpParam opParam = cmd->LayerConfig(); + + effect->GetCapabilities( caps ); + + opPossible = ETrue; + + if( !(caps.iInputLayerASupport&opParam.iInputLayerAStatus) ) + opPossible = EFalse; + if( !(caps.iInputLayerBSupport&opParam.iInputLayerBStatus) ) + opPossible = EFalse; + if( !(caps.iOutputLayerSupport&opParam.iOutputLayerStatus) ) + opPossible = EFalse; + if( opParam.iOutputLayerStatus == KAknsRlLayerNone ) + opPossible = EFalse; + + TInt effectRet = KErrArgument; + + if( opPossible ) + { + if( aApplyNamedReferences ) + { + // Apply time bound parameters + MAknsRlParameterIterator* iter = cmd->NamedReferenceIterator(); + if( iter ) + { + TRAPD( paramErr, effect->SetParametersL( *iter ) ); + if( paramErr ) + return paramErr; + } + } + + // Render effect + effectRet = KAknsRlRenderIncomplete; + while( effectRet == KAknsRlRenderIncomplete ) + { + effectRet = effect->Render( opParam ); + } + } +#if defined(_DEBUG) + else + { + AKNS_TRACE_ERROR1("CAknsAlAnimatorBmp::ApplyCommands Effect not executed %d", i); + } +#endif + +#if defined(_DEBUG) + if( effectRet ) + { + AKNS_TRACE_ERROR2("CAknsAlAnimatorBmp::ApplyCommands error %d for %d", effectRet, i); + } +#endif + + if( KErrNone != effectRet ) + return effectRet; + } + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::FindTimingModelById +// ----------------------------------------------------------------------------- +// +MAknsAlTimingModel* CAknsAlAnimatorBmp::FindTimingModelById( TInt aId ) const + { + if( 0 <= aId && aId < iTimingModels.Count() ) + return iTimingModels[ aId ]; + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::FindContainerById +// ----------------------------------------------------------------------------- +// +CAknsAlAnimationValueContainer* CAknsAlAnimatorBmp::FindContainerById( TInt aId ) const + { + if( 0 <= aId && aId < iValueContainers.Count() ) + return iValueContainers[ aId ]; + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CreateTimingModelsL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CreateTimingModelsL( + const CAknsAnimationItemData& aSkinData ) + { + MAknsAlIterator* iter = aSkinData.TimingModelIteratorL(); + CleanupStack::PushL( TCleanupItem( MAknsAlIterator::CleanupOp, iter ) ); + + while( iter->HasNext() ) + { + const TAknsAlTimingModelData* item = + static_cast( iter->NextL() ); + MAknsAlTimingModel* model = + AknsAlAnimationFactory::CreateTimingModelL( item->iTimingModelUid ); + if( !model ) + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PushL( TCleanupItem( MAknsAlTimingModel::CleanupOp, model ) ); + + if( item->iParamIterator ) + model->SetParametersL( *item->iParamIterator ); + + User::LeaveIfError( iTimingModels.Append( model ) ); + + CleanupStack::Pop(); // Model + } + + CleanupStack::PopAndDestroy(); // iter + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CreateAnimationValueContainersL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CreateAnimationValueContainersL( + const CAknsAnimationItemData& aSkinData ) + { + MAknsAlIterator* iter = aSkinData.AnimationValueIteratorL(); + CleanupStack::PushL( TCleanupItem( MAknsAlIterator::CleanupOp, iter ) ); + + while( iter->HasNext() ) + { + const TAknsAlAnimationValueData* data = + static_cast( iter->NextL() ); + + // Create animation value + MAknsAlAnimationValue* value = + AknsAlAnimationFactory::CreateAnimationValueL( data->iAnimationValueUid ); + if( !value ) + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PushL( TCleanupItem( MAknsAlAnimationValue::CleanupOp, value ) ); + + if( data->iParamIterator ) + value->SetParametersL( *data->iParamIterator ); + + // Fetch timing model + MAknsAlTimingModel* timing = FindTimingModelById( data->iTimingModelId ); + if( !timing ) + User::Leave( KErrNotFound ); + + // Create the container + CAknsAlAnimationValueContainer* container = + CAknsAlAnimationValueContainer::NewL( value, timing ); + + CleanupStack::Pop( value ); // Animation value is now owned by container + + CleanupStack::PushL( container ); + User::LeaveIfError( iValueContainers.Append( container ) ); + CleanupStack::Pop( container ); + } + + CleanupStack::PopAndDestroy(); // iter + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CreatePreprocessCommandsL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CreatePreprocessCommandsL( + const CAknsAnimationItemData& aSkinData ) + { + MAknsRlCommandIterator* iter = aSkinData.PreprocessCommandIteratorL(); + CleanupStack::PushL( TCleanupItem( MAknsRlCommandIterator::CleanupOperation, iter ) ); + + while( iter->HasNext() ) + { + const TAknsRlCommandData* data = iter->NextL(); + CAknsAlAnimationCommand* command = CAknsAlAnimationCommand::NewL(); + CleanupStack::PushL( command ); + + // Step 1: Create the plugin + CAknsRlEffectPlugin* plugin = + AknsAlAnimationFactory::CreateEffectPluginL( data->iEffectUid ); + if( !plugin ) + { + User::Leave( KErrNotFound ); + } + + command->SetPlugin( plugin ); + + // Step 2: Assign layer configuration + command->SetLayerConfig( data->iLayerConf ); + + // Step 3: Add initial parameters + if( data->iParamIterator ) + { + MAknsRlParameterIterator* paramIter = data->iParamIterator; + while( paramIter->HasNext() ) + { + const TAknsRlParameterData* param = paramIter->NextL(); + command->AddParameterL( *param ); + } + } + + // Preprocess commands don't have named references + User::LeaveIfError( iPreprocessCommands.Append( command ) ); + CleanupStack::Pop( command ); + } + + CleanupStack::PopAndDestroy(); // iter + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CreateAnimationCommandsL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CreateAnimationCommandsL( + const CAknsAnimationItemData& aSkinData ) + { + MAknsAlIterator* iter = aSkinData.CommandIteratorL(); + CleanupStack::PushL( TCleanupItem( MAknsAlIterator::CleanupOp, iter ) ); + + while( iter->HasNext() ) + { + const TAknsAlAnimationCommandData* data = + static_cast( iter->NextL() ); + + CAknsAlAnimationCommand* command = CAknsAlAnimationCommand::NewL(); + CleanupStack::PushL( command ); + + // Step 1: Create the plugin + CAknsRlEffectPlugin* plugin = + AknsAlAnimationFactory::CreateEffectPluginL( data->iEffectUid ); + if( !plugin ) + { + User::Leave( KErrNotFound ); + } + command->SetPlugin( plugin ); + + // Step 2: Assign layer configuration + command->SetLayerConfig( data->iLayerConf ); + + // Step 3: Add initial parameters + if( data->iParamIterator ) + { + MAknsRlParameterIterator* paramIter = data->iParamIterator; + while( paramIter->HasNext() ) + { + const TAknsRlParameterData* param = paramIter->NextL(); + command->AddParameterL( *param ); + } + } + + // Step 4: Add named references + if( data->iNamedReferenceIterator ) + { + MAknsAlIterator* refIter = data->iNamedReferenceIterator; + while( refIter->HasNext() ) + { + const TAknsAlNamedReferenceData* ref = + static_cast( refIter->NextL() ); + + CAknsAlAnimationValueContainer* container = FindContainerById( ref->iAnimationValueId ); + if( !container ) + User::Leave( KErrNotFound ); + + command->AddNamedReferenceL( *ref->iName, + container->AnimationValue() ); + } + } + + User::LeaveIfError( iAnimationCommands.Append( command ) ); + CleanupStack::Pop( command ); + } + + CleanupStack::PopAndDestroy(); // iter + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::CreateSizeBoundParamsL +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::CreateSizeBoundParamsL( + const CAknsAnimationItemData& aSkinData ) + { + MAknsAlIterator* iter = aSkinData.SizeBoundParamIteratorL(); + CleanupStack::PushL( TCleanupItem( MAknsAlIterator::CleanupOp, iter ) ); + + while( iter->HasNext() ) + { + const TAknsAlSizeBoundParameterData* data = + static_cast( iter->NextL() ); + + if( !data->iName ) + User::Leave( KErrBadHandle ); + + CAknsAlAnimationValueContainer* container = FindContainerById( data->iAnimationValueId ); + if( !container ) + User::Leave( KErrNotFound ); + + CAknsAlSizeBoundParam* param = + CAknsAlSizeBoundParam::NewL( container->AnimationValue(), + *data->iName, + data->iParamFlags ); + + CleanupStack::PushL( param ); + User::LeaveIfError( iSizeBoundParams.Append( param ) ); + CleanupStack::Pop( param ); + } + + CleanupStack::PopAndDestroy(); // iter + } + +// ----------------------------------------------------------------------------- +// CAknsAlAnimatorBmp::TimerTimeoutCallback +// ----------------------------------------------------------------------------- +// +TInt CAknsAlAnimatorBmp::TimerTimeoutCallback(TAny *aPtr) + { + CAknsAlAnimatorBmp* render = reinterpret_cast( aPtr ); + render->Tick(); + + return ETrue; // Continue running + } + +// ----------------------------------------------------------------------------- +// Callback interface for lights status. +// ----------------------------------------------------------------------------- +// +void CAknsAlAnimatorBmp::LightStatusChanged( TInt aTarget, + CHWRMLight::TLightStatus aStatus ) + { + if ( aTarget == CHWRMLight::EPrimaryDisplay || + aTarget == CHWRMLight::EPrimaryDisplayAndKeyboard ) + { + if ( aStatus == CHWRMLight::ELightOff ) + { + PauseAnimation(); // don't care about errors in here + } + else if ( aStatus == CHWRMLight::ELightOn ) + { + ContinueAnimation(); + } + } + } + +// End of File