// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
/**
@file
*/
#include <e32std.h>
#include <e32math.h>
#include <w32std.h>
#include <w32debug.h>
#include "teflogextensions.h"
#include "t_wsdynamicreswinbase.h"
#include "globalsettings.h"
#include <bitdraw.h>
#include <bitdrawinterfaceid.h>
#include <u32hal.h>
#include <dispchannel.h>
#include <graphics/displaycontrol.h>
#if (!defined(K_DISPLAY_CH_MAJOR_VERSION_NUMBER) && !defined(K_DISPLAY_CH_MINOR_VERSION_NUMBER))
#define MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER
#endif
_LIT(KMonospaceTestFontTypefaceName,"Arial");
const TInt KMaxFontSize = 150;
TBool CWsDynamicResWinBase::iTransparencyEnabled=EFalse;
CWsDynamicResWinBase::CWsDynamicResWinBase():
iDoTearDown(EFalse),
iSession(TGlobalSettings::Instance().iScreen)
{
}
void CWsDynamicResWinBase::SetupL()
{
SetupL(EFalse);
}
CActiveScheduler CWsDynamicResWinBase::iScheduler;
void CWsDynamicResWinBase::SetupL(TBool aUseOtherScreenForInfo)
{
if (CActiveScheduler::Current()!=&iScheduler)
{
new (&iScheduler) CActiveScheduler;
CActiveScheduler::Install(&iScheduler);
}
iDoTearDown=ETrue;
iRed.SetInternal(0xFFFF0000);
iGreen.SetInternal(0xFF00FF00);
iBlue.SetInternal(0xFF0000FF);
iCyan.SetInternal(0xFF00FFFF);
iMagenta.SetInternal(0xFFFF00FF);
iYellow.SetInternal(0xFFFFFF00);
iWhite.SetInternal(0xFFFFFFFF);
iLastGceHoleColor.SetInternal(0);
TITLE_BACKGROUND=iCyan;
COMPARE_BACKGROUND=iBlue;
ASSERT_EQUALS_X(iSession.Connect(), KErrNone);
{//Stolen from TAuto CloseAllPanicWindows()
TInt idFocus = iSession.GetFocusWindowGroup();
TWsEvent event;
event.SetType(EEventKey); //EEventKeyDown
TKeyEvent *keyEvent = event.Key();
keyEvent->iCode = EKeyEscape;
keyEvent->iScanCode = EStdKeyEscape;
keyEvent->iModifiers = 0;
TInt theLimit = 50;
while(idFocus != NULL && (theLimit-- > 0))
{
iSession.SendEventToAllWindowGroups(event);
TInt idNewFocus = iSession.GetFocusWindowGroup();
if (idNewFocus!=idFocus)
{
INFO_PRINTF1(_L("A window was closed [probably a panic box from the previous test]."));
}
idFocus=idNewFocus;
}
}
TInt err = KErrNone;
TRAP(err, iScreenDevice = new (ELeave) CWsScreenDevice(iSession));
PRINT_ON_ERROR2_L(err, _L("Failed to create screen device: %d"), err);
ASSERT_EQUALS_X(iScreenDevice->Construct(TGlobalSettings::Instance().iScreen), KErrNone);
iDisplayMode = iScreenDevice->DisplayMode(); // Get default display mode
CheckAndConnectScreen();
TRAP(err, iGc = new (ELeave) CWindowGc(iScreenDevice));
PRINT_ON_ERROR2_L(err, _L("Failed to create graphics context: %d"), err);
ASSERT_EQUALS_X(iGc->Construct(), KErrNone);
iGroup = RWindowGroup(iSession);
ASSERT_EQUALS_X(iGroup.Construct(++iWindowHandle,iScreenDevice), KErrNone);
iGroup.SetOrdinalPositionErr(0, KPasswordWindowGroupPriority - 1); // Added code ---- Fastpath
iSession.Flush();
if (aUseOtherScreenForInfo)
{
if (iSession.NumberOfScreens()>1)
{ //Create server objects for info windows to appear on alternate screen
TInt alternateScreenNum=iSession.NumberOfScreens()-1;
if (TGlobalSettings::Instance().iScreen==alternateScreenNum)
{ //Alternate screen is last screen, or first screen if that is being tested.
alternateScreenNum=0;
}
TRAP(err, iInfoScreenDevice = new (ELeave) CWsScreenDevice(iSession));
PRINT_ON_ERROR2_L(err, _L("Failed to create second screen device: %d"), err);
ASSERT_EQUALS_X(iInfoScreenDevice->Construct(alternateScreenNum), KErrNone);
TRAP(err, iInfoGc = new (ELeave) CWindowGc(iInfoScreenDevice));
PRINT_ON_ERROR2_L(err, _L("Failed to create second graphics context: %d"), err);
ASSERT_EQUALS_X(iInfoGc->Construct(), KErrNone);
iInfoGroupInstance = RWindowGroup(iSession);
ASSERT_EQUALS_X(iInfoGroupInstance.Construct(++iWindowHandle,iInfoScreenDevice), KErrNone);
iInfoGroup=&iInfoGroupInstance;
}
else
{ //If alternate screen is not available then no text or compare windows should be created!
iInfoScreenDevice=iScreenDevice; //it is "convenient" for the device to still be good.
iInfoGc=NULL;
iInfoGroup=NULL;
}
}
else
{ //
iInfoScreenDevice=iScreenDevice;
iInfoGc=iGc;
iInfoGroup=&iGroup;
}
if (iInfoGroup && iInfoGc)
{
// Add a plain background window to obscure anything else that
// happens to be behind the test. Setting this window's display mode is also
// used to set the screen device display mode, and hence the composition
// mode: alpha or chroma key.
iBackground = RBlankWindow(iSession);
ASSERT_EQUALS_X(iBackground.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
iBackground.SetOrdinalPosition(100); // Behind anything else in this group.
iBackground.SetColor(TRgb(iWhite));
//iBackground.SetExtent(TPoint(-1000,-1000),TSize(3000,3000));
iBackground.Activate();
iBackground.SetVisible(ETrue);
}
iSession.Flush();
RWindow testTrans(iSession);
ASSERT_EQUALS_X(testTrans.Construct(iGroup, ++iWindowHandle), KErrNone);
iTransparencyEnabled=(testTrans.SetTransparencyFactor(iWhite)==KErrNone);
if (iTransparencyEnabled)
{
TTestName testName;
testName.Format(_L("Screen %i, depth %i: Found Trans Man"),
TGlobalSettings::Instance().iScreen
);
UpdateTitleWindowL(testName,KMaxInfoLines-1);
}
else
{
TTestName testName;
testName.Format(_L("Screen %i, depth %i: No Trans Man"),
TGlobalSettings::Instance().iScreen
);
UpdateTitleWindowL(testName,KMaxInfoLines-1);
}
testTrans.Close();
}
void CWsDynamicResWinBase::CheckAndConnectScreen()
{
if (TGlobalSettings::Instance().iDisconnected) //set from script file to match wsini keyword SIMULATE_STARTUP_DISCONNECTED
{
//Verify that the display really is disconnected
ASSERT_TRUE_X(iScreenDevice != NULL);
MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId));
ASSERT_TRUE_X(interface != NULL);
RArray<MDisplayControl::TResolution> resolutions;
const TInt err = interface->GetResolutions(resolutions);
ASSERT_EQUALS_X(err, KErrDisconnected);
resolutions.Close();
}
#ifndef MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER
//make sure display is attached to screen (only if I/F is available at compile time...)
TInt displayState = ENormalResolution;
UserSvr::HalFunction(EHalGroupDisplay | (TGlobalSettings::Instance().iScreen<<16), EDisplayHalSetDisplayState, &displayState, NULL);
Pause(200);
#endif
if (TGlobalSettings::Instance().iDisconnected)
{
//Verify that the display now is connected
MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId));
RArray<MDisplayControl::TResolution> resolutions;
const TInt err = interface->GetResolutions(resolutions);
ASSERT_EQUALS_X(err, KErrNone);
const_cast<TGlobalSettings&>(TGlobalSettings::Instance()).iDisconnected = EFalse;
resolutions.Close();
}
}
/**
Common tear down code for all tests.
Windows, group and session created are closed. Screen device is destroyed.
Surfaces, manager and update session are closed.
*/
void CWsDynamicResWinBase::TearDownL()
{
iDoTearDown=EFalse;
if (iInfoGc!=iGc)
delete iInfoGc;
delete iGc;
if (iInfoScreenDevice!=iScreenDevice)
delete iInfoScreenDevice;
delete iScreenDevice;
iGroup.Close();
if (iInfoGroupInstance.WsHandle())
iInfoGroupInstance.Close();
iSession.Flush();
iSession.Close();
}
/**
* Note that this is not the ideal mechanism.
* A derived class may thinks its TearDown is safe to do from delete, but in the class it is derived from it may not be safe
**/
void CWsDynamicResWinBase::TearDownFromDeleteL()
{
CWsDynamicResWinBase::TearDownL(); //Explicitly call the non-derived implementation.
}
CWsDynamicResWinBase::~CWsDynamicResWinBase()
{
if (iDoTearDown)
TearDownFromDeleteL(); //This mechanism is not entirely clean to use.
}
/**
Pause for the given number of milliseconds.
@param aMilliseconds Time to wait in milliseconds.
*/
void CWsDynamicResWinBase::Pause(TInt aMilliseconds)
{
User::After(TTimeIntervalMicroSeconds32(aMilliseconds * 1000));
}
// This handles any non-member uses of the extended ASSERT_XXX macros
void TefUnitFailLeaveL()
{
User::Leave(KErrTEFUnitFail);
}
/**
* side-effect: log the state info just before I leave!
* Note that this only logs intentional assertion failures.
* Fails due to panics or throws won't log this info.
**/
void CWsDynamicResWinBase::TefUnitFailLeaveL()
{
for (TInt line=0;line<KMaxInfoLines;line++)
if (iTestInfo[line].Length())
Logger().LogExtra((TText8*)"Test state at fail - line",line, ESevrAll, iTestInfo[line]);
User::Leave(KErrTEFUnitFail);
}
/** Creates the LHS info window, annd a middle window to display a representation of the expected result.
* Also sets up a rectangle representing the space on the right to be used for the test
* @param aTitle The title to display on the info window
* @param aDetail Optional text to display on the first line under the title
**/
void CWsDynamicResWinBase::MakeTitleAndCompareWindowsL(TRefByValue<const TDesC16> aTitle,TRefByValue<const TDesC16> aDetail)
{
iTestName=aTitle;
iTestInfo[0]=aDetail;
TRect screenSize(iInfoScreenDevice->SizeInPixels());
TPoint oneThird(screenSize.iBr.iX/3,screenSize.iBr.iY/3);
TRect winSize(0,0,oneThird.iX,oneThird.iY);
if (oneThird.iX>oneThird.iY)
{
oneThird.iY=0;
winSize.iBr.iY=screenSize.iBr.iY;
}
else
{
oneThird.iX=0;
winSize.iBr.iX=screenSize.iBr.iX;
}
winSize.Shrink(5,5);
if (iInfoGc)
{
iTitle=RWindow(iSession);
ASSERT_EQUALS_X(iTitle.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
iTitle.SetBackgroundColor(iCyan);
iTitle.SetExtent(winSize.iTl,winSize.Size());
iTitle.Activate();
RepaintTitleWindowL();
iTitle.SetVisible(ETrue);
winSize.Move(oneThird);
iCompare=RWindow(iSession);
ASSERT_EQUALS_X(iCompare.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
iCompare.SetBackgroundColor(COMPARE_BACKGROUND);
iCompare.SetExtent(winSize.iTl,winSize.Size());
iCompare.Activate();
iCompare.BeginRedraw();
ActivateWithWipe(iInfoGc,iCompare,COMPARE_BACKGROUND);
TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize);
CFont *font=NULL;
ASSERT_EQUALS(iScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone);
iInfoGc->UseFont(font);
iInfoGc->DrawText(_L("Simulation"),winSize.Size(),winSize.Size().iHeight-5,iGc->ECenter);
iInfoGc->Deactivate();
iCompare.EndRedraw();
iCompare.SetVisible(ETrue);
if (iScreenDevice!=iInfoScreenDevice)
{
winSize.Move(-oneThird);
}
else
{
winSize.Move(oneThird);
}
}
else
{
winSize=iScreenDevice->SizeInPixels();
}
iTestPos=winSize;
iTestPointCentre=winSize.Center();
iCenteredFrontWinRect=winSize;
iCenteredFrontWinRect.Shrink(winSize.Size().iWidth/3,winSize.Size().iHeight/3);
}
/** Makes the compare window larger by covering the test window area as well.
* Copes with vertically aligned screens, but will be naughty if called multiple times!!!
* @param aGoLarger If set false, resets the size back.
**/
void CWsDynamicResWinBase::LargerCompareWindow(TBool aGoLarger)
{
TPoint currPos=iCompare.AbsPosition();
TSize currSize=iCompare.Size();
if (currPos.iX<currPos.iY)
{
if (aGoLarger)
currSize.iHeight<<=1;
else
currSize.iHeight>>=1;
}
else
{
if (aGoLarger)
currSize.iWidth<<=1;
else
currSize.iWidth>>=1;
}
iCompare.SetSize(currSize);
}
/** Puts a line of text on the LHS window.
* Repaints the window. The line of text will also be shown in the log if the test fails.
* @param aDetail The text to display
* @param aIndex The row number to display at
**/
void CWsDynamicResWinBase::UpdateTitleWindowL(TRefByValue<const TDesC16> aDetail,TInt aIndex)
{
ASSERT(aIndex>=0 && aIndex<KMaxInfoLines);
iTestInfo[aIndex]=aDetail;
RepaintTitleWindowL();
}
/** Activate the GC onto the Window.
* In non-transparent mode it also performs a wipe background as the WServ system does not necessarily do this.
* @param aGc The GC to associate
* @param aWin The window to associate
* @param aColor The color to use as the wipe. Default is transparent, which means no wipe.
**/
TBool CWsDynamicResWinBase::ActivateWithWipe(CWindowGc* aGc,RWindow& aWin,TRgb aColor)
{
aGc->Activate(aWin);
aGc->SetBrushColor(aColor);
aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
if (aColor!=TRgb(0,0) && !iTransparencyEnabled) //presume that all redraw-stored windows will draw background
{
aGc->Clear();
return ETrue; //window was cleared
}
return EFalse;
}
CWindowGc* CWsDynamicResWinBase::GcForWindow(RWindow& aWin)
{
if (aWin.WsHandle()==NULL)
return NULL; //can't activate uninitialised window.
CWindowGc* gc=iGc;
if (iGc!=iInfoGc)
if (&aWin==&iCompare || &aWin==&iTitle)
gc=iInfoGc;
else if (iInfoGroup && aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
gc=iInfoGc;
return gc;
}
/** Activates an appropriate predefined GC on the specified window and wipes the background if necessary.
* @param aWin The window to wipe
* @param aColor The colour to wipe with (if necessary)
* @return the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live"
**/
CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,RWindow& aWin,TRgb aColor)
{
CWindowGc* gc=GcForWindow(aWin);
iSession.Flush();
if (gc==NULL)
return gc; //can't activate uninitialised window.
if (aInvalidate)
aWin.Invalidate();
iSession.Flush();
aWin.BeginRedraw();
iSession.Flush();
ActivateWithWipe(gc,aWin,aColor);
return gc;
}
/** Activates an appropriate predefined GC on the specified window and wipes the background if necessary.
* @param aWin The window to wipe
* @param aColor The colour to wipe with (if necessary)
* @return the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live"
**/
CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,TRect aRect,RWindow& aWin,TRgb aColor)
{
if (aWin.WsHandle()==NULL)
return NULL; //can't activate uninitialised window.
if (aInvalidate)
aWin.Invalidate(aRect);
aWin.BeginRedraw(aRect);
CWindowGc* gc=iGc;
if (iGc!=iInfoGc)
if (&aWin==&iCompare || &aWin==&iTitle)
gc=iInfoGc;
else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
gc=iInfoGc;
ActivateWithWipe(gc,aWin,aColor);
return gc;
}
TBool CWsDynamicResWinBase::InvalidateRegion(const TRegion& aRegion,RWindow& aWin)
{
if (aWin.WsHandle()==NULL)
return false; //can't activate uninitialised window.
for (TInt ii = 0; ii < aRegion.Count(); ii++)
{
aWin.Invalidate(aRegion[ii]);
}
return true;
}
CWindowGc* CWsDynamicResWinBase::BeginActivateWithWipe(const TRegion& aRegion,RWindow& aWin,TRgb aColor)
{
if (!InvalidateRegion(aRegion,aWin))
return NULL; //can't activate uninitialised window.
aWin.BeginRedraw();
CWindowGc* gc=iGc;
if (iGc!=iInfoGc)
if (&aWin==&iCompare || &aWin==&iTitle)
gc=iInfoGc;
else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
gc=iInfoGc;
ActivateWithWipe(gc,aWin,aColor);
return gc;
}
/** Paints the LHS window with rows of text.
*
**/
void CWsDynamicResWinBase::RepaintTitleWindowL()
{
if (iTitle.WsHandle())
{
iTitle.Invalidate();
iTitle.BeginRedraw();
ActivateWithWipe(iInfoGc,iTitle,TITLE_BACKGROUND);
iInfoGc->SetUnderlineStyle(EUnderlineOn);
TSize winSize=iTitle.Size();
TRect textRect(winSize);
textRect.iBr.iY/=4;
TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize);
CFont *font=NULL;
ASSERT_EQUALS(iInfoScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone);
iInfoGc->UseFont(font);
iInfoGc->DrawText(iTestName,textRect,textRect.iBr.iY/2,iGc->ECenter);
iInfoGc->SetUnderlineStyle(EUnderlineOff);
textRect.iTl.iY=textRect.iBr.iY;
TInt rowHeight=winSize.iHeight*3/(4*(KMaxInfoLines+1));
textRect.iBr.iY+=rowHeight;
for (TInt index=0;index<KMaxInfoLines;index++)
{
if (iTestInfo[index].Length())
iInfoGc->DrawText(iTestInfo[index],textRect,textRect.Size().iHeight*3/4,iInfoGc->ECenter);
textRect.Move(0,rowHeight);
}
iInfoGc->DiscardFont();
iInfoGc->Deactivate();
iTitle.EndRedraw();
iInfoScreenDevice->ReleaseFont(font);
iSession.Flush();
iSession.Finish();
}
}
/** Useful test culled from other GCE test classes.
*
*
*
**/
TBool CWsDynamicResWinBase::DisplayHasAlpha() const
{
return (iDisplayMode == EColor16MA || iDisplayMode == EColor16MAP);
}
/** Test using an indipendent method that GCE version of WServ is running
* This method can only be called after the testcase is started
*
* @return true if WServ version is GCE technology, false if legacy technology
**/
TBool CWsDynamicResWinBase::GCEIsSupported() const
{
CFbsDrawDevice* screenDevice=NULL;
TDisplayMode displayMode=iScreenDevice->DisplayMode();
TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode));
TBool rv=EFalse;
if(err == KErrNone)
{
TAny* p=NULL;
rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone);
delete screenDevice;
}
return rv;
}
/** Test using an indipendent method that GCE version of WServ is running
* This method can be called at any time, even by external code, but creates temporary window session objects
*
* @return true if WServ version is GCE technology, false if legacy technology
**/
TBool CWsDynamicResWinBase::GCEIsSupportedStatic()
{
CFbsDrawDevice* screenDevice=NULL;
RWsSession session;
if (session.Connect()!=KErrNone)
{
return EFalse;
}
TDisplayMode displayMode=ENone;
{CWsScreenDevice screen(session);
if (screen.Construct(TGlobalSettings::Instance().iScreen)!=KErrNone)
{
return EFalse;
}
displayMode=screen.DisplayMode();
}//screen destroyed
TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode));
TBool rv=EFalse;
if(err == KErrNone)
{
TAny* p=NULL;
rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone);
delete screenDevice;
}
return rv;
}//session destroyed
/**
Use the full-screen background window to select a display mode that doesn't use
alpha (anything other than EColor16MA or EColor16MAP). Record the mode for use
in setting all other windows.
@return ETrue if an appropriate mode was selected, EFalse otherwise.
*/
TBool CWsDynamicResWinBase::SelectChromaCompositionMode()
{
// Request EColor64K, but as long as the actual mode doesn't use alpha, it
// doesn't matter too much which one is used.
if (iInfoGc==iGc)
{
iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(EColor64K);
iSession.Flush(); // Force switching to the display mode.
}
return !DisplayHasAlpha();
}
/** Returns the colour used by WServ to paint holes in UI layer to reveal the GCE behind.
* The window should have a surface attached.
* If the method is called after the surface has been detached or the window was removed then
* the previous recorded hole color is returned.
**/
TRgb CWsDynamicResWinBase::GceHoleColor( RWindowBase& aWin)const
{
if (aWin.WsHandle()==NULL)
{
return iLastGceHoleColor;
}
TRgb retVal=aWin.KeyColor();
if (retVal==TRgb(0,0))
{
return iLastGceHoleColor;
}
else
{
iLastGceHoleColor=retVal;
return retVal;
}
}
/**
Use the full-screen background window to select a display mode that can use
alpha (either EColor16MA or EColor16MAP). Record the mode for use in setting all
other windows.
@return ETrue if an appropriate mode was selected, EFalse otherwise.
*/
TBool CWsDynamicResWinBase::SelectAlphaCompositionMode(TDisplayMode aMode)
{
// Request EColor16MA, but as long as the actual mode can use alpha, it
// doesn't matter too much which one is used.
if (iInfoGc==iGc)
{
iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(aMode);
iSession.Flush(); // Force switching to the display mode.
}
return DisplayHasAlpha();
}
/**
* Interesting UI pattern used by other GCE tests.
*
*
**/
void CWsDynamicResWinBase::DrawUIContent(RWindow& aWindow)
{
aWindow.BeginRedraw();
CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc;
gc->Activate(aWindow);
TBool hasAlpha = DisplayHasAlpha();
// Draw a red-green graduated box in the central portion of the window,
// with alpha if available.
TPoint start;
TPoint end;
TInt halfW = KSurfaceWidth / 2;
TInt quarterW = halfW / 2;
TInt halfH = KSurfaceHeight / 2;
TInt quarterH = halfH / 2;
// Set constant ordinals for non-alpha case.
start.iX = quarterW;
end.iX = quarterW + halfW;
for (TInt yy = 0; yy < halfH; yy++)
{
TInt yval = yy * 255 / (halfH - 1);
start.iY = yy + quarterH;
end.iY = start.iY;
if (hasAlpha)
{
for (TInt xx = 0; xx < halfW; xx++)
{
TInt xval = xx * 255 / (halfW - 1);
start.iX = xx + quarterW;
end.iX = start.iX + 1;
gc->SetPenColor(TRgb(yval, 255 - yval, 0, xval));
gc->DrawLine(start, end);
}
}
else
{
gc->SetPenColor(TRgb(yval, 255 - yval, 0));
gc->DrawLine(start, end);
}
}
gc->Deactivate();
aWindow.EndRedraw();
}
/**
* Causes the given window to be redrawn.
* Doesn't draw anything except the background wipe, when the transparency manager hasn't
*
**/
void CWsDynamicResWinBase::DrawPlainUI(RWindow& aWindow,TBool aInvalidate,TRgb aWipeColor)
{
if (CWindowGc* gc=BeginActivateWithWipe(aInvalidate,aWindow,aWipeColor))
{
//actually does nothing!
gc->Deactivate();
aWindow.EndRedraw();
}
}
/**
* Interesting UI pattern used by other GCE tests.
*
*
**/
void CWsDynamicResWinBase::DrawCross(RWindow& aWindow, TRgb aColor, TInt aThickness)
{
aWindow.BeginRedraw();
CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc;
gc->Activate(aWindow);
// Draw a red diagonal cross in the window.
gc->SetPenColor(aColor);
gc->SetPenSize(TSize(aThickness, aThickness));
gc->DrawLine(TPoint(0, 0), TPoint(KSurfaceWidth, KSurfaceHeight));
gc->DrawLine(TPoint(KSurfaceWidth, 0), TPoint(0, KSurfaceHeight));
gc->Deactivate();
aWindow.EndRedraw();
}
/**
* Checks the RGB value
*
*
**/
void CWsDynamicResWinBase::TestPixelL(TPoint aPt, TRgb aColor, TBool aMatch)
{
TRect screenArea(iScreenDevice->SizeInPixels());
if (aPt.iX < screenArea.iTl.iX)
{
aPt.iX = screenArea.iTl.iX;
}
else if (aPt.iX >= screenArea.iBr.iX)
{
aPt.iX = screenArea.iBr.iX - 1;
}
if (aPt.iY < screenArea.iTl.iY)
{
aPt.iY = screenArea.iTl.iY;
}
else if (aPt.iY >= screenArea.iBr.iY)
{
aPt.iY = screenArea.iBr.iY - 1;
}
TRgb pixel;
iScreenDevice->GetPixel(pixel, aPt);
if (aMatch)
{
ASSERT_EQUALS_X(pixel.Internal(), aColor.Internal());
}
else
{
ASSERT_NOT_EQUALS_X(pixel.Internal(), aColor.Internal());
}
}
struct CountColour
{
TRgb iColor;
TInt iCount;
TBool operator < (const CountColour& aRhs)const
{ return iColor.Value()<aRhs.iColor.Value(); }
CountColour(TRgb aColor,TInt aCount=0):
iColor(aColor),iCount(aCount) {}
CountColour(const CountColour& aRhs):
iColor(aRhs.iColor),iCount(aRhs.iCount) {}
};
void LogColorL(TRgb aPixel,RArray<CountColour>& aColors)
{
//I am sure one of the find methods would do this, but life is too short!
TInt existingIndex;
for (existingIndex=0;existingIndex<aColors.Count();existingIndex++)
if (aColors[existingIndex].iColor==aPixel)
break;
if (existingIndex==aColors.Count())
aColors.AppendL(CountColour(aPixel,1));
else
aColors[existingIndex].iCount++;
}
/**
* Tests the outline of the given rectangle to verify that it has the expected inner and outer colors
* There may be a limited number of other colors present.
* If the given count of other colors is exceeded then false is returned
* If the majority of inner and outer edge pixels are not the given colors then returns false
* If the colors are repeated on inside and outside then returns false
* If there are corners then the insides of the corners are also check for outside color
* Note that the right and bottom edge coordinates are outside the rectangle.
* Note that I am not performing any safety clipping at present. The rectangle must be on-screen!
* A negative value for corner size indicates that the window may or may not have corners that size.
* Only leaves if fatal memory condition!
**/
TBool CWsDynamicResWinBase::TestRectL(TRect aRect,TRgb aInnerColor,TInt aOtherInnerColors,TRgb aOuterColor,TInt aOtherOuterColors,TInt aExpectedCornerSize)
{
if (aRect.iTl.iX<=0 || aRect.iTl.iY<=0)
return ETrue; //can't perform the test against the outside of the screen
//quantise the expectation based on the current mode.
switch (iScreenDevice->DisplayMode())
{
case EColor4K:
aInnerColor=aInnerColor.Color4K(aInnerColor.Color4K());
aOuterColor=aOuterColor.Color4K(aOuterColor.Color4K());
break;
case EColor64K:
aInnerColor=aInnerColor.Color64K(aInnerColor.Color64K());
aOuterColor=aOuterColor.Color64K(aOuterColor.Color64K());
break;
case EColor16M:
case EColor16MU:
case EColor16MA:
case EColor16MAP:
break;
default:
ASSERT_TRUE(!"Can't quantise color for this display mode!");
}
RArray<CountColour> innerColors;
innerColors.AppendL(aInnerColor);
RArray<CountColour> outerColors;
outerColors.AppendL(aOuterColor);
TInt cornerSize=aExpectedCornerSize>=0?aExpectedCornerSize:-aExpectedCornerSize;
//Check outside first!
TRgb pixelVal;
for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY-1);pixelPos.iX<aRect.iBr.iX;pixelPos.iX++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,outerColors);
}
for(TPoint pixelPos(aRect.iTl.iX,aRect.iBr.iY);pixelPos.iX<=aRect.iBr.iX;pixelPos.iX++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,outerColors);
}
for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY);pixelPos.iY<=aRect.iBr.iY;pixelPos.iY++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,outerColors);
}
for(TPoint pixelPos(aRect.iBr.iX,aRect.iTl.iY-1);pixelPos.iY<aRect.iBr.iY;pixelPos.iY++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,outerColors);
}
TInt cornerStart=1;
if (cornerSize)
{
cornerStart=cornerSize;
if (aExpectedCornerSize>0)
{
iScreenDevice->GetPixel(pixelVal, aRect.iTl);
LogColorL(pixelVal,outerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX,aRect.iBr.iY-1));
LogColorL(pixelVal,outerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iTl.iY));
LogColorL(pixelVal,outerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1));
LogColorL(pixelVal,outerColors);
}
}
//test inside edges (excluding 4 corner pixels - do them seperately)
for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iTl.iY);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,innerColors);
}
for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iBr.iY-1);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,innerColors);
}
for(TPoint pixelPos(aRect.iTl.iX,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,innerColors);
}
for(TPoint pixelPos(aRect.iBr.iX-1,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++)
{
iScreenDevice->GetPixel(pixelVal, pixelPos);
LogColorL(pixelVal,innerColors);
}
//the 4 corner cells - not checking the whole corner area...
if (aExpectedCornerSize>=0)
{
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iTl.iY+cornerSize));
LogColorL(pixelVal,innerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iBr.iY-1-cornerSize));
LogColorL(pixelVal,innerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iBr.iY-1-cornerSize));
LogColorL(pixelVal,innerColors);
iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iTl.iY+cornerSize));
LogColorL(pixelVal,innerColors);
}
//OK... that has tested all the pixels, now check the result
if (innerColors.Count()>aOtherInnerColors+1)
return EFalse;
if (outerColors.Count()>aOtherOuterColors+1)
return EFalse;
for (TInt index=1;index<innerColors.Count();index++)
if (innerColors[0].iCount<innerColors[index].iCount)
{
return EFalse;
}
for (TInt index=1;index<outerColors.Count();index++)
if (outerColors[0].iCount<outerColors[index].iCount)
{
return EFalse;
}
for (TInt indexIn=1;indexIn<innerColors.Count();indexIn++)
for (TInt indexOut=0;indexOut<outerColors.Count();indexOut++)
if (innerColors[indexIn].iColor.Value()==outerColors[indexOut].iColor.Value())
{
return EFalse;
}
return ETrue;
}
TRect CWsDynamicResWinBase::PentCellRect(const TRect& aFullRect,char aStartLetter,char aEndLetter)
{
if (aEndLetter==0)
aEndLetter=aStartLetter;
aStartLetter&=0x1f;
aEndLetter&=0x1f;
TInt startx=(aStartLetter-1)%5;
TInt starty=(aStartLetter-1)/5;
TInt endx=(aEndLetter-1)%5;
TInt endy=(aEndLetter-1)/5;
if (starty>endy)
{ //swap // s e
starty-=endy; // s-e
endy+=starty; // s
starty=endy-starty; // e
}
if (startx>endx)
{ //swap // s e
startx-=endx; // s-e
endx+=startx; // s
startx=endx-startx; // e
}
TSize fullSize=aFullRect.Size();
return TRect( aFullRect.iTl.iX+fullSize.iWidth*startx/5,
aFullRect.iTl.iY+fullSize.iHeight*starty/5,
aFullRect.iTl.iX+fullSize.iWidth*(endx+1)/5,
aFullRect.iTl.iY+fullSize.iHeight*(endy+1)/5
);
}