diff -r 000000000000 -r 09774dfdd46b internetradio2.0/uicontrolssrc/irimageconverterimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/internetradio2.0/uicontrolssrc/irimageconverterimpl.cpp Mon Apr 19 14:01:53 2010 +0300 @@ -0,0 +1,801 @@ +/* +* Copyright (c) 2008-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: Internal image converter implementation +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "irimageconverterimpl.h" +#include "irimageconverterobserver.h" +#include "irdebug.h" +// Image decoder options. +const CImageDecoder::TOptions KIRImageDecoderOptions = CImageDecoder::EOptionAlwaysThread; +// Bitmap scaler quality. +const CBitmapScaler::TQualityAlgorithm KIRBitmapScalerQualityAlgorithm = + CBitmapScaler::EMaximumQuality; +const TInt KFour=4; +// --------------------------------------------------------------------------- +// @see CIRImageConverter::NewL() +// --------------------------------------------------------------------------- +// +CIRImageConverterImpl* CIRImageConverterImpl::NewL() + { + IRLOG_DEBUG( "CIRImageConverterImpl::NewL - Entering" ); + CIRImageConverterImpl* self = new ( ELeave ) CIRImageConverterImpl; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CIRImageConverterImpl::CIRImageConverterImpl() + : CActive( CActive::EPriorityStandard ), + iEnableAnimations( ETrue ), + iMaintainAspectRatio( ETrue ) + { + CActiveScheduler::Add( this ); + } + +// --------------------------------------------------------------------------- +// Second-phase constructor. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::ConstructL() + { + IRLOG_DEBUG( "CIRImageConverterImpl::ConstructL - entering" ); + iNotifyObserverCallBack = new ( ELeave ) CAsyncCallBack( + TCallBack( StaticNotifyObserverCallBack, this ), CActive::EPriorityHigh ); + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::~CIRImageConverter() +// --------------------------------------------------------------------------- +// +CIRImageConverterImpl::~CIRImageConverterImpl() + { + Cancel(); + + iFrames.ResetAndDestroy(); + iFrames.Close(); + + delete iDecoder; + delete iScaler; + delete iSvgEngine; + delete iProcessedBitmap; + delete iProcessedMask; + delete iBitmap; + delete iMask; + delete iLastFrameBitmap; + delete iLastFrameMask; + delete iNotifyObserverCallBack; + delete iFrameTimer; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::SetDataL( const TDesC8& aData ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::SetDataL( const TDesC8& aData ) + { + IRRDEBUG2( "CIRImageConverterImpl::SetDataL - Entering", KNullDesC ); + Cleanup( ETrue ); + iData.Set( aData ); + CreateDataHandlerL(); + IRRDEBUG2( "CIRImageConverterImpl::SetDataL - Exiting", KNullDesC ); + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::SetObserver( MIRImageConverterObserver* aObserver ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::SetObserver( MIRImageConverterObserver* aObserver ) + { + iObserver = aObserver; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::EnableAnimations( TBool aEnable ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::EnableAnimations( TBool aEnable ) + { + __ASSERT_DEBUG( iState == EIRStateIdle, User::Invariant() ); + iEnableAnimations = aEnable; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::IsAnimated() const +// --------------------------------------------------------------------------- +// +TBool CIRImageConverterImpl::IsAnimated() const + { + __ASSERT_DEBUG( iState != EIRStateIdle, User::Invariant() ); + return iIsAnimated; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::MaintainAspectRatio( TBool aMaintain ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::MaintainAspectRatio( TBool aMaintain ) + { + __ASSERT_DEBUG( iState == EIRStateIdle, User::Invariant() ); + iMaintainAspectRatio = aMaintain; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::StartL( const TSize& aTarget, TInt aId ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::StartL( const TSize& aTarget, TInt aId ) + { + IRRDEBUG2( "CIRImageConverterImpl::StartL - Entering", KNullDesC ); + if ( iState != EIRStateBitmapDecoderInitialized && iState != EIRStateSvgEngineInitialized ) + { + if ( iState == EIRStateIdle ) + { + IRRDEBUG2("CIRImageConverterImpl::StartL, leave with KErrNotReady", KNullDesC); + User::Leave( KErrNotReady ); + } + else + { + IRRDEBUG2("CIRImageConverterImpl::StartL, leave with KErrInUse", KNullDesC); + User::Leave( KErrInUse ); + } + } + iTargetSize = aTarget; + iId = aId; + if ( iState == EIRStateSvgEngineInitialized ) + { + // The SVG-T engine has been initialized with dummy 0x0 bitmaps, so updating those must be handled here. + IRRDEBUG2( "CIRImageConverterImpl::StartL - if begin", KNullDesC ); + CreateBitmapL( iTargetSize, iBitmap, iMask ); + iSvgEngine->SetFrameBuffer( iBitmap ); + iState = EIRStateConvertingSvg; + iSvgEngine->Start(); + IRRDEBUG2( "CIRImageConverterImpl::StartL - if end", KNullDesC ); + } + else + { + IRRDEBUG2( "CIRImageConverterImpl::StartL - else begin", KNullDesC ); + iState = EIRStateConvertingBitmap; + IRRDEBUG2( "CIRImageConverterImpl::StartL, iDecorder = %d", iDecoder); + iDecoder->Convert( &iStatus, *iBitmap, *iMask ); + IRRDEBUG2( "CIRImageConverterImpl::StartL - else-exit call setactive", KNullDesC ); + SetActive(); + } + IRRDEBUG2( "CIRImageConverterImpl::StartL - Exiting", KNullDesC ); + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::Stop() +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::Stop() + { + IRRDEBUG2( "CIRImageConverterImpl::Stop - Entering", KNullDesC ); + Cancel(); + if ( iSvgEngine ) + { + iSvgEngine->Stop(); + } + TIRImageConverterState state = iState; + Cleanup(); + if ( state != EIRStateIdle && state != EIRStateBitmapDecoderInitialized && + state != EIRStateSvgEngineInitialized ) + { + NotifyObserver( KErrCancel ); + } + IRRDEBUG2( "CIRImageConverterImpl::Stop - Exiting",KNullDesC ); + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::Bitmap() const +// --------------------------------------------------------------------------- +// +const CFbsBitmap* CIRImageConverterImpl::Bitmap() const + { + IRLOG_DEBUG( "CIRImageConverterImpl::Bitmap - Entering" ); + return iProcessedBitmap; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::Mask() const +// --------------------------------------------------------------------------- +// +const CFbsBitmap* CIRImageConverterImpl::Mask() const + { + IRLOG_DEBUG( "CIRImageConverterImpl::Mask - Entering" ); + return iProcessedMask; + } + +// --------------------------------------------------------------------------- +// @see CIRImageConverter::TransferBitmapOwnership( CFbsBitmap*& aBitmap, CFbsBitmap*& aMask ) +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::TransferBitmapOwnership( CFbsBitmap*& aBitmap, CFbsBitmap*& aMask ) + { + aBitmap = iProcessedBitmap; + iProcessedBitmap = NULL; + aMask = iProcessedMask; + iProcessedMask = NULL; + } + +// --------------------------------------------------------------------------- +// From class CActive. +// Invoked when the active object is cancelled. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::DoCancel() + { + IRLOG_DEBUG( "CIRImageConverterImpl::DoCancel - Entering" ); + if ( iDecoder ) + { + iDecoder->Cancel(); + } + if ( iScaler ) + { + iScaler->Cancel(); + } + IRLOG_DEBUG( "CIRImageConverterImpl::DoCancel - Exiting" ); + } + +// --------------------------------------------------------------------------- +// From class CActive. +// Invoked when the active object completes an asynchronous request. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::RunL() + { + IRLOG_DEBUG( "CIRImageConverterImpl::RunL - Entering" ); + if ( iStatus.Int() == KErrNone ) + { + switch ( iState ) + { + case EIRStateConvertingBitmap: + { + if ( iIsAnimated && iEnableAnimations ) + { + CGulIcon* icon = CGulIcon::NewLC(); + + icon->SetBitmapsOwnedExternally( EFalse ); + icon->SetBitmap( iBitmap ); + icon->SetMask( iMask ); + + iBitmap = NULL; + iMask = NULL; + + iFrames.AppendL( icon ); + CleanupStack::Pop( icon ); + + if ( iFrames.Count() < iDecoder->FrameCount() ) + { + CreateBitmapL( iDecoder->FrameInfo( iFrames.Count() ).iOverallSizeInPixels, + iBitmap, iMask ); + + iDecoder->Convert( &iStatus, *iBitmap, *iMask, iFrames.Count() ); + SetActive(); + } + else + { + StartBitmapAnimationL(); + } + } + else + { + iState = EIRStateScalingBitmap; + iScaler->Scale( &iStatus, *iBitmap, iTargetSize, iMaintainAspectRatio ); + SetActive(); + } + } + break; + case EIRStateScalingBitmap: + iState = EIRStateScalingBitmapMask; + iScaler->Scale( &iStatus, *iMask, iTargetSize, iMaintainAspectRatio ); + SetActive(); + break; + case EIRStateScalingBitmapMask: + NotifyObserver( KErrNone ); + break; + default: + break; + } + } + else + { + NotifyObserver( iStatus.Int() ); + } + IRLOG_DEBUG( "CIRImageConverterImpl::RunL - Exiting" ); + } + +// --------------------------------------------------------------------------- +// From class CActive. +// Invoked when RunL leaves. +// --------------------------------------------------------------------------- +// +TInt CIRImageConverterImpl::RunError( TInt aError ) + { + IRLOG_DEBUG( "CIRImageConverterImpl::NewL - Entering" ); + NotifyObserver( aError ); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// From class MSvgRequestObserver. +// Invoked when the bitmap has been updated by the SVG-T engine. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::UpdateScreen() + { + iSvgEngine->GenerateMask( iMask ); + // SVG-T engine MUST NOT be destroyed here as its internal implementation + // relies on it existing after execution leaves this method. This means + // that the observer notification must be asynchronous + NotifyObserver( KErrNone, EFalse ); + } + +// --------------------------------------------------------------------------- +// From class MSvgRequestObserver. +// Not implemented. +// --------------------------------------------------------------------------- +// +TBool CIRImageConverterImpl::ScriptCall( const TDesC& /*aScript*/, CSvgElementImpl* + /*aCallerElement*/ ) + { + return EFalse; + } + +// --------------------------------------------------------------------------- +// From class MSvgRequestObserver. +// Not implemented. +// --------------------------------------------------------------------------- +// +TInt CIRImageConverterImpl::FetchImage( const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& + /*aFileHandle*/ ) + { + return KErrNone; + } + +// --------------------------------------------------------------------------- +// From class MSvgRequestObserver. +// Not implemented. +// --------------------------------------------------------------------------- +// +TInt CIRImageConverterImpl::FetchFont( const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& + /*aFileHandle*/ ) + { + return KErrNone; + } + +// --------------------------------------------------------------------------- +// From class MSvgRequestObserver. +// Not implemented. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::UpdatePresentation( const TInt32& /*aNoOfAnimation*/ ) + { + } + +// --------------------------------------------------------------------------- +// Performs cleanup on the converter object. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::Cleanup( TBool aThorough ) + { + Cancel(); + if ( aThorough ) + { + delete iProcessedBitmap; + iProcessedBitmap = NULL; + + delete iProcessedMask; + iProcessedMask = NULL; + } + if(iDecoder) + { + delete iDecoder; + iDecoder = NULL; + } + if(iScaler) + { + delete iScaler; + iScaler = NULL; + } + + if(iSvgEngine) + { + delete iSvgEngine; + iSvgEngine = NULL; + } + if(iFrameTimer) + { + delete iFrameTimer; + iFrameTimer = NULL; + } + if(iBitmap) + { + delete iBitmap; + iBitmap = NULL; + } + if(iMask) + { + delete iMask; + iMask = NULL; + } + if(iLastFrameBitmap) + { + delete iLastFrameBitmap; + iLastFrameBitmap = NULL; + } + if(iLastFrameMask) + { + delete iLastFrameMask; + iLastFrameMask = NULL; + } + + iFrames.ResetAndDestroy(); + + iNotifyObserverCallBack->Cancel(); + + iFrameIndex = 0; + iIsAnimated = EFalse; + iError = KErrNone; + iState = EIRStateIdle; + } + +// --------------------------------------------------------------------------- +// Creates the proper handler for the raw image data. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::CreateDataHandlerL() + { + IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL - Entering", KNullDesC ); + TBuf8 mimeType; + TRAPD( err, CImageDecoder::GetMimeTypeDataL( iData, mimeType ) ) + + if ( err == KErrNone ) // Image decoder can handle this MIME type. + { + + TRAPD(err1,iDecoder = CImageDecoder::DataNewL( CCoeEnv::Static()->FsSession(), iData, + KIRImageDecoderOptions );) + if(err1!=KErrNone) + { + if ( iObserver ) + { + IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL, err = %d", err1); + NotifyObserver( err1 ); + IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL, error is notified", KNullDesC); + } + } + else + { + iScaler = CBitmapScaler::NewL(); + iScaler->SetQualityAlgorithm( KIRBitmapScalerQualityAlgorithm ); + iScaler->UseLowMemoryAlgorithm( ETrue ); // Return value ignored on purpose; it's ok if low memory algorithm cannot be used when scaling. + + if ( iDecoder->FrameCount() > 1 ) + { + iFrameTimer = CPeriodic::NewL( CActive::EPriorityStandard ); + iIsAnimated = ETrue; + } + + CreateBitmapL( iDecoder->FrameInfo().iOverallSizeInPixels, iBitmap, iMask ); + } + } + else // Try using the SVG-T engine for decoding the image. + { + + TFontSpec fontSpec = AknLayoutUtils::LayoutFontFromId( + EAknLogicalFontSecondaryFont )->FontSpecInTwips(); + + // The SVG-T engine requires that the bitmap is created prior to its instantiation. + // As the dummy bitmaps created here are 0x0, StartL must take care of instantiating them to + // proper sizes and updating the SVG-T engine's frame buffer manually before starting the conversion. + + CreateBitmapL( TSize( 0, 0 ), iBitmap, iMask ); + + iSvgEngine = CSvgEngineInterfaceImpl::NewL( iBitmap, this, fontSpec ); + MSvgError* svgErr = iSvgEngine->Load( iData ); + if ( svgErr && svgErr->HasError() ) + { + err = svgErr->SystemErrorCode(); + } + else + { + err = KErrNone; + iIsAnimated = iSvgEngine->SvgHasAnimation( iSvgEngine->SvgDocument() ); + } + } + + if ( err ) + { + Cleanup( ETrue ); + User::Leave( KErrNotSupported ); + } + else + { + iState = iSvgEngine ? EIRStateSvgEngineInitialized : EIRStateBitmapDecoderInitialized; + } + + IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL - Exiting" , KNullDesC); + } + +// --------------------------------------------------------------------------- +// Creates new bitmaps of the given size. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::CreateBitmapL( const TSize& aSize, CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask ) + { + IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapL - Entering" ); + CFbsBitmap* bitmap = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( bitmap ); + User::LeaveIfError( bitmap->Create( aSize, CCoeEnv::Static()->ScreenDevice() + ->DisplayMode() ) ); + + CFbsBitmap* mask = new ( ELeave ) CFbsBitmap; + CleanupStack::PushL( mask ); + User::LeaveIfError( mask->Create( aSize, EGray256 ) ); + + delete aBitmap; + aBitmap = bitmap; + + delete aMask; + aMask = mask; + + CleanupStack::Pop( 2, bitmap ); + IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapL - Exiting" ); + } + +// --------------------------------------------------------------------------- +// Creates exact copies of the supplied bitmaps. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::CreateBitmapCopyL( const CFbsBitmap& aSourceBitmap, + const CFbsBitmap& aSourceMask, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask ) + { + IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapCopyL - Entering" ); + CFbsBitmap* bitmap = IHLBitmapUtil::CopyBitmapLC( aSourceBitmap ); + CFbsBitmap* mask = IHLBitmapUtil::CopyBitmapLC( aSourceMask ); + + delete aBitmap; + aBitmap = bitmap; + + delete aMask; + aMask = mask; + + CleanupStack::Pop( 2, bitmap ); + IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapCopyL - Exiting" ); + } + +// --------------------------------------------------------------------------- +// Starts the bitmap animation. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::StartBitmapAnimationL() + { + __ASSERT_DEBUG( iFrames.Count() == iDecoder->FrameCount(), User::Invariant() ); + + RenderBitmapAnimationFrameL( ETrue ); + } + +// --------------------------------------------------------------------------- +// Renders the current bitmap animation frame. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::RenderBitmapAnimationFrameL( TBool aFirstTime ) + { + IRLOG_DEBUG( "CIRImageConverterImpl::RenderBitmapAnimationFrameL - Entering" ); + __ASSERT_DEBUG( iFrames.Count() && iFrames.Count() > iFrameIndex, User::Invariant() ); + + + const TGifImageControl* gifImageControl = static_cast + ( iDecoder->FrameData( iFrameIndex ).GetFrameData( 0 ) ); + if ( gifImageControl ) + { + if ( aFirstTime ) + { + // When rendering the animation for the very first time, we just make a copy of the first frame. + CreateBitmapCopyL( *iFrames[0]->Bitmap(), *iFrames[0]->Mask(), + iLastFrameBitmap, iLastFrameMask ); + } + else + { + CFbsBitmapDevice* lastFrameBitmapDevice = CFbsBitmapDevice::NewL( iLastFrameBitmap ); + CleanupStack::PushL( lastFrameBitmapDevice ); + CFbsBitGc* lastFrameBitmapGc = CFbsBitGc::NewL(); + CleanupStack::PushL( lastFrameBitmapGc ); + lastFrameBitmapGc->Activate( lastFrameBitmapDevice ); + + CFbsBitmapDevice* lastFrameMaskDevice = CFbsBitmapDevice::NewL( iLastFrameMask ); + CleanupStack::PushL( lastFrameMaskDevice ); + CFbsBitGc* lastFrameMaskGc = CFbsBitGc::NewL(); + CleanupStack::PushL( lastFrameMaskGc ); + lastFrameMaskGc->Activate( lastFrameMaskDevice ); + + TRect rect = iDecoder->FrameInfo( iFrameIndex ).iFrameCoordsInPixels; + + + switch ( gifImageControl->iDisposalMethod ) + { + case TGifImageControl::ENone: + // The new frame is completely self-sufficient, so no information about the previous frame is required. + lastFrameBitmapGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Bitmap(), + TRect( TPoint(), rect.Size() ) ); + lastFrameMaskGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Mask(), + TRect( TPoint(), rect.Size() ) ); + break; + case TGifImageControl::ELeaveInPlace: + // The new frame only contains a partial update on the image, so we have to retain the previous frame state. + lastFrameBitmapGc->BitBltMasked( rect.iTl, iFrames[iFrameIndex]->Bitmap(), + TRect( TPoint(), rect.Size() ), + iFrames[iFrameIndex]->Mask(), EFalse ); + break; + case TGifImageControl::ERestoreToBackground: + // The new frame is restored to the background color defined in its data. + lastFrameBitmapGc->SetBrushColor( + iDecoder->FrameInfo( iFrameIndex ).iBackgroundColor ); + lastFrameBitmapGc->Clear(); + lastFrameMaskGc->SetBrushColor( KRgbBlack ); + lastFrameMaskGc->Clear(); + lastFrameBitmapGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Bitmap(), + TRect( TPoint(), rect.Size() ) ); + lastFrameMaskGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Mask(), + TRect( TPoint(), rect.Size() ) ); + break; + case TGifImageControl::ERestoreToPrevious: + // The new frame is exactly the same as the previous one, so no special processing is required. + break; + default: + break; + } + + CleanupStack::PopAndDestroy( KFour, lastFrameBitmapDevice ); + } + + CreateBitmapCopyL( *iLastFrameBitmap, *iLastFrameMask, iBitmap, iMask ); + } + else + { + User::Leave( KErrNotReady ); + } + + iState = EIRStateScalingBitmap; + iScaler->Scale( &iStatus, *iBitmap, iTargetSize, iMaintainAspectRatio ); + SetActive(); + IRLOG_DEBUG( "CIRImageConverterImpl::RenderBitmapAnimationFrameL - Exiting" ); + } + +// --------------------------------------------------------------------------- +// Notifies the observer either synchronously or asynchronously. +// --------------------------------------------------------------------------- +// +void CIRImageConverterImpl::NotifyObserver( TInt aError, TBool aSynchronous ) + { + IRRDEBUG2( "CIRImageConverterImpl::NotifyObserver - Entering, aError = %d", aError ); + iError = aError; + iNotifyObserverCallBack->Cancel(); + + if ( aSynchronous ) + { + StaticNotifyObserverCallBack( this ); + } + else + { + iNotifyObserverCallBack->CallBack(); + } + IRRDEBUG2( "CIRImageConverterImpl::NotifyObserver - Exiting", KNullDesC ); + } + +// --------------------------------------------------------------------------- +// Call back for notifying the observer. +// --------------------------------------------------------------------------- +// +TInt CIRImageConverterImpl::StaticNotifyObserverCallBack( TAny* aSelf ) + { + IRLOG_DEBUG( "CIRImageConverterImpl::StaticNotifyObserverCallBack - Entering" ); + CIRImageConverterImpl* self = static_cast( aSelf ); + if ( self ) + { + TInt err = self->iError; + MIRImageConverterObserver::TIRImageConversionEvent event = MIRImageConverterObserver:: + EIRImageConversionCompleted; + + if ( err == KErrNone ) + { + if ( self->iSvgEngine && self->iIsAnimated && self->iEnableAnimations ) + { + TRAP( err, self->CreateBitmapCopyL( *self->iBitmap, *self->iMask, + self->iProcessedBitmap, self->iProcessedMask ) ) + } + else + { + delete self->iProcessedBitmap; + self->iProcessedBitmap = self->iBitmap; + self->iBitmap = NULL; + delete self->iProcessedMask; + self->iProcessedMask = self->iMask; + self->iMask = NULL; + } + + if ( !err && self->iIsAnimated && self->iEnableAnimations ) + { + event = MIRImageConverterObserver::EIRFrameConversionCompleted; + + if ( self->iDecoder ) + { + self->iState = EIRStateBetweenBitmapAnimationFrames; + + self->iFrameTimer->Cancel(); + self->iFrameTimer->Start( static_cast( self->iDecoder-> + FrameInfo( self->iFrameIndex ).iDelay.Int64() ), 0, + TCallBack( StaticNextFrameCallBack, self ) ); + + self->iFrameIndex++; + if ( self->iFrameIndex >= self->iDecoder->FrameCount() ) + { + self->iFrameIndex = 0; + } + } + } + } + + if ( err || event == MIRImageConverterObserver::EIRImageConversionCompleted ) + { + self->Cleanup(); + } + + if ( self->iObserver ) + { + TRAP_IGNORE( self->iObserver->HandleImageConversionEventL( event, self->iId, err ) ) + } + } + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Call back for advancing to the next frame when bitmap animations are used. +// --------------------------------------------------------------------------- +// +TInt CIRImageConverterImpl::StaticNextFrameCallBack( TAny* aSelf ) + { + CIRImageConverterImpl* self = static_cast( aSelf ); + if ( self ) + { + self->iFrameTimer->Cancel(); + TRAPD( err, self->RenderBitmapAnimationFrameL() ) + if ( err ) + { + self->NotifyObserver( err ); + } + } + return KErrNone; + }