--- /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 <aknlayoutfont.h>
+#include <aknutils.h>
+#include <bitmaptransforms.h>
+#include <coemain.h>
+#include <gulicon.h>
+#include <ihlbitmaputil.h>
+#include <imageconversion.h>
+#include <svgengineinterfaceimpl.h>
+
+
+#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<KMaxDataTypeLength> 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<const TGifImageControl*>
+ ( 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<CIRImageConverterImpl*>( 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<TInt>( 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<CIRImageConverterImpl*>( aSelf );
+ if ( self )
+ {
+ self->iFrameTimer->Cancel();
+ TRAPD( err, self->RenderBitmapAnimationFrameL() )
+ if ( err )
+ {
+ self->NotifyObserver( err );
+ }
+ }
+ return KErrNone;
+ }