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