webengine/osswebengine/WebCore/platform/symbian/bitmap/AnimationDecoder.cpp
changeset 0 dd21522fd290
child 16 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2006 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 the License "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:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "config.h"
       
    21 #include "AnimationDecoder.h"
       
    22 #include "MaskedBitmap.h"
       
    23 #include "ImageObserver.h"
       
    24 #include "SyncDecodeThread.h"
       
    25 #include "Oma2Agent.h"
       
    26 using namespace ContentAccess;
       
    27 
       
    28 namespace TBidirectionalState {
       
    29     class TRunInfo;
       
    30 };
       
    31 
       
    32 #include <eikenv.h>
       
    33 
       
    34 // constants
       
    35 
       
    36 // Private namespace for constants and functions
       
    37 namespace
       
    38   {
       
    39   // Panic function
       
    40   void Panic( TInt aPanicCode ) { User::Panic( _L("AnimationDecoder"), aPanicCode ); }
       
    41   }
       
    42 
       
    43 using namespace WebCore;
       
    44 
       
    45 // ============================ MEMBER FUNCTIONS ===============================
       
    46 // -----------------------------------------------------------------------------
       
    47 //
       
    48 // C++ default constructor can NOT contain any code, that
       
    49 // might leave.
       
    50 // -----------------------------------------------------------------------------
       
    51 CAnimationDecoder::CAnimationDecoder( ImageObserver* aObs )
       
    52     :CActive( CActive::EPriorityIdle )
       
    53     , iObserver(aObs)
       
    54     , iLoopCount( -1 )
       
    55     , iCurLoopCount( -1 )
       
    56     , iSyncBitmapHandle(-1)
       
    57     , iSyncMaskHandle(-1)
       
    58     , iSyncDecodeThread(NULL)
       
    59     , iDecodeInProgress(ETrue)
       
    60 {
       
    61     if (CActiveScheduler::Current())
       
    62         CActiveScheduler::Add( this );    
       
    63 }
       
    64 
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 // Two-phased constructor.
       
    68 // -----------------------------------------------------------------------------
       
    69 CAnimationDecoder* CAnimationDecoder::NewL( ImageObserver* aObs )
       
    70 {
       
    71     CAnimationDecoder* self = new (ELeave) CAnimationDecoder( aObs );
       
    72     CleanupStack::PushL( self );
       
    73     self->ConstructL( );
       
    74     CleanupStack::Pop(); // self
       
    75     return self;
       
    76 }
       
    77 
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 // Symbian constructor can leave.
       
    81 // -----------------------------------------------------------------------------
       
    82 void CAnimationDecoder::ConstructL( )
       
    83   {
       
    84   }
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // Destructor
       
    88 // -----------------------------------------------------------------------------
       
    89 CAnimationDecoder::~CAnimationDecoder()
       
    90 {
       
    91     Cancel();
       
    92 
       
    93     if( iDecoder ) {
       
    94         // animated images still being decoded.
       
    95         iDecoder->Cancel();
       
    96         delete iDecoder, iDecoder = NULL;
       
    97     }
       
    98 
       
    99     delete iSyncDecodeThread; iSyncDecodeThread = NULL;
       
   100     delete iAnimationBitmap, iAnimationBitmap = NULL;
       
   101     delete iDestination, iDestination = NULL;
       
   102     if(iDrmContent) 
       
   103     {
       
   104         delete iDrmContent;
       
   105         iDrmContent = NULL;
       
   106     }
       
   107 }
       
   108 
       
   109 // -----------------------------------------------------------------------------
       
   110 // OpenL
       
   111 // -----------------------------------------------------------------------------
       
   112 void CAnimationDecoder::OpenAndDecodeSyncL( const TDesC8& aData )
       
   113 {    
       
   114     iSizeAvailable = EFalse;
       
   115     iRawDataComplete = ETrue;
       
   116     delete iDestination;
       
   117     iDestination = NULL;
       
   118     delete iSyncDecodeThread;
       
   119     iSyncDecodeThread = NULL;
       
   120     
       
   121     iSyncDecodeThread = CSynDecodeThread::NewL();
       
   122     
       
   123     TRequestStatus status;
       
   124     if (iSyncDecodeThread->Decode( aData, &status ) == KErrNone) {
       
   125         User::WaitForRequest(status);
       
   126         if( status == KErrNone ) {
       
   127             iSyncDecodeThread->Handle(iSyncBitmapHandle, iSyncMaskHandle);
       
   128             iSizeAvailable = ETrue;
       
   129         }
       
   130     }
       
   131     if (!iSizeAvailable) {
       
   132         delete iSyncDecodeThread;
       
   133         iSyncDecodeThread = NULL;
       
   134     }
       
   135 }
       
   136 
       
   137 CMaskedBitmap* CAnimationDecoder::Destination() 
       
   138 { 
       
   139     if (iDestination)
       
   140         return iDestination; 
       
   141         
       
   142     if (iSyncBitmapHandle != -1 && iSyncMaskHandle != -1) {
       
   143         CFbsBitmap* bitmap = new CFbsBitmap();
       
   144         bitmap->Duplicate(iSyncBitmapHandle);
       
   145         CFbsBitmap* mask = new CFbsBitmap();
       
   146         mask->Duplicate(iSyncMaskHandle);
       
   147 
       
   148         iDestination = new CMaskedBitmap(bitmap, mask);
       
   149         iDestination->SetFrameIndex(0);
       
   150         iDestination->SetFrameDelay(0);
       
   151         iSyncBitmapHandle = -1;
       
   152         iSyncMaskHandle = -1;
       
   153     }
       
   154     delete iSyncDecodeThread;
       
   155     iSyncDecodeThread = NULL;
       
   156     return iDestination;
       
   157 }
       
   158 //=============================================================================
       
   159 // DecodeDRMImageContentL : Function for handling the DRM image content
       
   160 //=============================================================================
       
   161 HBufC8* CAnimationDecoder::DecodeDRMImageContentL(const TDesC8& aData)
       
   162 {
       
   163     // input buffers for image conversion
       
   164     HBufC8* bufInput = HBufC8::NewLC( aData.Length() + 1 );
       
   165     TPtr8 ptrInput = bufInput->Des();
       
   166     //Reader intends to view content
       
   167     ptrInput.Append( EView );
       
   168     ptrInput.Append( aData );
       
   169 
       
   170     // output buffer for image conversion
       
   171     HBufC8* animatedDRMdata = HBufC8::NewLC( aData.Length() + 256 );
       
   172     TPtr8 ptrOutput = animatedDRMdata->Des();
       
   173 
       
   174   //Find DRM agent
       
   175     TAgent agentDRM;
       
   176     
       
   177     RArray<ContentAccess::TAgent> agents;
       
   178     ContentAccess::CManager* manager = CManager::NewLC();
       
   179     manager->ListAgentsL( agents );
       
   180     for ( TInt i = 0; i < agents.Count(); i++ )
       
   181       {
       
   182     if ( agents[i].Name().Compare( KOmaDrm2AgentName ) == 0)
       
   183       {
       
   184        agentDRM = agents[i];
       
   185        //convert the DRM image
       
   186        manager->AgentSpecificCommand( agentDRM, EDecryptOma1DcfBuffer, ptrInput,ptrOutput);
       
   187        break;
       
   188       }
       
   189     }
       
   190 
       
   191     CleanupStack::PopAndDestroy(manager);
       
   192     //keep animatedDRMdata to return
       
   193     CleanupStack::Pop(animatedDRMdata);
       
   194     CleanupStack::PopAndDestroy(bufInput);
       
   195 
       
   196     return animatedDRMdata;
       
   197     }
       
   198 // -----------------------------------------------------------------------------
       
   199 // OpenL
       
   200 // -----------------------------------------------------------------------------
       
   201 void CAnimationDecoder::OpenL( const TDesC8& aData, TDesC* aMIMEType, TBool aIsComplete )
       
   202 {
       
   203     if(!iObserver) {
       
   204         OpenAndDecodeSyncL(aData);
       
   205         return;
       
   206     }
       
   207         
       
   208     
       
   209     delete iDestination;
       
   210     iDestination = NULL;
       
   211     iDestination = CMaskedBitmap::NewL();
       
   212 
       
   213     HBufC8* mime = 0;
       
   214     TPtrC8 buffer(aData.Ptr(),aData.Length());
       
   215     if (aMIMEType) {
       
   216         // it is safer to ignore the server supplied mime type and just recognize
       
   217         // the image type from the data headers. this does not work for all formats though
       
   218         if ( *aMIMEType==KMimeWBMP || *aMIMEType==KMimeOTA || *aMIMEType==KMimeWMF){
       
   219             // convert to 8 bit
       
   220             mime = HBufC8::NewLC(aMIMEType->Length());
       
   221             mime->Des().Copy(*aMIMEType);
       
   222         }
       
   223         if( *aMIMEType==KMimeDRM )
       
   224         {
       
   225         iDrmContent = DecodeDRMImageContentL(aData);
       
   226         
       
   227         TInt drmContentLength = iDrmContent->Des().Length();
       
   228         buffer.Set( (const TUint8*)iDrmContent->Des().Ptr(), drmContentLength);
       
   229         }
       
   230     }
       
   231          
       
   232     if( !iDecoder )
       
   233         iDecoder = CBufferedImageDecoder::NewL(CEikonEnv::Static()->FsSession());
       
   234 
       
   235     if (mime){
       
   236         iDecoder->OpenL(buffer,*mime,CImageDecoder::EOptionNone);
       
   237         CleanupStack::PopAndDestroy(); // mime
       
   238     }
       
   239     else {
       
   240         iDecoder->OpenL(buffer,CImageDecoder::EOptionNone);
       
   241     }
       
   242 
       
   243     iRawDataComplete = aIsComplete;
       
   244 
       
   245     if(iDecoder->ValidDecoder()  && iDecoder->IsImageHeaderProcessingComplete())
       
   246         StartDecodingL();
       
   247     else
       
   248         // remove me when incremental image rendering gets supported
       
   249         User::Leave( KErrCorrupt );
       
   250 
       
   251     //If it is an animated image, let's figure out loop count
       
   252     if(IsAnimation()) {
       
   253         // first see if have a netscape 2.0 extension header 
       
   254         const TUint8 extString[] = { 'N', 'E', 'T', 'S', 'C', 'A', 'P','E','2','.','0','\3','\1' };
       
   255         const TInt sizeofextString = sizeof(extString);
       
   256         TPtrC8 rawDataPtr((TUint8*)aData.Ptr(), aData.Length());
       
   257         TInt offset = rawDataPtr.Find(extString, sizeofextString);
       
   258         if(offset != KErrNotFound) {
       
   259             // found a header, get the loop count -
       
   260             // (the loop count is in the 2 bytes following the header string listed above,
       
   261             // stored low byte then high byte)
       
   262             iLoopCount = (TInt16)((rawDataPtr[offset+sizeofextString+1] * 256) + rawDataPtr[offset+sizeofextString]);
       
   263             if(iLoopCount != 0) {
       
   264                 ++iLoopCount;  // +1 to make it 1 based rather than 0 based 
       
   265             }
       
   266             else{
       
   267             // 0 indicates infinite - map to internal loop count infinite value 
       
   268                 iLoopCount = -1;
       
   269             }
       
   270         }
       
   271         else {
       
   272             // no header found, assume 1x thru loop 
       
   273             iLoopCount = 1;
       
   274         }
       
   275         iCurLoopCount = iLoopCount;
       
   276     }
       
   277 }
       
   278 
       
   279 // -----------------------------------------------------------------------------
       
   280 // CAnimationDecoder::AddDataL
       
   281 // New chunk of raw data
       
   282 //
       
   283 // -----------------------------------------------------------------------------
       
   284 //
       
   285 void CAnimationDecoder::AddDataL(
       
   286     const TDesC8& aNextChunk,
       
   287     TBool aIsComplete )
       
   288 {
       
   289     iRawDataComplete = aIsComplete;
       
   290 
       
   291     if( iDecoder ) {
       
   292         iDecoder->AppendDataL(aNextChunk);
       
   293         if( iDecoder->ValidDecoder() ) {
       
   294             //  if the image conversion is busy , then just appending the
       
   295             // data should be sufficient
       
   296             if(iStatus == KRequestPending) {
       
   297                 // more image data
       
   298                 iDecoder->ContinueConvert( &iStatus );
       
   299                 SetActive();
       
   300             }
       
   301         }
       
   302         else {
       
   303             iDecoder->ContinueOpenL() ;
       
   304             if(iDecoder->ValidDecoder()  && iDecoder->IsImageHeaderProcessingComplete()){
       
   305                 StartDecodingL();
       
   306             }
       
   307         }
       
   308     }
       
   309 }
       
   310 
       
   311 // -----------------------------------------------------------------------------
       
   312 // CImageLoader::StartDecodingL
       
   313 //
       
   314 // -----------------------------------------------------------------------------
       
   315 //
       
   316 void CAnimationDecoder::StartDecodingL()
       
   317 {
       
   318     // Check frame count
       
   319     iAnimationFrameCount = iDecoder->FrameCount();
       
   320     iAnimation = iAnimationFrameCount > 1;
       
   321     iFrameInfo = iDecoder->FrameInfo( 0 );
       
   322     iSizeAvailable = ETrue;
       
   323 
       
   324     if (iFrameInfo.iFlags & TFrameInfo::ETransparencyPossible){
       
   325         // we only support gray2 and gray256 tiling
       
   326         TDisplayMode maskmode = ( (iFrameInfo.iFlags & TFrameInfo::EAlphaChannel) && (iFrameInfo.iFlags & TFrameInfo::ECanDither)) ? EGray256 : EGray2;
       
   327         TInt error = iDestination->Create( iFrameInfo.iOverallSizeInPixels, DisplayMode(), maskmode );
       
   328 
       
   329         if (!error)
       
   330             LoadFrame(0);
       
   331         else
       
   332             RunError(KErrNoMemory);
       
   333     }
       
   334     else {
       
   335         TInt error = iDestination->Create( iFrameInfo.iOverallSizeInPixels, DisplayMode() );
       
   336         if (!error)
       
   337             LoadFrame(0);
       
   338         else
       
   339             RunError(KErrNoMemory);
       
   340     }
       
   341 }
       
   342 
       
   343 // -----------------------------------------------------------------------------
       
   344 // CAnimationDecoder::MaskDisplayMode
       
   345 // -----------------------------------------------------------------------------
       
   346 TDisplayMode CAnimationDecoder::MaskDisplayMode() const
       
   347 {
       
   348     if( iFrameInfo.iFlags & TFrameInfo::ETransparencyPossible ){
       
   349         if( iFrameInfo.iFlags & TFrameInfo::EAlphaChannel && (iFrameInfo.iFlags & TFrameInfo::ECanDither))
       
   350             return EGray256;
       
   351     return EGray2;
       
   352     }
       
   353     return ENone;
       
   354 }
       
   355 
       
   356 // -----------------------------------------------------------------------------
       
   357 // CAnimationDecoder::AnimationFrameDelay
       
   358 // -----------------------------------------------------------------------------
       
   359 TTimeIntervalMicroSeconds32 CAnimationDecoder::AnimationFrameDelay( TInt aAnimationFrameIndex ) const
       
   360 {
       
   361     __ASSERT_ALWAYS( aAnimationFrameIndex >= 0 &&
       
   362     aAnimationFrameIndex < iAnimationFrameCount, Panic( KErrArgument ) );
       
   363 
       
   364     return I64INT( iDecoder->FrameInfo( aAnimationFrameIndex ).iDelay.Int64() );
       
   365 }
       
   366 
       
   367 
       
   368 // -----------------------------------------------------------------------------
       
   369 // CAnimationDecoder::DoCancel
       
   370 // -----------------------------------------------------------------------------
       
   371 void CAnimationDecoder::DoCancel()
       
   372 {
       
   373     iDecoder->Cancel();
       
   374     // Delete all processed bitmaps
       
   375     ErrorCleanup();
       
   376     // Complete with cancel
       
   377     iImageState = EInactive;
       
   378 }
       
   379 
       
   380 // -----------------------------------------------------------------------------
       
   381 // CAnimationDecoder::RunL
       
   382 // -----------------------------------------------------------------------------
       
   383 void CAnimationDecoder::RunL()
       
   384 {
       
   385     __ASSERT_DEBUG( iDestination, Panic( KErrGeneral ) );
       
   386     // don't kick off the image decoding until the preview mode is over
       
   387     if (iStatus==KErrUnderflow) {
       
   388         if (!IsAnimation())
       
   389             iObserver->partialImage();
       
   390         return;
       
   391     }
       
   392     else if( iStatus == KErrCorrupt ) {
       
   393         RunError( iStatus.Int() );
       
   394         return;
       
   395     }
       
   396     User::LeaveIfError( iStatus.Int() );
       
   397     switch( iImageState ) {
       
   398         case EStartLoad:
       
   399             {
       
   400             // start loading the bitmaps
       
   401             StartLoadL();
       
   402             break;
       
   403             }
       
   404         case ECompleteLoad:
       
   405             {
       
   406             // complete loading the bitmaps
       
   407             CompleteLoadL();
       
   408             break;
       
   409             }
       
   410         default:
       
   411             {
       
   412             Panic( KErrTotalLossOfPrecision );
       
   413             }
       
   414     }
       
   415 }
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // CAnimationDecoder::RunError
       
   419 // -----------------------------------------------------------------------------
       
   420 TInt CAnimationDecoder::RunError( TInt aError )
       
   421 {
       
   422     // Delete all processed bitmaps
       
   423     ErrorCleanup();
       
   424     // Complete with error
       
   425     iImageState = EInactive;
       
   426     iObserver->decoderError(aError);
       
   427     return KErrNone;
       
   428 }
       
   429 
       
   430 // -----------------------------------------------------------------------------
       
   431 // CAnimationDecoder::LoadFrame
       
   432 // -----------------------------------------------------------------------------
       
   433 TInt CAnimationDecoder::LoadFrame( TInt aFrameIndex )
       
   434 {
       
   435     if( IsBusy() )
       
   436         return KErrNotReady;
       
   437 
       
   438     if( aFrameIndex < 0 || aFrameIndex >= iDecoder->FrameCount() )
       
   439         return KErrArgument;
       
   440 
       
   441     iFrameIndex = aFrameIndex;
       
   442     // Start the active object
       
   443     iImageState = EStartLoad;
       
   444     SelfComplete();
       
   445     return KErrNone;
       
   446 }
       
   447 
       
   448 // -----------------------------------------------------------------------------
       
   449 // CAnimationDecoder::StartLoadL
       
   450 // -----------------------------------------------------------------------------
       
   451 void CAnimationDecoder::StartLoadL()
       
   452 {
       
   453     __ASSERT_DEBUG( !iAnimationBitmap, Panic( KErrGeneral ) );
       
   454 
       
   455     if( iAnimation ) {
       
   456         // Start animation from first frame by default
       
   457         iAnimationFrameIndex = 0;
       
   458 
       
   459         // Check is animation can be continued on top of destination bitmap
       
   460         if( iDestination->FrameIndex() < iFrameIndex )
       
   461           iAnimationFrameIndex = iDestination->FrameIndex() + 1;
       
   462 
       
   463         StartLoadAnimationBitmapL( iAnimationFrameIndex );
       
   464     }
       
   465     else // normal image
       
   466         StartLoadNormalBitmap( iFrameIndex );
       
   467     
       
   468     iDecodeInProgress = EFalse;    
       
   469     iImageState = ECompleteLoad;
       
   470     SetActive();
       
   471 }
       
   472 
       
   473 // -----------------------------------------------------------------------------
       
   474 // CAnimationDecoder::StartLoadNormalBitmap
       
   475 // -----------------------------------------------------------------------------
       
   476 void CAnimationDecoder::StartLoadNormalBitmap( TInt aFrameIndex )
       
   477 {
       
   478     CFbsBitmap& dstBitmap = iDestination->BitmapModifyable();
       
   479     CFbsBitmap& dstMask = iDestination->MaskModifyable();
       
   480 
       
   481     if( MaskDisplayMode() != ENone && dstMask.Handle() )
       
   482         iDecoder->Convert( &iStatus, dstBitmap, dstMask, aFrameIndex );
       
   483     else {
       
   484         dstMask.Reset();
       
   485         iDecoder->Convert( &iStatus, dstBitmap, aFrameIndex );
       
   486     }
       
   487 }
       
   488 
       
   489 // -----------------------------------------------------------------------------
       
   490 // CAnimationDecoder::StartLoadAnimationBitmapL
       
   491 // -----------------------------------------------------------------------------
       
   492 void CAnimationDecoder::StartLoadAnimationBitmapL( TInt aFrameIndex )
       
   493 {
       
   494     __ASSERT_DEBUG( !iAnimationBitmap, Panic( KErrGeneral ) );
       
   495 
       
   496     // Create animation bitmap
       
   497     iAnimationBitmap = CMaskedBitmap::NewL();
       
   498     CFbsBitmap& animBitmap = iAnimationBitmap->BitmapModifyable();
       
   499     CFbsBitmap& animMask = iAnimationBitmap->MaskModifyable();
       
   500 
       
   501     TFrameInfo frameInfo( iDecoder->FrameInfo( aFrameIndex ) );
       
   502     User::LeaveIfError( animBitmap.Create(
       
   503     frameInfo.iOverallSizeInPixels, EColor16M ) );
       
   504 
       
   505     TDisplayMode maskDisplayMode( ENone );
       
   506 
       
   507     if( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) {
       
   508         if( frameInfo.iFlags & TFrameInfo::EAlphaChannel && (frameInfo.iFlags & TFrameInfo::ECanDither)) 
       
   509             maskDisplayMode = EGray256;
       
   510         maskDisplayMode = EGray2;
       
   511 
       
   512         User::LeaveIfError( animMask.Create( frameInfo.iOverallSizeInPixels, maskDisplayMode ) );
       
   513         iDecoder->Convert( &iStatus, animBitmap, animMask, aFrameIndex );
       
   514     }
       
   515     else
       
   516         iDecoder->Convert( &iStatus, animBitmap, aFrameIndex );
       
   517 }
       
   518 
       
   519 // -----------------------------------------------------------------------------
       
   520 // CAnimationDecoder::CompleteLoadL
       
   521 // -----------------------------------------------------------------------------
       
   522 void CAnimationDecoder::CompleteLoadL()
       
   523 {
       
   524     TSize frameSize = iFrameInfo.iOverallSizeInPixels;
       
   525     int sizeinBytes = frameSize.iWidth * frameSize.iHeight * 2;
       
   526     if( iAnimationBitmap ){
       
   527         // Copy animation bitmap to destination
       
   528         BuildAnimationFrameL();
       
   529         delete iAnimationBitmap;
       
   530         iAnimationBitmap = NULL;
       
   531 
       
   532         iDestination->SetFrameIndex( iAnimationFrameIndex );
       
   533         iDestination->SetFrameDelay( AnimationFrameDelay( iAnimationFrameIndex ) );
       
   534 
       
   535         if( iAnimationFrameIndex < iFrameIndex ) {
       
   536             // re-start the active object and load next frame
       
   537             iAnimationFrameIndex++;
       
   538             iImageState = EStartLoad;
       
   539             SelfComplete();
       
   540         }
       
   541         else {
       
   542             // Animation ready
       
   543             iImageState = EInactive;
       
   544             iObserver->animationFrameReady(sizeinBytes);
       
   545         }
       
   546     }
       
   547     else {
       
   548         // Save source info destination
       
   549         iDestination->SetFrameIndex( iFrameIndex );
       
   550         iDestination->SetFrameDelay( 0 );
       
   551 
       
   552         // Normal image ready
       
   553         //iDestination = NULL;
       
   554         iImageState = EInactive;
       
   555         iObserver->imageReady(sizeinBytes);
       
   556         delete iDecoder, iDecoder = NULL;
       
   557     }
       
   558 }
       
   559 
       
   560 // -----------------------------------------------------------------------------
       
   561 // CAnimationDecoder::BuildAnimationFrameL
       
   562 // -----------------------------------------------------------------------------
       
   563 void CAnimationDecoder::BuildAnimationFrameL()
       
   564     {
       
   565     __ASSERT_DEBUG( iAnimationBitmap, Panic( KErrGeneral ) );
       
   566     const CFbsBitmap& animBitmap = iAnimationBitmap->Bitmap();
       
   567     const CFbsBitmap& animMask = iAnimationBitmap->Mask();
       
   568     __ASSERT_DEBUG( animBitmap.Handle(), Panic( KErrGeneral ) );
       
   569 
       
   570 
       
   571 		//If the first frame starts from position(0,0), copy directly to the destination bitmap 
       
   572 		//otherwise frame has to be appropriately positioned in the destination bitmap  
       
   573     TPoint aStartPoint(0,0);
       
   574     if( (iAnimationFrameIndex==0) && (iFrameInfo.iFrameCoordsInPixels.iTl==aStartPoint) )
       
   575     {
       
   576         // First frame can be directly put into destination
       
   577         User::LeaveIfError( iDestination->Copy( animBitmap, animMask, ETrue ) );
       
   578     }
       
   579     else {
       
   580         CFbsBitmap& prevBitmap = iDestination->BitmapModifyable();
       
   581         CFbsBitmap& prevMask = iDestination->MaskModifyable();
       
   582 
       
   583         // Other frames must be build on top of previous frames
       
   584         __ASSERT_DEBUG( prevBitmap.Handle(), Panic( KErrGeneral ) );
       
   585 
       
   586         // Create bitmap device to destination bitmap
       
   587         CFbsBitGc* bitGc;
       
   588         CFbsBitmapDevice* bitDevice = CFbsBitmapDevice::NewL( &prevBitmap );
       
   589         CleanupStack::PushL( bitDevice );
       
   590         User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
       
   591         CleanupStack::PushL( bitGc );
       
   592 
       
   593         // Restore area in destination bitmap if needed
       
   594         TRect restoreRect;
       
   595         TBool restoreToBackground( EFalse );
       
   596         
       
   597         TInt aFrameNo = (iAnimationFrameIndex >= 1)?(iAnimationFrameIndex):1;
       
   598         TFrameInfo prevFrameInfo(iDecoder->FrameInfo(aFrameNo - 1));
       
   599         
       
   600         //TFrameInfo prevFrameInfo( iDecoder->FrameInfo( iAnimationFrameIndex - 1 ) );
       
   601         
       
   602         if( (prevFrameInfo.iFlags & TFrameInfo::ERestoreToBackground )|| (iAnimationFrameIndex ==0)) 
       
   603         {
       
   604             restoreToBackground = ETrue;
       
   605             restoreRect = prevFrameInfo.iFrameCoordsInPixels;
       
   606             bitGc->SetPenColor( prevFrameInfo.iBackgroundColor );
       
   607             bitGc->SetBrushColor( prevFrameInfo.iBackgroundColor );
       
   608             bitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   609             if(iAnimationFrameIndex ==0){
       
   610               bitGc->Clear(); 		
       
   611             }
       
   612             else{
       
   613                bitGc->DrawRect( restoreRect ); 	
       
   614             }
       
   615             bitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   616          }
       
   617         // Copy animation frame to destination bitmap
       
   618         TFrameInfo frameInfo( iDecoder->FrameInfo( iAnimationFrameIndex) );
       
   619         if( animMask.Handle() ) {
       
   620             bitGc->BitBltMasked( frameInfo.iFrameCoordsInPixels.iTl, &animBitmap,
       
   621             animBitmap.SizeInPixels(), &animMask, EFalse );
       
   622         }
       
   623         else {
       
   624             bitGc->BitBlt( frameInfo.iFrameCoordsInPixels.iTl, &animBitmap,
       
   625             animBitmap.SizeInPixels() );
       
   626         }
       
   627         CleanupStack::PopAndDestroy( 2 ); // bitmapCtx, bitmapDev
       
   628 
       
   629         // Combine masks if any
       
   630         if( prevMask.Handle() && animMask.Handle() ) {
       
   631             bitDevice = CFbsBitmapDevice::NewL( &prevMask );
       
   632             CleanupStack::PushL( bitDevice );
       
   633             User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
       
   634             CleanupStack::PushL( bitGc );
       
   635 
       
   636             if( restoreToBackground ) {
       
   637                 bitGc->SetBrushColor( KRgbBlack );
       
   638                 bitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   639                 if(iAnimationFrameIndex ==0){
       
   640                    bitGc->Clear(); 		
       
   641                  }
       
   642                  else{
       
   643                    bitGc->DrawRect( restoreRect ); 	
       
   644                  }
       
   645                 bitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   646             }
       
   647             CFbsBitmap* tmpMask = new(ELeave) CFbsBitmap;
       
   648             CleanupStack::PushL( tmpMask );
       
   649             User::LeaveIfError( tmpMask->Create( prevMask.SizeInPixels(), prevMask.DisplayMode() ) );
       
   650             CFbsBitmapDevice* tmpMaskDev = CFbsBitmapDevice::NewL( tmpMask );
       
   651             CleanupStack::PushL( tmpMaskDev );
       
   652             CFbsBitGc* tmpMaskGc;
       
   653             User::LeaveIfError( tmpMaskDev->CreateContext( tmpMaskGc ) );
       
   654             CleanupStack::PushL( tmpMaskGc );
       
   655 
       
   656             tmpMaskGc->BitBlt( TPoint( 0, 0 ), &prevMask, frameInfo.iFrameCoordsInPixels );
       
   657 
       
   658             bitGc->BitBltMasked( frameInfo.iFrameCoordsInPixels.iTl, &animMask,
       
   659             animMask.SizeInPixels(), tmpMask, ETrue );
       
   660 
       
   661             CleanupStack::PopAndDestroy( 5 ); //tmpMask, tmpMaskDev, tmpMaskGc, bitGc, bitDevice
       
   662         }
       
   663     else
       
   664         prevMask.Reset(); // Mask not valid anymore -> reset
       
   665     }
       
   666 }
       
   667 
       
   668 // -----------------------------------------------------------------------------
       
   669 // CAnimationDecoder::ErrorCleanup
       
   670 // -----------------------------------------------------------------------------
       
   671 void CAnimationDecoder::ErrorCleanup()
       
   672 {
       
   673     if( iAnimationBitmap ) {
       
   674         delete iAnimationBitmap;
       
   675         iAnimationBitmap = NULL;
       
   676     }
       
   677 
       
   678     if( iDestination ) {
       
   679         delete iDestination;
       
   680         iDestination = NULL;
       
   681     }
       
   682 }
       
   683 
       
   684 // -----------------------------------------------------------------------------
       
   685 // CAnimationDecoder::SelfComplete
       
   686 // -----------------------------------------------------------------------------
       
   687 void CAnimationDecoder::SelfComplete( TInt aError )
       
   688 {
       
   689     SetActive();
       
   690     iStatus = KRequestPending;
       
   691     TRequestStatus* status = &iStatus;
       
   692     User::RequestComplete( status, aError );
       
   693 }
       
   694 
       
   695 
       
   696 
       
   697 //  End of File