diff -r 000000000000 -r 5752a19fdefe imaging/imagingfws/ImageDisplay/plugins/IclWrapper/ImagePostprocess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imaging/imagingfws/ImageDisplay/plugins/IclWrapper/ImagePostprocess.cpp Wed Aug 25 12:29:52 2010 +0300 @@ -0,0 +1,343 @@ +// Copyright (c) 2005-2009 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: +// + +/** @file + @internalComponent */ +#include +#include +#include "MiscUtils.h" + +#include "ImagePostprocess.h" + +/*static*/ +CAsyncTransformer* CAsyncTransformer::NewL(MPostProcessObserver& aObserver,CTransformerSharedData& aSingleton, + const TSize& aDestSize) + { + return new (ELeave) CAsyncTransformer(aObserver, aSingleton, aDestSize); + } + +CAsyncTransformer::CAsyncTransformer(MPostProcessObserver& aObserver, CTransformerSharedData& aSingleton, const TSize& aDestSize): + CActive(EPriorityNormal), + iObserver(aObserver), + iSingleton(&aSingleton), + iDestSize(aDestSize), + iScaleQuality(CBitmapScaler::EMinimumQuality) + + { + iSingleton->AddRef(); + CActiveScheduler::Add(this); + } + +CAsyncTransformer::~CAsyncTransformer() + { + Cleanup(); + iSingleton->Release(); + iSingleton = NULL; + delete iScaleDest; + delete iTransformDest; + } + +TInt CAsyncTransformer::RunError(TInt aError) + { + iResultStatus = aError; + iObserver.OnTransformDone(aError); + return KErrNone; + } + +TInt CAsyncTransformer::NextTransform(TUint& aTransFormTodo1) + { + if ((aTransFormTodo1&CImageDisplay::EOptionRotateCw90)==CImageDisplay::EOptionRotateCw90) + { + aTransFormTodo1 ^= CImageDisplay::EOptionRotateCw90; + return CBitmapRotator::ERotation90DegreesClockwise; + } + + if ((aTransFormTodo1&CImageDisplay::EOptionRotateCw180)==CImageDisplay::EOptionRotateCw180) + { + aTransFormTodo1 ^= CImageDisplay::EOptionRotateCw180; + return CBitmapRotator::ERotation180DegreesClockwise; + } + + if ((aTransFormTodo1&CImageDisplay::EOptionRotateCw270)==CImageDisplay::EOptionRotateCw270) + { + aTransFormTodo1 ^= CImageDisplay::EOptionRotateCw270; + return CBitmapRotator::ERotation270DegreesClockwise; + } + + if ((aTransFormTodo1&CImageDisplay::EOptionMirrorVertical)==CImageDisplay::EOptionMirrorVertical) + { + aTransFormTodo1 ^= CImageDisplay::EOptionMirrorVertical; + return CBitmapRotator::EMirrorVerticalAxis; + } + + if ((aTransFormTodo1&CImageDisplay::EOptionMirrorHorizontal)==CImageDisplay::EOptionMirrorHorizontal) + { + aTransFormTodo1 ^= CImageDisplay::EOptionMirrorHorizontal; + return CBitmapRotator::EMirrorHorizontalAxis; + } + + ASSERT(EFalse); + return -1; + } + +void CAsyncTransformer::RunL() + { + iResultStatus = iStatus.Int(); + User::LeaveIfError( iStatus.Int() ); + + switch (iState) + { + //coverity[unterminated_case] + case EStart: + // go further + CreateDestBitmapsL(); + //coverity[fallthrough] + case EClip: + { + if (iSingleton->ClippingSet()) + { + DeletePreTranformBmps(); + DoClipL(iCurrentSource, iClippingDest); + iCurrentSource = iClippingDest; + iState=ETransform; + RunAgain(); + break; + } + } // if no clipping just go further + case ETransform: + { + iState = ETransform; + if (iSingleton->TransformOptions()==0) + { + iState = EScale; + RunAgain(); + break; + } + if (iTransformTodo==0) + { + iState = ETransformDone; + } + else + { + CBitmapRotator::TRotationAngle transfromInstr=CBitmapRotator::TRotationAngle(NextTransform(iTransformTodo)); + if (iCurrentSource != iTransformDest) + { + iSingleton->RotatorL().Rotate(&iStatus, *iCurrentSource, *iTransformDest, transfromInstr); + } + else + { + iSingleton->RotatorL().Rotate(&iStatus, *iTransformDest, transfromInstr); + } + + iCurrentSource = iTransformDest; + SetActive(); + break; + } + } + case ETransformDone: + { + iCurrentSource = iTransformDest; + } // and go to scale + case EScale: + iState = EScale; + if (iClippingDest!=iCurrentSource) + { + DeletePreTranformBmps(); + } + if (iScaleNeeded) + { + CBitmapScaler& scaler=iSingleton->ScalerL(); + User::LeaveIfError( scaler.SetQualityAlgorithm( CBitmapScaler::TQualityAlgorithm(iScaleQuality)) ); + scaler.Scale(&iStatus, *iCurrentSource, *iScaleDest, EFalse); + // the EFalse is used because the Scaler uses an algorithm that is different for one + // that is used by CImageDecoder to calculate scaled sizes, so sizes sometime differ. + // there is no workaround for now.... + iCurrentSource = iScaleDest; + SetActive(); + iState = EDone; + break; + } + case EDone: + iState = EDone; + if (iClippingDest!=iCurrentSource) + { + DeletePreTranformBmps(); + } + if (iTransformDest!=iCurrentSource) + { + delete iTransformDest; + iTransformDest = NULL; + } + iObserver.OnTransformDone(iResultStatus); + break; + default: + ASSERT(EFalse); + } + } + +void CAsyncTransformer::Cleanup() + { + iSingleton->Cleanup(); + DeletePreTranformBmps(); + } + +void CAsyncTransformer::DoCancel() + { + Cleanup(); + iStatus = KErrCancel; + } + +void CAsyncTransformer::CreateDestBitmapsL() + { + delete iScaleDest; iScaleDest = NULL; + + iScaleDest = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iScaleDest->Create(iDestSize, iCurrentSource->DisplayMode()) ); + + delete iTransformDest; iTransformDest= NULL; + + iTransformDest = new (ELeave) CFbsBitmap(); + User::LeaveIfError(iTransformDest->Create(TSize(1,1), iCurrentSource->DisplayMode()) ); + } + +void CAsyncTransformer::DeletePreTranformBmps() + { + delete iClippingDest; + iClippingDest = NULL; + } + +void CAsyncTransformer::DoClipL(CFbsBitmap* aSrc, CFbsBitmap*& aDest) + { + ASSERT(aDest==NULL); + aDest = new (ELeave) CFbsBitmap(); + User::LeaveIfError( aDest->Create(iTrueClipRect.Size(), aSrc->DisplayMode()) ); + + CFbsBitmapDevice* device=CFbsBitmapDevice::NewL(aDest); + CleanupStack::PushL(device); + CFbsBitGc* gc=CFbsBitGc::NewL(); + CleanupStack::PushL(gc); + gc->Activate(device); + gc->BitBlt(TPoint(0,0), aSrc, iTrueClipRect); + CleanupStack::PopAndDestroy(2,device); + } + +void CAsyncTransformer::Transform(CFbsBitmap* aImage, TBool aMantainAspect) + { + ASSERT(!IsActive()); + + iImgSource = iCurrentSource = aImage; + iKeepAspect = aMantainAspect; + + const TSize srcSize(aImage->SizeInPixels()); + + iTrueClipRect = TRect(TPoint(0,0), srcSize.AsPoint()); + TSize clipRectSize(srcSize); + if (iSingleton->ClippingSet()) + { + const TRect& clipRect=iSingleton->ClipRect(); + iTrueClipRect.iTl.iX=MulDiv(clipRect.iTl.iX, srcSize.iWidth, iSingleton->TrueSrcSize().iWidth); + iTrueClipRect.iTl.iY=MulDiv(clipRect.iTl.iY, srcSize.iHeight,iSingleton->TrueSrcSize().iHeight); + iTrueClipRect.SetWidth(MulDiv(clipRect.Width(), srcSize.iWidth, iSingleton->TrueSrcSize().iWidth)); + iTrueClipRect.SetHeight(MulDiv(clipRect.Height(),srcSize.iHeight, iSingleton->TrueSrcSize().iHeight)); + clipRectSize=ScaleSize(srcSize, iSingleton->TrueSrcSize(), clipRect.Size()); + } + RotateSize(clipRectSize, iSingleton->TransformOptions()); + const TInt KMaxDelta=Min(7, Max(0, Max(iDestSize.iWidth / clipRectSize.iWidth, iDestSize.iHeight / clipRectSize.iHeight)-1 )); + // apply some treshold to size comparison because of decoder rounding algorithm + iScaleNeeded = (Abs(iDestSize.iWidth-clipRectSize.iWidth)>KMaxDelta || Abs(iDestSize.iHeight-clipRectSize.iHeight)>KMaxDelta); + Restart(); + } + + +TInt CAsyncTransformer::SetScaleQuality(TInt aQualityValue) + { + iScaleQuality = aQualityValue; + return KErrNone; + } + +void CAsyncTransformer::Restart() + { + iTransformTodo = iSingleton->TransformOptions(); + iCurrentSource = iImgSource; + iState = EStart; + + iResultStatus = KErrNone; + RunAgain(); + } + +void CAsyncTransformer::RunAgain() + { + SetActive(); + TRequestStatus* pR=&iStatus; + User::RequestComplete(pR,KErrNone); + } + +/*static*/ +CTransformerSharedData* CTransformerSharedData::NewL() + { + CTransformerSharedData* self = new (ELeave) CTransformerSharedData(); + self->AddRef(); + return self; + } + +void CTransformerSharedData::AddRef() + { + ++iRefCount; + } + +void CTransformerSharedData::Release() + { + ASSERT(iRefCount>0); + if (--iRefCount==0) + { + delete this; + } + } + + +void CTransformerSharedData::Cleanup() + { + delete iScaler; + iScaler = NULL; + delete iRotator; + iRotator= NULL; + } + +CTransformerSharedData::~CTransformerSharedData() + { + ASSERT(iRefCount==0); + Cleanup(); + } + +inline +CBitmapScaler& CTransformerSharedData::ScalerL() + { + if (iScaler==NULL) + { + iScaler=CBitmapScaler::NewL(); + } + return *iScaler; + } + +inline +CBitmapRotator& CTransformerSharedData::RotatorL() + { + if (iRotator == NULL) + { + iRotator = CBitmapRotator::NewL(); + } + return *iRotator; + } +