--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/stdgraphic/BITMAPANIMATIONGRAPHICDRAWER.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,235 @@
+// Copyright (c) 1995-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 "stdgraphicdrawer.h"
+#include "wsgraphicdrawercontext.h"
+#include "Graphics/WSGRAPHICMSGBUF.H"
+#include "Graphics/W32STDGRAPHICTEST.H"
+#include <s32mem.h>
+#include <fbs.h>
+#include "W32STDGRAPHIC.H"
+
+// CWsGraphicDrawerBitmapAnimation::CFrame \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+NONSHARABLE_STRUCT(CWsGraphicDrawerBitmapAnimation::CFrame): public CBase
+ {
+ ~CFrame();
+ TFrameInfo iFrameInfo;
+ CFbsBitmap* iBitmap;
+ CFbsBitmap* iMask;
+ mutable RRegionBuf<12> iVisibleRegion;
+ };
+
+CWsGraphicDrawerBitmapAnimation::CFrame::~CFrame()
+ {
+ delete iBitmap;
+ delete iMask;
+ iVisibleRegion.Close();
+ }
+
+// CWsGraphicDrawerBitmapAnimation \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+CWsGraphicDrawerBitmapAnimation* CWsGraphicDrawerBitmapAnimation::CreateL()
+ {
+ return new(ELeave) CWsGraphicDrawerBitmapAnimation;
+ }
+
+CWsGraphicDrawerBitmapAnimation::CWsGraphicDrawerBitmapAnimation()
+ {
+ }
+
+CWsGraphicDrawerBitmapAnimation::~CWsGraphicDrawerBitmapAnimation()
+ {
+ if (iContext)
+ {
+ iContext->Destroy();
+ iContext = NULL;
+ }
+ iFrames.ResetAndDestroy();
+ }
+
+void CWsGraphicDrawerBitmapAnimation::ConstructL(MWsGraphicDrawerEnvironment& aEnv,const TGraphicDrawerId& aId,MWsClient& aOwner,const TDesC8& aData)
+ {
+ __ASSERT_COMPILE(sizeof(TInt) == sizeof(TInt32));
+ RDesReadStream in(aData);
+ in.PushL();
+ const TInt count = in.ReadInt32L();
+ for(TInt i=0; i<count; i++)
+ {
+ CFrame* frame = new(ELeave) CFrame;
+ CleanupStack::PushL(frame);
+ in.ReadL(reinterpret_cast<TUint8*>(&(frame->iFrameInfo)),sizeof(TFrameInfo));
+ const TInt bitmapHandle = in.ReadInt32L();
+ if(bitmapHandle)
+ {
+ frame->iBitmap = new(ELeave) CFbsBitmap;
+ User::LeaveIfError(frame->iBitmap->Duplicate(bitmapHandle));
+ }
+ const TInt maskHandle = in.ReadInt32L();
+ if(maskHandle)
+ {
+ frame->iMask = new(ELeave) CFbsBitmap;
+ User::LeaveIfError(frame->iMask->Duplicate(maskHandle));
+ }
+ iFrames.AppendL(frame);
+ CleanupStack::Pop(frame);
+ TInt64 delay = frame->iFrameInfo.iDelay.Int64();
+ if((delay < 0) || (delay > KMaxTUint32))
+ {
+ User::Leave(KErrCorrupt);
+ }
+ iAnimationLength += delay;
+ }
+ in.Pop();
+ BaseConstructL(aEnv,aId,aOwner);
+ if (!(aEnv.Screen(0)->ResolveObjectInterface(KMWsCompositionContext) || aEnv.Screen(0)->ResolveObjectInterface(KMWsScene)))
+ {
+ iContext = CWsGraphicDrawerNonNgaContext::NewL();
+ }
+ else
+ {
+ iContext = CWsGraphicDrawerNgaContext::NewL();
+ }
+ }
+
+void CWsGraphicDrawerBitmapAnimation::DoDraw(MWsGc& aGc,const TRect& aRect,const TDesC8& aData) const
+ {
+ const TInt count = iFrames.Count();
+ if(0 >= count)
+ {
+ return;
+ }
+
+ TWsGraphicMsgBufParser buf(aData);
+ if(KErrNone != buf.Verify())
+ {
+ return;
+ }
+
+ TWsGraphicMsgAnimation anim;
+ if (KErrNone != anim.Load(buf))
+ {
+ return;
+ }
+
+ if (KErrNone != iContext->Push(aGc))
+ {
+ return;
+ }
+
+ const TInt64 now_microseconds = (iAnimationLength ? anim.AnimationTime(iContext->Now(aGc),iAnimationLength).Int64(): 0LL);
+ TInt64 time_microseconds = 0LL;
+
+ // find end frame
+ TInt endFrame = 0;
+ while((endFrame<count) && (time_microseconds <= now_microseconds))
+ {
+ // work out timing
+ time_microseconds += iFrames[endFrame]->iFrameInfo.iDelay.Int64();
+ endFrame++;
+ }
+
+ TBool drawError = EFalse;
+ // work out visible regions
+ for(TInt i = 0; (i < endFrame) && !drawError; i++)
+ {
+ const CFrame* frame = iFrames[i];
+ const TRect frameRect(frame->iFrameInfo.iFrameCoordsInPixels);
+ frame->iVisibleRegion.Clear();
+
+ if((i == (endFrame - 1)) || frame->iFrameInfo.iFlags & TFrameInfo::ELeaveInPlace) // ELeave - Enum TFrameInfo::ELeaveInPlace triggers leavescan
+ {
+ frame->iVisibleRegion.AddRect(frameRect);
+ drawError = frame->iVisibleRegion.CheckError();
+ }
+ else
+ {
+ if(frame->iFrameInfo.iFlags & TFrameInfo::ERestoreToBackground)
+ {
+ for(TInt j = 0; j <= i; j++)
+ {
+ iFrames[j]->iVisibleRegion.SubRect(frameRect);
+ // coverity[unchecked_value]
+ drawError |= iFrames[j]->iVisibleRegion.CheckError();
+ }
+ }
+ else if(!(frame->iFrameInfo.iFlags & TFrameInfo::ERestoreToPrevious)) // if no disposal method is set, treat it as leave in place
+ {
+ frame->iVisibleRegion.AddRect(frameRect);
+ drawError = frame->iVisibleRegion.CheckError();
+ }
+ }
+ }
+
+ //draw each of the visible sub frames
+ for(TInt i = 0; (i < endFrame) && !drawError; i++)
+ {
+ const CFrame* frame = iFrames[i];
+ if(frame->iBitmap)
+ {
+ const TRegionFix<1> bitmapRegion(frame->iFrameInfo.iFrameCoordsInPixels);
+ frame->iVisibleRegion.Intersect(bitmapRegion);
+ frame->iVisibleRegion.Tidy();
+ if(frame->iVisibleRegion.CheckError())
+ {
+ drawError = ETrue;
+ break;
+ }
+ else
+ {
+ const TInt clipCount = frame->iVisibleRegion.Count();
+ for(TInt j = 0; j < clipCount; j++)
+ {
+ TRect frameRect = frame->iVisibleRegion.RectangleList()[j];
+ TRect clipRect(frameRect);
+ clipRect.Move(aRect.iTl);
+ clipRect.Intersection(aRect);
+
+ frameRect.Move(aRect.iTl);
+ frameRect.Intersection(aRect);
+ frameRect.Move(-aRect.iTl);
+ frameRect.Move(-frame->iFrameInfo.iFrameCoordsInPixels.iTl);
+
+ if(!clipRect.IsEmpty() && !frameRect.IsEmpty())
+ {
+ iContext->DrawBitmap(aGc,clipRect.iTl, frame->iBitmap, frameRect, frame->iMask);
+ }
+ }
+ }
+ }
+ }
+
+ if(0 <= buf.Find(TUid::Uid(TWsGraphicFrameRate::ETypeId)))
+ {
+ iContext->DrawFrameRate(aGc,aRect,iFps);
+ }
+ iFps.Sample();
+
+ if(anim.IsPlaying(iContext->Now(aGc),iAnimationLength))
+ {
+ iContext->ScheduleAnimation(aGc, aRect,(time_microseconds - now_microseconds));
+ }
+ else if(drawError)
+ {
+ iContext->ScheduleAnimation(aGc, aRect,now_microseconds + 1000000); // retry in 1 second
+ }
+
+ iContext->Pop(aGc);
+ }
+
+void CWsGraphicDrawerBitmapAnimation::HandleMessage(const TDesC8& /*aData*/)
+ {
+ }
+