diff -r 2e2a89493e2b -r 48dd0f169f0d imagehandlinglib/Src/CIHLFileImage.cpp --- 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 - -// 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& 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( &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( animMask.DataAddress() ); - TSize srcSize( animMask.SizeInPixels() ); - TPoint srcPos( 0,0 ); - TInt srcScanLen8 = CFbsBitmap::ScanLineLength( srcSize.iWidth, EGray256 ); - - TUint8* dstAddress = reinterpret_cast( 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