imaging/imagingfws/ImageDisplay/plugins/IclWrapper/ImagePlayer.cpp
changeset 0 5752a19fdefe
--- /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 <imageconversion.h>
+#include <icl/imagedisplayplugin.h>
+#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();
+	}
+