windowing/windowserver/tauto/tcrpanim.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements  CTCrpAnim
       
    15 // Test CRP animations & their interaction with overlapping transparent/non-transparent windows 
       
    16 // & wserv's underlying redraw-store strategies
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22  @test
       
    23  @internalComponent - Internal Symbian test code
       
    24 */
       
    25 
       
    26 #include <w32stdgraphic.h>
       
    27 #include "tcrpanim.h"
       
    28 
       
    29 // RUN_SAMPLE_ON_LEFT allows the demo animation to run in the left-hand window during testing. 
       
    30 // Used for demonstration purposes only
       
    31 #define RUN_SAMPLE_ON_LEFT
       
    32 
       
    33 namespace	//anonymous local scope
       
    34 	{
       
    35 	const TInt KAnimationFrameDelayTime = 50000; 				// delay in microseconds between frames
       
    36 	const TInt KShortDelayLoop = 2*KAnimationFrameDelayTime; 	// delay time in microseconds used in test cases
       
    37 	const TInt KAnimationTotalFrames = 40;						// total number of frames in a CWsGraphicBitmapAnimation
       
    38 	const TInt KAnimDimension = 40;								// animation width/height. We're enforcing a square animation here
       
    39 	const TInt KFrameMissedAnimationsThreshold = 10;			// maximum number of missed frame steps allowed
       
    40 	const TInt KAnimationTearWidthThreshold = 4; 				// maximum columns permitted between a tear
       
    41 	const TInt KMinGoodFrameThreshold = 30; 					// percentage threshold for number of good frames detected in a test
       
    42 	const TInt KMaxXY = 200;									// arbitrary maximum size of square used to invalidate a window
       
    43 	const TInt KMaxRepeatDraw = 2;								// arbitrary value for DrawLine calls during a Draw
       
    44 	TUid  KUidTestAnimation2 = {0xBAADF00D};					// unique id. for CWsGraphicBitmapAnimation object
       
    45 	const TUint32 KWhitePixels = 0xFFFFFFFF;					// 32-bit mask value for rgb white
       
    46 	const TUint32 KBlackPixels = 0x00000000;					// 32-bit value for rgb black
       
    47 	const TPoint KPointZero(0,0);								// initial point used for animation creation & manipulation (currently 0,0)
       
    48 	const TPoint KPointOffsite(1000,1000);						// point used to draw off-screen
       
    49 	const TDisplayMode KTestDisplayMode = EColor16MU;			// display mode used for testing
       
    50 	const TInt KFrameStepCalculation = Max(1, KAnimDimension/Max(1, KAnimationTotalFrames)); // determine framestep size in columns
       
    51 	
       
    52 	enum TColorDetected
       
    53 		{
       
    54 		ECantTell=0,
       
    55 		EDetRed=1,
       
    56 		EDetGreen=2,
       
    57 		EDetBlue=4,
       
    58 		EDetBlack=0x10,
       
    59 		EDetGrey=0x20,
       
    60 		EDetWhite=0x40
       
    61 		};
       
    62 
       
    63 	class CCrpAnim;		
       
    64 	class CAnimRedrawWindow : public CTWin
       
    65 		{
       
    66 	public:
       
    67 		CAnimRedrawWindow(CCrpAnim *aAnimWindow, TBool aIsBase);
       
    68 		~CAnimRedrawWindow();
       
    69 		void Draw();
       
    70 	private:
       
    71 		CCrpAnim *iAnimWindow;
       
    72 		TBool iIsBase;
       
    73 		};
       
    74 		
       
    75 	class CCrpAnim : public CBase
       
    76 		{
       
    77 		friend class CAnimRedrawWindow;
       
    78 	public:
       
    79 		enum TWinType
       
    80 			{
       
    81 			ERedraw,
       
    82 			EBlank,		// note: not currently used in tcrpanim tests
       
    83 			EBackedUp	// note: not currently used in tcrpanim tests
       
    84 			};
       
    85 	public:
       
    86 		CCrpAnim(TBool aIsBase, TWinType aWinType);
       
    87 		~CCrpAnim();
       
    88 		enum 
       
    89 			{
       
    90 			ENoTransparency=0x100
       
    91 			};
       
    92 		void ConstructL(const TPoint &aPos, const TSize &aSize,const TInt aAlphaValue=ENoTransparency);
       
    93 		void DoDraw(TBool aBlankIt);
       
    94 		inline void DoDraw();
       
    95 		void DoDrawEllipse();
       
    96 		inline TSize Size() {return iCtWin->Size();};
       
    97 		inline RWindowBase* BaseWin() const {return iCtWin->BaseWin();};
       
    98 		inline RWindow* Window() const {return STATIC_CAST(RWindow*, iCtWin->BaseWin());};
       
    99 		inline CTBaseWin* CtBaseWin() {return iCtWin;};
       
   100 		inline void Invalidate() {CTUser::Splat(TheClient, TRect(iCtWin->Position(), iCtWin->Size()), KRgbGray);};
       
   101 		void Invalidate(const TRect &aRect);
       
   102 		static void SetEllipseDrawMode(CGraphicsContext::TDrawMode aEllipseDrawMode);
       
   103 		void InvalidateAndRedraw(TBool aUseBlankItMember,TBool aBlankIt,TBool aUseRWindowInvalidate,TRect* aRect=NULL);
       
   104 
       
   105 		//A bit of an animation interface...
       
   106 		//I have written this interface to be amenable to playing multiple animations,
       
   107 		//which I think needs testing,
       
   108 		//but the underlying implementation assumes one animation at present.
       
   109 		//Your mission, should you choose to accept it, ....
       
   110 		
       
   111 		void SetPosAnimation(const TUid& aUid, const TRect& aRect);
       
   112 		TRect* GetPosAnimation(const TUid& aUid);
       
   113 		TWsGraphicAnimation* SetAnimation(TUid);	
       
   114 		TWsGraphicAnimation* GetAnimation(TUid);	
       
   115 		TBool RemoveAnimation(TUid);	
       
   116 		inline void	SetBlankIt(TBool aNewVal) {iBlankIt = aNewVal;};
       
   117 		inline void SetRepeatDrawMax(TInt aVal) {iRepeatDrawMax = aVal;};
       
   118 	protected:
       
   119 		static void Draw(CBitmapContext *aGc, const TSize &aSize, TBool aIsBase,const TRect &aRect, TBool aBlankIt,TInt aRepeat, TInt aAlphaValue);
       
   120 		static void DrawEllipse(CBitmapContext *aGc, const TRect &aRect, TInt aAlphaValue);
       
   121 		CTBaseWin *iCtWin;
       
   122 		TWinType iWinType;
       
   123 		TBool iIsBase;
       
   124 		TBool iBlankIt;
       
   125 		TRect iRect;
       
   126 		TInt  iRepeatDrawMax;
       
   127 		static CGraphicsContext::TDrawMode iEllipseDrawMode;
       
   128 		TUid  iAnimUid;
       
   129 		TWsGraphicAnimation iAnimData;
       
   130 		TRect iAnimPos;
       
   131 		TInt iAlphaValue;
       
   132 		};
       
   133 
       
   134 /*	    Using this time delay class in order to allow animations to play in our draw.
       
   135 		User::Wait does not allow the draw to occur (aparrently)
       
   136 		Note when using this time-delay class: because other active objects can perform part of their
       
   137 	    processing whilst we wait, wrapping calls to this in __UHEAP_MARK / __UHEAP_MARKEND
       
   138 	    is likely to fail.  The data providers and animators are a major cause of this. 
       
   139 */
       
   140 	class CActiveWait : public CActive
       
   141 		{
       
   142 	public:
       
   143 		static CActiveWait* NewL();
       
   144 		~CActiveWait();
       
   145 		void Wait(TInt aDelay);
       
   146 		// From CActive:
       
   147 		void RunL();
       
   148 		void DoCancel();
       
   149 		TInt RunError(TInt aError);
       
   150 	protected:
       
   151 		CActiveWait();
       
   152 		void ConstructL();
       
   153 	protected:
       
   154 		RTimer iTimer;
       
   155 		TTime iFromTime;
       
   156 		};
       
   157 
       
   158 	CActiveWait* CActiveWait::NewL()
       
   159 		{
       
   160 		CActiveWait* self = new (ELeave) CActiveWait;
       
   161 		CleanupStack::PushL(self);
       
   162 		self->ConstructL();
       
   163 		CleanupStack::Pop(self);
       
   164 		return self;
       
   165 		}
       
   166 		
       
   167 	void CActiveWait::ConstructL()
       
   168 		{
       
   169 		User::LeaveIfError(iTimer.CreateLocal());
       
   170 		CActiveScheduler::Add(this);
       
   171 		}
       
   172 		
       
   173 	CActiveWait::CActiveWait() : CActive(EPriorityNormal)
       
   174 		{
       
   175 		iFromTime.HomeTime();
       
   176 		}
       
   177 
       
   178 	CActiveWait::~CActiveWait()
       
   179 		{
       
   180 		Cancel();
       
   181 		iTimer.Close();
       
   182 		}
       
   183 
       
   184 	void CActiveWait::DoCancel()
       
   185 		{
       
   186 		iTimer.Cancel();
       
   187 		CActiveScheduler::Stop();
       
   188 		}
       
   189 
       
   190 	void CActiveWait::RunL()
       
   191 		{
       
   192 		CActiveScheduler::Stop();
       
   193 		}
       
   194 		
       
   195 	TInt CActiveWait::RunError(TInt aError)
       
   196 		{
       
   197 		return aError; // exists so a break point can be placed on it.
       
   198 		}
       
   199 
       
   200 /*	    Note when using this : because other active objects can perform part of their
       
   201 	    processing whilst we wait, wrapping calls to this in __UHEAP_MARK / __UHEAP_MARKEND
       
   202 	    is likely to fail.  The data providers and animators are a major cause of this. 
       
   203 */
       
   204 	void CActiveWait::Wait(TInt aDelay)
       
   205 		{
       
   206 		iTimer.After(iStatus, aDelay);
       
   207 		SetActive();
       
   208 		CActiveScheduler::Start();
       
   209 		}
       
   210 	CGraphicsContext::TDrawMode CCrpAnim::iEllipseDrawMode;
       
   211 
       
   212 //
       
   213 	}	//end anonymous local scope
       
   214 //
       
   215 
       
   216 /** This fn allocates an animation frame of the specified dimensions.
       
   217 	Not tested outside the current limited parameter set (16/2/2007).
       
   218 	Note the use of 32-bit integers for pixel/colour values. Using display mode lower than 24bpp may not produce correct results
       
   219 	My attempt to write animation generating code that avoids CIclLoader and Decoder class.
       
   220 	@param aDelayUs	 	the display time for the frame
       
   221 	@param aImageType	Colour format for colour plane. 24MA currently not flagged correctly I expect.
       
   222 	@param aMaskType	Format for mask. ENone for no mask.
       
   223 	@param aImageSize	Width/height of bitmap area
       
   224 	@param aImageOffset	Optional offset for bitmap area
       
   225 	@param aTotalSize	Optional width/height of whole animation (I think)
       
   226 	@return CFrame		filled in with allocated bitmaps. The get methods for the bitmaps return const type.
       
   227 **/
       
   228 static CWsGraphicBitmapAnimation::CFrame* NewFrameLC(TInt aDelayUs,TDisplayMode aImageType,TDisplayMode aMaskType,const TSize& aImageSize,const TPoint& aImageOffset=KPointZero,const TSize& aTotalSize=TSize(0,0))
       
   229 	{
       
   230 	TFrameInfo info;
       
   231 	info.iFrameCoordsInPixels = TRect(aImageOffset,aImageSize);
       
   232 	info.iFrameSizeInTwips = aImageSize;	  //this is zero in the gif loader
       
   233 	info.iDelay = TTimeIntervalMicroSeconds(aDelayUs);
       
   234 	info.iFlags = TFrameInfo::EColor|TFrameInfo::ELeaveInPlace|TFrameInfo::EUsesFrameSizeInPixels;
       
   235 	if (aMaskType != ENone)
       
   236 		{
       
   237 		info.iFlags|=TFrameInfo::ETransparencyPossible;
       
   238 		}
       
   239 	if ((aTotalSize.iHeight > 0) && (aTotalSize.iWidth > 0))
       
   240 		{
       
   241 		// restrict the size of the frame to specified size of the animation
       
   242 		info.iOverallSizeInPixels = aTotalSize;
       
   243 		}
       
   244 	else
       
   245 		{
       
   246 		// assign the size of the frame to the size of the entire bitmap area
       
   247 		info.iOverallSizeInPixels = info.iFrameCoordsInPixels.iBr.AsSize();
       
   248 		}
       
   249 	info.iFrameDisplayMode = aImageType;
       
   250 	info.iBackgroundColor = KRgbGreen;
       
   251 
       
   252 	CWsGraphicBitmapAnimation::CFrame* frame = CWsGraphicBitmapAnimation::CFrame::NewL();
       
   253 	CleanupStack::PushL(frame);
       
   254 	frame->SetFrameInfo(info);
       
   255 	CFbsBitmap* bitmap = new(ELeave) CFbsBitmap;
       
   256 	frame->SetBitmap(bitmap); //takes ownership
       
   257 	TSize frameInfoSize = info.iFrameCoordsInPixels.Size();
       
   258 	User::LeaveIfError(bitmap->Create(frameInfoSize, aImageType));
       
   259 	if((TFrameInfo::EAlphaChannel|TFrameInfo::ETransparencyPossible) & info.iFlags)
       
   260 		{
       
   261 		CFbsBitmap* mask = new(ELeave) CFbsBitmap;
       
   262 		frame->SetMask(mask); //takes ownership
       
   263 		User::LeaveIfError(mask->Create(frameInfoSize, aMaskType));
       
   264 		}
       
   265 	return frame;
       
   266 	}
       
   267 
       
   268 //
       
   269 // function called back by TCleanupItem frameListCleanup from within CreateAnimFramesL(..) method
       
   270 //
       
   271 void CleanupFrameList(TAny* aPtr)
       
   272 	{
       
   273 	RPointerArray<CWsGraphicBitmapAnimation::CFrame>* ptrArray = STATIC_CAST(RPointerArray<CWsGraphicBitmapAnimation::CFrame>*, aPtr);
       
   274 	ptrArray->ResetAndDestroy();
       
   275 	ptrArray->Close();
       
   276 	}
       
   277 
       
   278 /** Helper function for making animation frames.
       
   279 	//Called from CreateAnimL(...)
       
   280 	@param aDelayUs		the delay between frames
       
   281 	@param aNumFrames	number of frames (approx - image width is a factor)
       
   282 	@param aImageType	colour format of colour data. This may not work properly for non-32-bit, but I haven't fully understood TBitmapUtil documentation.
       
   283 	@param aMaskType	format for mask - ENone for no mask.
       
   284 	@param aImageSize	width/height of animation
       
   285 	@param aBgCol		background colour for image non-masked areas. Masked areas are black.
       
   286 	@param aFgCol		foreground colour of animating area
       
   287 	@param aFrames		frames that the animation is constructed from
       
   288 **/
       
   289 static void CreateAnimFramesL(TInt aDelayUs,TInt aNumFrames,TDisplayMode aImageType,TDisplayMode aMaskType,TSize aImageSize,TRgb aBgCol,TRgb aFgCol, RPointerArray<CWsGraphicBitmapAnimation::CFrame>& aFrames)
       
   290 	{
       
   291 	const TInt 	animWH = aImageSize.iWidth;
       
   292 	const TInt	animStep = Max(1,animWH/Max(1,aNumFrames));	//note this intentionally rounds down to avoid overflows
       
   293 	for (TInt ii = 0 ; ii < animWH ; ii += animStep)
       
   294 		{
       
   295 		CWsGraphicBitmapAnimation::CFrame* frame = NewFrameLC(aDelayUs,aImageType,aMaskType,aImageSize,KPointZero,aImageSize);
       
   296 		aFrames.AppendL(frame);
       
   297 		CleanupStack::Pop(frame);
       
   298 		TBitmapUtil utilMask(CONST_CAST(CFbsBitmap*, frame->Mask()));
       
   299 		TBitmapUtil utilCol(CONST_CAST(CFbsBitmap*, frame->Bitmap()));
       
   300 		utilCol.Begin(KPointZero);
       
   301 		
       
   302 		// cycle through the frame's actual bitmap & assign each pixel a value identical to the specified colours
       
   303 		TUint32 colback=aBgCol.Internal();
       
   304 		TUint32 colfront=aFgCol.Internal();
       
   305 		TInt row = KErrNone;
       
   306 		TInt col = KErrNone;
       
   307 		for (row = 0 ; row < aImageSize.iHeight ; row++)
       
   308 			{
       
   309 			utilCol.SetPos(TPoint(0, row));
       
   310 			for (col = 0 ; col < aImageSize.iWidth ; col++)
       
   311 				{
       
   312 				utilCol.SetPixel(colback);	
       
   313 				utilCol.IncXPos();
       
   314 				}
       
   315 			utilCol.SetPos(TPoint(ii, row));
       
   316 			for (col = 0 ; col < animStep ; col++)	  //Note I rely on intentional rounding down here!
       
   317 				{
       
   318 				utilCol.SetPixel(colfront);	
       
   319 				utilCol.IncXPos();
       
   320 				}			
       
   321 			}
       
   322 		
       
   323 		if (aMaskType)
       
   324 			{
       
   325 			// cycle through each pixel of the frame's mask & assign a default pixel a colour value
       
   326 			utilMask.Begin(KPointZero);
       
   327 			for (row = 0 ; row < aImageSize.iHeight ; row++)
       
   328 				{
       
   329 				utilMask.SetPos(TPoint(0,row));
       
   330 				for (col = 0 ; col < aImageSize.iWidth ; col++)
       
   331 					{
       
   332 					utilMask.SetPixel(KWhitePixels);
       
   333 					utilMask.IncXPos();
       
   334 					}
       
   335 				}
       
   336 			
       
   337 			const TInt maxmaskWidth = Min(8,Max(animWH/3,2));
       
   338 
       
   339 			//cut the corners off the mask
       
   340 			for (row = 0 ; row < maxmaskWidth ; row++)
       
   341 				{
       
   342 				TInt currentX = maxmaskWidth - row;
       
   343 				TInt xPos = KErrNone;
       
   344 
       
   345 				utilCol.SetPos(TPoint(0,row));
       
   346 				utilMask.SetPos(TPoint(0,row));
       
   347 				for(xPos = currentX ; xPos >= 0 ; xPos--)
       
   348 					{
       
   349 					utilCol.SetPixel(KBlackPixels);	
       
   350 					utilCol.IncXPos();
       
   351 					utilMask.SetPixel(KBlackPixels);	
       
   352 					utilMask.IncXPos();
       
   353 					}
       
   354 
       
   355 				utilCol.SetPos(TPoint(animWH - 1, row));
       
   356 				utilMask.SetPos(TPoint(animWH - 1, row));
       
   357 				for(xPos = currentX ; xPos >= 0 ; xPos--)
       
   358 					{
       
   359 					utilCol.SetPixel(KBlackPixels);	
       
   360 					utilCol.DecXPos();
       
   361 					utilMask.SetPixel(KBlackPixels);	
       
   362 					utilMask.DecXPos();
       
   363 					}
       
   364 
       
   365 				utilCol.SetPos(TPoint(0, animWH - 1 - row));
       
   366 				utilMask.SetPos(TPoint(0, animWH - 1 - row));
       
   367 				for(xPos = currentX ; xPos >= 0 ; xPos--)
       
   368 					{
       
   369 					utilCol.SetPixel(KBlackPixels);	
       
   370 					utilCol.IncXPos();
       
   371 					utilMask.SetPixel(KBlackPixels);	
       
   372 					utilMask.IncXPos();
       
   373 					}
       
   374 
       
   375 				utilCol.SetPos(TPoint(animWH - 1, animWH - 1 - row));
       
   376 				utilMask.SetPos(TPoint(animWH - 1, animWH - 1 - row));
       
   377 				for(xPos = currentX ; xPos >= 0 ; xPos--)
       
   378 					{
       
   379 					utilCol.SetPixel(KBlackPixels);	
       
   380 					utilCol.DecXPos();
       
   381 					utilMask.SetPixel(KBlackPixels);	
       
   382 					utilMask.DecXPos();
       
   383 					}
       
   384 				}
       
   385 			utilMask.End();
       
   386 			}
       
   387 		utilCol.End();
       
   388 		}
       
   389 	}
       
   390 
       
   391 /** My attempt to write animation generating code that avoids CIclLoader and Decoder class.
       
   392 	//It is better if this test class used it's own generated animation
       
   393 	//rather than relying on the GIF loader in order to reduce the cross-dependencies.
       
   394 	//The animation generated is a simple vertical line moving from left to right.
       
   395 	//To prove the masking, I cut the corners off.
       
   396 	@param aDelayUs		the delay between frames
       
   397 	@param aNumFrames	number of frames (approx - image width is a factor)
       
   398 	@param aImageType	colour format of colour data. This may not work properly for non-32-bit, but I haven't fully understood TBitmapUtil documentation.
       
   399 	@param aMaskType	format for mask - ENone for no mask.
       
   400 	@param aImageSize	width/height of animation
       
   401 	@param aBgCol		background colour for image non-masked areas. Masked areas are black.
       
   402 	@param aFgCol		foreground colour of animating area
       
   403 	@param aTUid		TUid assigned to animation
       
   404 	@return CWsGraphicBitmapAnimation allocated to represent the final animation	
       
   405 **/
       
   406 static CWsGraphicBitmapAnimation* CreateAnimL(TInt aDelayUs,TInt aNumFrames,TDisplayMode aImageType,TDisplayMode aMaskType,TSize aImageSize,TRgb aBgCol,TRgb aFgCol,TUid& aTUid)
       
   407 	{
       
   408 	RPointerArray<CWsGraphicBitmapAnimation::CFrame> frames;
       
   409 	TCleanupItem frameListCleanup(CleanupFrameList, &frames);
       
   410 	CleanupStack::PushL(frameListCleanup);
       
   411 	
       
   412 	CreateAnimFramesL(aDelayUs, aNumFrames, aImageType, aMaskType, aImageSize,aBgCol, aFgCol, frames);
       
   413 	
       
   414 	CWsGraphicBitmapAnimation* anim = CWsGraphicBitmapAnimation::NewL(aTUid,frames.Array());
       
   415 	CleanupStack::PopAndDestroy(&frames);
       
   416 	return anim;
       
   417 	}
       
   418 
       
   419 //
       
   420 // Describes the pure colour of the RGB value. yellow/magenta/cyan set 2 bits. White/grey is seperately flagged.
       
   421 // This method attempts to determine the strongest primary colour present in any given pixel. 
       
   422 // Note: The algorithm used is known to work for the current test cases only but requires careful review
       
   423 // for anyone making additional changes to tcrpanim. Given time, improved algorithm should be developed
       
   424 // to replace the current one
       
   425 //
       
   426 TUint PredominantColour(TUint aCol)
       
   427 	{	 //I don't like all these ifs, but I don't see an easy alternative
       
   428 		 //Possibly a bit look-up of the deltas from average would work 
       
   429 		 //(ignoring the bottom 5 bits =32, not 0x30=48. Ignore bottom 4 bits and accept 3-same answers, or divide by delta?)
       
   430 		 //
       
   431 	const TInt Kdelta=0x30;
       
   432 	TInt red=(aCol&0x00ff0000)>>16;
       
   433 	TInt green=(aCol&0x0000ff00)>>8;
       
   434 	TInt blue=(aCol&0x000000ff);
       
   435 	TInt ave=((red+green+blue)*(65536/3))>>16;
       
   436 	TBool rOverA=(red>ave);
       
   437 	TBool gOverA=(green>ave);
       
   438 	TBool bOverA=(blue>ave);
       
   439 	TInt numOverAve=(rOverA?1:0)+(gOverA?1:0)+(bOverA?1:0);
       
   440 
       
   441 	if (numOverAve==1)
       
   442 		{
       
   443 		if (rOverA)
       
   444 			{
       
   445 			if (red>ave+Kdelta)
       
   446 				{
       
   447 				if ((green-blue)>-Kdelta && (green-blue)<Kdelta)
       
   448 					return  EDetRed;
       
   449 				}
       
   450 			else
       
   451 				{
       
   452 				if (ave<Kdelta)
       
   453 					return EDetBlack;
       
   454 				else
       
   455 					{
       
   456 					if (green>ave-Kdelta && blue>ave-Kdelta)
       
   457 						{
       
   458 						if (ave>256-Kdelta)
       
   459 							return EDetWhite;
       
   460 						else
       
   461 							return EDetGrey;
       
   462 						}
       
   463 					}
       
   464 				}
       
   465 			}
       
   466 				
       
   467 		if (gOverA)
       
   468 			{
       
   469 			if (green>ave+Kdelta)
       
   470 				{
       
   471 				if ((blue-red)>-Kdelta && (blue-red)<Kdelta)
       
   472 					return  EDetGreen;
       
   473 				}
       
   474 			else
       
   475 				{
       
   476 				if (ave<Kdelta)
       
   477 					return EDetBlack;
       
   478 				else
       
   479 					{
       
   480 					if (red>ave-Kdelta && blue>ave-Kdelta)
       
   481 						if (ave>256-Kdelta)
       
   482 							return EDetWhite;
       
   483 						else
       
   484 							return EDetGrey;
       
   485 					}
       
   486 				}
       
   487 			}
       
   488 
       
   489 		if (bOverA)
       
   490 			{
       
   491 			if (blue>ave+Kdelta)
       
   492 				{
       
   493 				if ((green-red)>-Kdelta && (green-red)<Kdelta)
       
   494 					return  EDetBlue;
       
   495 				}
       
   496 			else
       
   497 				{
       
   498 				if (ave<Kdelta)
       
   499 					return EDetBlack;
       
   500 				else
       
   501 					{
       
   502 					if (red>ave-Kdelta && green>ave-Kdelta)
       
   503 						if (ave>256-Kdelta)
       
   504 							return EDetWhite;
       
   505 						else
       
   506 							return EDetGrey;
       
   507 					}
       
   508 				}
       
   509 			}
       
   510 		}
       
   511 	else	
       
   512 		{
       
   513 		if (!rOverA)
       
   514 			 if (red<ave-Kdelta)
       
   515 			 	{
       
   516 			 	if ((green-blue)>-Kdelta && (green-blue)<Kdelta)
       
   517 			 		return EDetGreen|EDetBlue;
       
   518 			 	}
       
   519 			 else
       
   520 				{
       
   521 				if (ave>256-Kdelta)
       
   522 					return EDetWhite;
       
   523 				else
       
   524 					{
       
   525 					if (blue<ave+Kdelta && green<ave+Kdelta)
       
   526 						{
       
   527 						if (ave<Kdelta)
       
   528 							return EDetBlack;
       
   529 						else
       
   530 							return EDetGrey;
       
   531 						}
       
   532 					}
       
   533 				}
       
   534 
       
   535 		if (!gOverA)
       
   536 			{
       
   537 			if (green<ave-Kdelta)
       
   538 				{
       
   539 				if ((blue-red)>-Kdelta && (blue-red)<Kdelta)
       
   540 					return  EDetRed|EDetBlue;
       
   541 				}
       
   542 			 else
       
   543 				{
       
   544 				if (ave>256-Kdelta)
       
   545 					return EDetWhite;
       
   546 				else
       
   547 					{
       
   548 					if (blue<ave+Kdelta && red<ave+Kdelta)
       
   549 						if (ave<Kdelta)
       
   550 							return EDetBlack;
       
   551 						else
       
   552 							return EDetGrey;
       
   553 					}
       
   554 				}
       
   555 			}
       
   556 
       
   557 		if (!bOverA)
       
   558 			{
       
   559 			if (blue<ave-Kdelta)
       
   560 				{
       
   561 				if ((green-red)>-Kdelta && (green-red)<Kdelta)
       
   562 					return  EDetGreen|EDetRed;
       
   563 				}
       
   564 			 else
       
   565 				{
       
   566 				if (ave>256-Kdelta)
       
   567 					return EDetWhite;
       
   568 				else
       
   569 					{
       
   570 					if (red<ave+Kdelta && green<ave+Kdelta)
       
   571 						if (ave<Kdelta)
       
   572 							return EDetBlack;
       
   573 						else
       
   574 							return EDetGrey;
       
   575 					}
       
   576 				}
       
   577 			}
       
   578 		}
       
   579 	return ECantTell;
       
   580 	}
       
   581 
       
   582 /**
       
   583 	Helper fn to ensure I put the anims in the same place each time...
       
   584 **/
       
   585 void CalcCentredAnimPosition(TRect& aRect,const TSize& aWinSize)
       
   586 	{
       
   587 	aRect.Shrink(aWinSize.iWidth*3/8,aWinSize.iHeight*4/10);
       
   588 	}
       
   589 
       
   590 CTCrpAnim::CTCrpAnim(CTestStep* aStep) : 
       
   591 	CTWsGraphicsBase(aStep)
       
   592 	{
       
   593 	}
       
   594 
       
   595 void CTCrpAnim::ConstructL()
       
   596 	{
       
   597 	TheClient->iGroup->WinTreeNode()->SetOrdinalPosition(0);
       
   598 	iRedrawWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
       
   599 	iBaseWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
       
   600 	iOverWin=new(ELeave) CCrpAnim(EFalse, CCrpAnim::ERedraw);
       
   601 
       
   602 	TSize screenSize=TheClient->iGroup->Size();
       
   603 	TInt winWidth=(screenSize.iWidth/3)-10;
       
   604 	TInt winHeight=screenSize.iHeight-10;
       
   605 	TSize windowSize(winWidth,winHeight);
       
   606 
       
   607 	iRedrawWin->ConstructL(TPoint(screenSize.iWidth/3*2+5,5), windowSize);
       
   608 	iBaseWin->ConstructL(TPoint(screenSize.iWidth/3+5,5), windowSize);
       
   609 	
       
   610 	//Create a transparent window that exactly overlaps the test window
       
   611 	//If transparency is not supported the leave causes the window to be destroyed and set to NULL.
       
   612 	//There is a test for transparency supported, but that simply creates a temp window to test anyway... 
       
   613 	
       
   614 	//Note that when I originally wrote this test to fix PDEF101991, it generated white areas that I detected.
       
   615 	//However, if this transparent window used for extended tests is created over the test window,
       
   616 	//that somehow stops the white fill from occurring.
       
   617 	//The fault still occurs, but the previous screen contents are left behind.
       
   618 	//So now this window is created at an off-screen location.
       
   619 	TRAPD(err, iOverWin->ConstructL(KPointOffsite, windowSize, 0x80); iOverWin->SetBlankIt(ETrue); iOverWin->SetRepeatDrawMax(KMaxRepeatDraw););
       
   620 	if (err)
       
   621 		{
       
   622 		delete iOverWin;
       
   623 		iOverWin = NULL;
       
   624 		}
       
   625 	
       
   626 	iTestWin = iRedrawWin;
       
   627 	iTestWin->SetRepeatDrawMax(KMaxRepeatDraw);
       
   628 	iBaseWin->SetRepeatDrawMax(KMaxRepeatDraw);
       
   629 
       
   630 	// create animation object & share it with everyone
       
   631 	iAnim = CreateAnimL(KAnimationFrameDelayTime,KAnimationTotalFrames,KTestDisplayMode,EGray256,TSize(KAnimDimension, KAnimDimension),KRgbBlue,KRgbRed,KUidTestAnimation2);
       
   632 	if (!iAnim)
       
   633 		{
       
   634 		User::Leave(KErrNoMemory);
       
   635 		}
       
   636 	iAnim->ShareGlobally();
       
   637 	
       
   638 	// calculate minimum length of the red line
       
   639 	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
       
   640 	iMinimumCalcRedLine = KAnimDimension - maxmaskHeight*2; // the height of the image minus the two cut corners
       
   641 
       
   642 	// create the timer object
       
   643 	iWaiter = CActiveWait::NewL();
       
   644 
       
   645 	// create screen bitmap object & scanline buffer
       
   646 	iScreenBitmap = new (ELeave) CFbsBitmap;
       
   647 	User::LeaveIfError(iScreenBitmap->Create(TSize(KAnimDimension, KAnimDimension), KTestDisplayMode));
       
   648 	TInt bufLength = iScreenBitmap->ScanLineLength(windowSize.iHeight, KTestDisplayMode);
       
   649 	iScanlineBuf = HBufC8::NewL(bufLength);
       
   650 	
       
   651 	#ifdef RUN_SAMPLE_ON_LEFT
       
   652     	{
       
   653 		// play animation on iBaseWin window
       
   654 		iBaseWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
       
   655 		TSize subsize1 = iTestWin->BaseWin()->Size();
       
   656 		TRect subposition1(subsize1);
       
   657 		CalcCentredAnimPosition(subposition1, subsize1);
       
   658 		iBaseWin->SetPosAnimation(KUidTestAnimation2, subposition1);
       
   659 		iBaseWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
   660     	}
       
   661 	#endif
       
   662 	}
       
   663 
       
   664 CTCrpAnim::~CTCrpAnim()
       
   665 	{
       
   666 	delete iRedrawWin;
       
   667 	delete iBaseWin;
       
   668 	delete iOverWin;
       
   669 	if (iAnim)
       
   670 		{
       
   671 		// destroy the animation object
       
   672 		iAnim->UnShareGlobally();
       
   673 		iAnim->Destroy();
       
   674 		delete iAnim;				
       
   675 		iAnim = NULL;
       
   676 		}
       
   677 	if (iWaiter)
       
   678 		{
       
   679 		// destroy the timer object
       
   680 		delete iWaiter;
       
   681 		iWaiter = NULL;
       
   682 		}
       
   683 	if (iScreenBitmap)
       
   684 		{
       
   685 		// destroy the screen capture of the animation
       
   686 		delete iScreenBitmap;
       
   687 		iScreenBitmap = NULL;
       
   688 		}
       
   689 	if (iScanlineBuf)
       
   690 		{
       
   691 		// destroy the scanline buffer
       
   692 		delete iScanlineBuf;
       
   693 		iScanlineBuf = NULL;
       
   694 		}
       
   695 	User::After(200000);
       
   696 	}
       
   697 
       
   698 //
       
   699 // This method checks the animation contained in the aAnimWin window has progressed. That is 
       
   700 // that it's drawn a sufficient number of concurrent frames to screen & the animation is 
       
   701 // drawn properly to screen
       
   702 // returns a Bool identifying whether the animation is considered 'good' or not
       
   703 //  
       
   704 void CTCrpAnim::CheckAnimProgressedL(CAnonAnimWindow* aAnimWin, TInt aAdditionalFrameCount, TBool aCaptureFrameResult)
       
   705 	{
       
   706 	TBool goodAnimation = ETrue;
       
   707 
       
   708 	// retrieve the rect from the screen's bitmap that contains the animation
       
   709 	CWsScreenDevice* screen = TheClient->iScreen;
       
   710 	TRect animPos = *aAnimWin->GetPosAnimation(KUidTestAnimation2);
       
   711 	CTBaseWin* bWin = aAnimWin->CtBaseWin();
       
   712 	animPos.Move(bWin->Position());
       
   713 	User::LeaveIfError(screen->CopyScreenToBitmap(iScreenBitmap, animPos));
       
   714 	
       
   715 	TInt frameNum = DetermineApproxFrameNum(iScreenBitmap, aCaptureFrameResult); // determines the frame Number & checks quality of animation (no tearing, etc)
       
   716 	TBool frameIdentified=(frameNum>=0);
       
   717 	
       
   718 	if (aCaptureFrameResult)
       
   719 		{
       
   720 		if (frameIdentified)
       
   721 			{
       
   722 			if (iPreviousFrameNum != KErrNotFound)
       
   723 			 	{
       
   724 				if (iPreviousFrameNum < frameNum)
       
   725 					{
       
   726 					TInt frameStep = KFrameStepCalculation * aAdditionalFrameCount;
       
   727 					iPreviousFrameNum += frameStep; // move to our *expected* framenumber
       
   728 					if (frameNum > iPreviousFrameNum)
       
   729 						{
       
   730 						// the frame number is ahead of it's expected position
       
   731 						// This suggests we've possibly missed animating a frame in wserv
       
   732 						// or test code isn't getting a chance to execute as crp animations taking all cpu cycles
       
   733 						// If its significantly outside norms, we log the fact (as a performance metric)
       
   734 						TInt performance = ((frameNum - iPreviousFrameNum) / frameStep);
       
   735 						if (performance > KFrameMissedAnimationsThreshold)
       
   736 							{
       
   737 							iFrameStatus.iFrameSkipped++;
       
   738 							goodAnimation = EFalse;	
       
   739 							}	
       
   740 						}
       
   741 					// else we're animating above an acceptable threshold
       
   742 					}
       
   743 				else if (iPreviousFrameNum == frameNum) // potentially not animating anymore
       
   744 					{
       
   745 					iFrameStatus.iFrameIdentical++;
       
   746 					goodAnimation = EFalse;
       
   747 					}
       
   748 				// else animation is progressing fine
       
   749 				}
       
   750 			// ignore iPreviousFrameNum == KErrNotFound
       
   751 			}
       
   752 		else
       
   753 			{
       
   754 			goodAnimation = EFalse; // couldn't id the red line	
       
   755 			}
       
   756 
       
   757 		if (goodAnimation)
       
   758 			{
       
   759 			iFrameStatus.iFrameOK++;
       
   760 			}
       
   761 		}
       
   762 	// else we were only interested in calculating the frameNum
       
   763 	iPreviousFrameNum = frameNum;
       
   764 	}
       
   765 
       
   766 //
       
   767 // method to estimate the framenumber based on the location of the thin, red line. 
       
   768 // Also checks whether tearing of the animation has occured or the animation
       
   769 // is only partially drawn. 
       
   770 // These are known issues with wserv animation performance & so we give some allowance for error
       
   771 // 
       
   772 TInt CTCrpAnim::DetermineApproxFrameNum(CFbsBitmap* aBitmap, TBool aCaptureFrameResult)
       
   773 	{
       
   774 	TInt colFirstTear = KErrNotFound; 	// column id'ing the first tear in the vertical line
       
   775 	TPtr8 des = iScanlineBuf->Des();	// ptr to the scanline buffer
       
   776 
       
   777 	// locate the thin, red line in the bitmap
       
   778 	for (TInt xPos = 0 ; xPos < aBitmap->SizeInPixels().iWidth ; xPos++)
       
   779 		{
       
   780 		aBitmap->GetVerticalScanLine(des, xPos, EColor16MA);
       
   781 		TUint32* pixel = (TUint32*) des.Ptr();
       
   782 		TInt colour = KErrNone;
       
   783 		
       
   784 		for (TInt ii = 0 ; ii < aBitmap->SizeInPixels().iHeight ; ii++)
       
   785 			{
       
   786 			colour = PredominantColour(*pixel);
       
   787 			if (colour & EDetRed)
       
   788 				{
       
   789 				if (colFirstTear < 0)
       
   790 					{
       
   791 					// check the length of the red line is a good length
       
   792 					pixel += (iMinimumCalcRedLine - 1); // minus the one pixel to position on last pixel in red line
       
   793 					colour = PredominantColour(*pixel);
       
   794 					if (colour & EDetRed)
       
   795 						{
       
   796 						// good line
       
   797 						return xPos;
       
   798 						}
       
   799 					else // we've detected first part of a torn line
       
   800 						{
       
   801 						colFirstTear = xPos; 
       
   802 						}
       
   803 					}
       
   804 				else
       
   805 					{
       
   806 					// located second part of torn line
       
   807 					if ((xPos - colFirstTear) > KAnimationTearWidthThreshold)
       
   808 						{
       
   809 						if (aCaptureFrameResult)
       
   810 							{
       
   811 							iFrameStatus.iFrameTearing++;	
       
   812 							}
       
   813 						xPos = KErrNotFound;
       
   814 						}
       
   815 					return xPos;
       
   816 					}	
       
   817 				break;
       
   818 				}
       
   819 			pixel++;
       
   820 			}
       
   821 		}
       
   822 	if (aCaptureFrameResult)
       
   823 		{
       
   824 		if (colFirstTear < 0)
       
   825 			{
       
   826 			iFrameStatus.iFrameEmpty++; // we never located any red line at all
       
   827 			}
       
   828 		else
       
   829 			{
       
   830 			iFrameStatus.iFramePartial++; // we only located a single, small part of the red line
       
   831 			}
       
   832 		}
       
   833 	return KErrNotFound;
       
   834 	}
       
   835 
       
   836 /**	This internal loop tests that the animation and the foreground interact correctly
       
   837 	The primary test is that the outline of the animation 
       
   838 	intersects the lines drawn on the foreground correctly, compared to a reference version.
       
   839 	The iBaseWin is already showing this reference anim.
       
   840 	If the animation is not drawn, or the foreground is wiped, then this test will fail.
       
   841 **/
       
   842 void CTCrpAnim::TestSpriteLoopL(TBool aAnimForeground,TBool aDrawForeground)
       
   843 	{
       
   844 	_LIT(KForegroundInfo,"TestSpriteLoop animForeground [%d] drawForeground [%d]");
       
   845 	INFO_PRINTF3(KForegroundInfo, aAnimForeground, aDrawForeground);
       
   846 	
       
   847 	if (!iOverWin && (aAnimForeground || aDrawForeground))
       
   848 		{
       
   849 		User::Leave(KErrGeneral); // unable to run this test without iOverWin
       
   850 		}
       
   851 
       
   852 	ResetFrameCounters();
       
   853 	iTestWin->RemoveAnimation(KUidTestAnimation2);
       
   854 	iTestWin->SetBlankIt(ETrue);		
       
   855 	if (iOverWin)
       
   856 		{
       
   857 		iOverWin->RemoveAnimation(KUidTestAnimation2);
       
   858 		iOverWin->SetBlankIt(ETrue);
       
   859 		}
       
   860 
       
   861 	// determine which window holds the animation, & which will be invalidated with progressively larger rects
       
   862 	CCrpAnim* animWin=aAnimForeground?iOverWin:iTestWin;
       
   863 	CCrpAnim* paintWin=aDrawForeground?iOverWin:iTestWin;
       
   864 	paintWin->SetBlankIt(EFalse);
       
   865 	
       
   866 	// set & play the animation on the specified window (animWin)
       
   867 	animWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
       
   868 	TSize subsize1 = paintWin->BaseWin()->Size();
       
   869 	TRect subposition1(subsize1);
       
   870 	CalcCentredAnimPosition(subposition1, subsize1);
       
   871 	animWin->SetPosAnimation(KUidTestAnimation2, subposition1);
       
   872 	
       
   873 	#ifdef RUN_SAMPLE_ON_LEFT
       
   874 		// play the demo animation in the left-hand window also
       
   875 		iBaseWin->InvalidateAndRedraw(ETrue, EFalse, ETrue);
       
   876 	#endif
       
   877 
       
   878 	iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
   879 	if (iOverWin)
       
   880 		{
       
   881 		iOverWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
   882 		}
       
   883 	
       
   884 	// invalidate increasingly larger squares on paintWin 
       
   885 	// note, some fully overlap the animation, some partially overlap, and some don't overlap at all
       
   886 	TInt invalidateWaitTime=KAnimationFrameDelayTime*3/4; // microseconds
       
   887 	TInt temp = KErrNotFound;
       
   888 	for (TInt step=30;step<KMaxXY;step+=30)
       
   889 		{
       
   890 		for (TInt xx=0;xx<KMaxXY;xx+=step)
       
   891 			{
       
   892 			for (TInt yy=10;yy<KMaxXY;yy+=step)
       
   893 	    		{
       
   894 				// calculate rectangle & invalidate paintWin with it
       
   895 	    		TRect invalidRect(xx,yy,xx+step,yy+step);
       
   896 	    		paintWin->InvalidateAndRedraw(ETrue,EFalse,ETrue,&invalidRect);
       
   897 				
       
   898 				// calculate any additional frames that may be drawn by above. Note intentionally ignore frame result
       
   899 				temp = iPreviousFrameNum;	
       
   900 				CheckAnimProgressedL(animWin, 1, EFalse);
       
   901 				
       
   902 				//new defect DEF101896: Test runs faster with this line removed, but there is evident tearing
       
   903 				iWaiter->Wait(invalidateWaitTime);			//DEF101896 search string: //interrupt_foreground_draw
       
   904 				
       
   905 				if (temp == iPreviousFrameNum)
       
   906 					{
       
   907 					// give wserv more time to animate the frame
       
   908 					iWaiter->Wait(invalidateWaitTime);
       
   909 					}
       
   910 				CheckAnimProgressedL(animWin, 1); // calculate the frame drawn. Capture frame result
       
   911 				}
       
   912 			}
       
   913 		}
       
   914 
       
   915 	// determine whether the animation was successful (ie: enough Good frames were detected) or not
       
   916 	// Note KMinGoodFrameThreshold is essentially an arbitrary number. This can be adjusted to accommodate
       
   917 	// performance requirements as needed
       
   918 	temp = LogResults();
       
   919 	TInt quality = 100*iFrameStatus.iFrameOK/temp;
       
   920 	TEST(quality > KMinGoodFrameThreshold);
       
   921 	
       
   922 	ResetFrameCounters();
       
   923 	iWaiter->Cancel();
       
   924 	iTestWin->RemoveAnimation(KUidTestAnimation2);
       
   925 	iTestWin->SetBlankIt(ETrue);		
       
   926 	if (iOverWin)
       
   927 		{
       
   928 		iOverWin->RemoveAnimation(KUidTestAnimation2);
       
   929 		iOverWin->SetBlankIt(ETrue);
       
   930 		}
       
   931 	}
       
   932 
       
   933 //
       
   934 // resets the frame trackers to intial values
       
   935 //
       
   936 void CTCrpAnim::ResetFrameCounters()
       
   937 	{
       
   938 	iPreviousFrameNum = KErrNotFound;
       
   939 	iFrameStatus.iFrameOK = 0;
       
   940 	iFrameStatus.iFramePartial = 0;
       
   941 	iFrameStatus.iFrameIdentical = 0;
       
   942 	iFrameStatus.iFrameEmpty = 0;
       
   943 	iFrameStatus.iFrameTearing = 0;
       
   944 	iFrameStatus.iFrameSkipped = 0;
       
   945 	}
       
   946 
       
   947 //
       
   948 // Log the current frame results & return the total number of frame calculations
       
   949 //
       
   950 // Calculated : the total number of frame-checks run
       
   951 // Good: 		the frame was successfully drawn to screen & within specified tolerances for tearing, expected position & colour
       
   952 // Partial: 	the frame was only partially drawn to screen. Specifcally the animated red line was only partially drawn
       
   953 // Identical: 	the frame was in the same position as the last frame
       
   954 // Empty: 		no redline was detected at all in the frame
       
   955 // Skipped: 	the position of the frame was beyond the expected position
       
   956 //
       
   957 // There is a dependency on the timing as to when the frame is animated hence tolerances are used to allow
       
   958 // for this. 
       
   959 // 
       
   960 TInt CTCrpAnim::LogResults()
       
   961 	{
       
   962 	TInt result = iFrameStatus.iFrameOK + iFrameStatus.iFramePartial + iFrameStatus.iFrameIdentical + 
       
   963 				iFrameStatus.iFrameEmpty + iFrameStatus.iFrameTearing + iFrameStatus.iFrameSkipped;
       
   964 	INFO_PRINTF4(_L("\tAnimation results:  Calculated[%d], Good[%d], Partial[%d]"), result, iFrameStatus.iFrameOK, iFrameStatus.iFramePartial);
       
   965 	INFO_PRINTF5(_L("\tAnimation results:  Identical[%d], Empty[%d], Tearing[%d], Skipped[%d]"), iFrameStatus.iFrameIdentical, iFrameStatus.iFrameEmpty, iFrameStatus.iFrameTearing, iFrameStatus.iFrameSkipped);
       
   966 	return result;
       
   967 	}
       
   968 
       
   969 /** This test tests the result of drawing an animation and main draw to two windows that overlap.
       
   970 	The two windows are placed in exactly the same location, so the result of splitting the drawing across them should be "identical".
       
   971 	Note that when the anim and the draw are on different screens the lines are seen merged over the anim.
       
   972 **/
       
   973 void CTCrpAnim::TestOverlappingWindowsL()
       
   974 	{
       
   975 	if (!iOverWin)
       
   976 		{
       
   977 		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
       
   978 		return;
       
   979 		}
       
   980 		
       
   981 	// setup necessary params
       
   982 	// Note we place the overlapping transparent window (iOverWin) directly on top of the test window (iTestWin)
       
   983 	iOverWin->BaseWin()->SetPosition(iTestWin->BaseWin()->Position());
       
   984 		
       
   985 	enum 
       
   986 		{
       
   987 		 EAllBackground=0,
       
   988 		 EForegroundDraw=1,
       
   989 		 EForegroundAnim=2,
       
   990 		 EAllForeGround=3,
       
   991 		 ECountModes,
       
   992 		 EFirstMode=EAllBackground,
       
   993 		};
       
   994 	
       
   995 	// test the various permutations of overlapping vs animated windows
       
   996 	for (TInt mode = EFirstMode ; mode < ECountModes ; mode++)	    
       
   997 		{
       
   998 		INFO_PRINTF2(_L("TestOverlappingWindowsL [%d]"), mode);
       
   999 		TestSpriteLoopL((mode&EForegroundAnim)!=0,(mode&EForegroundDraw)!=0);
       
  1000 		}
       
  1001 	}
       
  1002 	
       
  1003 /**
       
  1004 	This method demonstrates clipping of an animation running behind a transparent window.
       
  1005 	No main window redraw takes place here.
       
  1006 **/	
       
  1007 void CTCrpAnim::DemoClippingWindowsL()
       
  1008 	{
       
  1009 	if (!iOverWin)
       
  1010 		{
       
  1011 		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
       
  1012 		return;
       
  1013 		}
       
  1014 
       
  1015 	// setup test case params. Note we calculate three different positions for the overlapping window
       
  1016 	RWindow* win = iTestWin->Window();
       
  1017 	
       
  1018 	TPoint	screenPos= win->Position();
       
  1019 	TSize screenSize = win->Size();	
       
  1020 	TRect subposition1(screenSize);
       
  1021 	CalcCentredAnimPosition(subposition1, screenSize);
       
  1022 
       
  1023 	TPoint testPositions[]=
       
  1024 		{	
       
  1025 		//first test: window clips corner of anim
       
  1026 			TPoint(screenPos.iX+screenSize.iWidth/2-10,screenPos.iY+screenSize.iHeight/2-10),
       
  1027 		//test: window clips all of anim
       
  1028 			TPoint(screenPos.iX+screenSize.iWidth/3,screenPos.iY+screenSize.iHeight/3),
       
  1029 		//test: window clips none of anim
       
  1030 			TPoint(screenPos.iX+screenSize.iWidth*2/3,screenPos.iY+screenSize.iHeight*2/3),
       
  1031 		};
       
  1032 
       
  1033 	// calculate roughly number of frames we expect to have drawn
       
  1034 	TInt loopWaitTime = KShortDelayLoop; // time given to allow animation to progress (arbitrary number)
       
  1035 	float expectedFrameCount = 1;
       
  1036 	if (loopWaitTime > KAnimationFrameDelayTime)
       
  1037 		{
       
  1038 		expectedFrameCount = loopWaitTime/KAnimationFrameDelayTime;
       
  1039 		}
       
  1040 
       
  1041 	for (TInt ii = 0; ii < ((sizeof testPositions)/(sizeof testPositions[0])) ; ii++)
       
  1042 		{
       
  1043 		// initialise test windows to known state with no active animations
       
  1044 		ResetFrameCounters();
       
  1045 		iTestWin->RemoveAnimation(KUidTestAnimation2);
       
  1046 		iTestWin->SetBlankIt(EFalse);		
       
  1047 		iOverWin->SetBlankIt(ETrue);		
       
  1048 		iOverWin->RemoveAnimation(KUidTestAnimation2);
       
  1049 
       
  1050 		// position animation windows
       
  1051 		iTestWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
       
  1052 		iTestWin->SetPosAnimation(KUidTestAnimation2, subposition1);
       
  1053 		iOverWin->BaseWin()->SetPosition(testPositions[ii]); // positions the transparent overlapping window
       
  1054 
       
  1055 		// redraw both test windows
       
  1056 		iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
  1057 		iOverWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
  1058 
       
  1059 		// run the animation for an arbitrary period
       
  1060 		for (TInt loopit = 0 ; loopit < 20 ; loopit++)
       
  1061 			{
       
  1062 			iWaiter->Wait(loopWaitTime);	
       
  1063 			CheckAnimProgressedL(iTestWin,static_cast<TInt>(expectedFrameCount)); // log the frame result
       
  1064 			}
       
  1065 
       
  1066 		// calculate & log frame results. Test an acceptable number of frames were successfully animated
       
  1067 		TInt total = LogResults();
       
  1068 		TInt qA = 100*iFrameStatus.iFrameOK/total;
       
  1069 		TEST(qA > KMinGoodFrameThreshold);
       
  1070 		}
       
  1071 	}
       
  1072 
       
  1073 /**	In this version, the background window is updated in patches. 
       
  1074 	If the animation intersects the transparent window then the whole transparent window is redrawn.
       
  1075 **/	
       
  1076 void CTCrpAnim::TestClippingWindowsL()
       
  1077 	{
       
  1078 	if (!iOverWin)
       
  1079 		{
       
  1080 		INFO_PRINTF1(_L("- Test skipped - transparency not supported"));
       
  1081 		return;
       
  1082 		}
       
  1083 	// setup test case params. Note we calculate three different positions for the overlapping window
       
  1084 	RWindow* win = iTestWin->Window();
       
  1085 	TPoint screenPos= win->Position();
       
  1086 	TSize screenSize = win->Size();	
       
  1087 	
       
  1088 	TPoint testPositions[]=
       
  1089 		{	
       
  1090 		//first test: window clips corner of anim
       
  1091 			TPoint(screenPos.iX+screenSize.iWidth/2-10,screenPos.iY+screenSize.iHeight/2-10),
       
  1092 		//test: window clips all of anim
       
  1093 			TPoint(screenPos.iX+screenSize.iWidth/3,screenPos.iY+screenSize.iHeight/3),
       
  1094 		//test: window clips none of anim
       
  1095 			TPoint(screenPos.iX+screenSize.iWidth*2/3,screenPos.iY+screenSize.iHeight*2/3),
       
  1096 		};
       
  1097 
       
  1098 	for (TInt loopIt = 0; loopIt < ((sizeof testPositions)/(sizeof testPositions[0])) ; loopIt++)
       
  1099 		{
       
  1100 	    iOverWin->BaseWin()->SetPosition(testPositions[loopIt]); // position the overlapping window
       
  1101 	    TestSpriteLoopL(EFalse,EFalse);
       
  1102 		}
       
  1103 	}
       
  1104 
       
  1105 /**	This just demonstrates that an animation plays - for about 1 second.
       
  1106 **/
       
  1107 void CTCrpAnim::BasicCRPDemo()
       
  1108 	{
       
  1109 	// draw the animation in two positions
       
  1110 	TSize subsize1 = iTestWin->BaseWin()->Size();
       
  1111 	TRect subposition1(subsize1);
       
  1112 	CalcCentredAnimPosition(subposition1, subsize1);
       
  1113 	
       
  1114 	if (iOverWin)
       
  1115 		{
       
  1116 		iOverWin->BaseWin()->SetPosition(KPointOffsite);	//way away!
       
  1117 		iOverWin->InvalidateAndRedraw(EFalse,EFalse,ETrue);
       
  1118 		}
       
  1119 		
       
  1120 	CCrpAnim *animWin= iTestWin;
       
  1121 	animWin->SetAnimation(KUidTestAnimation2)->Play(ETrue);
       
  1122 	animWin->SetPosAnimation(KUidTestAnimation2, subposition1);
       
  1123 	iTestWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
  1124 	iBaseWin->InvalidateAndRedraw(ETrue,EFalse,ETrue);
       
  1125 
       
  1126 	// allow the animation to play for ~1 second. Purpose is to demonstrate animation to an observer	
       
  1127 	iWaiter->Wait(KShortDelayLoop);
       
  1128 	
       
  1129 	ResetFrameCounters();
       
  1130 	iWaiter->Cancel();
       
  1131 	iTestWin->RemoveAnimation(KUidTestAnimation2);
       
  1132 	}
       
  1133 
       
  1134 /**
       
  1135 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0001
       
  1136 
       
  1137 @SYMDEF             DEF100356
       
  1138 
       
  1139 @SYMTestCaseDesc    CRP animation test for redraw storing interrupting main draw
       
  1140 
       
  1141 @SYMTestPriority    High
       
  1142 
       
  1143 @SYMTestStatus      Implemented
       
  1144 
       
  1145 @SYMTestActions     Creates a CRP animation and runs it on the server scheduler 
       
  1146 					while also running redraws of the window.
       
  1147 					
       
  1148 					With Redraw storing this has been known to cause problems 
       
  1149 					sharing and resetting the window iDisplayRegion.
       
  1150 					This is evidenced by white areas.
       
  1151 
       
  1152 
       
  1153 @SYMTestExpectedResults 
       
  1154 					The LHS window shows what the animation should look like just animating,
       
  1155 					while the RHS window demonstrates the simultanious animation and redraw.
       
  1156 					No White patches should be in evidence, and no missing fragments of animation.
       
  1157 					The TEST should detect white patches.
       
  1158 */
       
  1159 void CTCrpAnim::TestSpriteInterruptsForegroundL()
       
  1160 	{	
       
  1161 	// setup test params
       
  1162 	TSize subsize1(iTestWin->BaseWin()->Size());
       
  1163 	TRect subposition1(subsize1);
       
  1164 	CalcCentredAnimPosition(subposition1, subsize1);
       
  1165 	if (iOverWin)
       
  1166 		{
       
  1167 		iOverWin->BaseWin()->SetPosition(KPointOffsite);	// ensure overlapping transparent window DOESN'T overlap the test window
       
  1168 		}
       
  1169 
       
  1170 	// execute test loop
       
  1171 	TestSpriteLoopL(EFalse,EFalse);
       
  1172 	}
       
  1173 
       
  1174 void CTCrpAnim::RunTestCaseL(TInt /*aCurTestCase*/)
       
  1175 	{
       
  1176 	_LIT(KTest1,"1: Basic CRP demo");
       
  1177 	_LIT(KTest2,"2: sprite anim interrupts foreground");
       
  1178 	_LIT(KTest3,"3: translucent windows");
       
  1179 	_LIT(KTest4,"4: CRP clipping windows");
       
  1180 	_LIT(KTest5,"5: CRP & redraw clipping windows");
       
  1181 	_LIT(KTest6,"6: CRP Invalidation");
       
  1182 
       
  1183 	((CTCrpAnimStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
       
  1184 	switch(++iTest->iState)
       
  1185 		{
       
  1186 		case 1:
       
  1187 /**
       
  1188 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0002
       
  1189 */
       
  1190 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0002"));
       
  1191 			iTest->LogSubTest(KTest1);
       
  1192 			BasicCRPDemo();
       
  1193 			break;
       
  1194 		case 2:
       
  1195 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0001"));
       
  1196 			iTest->LogSubTest(KTest2);
       
  1197 			TestSpriteInterruptsForegroundL();
       
  1198 			break;
       
  1199 		case 3:
       
  1200 /**
       
  1201 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0003
       
  1202 */
       
  1203 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0003"));
       
  1204 			iTest->LogSubTest(KTest3);
       
  1205 			TestOverlappingWindowsL();
       
  1206 			break;
       
  1207 		case 4:
       
  1208 /**
       
  1209 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0004
       
  1210 */
       
  1211 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0004"));
       
  1212 			iTest->LogSubTest(KTest4);
       
  1213 			DemoClippingWindowsL();
       
  1214 			break;
       
  1215 		case 5:
       
  1216 /**
       
  1217 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0005
       
  1218 */
       
  1219 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0005"));
       
  1220 			iTest->LogSubTest(KTest5);
       
  1221 			TestClippingWindowsL();
       
  1222 			break;
       
  1223 		case 6:
       
  1224 /**
       
  1225 @SYMTestCaseID		GRAPHICS-WSERV-CRP01-0006
       
  1226 */
       
  1227 			((CTCrpAnimStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-CRP01-0006"));
       
  1228 			iTest->LogSubTest(KTest6);
       
  1229 			//this testcase is removed, because invalidation is removed from CWsGraphicDrawer destructor (due to flickering)
       
  1230 			break;
       
  1231 		default:
       
  1232 			((CTCrpAnimStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
       
  1233 			((CTCrpAnimStep*)iStep)->CloseTMSGraphicsStep();
       
  1234 			TestComplete();
       
  1235 		}
       
  1236 	((CTCrpAnimStep*)iStep)->RecordTestResultL();
       
  1237 	}
       
  1238 
       
  1239 //
       
  1240 namespace	//anonymous namespace
       
  1241 	{
       
  1242 //
       
  1243 	CAnimRedrawWindow::CAnimRedrawWindow(CCrpAnim *aAnimWindow, TBool aIsBase) : CTWin(),
       
  1244 		iAnimWindow(aAnimWindow),
       
  1245 		iIsBase(aIsBase)
       
  1246 		{
       
  1247 		}
       
  1248 
       
  1249 	CAnimRedrawWindow::~CAnimRedrawWindow()
       
  1250 		{
       
  1251 		}
       
  1252 
       
  1253 	void CAnimRedrawWindow::Draw()
       
  1254 		{
       
  1255 		CCrpAnim::Draw(Gc(),Size(),iIsBase,iAnimWindow->iRect,iAnimWindow->iBlankIt,iAnimWindow->iRepeatDrawMax,iAnimWindow->iAlphaValue);
       
  1256 		if (iAnimWindow->iAnimUid!=TUid::Null())
       
  1257 			{
       
  1258 			TheClient->Flush();
       
  1259 			Gc()->DrawWsGraphic(iAnimWindow->iAnimUid,iAnimWindow->iAnimPos,iAnimWindow->iAnimData.Pckg());
       
  1260 			TheClient->Flush();
       
  1261 			}
       
  1262 		}
       
  1263 
       
  1264 	//
       
  1265 
       
  1266 	CCrpAnim::CCrpAnim(TBool aIsBase, TWinType aWinType) 
       
  1267 	:	iWinType(aWinType), 
       
  1268 		iIsBase(aIsBase),
       
  1269 		iBlankIt(EFalse),
       
  1270 		iRepeatDrawMax(1),
       
  1271 		iAnimUid(TUid::Null()),
       
  1272 		iAlphaValue(ENoTransparency)
       
  1273 		{
       
  1274 		}
       
  1275 
       
  1276 	CCrpAnim::~CCrpAnim()
       
  1277 		{
       
  1278 		delete iCtWin;
       
  1279 		}
       
  1280 
       
  1281 	void CCrpAnim::ConstructL(const TPoint &aPos, const TSize &aSize, TInt aAlphaValue)
       
  1282 		{
       
  1283 		TDisplayMode reqMode = EColor16MA; //for transparency we need 16ma or 16map mode
       
  1284 		TDisplayMode *pReqMode=&reqMode;	
       
  1285 		switch(iWinType)
       
  1286 			{
       
  1287 			case ERedraw:
       
  1288 				iCtWin = new(ELeave) CAnimRedrawWindow(this, iIsBase);
       
  1289 				break;
       
  1290 			case EBlank:
       
  1291 				iCtWin = new(ELeave) CTBlankWindow();
       
  1292 				break;
       
  1293 			case EBackedUp:
       
  1294 				iCtWin = new(ELeave) CTBackedUpWin(EColor64K);
       
  1295 				pReqMode = NULL;
       
  1296 				break;
       
  1297 			}
       
  1298 		iCtWin->SetUpL(aPos, aSize, TheClient->iGroup, *TheClient->iGc, pReqMode, ETrue);
       
  1299 		if (aAlphaValue != ENoTransparency)
       
  1300 			{
       
  1301 			User::LeaveIfError(Window()->SetTransparencyAlphaChannel());
       
  1302 			//the window itself should be completely transparent, the draw commands will use the alpha value
       
  1303 			Window()->SetBackgroundColor(TRgb(0, 0, 0, 0));
       
  1304 			iAlphaValue = aAlphaValue;
       
  1305 			}
       
  1306 		}
       
  1307 
       
  1308 	void CCrpAnim::SetEllipseDrawMode(CGraphicsContext::TDrawMode aEllipseDrawMode)
       
  1309 		{
       
  1310 		iEllipseDrawMode = aEllipseDrawMode;
       
  1311 		}
       
  1312 
       
  1313 	void CCrpAnim::DrawEllipse(CBitmapContext *aGc, const TRect &aRect, TInt aAlphaValue)
       
  1314 		{
       
  1315 		if(aAlphaValue != ENoTransparency)
       
  1316 			{
       
  1317 			aGc->SetBrushColor(TRgb(85,85,85, aAlphaValue));
       
  1318 			aGc->SetPenColor(TRgb(170,170,170, aAlphaValue));
       
  1319 			}
       
  1320 		else
       
  1321 			{
       
  1322 			aGc->SetBrushColor(TRgb(85,85,85));
       
  1323 			aGc->SetPenColor(TRgb(170,170,170));
       
  1324 			}
       
  1325 		aGc->SetDrawMode(iEllipseDrawMode);
       
  1326 		aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
  1327 		aGc->DrawEllipse(aRect);
       
  1328 		}
       
  1329 
       
  1330 	void CCrpAnim::Draw(CBitmapContext *aGc, const TSize &aSize, TBool aIsBase, const TRect &aRect, TBool aBlankIt,TInt aRepeat, TInt aAlphaValue)
       
  1331 		{
       
  1332 		static TInt sGrey=0;
       
  1333 		sGrey+=3;
       
  1334 		if (sGrey>0x40)
       
  1335 			sGrey-=0x40;		
       
  1336 		sGrey=sGrey^0x20;
       
  1337 		if(aAlphaValue != ENoTransparency)
       
  1338 			{
       
  1339 			aGc->SetBrushColor(TRgb(sGrey, sGrey, sGrey, aAlphaValue));
       
  1340 		    aGc->SetPenColor(TRgb(KRgbGreen.Value(), aAlphaValue));
       
  1341 			}
       
  1342 		else
       
  1343 			{		
       
  1344 			aGc->SetBrushColor(TRgb::Gray256(sGrey));
       
  1345 		    aGc->SetPenColor(KRgbGreen);
       
  1346 			}
       
  1347 		aGc->Clear();
       
  1348 	    TInt xPos=aSize.iHeight,yPos=aSize.iWidth;
       
  1349 	    
       
  1350 	    // The test windows are created relative to screen size. The
       
  1351 	    // number of green lines generated needs to be tied into the
       
  1352 	    // window size to prevent green becoming the dominant colour
       
  1353 	    // when blended with the second animation, which would
       
  1354 	    // prevent the PredominantColour() algorithm from discovering
       
  1355 	    // the red line.
       
  1356 	    TInt yStep = aSize.iHeight/14;
       
  1357 	    TInt xStep = aSize.iWidth/6;
       
  1358 	    
       
  1359 	    //This paint is intentionally complex and slow so that the animation timer is likely to interrupt it.
       
  1360 		if (!aBlankIt)
       
  1361 		 for (TInt nn = 0 ; nn < aRepeat ; nn++)
       
  1362 			for(yPos=0 ; yPos < aSize.iHeight ; yPos += yStep)
       
  1363 				for(xPos=0 ; xPos < aSize.iWidth ; xPos += xStep)
       
  1364 					aGc->DrawLine(aRect.Center(),TPoint(xPos,yPos));
       
  1365 		if (aIsBase)
       
  1366 			DrawEllipse(aGc, aRect, aAlphaValue);			
       
  1367 		}
       
  1368 
       
  1369 	//This simple API may need replacing by a list and search if multiple anims are played together
       
  1370 	TWsGraphicAnimation* CCrpAnim::SetAnimation(TUid aUid)
       
  1371 		{	//currently only have 1 animation - it gets replaced. It could get refiused
       
  1372 		iAnimUid=aUid;
       
  1373 		return &iAnimData;	
       
  1374 		}
       
  1375 
       
  1376 	TWsGraphicAnimation* CCrpAnim::GetAnimation(TUid aUid)
       
  1377 		{   //currently only have 1 animation
       
  1378 		if (iAnimUid==aUid)
       
  1379 			return &iAnimData;	
       
  1380 		else
       
  1381 			return NULL;
       
  1382 		}
       
  1383 		
       
  1384 	void CCrpAnim::SetPosAnimation(const TUid& aUid, const TRect& aRect)
       
  1385 		{   //currently only have 1 animation
       
  1386 		if (iAnimUid==aUid)
       
  1387 			iAnimPos = aRect;
       
  1388 		}
       
  1389 	
       
  1390 	TRect* CCrpAnim::GetPosAnimation(const TUid& aUid)
       
  1391 		{   //currently only have 1 animation
       
  1392 		if (iAnimUid==aUid)
       
  1393 			return &iAnimPos;	
       
  1394 		else
       
  1395 			return NULL;
       
  1396 		}
       
  1397 	
       
  1398 	TBool CCrpAnim::RemoveAnimation(TUid)
       
  1399 		{
       
  1400 		iAnimUid=TUid::Null();
       
  1401 		iAnimData.Stop(EFalse);		
       
  1402 		return ETrue;
       
  1403 		}	
       
  1404 
       
  1405 	void CCrpAnim::DoDraw()
       
  1406 		{
       
  1407 		DoDraw(iBlankIt);
       
  1408 		}
       
  1409 
       
  1410 	inline void CCrpAnim::DoDraw(TBool aBlankIt)
       
  1411 		{
       
  1412 		__ASSERT_ALWAYS(iWinType!=EBlank,AutoPanic(EAutoPanicWindowType));
       
  1413 		iCtWin->Gc()->Activate(*Window());
       
  1414 		Draw(iCtWin->Gc(),Size(),iIsBase,iRect,aBlankIt,iRepeatDrawMax,iAlphaValue);
       
  1415 		if (iAnimUid!=TUid::Null())
       
  1416 			iCtWin->Gc()->DrawWsGraphic(iAnimUid,iAnimPos,iAnimData.Pckg());
       
  1417 		iCtWin->Gc()->Deactivate();
       
  1418 		}
       
  1419 		
       
  1420 	void CCrpAnim::DoDrawEllipse()
       
  1421 		{
       
  1422 		__ASSERT_ALWAYS(iWinType!=EBlank,AutoPanic(EAutoPanicWindowType));
       
  1423 		iCtWin->Gc()->Activate(*Window());
       
  1424 		DrawEllipse(iCtWin->Gc(),iRect,iAlphaValue);
       
  1425 		iCtWin->Gc()->Deactivate();
       
  1426 		}
       
  1427 
       
  1428 	void CCrpAnim::InvalidateAndRedraw(TBool /*aUseBlankItMember*/,TBool /*aBlankIt*/,TBool aUseRWindowInvalidate,TRect* aRect)
       
  1429 		{
       
  1430 		RWindow& win = *Window();
       
  1431 		if (aRect)
       
  1432 			{
       
  1433 			if (aUseRWindowInvalidate)
       
  1434 				win.Invalidate(*aRect);
       
  1435 			else
       
  1436 				Invalidate(*aRect);
       
  1437 			}
       
  1438 		else
       
  1439 			{
       
  1440 			if (aUseRWindowInvalidate)
       
  1441 				win.Invalidate();
       
  1442 			else
       
  1443 				Invalidate();
       
  1444 			}
       
  1445 		if (aRect)
       
  1446 			win.BeginRedraw(*aRect);
       
  1447 		else
       
  1448 			win.BeginRedraw();
       
  1449 		DoDraw();
       
  1450 		win.EndRedraw();
       
  1451 		TheClient->Flush();
       
  1452 		}
       
  1453 		
       
  1454 	void CCrpAnim::Invalidate(const TRect &aRect)
       
  1455 		{
       
  1456 		TRect rect(aRect);
       
  1457 		rect.Move(iCtWin->Position());
       
  1458 		CTUser::Splat(TheClient,rect,TRgb::Gray256(0));
       
  1459 		}
       
  1460 
       
  1461 //
       
  1462 	}	//end anonymous namespace
       
  1463 //
       
  1464 __WS_CONSTRUCT_STEP__(CrpAnim)