uiacceltk/hitchcock/coretoolkit/src/huitextureanimationstate.cpp
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 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:   Implementation of CHuiTextureAnimationState.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <e32base.h>
       
    21 #include <fbs.h>
       
    22 #include <bitstd.h>
       
    23 #include <uiacceltk/HuiUtil.h>
       
    24 #include "huitextureanimationstate.h"
       
    25 
       
    26 /**
       
    27  * Modifiable bitmap helper class for CHuiTextureAnimationState.
       
    28  */
       
    29 NONSHARABLE_CLASS( CHuiModifiableBitmap ) : public CBase
       
    30     {
       
    31 public:
       
    32     /**
       
    33      * Two-phased constructor. This creates new bitmap, 
       
    34      * this instance owns it until @c ReleaseBitmap is called.
       
    35      * @param aSize size of bitmap.
       
    36      * @param aMode display mode of bitmap.
       
    37      */
       
    38     static CHuiModifiableBitmap* NewLC( const TSize& aSize, TDisplayMode aMode );
       
    39     
       
    40     /**
       
    41      * Two-phased constructor. Use another bitmap and ownership
       
    42      * is not taken.
       
    43      * @param aBitmap bitmap to be modified.
       
    44      */
       
    45     static CHuiModifiableBitmap* NewLC( CFbsBitmap& aBitmap );
       
    46     
       
    47     /**
       
    48      * Destructor.
       
    49      */
       
    50     ~CHuiModifiableBitmap();
       
    51 
       
    52     /**
       
    53      * Returns graphics context. Ownership is not passed.
       
    54      * @return graphics context.
       
    55      */
       
    56     CFbsBitGc& Context();    
       
    57     
       
    58     /**
       
    59      * Releases bitmap and passes ownership to caller.
       
    60      * After this has been called, bitmap operations should not
       
    61      * be performed through this class.
       
    62      * @return bitmap.
       
    63      */
       
    64     CFbsBitmap* ReleaseBitmap();
       
    65     
       
    66     /**
       
    67      * Clears the whole bitmap with specified color.
       
    68      * @param aColor color to use.
       
    69      */
       
    70     void Clear( const TRgb& aColor );
       
    71     
       
    72     /**
       
    73      * Clears area of bitmap with specified color.
       
    74      * @param aRect area to fill.
       
    75      * @param aColor color to use.
       
    76      */
       
    77     void Clear( const TRect& aRect, const TRgb& aColor );
       
    78         
       
    79     /**
       
    80      * Copies area from another bitmap to this one.
       
    81      * @param aRect area to copy.
       
    82      * @param aBitmap source bitmap.
       
    83      */
       
    84     void BitBlt( const TRect& aRect, CHuiModifiableBitmap& aBitmap );
       
    85     
       
    86     /**
       
    87      * Combines source and mask bitmap to this 16MA bitmap.
       
    88      * @param aSrc bitmap.
       
    89      * @param aSrcMask mask bitmap.
       
    90      */
       
    91     void Combine( const CFbsBitmap& aSrc, const CFbsBitmap& aSrcMask );
       
    92     
       
    93     /**
       
    94      * Combines source and mask bitmap to this 16MA bitmap.
       
    95      * @para aPos position of bitmap.
       
    96      * @param aSrc bitmap.
       
    97      * @param aSrcMask mask bitmap.
       
    98      */
       
    99     void Combine( const TPoint& aPos, const CFbsBitmap& aSrc, const CFbsBitmap& aSrcMask );
       
   100     
       
   101     /**
       
   102      * Combines gray 256 mask to this gray 256 bitmap. 
       
   103      * It's expected that aMask contains only 0 or 255 values.
       
   104      * @param aRect rect to combine.
       
   105      * @param aMask gray 256 bitmap.
       
   106      */
       
   107     void CombineMasks( const TRect& aRect, CFbsBitmap* aMask );
       
   108     
       
   109     /**
       
   110      * Extracts alpha from 16MA source to this EGray256 bitmap.
       
   111      * @param aSource source bitmap.
       
   112      */
       
   113     void ExtractAlpha( CHuiModifiableBitmap& aSource );
       
   114     
       
   115     /**
       
   116      * Extracts color from 16MA source to this EColor64K/EColor16MU bitmap.
       
   117      * @param aSource source bitmap.
       
   118      */
       
   119     void ExtractColor( CHuiModifiableBitmap& aSource );
       
   120         
       
   121 private:
       
   122     void ConstructL( const TSize& aSize, TDisplayMode aMode );
       
   123     void ConstructL( CFbsBitmap& aBitmap );
       
   124 
       
   125     template<class Converter>
       
   126     static void DoExtractColor( CFbsBitmap* aTarget, CFbsBitmap* aSource );
       
   127     
       
   128     struct Convert16MA_16MU
       
   129         {    
       
   130         inline static TUint32 Convert( TUint32 aPixel );
       
   131         };
       
   132     struct Convert16MA_64K
       
   133         {
       
   134         inline static TUint32 Convert( TUint32 aPixel );
       
   135         };
       
   136     
       
   137 private:
       
   138     /**
       
   139      * Boolean value indicating if iBitmap is owned by this class.
       
   140      */
       
   141     TBool iOwnBitmap;
       
   142     /**
       
   143      * Bitmap instance. Ownership depends on value of iOwnBitmap.
       
   144      */
       
   145     CFbsBitmap* iBitmap;
       
   146     /**
       
   147      * Bitmap device.
       
   148      * Own.
       
   149      */
       
   150     CFbsBitmapDevice* iDevice;
       
   151     /**
       
   152      * Graphics context.
       
   153      * Own.
       
   154      */
       
   155     CFbsBitGc* iGc;
       
   156     };
       
   157 
       
   158 CHuiTextureAnimationState* CHuiTextureAnimationState::NewL(
       
   159         TInt aTextureGroupId, const TDesC& aImageFile, TInt aFrameCount )
       
   160     {
       
   161     CHuiTextureAnimationState* self = new (ELeave) CHuiTextureAnimationState;
       
   162     CleanupStack::PushL( self );
       
   163     self->ConstructL( aTextureGroupId, aImageFile, aFrameCount );
       
   164     CleanupStack::Pop( self );
       
   165     return self;
       
   166     }
       
   167 
       
   168 CHuiTextureAnimationState::~CHuiTextureAnimationState()
       
   169     {
       
   170     HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Destroyed"), this );
       
   171     delete iFile;
       
   172     
       
   173     delete iPrevFrame;
       
   174     delete iPrevFrameMask;
       
   175     }
       
   176 
       
   177 TInt CHuiTextureAnimationState::OwnerTextureGroupId() const
       
   178     {
       
   179     return iTextureGroupId;
       
   180     }
       
   181     
       
   182 TBool CHuiTextureAnimationState::CheckIfCanProduce( 
       
   183         const TDesC& aImageFile, TInt aFrameNumber, TInt aFrameCount ) const
       
   184     {
       
   185     aFrameNumber--;
       
   186     
       
   187     TBool ok = ( aFrameCount == iFrameCount ) && 
       
   188                ( iFrame <= aFrameNumber ) &&
       
   189                !aImageFile.CompareF( *iFile );
       
   190                
       
   191     return ok; 
       
   192     }
       
   193 
       
   194 TInt CHuiTextureAnimationState::GetNextFrameNumber() const
       
   195     {
       
   196     return ( iFrame + 1 );
       
   197     }
       
   198 
       
   199 void CHuiTextureAnimationState::OfferNextFrameInfo( 
       
   200         const TFrameInfo& aFrameInfo )
       
   201     {
       
   202     if ( iFrame == KErrNotFound )
       
   203         {
       
   204         // First frame defines size of all frames; subsequent frames
       
   205         // are deltas to first frame.
       
   206         iSize = aFrameInfo.iOverallSizeInPixels;
       
   207         }
       
   208         
       
   209     iNextSubFrameRect = aFrameInfo.iFrameCoordsInPixels;
       
   210     iNextSubFrameBgColor = aFrameInfo.iBackgroundColor;
       
   211     
       
   212     if ( aFrameInfo.iFlags & TFrameInfo::ERestoreToPrevious )
       
   213         {
       
   214         iNextSubFrameDisposalAction = ERestoreToPrevious;
       
   215         }
       
   216     else if ( aFrameInfo.iFlags & TFrameInfo::ELeaveInPlace )
       
   217         {
       
   218         // The variable name "'ELeave'InPlace" will cause FALSE positive in CodeScanners "Leave scan"
       
   219         iNextSubFrameDisposalAction = ELeaveInPlace;
       
   220         }
       
   221     else if ( aFrameInfo.iFlags & TFrameInfo::ERestoreToBackground )
       
   222         {
       
   223         iNextSubFrameDisposalAction = ERestoreToBackgroundColour;
       
   224         }
       
   225     else
       
   226         {
       
   227         iNextSubFrameDisposalAction = EUnspecified;
       
   228         }
       
   229         
       
   230     // If EAlphaChannel flag is on, EGray256 style alpha is available.
       
   231     // If ETransparencyPossible flag is on, just EGray2.
       
   232     iNextSubFrameHasAlpha = aFrameInfo.iFlags & TFrameInfo::EAlphaChannel;
       
   233     }
       
   234 
       
   235 TSize CHuiTextureAnimationState::OverallSize() const
       
   236     {
       
   237     return iSize;
       
   238     }
       
   239 
       
   240 void CHuiTextureAnimationState::ProduceNextFrameL(
       
   241         CFbsBitmap*& aNewFrame,
       
   242         CFbsBitmap*& aNewFrameMask,
       
   243         CFbsBitmap* aSubFrame,
       
   244         CFbsBitmap* aSubFrameMask )
       
   245     {
       
   246     HUI_DEBUG2(_L("CHuiTextureAnimationState(%x): Produce next %d"), 
       
   247         this, iFrame + 1 );
       
   248     HUI_DEBUG4(_L("CHuiTextureAnimationState(%x): pf:%x pfm:%x d:%d"), 
       
   249         this, iPrevFrame, iPrevFrameMask, iNextSubFrameDisposalAction );
       
   250     aNewFrame = NULL;
       
   251     aNewFrameMask = NULL;
       
   252     CheckSubFrameL( aSubFrame, aSubFrameMask );
       
   253     
       
   254     if ( iFrame == KErrNotFound )
       
   255         {
       
   256         // Check if previous frames can be reused.
       
   257         const TSize frameSize = OverallSize();
       
   258         if ( iPrevFrame )
       
   259             {
       
   260             if ( iPrevFrame->SizeInPixels() != frameSize ||
       
   261                  iPrevFrame->DisplayMode() != aSubFrame->DisplayMode() )
       
   262                 {
       
   263                 delete iPrevFrame;
       
   264                 iPrevFrame = NULL;
       
   265                 }
       
   266             }
       
   267         if ( iPrevFrameMask && aSubFrameMask )
       
   268             {
       
   269             if ( iPrevFrameMask->SizeInPixels() != frameSize ||
       
   270                  iPrevFrameMask->DisplayMode() != aSubFrameMask->DisplayMode() )
       
   271                 {
       
   272                 delete iPrevFrameMask;
       
   273                 iPrevFrameMask = NULL;
       
   274                 }
       
   275             }
       
   276         else
       
   277             {
       
   278             delete iPrevFrameMask;
       
   279             iPrevFrameMask = NULL;
       
   280             }
       
   281 
       
   282         if ( !iNextSubFrameHasAlpha || !aSubFrameMask )
       
   283             {
       
   284             HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Quick 1st"), this );
       
   285             QuickProduceFirstFrameAndGeneratePreviousL( 
       
   286                 aNewFrame, aNewFrameMask, 
       
   287                 aSubFrame, aSubFrameMask );
       
   288             }
       
   289         else
       
   290             {           
       
   291             HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Slow 1st"), this );
       
   292             ProduceFirstFrameAndGeneratePreviousL( 
       
   293                 aNewFrame, aNewFrameMask, 
       
   294                 aSubFrame, aSubFrameMask );
       
   295             }
       
   296             
       
   297         if ( !aNewFrameMask )
       
   298             {
       
   299             // So mask was not needed - get rid of previous (if any)
       
   300             delete iPrevFrameMask;
       
   301             iPrevFrameMask = NULL;
       
   302             }
       
   303         }
       
   304     else
       
   305         {
       
   306         if ( !iPrevFrame )
       
   307             {
       
   308             User::Leave( KErrNotSupported );
       
   309             }
       
   310             
       
   311         if ( !iNextSubFrameHasAlpha || 
       
   312              !aSubFrameMask || 
       
   313              !iPrevFrameMask )
       
   314             {
       
   315             HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Quick 2-"), this );
       
   316             QuickProduceNextFrameAndUpdatePreviousL(
       
   317                 aNewFrame, aNewFrameMask,
       
   318                 aSubFrame, aSubFrameMask );
       
   319             }
       
   320         else
       
   321             {
       
   322             HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Slow 2-"), this );
       
   323             ProduceNextFrameAndUpdatePreviousL(
       
   324                 aNewFrame, aNewFrameMask,
       
   325                 aSubFrame, aSubFrameMask );
       
   326             }
       
   327         }
       
   328         
       
   329     iFrame++; // Go to next frame
       
   330         
       
   331     if ( iFrame == ( iFrameCount - 1 ) )
       
   332         {
       
   333         // Reset back to the beginning
       
   334         iFrame = KErrNotFound;
       
   335         }
       
   336     HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Produce next done"), this );        
       
   337     }
       
   338 
       
   339 void CHuiTextureAnimationState::ProceedWithoutNextFrameL(
       
   340         CFbsBitmap* aSubFrame,
       
   341         CFbsBitmap* aSubFrameMask )
       
   342     {
       
   343     // This could be optimized. However, if this method is called,
       
   344     // it means that client is anyway using the API in very performance
       
   345     // inefficient way, i.e. asking system to load random frames rather
       
   346     // than in sequence 0, 1, ..., N.
       
   347     
       
   348     CFbsBitmap* frame = NULL;
       
   349     CFbsBitmap* frameMask = NULL;
       
   350     
       
   351     ProduceNextFrameL( frame, frameMask, aSubFrame, aSubFrameMask );
       
   352     
       
   353     delete frame;
       
   354     delete frameMask;
       
   355     }
       
   356 
       
   357 CHuiTextureAnimationState::CHuiTextureAnimationState()
       
   358     {
       
   359     HUI_DEBUG1(_L("CHuiTextureAnimationState(%x): Created"), this );
       
   360     }
       
   361     
       
   362 void CHuiTextureAnimationState::ConstructL( 
       
   363         TInt aTextureGroupId, const TDesC& aImageFile, TInt aFrameCount )
       
   364     {
       
   365     iTextureGroupId = aTextureGroupId;
       
   366     iFile = aImageFile.AllocL();
       
   367     iFrame = KErrNotFound;
       
   368     iFrameCount = aFrameCount;
       
   369     }
       
   370 
       
   371 void CHuiTextureAnimationState::ProduceFirstFrameAndGeneratePreviousL(
       
   372         CFbsBitmap*& aNewFrame,
       
   373         CFbsBitmap*& aNewFrameMask,
       
   374         CFbsBitmap* aSubFrame,
       
   375         CFbsBitmap* aSubFrameMask )
       
   376     {
       
   377     if ( !aSubFrameMask )
       
   378         {
       
   379         User::Leave( KErrNotSupported );
       
   380         }
       
   381         
       
   382     const TSize frameSize = OverallSize();
       
   383 
       
   384     // Make scratch
       
   385     CHuiModifiableBitmap* scratch = 
       
   386         CHuiModifiableBitmap::NewLC( frameSize, EColor16MA );
       
   387     scratch->Combine( iNextSubFrameRect.iTl, *aSubFrame, *aSubFrameMask );
       
   388                         
       
   389     // Extract new frame & mask
       
   390     CHuiModifiableBitmap* frame = 
       
   391         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   392     frame->ExtractColor( *scratch );
       
   393 
       
   394     CHuiModifiableBitmap* frameMask = 
       
   395         CHuiModifiableBitmap::NewLC( frameSize, EGray256 );
       
   396     frameMask->ExtractAlpha( *scratch );
       
   397             
       
   398     // Create prev frame & mask
       
   399     CHuiModifiableBitmap* prevFrame = 
       
   400         iPrevFrame ?
       
   401         CHuiModifiableBitmap::NewLC( *iPrevFrame ) :
       
   402         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   403 
       
   404     CHuiModifiableBitmap* prevFrameMask = 
       
   405         iPrevFrameMask ?
       
   406             CHuiModifiableBitmap::NewLC( *iPrevFrameMask ) :
       
   407             CHuiModifiableBitmap::NewLC( frameSize, EGray256 );
       
   408 
       
   409     prevFrame->Clear( BitmapClearColor() );
       
   410     prevFrameMask->Clear( MaskClearColor() );
       
   411     
       
   412     switch ( iNextSubFrameDisposalAction )
       
   413         {                    
       
   414         case ELeaveInPlace:
       
   415             prevFrame->BitBlt( iNextSubFrameRect, *frame );
       
   416             prevFrameMask->BitBlt( iNextSubFrameRect, *frameMask );
       
   417             break;
       
   418         
       
   419         case ERestoreToPrevious:
       
   420         case EUnspecified:        
       
   421         case ERestoreToBackgroundColour:
       
   422         default:
       
   423             break;
       
   424         }
       
   425 
       
   426     // Cleanup
       
   427     iPrevFrameMask = prevFrameMask->ReleaseBitmap();
       
   428     CleanupStack::PopAndDestroy( prevFrameMask );
       
   429             
       
   430     iPrevFrame = prevFrame->ReleaseBitmap();
       
   431     CleanupStack::PopAndDestroy( prevFrame );
       
   432             
       
   433     aNewFrameMask = frameMask->ReleaseBitmap();
       
   434     CleanupStack::PopAndDestroy( frameMask );
       
   435                 
       
   436     aNewFrame = frame->ReleaseBitmap();              
       
   437     CleanupStack::PopAndDestroy( frame );
       
   438     CleanupStack::PopAndDestroy( scratch ); 
       
   439     }
       
   440 
       
   441 void CHuiTextureAnimationState::ProduceNextFrameAndUpdatePreviousL(
       
   442         CFbsBitmap*& aNewFrame,
       
   443         CFbsBitmap*& aNewFrameMask,
       
   444         CFbsBitmap* aSubFrame,
       
   445         CFbsBitmap* aSubFrameMask )
       
   446     {
       
   447     if ( !aSubFrameMask || !iPrevFrameMask )
       
   448         {
       
   449         User::Leave( KErrNotSupported );
       
   450         }
       
   451 
       
   452     const TSize frameSize = OverallSize();
       
   453             
       
   454     // Make previous state and blit new subframe on top of that
       
   455     CHuiModifiableBitmap* scratch = 
       
   456         CHuiModifiableBitmap::NewLC( frameSize, EColor16MA );
       
   457     scratch->Combine( *iPrevFrame, *iPrevFrameMask );
       
   458             
       
   459     scratch->Context().BitBltMasked(
       
   460         iNextSubFrameRect.iTl,
       
   461         aSubFrame,
       
   462         TRect( aSubFrame->SizeInPixels() ),
       
   463         aSubFrameMask,
       
   464         ETrue );
       
   465             
       
   466     // Extract new frame & mask
       
   467     CHuiModifiableBitmap* frame = 
       
   468         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   469     frame->ExtractColor( *scratch );
       
   470             
       
   471     CHuiModifiableBitmap* frameMask =
       
   472         CHuiModifiableBitmap::NewLC( frameSize, EGray256 );
       
   473     frameMask->ExtractAlpha( *scratch );
       
   474             
       
   475     // Update previous frame & mask
       
   476     CHuiModifiableBitmap* prevFrame = 
       
   477         CHuiModifiableBitmap::NewLC( *iPrevFrame );
       
   478     CHuiModifiableBitmap* prevFrameMask =
       
   479         CHuiModifiableBitmap::NewLC( *iPrevFrameMask );
       
   480         
       
   481     switch ( iNextSubFrameDisposalAction )
       
   482         {                    
       
   483         case EUnspecified:
       
   484         case ERestoreToBackgroundColour:
       
   485             prevFrameMask->Clear( iNextSubFrameRect, MaskClearColor() );
       
   486             prevFrame->Clear( iNextSubFrameRect, BitmapClearColor() );
       
   487             break;
       
   488                     
       
   489         case ELeaveInPlace:
       
   490             prevFrame->BitBlt( iNextSubFrameRect, *frame );
       
   491             prevFrameMask->BitBlt( iNextSubFrameRect, *frameMask );
       
   492             break;
       
   493             
       
   494         case ERestoreToPrevious:
       
   495         default:
       
   496             break;
       
   497             }
       
   498         
       
   499     CleanupStack::PopAndDestroy( prevFrameMask );
       
   500     CleanupStack::PopAndDestroy( prevFrame );
       
   501 
       
   502     aNewFrame = frame->ReleaseBitmap();
       
   503     aNewFrameMask = frameMask->ReleaseBitmap();
       
   504             
       
   505     CleanupStack::PopAndDestroy( frameMask );
       
   506     CleanupStack::PopAndDestroy( frame );
       
   507                         
       
   508     CleanupStack::PopAndDestroy( scratch );
       
   509     }
       
   510 
       
   511 void CHuiTextureAnimationState::QuickProduceFirstFrameAndGeneratePreviousL(
       
   512         CFbsBitmap*& aNewFrame,
       
   513         CFbsBitmap*& aNewFrameMask,
       
   514         CFbsBitmap* aSubFrame,
       
   515         CFbsBitmap* aSubFrameMask )
       
   516     {
       
   517     const TSize frameSize = OverallSize();
       
   518     const TBool hasAlpha = ( aSubFrameMask != NULL );
       
   519         
       
   520     const TBool exactMatch = 
       
   521         ( TRect( frameSize ) == iNextSubFrameRect ) &&
       
   522         ( aSubFrame->SizeInPixels() == frameSize );
       
   523                             
       
   524     // Produce new frame & mask
       
   525     CHuiModifiableBitmap* frame = 
       
   526         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   527     
       
   528     CHuiModifiableBitmap* frameMask = NULL;
       
   529     if ( hasAlpha )
       
   530         {           
       
   531         frameMask = CHuiModifiableBitmap::NewLC( frameSize, EGray256 );
       
   532         
       
   533         frame->Clear( BitmapClearColor() );
       
   534         if ( !exactMatch )
       
   535             {
       
   536             frameMask->Clear( MaskClearColor() );
       
   537             }
       
   538         
       
   539         frame->Context().BitBltMasked( 
       
   540             iNextSubFrameRect.iTl, 
       
   541             aSubFrame, 
       
   542             TRect( aSubFrame->SizeInPixels() ), 
       
   543             aSubFrameMask, 
       
   544             ETrue );
       
   545         frameMask->Context().BitBlt( iNextSubFrameRect.iTl, aSubFrameMask );
       
   546         }
       
   547     else
       
   548         {
       
   549         if ( !exactMatch )
       
   550             {
       
   551             frame->Clear( iNextSubFrameBgColor );
       
   552             }
       
   553         frame->Context().BitBlt( iNextSubFrameRect.iTl, aSubFrame );
       
   554         }
       
   555                 
       
   556     // Create prev frame & mask
       
   557     CHuiModifiableBitmap* prevFrame = 
       
   558         iPrevFrame ?
       
   559         CHuiModifiableBitmap::NewLC( *iPrevFrame ) :
       
   560         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   561 
       
   562     CHuiModifiableBitmap* prevFrameMask = NULL;
       
   563     if ( hasAlpha )
       
   564         {
       
   565         prevFrameMask = 
       
   566             iPrevFrameMask ?
       
   567                 CHuiModifiableBitmap::NewLC( *iPrevFrameMask ) :
       
   568                 CHuiModifiableBitmap::NewLC( frameSize, EGray256 );
       
   569         }
       
   570 
       
   571     const TRgb clearColor = 
       
   572         hasAlpha ? 
       
   573             BitmapClearColor() : 
       
   574             iNextSubFrameBgColor;
       
   575     prevFrame->Clear( clearColor );        
       
   576     if ( prevFrameMask )
       
   577         {
       
   578         prevFrameMask->Clear( MaskClearColor() );
       
   579         }
       
   580     
       
   581     switch ( iNextSubFrameDisposalAction )
       
   582         {                    
       
   583         case ELeaveInPlace:
       
   584             prevFrame->BitBlt( iNextSubFrameRect, *frame );
       
   585             if ( prevFrameMask )
       
   586                 {
       
   587                 prevFrameMask->BitBlt( iNextSubFrameRect, *frameMask );
       
   588                 }
       
   589             break;
       
   590         
       
   591         case ERestoreToPrevious:
       
   592         case EUnspecified:        
       
   593         case ERestoreToBackgroundColour:
       
   594         default:
       
   595             break;
       
   596         }
       
   597 
       
   598     // Cleanup
       
   599     if ( prevFrameMask )
       
   600         {
       
   601         iPrevFrameMask = prevFrameMask->ReleaseBitmap();
       
   602         CleanupStack::PopAndDestroy( prevFrameMask );
       
   603         }       
       
   604             
       
   605     iPrevFrame = prevFrame->ReleaseBitmap();
       
   606     CleanupStack::PopAndDestroy( prevFrame );
       
   607             
       
   608     if ( frameMask )
       
   609         {
       
   610         aNewFrameMask = frameMask->ReleaseBitmap();
       
   611         CleanupStack::PopAndDestroy( frameMask );
       
   612         }
       
   613                 
       
   614     aNewFrame = frame->ReleaseBitmap();                    
       
   615     CleanupStack::PopAndDestroy( frame );     
       
   616     }
       
   617 
       
   618 void CHuiTextureAnimationState::QuickProduceNextFrameAndUpdatePreviousL(
       
   619         CFbsBitmap*& aNewFrame,
       
   620         CFbsBitmap*& aNewFrameMask,
       
   621         CFbsBitmap* aSubFrame,
       
   622         CFbsBitmap* aSubFrameMask )
       
   623     {
       
   624     const TSize frameSize = OverallSize();
       
   625     const TBool hasAlpha = aSubFrameMask != NULL;
       
   626 
       
   627     // Produce frame & frame mask
       
   628     CHuiModifiableBitmap* frame = 
       
   629         CHuiModifiableBitmap::NewLC( frameSize, aSubFrame->DisplayMode() );
       
   630     frame->Context().BitBlt( TPoint(), iPrevFrame );
       
   631     
       
   632     CHuiModifiableBitmap* frameMask = NULL;
       
   633     if ( iPrevFrameMask )
       
   634         {
       
   635         frameMask =
       
   636             CHuiModifiableBitmap::NewLC( frameSize, EGray256 );        
       
   637         frameMask->Context().BitBlt( TPoint(), iPrevFrameMask );
       
   638         }
       
   639     
       
   640     if ( hasAlpha )
       
   641         {
       
   642         frame->Context().SetBrushStyle( CGraphicsContext::ENullBrush );
       
   643         frame->Context().BitBltMasked( 
       
   644             iNextSubFrameRect.iTl, 
       
   645             aSubFrame, 
       
   646             TRect( aSubFrame->SizeInPixels() ), 
       
   647             aSubFrameMask, 
       
   648             ETrue );
       
   649 
       
   650         if ( iPrevFrameMask )
       
   651             {                
       
   652             // Merge masks:
       
   653             // prev: 255 sub: 255 frame: 255
       
   654             // prev: 255 sub: 0   frame: 255
       
   655             // prev: 0   sub: 255 frame: 255
       
   656             // prev: 0   sub: 0   frame: 0
       
   657             // => OR style behaviour works
       
   658             frameMask->CombineMasks( iNextSubFrameRect, aSubFrameMask );
       
   659             }
       
   660         }
       
   661     else
       
   662         {
       
   663         frame->Context().BitBlt( iNextSubFrameRect.iTl, aSubFrame );
       
   664         
       
   665         if ( iPrevFrameMask )
       
   666             {
       
   667             frameMask->Clear( iNextSubFrameRect, MaskOpaqueColor() );
       
   668             }
       
   669         }
       
   670     
       
   671     // Update previous frame & mask
       
   672     CHuiModifiableBitmap* prevFrame = 
       
   673         CHuiModifiableBitmap::NewLC( *iPrevFrame );
       
   674     CHuiModifiableBitmap* prevFrameMask = NULL;
       
   675     if ( iPrevFrameMask )
       
   676         {
       
   677         prevFrameMask =
       
   678             CHuiModifiableBitmap::NewLC( *iPrevFrameMask );
       
   679         }
       
   680         
       
   681     switch ( iNextSubFrameDisposalAction )
       
   682         {   
       
   683         case EUnspecified:                         
       
   684         case ERestoreToBackgroundColour:
       
   685             if ( prevFrameMask )
       
   686                 {
       
   687                 prevFrameMask->Clear( iNextSubFrameRect, MaskClearColor() );
       
   688                 prevFrame->Clear( iNextSubFrameRect, BitmapClearColor() );
       
   689                 }
       
   690             else
       
   691                 {
       
   692                 prevFrame->Clear( iNextSubFrameRect, iNextSubFrameBgColor );
       
   693                 }    
       
   694             break;
       
   695                     
       
   696         case ELeaveInPlace:
       
   697             prevFrame->BitBlt( iNextSubFrameRect, *frame );
       
   698             if ( prevFrameMask )
       
   699                 {
       
   700                 prevFrameMask->BitBlt( iNextSubFrameRect, *frameMask );
       
   701                 }
       
   702             break;
       
   703             
       
   704         case ERestoreToPrevious:
       
   705         default:
       
   706             break;
       
   707         }
       
   708 
       
   709     if ( prevFrameMask )
       
   710         {
       
   711         CleanupStack::PopAndDestroy( prevFrameMask );
       
   712         }
       
   713     CleanupStack::PopAndDestroy( prevFrame );
       
   714 
       
   715     aNewFrame = frame->ReleaseBitmap();
       
   716     if ( frameMask )
       
   717         {
       
   718         aNewFrameMask = frameMask->ReleaseBitmap();
       
   719         CleanupStack::PopAndDestroy( frameMask );
       
   720         }
       
   721     CleanupStack::PopAndDestroy( frame );        
       
   722     }
       
   723 
       
   724 inline TRgb CHuiTextureAnimationState::BitmapClearColor()
       
   725     {
       
   726     return TRgb(0,0,0); // black
       
   727     }
       
   728     
       
   729 inline TRgb CHuiTextureAnimationState::MaskClearColor()
       
   730     {
       
   731     return TRgb::Gray256( 0 ); // transparent for EGray256 masks
       
   732     }
       
   733 
       
   734 inline TRgb CHuiTextureAnimationState::MaskOpaqueColor()
       
   735     {
       
   736     return TRgb::Gray256( 255 ); // opaque for EGray256 masks
       
   737     }
       
   738 
       
   739 void CHuiTextureAnimationState::CheckSubFrameL( 
       
   740         CFbsBitmap* aSubFrame, 
       
   741         CFbsBitmap* aSubFrameMask )
       
   742     {
       
   743     if ( !aSubFrame )
       
   744         {
       
   745         User::Leave( KErrNotSupported );
       
   746         }    
       
   747             
       
   748     // aSubFrame display mode should be either 64K or 16MU,
       
   749     // but let's check it.
       
   750     const TDisplayMode subFrameMode = aSubFrame->DisplayMode();
       
   751     if ( ( subFrameMode != EColor64K && subFrameMode != EColor16MU ) ||
       
   752          aSubFrame->IsCompressedInRAM() )
       
   753         {
       
   754         User::Leave( KErrNotSupported );
       
   755         }
       
   756         
       
   757     // aSubFrameMask should be EGray256
       
   758     if ( aSubFrameMask )
       
   759         {
       
   760         if ( ( aSubFrameMask->DisplayMode() != EGray256 ) ||
       
   761              aSubFrame->IsCompressedInRAM() )
       
   762             {
       
   763             User::Leave( KErrNotSupported );
       
   764             }
       
   765         }
       
   766     }
       
   767 
       
   768 
       
   769 
       
   770 //
       
   771 // CHuiModifiableBitmap implementation
       
   772 //
       
   773 
       
   774 
       
   775 CHuiModifiableBitmap* CHuiModifiableBitmap::NewLC( 
       
   776         const TSize& aSize, TDisplayMode aMode )
       
   777     {
       
   778     CHuiModifiableBitmap* self = new (ELeave) CHuiModifiableBitmap;
       
   779     CleanupStack::PushL( self );
       
   780     self->ConstructL( aSize, aMode );
       
   781     return self;
       
   782     }
       
   783     
       
   784 CHuiModifiableBitmap* CHuiModifiableBitmap::NewLC( 
       
   785         CFbsBitmap& aBitmap )
       
   786     {
       
   787     CHuiModifiableBitmap* self = new (ELeave) CHuiModifiableBitmap;
       
   788     CleanupStack::PushL( self );
       
   789     self->ConstructL( aBitmap );
       
   790     return self;    
       
   791     }
       
   792 
       
   793 CHuiModifiableBitmap::~CHuiModifiableBitmap()
       
   794     {
       
   795     delete iGc;
       
   796     delete iDevice;
       
   797     if ( iOwnBitmap )
       
   798         {
       
   799         delete iBitmap;
       
   800         }
       
   801     }
       
   802 
       
   803 CFbsBitGc& CHuiModifiableBitmap::Context()
       
   804     {
       
   805     return *iGc;
       
   806     }
       
   807     
       
   808 CFbsBitmap* CHuiModifiableBitmap::ReleaseBitmap()
       
   809     {
       
   810     delete iGc;
       
   811     iGc = NULL;
       
   812     delete iDevice;
       
   813     iDevice = NULL;
       
   814     CFbsBitmap* bitmap = iBitmap;
       
   815     iBitmap = NULL;
       
   816     return bitmap;
       
   817     }
       
   818 
       
   819 void CHuiModifiableBitmap::Clear( const TRgb& aColor )
       
   820     {
       
   821     iGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   822     iGc->SetBrushColor( aColor );
       
   823     iGc->Clear();
       
   824     iGc->SetBrushStyle( CGraphicsContext::ENullBrush );
       
   825     }
       
   826 
       
   827 void CHuiModifiableBitmap::Clear( const TRect& aRect, const TRgb& aColor )
       
   828     {
       
   829     iGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   830     iGc->SetBrushColor( aColor );
       
   831     iGc->Clear( aRect );
       
   832     iGc->SetBrushStyle( CGraphicsContext::ENullBrush );    
       
   833     }
       
   834 
       
   835 void CHuiModifiableBitmap::BitBlt( 
       
   836         const TRect& aRect, CHuiModifiableBitmap& aBitmap )
       
   837     {
       
   838     if ( iGc && aBitmap.iBitmap && iBitmap )
       
   839         {
       
   840         // Copy area from one bitmap to another. Same size expected.
       
   841         iGc->BitBlt( aRect.iTl, aBitmap.iBitmap, aRect );
       
   842         }
       
   843     }
       
   844 
       
   845 void CHuiModifiableBitmap::Combine( 
       
   846         const CFbsBitmap& aSrc, const CFbsBitmap& aSrcMask )
       
   847     {
       
   848     if ( iBitmap )
       
   849         {
       
   850         Combine( TPoint(), aSrc, aSrcMask );
       
   851         }
       
   852     }
       
   853 
       
   854 void CHuiModifiableBitmap::Combine( 
       
   855         const TPoint& aPos, const CFbsBitmap& aSrc, const CFbsBitmap& aSrcMask )
       
   856     {
       
   857     if ( iBitmap )
       
   858         {
       
   859         // Clear with transparent
       
   860         iGc->SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha );
       
   861         iGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   862         iGc->SetBrushColor( TRgb( 0, 0, 0, 0 ) );
       
   863         iGc->Clear();
       
   864         iGc->SetBrushStyle( CGraphicsContext::ENullBrush );    
       
   865         iGc->SetDrawMode( CGraphicsContext::EDrawModePEN );
       
   866         
       
   867         // Blit masked
       
   868         iGc->BitBltMasked( 
       
   869             aPos, 
       
   870             &aSrc, 
       
   871             TRect( aSrc.SizeInPixels() ), 
       
   872             &aSrcMask, 
       
   873             ETrue );
       
   874         }
       
   875     }
       
   876 
       
   877 void CHuiModifiableBitmap::CombineMasks( 
       
   878         const TRect& aRect, 
       
   879         CFbsBitmap* aMask )
       
   880     {    
       
   881     if ( iBitmap )
       
   882         {
       
   883         // this is EGray256, aMask is EGray256
       
   884         TRect targetRect( aRect );
       
   885         targetRect.Intersection( iBitmap->SizeInPixels() );
       
   886         targetRect.Intersection( TRect( aRect.iTl, aMask->SizeInPixels() ) );
       
   887         
       
   888         if ( targetRect.IsEmpty() )
       
   889             {
       
   890             // nothing to draw
       
   891             return;
       
   892             }
       
   893     
       
   894         // Starting target & source point and size to draw
       
   895         const TPoint targetPoint = targetRect.iTl;
       
   896         const TPoint sourcePoint = targetRect.iTl - aRect.iTl;
       
   897         const TSize size = targetRect.Size();
       
   898 
       
   899         // Go through all pixels using OR operation.
       
   900         // As aMask contains only 0 or 255 values, it is
       
   901         // sufficient to combine these masks.
       
   902         TBitmapUtil source(aMask);
       
   903         TBitmapUtil target(iBitmap);
       
   904     
       
   905         source.Begin( sourcePoint );
       
   906         target.Begin( targetPoint );
       
   907     
       
   908         for( TInt y = 0; y < size.iHeight; ++y )
       
   909             {
       
   910             source.SetPos( sourcePoint + TPoint(0,y) );
       
   911             target.SetPos( targetPoint + TPoint(0,y) );
       
   912             
       
   913             for( TInt x = 0; x < size.iWidth; ++x )
       
   914                 {
       
   915                 TUint32 pixel = source.GetPixel();
       
   916                 if ( pixel )
       
   917                     {
       
   918                     target.SetPixel( target.GetPixel() | pixel );
       
   919                     }
       
   920                 
       
   921                 target.IncXPos();
       
   922                 source.IncXPos();
       
   923                 }
       
   924             }
       
   925             
       
   926         target.End();
       
   927         source.End();        
       
   928         }    
       
   929     }
       
   930 
       
   931 void CHuiModifiableBitmap::ExtractAlpha( CHuiModifiableBitmap& aSource )
       
   932     {
       
   933     if ( iBitmap && aSource.iBitmap )
       
   934         {
       
   935         // this is EGray256, aSource is 16MA
       
   936         
       
   937         TBitmapUtil source(aSource.iBitmap);
       
   938         TBitmapUtil target(iBitmap);
       
   939     
       
   940         source.Begin( TPoint() );
       
   941         target.Begin( TPoint() );
       
   942     
       
   943         const TSize size( iBitmap->SizeInPixels() );
       
   944         for( TInt y = 0; y < size.iHeight; ++y )
       
   945             {
       
   946             source.SetPos( TPoint( 0, y) );
       
   947             target.SetPos( TPoint( 0, y) );
       
   948             
       
   949             for( TInt x = 0; x < size.iWidth; ++x )
       
   950                 {
       
   951                 target.SetPixel( source.GetPixel() >> 24 );
       
   952                 
       
   953                 target.IncXPos();
       
   954                 source.IncXPos();
       
   955                 }
       
   956             }
       
   957             
       
   958         target.End();
       
   959         source.End();        
       
   960         }
       
   961     }
       
   962    
       
   963 void CHuiModifiableBitmap::ExtractColor( CHuiModifiableBitmap& aSource )
       
   964     {
       
   965     // this is color, aSource is 16MA
       
   966     
       
   967     if ( iBitmap && aSource.iBitmap )
       
   968         {
       
   969         TDisplayMode mode = iBitmap->DisplayMode();
       
   970         if ( mode == EColor64K )
       
   971             {
       
   972             DoExtractColor<Convert16MA_64K>( iBitmap, aSource.iBitmap );
       
   973             }
       
   974         else if ( mode == EColor16MU )
       
   975             {
       
   976             DoExtractColor<Convert16MA_16MU>( iBitmap, aSource.iBitmap );
       
   977             }
       
   978         }
       
   979     }
       
   980     
       
   981 void CHuiModifiableBitmap::ConstructL( const TSize& aSize, TDisplayMode aMode )
       
   982     {
       
   983     iOwnBitmap = ETrue;
       
   984     iBitmap = new (ELeave) CFbsBitmap;
       
   985     User::LeaveIfError( iBitmap->Create( aSize, aMode ) );
       
   986     
       
   987     iDevice = CFbsBitmapDevice::NewL( iBitmap );
       
   988     iDevice->CreateContext( iGc );
       
   989     User::LeaveIfNull( iGc );        
       
   990     }
       
   991 
       
   992 void CHuiModifiableBitmap::ConstructL( CFbsBitmap& aBitmap )
       
   993     {
       
   994     iOwnBitmap = EFalse;
       
   995     iBitmap = &aBitmap;
       
   996     
       
   997     iDevice = CFbsBitmapDevice::NewL( iBitmap );
       
   998     iDevice->CreateContext( iGc );
       
   999     User::LeaveIfNull( iGc );        
       
  1000     }
       
  1001 
       
  1002 template<typename Converter>
       
  1003 void CHuiModifiableBitmap::DoExtractColor( 
       
  1004         CFbsBitmap* aTarget, CFbsBitmap* aSource )
       
  1005     {
       
  1006     TBitmapUtil source(aSource);
       
  1007     TBitmapUtil target(aTarget);
       
  1008     
       
  1009     source.Begin( TPoint() );
       
  1010     target.Begin( TPoint() );
       
  1011     
       
  1012     const TSize size( aTarget->SizeInPixels() );
       
  1013     for(TInt y = 0; y < size.iHeight; ++y)
       
  1014         {
       
  1015         source.SetPos(TPoint(0, y));
       
  1016         target.SetPos(TPoint(0, y));
       
  1017             
       
  1018         for(TInt x = 0; x < size.iWidth; ++x)
       
  1019             {
       
  1020             target.SetPixel( Converter::Convert( source.GetPixel() ) );
       
  1021                 
       
  1022             target.IncXPos();
       
  1023             source.IncXPos();
       
  1024             }
       
  1025         }
       
  1026             
       
  1027     target.End();
       
  1028     source.End();
       
  1029     }
       
  1030 
       
  1031 inline TUint32 CHuiModifiableBitmap::Convert16MA_16MU::Convert( TUint32 aPixel )
       
  1032     {
       
  1033     return aPixel | 0xFF000000;
       
  1034     }
       
  1035     
       
  1036 inline TUint32 CHuiModifiableBitmap::Convert16MA_64K::Convert( TUint32 aPixel )
       
  1037     {
       
  1038 	const TUint32 b = (aPixel&0x000000ff)>>3;
       
  1039 	const TUint32 g = (aPixel&0x0000fc00)>>5;
       
  1040 	const TUint32 r = (aPixel&0x00f80000)>>8;
       
  1041 	return (r|g|b);
       
  1042     }
       
  1043