os/graphics/windowing/windowserver/test/tauto/tcrpanim.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/windowing/windowserver/test/tauto/tcrpanim.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1464 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// Implements  CTCrpAnim
    1.18 +// Test CRP animations & their interaction with overlapping transparent/non-transparent windows 
    1.19 +// & wserv's underlying redraw-store strategies
    1.20 +// 
    1.21 +//
    1.22 +
    1.23 +/**
    1.24 + @file
    1.25 + @test
    1.26 + @internalComponent - Internal Symbian test code
    1.27 +*/
    1.28 +
    1.29 +#include <w32stdgraphic.h>
    1.30 +#include "tcrpanim.h"
    1.31 +
    1.32 +// RUN_SAMPLE_ON_LEFT allows the demo animation to run in the left-hand window during testing. 
    1.33 +// Used for demonstration purposes only
    1.34 +#define RUN_SAMPLE_ON_LEFT
    1.35 +
    1.36 +namespace	//anonymous local scope
    1.37 +	{
    1.38 +	const TInt KAnimationFrameDelayTime = 50000; 				// delay in microseconds between frames
    1.39 +	const TInt KShortDelayLoop = 2*KAnimationFrameDelayTime; 	// delay time in microseconds used in test cases
    1.40 +	const TInt KAnimationTotalFrames = 40;						// total number of frames in a CWsGraphicBitmapAnimation
    1.41 +	const TInt KAnimDimension = 40;								// animation width/height. We're enforcing a square animation here
    1.42 +	const TInt KFrameMissedAnimationsThreshold = 10;			// maximum number of missed frame steps allowed
    1.43 +	const TInt KAnimationTearWidthThreshold = 4; 				// maximum columns permitted between a tear
    1.44 +	const TInt KMinGoodFrameThreshold = 30; 					// percentage threshold for number of good frames detected in a test
    1.45 +	const TInt KMaxXY = 200;									// arbitrary maximum size of square used to invalidate a window
    1.46 +	const TInt KMaxRepeatDraw = 2;								// arbitrary value for DrawLine calls during a Draw
    1.47 +	TUid  KUidTestAnimation2 = {0xBAADF00D};					// unique id. for CWsGraphicBitmapAnimation object
    1.48 +	const TUint32 KWhitePixels = 0xFFFFFFFF;					// 32-bit mask value for rgb white
    1.49 +	const TUint32 KBlackPixels = 0x00000000;					// 32-bit value for rgb black
    1.50 +	const TPoint KPointZero(0,0);								// initial point used for animation creation & manipulation (currently 0,0)
    1.51 +	const TPoint KPointOffsite(1000,1000);						// point used to draw off-screen
    1.52 +	const TDisplayMode KTestDisplayMode = EColor16MU;			// display mode used for testing
    1.53 +	const TInt KFrameStepCalculation = Max(1, KAnimDimension/Max(1, KAnimationTotalFrames)); // determine framestep size in columns
    1.54 +	
    1.55 +	enum TColorDetected
    1.56 +		{
    1.57 +		ECantTell=0,
    1.58 +		EDetRed=1,
    1.59 +		EDetGreen=2,
    1.60 +		EDetBlue=4,
    1.61 +		EDetBlack=0x10,
    1.62 +		EDetGrey=0x20,
    1.63 +		EDetWhite=0x40
    1.64 +		};
    1.65 +
    1.66 +	class CCrpAnim;		
    1.67 +	class CAnimRedrawWindow : public CTWin
    1.68 +		{
    1.69 +	public:
    1.70 +		CAnimRedrawWindow(CCrpAnim *aAnimWindow, TBool aIsBase);
    1.71 +		~CAnimRedrawWindow();
    1.72 +		void Draw();
    1.73 +	private:
    1.74 +		CCrpAnim *iAnimWindow;
    1.75 +		TBool iIsBase;
    1.76 +		};
    1.77 +		
    1.78 +	class CCrpAnim : public CBase
    1.79 +		{
    1.80 +		friend class CAnimRedrawWindow;
    1.81 +	public:
    1.82 +		enum TWinType
    1.83 +			{
    1.84 +			ERedraw,
    1.85 +			EBlank,		// note: not currently used in tcrpanim tests
    1.86 +			EBackedUp	// note: not currently used in tcrpanim tests
    1.87 +			};
    1.88 +	public:
    1.89 +		CCrpAnim(TBool aIsBase, TWinType aWinType);
    1.90 +		~CCrpAnim();
    1.91 +		enum 
    1.92 +			{
    1.93 +			ENoTransparency=0x100
    1.94 +			};
    1.95 +		void ConstructL(const TPoint &aPos, const TSize &aSize,const TInt aAlphaValue=ENoTransparency);
    1.96 +		void DoDraw(TBool aBlankIt);
    1.97 +		inline void DoDraw();
    1.98 +		void DoDrawEllipse();
    1.99 +		inline TSize Size() {return iCtWin->Size();};
   1.100 +		inline RWindowBase* BaseWin() const {return iCtWin->BaseWin();};
   1.101 +		inline RWindow* Window() const {return STATIC_CAST(RWindow*, iCtWin->BaseWin());};
   1.102 +		inline CTBaseWin* CtBaseWin() {return iCtWin;};
   1.103 +		inline void Invalidate() {CTUser::Splat(TheClient, TRect(iCtWin->Position(), iCtWin->Size()), KRgbGray);};
   1.104 +		void Invalidate(const TRect &aRect);
   1.105 +		static void SetEllipseDrawMode(CGraphicsContext::TDrawMode aEllipseDrawMode);
   1.106 +		void InvalidateAndRedraw(TBool aUseBlankItMember,TBool aBlankIt,TBool aUseRWindowInvalidate,TRect* aRect=NULL);
   1.107 +
   1.108 +		//A bit of an animation interface...
   1.109 +		//I have written this interface to be amenable to playing multiple animations,
   1.110 +		//which I think needs testing,
   1.111 +		//but the underlying implementation assumes one animation at present.
   1.112 +		//Your mission, should you choose to accept it, ....
   1.113 +		
   1.114 +		void SetPosAnimation(const TUid& aUid, const TRect& aRect);
   1.115 +		TRect* GetPosAnimation(const TUid& aUid);
   1.116 +		TWsGraphicAnimation* SetAnimation(TUid);	
   1.117 +		TWsGraphicAnimation* GetAnimation(TUid);	
   1.118 +		TBool RemoveAnimation(TUid);	
   1.119 +		inline void	SetBlankIt(TBool aNewVal) {iBlankIt = aNewVal;};
   1.120 +		inline void SetRepeatDrawMax(TInt aVal) {iRepeatDrawMax = aVal;};
   1.121 +	protected:
   1.122 +		static void Draw(CBitmapContext *aGc, const TSize &aSize, TBool aIsBase,const TRect &aRect, TBool aBlankIt,TInt aRepeat, TInt aAlphaValue);
   1.123 +		static void DrawEllipse(CBitmapContext *aGc, const TRect &aRect, TInt aAlphaValue);
   1.124 +		CTBaseWin *iCtWin;
   1.125 +		TWinType iWinType;
   1.126 +		TBool iIsBase;
   1.127 +		TBool iBlankIt;
   1.128 +		TRect iRect;
   1.129 +		TInt  iRepeatDrawMax;
   1.130 +		static CGraphicsContext::TDrawMode iEllipseDrawMode;
   1.131 +		TUid  iAnimUid;
   1.132 +		TWsGraphicAnimation iAnimData;
   1.133 +		TRect iAnimPos;
   1.134 +		TInt iAlphaValue;
   1.135 +		};
   1.136 +
   1.137 +/*	    Using this time delay class in order to allow animations to play in our draw.
   1.138 +		User::Wait does not allow the draw to occur (aparrently)
   1.139 +		Note when using this time-delay class: because other active objects can perform part of their
   1.140 +	    processing whilst we wait, wrapping calls to this in __UHEAP_MARK / __UHEAP_MARKEND
   1.141 +	    is likely to fail.  The data providers and animators are a major cause of this. 
   1.142 +*/
   1.143 +	class CActiveWait : public CActive
   1.144 +		{
   1.145 +	public:
   1.146 +		static CActiveWait* NewL();
   1.147 +		~CActiveWait();
   1.148 +		void Wait(TInt aDelay);
   1.149 +		// From CActive:
   1.150 +		void RunL();
   1.151 +		void DoCancel();
   1.152 +		TInt RunError(TInt aError);
   1.153 +	protected:
   1.154 +		CActiveWait();
   1.155 +		void ConstructL();
   1.156 +	protected:
   1.157 +		RTimer iTimer;
   1.158 +		TTime iFromTime;
   1.159 +		};
   1.160 +
   1.161 +	CActiveWait* CActiveWait::NewL()
   1.162 +		{
   1.163 +		CActiveWait* self = new (ELeave) CActiveWait;
   1.164 +		CleanupStack::PushL(self);
   1.165 +		self->ConstructL();
   1.166 +		CleanupStack::Pop(self);
   1.167 +		return self;
   1.168 +		}
   1.169 +		
   1.170 +	void CActiveWait::ConstructL()
   1.171 +		{
   1.172 +		User::LeaveIfError(iTimer.CreateLocal());
   1.173 +		CActiveScheduler::Add(this);
   1.174 +		}
   1.175 +		
   1.176 +	CActiveWait::CActiveWait() : CActive(EPriorityNormal)
   1.177 +		{
   1.178 +		iFromTime.HomeTime();
   1.179 +		}
   1.180 +
   1.181 +	CActiveWait::~CActiveWait()
   1.182 +		{
   1.183 +		Cancel();
   1.184 +		iTimer.Close();
   1.185 +		}
   1.186 +
   1.187 +	void CActiveWait::DoCancel()
   1.188 +		{
   1.189 +		iTimer.Cancel();
   1.190 +		CActiveScheduler::Stop();
   1.191 +		}
   1.192 +
   1.193 +	void CActiveWait::RunL()
   1.194 +		{
   1.195 +		CActiveScheduler::Stop();
   1.196 +		}
   1.197 +		
   1.198 +	TInt CActiveWait::RunError(TInt aError)
   1.199 +		{
   1.200 +		return aError; // exists so a break point can be placed on it.
   1.201 +		}
   1.202 +
   1.203 +/*	    Note when using this : because other active objects can perform part of their
   1.204 +	    processing whilst we wait, wrapping calls to this in __UHEAP_MARK / __UHEAP_MARKEND
   1.205 +	    is likely to fail.  The data providers and animators are a major cause of this. 
   1.206 +*/
   1.207 +	void CActiveWait::Wait(TInt aDelay)
   1.208 +		{
   1.209 +		iTimer.After(iStatus, aDelay);
   1.210 +		SetActive();
   1.211 +		CActiveScheduler::Start();
   1.212 +		}
   1.213 +	CGraphicsContext::TDrawMode CCrpAnim::iEllipseDrawMode;
   1.214 +
   1.215 +//
   1.216 +	}	//end anonymous local scope
   1.217 +//
   1.218 +
   1.219 +/** This fn allocates an animation frame of the specified dimensions.
   1.220 +	Not tested outside the current limited parameter set (16/2/2007).
   1.221 +	Note the use of 32-bit integers for pixel/colour values. Using display mode lower than 24bpp may not produce correct results
   1.222 +	My attempt to write animation generating code that avoids CIclLoader and Decoder class.
   1.223 +	@param aDelayUs	 	the display time for the frame
   1.224 +	@param aImageType	Colour format for colour plane. 24MA currently not flagged correctly I expect.
   1.225 +	@param aMaskType	Format for mask. ENone for no mask.
   1.226 +	@param aImageSize	Width/height of bitmap area
   1.227 +	@param aImageOffset	Optional offset for bitmap area
   1.228 +	@param aTotalSize	Optional width/height of whole animation (I think)
   1.229 +	@return CFrame		filled in with allocated bitmaps. The get methods for the bitmaps return const type.
   1.230 +**/
   1.231 +static CWsGraphicBitmapAnimation::CFrame* NewFrameLC(TInt aDelayUs,TDisplayMode aImageType,TDisplayMode aMaskType,const TSize& aImageSize,const TPoint& aImageOffset=KPointZero,const TSize& aTotalSize=TSize(0,0))
   1.232 +	{
   1.233 +	TFrameInfo info;
   1.234 +	info.iFrameCoordsInPixels = TRect(aImageOffset,aImageSize);
   1.235 +	info.iFrameSizeInTwips = aImageSize;	  //this is zero in the gif loader
   1.236 +	info.iDelay = TTimeIntervalMicroSeconds(aDelayUs);
   1.237 +	info.iFlags = TFrameInfo::EColor|TFrameInfo::ELeaveInPlace|TFrameInfo::EUsesFrameSizeInPixels;
   1.238 +	if (aMaskType != ENone)
   1.239 +		{
   1.240 +		info.iFlags|=TFrameInfo::ETransparencyPossible;
   1.241 +		}
   1.242 +	if ((aTotalSize.iHeight > 0) && (aTotalSize.iWidth > 0))
   1.243 +		{
   1.244 +		// restrict the size of the frame to specified size of the animation
   1.245 +		info.iOverallSizeInPixels = aTotalSize;
   1.246 +		}
   1.247 +	else
   1.248 +		{
   1.249 +		// assign the size of the frame to the size of the entire bitmap area
   1.250 +		info.iOverallSizeInPixels = info.iFrameCoordsInPixels.iBr.AsSize();
   1.251 +		}
   1.252 +	info.iFrameDisplayMode = aImageType;
   1.253 +	info.iBackgroundColor = KRgbGreen;
   1.254 +
   1.255 +	CWsGraphicBitmapAnimation::CFrame* frame = CWsGraphicBitmapAnimation::CFrame::NewL();
   1.256 +	CleanupStack::PushL(frame);
   1.257 +	frame->SetFrameInfo(info);
   1.258 +	CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
   1.259 +	frame->SetBitmap(bitmap); //takes ownership
   1.260 +	TSize frameInfoSize = info.iFrameCoordsInPixels.Size();
   1.261 +	User::LeaveIfError(bitmap->Create(frameInfoSize, aImageType));
   1.262 +	if((TFrameInfo::EAlphaChannel|TFrameInfo::ETransparencyPossible) & info.iFlags)
   1.263 +		{
   1.264 +		CFbsBitmap* mask = new(ELeave) CFbsBitmap;
   1.265 +		frame->SetMask(mask); //takes ownership
   1.266 +		User::LeaveIfError(mask->Create(frameInfoSize, aMaskType));
   1.267 +		}
   1.268 +	return frame;
   1.269 +	}
   1.270 +
   1.271 +//
   1.272 +// function called back by TCleanupItem frameListCleanup from within CreateAnimFramesL(..) method
   1.273 +//
   1.274 +void CleanupFrameList(TAny* aPtr)
   1.275 +	{
   1.276 +	RPointerArray<CWsGraphicBitmapAnimation::CFrame>* ptrArray = STATIC_CAST(RPointerArray<CWsGraphicBitmapAnimation::CFrame>*, aPtr);
   1.277 +	ptrArray->ResetAndDestroy();
   1.278 +	ptrArray->Close();
   1.279 +	}
   1.280 +
   1.281 +/** Helper function for making animation frames.
   1.282 +	//Called from CreateAnimL(...)
   1.283 +	@param aDelayUs		the delay between frames
   1.284 +	@param aNumFrames	number of frames (approx - image width is a factor)
   1.285 +	@param aImageType	colour format of colour data. This may not work properly for non-32-bit, but I haven't fully understood TBitmapUtil documentation.
   1.286 +	@param aMaskType	format for mask - ENone for no mask.
   1.287 +	@param aImageSize	width/height of animation
   1.288 +	@param aBgCol		background colour for image non-masked areas. Masked areas are black.
   1.289 +	@param aFgCol		foreground colour of animating area
   1.290 +	@param aFrames		frames that the animation is constructed from
   1.291 +**/
   1.292 +static void CreateAnimFramesL(TInt aDelayUs,TInt aNumFrames,TDisplayMode aImageType,TDisplayMode aMaskType,TSize aImageSize,TRgb aBgCol,TRgb aFgCol, RPointerArray<CWsGraphicBitmapAnimation::CFrame>& aFrames)
   1.293 +	{
   1.294 +	const TInt 	animWH = aImageSize.iWidth;
   1.295 +	const TInt	animStep = Max(1,animWH/Max(1,aNumFrames));	//note this intentionally rounds down to avoid overflows
   1.296 +	for (TInt ii = 0 ; ii < animWH ; ii += animStep)
   1.297 +		{
   1.298 +		CWsGraphicBitmapAnimation::CFrame* frame = NewFrameLC(aDelayUs,aImageType,aMaskType,aImageSize,KPointZero,aImageSize);
   1.299 +		aFrames.AppendL(frame);
   1.300 +		CleanupStack::Pop(frame);
   1.301 +		TBitmapUtil utilMask(CONST_CAST(CFbsBitmap*, frame->Mask()));
   1.302 +		TBitmapUtil utilCol(CONST_CAST(CFbsBitmap*, frame->Bitmap()));
   1.303 +		utilCol.Begin(KPointZero);
   1.304 +		
   1.305 +		// cycle through the frame's actual bitmap & assign each pixel a value identical to the specified colours
   1.306 +		TUint32 colback=aBgCol.Internal();
   1.307 +		TUint32 colfront=aFgCol.Internal();
   1.308 +		TInt row = KErrNone;
   1.309 +		TInt col = KErrNone;
   1.310 +		for (row = 0 ; row < aImageSize.iHeight ; row++)
   1.311 +			{
   1.312 +			utilCol.SetPos(TPoint(0, row));
   1.313 +			for (col = 0 ; col < aImageSize.iWidth ; col++)
   1.314 +				{
   1.315 +				utilCol.SetPixel(colback);	
   1.316 +				utilCol.IncXPos();
   1.317 +				}
   1.318 +			utilCol.SetPos(TPoint(ii, row));
   1.319 +			for (col = 0 ; col < animStep ; col++)	  //Note I rely on intentional rounding down here!
   1.320 +				{
   1.321 +				utilCol.SetPixel(colfront);	
   1.322 +				utilCol.IncXPos();
   1.323 +				}			
   1.324 +			}
   1.325 +		
   1.326 +		if (aMaskType)
   1.327 +			{
   1.328 +			// cycle through each pixel of the frame's mask & assign a default pixel a colour value
   1.329 +			utilMask.Begin(KPointZero);
   1.330 +			for (row = 0 ; row < aImageSize.iHeight ; row++)
   1.331 +				{
   1.332 +				utilMask.SetPos(TPoint(0,row));
   1.333 +				for (col = 0 ; col < aImageSize.iWidth ; col++)
   1.334 +					{
   1.335 +					utilMask.SetPixel(KWhitePixels);
   1.336 +					utilMask.IncXPos();
   1.337 +					}
   1.338 +				}
   1.339 +			
   1.340 +			const TInt maxmaskWidth = Min(8,Max(animWH/3,2));
   1.341 +
   1.342 +			//cut the corners off the mask
   1.343 +			for (row = 0 ; row < maxmaskWidth ; row++)
   1.344 +				{
   1.345 +				TInt currentX = maxmaskWidth - row;
   1.346 +				TInt xPos = KErrNone;
   1.347 +
   1.348 +				utilCol.SetPos(TPoint(0,row));
   1.349 +				utilMask.SetPos(TPoint(0,row));
   1.350 +				for(xPos = currentX ; xPos >= 0 ; xPos--)
   1.351 +					{
   1.352 +					utilCol.SetPixel(KBlackPixels);	
   1.353 +					utilCol.IncXPos();
   1.354 +					utilMask.SetPixel(KBlackPixels);	
   1.355 +					utilMask.IncXPos();
   1.356 +					}
   1.357 +
   1.358 +				utilCol.SetPos(TPoint(animWH - 1, row));
   1.359 +				utilMask.SetPos(TPoint(animWH - 1, row));
   1.360 +				for(xPos = currentX ; xPos >= 0 ; xPos--)
   1.361 +					{
   1.362 +					utilCol.SetPixel(KBlackPixels);	
   1.363 +					utilCol.DecXPos();
   1.364 +					utilMask.SetPixel(KBlackPixels);	
   1.365 +					utilMask.DecXPos();
   1.366 +					}
   1.367 +
   1.368 +				utilCol.SetPos(TPoint(0, animWH - 1 - row));
   1.369 +				utilMask.SetPos(TPoint(0, animWH - 1 - row));
   1.370 +				for(xPos = currentX ; xPos >= 0 ; xPos--)
   1.371 +					{
   1.372 +					utilCol.SetPixel(KBlackPixels);	
   1.373 +					utilCol.IncXPos();
   1.374 +					utilMask.SetPixel(KBlackPixels);	
   1.375 +					utilMask.IncXPos();
   1.376 +					}
   1.377 +
   1.378 +				utilCol.SetPos(TPoint(animWH - 1, animWH - 1 - row));
   1.379 +				utilMask.SetPos(TPoint(animWH - 1, animWH - 1 - row));
   1.380 +				for(xPos = currentX ; xPos >= 0 ; xPos--)
   1.381 +					{
   1.382 +					utilCol.SetPixel(KBlackPixels);	
   1.383 +					utilCol.DecXPos();
   1.384 +					utilMask.SetPixel(KBlackPixels);	
   1.385 +					utilMask.DecXPos();
   1.386 +					}
   1.387 +				}
   1.388 +			utilMask.End();
   1.389 +			}
   1.390 +		utilCol.End();
   1.391 +		}
   1.392 +	}
   1.393 +
   1.394 +/** My attempt to write animation generating code that avoids CIclLoader and Decoder class.
   1.395 +	//It is better if this test class used it's own generated animation
   1.396 +	//rather than relying on the GIF loader in order to reduce the cross-dependencies.
   1.397 +	//The animation generated is a simple vertical line moving from left to right.
   1.398 +	//To prove the masking, I cut the corners off.
   1.399 +	@param aDelayUs		the delay between frames
   1.400 +	@param aNumFrames	number of frames (approx - image width is a factor)
   1.401 +	@param aImageType	colour format of colour data. This may not work properly for non-32-bit, but I haven't fully understood TBitmapUtil documentation.
   1.402 +	@param aMaskType	format for mask - ENone for no mask.
   1.403 +	@param aImageSize	width/height of animation
   1.404 +	@param aBgCol		background colour for image non-masked areas. Masked areas are black.
   1.405 +	@param aFgCol		foreground colour of animating area
   1.406 +	@param aTUid		TUid assigned to animation
   1.407 +	@return CWsGraphicBitmapAnimation allocated to represent the final animation	
   1.408 +**/
   1.409 +static CWsGraphicBitmapAnimation* CreateAnimL(TInt aDelayUs,TInt aNumFrames,TDisplayMode aImageType,TDisplayMode aMaskType,TSize aImageSize,TRgb aBgCol,TRgb aFgCol,TUid& aTUid)
   1.410 +	{
   1.411 +	RPointerArray<CWsGraphicBitmapAnimation::CFrame> frames;
   1.412 +	TCleanupItem frameListCleanup(CleanupFrameList, &frames);
   1.413 +	CleanupStack::PushL(frameListCleanup);
   1.414 +	
   1.415 +	CreateAnimFramesL(aDelayUs, aNumFrames, aImageType, aMaskType, aImageSize,aBgCol, aFgCol, frames);
   1.416 +	
   1.417 +	CWsGraphicBitmapAnimation* anim = CWsGraphicBitmapAnimation::NewL(aTUid,frames.Array());
   1.418 +	CleanupStack::PopAndDestroy(&frames);
   1.419 +	return anim;
   1.420 +	}
   1.421 +
   1.422 +//
   1.423 +// Describes the pure colour of the RGB value. yellow/magenta/cyan set 2 bits. White/grey is seperately flagged.
   1.424 +// This method attempts to determine the strongest primary colour present in any given pixel. 
   1.425 +// Note: The algorithm used is known to work for the current test cases only but requires careful review
   1.426 +// for anyone making additional changes to tcrpanim. Given time, improved algorithm should be developed
   1.427 +// to replace the current one
   1.428 +//
   1.429 +TUint PredominantColour(TUint aCol)
   1.430 +	{	 //I don't like all these ifs, but I don't see an easy alternative
   1.431 +		 //Possibly a bit look-up of the deltas from average would work 
   1.432 +		 //(ignoring the bottom 5 bits =32, not 0x30=48. Ignore bottom 4 bits and accept 3-same answers, or divide by delta?)
   1.433 +		 //
   1.434 +	const TInt Kdelta=0x30;
   1.435 +	TInt red=(aCol&0x00ff0000)>>16;
   1.436 +	TInt green=(aCol&0x0000ff00)>>8;
   1.437 +	TInt blue=(aCol&0x000000ff);
   1.438 +	TInt ave=((red+green+blue)*(65536/3))>>16;
   1.439 +	TBool rOverA=(red>ave);
   1.440 +	TBool gOverA=(green>ave);
   1.441 +	TBool bOverA=(blue>ave);
   1.442 +	TInt numOverAve=(rOverA?1:0)+(gOverA?1:0)+(bOverA?1:0);
   1.443 +
   1.444 +	if (numOverAve==1)
   1.445 +		{
   1.446 +		if (rOverA)
   1.447 +			{
   1.448 +			if (red>ave+Kdelta)
   1.449 +				{
   1.450 +				if ((green-blue)>-Kdelta && (green-blue)<Kdelta)
   1.451 +					return  EDetRed;
   1.452 +				}
   1.453 +			else
   1.454 +				{
   1.455 +				if (ave<Kdelta)
   1.456 +					return EDetBlack;
   1.457 +				else
   1.458 +					{
   1.459 +					if (green>ave-Kdelta && blue>ave-Kdelta)
   1.460 +						{
   1.461 +						if (ave>256-Kdelta)
   1.462 +							return EDetWhite;
   1.463 +						else
   1.464 +							return EDetGrey;
   1.465 +						}
   1.466 +					}
   1.467 +				}
   1.468 +			}
   1.469 +				
   1.470 +		if (gOverA)
   1.471 +			{
   1.472 +			if (green>ave+Kdelta)
   1.473 +				{
   1.474 +				if ((blue-red)>-Kdelta && (blue-red)<Kdelta)
   1.475 +					return  EDetGreen;
   1.476 +				}
   1.477 +			else
   1.478 +				{
   1.479 +				if (ave<Kdelta)
   1.480 +					return EDetBlack;
   1.481 +				else
   1.482 +					{
   1.483 +					if (red>ave-Kdelta && blue>ave-Kdelta)
   1.484 +						if (ave>256-Kdelta)
   1.485 +							return EDetWhite;
   1.486 +						else
   1.487 +							return EDetGrey;
   1.488 +					}
   1.489 +				}
   1.490 +			}
   1.491 +
   1.492 +		if (bOverA)
   1.493 +			{
   1.494 +			if (blue>ave+Kdelta)
   1.495 +				{
   1.496 +				if ((green-red)>-Kdelta && (green-red)<Kdelta)
   1.497 +					return  EDetBlue;
   1.498 +				}
   1.499 +			else
   1.500 +				{
   1.501 +				if (ave<Kdelta)
   1.502 +					return EDetBlack;
   1.503 +				else
   1.504 +					{
   1.505 +					if (red>ave-Kdelta && green>ave-Kdelta)
   1.506 +						if (ave>256-Kdelta)
   1.507 +							return EDetWhite;
   1.508 +						else
   1.509 +							return EDetGrey;
   1.510 +					}
   1.511 +				}
   1.512 +			}
   1.513 +		}
   1.514 +	else	
   1.515 +		{
   1.516 +		if (!rOverA)
   1.517 +			 if (red<ave-Kdelta)
   1.518 +			 	{
   1.519 +			 	if ((green-blue)>-Kdelta && (green-blue)<Kdelta)
   1.520 +			 		return EDetGreen|EDetBlue;
   1.521 +			 	}
   1.522 +			 else
   1.523 +				{
   1.524 +				if (ave>256-Kdelta)
   1.525 +					return EDetWhite;
   1.526 +				else
   1.527 +					{
   1.528 +					if (blue<ave+Kdelta && green<ave+Kdelta)
   1.529 +						{
   1.530 +						if (ave<Kdelta)
   1.531 +							return EDetBlack;
   1.532 +						else
   1.533 +							return EDetGrey;
   1.534 +						}
   1.535 +					}
   1.536 +				}
   1.537 +
   1.538 +		if (!gOverA)
   1.539 +			{
   1.540 +			if (green<ave-Kdelta)
   1.541 +				{
   1.542 +				if ((blue-red)>-Kdelta && (blue-red)<Kdelta)
   1.543 +					return  EDetRed|EDetBlue;
   1.544 +				}
   1.545 +			 else
   1.546 +				{
   1.547 +				if (ave>256-Kdelta)
   1.548 +					return EDetWhite;
   1.549 +				else
   1.550 +					{
   1.551 +					if (blue<ave+Kdelta && red<ave+Kdelta)
   1.552 +						if (ave<Kdelta)
   1.553 +							return EDetBlack;
   1.554 +						else
   1.555 +							return EDetGrey;
   1.556 +					}
   1.557 +				}
   1.558 +			}
   1.559 +
   1.560 +		if (!bOverA)
   1.561 +			{
   1.562 +			if (blue<ave-Kdelta)
   1.563 +				{
   1.564 +				if ((green-red)>-Kdelta && (green-red)<Kdelta)
   1.565 +					return  EDetGreen|EDetRed;
   1.566 +				}
   1.567 +			 else
   1.568 +				{
   1.569 +				if (ave>256-Kdelta)
   1.570 +					return EDetWhite;
   1.571 +				else
   1.572 +					{
   1.573 +					if (red<ave+Kdelta && green<ave+Kdelta)
   1.574 +						if (ave<Kdelta)
   1.575 +							return EDetBlack;
   1.576 +						else
   1.577 +							return EDetGrey;
   1.578 +					}
   1.579 +				}
   1.580 +			}
   1.581 +		}
   1.582 +	return ECantTell;
   1.583 +	}
   1.584 +
   1.585 +/**
   1.586 +	Helper fn to ensure I put the anims in the same place each time...
   1.587 +**/
   1.588 +void CalcCentredAnimPosition(TRect& aRect,const TSize& aWinSize)
   1.589 +	{
   1.590 +	aRect.Shrink(aWinSize.iWidth*3/8,aWinSize.iHeight*4/10);
   1.591 +	}
   1.592 +
   1.593 +CTCrpAnim::CTCrpAnim(CTestStep* aStep) : 
   1.594 +	CTWsGraphicsBase(aStep)
   1.595 +	{
   1.596 +	}
   1.597 +
   1.598 +void CTCrpAnim::ConstructL()
   1.599 +	{
   1.600 +	TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0);
   1.601 +	iRedrawWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
   1.602 +	iBaseWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
   1.603 +	iOverWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
   1.604 +
   1.605 +	TSize screenSize=TheClient->iGroup->Size();
   1.606 +	TInt winWidth=(screenSize.iWidth/3)-10;
   1.607 +	TInt winHeight=screenSize.iHeight-10;
   1.608 +	TSize windowSize(winWidth,winHeight);
   1.609 +
   1.610 +	iRedrawWin->ConstructL(TPoint(screenSize.iWidth/3*2+5,5), windowSize);
   1.611 +	iBaseWin->ConstructL(TPoint(screenSize.iWidth/3+5,5), windowSize);
   1.612 +	
   1.613 +	//Create a transparent window that exactly overlaps the test window
   1.614 +	//If transparency is not supported the leave causes the window to be destroyed and set to NULL.
   1.615 +	//There is a test for transparency supported, but that simply creates a temp window to test anyway... 
   1.616 +	
   1.617 +	//Note that when I originally wrote this test to fix PDEF101991, it generated white areas that I detected.
   1.618 +	//However, if this transparent window used for extended tests is created over the test window,
   1.619 +	//that somehow stops the white fill from occurring.
   1.620 +	//The fault still occurs, but the previous screen contents are left behind.
   1.621 +	//So now this window is created at an off-screen location.
   1.622 +	TRAPD(err, iOverWin->ConstructL(KPointOffsite, windowSize, 0x80); iOverWin->SetBlankIt(ETrue); iOverWin->SetRepeatDrawMax(KMaxRepeatDraw););
   1.623 +	if (err)
   1.624 +		{
   1.625 +		delete iOverWin;
   1.626 +		iOverWin = NULL;
   1.627 +		}
   1.628 +	
   1.629 +	iTestWin = iRedrawWin;
   1.630 +	iTestWin->SetRepeatDrawMax(KMaxRepeatDraw);
   1.631 +	iBaseWin->SetRepeatDrawMax(KMaxRepeatDraw);
   1.632 +
   1.633 +	// create animation object & share it with everyone
   1.634 +	iAnim = CreateAnimL(KAnimationFrameDelayTime,KAnimationTotalFrames,KTestDisplayMode,EGray256,TSize(KAnimDimension, KAnimDimension),KRgbBlue,KRgbRed,KUidTestAnimation2);
   1.635 +	if (!iAnim)
   1.636 +		{
   1.637 +		User::Leave(KErrNoMemory);
   1.638 +		}
   1.639 +	iAnim->ShareGlobally();
   1.640 +	
   1.641 +	// calculate minimum length of the red line
   1.642 +	const TInt maxmaskHeight = Min(8, Max(KAnimDimension/3,2)); // note this calculation mimics that for the size of the corners cut from the mask in CreateAnimL above
   1.643 +	iMinimumCalcRedLine = KAnimDimension - maxmaskHeight*2; // the height of the image minus the two cut corners
   1.644 +
   1.645 +	// create the timer object
   1.646 +	iWaiter = CActiveWait::NewL();
   1.647 +
   1.648 +	// create screen bitmap object & scanline buffer
   1.649 +	iScreenBitmap = new (ELeave) CFbsBitmap;
   1.650 +	User::LeaveIfError(iScreenBitmap->Create(TSize(KAnimDimension, KAnimDimension), KTestDisplayMode));
   1.651 +	TInt bufLength = iScreenBitmap->ScanLineLength(windowSize.iHeight, KTestDisplayMode);
   1.652 +	iScanlineBuf = HBufC8::NewL(bufLength);
   1.653 +	
   1.654 +	#ifdef RUN_SAMPLE_ON_LEFT
   1.655 +    	{
   1.656 +		// play animation on iBaseWin window
   1.657 +		iBaseWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
   1.658 +		TSize subsize1 = iTestWin->BaseWin()->Size();
   1.659 +		TRect subposition1(subsize1);
   1.660 +		CalcCentredAnimPosition(subposition1, subsize1);
   1.661 +		iBaseWin->SetPosAnimation(KUidTestAnimation2, subposition1);
   1.662 +		iBaseWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
   1.663 +    	}
   1.664 +	#endif
   1.665 +	}
   1.666 +
   1.667 +CTCrpAnim::~CTCrpAnim()
   1.668 +	{
   1.669 +	delete iRedrawWin;
   1.670 +	delete iBaseWin;
   1.671 +	delete iOverWin;
   1.672 +	if (iAnim)
   1.673 +		{
   1.674 +		// destroy the animation object
   1.675 +		iAnim->UnShareGlobally();
   1.676 +		iAnim->Destroy();
   1.677 +		delete iAnim;				
   1.678 +		iAnim = NULL;
   1.679 +		}
   1.680 +	if (iWaiter)
   1.681 +		{
   1.682 +		// destroy the timer object
   1.683 +		delete iWaiter;
   1.684 +		iWaiter = NULL;
   1.685 +		}
   1.686 +	if (iScreenBitmap)
   1.687 +		{
   1.688 +		// destroy the screen capture of the animation
   1.689 +		delete iScreenBitmap;
   1.690 +		iScreenBitmap = NULL;
   1.691 +		}
   1.692 +	if (iScanlineBuf)
   1.693 +		{
   1.694 +		// destroy the scanline buffer
   1.695 +		delete iScanlineBuf;
   1.696 +		iScanlineBuf = NULL;
   1.697 +		}
   1.698 +	User::After(200000);
   1.699 +	}
   1.700 +
   1.701 +//
   1.702 +// This method checks the animation contained in the aAnimWin window has progressed. That is 
   1.703 +// that it's drawn a sufficient number of concurrent frames to screen & the animation is 
   1.704 +// drawn properly to screen
   1.705 +// returns a Bool identifying whether the animation is considered 'good' or not
   1.706 +//  
   1.707 +void CTCrpAnim::CheckAnimProgressedL(CAnonAnimWindow* aAnimWin, TInt aAdditionalFrameCount, TBool aCaptureFrameResult)
   1.708 +	{
   1.709 +	TBool goodAnimation = ETrue;
   1.710 +
   1.711 +	// retrieve the rect from the screen's bitmap that contains the animation
   1.712 +	CWsScreenDevice* screen = TheClient->iScreen;
   1.713 +	TRect animPos = *aAnimWin->GetPosAnimation(KUidTestAnimation2);
   1.714 +	CTBaseWin* bWin = aAnimWin->CtBaseWin();
   1.715 +	animPos.Move(bWin->Position());
   1.716 +	User::LeaveIfError(screen->CopyScreenToBitmap(iScreenBitmap, animPos));
   1.717 +	
   1.718 +	TInt frameNum = DetermineApproxFrameNum(iScreenBitmap, aCaptureFrameResult); // determines the frame Number & checks quality of animation (no tearing, etc)
   1.719 +	TBool frameIdentified=(frameNum>=0);
   1.720 +	
   1.721 +	if (aCaptureFrameResult)
   1.722 +		{
   1.723 +		if (frameIdentified)
   1.724 +			{
   1.725 +			if (iPreviousFrameNum != KErrNotFound)
   1.726 +			 	{
   1.727 +				if (iPreviousFrameNum < frameNum)
   1.728 +					{
   1.729 +					TInt frameStep = KFrameStepCalculation * aAdditionalFrameCount;
   1.730 +					iPreviousFrameNum += frameStep; // move to our *expected* framenumber
   1.731 +					if (frameNum > iPreviousFrameNum)
   1.732 +						{
   1.733 +						// the frame number is ahead of it's expected position
   1.734 +						// This suggests we've possibly missed animating a frame in wserv
   1.735 +						// or test code isn't getting a chance to execute as crp animations taking all cpu cycles
   1.736 +						// If its significantly outside norms, we log the fact (as a performance metric)
   1.737 +						TInt performance = ((frameNum - iPreviousFrameNum) / frameStep);
   1.738 +						if (performance > KFrameMissedAnimationsThreshold)
   1.739 +							{
   1.740 +							iFrameStatus.iFrameSkipped++;
   1.741 +							goodAnimation = EFalse;	
   1.742 +							}	
   1.743 +						}
   1.744 +					// else we're animating above an acceptable threshold
   1.745 +					}
   1.746 +				else if (iPreviousFrameNum == frameNum) // potentially not animating anymore
   1.747 +					{
   1.748 +					iFrameStatus.iFrameIdentical++;
   1.749 +					goodAnimation = EFalse;
   1.750 +					}
   1.751 +				// else animation is progressing fine
   1.752 +				}
   1.753 +			// ignore iPreviousFrameNum == KErrNotFound
   1.754 +			}
   1.755 +		else
   1.756 +			{
   1.757 +			goodAnimation = EFalse; // couldn't id the red line	
   1.758 +			}
   1.759 +
   1.760 +		if (goodAnimation)
   1.761 +			{
   1.762 +			iFrameStatus.iFrameOK++;
   1.763 +			}
   1.764 +		}
   1.765 +	// else we were only interested in calculating the frameNum
   1.766 +	iPreviousFrameNum = frameNum;
   1.767 +	}
   1.768 +
   1.769 +//
   1.770 +// method to estimate the framenumber based on the location of the thin, red line. 
   1.771 +// Also checks whether tearing of the animation has occured or the animation
   1.772 +// is only partially drawn. 
   1.773 +// These are known issues with wserv animation performance & so we give some allowance for error
   1.774 +// 
   1.775 +TInt CTCrpAnim::DetermineApproxFrameNum(CFbsBitmap* aBitmap, TBool aCaptureFrameResult)
   1.776 +	{
   1.777 +	TInt colFirstTear = KErrNotFound; 	// column id'ing the first tear in the vertical line
   1.778 +	TPtr8 des = iScanlineBuf->Des();	// ptr to the scanline buffer
   1.779 +
   1.780 +	// locate the thin, red line in the bitmap
   1.781 +	for (TInt xPos = 0 ; xPos < aBitmap->SizeInPixels().iWidth ; xPos++)
   1.782 +		{
   1.783 +		aBitmap->GetVerticalScanLine(des, xPos, EColor16MA);
   1.784 +		TUint32* pixel = (TUint32*) des.Ptr();
   1.785 +		TInt colour = KErrNone;
   1.786 +		
   1.787 +		for (TInt ii = 0 ; ii < aBitmap->SizeInPixels().iHeight ; ii++)
   1.788 +			{
   1.789 +			colour = PredominantColour(*pixel);
   1.790 +			if (colour & EDetRed)
   1.791 +				{
   1.792 +				if (colFirstTear < 0)
   1.793 +					{
   1.794 +					// check the length of the red line is a good length
   1.795 +					pixel += (iMinimumCalcRedLine - 1); // minus the one pixel to position on last pixel in red line
   1.796 +					colour = PredominantColour(*pixel);
   1.797 +					if (colour & EDetRed)
   1.798 +						{
   1.799 +						// good line
   1.800 +						return xPos;
   1.801 +						}
   1.802 +					else // we've detected first part of a torn line
   1.803 +						{
   1.804 +						colFirstTear = xPos; 
   1.805 +						}
   1.806 +					}
   1.807 +				else
   1.808 +					{
   1.809 +					// located second part of torn line
   1.810 +					if ((xPos - colFirstTear) > KAnimationTearWidthThreshold)
   1.811 +						{
   1.812 +						if (aCaptureFrameResult)
   1.813 +							{
   1.814 +							iFrameStatus.iFrameTearing++;	
   1.815 +							}
   1.816 +						xPos = KErrNotFound;
   1.817 +						}
   1.818 +					return xPos;
   1.819 +					}	
   1.820 +				break;
   1.821 +				}
   1.822 +			pixel++;
   1.823 +			}
   1.824 +		}
   1.825 +	if (aCaptureFrameResult)
   1.826 +		{
   1.827 +		if (colFirstTear < 0)
   1.828 +			{
   1.829 +			iFrameStatus.iFrameEmpty++; // we never located any red line at all
   1.830 +			}
   1.831 +		else
   1.832 +			{
   1.833 +			iFrameStatus.iFramePartial++; // we only located a single, small part of the red line
   1.834 +			}
   1.835 +		}
   1.836 +	return KErrNotFound;
   1.837 +	}
   1.838 +
   1.839 +/**	This internal loop tests that the animation and the foreground interact correctly
   1.840 +	The primary test is that the outline of the animation 
   1.841 +	intersects the lines drawn on the foreground correctly, compared to a reference version.
   1.842 +	The iBaseWin is already showing this reference anim.
   1.843 +	If the animation is not drawn, or the foreground is wiped, then this test will fail.
   1.844 +**/
   1.845 +void CTCrpAnim::TestSpriteLoopL(TBool aAnimForeground,TBool aDrawForeground)
   1.846 +	{
   1.847 +	_LIT(KForegroundInfo,"TestSpriteLoop animForeground [%d] drawForeground [%d]");
   1.848 +	INFO_PRINTF3(KForegroundInfo, aAnimForeground, aDrawForeground);
   1.849 +	
   1.850 +	if (!iOverWin && (aAnimForeground || aDrawForeground))
   1.851 +		{
   1.852 +		User::Leave(KErrGeneral); // unable to run this test without iOverWin
   1.853 +		}
   1.854 +
   1.855 +	ResetFrameCounters();
   1.856 +	iTestWin->RemoveAnimation(KUidTestAnimation2);
   1.857 +	iTestWin->SetBlankIt(ETrue);		
   1.858 +	if (iOverWin)
   1.859 +		{
   1.860 +		iOverWin->RemoveAnimation(KUidTestAnimation2);
   1.861 +		iOverWin->SetBlankIt(ETrue);
   1.862 +		}
   1.863 +
   1.864 +	// determine which window holds the animation, & which will be invalidated with progressively larger rects
   1.865 +	CCrpAnim* animWin=aAnimForeground?iOverWin:iTestWin;
   1.866 +	CCrpAnim* paintWin=aDrawForeground?iOverWin:iTestWin;
   1.867 +	paintWin->SetBlankIt(EFalse);
   1.868 +	
   1.869 +	// set & play the animation on the specified window (animWin)
   1.870 +	animWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
   1.871 +	TSize subsize1 = paintWin->BaseWin()->Size();
   1.872 +	TRect subposition1(subsize1);
   1.873 +	CalcCentredAnimPosition(subposition1, subsize1);
   1.874 +	animWin->SetPosAnimation(KUidTestAnimation2, subposition1);
   1.875 +	
   1.876 +	#ifdef RUN_SAMPLE_ON_LEFT
   1.877 +		// play the demo animation in the left-hand window also
   1.878 +		iBaseWin->InvalidateAndRedraw(ETrue, EFalse, ETrue);
   1.879 +	#endif
   1.880 +
   1.881 +	iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
   1.882 +	if (iOverWin)
   1.883 +		{
   1.884 +		iOverWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
   1.885 +		}
   1.886 +	
   1.887 +	// invalidate increasingly larger squares on paintWin 
   1.888 +	// note, some fully overlap the animation, some partially overlap, and some don't overlap at all
   1.889 +	TInt invalidateWaitTime=KAnimationFrameDelayTime*3/4; // microseconds
   1.890 +	TInt temp = KErrNotFound;
   1.891 +	for (TInt step=30;step<KMaxXY;step+=30)
   1.892 +		{
   1.893 +		for (TInt xx=0;xx<KMaxXY;xx+=step)
   1.894 +			{
   1.895 +			for (TInt yy=10;yy<KMaxXY;yy+=step)
   1.896 +	    		{
   1.897 +				// calculate rectangle & invalidate paintWin with it
   1.898 +	    		TRect invalidRect(xx,yy,xx+step,yy+step);
   1.899 +	    		paintWin->InvalidateAndRedraw(ETrue,EFalse,ETrue,&invalidRect);
   1.900 +				
   1.901 +				// calculate any additional frames that may be drawn by above. Note intentionally ignore frame result
   1.902 +				temp = iPreviousFrameNum;	
   1.903 +				CheckAnimProgressedL(animWin, 1, EFalse);
   1.904 +				
   1.905 +				//new defect DEF101896: Test runs faster with this line removed, but there is evident tearing
   1.906 +				iWaiter->Wait(invalidateWaitTime);			//DEF101896 search string: //interrupt_foreground_draw
   1.907 +				
   1.908 +				if (temp == iPreviousFrameNum)
   1.909 +					{
   1.910 +					// give wserv more time to animate the frame
   1.911 +					iWaiter->Wait(invalidateWaitTime);
   1.912 +					}
   1.913 +				CheckAnimProgressedL(animWin, 1); // calculate the frame drawn. Capture frame result
   1.914 +				}
   1.915 +			}
   1.916 +		}
   1.917 +
   1.918 +	// determine whether the animation was successful (ie: enough Good frames were detected) or not
   1.919 +	// Note KMinGoodFrameThreshold is essentially an arbitrary number. This can be adjusted to accommodate
   1.920 +	// performance requirements as needed
   1.921 +	temp = LogResults();
   1.922 +	TInt quality = 100*iFrameStatus.iFrameOK/temp;
   1.923 +	TEST(quality > KMinGoodFrameThreshold);
   1.924 +	
   1.925 +	ResetFrameCounters();
   1.926 +	iWaiter->Cancel();
   1.927 +	iTestWin->RemoveAnimation(KUidTestAnimation2);
   1.928 +	iTestWin->SetBlankIt(ETrue);		
   1.929 +	if (iOverWin)
   1.930 +		{
   1.931 +		iOverWin->RemoveAnimation(KUidTestAnimation2);
   1.932 +		iOverWin->SetBlankIt(ETrue);
   1.933 +		}
   1.934 +	}
   1.935 +
   1.936 +//
   1.937 +// resets the frame trackers to intial values
   1.938 +//
   1.939 +void CTCrpAnim::ResetFrameCounters()
   1.940 +	{
   1.941 +	iPreviousFrameNum = KErrNotFound;
   1.942 +	iFrameStatus.iFrameOK = 0;
   1.943 +	iFrameStatus.iFramePartial = 0;
   1.944 +	iFrameStatus.iFrameIdentical = 0;
   1.945 +	iFrameStatus.iFrameEmpty = 0;
   1.946 +	iFrameStatus.iFrameTearing = 0;
   1.947 +	iFrameStatus.iFrameSkipped = 0;
   1.948 +	}
   1.949 +
   1.950 +//
   1.951 +// Log the current frame results & return the total number of frame calculations
   1.952 +//
   1.953 +// Calculated : the total number of frame-checks run
   1.954 +// Good: 		the frame was successfully drawn to screen & within specified tolerances for tearing, expected position & colour
   1.955 +// Partial: 	the frame was only partially drawn to screen. Specifcally the animated red line was only partially drawn
   1.956 +// Identical: 	the frame was in the same position as the last frame
   1.957 +// Empty: 		no redline was detected at all in the frame
   1.958 +// Skipped: 	the position of the frame was beyond the expected position
   1.959 +//
   1.960 +// There is a dependency on the timing as to when the frame is animated hence tolerances are used to allow
   1.961 +// for this. 
   1.962 +// 
   1.963 +TInt CTCrpAnim::LogResults()
   1.964 +	{
   1.965 +	TInt result = iFrameStatus.iFrameOK + iFrameStatus.iFramePartial + iFrameStatus.iFrameIdentical + 
   1.966 +				iFrameStatus.iFrameEmpty + iFrameStatus.iFrameTearing + iFrameStatus.iFrameSkipped;
   1.967 +	INFO_PRINTF4(_L("\tAnimation results:  Calculated[%d], Good[%d], Partial[%d]"), result, iFrameStatus.iFrameOK, iFrameStatus.iFramePartial);
   1.968 +	INFO_PRINTF5(_L("\tAnimation results:  Identical[%d], Empty[%d], Tearing[%d], Skipped[%d]"), iFrameStatus.iFrameIdentical, iFrameStatus.iFrameEmpty, iFrameStatus.iFrameTearing, iFrameStatus.iFrameSkipped);
   1.969 +	return result;
   1.970 +	}
   1.971 +
   1.972 +/** This test tests the result of drawing an animation and main draw to two windows that overlap.
   1.973 +	The two windows are placed in exactly the same location, so the result of splitting the drawing across them should be "identical".
   1.974 +	Note that when the anim and the draw are on different screens the lines are seen merged over the anim.
   1.975 +**/
   1.976 +void CTCrpAnim::TestOverlappingWindowsL()
   1.977 +	{
   1.978 +	if (!iOverWin)
   1.979 +		{
   1.980 +		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
   1.981 +		return;
   1.982 +		}
   1.983 +		
   1.984 +	// setup necessary params
   1.985 +	// Note we place the overlapping transparent window (iOverWin) directly on top of the test window (iTestWin)
   1.986 +	iOverWin->BaseWin()->SetPosition(iTestWin->BaseWin()->Position());
   1.987 +		
   1.988 +	enum 
   1.989 +		{
   1.990 +		 EAllBackground=0,
   1.991 +		 EForegroundDraw=1,
   1.992 +		 EForegroundAnim=2,
   1.993 +		 EAllForeGround=3,
   1.994 +		 ECountModes,
   1.995 +		 EFirstMode=EAllBackground,
   1.996 +		};
   1.997 +	
   1.998 +	// test the various permutations of overlapping vs animated windows
   1.999 +	for (TInt mode = EFirstMode ; mode < ECountModes ; mode++)	    
  1.1000 +		{
  1.1001 +		INFO_PRINTF2(_L("TestOverlappingWindowsL [%d]"), mode);
  1.1002 +		TestSpriteLoopL((mode&EForegroundAnim)!=0,(mode&EForegroundDraw)!=0);
  1.1003 +		}
  1.1004 +	}
  1.1005 +	
  1.1006 +/**
  1.1007 +	This method demonstrates clipping of an animation running behind a transparent window.
  1.1008 +	No main window redraw takes place here.
  1.1009 +**/	
  1.1010 +void CTCrpAnim::DemoClippingWindowsL()
  1.1011 +	{
  1.1012 +	if (!iOverWin)
  1.1013 +		{
  1.1014 +		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
  1.1015 +		return;
  1.1016 +		}
  1.1017 +
  1.1018 +	// setup test case params. Note we calculate three different positions for the overlapping window
  1.1019 +	RWindow* win = iTestWin->Window();
  1.1020 +	
  1.1021 +	TPoint	screenPos= win->Position();
  1.1022 +	TSize screenSize = win->Size();	
  1.1023 +	TRect subposition1(screenSize);
  1.1024 +	CalcCentredAnimPosition(subposition1, screenSize);
  1.1025 +
  1.1026 +	TPoint testPositions[]=
  1.1027 +		{	
  1.1028 +		//first test: window clips corner of anim
  1.1029 +			TPoint(screenPos.iX+screenSize.iWidth/2-10,screenPos.iY+screenSize.iHeight/2-10),
  1.1030 +		//test: window clips all of anim
  1.1031 +			TPoint(screenPos.iX+screenSize.iWidth/3,screenPos.iY+screenSize.iHeight/3),
  1.1032 +		//test: window clips none of anim
  1.1033 +			TPoint(screenPos.iX+screenSize.iWidth*2/3,screenPos.iY+screenSize.iHeight*2/3),
  1.1034 +		};
  1.1035 +
  1.1036 +	// calculate roughly number of frames we expect to have drawn
  1.1037 +	TInt loopWaitTime = KShortDelayLoop; // time given to allow animation to progress (arbitrary number)
  1.1038 +	float expectedFrameCount = 1;
  1.1039 +	if (loopWaitTime > KAnimationFrameDelayTime)
  1.1040 +		{
  1.1041 +		expectedFrameCount = loopWaitTime/KAnimationFrameDelayTime;
  1.1042 +		}
  1.1043 +
  1.1044 +	for (TInt ii = 0; ii < ((sizeof testPositions)/(sizeof testPositions[0])) ; ii++)
  1.1045 +		{
  1.1046 +		// initialise test windows to known state with no active animations
  1.1047 +		ResetFrameCounters();
  1.1048 +		iTestWin->RemoveAnimation(KUidTestAnimation2);
  1.1049 +		iTestWin->SetBlankIt(EFalse);		
  1.1050 +		iOverWin->SetBlankIt(ETrue);		
  1.1051 +		iOverWin->RemoveAnimation(KUidTestAnimation2);
  1.1052 +
  1.1053 +		// position animation windows
  1.1054 +		iTestWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
  1.1055 +		iTestWin->SetPosAnimation(KUidTestAnimation2, subposition1);
  1.1056 +		iOverWin->BaseWin()->SetPosition(testPositions[ii]); // positions the transparent overlapping window
  1.1057 +
  1.1058 +		// redraw both test windows
  1.1059 +		iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
  1.1060 +		iOverWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
  1.1061 +
  1.1062 +		// run the animation for an arbitrary period
  1.1063 +		for (TInt loopit = 0 ; loopit < 20 ; loopit++)
  1.1064 +			{
  1.1065 +			iWaiter->Wait(loopWaitTime);	
  1.1066 +			CheckAnimProgressedL(iTestWin,static_cast<TInt>(expectedFrameCount)); // log the frame result
  1.1067 +			}
  1.1068 +
  1.1069 +		// calculate & log frame results. Test an acceptable number of frames were successfully animated
  1.1070 +		TInt total = LogResults();
  1.1071 +		TInt qA = 100*iFrameStatus.iFrameOK/total;
  1.1072 +		TEST(qA > KMinGoodFrameThreshold);
  1.1073 +		}
  1.1074 +	}
  1.1075 +
  1.1076 +/**	In this version, the background window is updated in patches. 
  1.1077 +	If the animation intersects the transparent window then the whole transparent window is redrawn.
  1.1078 +**/	
  1.1079 +void CTCrpAnim::TestClippingWindowsL()
  1.1080 +	{
  1.1081 +	if (!iOverWin)
  1.1082 +		{
  1.1083 +		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
  1.1084 +		return;
  1.1085 +		}
  1.1086 +	// setup test case params. Note we calculate three different positions for the overlapping window
  1.1087 +	RWindow* win = iTestWin->Window();
  1.1088 +	TPoint screenPos= win->Position();
  1.1089 +	TSize screenSize = win->Size();	
  1.1090 +	
  1.1091 +	TPoint testPositions[]=
  1.1092 +		{	
  1.1093 +		//first test: window clips corner of anim
  1.1094 +			TPoint(screenPos.iX+screenSize.iWidth/2-10,screenPos.iY+screenSize.iHeight/2-10),
  1.1095 +		//test: window clips all of anim
  1.1096 +			TPoint(screenPos.iX+screenSize.iWidth/3,screenPos.iY+screenSize.iHeight/3),
  1.1097 +		//test: window clips none of anim
  1.1098 +			TPoint(screenPos.iX+screenSize.iWidth*2/3,screenPos.iY+screenSize.iHeight*2/3),
  1.1099 +		};
  1.1100 +
  1.1101 +	for (TInt loopIt = 0; loopIt < ((sizeof testPositions)/(sizeof testPositions[0])) ; loopIt++)
  1.1102 +		{
  1.1103 +	    iOverWin->BaseWin()->SetPosition(testPositions[loopIt]); // position the overlapping window
  1.1104 +	    TestSpriteLoopL(EFalse,EFalse);
  1.1105 +		}
  1.1106 +	}
  1.1107 +
  1.1108 +/**	This just demonstrates that an animation plays - for about 1 second.
  1.1109 +**/
  1.1110 +void CTCrpAnim::BasicCRPDemo()
  1.1111 +	{
  1.1112 +	// draw the animation in two positions
  1.1113 +	TSize subsize1 = iTestWin->BaseWin()->Size();
  1.1114 +	TRect subposition1(subsize1);
  1.1115 +	CalcCentredAnimPosition(subposition1, subsize1);
  1.1116 +	
  1.1117 +	if (iOverWin)
  1.1118 +		{
  1.1119 +		iOverWin->BaseWin()->SetPosition(KPointOffsite);	//way away!
  1.1120 +		iOverWin->InvalidateAndRedraw(EFalse,EFalse,ETrue);
  1.1121 +		}
  1.1122 +		
  1.1123 +	CCrpAnim *animWin= iTestWin;
  1.1124 +	animWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
  1.1125 +	animWin->SetPosAnimation(KUidTestAnimation2, subposition1);
  1.1126 +	iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
  1.1127 +	iBaseWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
  1.1128 +
  1.1129 +	// allow the animation to play for ~1 second. Purpose is to demonstrate animation to an observer	
  1.1130 +	iWaiter->Wait(KShortDelayLoop);
  1.1131 +	
  1.1132 +	ResetFrameCounters();
  1.1133 +	iWaiter->Cancel();
  1.1134 +	iTestWin->RemoveAnimation(KUidTestAnimation2);
  1.1135 +	}
  1.1136 +
  1.1137 +/**
  1.1138 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0001
  1.1139 +
  1.1140 +@SYMDEF             DEF100356
  1.1141 +
  1.1142 +@SYMTestCaseDesc    CRP animation test for redraw storing interrupting main draw
  1.1143 +
  1.1144 +@SYMTestPriority    High
  1.1145 +
  1.1146 +@SYMTestStatus      Implemented
  1.1147 +
  1.1148 +@SYMTestActions     Creates a CRP animation and runs it on the server scheduler 
  1.1149 +					while also running redraws of the window.
  1.1150 +					
  1.1151 +					With Redraw storing this has been known to cause problems 
  1.1152 +					sharing and resetting the window iDisplayRegion.
  1.1153 +					This is evidenced by white areas.
  1.1154 +
  1.1155 +
  1.1156 +@SYMTestExpectedResults 
  1.1157 +					The LHS window shows what the animation should look like just animating,
  1.1158 +					while the RHS window demonstrates the simultanious animation and redraw.
  1.1159 +					No White patches should be in evidence, and no missing fragments of animation.
  1.1160 +					The TEST should detect white patches.
  1.1161 +*/
  1.1162 +void CTCrpAnim::TestSpriteInterruptsForegroundL()
  1.1163 +	{	
  1.1164 +	// setup test params
  1.1165 +	TSize subsize1(iTestWin->BaseWin()->Size());
  1.1166 +	TRect subposition1(subsize1);
  1.1167 +	CalcCentredAnimPosition(subposition1, subsize1);
  1.1168 +	if (iOverWin)
  1.1169 +		{
  1.1170 +		iOverWin->BaseWin()->SetPosition(KPointOffsite);	// ensure overlapping transparent window DOESN'T overlap the test window
  1.1171 +		}
  1.1172 +
  1.1173 +	// execute test loop
  1.1174 +	TestSpriteLoopL(EFalse,EFalse);
  1.1175 +	}
  1.1176 +
  1.1177 +void CTCrpAnim::RunTestCaseL(TInt /*aCurTestCase*/)
  1.1178 +	{
  1.1179 +	_LIT(KTest1,"1: Basic CRP demo");
  1.1180 +	_LIT(KTest2,"2: sprite anim interrupts foreground");
  1.1181 +	_LIT(KTest3,"3: translucent windows");
  1.1182 +	_LIT(KTest4,"4: CRP clipping windows");
  1.1183 +	_LIT(KTest5,"5: CRP & redraw clipping windows");
  1.1184 +	_LIT(KTest6,"6: CRP Invalidation");
  1.1185 +
  1.1186 +	((CTCrpAnimStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
  1.1187 +	switch(++iTest->iState)
  1.1188 +		{
  1.1189 +		case 1:
  1.1190 +/**
  1.1191 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0002
  1.1192 +*/
  1.1193 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0002"));
  1.1194 +			iTest->LogSubTest(KTest1);
  1.1195 +			BasicCRPDemo();
  1.1196 +			break;
  1.1197 +		case 2:
  1.1198 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0001"));
  1.1199 +			iTest->LogSubTest(KTest2);
  1.1200 +			TestSpriteInterruptsForegroundL();
  1.1201 +			break;
  1.1202 +		case 3:
  1.1203 +/**
  1.1204 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0003
  1.1205 +*/
  1.1206 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0003"));
  1.1207 +			iTest->LogSubTest(KTest3);
  1.1208 +			TestOverlappingWindowsL();
  1.1209 +			break;
  1.1210 +		case 4:
  1.1211 +/**
  1.1212 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0004
  1.1213 +*/
  1.1214 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0004"));
  1.1215 +			iTest->LogSubTest(KTest4);
  1.1216 +			DemoClippingWindowsL();
  1.1217 +			break;
  1.1218 +		case 5:
  1.1219 +/**
  1.1220 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0005
  1.1221 +*/
  1.1222 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0005"));
  1.1223 +			iTest->LogSubTest(KTest5);
  1.1224 +			TestClippingWindowsL();
  1.1225 +			break;
  1.1226 +		case 6:
  1.1227 +/**
  1.1228 +@SYMTestCaseID		GRAPHICS-WSERV-CRP01-0006
  1.1229 +*/
  1.1230 +			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0006"));
  1.1231 +			iTest->LogSubTest(KTest6);
  1.1232 +			//this testcase is removed, because invalidation is removed from CWsGraphicDrawer destructor (due to flickering)
  1.1233 +			break;
  1.1234 +		default:
  1.1235 +			((CTCrpAnimStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
  1.1236 +			((CTCrpAnimStep*)iStep)->CloseTMSGraphicsStep();
  1.1237 +			TestComplete();
  1.1238 +		}
  1.1239 +	((CTCrpAnimStep*)iStep)->RecordTestResultL();
  1.1240 +	}
  1.1241 +
  1.1242 +//
  1.1243 +namespace	//anonymous namespace
  1.1244 +	{
  1.1245 +//
  1.1246 +	CAnimRedrawWindow::CAnimRedrawWindow(CCrpAnim *aAnimWindow, TBool aIsBase) : CTWin(),
  1.1247 +		iAnimWindow(aAnimWindow),
  1.1248 +		iIsBase(aIsBase)
  1.1249 +		{
  1.1250 +		}
  1.1251 +
  1.1252 +	CAnimRedrawWindow::~CAnimRedrawWindow()
  1.1253 +		{
  1.1254 +		}
  1.1255 +
  1.1256 +	void CAnimRedrawWindow::Draw()
  1.1257 +		{
  1.1258 +		CCrpAnim::Draw(Gc(),Size(),iIsBase,iAnimWindow->iRect,iAnimWindow->iBlankIt,iAnimWindow->iRepeatDrawMax,iAnimWindow->iAlphaValue);
  1.1259 +		if (iAnimWindow->iAnimUid!=TUid::Null())
  1.1260 +			{
  1.1261 +			TheClient->Flush();
  1.1262 +			Gc()->DrawWsGraphic(iAnimWindow->iAnimUid,iAnimWindow->iAnimPos,iAnimWindow->iAnimData.Pckg());
  1.1263 +			TheClient->Flush();
  1.1264 +			}
  1.1265 +		}
  1.1266 +
  1.1267 +	//
  1.1268 +
  1.1269 +	CCrpAnim::CCrpAnim(TBool aIsBase, TWinType aWinType) 
  1.1270 +	:	iWinType(aWinType), 
  1.1271 +		iIsBase(aIsBase),
  1.1272 +		iBlankIt(EFalse),
  1.1273 +		iRepeatDrawMax(1),
  1.1274 +		iAnimUid(TUid::Null()),
  1.1275 +		iAlphaValue(ENoTransparency)
  1.1276 +		{
  1.1277 +		}
  1.1278 +
  1.1279 +	CCrpAnim::~CCrpAnim()
  1.1280 +		{
  1.1281 +		delete iCtWin;
  1.1282 +		}
  1.1283 +
  1.1284 +	void CCrpAnim::ConstructL(const TPoint &aPos, const TSize &aSize, TInt aAlphaValue)
  1.1285 +		{
  1.1286 +		TDisplayMode reqMode = EColor16MA; //for transparency we need 16ma or 16map mode
  1.1287 +		TDisplayMode *pReqMode=&reqMode;	
  1.1288 +		switch(iWinType)
  1.1289 +			{
  1.1290 +			case ERedraw:
  1.1291 +				iCtWin = new(ELeave) CAnimRedrawWindow(this, iIsBase);
  1.1292 +				break;
  1.1293 +			case EBlank:
  1.1294 +				iCtWin = new(ELeave) CTBlankWindow();
  1.1295 +				break;
  1.1296 +			case EBackedUp:
  1.1297 +				iCtWin = new(ELeave) CTBackedUpWin(EColor64K);
  1.1298 +				pReqMode = NULL;
  1.1299 +				break;
  1.1300 +			}
  1.1301 +		iCtWin->SetUpL(aPos, aSize, TheClient->iGroup, *TheClient->iGc, pReqMode, ETrue);
  1.1302 +		if (aAlphaValue != ENoTransparency)
  1.1303 +			{
  1.1304 +			User::LeaveIfError(Window()->SetTransparencyAlphaChannel());
  1.1305 +			//the window itself should be completely transparent, the draw commands will use the alpha value
  1.1306 +			Window()->SetBackgroundColor(TRgb(0, 0, 0, 0));
  1.1307 +			iAlphaValue = aAlphaValue;
  1.1308 +			}
  1.1309 +		}
  1.1310 +
  1.1311 +	void CCrpAnim::SetEllipseDrawMode(CGraphicsContext::TDrawMode aEllipseDrawMode)
  1.1312 +		{
  1.1313 +		iEllipseDrawMode = aEllipseDrawMode;
  1.1314 +		}
  1.1315 +
  1.1316 +	void CCrpAnim::DrawEllipse(CBitmapContext *aGc, const TRect &aRect, TInt aAlphaValue)
  1.1317 +		{
  1.1318 +		if(aAlphaValue != ENoTransparency)
  1.1319 +			{
  1.1320 +			aGc->SetBrushColor(TRgb(85,85,85, aAlphaValue));
  1.1321 +			aGc->SetPenColor(TRgb(170,170,170, aAlphaValue));
  1.1322 +			}
  1.1323 +		else
  1.1324 +			{
  1.1325 +			aGc->SetBrushColor(TRgb(85,85,85));
  1.1326 +			aGc->SetPenColor(TRgb(170,170,170));
  1.1327 +			}
  1.1328 +		aGc->SetDrawMode(iEllipseDrawMode);
  1.1329 +		aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
  1.1330 +		aGc->DrawEllipse(aRect);
  1.1331 +		}
  1.1332 +
  1.1333 +	void CCrpAnim::Draw(CBitmapContext *aGc, const TSize &aSize, TBool aIsBase, const TRect &aRect, TBool aBlankIt,TInt aRepeat, TInt aAlphaValue)
  1.1334 +		{
  1.1335 +		static TInt sGrey=0;
  1.1336 +		sGrey+=3;
  1.1337 +		if (sGrey>0x40)
  1.1338 +			sGrey-=0x40;		
  1.1339 +		sGrey=sGrey^0x20;
  1.1340 +		if(aAlphaValue != ENoTransparency)
  1.1341 +			{
  1.1342 +			aGc->SetBrushColor(TRgb(sGrey, sGrey, sGrey, aAlphaValue));
  1.1343 +		    aGc->SetPenColor(TRgb(KRgbGreen.Value(), aAlphaValue));
  1.1344 +			}
  1.1345 +		else
  1.1346 +			{		
  1.1347 +			aGc->SetBrushColor(TRgb::Gray256(sGrey));
  1.1348 +		    aGc->SetPenColor(KRgbGreen);
  1.1349 +			}
  1.1350 +		aGc->Clear();
  1.1351 +	    TInt xPos=aSize.iHeight,yPos=aSize.iWidth;
  1.1352 +	    
  1.1353 +	    // The test windows are created relative to screen size. The
  1.1354 +	    // number of green lines generated needs to be tied into the
  1.1355 +	    // window size to prevent green becoming the dominant colour
  1.1356 +	    // when blended with the second animation, which would
  1.1357 +	    // prevent the PredominantColour() algorithm from discovering
  1.1358 +	    // the red line.
  1.1359 +	    TInt yStep = aSize.iHeight/14;
  1.1360 +	    TInt xStep = aSize.iWidth/6;
  1.1361 +	    
  1.1362 +	    //This paint is intentionally complex and slow so that the animation timer is likely to interrupt it.
  1.1363 +		if (!aBlankIt)
  1.1364 +		 for (TInt nn = 0 ; nn < aRepeat ; nn++)
  1.1365 +			for(yPos=0 ; yPos < aSize.iHeight ; yPos += yStep)
  1.1366 +				for(xPos=0 ; xPos < aSize.iWidth ; xPos += xStep)
  1.1367 +					aGc->DrawLine(aRect.Center(),TPoint(xPos,yPos));
  1.1368 +		if (aIsBase)
  1.1369 +			DrawEllipse(aGc, aRect, aAlphaValue);			
  1.1370 +		}
  1.1371 +
  1.1372 +	//This simple API may need replacing by a list and search if multiple anims are played together
  1.1373 +	TWsGraphicAnimation* CCrpAnim::SetAnimation(TUid aUid)
  1.1374 +		{	//currently only have 1 animation - it gets replaced. It could get refiused
  1.1375 +		iAnimUid=aUid;
  1.1376 +		return &iAnimData;	
  1.1377 +		}
  1.1378 +
  1.1379 +	TWsGraphicAnimation* CCrpAnim::GetAnimation(TUid aUid)
  1.1380 +		{   //currently only have 1 animation
  1.1381 +		if (iAnimUid==aUid)
  1.1382 +			return &iAnimData;	
  1.1383 +		else
  1.1384 +			return NULL;
  1.1385 +		}
  1.1386 +		
  1.1387 +	void CCrpAnim::SetPosAnimation(const TUid& aUid, const TRect& aRect)
  1.1388 +		{   //currently only have 1 animation
  1.1389 +		if (iAnimUid==aUid)
  1.1390 +			iAnimPos = aRect;
  1.1391 +		}
  1.1392 +	
  1.1393 +	TRect* CCrpAnim::GetPosAnimation(const TUid& aUid)
  1.1394 +		{   //currently only have 1 animation
  1.1395 +		if (iAnimUid==aUid)
  1.1396 +			return &iAnimPos;	
  1.1397 +		else
  1.1398 +			return NULL;
  1.1399 +		}
  1.1400 +	
  1.1401 +	TBool CCrpAnim::RemoveAnimation(TUid)
  1.1402 +		{
  1.1403 +		iAnimUid=TUid::Null();
  1.1404 +		iAnimData.Stop(EFalse);		
  1.1405 +		return ETrue;
  1.1406 +		}	
  1.1407 +
  1.1408 +	void CCrpAnim::DoDraw()
  1.1409 +		{
  1.1410 +		DoDraw(iBlankIt);
  1.1411 +		}
  1.1412 +
  1.1413 +	inline void CCrpAnim::DoDraw(TBool aBlankIt)
  1.1414 +		{
  1.1415 +		__ASSERT_ALWAYS(iWinType!=EBlank,AutoPanic(EAutoPanicWindowType));
  1.1416 +		iCtWin->Gc()->Activate(*Window());
  1.1417 +		Draw(iCtWin->Gc(),Size(),iIsBase,iRect,aBlankIt,iRepeatDrawMax,iAlphaValue);
  1.1418 +		if (iAnimUid!=TUid::Null())
  1.1419 +			iCtWin->Gc()->DrawWsGraphic(iAnimUid,iAnimPos,iAnimData.Pckg());
  1.1420 +		iCtWin->Gc()->Deactivate();
  1.1421 +		}
  1.1422 +		
  1.1423 +	void CCrpAnim::DoDrawEllipse()
  1.1424 +		{
  1.1425 +		__ASSERT_ALWAYS(iWinType!=EBlank,AutoPanic(EAutoPanicWindowType));
  1.1426 +		iCtWin->Gc()->Activate(*Window());
  1.1427 +		DrawEllipse(iCtWin->Gc(),iRect,iAlphaValue);
  1.1428 +		iCtWin->Gc()->Deactivate();
  1.1429 +		}
  1.1430 +
  1.1431 +	void CCrpAnim::InvalidateAndRedraw(TBool /*aUseBlankItMember*/,TBool /*aBlankIt*/,TBool aUseRWindowInvalidate,TRect* aRect)
  1.1432 +		{
  1.1433 +		RWindow& win = *Window();
  1.1434 +		if (aRect)
  1.1435 +			{
  1.1436 +			if (aUseRWindowInvalidate)
  1.1437 +				win.Invalidate(*aRect);
  1.1438 +			else
  1.1439 +				Invalidate(*aRect);
  1.1440 +			}
  1.1441 +		else
  1.1442 +			{
  1.1443 +			if (aUseRWindowInvalidate)
  1.1444 +				win.Invalidate();
  1.1445 +			else
  1.1446 +				Invalidate();
  1.1447 +			}
  1.1448 +		if (aRect)
  1.1449 +			win.BeginRedraw(*aRect);
  1.1450 +		else
  1.1451 +			win.BeginRedraw();
  1.1452 +		DoDraw();
  1.1453 +		win.EndRedraw();
  1.1454 +		TheClient->Flush();
  1.1455 +		}
  1.1456 +		
  1.1457 +	void CCrpAnim::Invalidate(const TRect &aRect)
  1.1458 +		{
  1.1459 +		TRect rect(aRect);
  1.1460 +		rect.Move(iCtWin->Position());
  1.1461 +		CTUser::Splat(TheClient,rect,TRgb::Gray256(0));
  1.1462 +		}
  1.1463 +
  1.1464 +//
  1.1465 +	}	//end anonymous namespace
  1.1466 +//
  1.1467 +__WS_CONSTRUCT_STEP__(CrpAnim)