diff -r 000000000000 -r 5752a19fdefe imaging/imagingfws/ImageDisplay/plugins/IclWrapper/ImagePlayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imaging/imagingfws/ImageDisplay/plugins/IclWrapper/ImagePlayer.cpp Wed Aug 25 12:29:52 2010 +0300 @@ -0,0 +1,285 @@ +// 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: +// + +#include +#include +#include "MiscUtils.h" + +#include "ImagePlayer.h" + +/** @file + @internalComponent */ + +const TUint KDecodeError = CImageDisplayPlugin::EStatusNoMoreToDecode; +const TUint KPartialFrameReady= CImageDisplayPlugin::EStatusFrameReady|CImageDisplayPlugin::EStatusPartialFrame; +const TUint KFrameReady = CImageDisplayPlugin::EStatusFrameReady; +const TUint KLastFrame = CImageDisplayPlugin::EStatusFrameReady|CImageDisplayPlugin::EStatusNoMoreToDecode; + + +CImagePlayer::CImagePlayer(MImagePlayerObserver& aObserver): + CActive(EPriorityIdle), + iObserver(aObserver) + { + CActiveScheduler::Add(this); + } + +CImagePlayer::~CImagePlayer() + { + Cancel(); + delete iFrame; + delete iMask; + delete iTmpFrame; + delete iTmpMask; + } + +void CImagePlayer::Play(CImageDecoder& aDecoder, TDisplayMode aDisplayMode, TInt aFrameLimit) + { + iDecoder = &aDecoder; + iFrameNumber = 0; + iCurrentReduction = iMaxReduction; + iDisplayMode = aDisplayMode; + iNeedRunAfterResume = ETrue; + iCurrentFrameInfo = &iDecoder->FrameInfo(); + if (aFrameLimit==KNoFrameLimit) + { + iFrameLimitToDecode = iDecoder->FrameCount(); + } + else + { + ASSERT(aFrameLimit > 0 && aFrameLimit <= iDecoder->FrameCount()); + iFrameLimitToDecode = aFrameLimit; + } + Resume(); + } + +void CImagePlayer::Setup(const TSize& aDestSize,TInt aMaxReduction, TInt aMinReduction) + { + iDestSize = aDestSize; + iMaxReduction = aMaxReduction; + iMinReduction = aMinReduction; + } + +TInt CImagePlayer::RunError(TInt aError) + { + iObserver.OnPlayEvent(aError,KDecodeError,NULL, NULL); + return KErrNone; + } + +void CImagePlayer::Pause() + { + iIsPaused = ETrue; + } + +void CImagePlayer::Resume() + { + iIsPaused = EFalse; + if (iNeedRunAfterResume) + { + iNeedRunAfterResume = EFalse; + RunAgain(); + } + } + +void CImagePlayer::RunAgain() + { + SetActive(); + TRequestStatus* pR=&iStatus; + User::RequestComplete(pR,KErrNone); + } + +/*static*/ +void CImagePlayer::CreateBitmapsL(CFbsBitmap*& aFrame, CFbsBitmap** aMask, const TSize& aSize, TDisplayMode aFrameMode) + { + if (aFrame==NULL || aFrame->DisplayMode()!=aFrameMode) + { + delete aFrame; + aFrame = NULL; + aFrame = new (ELeave) CFbsBitmap(); + User::LeaveIfError( aFrame->Create(aSize, aFrameMode) ); + } + else if (aFrame->SizeInPixels()!=aSize) + { + User::LeaveIfError( aFrame->Resize(aSize) ); + } + + if ( aMask != NULL ) + { + if (*aMask==NULL) + { + *aMask = new (ELeave) CFbsBitmap(); + User::LeaveIfError( (*aMask)->Create(aSize, EGray256) ); + } + else if ((*aMask)->SizeInPixels()!=aSize) + { + User::LeaveIfError( (*aMask)->Resize(aSize) ); + } + } + } + +void CImagePlayer::CreateBitmapsL() + { + TSize thisFrameSz(ScaleSize(iDestSize, iDecoder->FrameInfo().iFrameCoordsInPixels.Size(), + iCurrentFrameInfo->iFrameCoordsInPixels.Size() ) + ); + + if (iCurrentReduction != 0) + { + User::LeaveIfError( iDecoder->ReducedSize(iCurrentFrameInfo->iFrameCoordsInPixels.Size(), iCurrentReduction, thisFrameSz) ); + } + + iUseTempBitmap = EFalse; + const TBool KNeedMask= (iCurrentFrameInfo->iFlags&TFrameInfo::ETransparencyPossible) != 0; + + if (iCurrentFrameInfo->iFrameCoordsInPixels.iTl.iX != 0 || iCurrentFrameInfo->iFrameCoordsInPixels.iTl.iY != 0 + || (iCurrentFrameInfo->iFlags&TFrameInfo::ELeaveInPlace) != 0 ) + { + iUseTempBitmap = ETrue; + CreateBitmapsL(iTmpFrame, (KNeedMask? &iTmpMask : NULL), thisFrameSz, iDisplayMode ); + } + iIsAnimationSubframe = ETrue; + // create/change bitmaps only in case if it's 1st frame and we do not need to compose frames + // and we'are not dealing with some kind of strange image (like multiple MBMs) + if (iFrameNumber==0 || iCurrentReduction!=iMinReduction + || (!iUseTempBitmap + && iCurrentFrameInfo->iFrameCoordsInPixels!=iDecoder->FrameInfo().iFrameCoordsInPixels + && (iCurrentFrameInfo->iFlags&(TFrameInfo::ELeaveInPlace|TFrameInfo::ERestoreToBackground|TFrameInfo::ERestoreToPrevious))==0 + ) + ) + { + CreateBitmapsL(iFrame, (KNeedMask? &iMask : NULL), thisFrameSz, iDisplayMode ); + iIsAnimationSubframe = EFalse; + } + } + +void CImagePlayer::MergeFrameL() + { + ASSERT((iCurrentFrameInfo->iFlags&TFrameInfo::ELeaveInPlace) != 0 || (iCurrentFrameInfo->iFlags&TFrameInfo::ERestoreToBackground) != 0 ); + + const TBool hasMask=((iCurrentFrameInfo->iFlags&TFrameInfo::ETransparencyPossible) != 0); + CFbsBitmapDevice* device=CFbsBitmapDevice::NewL(iFrame); + CleanupStack::PushL(device); + CFbsBitGc* gc=CFbsBitGc::NewL(); + CleanupStack::PushL(gc); + gc->Activate(device); + + const TPoint dest(ScaleSize(iFrame->SizeInPixels(), iDecoder->FrameInfo().iFrameCoordsInPixels.Size(), + iCurrentFrameInfo->iFrameCoordsInPixels.iTl.AsSize() ).AsPoint()); + + if ((iCurrentFrameInfo->iFlags&TFrameInfo::ERestoreToBackground) != 0 ) + { + gc->SetBrushColor(iCurrentFrameInfo->iBackgroundColor); + gc->SetBrushStyle(CGraphicsContext::ESolidBrush); + gc->Clear(); + } + + if (hasMask) + { + gc->BitBltMasked(dest, iTmpFrame, TRect(TPoint(0,0),iTmpFrame->SizeInPixels().AsPoint()), iTmpMask, EFalse); + } + else + { + gc->BitBlt(dest, iTmpFrame); + } + + CleanupStack::PopAndDestroy(2,device); + if (!hasMask || (iCurrentFrameInfo->iFlags&TFrameInfo::ERestoreToBackground) == 0 ) + { + return; + } + device=CFbsBitmapDevice::NewL(iMask); + CleanupStack::PushL(device); + gc=CFbsBitGc::NewL(); + CleanupStack::PushL(gc); + gc->Activate(device); + gc->SetBrushColor(KRgbBlack); + gc->SetBrushStyle(CGraphicsContext::ESolidBrush); + gc->Clear(); + gc->BitBlt(iCurrentFrameInfo->iFrameCoordsInPixels.iTl, iTmpMask); + CleanupStack::PopAndDestroy(2,device); + } + +void CImagePlayer::RunL() + { + if (iIsPaused) + { + iNeedRunAfterResume = ETrue; + return; + } + switch (iState) + { + case EIdle: + { + iCurrentFrameInfo = &iDecoder->FrameInfo(iFrameNumber); + CreateBitmapsL(); + + const TBool useMask=((iCurrentFrameInfo->iFlags & TFrameInfo::ETransparencyPossible) != 0); + if ( useMask ) + { + iDecoder->Convert(&iStatus, *FrameBitmap(), *MaskBitmap(), iFrameNumber); + } + else + { + iDecoder->Convert(&iStatus, *FrameBitmap(), iFrameNumber); + } + + iState = EDecoding; + SetActive(); + } + break; + case EDecoding: + { + if (iUseTempBitmap) + { + MergeFrameL(); + } + TUint status=KPartialFrameReady; // first we iterate reduction factors + if (iCurrentReduction == iMinReduction) + { + status = KFrameReady; // than "true" image frames + if (++iFrameNumber == iFrameLimitToDecode) + { + status = KLastFrame; + iFrameNumber= 0; + } + iCurrentReduction = iMaxReduction; + } + else + { + --iCurrentReduction; + } + iObserver.OnPlayEvent(iStatus.Int(), status, iFrame, iMask); + iNeedRunAfterResume = ETrue; + iState = EIdle; + } + break; + default: + ASSERT(EFalse); // shan't reach it. + } + } + +void CImagePlayer::DoCancel() + { + iDecoder->Cancel(); + iNeedRunAfterResume = EFalse; + iState = EIdle; + } + +TSize CImagePlayer::OriginalFrameSize() const + { + return iUseTempBitmap || iIsAnimationSubframe ? + iDecoder->FrameInfo(0).iFrameCoordsInPixels.Size() : + iDecoder->FrameInfo(iFrameNumber).iFrameCoordsInPixels.Size(); + } +