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