--- a/imagehandlinglib/Src/CIHLFileImage.cpp Fri Sep 03 10:29:37 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,992 +0,0 @@
-/*
-* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: Implementation of Image class.
-*
-*/
-
-
-// INCLUDE FILES
-#include "CIHLFileImage.h"
-
-#include "CIHLBitmap.h"
-#include "IHLImplementationIds.h"
-#include "IHLDebugPrint.h" // Debug print
-#include <IHLInterfaceIds.h>
-
-// Private namespace for constants and functions
-namespace
- {
- // Fixed scale factors
- enum TScaleFactors
- {
- EFull = 1,
- EHalf = 2,
- EQuarter = 4,
- EEighth = 8,
- };
-
- // Panic function
- _LIT( KIHLPanicString, "IHLImage" );
- void Panic( TInt aPanicCode ) { User::Panic( KIHLPanicString, aPanicCode ); }
- }
-
-// ============================ MEMBER FUNCTIONS ===============================
-// -----------------------------------------------------------------------------
-//
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-CIHLFileImage::CIHLFileImage( TInt aImageIndex )
-:CActive( CActive::EPriorityStandard ),
-iImageIndex( aImageIndex )
- {
- CActiveScheduler::Add( this );
- }
-
-// -----------------------------------------------------------------------------
-//
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-CIHLFileImage* CIHLFileImage::NewL( RFile& aFile, TInt aImageIndex, const TUint32 aOptions )
- {
- CIHLFileImage* self = new (ELeave) CIHLFileImage( aImageIndex );
- CleanupStack::PushL( self );
- self->ConstructL( aFile, aOptions );
- CleanupStack::Pop(); // self
- return self;
- }
-
-CIHLFileImage* CIHLFileImage::NewL( RFs& aFs, const TDesC8& aDataBuf,
- TInt aImageIndex, const TUint32 aOptions )
- {
- CIHLFileImage* self = new (ELeave) CIHLFileImage( aImageIndex );
- CleanupStack::PushL( self );
- self->ConstructL( aFs, aDataBuf, aOptions );
- CleanupStack::Pop(); // self
- return self;
- }
-
-// -----------------------------------------------------------------------------
-//
-// Symbian constructor can leave.
-// -----------------------------------------------------------------------------
-void CIHLFileImage::ConstructL( RFile& aFile, const TUint32 aOptions )
- {
- TInt decoderOptions( CImageDecoder::EOptionNoDither | CImageDecoder::EOptionUseFrameSizeInPixels );
-
- // Open decoder
- IHL_DEBUG1( KIHLDebug1, "IHL - CIHLFileImage - Start create ICL image decoder" );
- if( aOptions & MIHLFileImage::EOptionNoDRMConsume )
- {
- iDecoder = CImageDecoder::FileNewL( aFile, ContentAccess::EPeek,
- (CImageDecoder::TOptions)decoderOptions );
- }
- else
- {
- iDecoder = CImageDecoder::FileNewL( aFile, ContentAccess::EView,
- (CImageDecoder::TOptions)decoderOptions );
- }
- ConstructCommonL();
- IHL_DEBUG1( KIHLDebug2, "IHL - CIHLFileImage - ICL image decoder ready!" );
- }
-
-void CIHLFileImage::ConstructL( RFs& aFs, const TDesC8& aDataBuf, const TUint32 /*aOptions*/ )
- {
- TInt decoderOptions( CImageDecoder::EOptionNoDither | CImageDecoder::EOptionUseFrameSizeInPixels );
-
- IHL_DEBUG1( KIHLDebug1, "IHL - CIHLFileImage - Start create buffered ICL image decoder" );
-
- iDecoder = CImageDecoder::DataNewL( aFs, aDataBuf, (CImageDecoder::TOptions)decoderOptions );
- ConstructCommonL();
-
- IHL_DEBUG1( KIHLDebug2, "IHL - CIHLFileImage - Buffered ICL image decoder ready!" );
- }
-
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ConstructCommonL
-// -----------------------------------------------------------------------------
-
-void CIHLFileImage::ConstructCommonL()
- {
- // Check frame count and image index
- iImageCount = iDecoder->FrameCount();
- __ASSERT_ALWAYS( iImageCount > 0, User::Leave( KErrCorrupt ) );
-
- // Get image types
- iDecoder->ImageType( iImageIndex, iImageType, iImageSubType );
-
- if( KImageTypeGIFUid == iImageType )
- {
- iGif = ETrue;
- if( iImageCount > 1 )
- {
- iAnimation = ETrue;
- iAnimationFrameCount = iImageCount;
- iImageCount = 1; // Handled as one animated image
- }
- }
- __ASSERT_ALWAYS( iImageIndex >= 0 && iImageIndex < iImageCount, User::Leave( KErrArgument ) );
-
- // cache frame info and set scale sizes
- iFrameInfo = iDecoder->FrameInfo( iImageIndex );
- if( !iAnimation )
- {
- // Animation must always be loaded 1:1
- if( !iGif &&
- iFrameInfo.iFlags & TFrameInfo::EFullyScaleable )
- {
- // Gif cannot be fully scaleable
- iFullyScaleable = ETrue;
- }
- else
- {
- TSize size( iFrameInfo.iOverallSizeInPixels );
- iLoadSizeArray.AppendL( ScaledLoadSize( size, EEighth ) );
- iLoadSizeArray.AppendL( ScaledLoadSize( size, EQuarter ) );
- iLoadSizeArray.AppendL( ScaledLoadSize( size, EHalf ) );
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// Destructor
-// -----------------------------------------------------------------------------
-CIHLFileImage::~CIHLFileImage()
- {
- Cancel();
- delete iPrevAnimationFrame;
- delete iSubFrameBitmap;
- delete iDecoder;
- iLoadSizeArray.Reset();
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::Type
-// -----------------------------------------------------------------------------
-TIHLInterfaceType CIHLFileImage::Type() const
- {
- return TIHLInterfaceType( KIHLInterfaceIdFileImage,
- KIHLImplementationIdFileImage );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ImageType
-// -----------------------------------------------------------------------------
-const TUid& CIHLFileImage::ImageType() const
- {
- return iImageType;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ImageSubType
-// -----------------------------------------------------------------------------
-const TUid& CIHLFileImage::ImageSubType() const
- {
- return iImageSubType;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ImageIndex
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::ImageIndex() const
- {
- return iImageIndex;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ImageCount
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::ImageCount() const
- {
- return iImageCount;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::Size
-// -----------------------------------------------------------------------------
-TSize CIHLFileImage::Size() const
- {
- return iFrameInfo.iOverallSizeInPixels;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::DisplayMode
-// -----------------------------------------------------------------------------
-TDisplayMode CIHLFileImage::DisplayMode() const
- {
- if( iGif )
- {
- // We cannot trust iFrameDisplayMode for GIF images. It always return EColor256.
- // This is error because palette sure holds only 256 colors but these colors can
- // be still any RGB values and so for cannot be directly put to 8 bit bitmap (EColor256).
- // To decrypt image correctly and without color dithering, we must use 24 bit (EColor16M)
- // destination bitmap. Note that CFbsBitmap has palette methods but they are
- // not supported currently.
- // Return maximum color mode to ensure best image quality.
- return EColor16MU;
- }
- else if( iFrameInfo.iFrameDisplayMode < EColor16MU ||
- iFrameInfo.iFrameDisplayMode == EColor4K )
- {
- return EColor64K;
- }
- return EColor16MU;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::MaskDisplayMode
-// -----------------------------------------------------------------------------
-TDisplayMode CIHLFileImage::MaskDisplayMode() const
- {
- if( iFrameInfo.iFlags & TFrameInfo::ETransparencyPossible )
- {
- if( iFrameInfo.iFlags & TFrameInfo::EAlphaChannel )
- {
- return EGray256;
- }
- return EGray2;
- }
- return ENone;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::BackgroundColor
-// -----------------------------------------------------------------------------
-TRgb CIHLFileImage::BackgroundColor() const
- {
- return iFrameInfo.iBackgroundColor;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::CustomLoadSizeArray
-// -----------------------------------------------------------------------------
-const RArray<TSize>& CIHLFileImage::CustomLoadSizeArray() const
- {
- return iLoadSizeArray;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::CustomLoadSizeArray
-// -----------------------------------------------------------------------------
-TBool CIHLFileImage::IsFullyScaleable() const
- {
- return iFullyScaleable;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::IsAnimation
-// -----------------------------------------------------------------------------
-TBool CIHLFileImage::IsAnimation() const
- {
- return iAnimation;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::AnimationFrameCount
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::AnimationFrameCount() const
- {
- return iAnimationFrameCount;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::AnimationFrameDelay
-// -----------------------------------------------------------------------------
-TTimeIntervalMicroSeconds32 CIHLFileImage::AnimationFrameDelay( TInt aAnimationFrameIndex ) const
- {
- __ASSERT_ALWAYS( aAnimationFrameIndex >= 0 &&
- aAnimationFrameIndex < iAnimationFrameCount, Panic( KErrArgument ) );
-
- return I64INT( iDecoder->FrameInfo( aAnimationFrameIndex ).iDelay.Int64() );
- }
-
-// ------------------------------------------------------------------------------
-// CIHLFileImage::Load
-// ------------------------------------------------------------------------------
-
-TInt CIHLFileImage::Load( TRequestStatus& aStatus, MIHLBitmap& aDestination, TInt aFrameIndex )
- {
- iImageIndex = aFrameIndex;
- return LoadRequest( aStatus, aDestination, iImageIndex );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::LoadAnimation
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::LoadAnimation( TRequestStatus& aStatus, MIHLBitmap& aDestination,
- TInt aAnimationFrameIndex )
- {
- __ASSERT_ALWAYS( aAnimationFrameIndex >= 0 &&
- aAnimationFrameIndex < iAnimationFrameCount, Panic( KErrArgument ) );
-
- return LoadRequest( aStatus, aDestination, aAnimationFrameIndex );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::IsBusy
-// -----------------------------------------------------------------------------
-TBool CIHLFileImage::IsBusy() const
- {
- return ( iImageState != EInactive );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::CancelLoad
-// -----------------------------------------------------------------------------
-void CIHLFileImage::CancelLoad()
- {
- Cancel();
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::SetFilter
-// -----------------------------------------------------------------------------
-void CIHLFileImage::SetFilter( MIHLFilter* /*aFilter*/ )
- {
- // Not in use
- }
-
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::Decoder
-// -----------------------------------------------------------------------------
-const CImageDecoder& CIHLFileImage::Decoder() const
- {
- return *iDecoder;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::DoCancel
-// -----------------------------------------------------------------------------
-void CIHLFileImage::DoCancel()
- {
- iDecoder->Cancel();
-
- // Delete all processed bitmaps
- ErrorCleanup();
-
- // Complete with cancel
- iImageState = EInactive;
- RequestComplete( KErrCancel );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::RunL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::RunL()
- {
- __ASSERT_DEBUG( iDestination, Panic( KErrGeneral ) );
- User::LeaveIfError( iStatus.Int() );
-
- switch( iImageState )
- {
- case EStartLoad:
- {
- // start loading the bitmaps
- StartLoadL();
- break;
- }
- case ECompleteLoad:
- {
- // complete loading the bitmaps
- CompleteLoadL();
- break;
- }
- default:
- {
- Panic( KErrTotalLossOfPrecision );
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::RunError
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::RunError( TInt aError )
- {
- IHL_DEBUG2( KIHLDebug, "IHL - CIHLFileImage - Loading error: %d", aError );
-
- // Delete all processed bitmaps
- ErrorCleanup();
-
- // Complete with error
- iImageState = EInactive;
- RequestComplete( aError );
- return KErrNone;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::LoadRequest
-// -----------------------------------------------------------------------------
-TInt CIHLFileImage::LoadRequest( TRequestStatus& aStatus,
- MIHLBitmap& aDestination,
- TInt aFrameIndex )
- {
- if( IsBusy() )
- {
- return KErrNotReady;
- }
-
- if( aFrameIndex < 0 || aFrameIndex >= iDecoder->FrameCount() )
- {
- return KErrArgument;
- }
-
- const CFbsBitmap& dstBitmap = aDestination.Bitmap();
- if( !dstBitmap.Handle() )
- {
- return KErrArgument;
- }
-
- TSize dstSize( dstBitmap.SizeInPixels() );
- if( dstSize != Size() &&
- !iFullyScaleable )
- {
- TBool sizeFound( EFalse );
- const TInt count( iLoadSizeArray.Count() );
- for( TInt i( 0 ); i < count; ++i )
- {
- if( dstSize == iLoadSizeArray[ i ] )
- {
- sizeFound = ETrue;
- }
- }
- if( !sizeFound )
- {
- return KErrArgument;
- }
- }
-
- IHL_DEBUG1( KIHLDebug, "IHL - CIHLFileImage - Frame loading requested" );
-
- iImageStatus = &aStatus;
- *iImageStatus = KRequestPending;
-
- iDestination = static_cast<CIHLBitmap*>( &aDestination ); //lint !e826
- iFrameIndex = aFrameIndex;
-
- // Start the active object
- iImageState = EStartLoad;
- SelfComplete();
- return KErrNone;
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::StartLoadL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::StartLoadL()
- {
- __ASSERT_DEBUG( !iSubFrameBitmap, Panic( KErrGeneral ) );
-
- IHL_DEBUG1( KIHLDebug, "IHL - CIHLFileImage - Start ICL convert" );
-
- if( iAnimation )
- {
- // Start animation from first frame by default
- iSubFrameIndex = 0;
-
- // Check is animation can be continued on top of destination bitmap
- if( iDestination->IsCreated() &&
- iDestination->EditorPtr() == this &&
- iDestination->EditorValue() < iFrameIndex )
- {
- // Editor value means frame index
- iSubFrameIndex = iDestination->EditorValue() + 1;
- }
-
- StartLoadSubFrameL( iSubFrameIndex, ETrue );
- }
- else if( iGif )
- {
- StartLoadSubFrameL( iFrameIndex, EFalse );
- }
- else
- {
- // Frame fills the whole image -> normal load
- StartLoadNormalFrame( iFrameIndex );
- }
-
- iImageState = ECompleteLoad;
- SetActive();
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::StartLoadNormalFrame
-// -----------------------------------------------------------------------------
-void CIHLFileImage::StartLoadNormalFrame( TInt aFrameIndex )
- {
- CFbsBitmap& dstBitmap = iDestination->BitmapModifyable();
- CFbsBitmap& dstMask = iDestination->MaskModifyable();
-
- if( MaskDisplayMode() && dstMask.Handle() )
- {
- iDecoder->Convert( &iStatus, dstBitmap, dstMask, aFrameIndex );
- }
- else
- {
- dstMask.Reset();
- iDecoder->Convert( &iStatus, dstBitmap, aFrameIndex );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::StartLoadSubFrameL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::StartLoadSubFrameL( TInt aFrameIndex, TBool aAnimation )
- {
- __ASSERT_DEBUG( !iSubFrameBitmap, Panic( KErrGeneral ) );
-
- // Create animation bitmap
- iSubFrameBitmap = CIHLBitmap::NewL();
- CFbsBitmap& subBitmap = iSubFrameBitmap->BitmapModifyable();
- CFbsBitmap& subMask = iSubFrameBitmap->MaskModifyable();
-
- TSize dstSize( iDestination->Bitmap().SizeInPixels() );
- TFrameInfo subFrameInfo( iDecoder->FrameInfo( aFrameIndex ) );
-
- // Check is client uses downscaling (not used in animations)
- TSize loadSize( subFrameInfo.iFrameSizeInPixels );
- iSubFrameScaleFactor = EFull;
- if( !aAnimation &&
- dstSize != iFrameInfo.iOverallSizeInPixels )
- {
- if( dstSize == ScaledLoadSize( iFrameInfo.iOverallSizeInPixels, EHalf ) )
- {
- iSubFrameScaleFactor = EHalf;
- loadSize = ScaledLoadSize( loadSize, EHalf );
- }
- else if( dstSize == ScaledLoadSize( iFrameInfo.iOverallSizeInPixels, EQuarter ) )
- {
- iSubFrameScaleFactor = EQuarter;
- loadSize = ScaledLoadSize( loadSize, EQuarter );
- }
- else if( dstSize == ScaledLoadSize( iFrameInfo.iOverallSizeInPixels, EEighth ) )
- {
- iSubFrameScaleFactor = EEighth;
- loadSize = ScaledLoadSize( loadSize, EEighth );
- }
- }
- User::LeaveIfError( subBitmap.Create( loadSize, EColor16M ) );
-
- if( subFrameInfo.iFlags & TFrameInfo::ETransparencyPossible )
- {
- User::LeaveIfError( subMask.Create( loadSize,
- subFrameInfo.iFlags & TFrameInfo::EAlphaChannel ? EGray256 : EGray2 ) );
- iDecoder->Convert( &iStatus, subBitmap, subMask, aFrameIndex );
- }
- else
- {
- iDecoder->Convert( &iStatus, subBitmap, aFrameIndex );
- }
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::CompleteLoadL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::CompleteLoadL()
- {
- IHL_DEBUG1( KIHLDebug1, "IHL - CIHLFileImage - ICL convert complete!" );
-
- if( iSubFrameBitmap )
- {
- IHL_DEBUG1( KIHLDebug2, "IHL - CIHLFileImage - Start build animation frame" );
-
- // Copy animation bitmap to destination
- BuildSubFrameL();
- delete iSubFrameBitmap;
- iSubFrameBitmap = NULL;
-
- IHL_DEBUG1( KIHLDebug3, "IHL - CIHLFileImage - Animation frame complete!" );
-
- // Save source info destination
- iDestination->SetEditorPtr( this );
- iDestination->SetEditorValue( iSubFrameIndex );
-
- if( iSubFrameIndex < iFrameIndex )
- {
- // re-start the active object and load next subframe
- iSubFrameIndex++;
- iImageState = EStartLoad;
- SelfComplete();
- }
- else
- {
- // Animation/subframe image ready
- iDestination = NULL;
- iImageState = EInactive;
- RequestComplete( KErrNone );
- }
- }
- else
- {
- // Save source info destination
- iDestination->SetEditorPtr( this );
- iDestination->SetEditorValue( iFrameIndex );
-
- // Normal image ready
- iDestination = NULL;
- iImageState = EInactive;
- RequestComplete( KErrNone );
- }
-
- IHL_DEBUG1( KIHLDebug4, "IHL - CIHLFileImage - Frame loading request complete!" );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::BuildSubFrameL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::BuildSubFrameL()
- {
- __ASSERT_DEBUG( iSubFrameBitmap, Panic( KErrGeneral ) );
- const CFbsBitmap& subBitmap = iSubFrameBitmap->Bitmap();
- const CFbsBitmap& subMask = iSubFrameBitmap->Mask();
- __ASSERT_DEBUG( subBitmap.Handle(), Panic( KErrGeneral ) );
-
- if( !iAnimation ||
- ( iAnimation && iSubFrameIndex == 0 ) )
- {
- TFrameInfo frameInfo( iDecoder->FrameInfo( iSubFrameIndex ) );
- if( iDestination->Bitmap().SizeInPixels() == subBitmap.SizeInPixels() &&
- frameInfo.iFrameCoordsInPixels.iTl == TPoint(0,0) )
- {
- // Sub frame is same size as destination image and has no offset
- // -> put directly into destination
- User::LeaveIfError( iDestination->Copy( subBitmap, subMask, ETrue ) );
- }
- else
- {
- // Sub frame size differs from destination image size
- CFbsBitmap& desBitmap = iDestination->BitmapModifyable();
- CFbsBitmap& desMask = iDestination->MaskModifyable();
-
- // Other frames must be build on top of previous frames
- __ASSERT_DEBUG( desBitmap.Handle(), Panic( KErrGeneral ) );
-
- // Fill destination using background color
- FillL( desBitmap, frameInfo.iBackgroundColor );
-
- // Copy loaded frame on top of background
- CFbsBitGc* bitGc;
- CFbsBitmapDevice* bitDevice = CFbsBitmapDevice::NewL( &desBitmap );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
-
- TPoint framePos( ScaledFramePosition(
- frameInfo.iFrameCoordsInPixels.iTl, iSubFrameScaleFactor ) );
- if( subMask.Handle() )
- {
- bitGc->BitBltMasked( framePos, &subBitmap,
- subBitmap.SizeInPixels(), &subMask, EFalse );
- }
- else
- {
- bitGc->BitBlt( framePos, &subBitmap, subBitmap.SizeInPixels() );
- }
- CleanupStack::PopAndDestroy( 2, bitDevice ); // bitGc, bitDevice
-
- if( desMask.Handle() )
- {
- // Fill mask to transparent
- FillL( desMask, KRgbBlack );
-
- // Fill bg mask with transparency (=black)
- CFbsBitmapDevice* maskDev = CFbsBitmapDevice::NewL( &desMask );
- CleanupStack::PushL( maskDev );
- CFbsBitGc* maskGc;
- User::LeaveIfError( maskDev->CreateContext( maskGc ) );
- CleanupStack::PushL( maskGc );
-
- // Combine bg mask with first frame mask
- maskGc->BitBlt( framePos, &subMask, subMask.SizeInPixels() );
-
- CleanupStack::PopAndDestroy( 2, maskDev ); // maskGc, maskDev
- }
- }
-
- // Create "previous frame" if animation
- if( iAnimation )
- {
- if( !iPrevAnimationFrame )
- {
- iPrevAnimationFrame = CIHLBitmap::NewL();
- }
- CFbsBitmap& desBitmap = iDestination->BitmapModifyable();
- CFbsBitmap& desMask = iDestination->MaskModifyable();
- if( iSubFrameBitmap->HasMask() )
- {
- User::LeaveIfError(
- iPrevAnimationFrame->Create( desBitmap.SizeInPixels(),
- desBitmap.DisplayMode(), desMask.DisplayMode() ) );
- FillL( iPrevAnimationFrame->BitmapModifyable(), frameInfo.iBackgroundColor );
- FillL( iPrevAnimationFrame->MaskModifyable(), KRgbBlack );
- }
- else
- {
- User::LeaveIfError(
- iPrevAnimationFrame->Create( desBitmap.SizeInPixels(),
- desBitmap.DisplayMode() ) );
- FillL( iPrevAnimationFrame->BitmapModifyable(), frameInfo.iBackgroundColor );
- }
- }
- }
- else // same as iAnimation && iSubFrameIndex > 0
- {
- TFrameInfo prevFrameInfo( iDecoder->FrameInfo( iSubFrameIndex - 1 ) );
- if ( prevFrameInfo.iFlags & TFrameInfo::ERestoreToPrevious )
- {
- // Restore destination to "previous frame"
- User::LeaveIfError( iDestination->Copy( *iPrevAnimationFrame, EFalse ) );
- }
-
- CFbsBitmap& prevBitmap = iDestination->BitmapModifyable();
- CFbsBitmap& prevMask = iDestination->MaskModifyable();
-
- // Other frames must be build on top of previous frames
- __ASSERT_DEBUG( prevBitmap.Handle(), Panic( KErrGeneral ) );
-
- // Restore area in destination bitmap if needed
- TRect restoreRect;
- TBool restoreToBackground( EFalse );
- if( prevFrameInfo.iFlags & TFrameInfo::ERestoreToBackground )
- {
- restoreToBackground = ETrue;
- restoreRect = prevFrameInfo.iFrameCoordsInPixels;
- FillRectL( prevBitmap, restoreRect, prevFrameInfo.iBackgroundColor );
-
- // Cache new "previous frame"
- User::LeaveIfError( iPrevAnimationFrame->Copy( *iDestination, EFalse ) );
- }
- else if( prevFrameInfo.iFlags & TFrameInfo::ELeaveInPlace )
- {
- // Cache new "previous frame"
- User::LeaveIfError( iPrevAnimationFrame->Copy( *iDestination, EFalse ) );
- }
-
- // Copy animation frame to destination bitmap
- TFrameInfo frameInfo( iDecoder->FrameInfo( iSubFrameIndex ) );
- CFbsBitGc* bitGc;
- CFbsBitmapDevice* bitDevice = CFbsBitmapDevice::NewL( &prevBitmap );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
- if( subMask.Handle() )
- {
- bitGc->BitBltMasked( frameInfo.iFrameCoordsInPixels.iTl, &subBitmap,
- subBitmap.SizeInPixels(), &subMask, EFalse );
- }
- else
- {
- bitGc->BitBlt( frameInfo.iFrameCoordsInPixels.iTl, &subBitmap,
- subBitmap.SizeInPixels() );
- }
- CleanupStack::PopAndDestroy( 2 ); // bitGc, bitDevice
-
- // Combine masks if any
- if( prevMask.Handle() && subMask.Handle() )
- {
- //////////////////////////////////////////////////////////////////////////
- // ALTERNATIVE WAY TO COMBINE MASKS!
- // Current solution doesn't combine soft masks.
- // Following code could be used if soft masks are enabled in animations.
- // Do not delete!
- //////////////////////////////////////////////////////////////////////////
- /*
- if( restoreToBackground )
- {
- bitDevice = CFbsBitmapDevice::NewL( &prevMask );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
-
- bitGc->SetBrushColor( KRgbBlack );
- bitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
- bitGc->DrawRect( restoreRect );
- bitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
-
- CleanupStack::PopAndDestroy( 2 ); // bitDevice, bitGc
- }
-
- prevMask.LockHeap();
-
- TUint8* srcAddress = reinterpret_cast<TUint8*>( animMask.DataAddress() );
- TSize srcSize( animMask.SizeInPixels() );
- TPoint srcPos( 0,0 );
- TInt srcScanLen8 = CFbsBitmap::ScanLineLength( srcSize.iWidth, EGray256 );
-
- TUint8* dstAddress = reinterpret_cast<TUint8*>( prevMask.DataAddress() );
- TSize dstSize( prevMask.SizeInPixels() );
- TPoint dstPos( frameInfo.iFrameCoordsInPixels.iTl );
- TPoint dstEndPos( frameInfo.iFrameCoordsInPixels.iBr );
- TInt dstScanLen8 = CFbsBitmap::ScanLineLength( dstSize.iWidth, EGray256 );
-
- while( dstPos.iY < dstEndPos.iY )
- {
- TUint8* srcAddressCur = srcAddress + ( srcPos.iY * srcScanLen8 );
- TUint8* dstAddressCur = dstAddress + ( dstPos.iY * dstScanLen8 );
- while( dstPos.iX < dstEndPos.iX )
- {
- TUint8& srcPixel = srcAddressCur[ srcPos.iX++ ];
- TUint8& dstPixel = dstAddressCur[ dstPos.iX++ ];
- if( srcPixel > dstPixel )
- {
- dstPixel = srcPixel;
- }
- }
-
- srcPos.iX = 0;
- srcPos.iY++;
- dstPos.iX = frameInfo.iFrameCoordsInPixels.iTl.iX;
- dstPos.iY++;
- }
-
- animMask.UnlockHeap();
- */
-
- if( restoreToBackground )
- {
- FillRectL( prevMask, restoreRect, KRgbBlack );
- }
-
- bitDevice = CFbsBitmapDevice::NewL( &prevMask );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
-
- CFbsBitmap* tmpMask = new(ELeave) CFbsBitmap;
- CleanupStack::PushL( tmpMask );
- User::LeaveIfError( tmpMask->Create( prevMask.SizeInPixels(), prevMask.DisplayMode() ) );
- CFbsBitmapDevice* tmpMaskDev = CFbsBitmapDevice::NewL( tmpMask );
- CleanupStack::PushL( tmpMaskDev );
- CFbsBitGc* tmpMaskGc;
- User::LeaveIfError( tmpMaskDev->CreateContext( tmpMaskGc ) );
- CleanupStack::PushL( tmpMaskGc );
-
- tmpMaskGc->BitBlt( TPoint( 0, 0 ), &prevMask, frameInfo.iFrameCoordsInPixels );
-
- bitGc->BitBltMasked( frameInfo.iFrameCoordsInPixels.iTl, &subMask,
- subMask.SizeInPixels(), tmpMask, ETrue );
-
- CleanupStack::PopAndDestroy( 5 ); // tmpMaskGc,tmpMaskDev,tmpMask,bitGc,bitDevice
- }
- else
- {
- prevMask.Reset(); // Mask not valid anymore -> reset
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::FillL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::FillL( CFbsBitmap& aBitmap, const TRgb& aColor )
- {
- CFbsBitGc* bitGc;
- CFbsBitmapDevice* bitDevice = CFbsBitmapDevice::NewL( &aBitmap );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
-
- bitGc->SetBrushColor( aColor );
- bitGc->SetPenColor( aColor );
- bitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
- bitGc->Clear();
- bitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
-
- CleanupStack::PopAndDestroy( 2 ); // bitGc, bitDevice
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::FillRectL
-// -----------------------------------------------------------------------------
-void CIHLFileImage::FillRectL( CFbsBitmap& aBitmap, const TRect& aRect,
- const TRgb& aColor )
- {
- CFbsBitGc* bitGc;
- CFbsBitmapDevice* bitDevice = CFbsBitmapDevice::NewL( &aBitmap );
- CleanupStack::PushL( bitDevice );
- User::LeaveIfError( bitDevice->CreateContext( bitGc ) );
- CleanupStack::PushL( bitGc );
-
- bitGc->SetBrushColor( aColor );
- bitGc->SetPenColor( aColor );
- bitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
- bitGc->DrawRect( aRect );
- bitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
-
- CleanupStack::PopAndDestroy( 2 ); // bitGc, bitDevice
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ErrorCleanup
-// -----------------------------------------------------------------------------
-void CIHLFileImage::ErrorCleanup()
- {
- if( iSubFrameBitmap )
- {
- delete iSubFrameBitmap;
- iSubFrameBitmap = NULL;
- }
-
- if( iDestination )
- {
- iDestination = NULL;
- }
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::SelfComplete
-// -----------------------------------------------------------------------------
-void CIHLFileImage::SelfComplete()
- {
- SetActive();
- iStatus = KRequestPending;
- TRequestStatus* status = &iStatus;
- User::RequestComplete( status, KErrNone );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::RequestComplete
-// -----------------------------------------------------------------------------
-void CIHLFileImage::RequestComplete( TInt aReason )
- {
- ASSERT( iImageStatus );
- User::RequestComplete( iImageStatus, aReason );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ScaledLoadSize
-// -----------------------------------------------------------------------------
-TSize CIHLFileImage::ScaledLoadSize( const TSize& aOriginalSize, TInt aScaleFactor )
- {
- // Divide original size with scalefactor
- // Round always up if result is not integer
- return ( aScaleFactor == EFull ) ? aOriginalSize :
- TSize( aOriginalSize.iWidth / aScaleFactor + ( aOriginalSize.iWidth % aScaleFactor ? 1 : 0 ),
- aOriginalSize.iHeight / aScaleFactor + ( aOriginalSize.iHeight % aScaleFactor ? 1 : 0 ) );
- }
-
-// -----------------------------------------------------------------------------
-// CIHLFileImage::ScaledLoadSize
-// -----------------------------------------------------------------------------
-TPoint CIHLFileImage::ScaledFramePosition( const TPoint& aOriginalPos, TInt aScaleFactor )
- {
- // Divide original position with scalefactor
- // Round always up if result is not integer
- return ( aScaleFactor == EFull ) ? aOriginalPos :
- TPoint( aOriginalPos.iX / aScaleFactor + ( aOriginalPos.iX % aScaleFactor ? 1 : 0 ),
- aOriginalPos.iY / aScaleFactor + ( aOriginalPos.iY % aScaleFactor ? 1 : 0 ) );
- }
-// End of File