diff -r 6ca72c0fe49a -r a941bc465d9f PECengine/AttributeLibrary2/SrcWVAttributes/CPEngMyLogoConverter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PECengine/AttributeLibrary2/SrcWVAttributes/CPEngMyLogoConverter.cpp Wed Sep 01 12:31:13 2010 +0100 @@ -0,0 +1,573 @@ +/* +* Copyright (c) 2005 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: MyLogo converter. +* +*/ + +// INCLUDE FILES +#include "CPEngMyLogoConverter.h" +#include "PresenceDebugPrint.h" + +#include +#include +#include +#include + + + +//LOCAL constants +namespace + { + //MyLogo image frame + const TInt KPEngMyLogoFrame = 0; + + //MyLogo converter panics + _LIT( KPEngMyLogoConverterPanic, "MyLogoConv" ); + + //MyLogo converter panic reasons + enum TPEngMyLogoConverterPanicReasons + { + EConvUnkownConvertState, + EConvNoImageDecoder, + EConvNoMyLogoBitmap, + EConvMyLogoBitmapExists, + EConvMyLogoEncoderExists, + EConvMyLogoScalerExists, + EConvParamsMissingNotifyNewLogo, + EConvParamsMissingVerifyMyLogoRequirements1, + EConvParamsMissingVerifyMyLogoRequirements2 + }; + } + + + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::FileNewL() +// ----------------------------------------------------------------------------- +// +CPEngMyLogoConverter* CPEngMyLogoConverter::FileNewL( const TDesC& aFileName, + MPEngMyLogoConversionObserver& aObserver ) + { + CPEngMyLogoConverter* self = new ( ELeave ) CPEngMyLogoConverter( aObserver ); + CleanupStack::PushL( self ); + self->ConstructFromFileL( aFileName ); + CleanupStack::Pop( self ); + return self; + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::DataNewL() +// ----------------------------------------------------------------------------- +// +CPEngMyLogoConverter* CPEngMyLogoConverter::DataNewL( const TDesC8& aImageData, + MPEngMyLogoConversionObserver& aObserver ) + { + CPEngMyLogoConverter* self = new ( ELeave ) CPEngMyLogoConverter( aObserver ); + CleanupStack::PushL( self ); + self->ConstructFromDataL( aImageData ); + CleanupStack::Pop( self ); + return self; + } + + + +// Destructor +CPEngMyLogoConverter::~CPEngMyLogoConverter() + { + CActive::Cancel(); + iObserver.HandleConverterDestroy(); + + delete iImageDataBuffer; + delete iImageMimeTypeBuffer; + delete iImageFileNameBuffer; + delete iImageDecoder; + delete iImageEncoder; + delete iBitmapScaler; + delete iMyLogoBitmap; + + iFs.Close(); + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::CPEngMyLogoConverter +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPEngMyLogoConverter::CPEngMyLogoConverter( MPEngMyLogoConversionObserver& aObserver ) + : CActive( EPriorityIdle ), + iState( EConverterIdle ), + iObserver( aObserver ) + { + CActiveScheduler::Add( this ); + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::ConstructFromFileL() +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::ConstructFromFileL( const TDesC& aImageFile ) + { + User::LeaveIfError( iFs.Connect() ); + iImageFileNameBuffer = aImageFile.AllocL(); + + if ( aImageFile.Length() > 0 ) + { + RFile imageFile; + CleanupClosePushL( imageFile ); + + + //Try open source file with different access modes + TInt openErr = imageFile.Open( iFs, aImageFile, EFileShareReadersOnly ); + if ( openErr != KErrNone ) + { + openErr = imageFile.Open( iFs, aImageFile, EFileShareAny | EFileStream ); + } + User::LeaveIfError( openErr ); + + + //And read file contents to buffer + TInt fileSize; + User::LeaveIfError( imageFile.Size( fileSize ) ); + iImageDataBuffer = HBufC8::NewL( fileSize ); + TPtr8 imageData( iImageDataBuffer->Des() ); + + User::LeaveIfError( imageFile.Read( imageData ) ); + + CleanupStack::PopAndDestroy(); // imageFile + + + //And open image decoder to buffer + iImageDecoder = CImageDecoder::DataNewL( iFs, + *iImageDataBuffer, + CImageDecoder::EOptionAlwaysThread ); + } + + else + { + iImageDataBuffer = HBufC8::NewL( 0 ); + iImageMimeTypeBuffer = HBufC8::NewL( 0 ); + } + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::ConstructFromDataL() +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::ConstructFromDataL( const TDesC8& aImageData ) + { + iImageFileNameBuffer = HBufC::NewL( 0 ); + + if ( aImageData.Length() > 0 ) + { + //Make a local copy from image + iImageDataBuffer = aImageData.AllocL(); + + //And open image decoder to buffer + iImageDecoder = CImageDecoder::DataNewL( iFs, + *iImageDataBuffer, + CImageDecoder::EOptionAlwaysThread ); + } + + else + { + iImageDataBuffer = HBufC8::NewL( 0 ); + iImageMimeTypeBuffer = HBufC8::NewL( 0 ); + } + } + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::IssueConvert() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::IssueConvert( TRequestStatus& aRequestStatus ) + { + //Issue first image processing round + iStatus = KRequestPending; + SetStateActive( EConverterIdle ); + + TRequestStatus *s = &iStatus; + User::RequestComplete( s, KErrNone ); + + //And cache client request status so it can be signalled later + //Client request status must be also set to pending state.. + iClientRequest = &aRequestStatus; + *iClientRequest = KRequestPending; + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::RunL() +// From CActive +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::RunL() + { + PENG_DP( D_PENG_LIT( "CPEngMyLogoConverter::RunL() iState[%d], iStatus[%d]" ), + iState, iStatus.Int() ); + + switch ( iState ) + { + case EConverterIdle: + { + if ( VerifyMyLogoRequirementsL() ) + { + NotifyNewLogo(); + ConversionCompletedD( KErrNone ); + } + + else + { + IssueImageOpenToBitmapL(); + SetStateActive( EImageOpenToBitmap ); + } + + break; + } + + case EImageOpenToBitmap: + { + User::LeaveIfError( iStatus.Int() ); + + delete iImageDecoder; + iImageDecoder = NULL; + + IssueBitmapScaleDownL(); + SetStateActive( EBitmapScaleDown ); + break; + } + + + case EBitmapScaleDown: + { + User::LeaveIfError( iStatus.Int() ); + + delete iBitmapScaler; + iBitmapScaler = NULL; + + IssueBitmapStoreToImageL(); + SetStateActive( EBitmapStoreToImage ); + break; + } + + case EBitmapStoreToImage: + { + User::LeaveIfError( iStatus.Int() ); + if ( iImageDataBuffer->Size() > KPEngWVMyLogoImageMaxByteSize ) + { + User::Leave( KErrTooBig ); + } + + NotifyNewLogo(); + ConversionCompletedD( KErrNone ); + break; + } + + + default: + { + PanicConverter( EConvUnkownConvertState ); + break; + } + } + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::RunError() +// From CActive +// ----------------------------------------------------------------------------- +// +TInt CPEngMyLogoConverter::RunError( TInt aError ) + { + PENG_DP( D_PENG_LIT( "CPEngMyLogoConverter::RunError [%d]" ), aError ); + + //RunL() has leaved. Stop the processing. + ConversionCompletedD( aError ); + + return KErrNone; + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::DoCancel() +// From CActive +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::DoCancel() + { + //cancel the operation step currently running... + switch ( iState ) + { + case EConverterIdle: + { + //no issued request to cancel + break; + } + + case EImageOpenToBitmap: + { + iImageDecoder->Cancel(); + break; + } + + case EBitmapScaleDown: + { + iBitmapScaler->Cancel(); + break; + } + + case EBitmapStoreToImage: + { + iImageEncoder->Cancel(); + break; + } + + default: + { + //nothing to do + break; + } + } + + //and complete original client request + User::RequestComplete( iClientRequest, KErrCancel ); + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::SetStateActive() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::SetStateActive( TLogoConverterState aNewState ) + { + SetActive(); + iState = aNewState; + + //Give other threads a chance + User::After( 0 ); // CSI: 92 # + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::VerifyMyLogoRequirements() +// ----------------------------------------------------------------------------- +// +TBool CPEngMyLogoConverter::VerifyMyLogoRequirementsL() + { + __ASSERT_DEBUG( iImageDataBuffer, + PanicConverter( EConvParamsMissingVerifyMyLogoRequirements1 ) ); + + if ( iImageDataBuffer->Length() == 0 ) + { + //Empty logo - no processing needed + return ETrue; + } + + + //verify image properties + __ASSERT_DEBUG( iImageDecoder && !iImageMimeTypeBuffer, + PanicConverter( EConvParamsMissingVerifyMyLogoRequirements2 ) ); + + if ( iImageDecoder->FrameCount() == 0 ) + { + User::Leave( KErrNotSupported ); //no frames in image + } + + + TFrameInfo fi; + fi = iImageDecoder->FrameInfo( KPEngMyLogoFrame ); + + + TUid imageType; + TUid imageSubType; + iImageDecoder->ImageType( KPEngMyLogoFrame, imageType, imageSubType ); + + + //Check image type + if ( ( imageType != KImageTypeGIFUid ) && ( imageType != KImageTypeJPGUid ) ) + { + PENG_DP( D_PENG_LIT( "CPEngMyLogoConverter::VerifyMyLogoRequirementsL() - wrong image format [%08x]" ), + imageType.iUid ); + return EFalse; + } + + //Check image pixel size + if ( ( fi.iOverallSizeInPixels.iHeight > KPEngWVMyLogoImageMaxHeight ) || + ( fi.iOverallSizeInPixels.iWidth > KPEngWVMyLogoImageMaxWidth ) ) + { + PENG_DP( D_PENG_LIT( "CPEngMyLogoConverter::VerifyMyLogoRequirementsL() - image pixel size too big h[%d] w[%d]" ), + fi.iOverallSizeInPixels.iHeight, fi.iOverallSizeInPixels.iWidth ); + return EFalse; + } + + //Check image byte size + if ( iImageDataBuffer->Size() > KPEngWVMyLogoImageMaxByteSize ) + { + PENG_DP( D_PENG_LIT( "CPEngMyLogoConverter::VerifyMyLogoRequirementsL() - image byte size too big [%d]" ), + iImageDataBuffer->Size() ); + return EFalse; + } + + + //Perfectly OK logo image. + if ( imageType == KImageTypeGIFUid ) + { + iImageMimeTypeBuffer = KPEngWVMyLogoMimeImageGif().AllocL(); + } + else + { + iImageMimeTypeBuffer = KPEngWVMyLogoMimeJpeg().AllocL(); + } + + return ETrue; + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::IssueImageOpenToBitmapL() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::IssueImageOpenToBitmapL() + { + __ASSERT_DEBUG( !iMyLogoBitmap, + PanicConverter( EConvMyLogoBitmapExists ) ); + + __ASSERT_DEBUG( iImageDecoder, + PanicConverter( EConvNoImageDecoder ) ); + + + //For future: This could be optimized to take just 1/8 sized image... + TFrameInfo fi; + fi = iImageDecoder->FrameInfo( KPEngMyLogoFrame ); + + iMyLogoBitmap = new( ELeave ) CFbsBitmap; + User::LeaveIfError( iMyLogoBitmap->Create( fi.iOverallSizeInPixels, + fi.iFrameDisplayMode ) ); + + iImageDecoder->Convert( &iStatus, *iMyLogoBitmap, KPEngMyLogoFrame ); + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::IssueBitmapScaleDownL() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::IssueBitmapScaleDownL() + { + __ASSERT_DEBUG( !iBitmapScaler, + PanicConverter( EConvMyLogoScalerExists ) ); + + __ASSERT_DEBUG( iMyLogoBitmap, + PanicConverter( EConvNoMyLogoBitmap ) ); + + + iBitmapScaler = CBitmapScaler::NewL(); + iBitmapScaler->Scale( &iStatus, + *iMyLogoBitmap, + TSize( KPEngWVMyLogoImageMaxWidth, KPEngWVMyLogoImageMaxHeight ), + ETrue ); + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::IssueBitmapStoreToImageL() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::IssueBitmapStoreToImageL() + { + __ASSERT_DEBUG( !iImageEncoder && !iImageMimeTypeBuffer, + PanicConverter( EConvMyLogoEncoderExists ) ); + + __ASSERT_DEBUG( iMyLogoBitmap, + PanicConverter( EConvNoMyLogoBitmap ) ); + + + iImageMimeTypeBuffer = KPEngWVMyLogoMimeJpeg().AllocL(); + + delete iImageDataBuffer; + iImageDataBuffer = NULL; + + iImageEncoder = CImageEncoder::DataNewL( iImageDataBuffer, + KPEngWVMyLogoMimeJpeg, + CImageEncoder::EOptionAlwaysThread ); + iImageEncoder->SetThumbnail( EFalse ); + iImageEncoder->Convert( &iStatus, *iMyLogoBitmap ); + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::NotifyNewLogo() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::NotifyNewLogo() + { + __ASSERT_DEBUG( iImageDataBuffer && iImageMimeTypeBuffer && iImageFileNameBuffer, + PanicConverter( EConvParamsMissingNotifyNewLogo ) ); + + + + iObserver.HandleNewMyLogo( iImageDataBuffer, iImageMimeTypeBuffer, iImageFileNameBuffer ); + + //HandleNewMyLogo took the ownership of passed + //iImageDataBuffer and iImageMimeTypeBuffer and iImageFileNameBuffer + //==> NULL own member pointers + iImageDataBuffer = NULL; + iImageMimeTypeBuffer = NULL; + iImageFileNameBuffer = NULL; + } + + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::ConversionCompletedD() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::ConversionCompletedD( TInt aStatus ) + { + User::RequestComplete( iClientRequest, aStatus ); + delete this; + } + + +// ----------------------------------------------------------------------------- +// CPEngMyLogoConverter::PanicConverter() +// ----------------------------------------------------------------------------- +// +void CPEngMyLogoConverter::PanicConverter( TInt aPanicReason ) const + { + User::Panic( KPEngMyLogoConverterPanic, aPanicReason ); + } + + + +// End of File + +