diff -r e686773b3f54 -r 04ab22b956c2 phonebookui/Phonebook2/ccapplication/ccapp/ccapputil/src/ccappimagedecoding.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/ccapplication/ccapp/ccapputil/src/ccappimagedecoding.cpp Fri Feb 19 22:40:27 2010 +0200 @@ -0,0 +1,268 @@ +/* +* Copyright (c) 2008-2008 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 the utility class for asynchronously decoding the header thumbnail image +* +*/ + +#include "ccappimagedecoding.h" +#include +#include +#include + +namespace{ + +const TInt KDelay = 500000; // 0.5s + +inline TSize ScaledLoadSize( const TSize& aOriginalSize, TInt aScaleFactor ) + { + // Divide original size with scalefactor + // Round always up if result is not integer + return TSize( aOriginalSize.iWidth / aScaleFactor + ( aOriginalSize.iWidth % aScaleFactor ? 1 : 0 ), + aOriginalSize.iHeight / aScaleFactor + ( aOriginalSize.iHeight % aScaleFactor ? 1 : 0 ) ); + } +} // namespace + +// --------------------------------------------------------------------------- +// Two-phase construction +// --------------------------------------------------------------------------- +// +EXPORT_C CCCAppImageDecoding* CCCAppImageDecoding::NewL( + MCCAppImageDecodingObserver& aObserver, + RFs& aFs, + HBufC8* aBitmapData, + HBufC* aImageFile) + { + CCCAppImageDecoding* self = new (ELeave) CCCAppImageDecoding( + aObserver, aFs, aBitmapData, aImageFile); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + self->iBitmapData = aBitmapData; // take ownship + self->iImageFullName = aImageFile; // take ownship + + return self; + } + +// --------------------------------------------------------------------------- +// First phase (C++) constructor +// --------------------------------------------------------------------------- +// +inline CCCAppImageDecoding::CCCAppImageDecoding( + MCCAppImageDecodingObserver& aObserver, + RFs& aFs, + HBufC8* aBitmapData, + HBufC* aImageFile) : +CActive( CActive::EPriorityStandard ), +iObserver(aObserver), +iFs(aFs) + { + CActiveScheduler::Add(this); + } + +// --------------------------------------------------------------------------- +// Second phase (C++) constructor +// --------------------------------------------------------------------------- +// +inline void CCCAppImageDecoding::ConstructL() + { + User::LeaveIfError( iTimer.CreateLocal() ); + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CCCAppImageDecoding::~CCCAppImageDecoding() + { + Cancel(); + if (iImgDecoder) + { + iImgDecoder->Cancel(); + delete iImgDecoder; + } + if (iBitmapScaler) + { + iBitmapScaler->Cancel(); + delete iBitmapScaler; + } + delete iBitmap; + delete iBitmapData; + delete iImageFullName; + iTimer.Close(); + } + +// --------------------------------------------------------------------------- +// Starts the decoding process +// --------------------------------------------------------------------------- +// +EXPORT_C void CCCAppImageDecoding::StartL( const TSize& aImageSize ) + { + Cancel(); + iDecoderState = ECcaConvertThumbnailImage; + iBitmapSize = aImageSize; + CreateBitmapL(); + } + +// --------------------------------------------------------------------------- +// Called by the active object framework when the decoding (request) is +// completed. +// --------------------------------------------------------------------------- +// +void CCCAppImageDecoding::RunL() + { + User::LeaveIfError( iStatus.Int() ); + switch ( iDecoderState ) + { + case ECcaConvertThumbnailImage: + { + iDecoderState = ECcaScaleThumbnail; + CropBitmapL(); + ScaleBitmapL(); + break; + } + + case ECcaScaleThumbnail: + { + if ( iImageFullName ) + { + iDecoderState = ECcaReadImageFromFile; + SetPriority( EPriorityIdle ); + iTimer.After( iStatus, KDelay ); + SetActive(); + } + // don't break here + } + + case ECcaScaleImage: + { + // Ownership of the bitmap is transferred + iObserver.BitmapReadyL( iBitmap ); + iBitmap = NULL; + delete iBitmapScaler; + iBitmapScaler = NULL; + delete iImgDecoder; + iImgDecoder = NULL; + break; + } + + case ECcaReadImageFromFile: + { + if ( iImageFullName ) + { + iDecoderState = ECcaConvertImageFromFile; + CreateBitmapL(); + } + break; + } + + case ECcaConvertImageFromFile: + { + iDecoderState = ECcaScaleImage; + SetPriority( EPriorityStandard ); + CropBitmapL(); + ScaleBitmapL(); + break; + } + + default: + break; + } + } +// --------------------------------------------------------------------------- +// Called when the decoding (request) is cancelled for some reason. +// --------------------------------------------------------------------------- +// +void CCCAppImageDecoding::DoCancel() + { + if (iImgDecoder) + { + iImgDecoder->Cancel(); + delete iImgDecoder; + iImgDecoder = NULL; + } + if ( iBitmapScaler ) + { + iBitmapScaler->Cancel(); + delete iBitmapScaler; + iBitmapScaler = NULL; + } + iTimer.Cancel(); + } + +void CCCAppImageDecoding::CropBitmapL() + { + TSize dummy; + Pbk2PresentationImageUtils::CropImageL( + *iBitmap, + Pbk2PresentationImageUtils::ELandscapeCropping, + dummy ); + } + +void CCCAppImageDecoding::ScaleBitmapL() + { + iBitmapScaler = CBitmapScaler::NewL(); + iBitmapScaler->Scale( &iStatus, *iBitmap, iBitmapSize ); + SetActive(); + } + +void CCCAppImageDecoding::CreateBitmapL() + { + TInt initDecoder( KErrGeneral ); + if ( iDecoderState == ECcaConvertThumbnailImage && iBitmapData ) + { + iImgDecoder = CImageDecoder::DataNewL( iFs, *iBitmapData, CImageDecoder::EOptionAlwaysThread ); + initDecoder = KErrNone; + } + else if ( iDecoderState == ECcaConvertImageFromFile && iImageFullName ) + { + // leaaves if file doesn't exist + TRAP ( initDecoder, iImgDecoder = CImageDecoder::FileNewL( iFs, *iImageFullName, CImageDecoder::EOptionAlwaysThread ) ); + } + if ( initDecoder ) + { + delete iBitmapScaler; + iBitmapScaler = NULL; + delete iImgDecoder; + iImgDecoder = NULL; + return; + } + + if ( !iBitmap ) + { + const TFrameInfo info = iImgDecoder->FrameInfo(); + // calculate size for the bitmap + const TSize size( iBitmapSize ); + TSize loadSize( info.iOverallSizeInPixels ); + + for( TInt i = 1 ; i < 9 ; i = i * 2 ) + { + // we can use scalers 1:1 1:2 1:4 1:8 + TSize calcSize( ScaledLoadSize( info.iOverallSizeInPixels, i ) ); + if( calcSize.iHeight < size.iHeight || + calcSize.iWidth < size.iWidth ) + { + break; + } + loadSize = calcSize; + } + + iBitmap = new ( ELeave ) CFbsBitmap; + User::LeaveIfError( iBitmap->Create( loadSize, info.iFrameDisplayMode )); + } + + iStatus = KRequestPending; + iImgDecoder->Convert( &iStatus, *iBitmap ); + SetActive(); + }