internetradio2.0/uicontrolssrc/irimageconverterimpl.cpp
changeset 14 896e9dbc5f19
parent 12 608f67c22514
child 15 065198191975
equal deleted inserted replaced
12:608f67c22514 14:896e9dbc5f19
     1 /*
       
     2 * Copyright (c) 2008-2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Internal image converter implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <aknlayoutfont.h>
       
    20 #include <aknutils.h>
       
    21 #include <bitmaptransforms.h>
       
    22 #include <coemain.h>
       
    23 #include <gulicon.h>
       
    24 #include <ihlbitmaputil.h>
       
    25 #include <imageconversion.h>
       
    26 #include <svgengineinterfaceimpl.h>
       
    27 
       
    28 
       
    29 #include "irimageconverterimpl.h"
       
    30 #include "irimageconverterobserver.h"
       
    31 #include "irdebug.h"
       
    32 // Image decoder options.
       
    33 const CImageDecoder::TOptions KIRImageDecoderOptions = CImageDecoder::EOptionAlwaysThread;
       
    34 // Bitmap scaler quality.
       
    35 const CBitmapScaler::TQualityAlgorithm KIRBitmapScalerQualityAlgorithm = 
       
    36 											CBitmapScaler::EMaximumQuality;
       
    37 const TInt KFour=4;
       
    38 // ---------------------------------------------------------------------------
       
    39 // @see CIRImageConverter::NewL()
       
    40 // ---------------------------------------------------------------------------
       
    41 //
       
    42 CIRImageConverterImpl* CIRImageConverterImpl::NewL()
       
    43     {
       
    44 	IRLOG_DEBUG( "CIRImageConverterImpl::NewL - Entering" );
       
    45     CIRImageConverterImpl* self = new ( ELeave ) CIRImageConverterImpl;
       
    46     CleanupStack::PushL( self );
       
    47     self->ConstructL();
       
    48     CleanupStack::Pop( self );
       
    49     return self;
       
    50     }
       
    51 
       
    52 // ---------------------------------------------------------------------------
       
    53 // Constructor.
       
    54 // ---------------------------------------------------------------------------
       
    55 //
       
    56 CIRImageConverterImpl::CIRImageConverterImpl()
       
    57     : CActive( CActive::EPriorityStandard ),
       
    58       iEnableAnimations( ETrue ),
       
    59       iMaintainAspectRatio( ETrue )
       
    60     {
       
    61     CActiveScheduler::Add( this );
       
    62     }
       
    63 
       
    64 // ---------------------------------------------------------------------------
       
    65 // Second-phase constructor.
       
    66 // ---------------------------------------------------------------------------
       
    67 //
       
    68 void CIRImageConverterImpl::ConstructL()
       
    69     {
       
    70 	IRLOG_DEBUG( "CIRImageConverterImpl::ConstructL - entering" );
       
    71     iNotifyObserverCallBack = new ( ELeave ) CAsyncCallBack( 
       
    72         TCallBack( StaticNotifyObserverCallBack, this ), CActive::EPriorityHigh );
       
    73     }
       
    74 
       
    75 // ---------------------------------------------------------------------------
       
    76 // @see CIRImageConverter::~CIRImageConverter()
       
    77 // ---------------------------------------------------------------------------
       
    78 //
       
    79 CIRImageConverterImpl::~CIRImageConverterImpl()
       
    80     {
       
    81     Cancel();
       
    82 
       
    83     iFrames.ResetAndDestroy();
       
    84     iFrames.Close();
       
    85     
       
    86     delete iDecoder;
       
    87     delete iScaler;
       
    88     delete iSvgEngine;
       
    89     delete iProcessedBitmap;
       
    90     delete iProcessedMask;
       
    91     delete iBitmap;
       
    92     delete iMask;
       
    93     delete iLastFrameBitmap;
       
    94     delete iLastFrameMask;
       
    95     delete iNotifyObserverCallBack;
       
    96     delete iFrameTimer;
       
    97     }
       
    98 
       
    99 // ---------------------------------------------------------------------------
       
   100 // @see CIRImageConverter::SetDataL( const TDesC8& aData )
       
   101 // ---------------------------------------------------------------------------
       
   102 //
       
   103 void CIRImageConverterImpl::SetDataL( const TDesC8& aData )
       
   104     {
       
   105     IRRDEBUG2( "CIRImageConverterImpl::SetDataL - Entering", KNullDesC );
       
   106     Cleanup( ETrue );
       
   107     iData.Set( aData );
       
   108     CreateDataHandlerL();
       
   109     IRRDEBUG2( "CIRImageConverterImpl::SetDataL - Exiting", KNullDesC );
       
   110    }
       
   111 
       
   112 // ---------------------------------------------------------------------------
       
   113 // @see CIRImageConverter::SetObserver( MIRImageConverterObserver* aObserver )
       
   114 // ---------------------------------------------------------------------------
       
   115 //
       
   116 void CIRImageConverterImpl::SetObserver( MIRImageConverterObserver* aObserver )
       
   117     {
       
   118     iObserver = aObserver;
       
   119     }
       
   120 
       
   121 // ---------------------------------------------------------------------------
       
   122 // @see CIRImageConverter::EnableAnimations( TBool aEnable )
       
   123 // ---------------------------------------------------------------------------
       
   124 //
       
   125 void CIRImageConverterImpl::EnableAnimations( TBool aEnable )
       
   126     {
       
   127     __ASSERT_DEBUG( iState == EIRStateIdle, User::Invariant() );
       
   128     iEnableAnimations = aEnable;
       
   129     }
       
   130 
       
   131 // ---------------------------------------------------------------------------
       
   132 // @see CIRImageConverter::IsAnimated() const
       
   133 // ---------------------------------------------------------------------------
       
   134 //
       
   135 TBool CIRImageConverterImpl::IsAnimated() const
       
   136     {
       
   137     __ASSERT_DEBUG( iState != EIRStateIdle, User::Invariant() );
       
   138     return iIsAnimated;
       
   139     }
       
   140 
       
   141 // ---------------------------------------------------------------------------
       
   142 // @see CIRImageConverter::MaintainAspectRatio( TBool aMaintain )
       
   143 // ---------------------------------------------------------------------------
       
   144 //
       
   145 void CIRImageConverterImpl::MaintainAspectRatio( TBool aMaintain )
       
   146     {
       
   147     __ASSERT_DEBUG( iState == EIRStateIdle, User::Invariant() );
       
   148     iMaintainAspectRatio = aMaintain;
       
   149     }
       
   150 
       
   151 // ---------------------------------------------------------------------------
       
   152 // @see CIRImageConverter::StartL( const TSize& aTarget, TInt aId )
       
   153 // ---------------------------------------------------------------------------
       
   154 //
       
   155 void CIRImageConverterImpl::StartL( const TSize& aTarget, TInt aId )
       
   156 	{
       
   157     IRRDEBUG2( "CIRImageConverterImpl::StartL - Entering", KNullDesC );
       
   158 	if ( iState != EIRStateBitmapDecoderInitialized && iState != EIRStateSvgEngineInitialized )
       
   159 		{
       
   160 		if ( iState == EIRStateIdle )
       
   161 			{
       
   162 		    IRRDEBUG2("CIRImageConverterImpl::StartL, leave with KErrNotReady", KNullDesC);
       
   163 			User::Leave( KErrNotReady );
       
   164 			}
       
   165 		else
       
   166 			{
       
   167 		    IRRDEBUG2("CIRImageConverterImpl::StartL, leave with KErrInUse", KNullDesC);
       
   168 			User::Leave( KErrInUse );
       
   169 			}
       
   170 		}
       
   171 	iTargetSize = aTarget;
       
   172 	iId = aId;
       
   173 	if ( iState == EIRStateSvgEngineInitialized )
       
   174 		{
       
   175 		// The SVG-T engine has been initialized with dummy 0x0 bitmaps, so updating those must be handled here.
       
   176 	    IRRDEBUG2( "CIRImageConverterImpl::StartL - if begin", KNullDesC );
       
   177 		CreateBitmapL( iTargetSize, iBitmap, iMask );
       
   178 		iSvgEngine->SetFrameBuffer( iBitmap );
       
   179 		iState = EIRStateConvertingSvg;
       
   180 		iSvgEngine->Start();
       
   181 		IRRDEBUG2( "CIRImageConverterImpl::StartL - if end", KNullDesC );
       
   182 		}
       
   183 	else
       
   184 		{
       
   185 	    IRRDEBUG2( "CIRImageConverterImpl::StartL - else begin", KNullDesC );
       
   186 		iState = EIRStateConvertingBitmap;
       
   187 		IRRDEBUG2( "CIRImageConverterImpl::StartL, iDecorder = %d", iDecoder);
       
   188 		iDecoder->Convert( &iStatus, *iBitmap, *iMask );
       
   189 		IRRDEBUG2( "CIRImageConverterImpl::StartL - else-exit call setactive", KNullDesC );
       
   190 		SetActive();
       
   191 		}
       
   192 	IRRDEBUG2( "CIRImageConverterImpl::StartL - Exiting", KNullDesC );
       
   193 	}
       
   194 
       
   195 // ---------------------------------------------------------------------------
       
   196 // @see CIRImageConverter::Stop()
       
   197 // ---------------------------------------------------------------------------
       
   198 //
       
   199 void CIRImageConverterImpl::Stop()
       
   200 	{
       
   201     IRRDEBUG2( "CIRImageConverterImpl::Stop - Entering", KNullDesC );
       
   202 	Cancel();
       
   203 	if ( iSvgEngine )
       
   204 	    {
       
   205 	    iSvgEngine->Stop();
       
   206 	    }
       
   207 	TIRImageConverterState state = iState;
       
   208 	Cleanup();
       
   209 	if ( state != EIRStateIdle && state != EIRStateBitmapDecoderInitialized && 
       
   210 		state != EIRStateSvgEngineInitialized )
       
   211 	    {
       
   212 	    NotifyObserver( KErrCancel );
       
   213 	    }
       
   214 	IRRDEBUG2( "CIRImageConverterImpl::Stop - Exiting",KNullDesC );
       
   215 	}
       
   216 
       
   217 // ---------------------------------------------------------------------------
       
   218 // @see CIRImageConverter::Bitmap() const
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 const CFbsBitmap* CIRImageConverterImpl::Bitmap() const
       
   222     {
       
   223 	IRLOG_DEBUG( "CIRImageConverterImpl::Bitmap - Entering" );
       
   224     return iProcessedBitmap;
       
   225     }
       
   226 
       
   227 // ---------------------------------------------------------------------------
       
   228 // @see CIRImageConverter::Mask() const
       
   229 // ---------------------------------------------------------------------------
       
   230 //
       
   231 const CFbsBitmap* CIRImageConverterImpl::Mask() const
       
   232     {
       
   233 	IRLOG_DEBUG( "CIRImageConverterImpl::Mask - Entering" );
       
   234     return iProcessedMask;
       
   235     }
       
   236 
       
   237 // ---------------------------------------------------------------------------
       
   238 // @see CIRImageConverter::TransferBitmapOwnership( CFbsBitmap*& aBitmap, CFbsBitmap*& aMask )
       
   239 // ---------------------------------------------------------------------------
       
   240 //
       
   241 void CIRImageConverterImpl::TransferBitmapOwnership( CFbsBitmap*& aBitmap, CFbsBitmap*& aMask )
       
   242     {
       
   243     aBitmap = iProcessedBitmap;
       
   244     iProcessedBitmap = NULL;
       
   245     aMask = iProcessedMask;
       
   246     iProcessedMask = NULL;
       
   247     }
       
   248 
       
   249 // ---------------------------------------------------------------------------
       
   250 // From class CActive.
       
   251 // Invoked when the active object is cancelled.
       
   252 // ---------------------------------------------------------------------------
       
   253 //
       
   254 void CIRImageConverterImpl::DoCancel()
       
   255     {
       
   256 	IRLOG_DEBUG( "CIRImageConverterImpl::DoCancel - Entering" );
       
   257     if ( iDecoder )
       
   258         {
       
   259         iDecoder->Cancel();
       
   260         }
       
   261     if ( iScaler )
       
   262         {
       
   263         iScaler->Cancel();
       
   264         }
       
   265 	IRLOG_DEBUG( "CIRImageConverterImpl::DoCancel - Exiting" );
       
   266     }
       
   267 
       
   268 // ---------------------------------------------------------------------------
       
   269 // From class CActive.
       
   270 // Invoked when the active object completes an asynchronous request.
       
   271 // ---------------------------------------------------------------------------
       
   272 //
       
   273 void CIRImageConverterImpl::RunL()
       
   274 	{
       
   275 	IRLOG_DEBUG( "CIRImageConverterImpl::RunL - Entering" );
       
   276 	if ( iStatus.Int() == KErrNone )
       
   277 		{
       
   278 		switch ( iState )
       
   279 			{
       
   280 			case EIRStateConvertingBitmap:
       
   281 				{
       
   282 				if ( iIsAnimated && iEnableAnimations )
       
   283 					{
       
   284 					CGulIcon* icon = CGulIcon::NewLC();
       
   285 
       
   286 					icon->SetBitmapsOwnedExternally( EFalse );
       
   287 					icon->SetBitmap( iBitmap );
       
   288 					icon->SetMask( iMask );
       
   289 
       
   290 					iBitmap = NULL;
       
   291 					iMask = NULL;
       
   292 
       
   293 					iFrames.AppendL( icon );
       
   294 					CleanupStack::Pop( icon );
       
   295 
       
   296 					if ( iFrames.Count() < iDecoder->FrameCount() )
       
   297 						{
       
   298 						CreateBitmapL( iDecoder->FrameInfo( iFrames.Count() ).iOverallSizeInPixels,
       
   299 								 iBitmap, iMask );
       
   300 
       
   301 						iDecoder->Convert( &iStatus, *iBitmap, *iMask, iFrames.Count() );
       
   302 						SetActive();
       
   303 						}
       
   304 					else
       
   305 						{
       
   306 						StartBitmapAnimationL();
       
   307 						}
       
   308 					}
       
   309 				else
       
   310 					{
       
   311 					iState = EIRStateScalingBitmap;
       
   312 					iScaler->Scale( &iStatus, *iBitmap, iTargetSize, iMaintainAspectRatio );
       
   313 					SetActive();
       
   314 					}
       
   315 				}
       
   316 			break;
       
   317 			case EIRStateScalingBitmap:
       
   318 			iState = EIRStateScalingBitmapMask;
       
   319 			iScaler->Scale( &iStatus, *iMask, iTargetSize, iMaintainAspectRatio );
       
   320 			SetActive();
       
   321 			break;
       
   322 			case EIRStateScalingBitmapMask:
       
   323 			NotifyObserver( KErrNone );
       
   324 			break;
       
   325 			default:
       
   326 			break;
       
   327 			}
       
   328 		}
       
   329 	else
       
   330 		{
       
   331 		NotifyObserver( iStatus.Int() );
       
   332 		}
       
   333 	IRLOG_DEBUG( "CIRImageConverterImpl::RunL - Exiting" );
       
   334 	}
       
   335 
       
   336 // ---------------------------------------------------------------------------
       
   337 // From class CActive.
       
   338 // Invoked when RunL leaves.
       
   339 // ---------------------------------------------------------------------------
       
   340 //
       
   341 TInt CIRImageConverterImpl::RunError( TInt aError )
       
   342     {
       
   343 	IRLOG_DEBUG( "CIRImageConverterImpl::NewL - Entering" );
       
   344     NotifyObserver( aError );
       
   345     return KErrNone;
       
   346     }
       
   347 
       
   348 // ---------------------------------------------------------------------------
       
   349 // From class MSvgRequestObserver.
       
   350 // Invoked when the bitmap has been updated by the SVG-T engine.
       
   351 // ---------------------------------------------------------------------------
       
   352 //
       
   353 void CIRImageConverterImpl::UpdateScreen()
       
   354     {
       
   355     iSvgEngine->GenerateMask( iMask );
       
   356     // SVG-T engine MUST NOT be destroyed here as its internal implementation
       
   357     // relies on it existing after execution leaves this method. This means
       
   358     // that the observer notification must be asynchronous
       
   359     NotifyObserver( KErrNone, EFalse );
       
   360     }
       
   361 
       
   362 // ---------------------------------------------------------------------------
       
   363 // From class MSvgRequestObserver.
       
   364 // Not implemented.
       
   365 // ---------------------------------------------------------------------------
       
   366 //
       
   367 TBool CIRImageConverterImpl::ScriptCall( const TDesC& /*aScript*/, CSvgElementImpl* 
       
   368 											/*aCallerElement*/ )
       
   369     {
       
   370     return EFalse;
       
   371     }
       
   372 
       
   373 // ---------------------------------------------------------------------------
       
   374 // From class MSvgRequestObserver.
       
   375 // Not implemented.
       
   376 // ---------------------------------------------------------------------------
       
   377 //
       
   378 TInt CIRImageConverterImpl::FetchImage( const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& 
       
   379 																		/*aFileHandle*/ )
       
   380     {
       
   381     return KErrNone;
       
   382     }
       
   383 
       
   384 // ---------------------------------------------------------------------------
       
   385 // From class MSvgRequestObserver.
       
   386 // Not implemented.
       
   387 // ---------------------------------------------------------------------------
       
   388 //
       
   389 TInt CIRImageConverterImpl::FetchFont( const TDesC& /*aUri*/, RFs& /*aSession*/, RFile& 
       
   390 																		/*aFileHandle*/ )
       
   391     {
       
   392     return KErrNone;
       
   393     }
       
   394 
       
   395 // ---------------------------------------------------------------------------
       
   396 // From class MSvgRequestObserver.
       
   397 // Not implemented.
       
   398 // ---------------------------------------------------------------------------
       
   399 //
       
   400 void CIRImageConverterImpl::UpdatePresentation( const TInt32& /*aNoOfAnimation*/ )
       
   401     {
       
   402     }
       
   403 
       
   404 // ---------------------------------------------------------------------------
       
   405 // Performs cleanup on the converter object.
       
   406 // ---------------------------------------------------------------------------
       
   407 //
       
   408 void CIRImageConverterImpl::Cleanup( TBool aThorough )
       
   409     {
       
   410     Cancel();
       
   411     if ( aThorough )
       
   412         {
       
   413         delete iProcessedBitmap;
       
   414         iProcessedBitmap = NULL;
       
   415         
       
   416         delete iProcessedMask;
       
   417         iProcessedMask = NULL;
       
   418         }
       
   419     if(iDecoder)
       
   420 	    {
       
   421 	    delete iDecoder;
       
   422 	    iDecoder = NULL;
       
   423 	    }
       
   424     if(iScaler)
       
   425 	    {
       
   426 	    delete iScaler;
       
   427 	    iScaler = NULL;
       
   428 	    }
       
   429 	    
       
   430 	if(iSvgEngine)
       
   431 		{
       
   432 	    delete iSvgEngine;
       
   433 	    iSvgEngine = NULL;
       
   434 		}
       
   435 	if(iFrameTimer)
       
   436 		{
       
   437 	    delete iFrameTimer;
       
   438 	    iFrameTimer = NULL;
       
   439 		}
       
   440 	if(iBitmap)
       
   441 		{
       
   442 	    delete iBitmap;
       
   443 	    iBitmap = NULL;
       
   444 		}
       
   445 	if(iMask)
       
   446 		{
       
   447 	    delete iMask;
       
   448 	    iMask = NULL;
       
   449 		}
       
   450 	if(iLastFrameBitmap)
       
   451 		{
       
   452 	    delete iLastFrameBitmap;
       
   453 	    iLastFrameBitmap = NULL;
       
   454 		}
       
   455 	if(iLastFrameMask)
       
   456 		{
       
   457 	    delete iLastFrameMask;
       
   458 	    iLastFrameMask = NULL;
       
   459 		}
       
   460 
       
   461     iFrames.ResetAndDestroy();
       
   462 
       
   463     iNotifyObserverCallBack->Cancel();
       
   464 
       
   465     iFrameIndex = 0;
       
   466     iIsAnimated = EFalse;
       
   467     iError = KErrNone;
       
   468     iState = EIRStateIdle;
       
   469     }
       
   470 
       
   471 // ---------------------------------------------------------------------------
       
   472 // Creates the proper handler for the raw image data.
       
   473 // ---------------------------------------------------------------------------
       
   474 //
       
   475 void CIRImageConverterImpl::CreateDataHandlerL()
       
   476     {
       
   477     IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL - Entering", KNullDesC );
       
   478     TBuf8<KMaxDataTypeLength> mimeType;
       
   479     TRAPD( err, CImageDecoder::GetMimeTypeDataL( iData, mimeType ) )
       
   480 
       
   481 	if ( err == KErrNone ) // Image decoder can handle this MIME type.
       
   482 		{
       
   483 
       
   484 		TRAPD(err1,iDecoder = CImageDecoder::DataNewL( CCoeEnv::Static()->FsSession(), iData,
       
   485 		KIRImageDecoderOptions );)
       
   486 		if(err1!=KErrNone)
       
   487 			{  
       
   488 			if ( iObserver )
       
   489 				{
       
   490 			    IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL, err = %d", err1);
       
   491 				NotifyObserver( err1 );
       
   492 				IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL, error is notified", KNullDesC);
       
   493 				}
       
   494 			}
       
   495 		else
       
   496 			{
       
   497         iScaler = CBitmapScaler::NewL();
       
   498         iScaler->SetQualityAlgorithm( KIRBitmapScalerQualityAlgorithm );
       
   499         iScaler->UseLowMemoryAlgorithm( ETrue ); // Return value ignored on purpose; it's ok if low memory algorithm cannot be used when scaling.
       
   500 
       
   501         if ( iDecoder->FrameCount() > 1 )
       
   502             {
       
   503             iFrameTimer = CPeriodic::NewL( CActive::EPriorityStandard );
       
   504             iIsAnimated = ETrue;
       
   505             }
       
   506 
       
   507         CreateBitmapL( iDecoder->FrameInfo().iOverallSizeInPixels, iBitmap, iMask );
       
   508         }
       
   509 		}
       
   510     else // Try using the SVG-T engine for decoding the image.
       
   511         {
       
   512         
       
   513         TFontSpec fontSpec = AknLayoutUtils::LayoutFontFromId( 
       
   514         						EAknLogicalFontSecondaryFont )->FontSpecInTwips();
       
   515 
       
   516         // The SVG-T engine requires that the bitmap is created prior to its instantiation.
       
   517         // As the dummy bitmaps created here are 0x0, StartL must take care of instantiating them to
       
   518         // proper sizes and updating the SVG-T engine's frame buffer manually before starting the conversion.
       
   519         
       
   520         CreateBitmapL( TSize( 0, 0 ), iBitmap, iMask );
       
   521         
       
   522         iSvgEngine = CSvgEngineInterfaceImpl::NewL( iBitmap, this, fontSpec );
       
   523         MSvgError* svgErr = iSvgEngine->Load( iData );
       
   524         if ( svgErr && svgErr->HasError() )
       
   525             {
       
   526             err = svgErr->SystemErrorCode();
       
   527             }
       
   528         else
       
   529             {
       
   530             err = KErrNone;
       
   531             iIsAnimated = iSvgEngine->SvgHasAnimation( iSvgEngine->SvgDocument() );
       
   532             }
       
   533         }
       
   534 
       
   535     if ( err )
       
   536         {
       
   537         Cleanup( ETrue );
       
   538         User::Leave( KErrNotSupported );
       
   539         }
       
   540     else
       
   541         {
       
   542         iState = iSvgEngine ? EIRStateSvgEngineInitialized : EIRStateBitmapDecoderInitialized;
       
   543         }
       
   544 
       
   545     IRRDEBUG2( "CIRImageConverterImpl::CreateDataHandlerL - Exiting" , KNullDesC);
       
   546    }
       
   547 
       
   548 // ---------------------------------------------------------------------------
       
   549 // Creates new bitmaps of the given size.
       
   550 // ---------------------------------------------------------------------------
       
   551 //
       
   552 void CIRImageConverterImpl::CreateBitmapL( const TSize& aSize, CFbsBitmap*& aBitmap, 
       
   553 										CFbsBitmap*& aMask )
       
   554     {
       
   555 	IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapL - Entering" );
       
   556     CFbsBitmap* bitmap = new ( ELeave ) CFbsBitmap;
       
   557     CleanupStack::PushL( bitmap );
       
   558     User::LeaveIfError( bitmap->Create( aSize, CCoeEnv::Static()->ScreenDevice()
       
   559     									->DisplayMode() ) );
       
   560     
       
   561     CFbsBitmap* mask = new ( ELeave ) CFbsBitmap;
       
   562     CleanupStack::PushL( mask );
       
   563     User::LeaveIfError( mask->Create( aSize, EGray256 ) );
       
   564     
       
   565     delete aBitmap;
       
   566     aBitmap = bitmap;
       
   567     
       
   568     delete aMask;
       
   569     aMask = mask;
       
   570     
       
   571     CleanupStack::Pop( 2, bitmap );
       
   572 	IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapL - Exiting" );
       
   573     }
       
   574 
       
   575 // ---------------------------------------------------------------------------
       
   576 // Creates exact copies of the supplied bitmaps.
       
   577 // ---------------------------------------------------------------------------
       
   578 //
       
   579 void CIRImageConverterImpl::CreateBitmapCopyL( const CFbsBitmap& aSourceBitmap, 
       
   580                                                const CFbsBitmap& aSourceMask, 
       
   581                                                CFbsBitmap*& aBitmap, 
       
   582                                                CFbsBitmap*& aMask )
       
   583     {
       
   584 	IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapCopyL - Entering" );
       
   585     CFbsBitmap* bitmap = IHLBitmapUtil::CopyBitmapLC( aSourceBitmap );
       
   586     CFbsBitmap* mask = IHLBitmapUtil::CopyBitmapLC( aSourceMask );
       
   587     
       
   588     delete aBitmap;
       
   589     aBitmap = bitmap;
       
   590     
       
   591     delete aMask;
       
   592     aMask = mask;
       
   593 
       
   594     CleanupStack::Pop( 2, bitmap );
       
   595 	IRLOG_DEBUG( "CIRImageConverterImpl::CreateBitmapCopyL - Exiting" );
       
   596     }
       
   597 
       
   598 // ---------------------------------------------------------------------------
       
   599 // Starts the bitmap animation.
       
   600 // ---------------------------------------------------------------------------
       
   601 //
       
   602 void CIRImageConverterImpl::StartBitmapAnimationL()
       
   603     {
       
   604     __ASSERT_DEBUG( iFrames.Count() == iDecoder->FrameCount(), User::Invariant() );
       
   605     
       
   606     RenderBitmapAnimationFrameL( ETrue );
       
   607     }
       
   608 
       
   609 // ---------------------------------------------------------------------------
       
   610 // Renders the current bitmap animation frame.
       
   611 // ---------------------------------------------------------------------------
       
   612 //
       
   613 void CIRImageConverterImpl::RenderBitmapAnimationFrameL( TBool aFirstTime )
       
   614     {
       
   615 	IRLOG_DEBUG( "CIRImageConverterImpl::RenderBitmapAnimationFrameL - Entering" );
       
   616     __ASSERT_DEBUG( iFrames.Count() && iFrames.Count() > iFrameIndex, User::Invariant() );
       
   617     
       
   618     
       
   619     const TGifImageControl* gifImageControl = static_cast<const TGifImageControl*>
       
   620     							( iDecoder->FrameData( iFrameIndex ).GetFrameData( 0 ) );
       
   621     if ( gifImageControl )
       
   622         {
       
   623         if ( aFirstTime )
       
   624             {
       
   625             // When rendering the animation for the very first time, we just make a copy of the first frame.
       
   626             CreateBitmapCopyL( *iFrames[0]->Bitmap(), *iFrames[0]->Mask(), 
       
   627             				iLastFrameBitmap, iLastFrameMask );
       
   628             }
       
   629         else
       
   630             {
       
   631             CFbsBitmapDevice* lastFrameBitmapDevice = CFbsBitmapDevice::NewL( iLastFrameBitmap );
       
   632             CleanupStack::PushL( lastFrameBitmapDevice );
       
   633             CFbsBitGc* lastFrameBitmapGc = CFbsBitGc::NewL();
       
   634             CleanupStack::PushL( lastFrameBitmapGc );
       
   635             lastFrameBitmapGc->Activate( lastFrameBitmapDevice );
       
   636             
       
   637             CFbsBitmapDevice* lastFrameMaskDevice = CFbsBitmapDevice::NewL( iLastFrameMask );
       
   638             CleanupStack::PushL( lastFrameMaskDevice );
       
   639             CFbsBitGc* lastFrameMaskGc = CFbsBitGc::NewL();
       
   640             CleanupStack::PushL( lastFrameMaskGc );
       
   641             lastFrameMaskGc->Activate( lastFrameMaskDevice );
       
   642             
       
   643             TRect rect = iDecoder->FrameInfo( iFrameIndex ).iFrameCoordsInPixels;
       
   644             
       
   645 
       
   646             switch ( gifImageControl->iDisposalMethod )
       
   647                 {
       
   648                 case TGifImageControl::ENone:
       
   649                     // The new frame is completely self-sufficient, so no information about the previous frame is required.
       
   650                     lastFrameBitmapGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Bitmap(), 
       
   651                     							TRect( TPoint(), rect.Size() ) );
       
   652                     lastFrameMaskGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Mask(),
       
   653                     						 TRect( TPoint(), rect.Size() ) );
       
   654                     break;
       
   655                 case TGifImageControl::ELeaveInPlace:
       
   656                     // The new frame only contains a partial update on the image, so we have to retain the previous frame state.
       
   657                     lastFrameBitmapGc->BitBltMasked( rect.iTl, iFrames[iFrameIndex]->Bitmap(), 
       
   658                     								TRect( TPoint(), rect.Size() ),
       
   659                     								iFrames[iFrameIndex]->Mask(), EFalse );
       
   660                     break;
       
   661                 case TGifImageControl::ERestoreToBackground:
       
   662                     // The new frame is restored to the background color defined in its data.
       
   663                     lastFrameBitmapGc->SetBrushColor( 
       
   664                     					iDecoder->FrameInfo( iFrameIndex ).iBackgroundColor );
       
   665                     lastFrameBitmapGc->Clear();
       
   666                     lastFrameMaskGc->SetBrushColor( KRgbBlack );
       
   667                     lastFrameMaskGc->Clear();
       
   668                     lastFrameBitmapGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Bitmap(), 
       
   669                     						TRect( TPoint(), rect.Size() ) );
       
   670                     lastFrameMaskGc->BitBlt( rect.iTl, iFrames[iFrameIndex]->Mask(),
       
   671                     						 TRect( TPoint(), rect.Size() ) );
       
   672                     break;
       
   673                 case TGifImageControl::ERestoreToPrevious:
       
   674                     // The new frame is exactly the same as the previous one, so no special processing is required.
       
   675                     break;
       
   676                 default:
       
   677                     break;
       
   678                 }
       
   679     
       
   680             CleanupStack::PopAndDestroy( KFour, lastFrameBitmapDevice );
       
   681             }
       
   682         
       
   683         CreateBitmapCopyL( *iLastFrameBitmap, *iLastFrameMask, iBitmap, iMask );
       
   684         }
       
   685     else
       
   686         {
       
   687         User::Leave( KErrNotReady );
       
   688         }
       
   689 
       
   690     iState = EIRStateScalingBitmap;
       
   691     iScaler->Scale( &iStatus, *iBitmap, iTargetSize, iMaintainAspectRatio );
       
   692     SetActive();
       
   693 	IRLOG_DEBUG( "CIRImageConverterImpl::RenderBitmapAnimationFrameL - Exiting" );
       
   694     }
       
   695 
       
   696 // ---------------------------------------------------------------------------
       
   697 // Notifies the observer either synchronously or asynchronously.
       
   698 // ---------------------------------------------------------------------------
       
   699 //
       
   700 void CIRImageConverterImpl::NotifyObserver( TInt aError, TBool aSynchronous )
       
   701     {
       
   702     IRRDEBUG2( "CIRImageConverterImpl::NotifyObserver - Entering, aError = %d", aError );
       
   703     iError = aError;
       
   704     iNotifyObserverCallBack->Cancel();
       
   705 
       
   706     if ( aSynchronous )
       
   707         {
       
   708         StaticNotifyObserverCallBack( this );
       
   709         }
       
   710     else
       
   711         {
       
   712         iNotifyObserverCallBack->CallBack();
       
   713         }
       
   714     IRRDEBUG2( "CIRImageConverterImpl::NotifyObserver - Exiting", KNullDesC );
       
   715     }
       
   716 
       
   717 // ---------------------------------------------------------------------------
       
   718 // Call back for notifying the observer.
       
   719 // ---------------------------------------------------------------------------
       
   720 //
       
   721 TInt CIRImageConverterImpl::StaticNotifyObserverCallBack( TAny* aSelf )
       
   722     {
       
   723 	IRLOG_DEBUG( "CIRImageConverterImpl::StaticNotifyObserverCallBack - Entering" );
       
   724     CIRImageConverterImpl* self = static_cast<CIRImageConverterImpl*>( aSelf );
       
   725     if ( self )
       
   726         {
       
   727         TInt err = self->iError;
       
   728         MIRImageConverterObserver::TIRImageConversionEvent event = MIRImageConverterObserver::
       
   729         														EIRImageConversionCompleted;
       
   730         
       
   731         if ( err == KErrNone )
       
   732             {
       
   733             if ( self->iSvgEngine && self->iIsAnimated && self->iEnableAnimations )
       
   734                 {
       
   735                 TRAP( err, self->CreateBitmapCopyL( *self->iBitmap, *self->iMask, 
       
   736                 		self->iProcessedBitmap, self->iProcessedMask ) )
       
   737                 }
       
   738             else
       
   739                 {
       
   740                 delete self->iProcessedBitmap;
       
   741                 self->iProcessedBitmap = self->iBitmap;
       
   742                 self->iBitmap = NULL;
       
   743                 delete self->iProcessedMask;
       
   744                 self->iProcessedMask = self->iMask;
       
   745                 self->iMask = NULL;
       
   746                 }
       
   747             
       
   748             if ( !err && self->iIsAnimated && self->iEnableAnimations )
       
   749                 {
       
   750                 event = MIRImageConverterObserver::EIRFrameConversionCompleted;
       
   751 
       
   752                 if ( self->iDecoder )
       
   753                     {
       
   754                     self->iState = EIRStateBetweenBitmapAnimationFrames;
       
   755                     
       
   756                     self->iFrameTimer->Cancel();
       
   757                     self->iFrameTimer->Start( static_cast<TInt>( self->iDecoder->
       
   758                     				FrameInfo( self->iFrameIndex ).iDelay.Int64() ), 0, 
       
   759                                               TCallBack( StaticNextFrameCallBack, self ) );
       
   760 
       
   761                     self->iFrameIndex++;
       
   762                     if ( self->iFrameIndex >= self->iDecoder->FrameCount() )
       
   763                         {
       
   764                         self->iFrameIndex = 0;
       
   765                         }
       
   766                     }
       
   767                 }
       
   768             }
       
   769 
       
   770         if ( err || event == MIRImageConverterObserver::EIRImageConversionCompleted )
       
   771             {
       
   772             self->Cleanup();
       
   773             }
       
   774         
       
   775         if ( self->iObserver )
       
   776             {
       
   777             TRAP_IGNORE( self->iObserver->HandleImageConversionEventL( event, self->iId, err ) )
       
   778             }
       
   779         }
       
   780     
       
   781     return KErrNone;
       
   782     }
       
   783 
       
   784 // ---------------------------------------------------------------------------
       
   785 // Call back for advancing to the next frame when bitmap animations are used.
       
   786 // ---------------------------------------------------------------------------
       
   787 //
       
   788 TInt CIRImageConverterImpl::StaticNextFrameCallBack( TAny* aSelf )
       
   789     {
       
   790     CIRImageConverterImpl* self = static_cast<CIRImageConverterImpl*>( aSelf );
       
   791     if ( self )
       
   792         {
       
   793         self->iFrameTimer->Cancel();
       
   794         TRAPD( err, self->RenderBitmapAnimationFrameL() )
       
   795         if ( err )
       
   796             {
       
   797             self->NotifyObserver( err );
       
   798             }
       
   799         }
       
   800     return KErrNone;
       
   801     }