--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/screendriver/tsrc/TLLD.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,4035 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32math.h>
+#include <hal.h>
+#include <bitdraw.h>
+#include "Tlld.h"
+#include <bitdrawinterfaceid.h>
+#include <bmalphablend.h>
+#include <graphics/lookuptable.h>
+#include <graphics/blendingalgorithms.h>
+#include <graphics/gdi/gdiconsts.h>
+#include "BMDRAW.H"
+
+GLREF_C TInt ByteSize(TDisplayMode aDisplayMode,TInt aWidth);
+
+TInt KNumberDisplayModes1 = sizeof (TestDisplayMode1) / sizeof (TestDisplayMode1[0]);
+
+#if defined(SYMBIAN_USE_FAST_FADING)
+const TBool KFastFading = ETrue;
+#else
+const TBool KFastFading = EFalse;
+#endif
+
+//these are for EColor16MAP testing
+const TInt KInaccuracyLimit = 15;
+const TInt KUserDispModes = 2;
+//The array below is used in CTLowLevel::TestWriteRGBAlpha() to step through display modes,
+//to ensure adequate test coverage.
+const TDisplayMode UserDisplayModes[KUserDispModes] =
+ {
+ ENone,
+ EColor16MAP,
+ };
+const TInt KMaskFill =3;
+const TUint32 MaskFill[KMaskFill] =
+ {
+ 0x00,
+ 0xff,
+ 0x3A,
+ };
+
+TInt DisplayMode2Index(TDisplayMode aMode)
+ {
+ TInt i;
+ for(i=0;i<KNumDispModes;i++)
+ {
+ if(TestDisplayMode[i] == aMode)
+ break;
+ }
+ return i;
+ }
+
+inline TInt AbsDiff(TInt aValue1, TInt aValue2)
+ {
+ return (aValue1 < aValue2) ? (aValue2-aValue1) : (aValue1-aValue2);
+ }
+
+//CTLowLevel implementation is shared between TLLD and TLLD2 test apps.
+//The change was made because the original TLLD test app took too much time (over 0.5 hour)
+//and usually was terminated with a TIMEOUT on LUBBOCK device.
+CTLowLevel::CTLowLevel(CTestStep* aStep):
+ CTGraphicsBase(aStep),
+ iDrawDevice(NULL),
+ iBits(NULL),
+ iBuf(NULL),
+ iDispMode(ENone),
+ iUserDispMode(ENone),
+ iOrientation(CFbsDrawDevice::EOrientationNormal),
+ iSize(TSize(0,0)),
+ iLongWidth(0),
+ iTestNo(0),
+ iIteration(0),
+ iReportIteration(0),
+ iTotalReportIterations(0),
+ iFuzzyMatch(EFalse),
+ iBlendTestColors(ETrue),
+ iUseFastFade(EFalse)
+ {
+ iColorConvertor[ENone] = &iNullConvertor;
+ iColorConvertor[EGray2] = &iGray2Convertor;
+ iColorConvertor[EGray4] = &iGray4Convertor;
+ iColorConvertor[EGray16] = &iGray16Convertor;
+ iColorConvertor[EGray256] = &iGray256Convertor;
+ iColorConvertor[EColor16] = &iColor16Convertor;
+ iColorConvertor[EColor256] = &iColor256Convertor;
+ iColorConvertor[EColor4K] = &iColor4KConvertor;
+ iColorConvertor[EColor64K] = &iColor64KConvertor;
+ iColorConvertor[EColor16M] = &iColor16MConvertor;
+ iColorConvertor[ERgb] = &iColor16MConvertor;
+ iColorConvertor[EColor16MU] = &iColor16MUConvertor;
+ iColorConvertor[EColor16MA] = &iColor16MAConvertor;
+ iColorConvertor[EColor16MAP] = &iColor16MAPConvertor;
+ iOrientation = CFbsDrawDevice::EOrientationNormal;
+ iOrientationEnd = CFbsDrawDevice::EOrientationRotated90;
+ }
+
+CTLowLevel::~CTLowLevel()
+ {
+ Reset();
+ }
+
+void CTLowLevel::Reset()
+ {
+ delete iDrawDevice;
+ iDrawDevice = NULL;
+
+ delete iBits;
+ iBits = NULL;
+ delete iBuf;
+ iBuf = NULL;
+ iDispMode = ENone;
+ iSize.SetSize(0,0);
+ iLongWidth = 0;
+ }
+
+void CTLowLevel::RunTestCaseL(TInt aCurTestCase)
+ {
+ ((CTLowLevelStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+ switch(aCurTestCase)
+ {
+ case 1:
+ INFO_PRINTF1(_L("Bitmap device EGray2"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0004
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0004"));
+ TestBitmapDraw(EGray2,TSize(128,100));
+ break;
+ case 2:
+ INFO_PRINTF1(_L("Bitmap device EGray4"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0005
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0005"));
+ TestBitmapDraw(EGray4,TSize(112,100));
+ break;
+ case 3:
+ INFO_PRINTF1(_L("Bitmap device EGray16"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0006
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0006"));
+ TestBitmapDraw(EGray16,TSize(104,100));
+ break;
+ case 4:
+ INFO_PRINTF1(_L("Bitmap device EGray256"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0007
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0007"));
+ TestBitmapDraw(EGray256,TSize(104,100));
+ break;
+ case 5:
+ INFO_PRINTF1(_L("Bitmap device EColor16"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0008
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0008"));
+ TestBitmapDraw(EColor16,TSize(104,100));
+ break;
+ case 6:
+ INFO_PRINTF1(_L("Bitmap device EColor256"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0009
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0009"));
+ TestBitmapDraw(EColor256,TSize(102,100));
+ break;
+ case 7:
+ INFO_PRINTF1(_L("Bitmap device EColor4K"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0010
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0010"));
+ TestBitmapDraw(EColor4K,TSize(100,100));
+ break;
+ case 8:
+ INFO_PRINTF1(_L("Bitmap device EColor64K"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0011
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0011"));
+ TestBitmapDraw(EColor64K,TSize(100,100));
+ break;
+ case 9:
+ INFO_PRINTF1(_L("Bitmap device EColor16M"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0012
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0012"));
+ TestBitmapDraw(EColor16M,TSize(102,100));
+ break;
+ case 10:
+ INFO_PRINTF1(_L("Bitmap device EColor16MU"));
+ iFuzzyMatch=ETrue;
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0013
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0013"));
+ TestBitmapDraw(EColor16MU,TSize(102,100));
+ iFuzzyMatch=EFalse;
+ break;
+ case 11:
+ INFO_PRINTF1(_L("Bitmap device EColor16MA"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0014
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0014"));
+ TestBitmapDraw(EColor16MA,TSize(102,100));
+ break;
+ case 12:
+ INFO_PRINTF1(_L("Bitmap device EColor16MAP"));
+ iFuzzyMatch=ETrue;
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0015
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0015"));
+ TestBitmapDraw(EColor16MAP,TSize(102,100));
+ iFuzzyMatch=EFalse;
+ break;
+ case 13:
+ INFO_PRINTF1(_L("User display mode mapping"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0016
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0016"));
+ TestUserDisplayModeMapping();
+ ((CTLowLevelStep*)iStep)->RecordTestResultL();
+ break;
+ default:
+ if(iOrientation <= iOrientationEnd)
+ {
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0017
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0017"));
+ INFO_PRINTF2(_L("Screen device : %S"), &DisplayModeNames1[iCurScreenDeviceModeIndex]);
+ TDisplayMode display = TestDisplayMode1[iCurScreenDeviceModeIndex++];
+ TestScreenDrawL(display);
+ if(iCurScreenDeviceModeIndex >= KNumberDisplayModes1)
+ {
+ iCurScreenDeviceModeIndex = 0;
+ iOrientation ++;
+ }
+ }
+ else
+ {
+ ((CTLowLevelStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+ ((CTLowLevelStep*)iStep)->CloseTMSGraphicsStep();
+ TestComplete();
+ ((CTLowLevelStep*)iStep)->RecordTestResultL();
+ }
+ break;
+ }
+ }
+
+/* this function is used for likeness matching, using a fixed inaccuracy */
+void CTLowLevel::CheckMatch(TUint32 aFirst,TUint32 aSecond)
+ {
+ TBool fail=EFalse;
+ if (iFuzzyMatch==EFalse)
+ fail|=Check(aFirst==aSecond);
+ else
+ {
+ TUint8* val1=static_cast<TUint8*>(static_cast<void*>(&aFirst));
+ TUint8* val2=static_cast<TUint8*>(static_cast<void*>(&aSecond));
+ fail|=Check(AbsDiff(*val1,*val2)<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(val1+1),*(val2+1))<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(val1+2),*(val2+2))<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(val1+3),*(val2+3))<KInaccuracyLimit);
+ }
+ if (fail)
+ {
+ _LIT(KLog,"The values 0x%x and 0x%x don't match, fuzzyMatch=%d (limit=%d)");
+ INFO_PRINTF5(KLog,aFirst,aSecond,iFuzzyMatch,KInaccuracyLimit);
+ }
+ }
+
+void CTLowLevel::TestScreenDrawL(TDisplayMode aDisplayMode)
+ {
+ TUint startTime=User::TickCount();
+
+ Reset();
+
+ iDispMode = aDisplayMode;
+
+ INFO_PRINTF1(_L("\n"));
+ INFO_PRINTF2(_L("Testing Screen driver \"%S\""), &(DisplayModeNames[::DisplayMode2Index(aDisplayMode)]));
+ INFO_PRINTF1(_L("\r\n"));
+ TInt address = NULL;
+ TSize size(0,0);
+
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayMemoryAddress,address));
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayXPixels,size.iWidth));
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayYPixels,size.iHeight));
+ ASSERT(size.iWidth > 0 && size.iHeight > 0 && address != NULL);
+
+ TPckgBuf<TScreenInfoV01> info;
+ info().iScreenAddressValid = ETrue;
+ info().iScreenAddress = REINTERPRET_CAST(TAny*,address);
+ info().iScreenSize = size;
+
+ TRAPD(ret,iDrawDevice = CFbsDrawDevice::NewScreenDeviceL(info(),aDisplayMode));
+
+ if (ret == KErrNotSupported)
+ {
+ INFO_PRINTF1(_L("Not supported\r\n"));
+ return;
+ }
+ else if (ret != KErrNone)
+ User::Panic(_L("Draw device create"),ret);
+
+ iDrawDevice->InitScreen();
+ iDrawDevice->SetDisplayMode(iDrawDevice);
+ iDrawDevice->SetAutoUpdate(EFalse);
+ TBool orientation[4];
+ iDrawDevice->OrientationsAvailable(orientation);
+
+ TBool orientationSupported = iDrawDevice->SetOrientation(CFbsDrawDevice::TOrientation(iOrientation));
+ if (orientationSupported)
+ {
+ Check(orientation[iOrientation]);
+ if (iOrientation & 1)
+ iSize = TSize(size.iHeight,size.iWidth);
+ else
+ iSize = size;
+ iLongWidth = LongWidth(iSize.iWidth,aDisplayMode);
+ Test();
+ }
+ else
+ {
+ Check(!orientation[iOrientation]);
+ INFO_PRINTF1(_L("Orientation not supported\r\n"));
+ }
+
+ INFO_PRINTF2(_L("Testing time=%d"), (User::TickCount() - startTime) * 100 / 64);
+ }
+
+void CTLowLevel::TestBitmapDraw(TDisplayMode aDisplayMode,const TSize& aSize)
+ {
+ TUint startTime=User::TickCount();
+ Reset();
+ iDispMode = aDisplayMode;
+ iSize = aSize;
+ iLongWidth = LongWidth(aSize.iWidth,aDisplayMode);
+ TSize size(0,0);
+ INFO_PRINTF1(KNullDesC);
+
+ const TInt byteSize=ByteSize()*iSize.iHeight;
+ _LIT(KNoMem,"Not enough memory for bitmap bits");
+ iBits = new TUint8[byteSize];
+ if(!iBits)
+ {
+ User::Panic(KNoMem,KErrNoMemory);
+ }
+
+ iBuf = new TUint32[byteSize];
+ if(!iBuf)
+ {
+ User::Panic(KNoMem,KErrNoMemory);
+ }
+
+ TPckgBuf<TScreenInfoV01> info;
+ info().iScreenSize = aSize;
+ info().iScreenAddress = NULL;
+ info().iScreenAddressValid = ETrue;
+
+ TRAPD(ret, iDrawDevice = CFbsDrawDevice::NewBitmapDeviceL(info(), aDisplayMode, ByteSize() ));
+ if (ret == KErrNotSupported)
+ {
+ INFO_PRINTF1(_L("Not supported\r\n"));
+ return;
+ }
+ else if (ret != KErrNone)
+ {
+ User::Panic(_L("Draw device create"),ret);
+ }
+ iDrawDevice->SetAutoUpdate(EFalse);
+ //Initialize the iDrowDevice object, if successful val=KErrNone
+ TInt val=iDrawDevice->InitScreen();
+ TEST(val==KErrNone);
+ iDrawDevice->CFbsDrawDevice::SetBits(iBits);
+ iDrawDevice->CFbsDrawDevice::ShadowBuffer(10,iBuf);
+ iDrawDevice->CFbsDrawDevice::SetUserDisplayMode(iDispMode);
+ iDrawDevice->SetDisplayMode(iDrawDevice);
+ iDrawDevice->Update();
+ iDrawDevice->SetUserDisplayMode(iDispMode);
+ iDrawDevice->SetBits(iBits);
+ Test();
+ TBool orientation[4];
+ iDrawDevice->OrientationsAvailable(orientation);
+ TBool orientationSupported = iDrawDevice->SetOrientation(CFbsDrawDevice::TOrientation(iOrientation));
+ if (orientationSupported)
+ {
+ Check(orientation[iOrientation]);
+ if (iOrientation & 1)
+ iSize = TSize(size.iHeight,size.iWidth);
+ else
+ iSize = size;
+ iLongWidth = LongWidth(iSize.iWidth,aDisplayMode);
+ }
+ else
+ {
+ Check(!orientation[iOrientation]);
+ INFO_PRINTF1(_L("Orientation not supported\r\n"));
+ }
+ INFO_PRINTF2(_L("Testing time=%d"), (User::TickCount() - startTime) * 100 / 64);
+ }
+
+TInt RgbComponent(TRgb aRgb, TInt aRgbIndex)
+ {
+ return(aRgbIndex==0?aRgb.Red():(aRgbIndex==1?aRgb.Green():aRgb.Blue()));
+ }
+
+TBool CheckNormalizedValue(TRgb aReadCol, TRgb aNormalizedCol1, TRgb aNormalizedCol2, TRgb aNormalizedCol3, TRgb aNormalizedCol4, TInt aRgbIndex)
+ {
+
+ const TInt KErrorMargin=5;
+ TInt minCol=Min(RgbComponent(aNormalizedCol1,aRgbIndex),
+ Min(RgbComponent(aNormalizedCol2,aRgbIndex),
+ Min(RgbComponent(aNormalizedCol3,aRgbIndex),RgbComponent(aNormalizedCol4,aRgbIndex))))-KErrorMargin;
+ TInt maxCol=Max(RgbComponent(aNormalizedCol1,aRgbIndex),
+ Max(RgbComponent(aNormalizedCol2,aRgbIndex),
+ Max(RgbComponent(aNormalizedCol3,aRgbIndex),RgbComponent(aNormalizedCol4,aRgbIndex))))+KErrorMargin;
+ TInt readComponent=RgbComponent(aReadCol,aRgbIndex);
+ return(readComponent>=minCol && readComponent<=maxCol);
+ }
+
+void CTLowLevel::CheckNormalizedRgb(TRgb aReadRgb, TRgb aCheckRgb, TDisplayMode aDevDisplayMode, TDisplayMode aUserDisplayMode, TBool aWriteRgbAlphaLine)
+ {
+ TRgb normalized1=aCheckRgb;
+ Normalize(normalized1,aUserDisplayMode);
+ if (aDevDisplayMode==EColor16MAP)
+ {
+ const TInt KNormalizeErrorMargin=3;
+ TRgb normalizedPMA1=aCheckRgb;
+// Allow error margin for blending errors before calculating value normalized to user display mode
+ normalizedPMA1.SetRed(Min(0xFF,normalizedPMA1.Red()+KNormalizeErrorMargin));
+ normalizedPMA1.SetGreen(Min(0xFF,normalizedPMA1.Green()+KNormalizeErrorMargin));
+ normalizedPMA1.SetBlue(Min(0xFF,normalizedPMA1.Blue()+KNormalizeErrorMargin));
+//
+ Normalize(normalizedPMA1,aUserDisplayMode);
+ TRgb normalizedPMA3=normalizedPMA1;
+ normalizedPMA1=TRgb::Color16MAP(normalizedPMA1.Color16MAP());
+ TRgb normalizedPMA2=aCheckRgb;
+ normalizedPMA2=TRgb::Color16MAP(normalizedPMA2.Color16MAP());
+ normalizedPMA2.SetRed(Max(0,normalizedPMA2.Red()-KNormalizeErrorMargin));
+ normalizedPMA2.SetGreen(Max(0,normalizedPMA2.Green()-KNormalizeErrorMargin));
+ normalizedPMA2.SetBlue(Max(0,normalizedPMA2.Blue()-KNormalizeErrorMargin));
+ Normalize(normalizedPMA2,aUserDisplayMode);
+ TEST(CheckNormalizedValue(aReadRgb,normalizedPMA1,normalizedPMA2,normalizedPMA3,normalized1,0) &&
+ CheckNormalizedValue(aReadRgb,normalizedPMA1,normalizedPMA2,normalizedPMA3,normalized1,1) &&
+ CheckNormalizedValue(aReadRgb,normalizedPMA1,normalizedPMA2,normalizedPMA3,normalized1,2));
+ }
+ else
+ {
+ if (aDevDisplayMode==EColor64K && aWriteRgbAlphaLine)
+ {
+ // In EColor64K the WriteRgbAlphaLine code maps to native display mode first, before mapping to
+ // user mode then back again to device display mode. So use normalized2 to check for that case
+ TRgb normalized2=aCheckRgb;
+ Normalize(normalized2,aDevDisplayMode);
+ Normalize(normalized2,aUserDisplayMode);
+ Normalize(normalized2,aDevDisplayMode);
+ TEST(aReadRgb.Color16MU()==normalized2.Color16MU());
+ }
+ else
+ {
+ Normalize(normalized1,aDevDisplayMode);
+ TEST(aReadRgb.Color16MU()==normalized1.Color16MU());
+ }
+ }
+ }
+
+void CTLowLevel::PrepareDestPixel(TDisplayMode aDevDisplayMode, TRgb& aRgb, TInt aDstAlpha)
+ {
+ CGraphicsContext::TDrawMode drawMode;
+ if (aDevDisplayMode==EColor16MAP)
+ {
+ aRgb.SetAlpha(aDstAlpha);
+ drawMode=CGraphicsContext::EDrawModeWriteAlpha;
+ }
+ else
+ {
+ aRgb.SetAlpha(0xFF);
+ drawMode=CGraphicsContext::EDrawModePEN;
+ }
+ iDrawDevice->WriteRgbMulti(0,0,1,1,aRgb,drawMode);
+ }
+
+void CTLowLevel::CheckMappedRgb(TDisplayMode aDevDisplayMode, TDisplayMode aUserDisplayMode, TRgb aRgb)
+ {
+ const TInt KMaxAlphaModes=5;
+ TInt alphaModeValues[KMaxAlphaModes]={0xFF,0xC0,0x80,0x40,0};
+ TInt dstAlphaModeCount=aDevDisplayMode==EColor16MAP?KMaxAlphaModes:1;
+ for(TInt dstAlphaMode=0;dstAlphaMode<dstAlphaModeCount;dstAlphaMode++)
+ {
+ TInt dstAlpha=alphaModeValues[dstAlphaMode];
+ for(TInt alphaMode=0;alphaMode<KMaxAlphaModes;alphaMode++)
+ {
+ TInt alpha=alphaModeValues[alphaMode];
+ if ((aUserDisplayMode==EColor16 || aUserDisplayMode==EColor256) && (alpha!=0xFF || dstAlpha!=0xFF))
+ continue; // Mapping to EColor16 or EColor256 with fuzzy blends and PMA losses impossible to check for accurately
+ PrepareDestPixel(aDevDisplayMode,aRgb,dstAlpha);
+ aRgb.SetAlpha(alpha);
+ iDrawDevice->WriteRgb(0,0,aRgb,CGraphicsContext::EDrawModePEN);
+ TRgb readRgb=iDrawDevice->ReadPixel(0,0);
+ CheckNormalizedRgb(readRgb,aRgb,aDevDisplayMode,aUserDisplayMode,EFalse);
+//
+ PrepareDestPixel(aDevDisplayMode,aRgb,dstAlpha);
+ iDrawDevice->WriteRgbMulti(0,0,1,1,aRgb,CGraphicsContext::EDrawModePEN);
+ readRgb=iDrawDevice->ReadPixel(0,0);
+ CheckNormalizedRgb(readRgb,aRgb,aDevDisplayMode,aUserDisplayMode,EFalse);
+//
+ PrepareDestPixel(aDevDisplayMode,aRgb,dstAlpha);
+ TUint32 writeBuffer[1];
+ writeBuffer[0]=aRgb.Internal();
+ TUint8 mask[1]={0xFF};
+ iDrawDevice->WriteRgbAlphaLine(0,0,1,(TUint8*)writeBuffer,mask,CGraphicsContext::EDrawModePEN);
+ readRgb=iDrawDevice->ReadPixel(0,0);
+ CheckNormalizedRgb(readRgb,aRgb,aDevDisplayMode,aUserDisplayMode,ETrue);
+ }
+ }
+ }
+
+void CTLowLevel::TestUserDisplayModeMapping()
+ {
+ TInt address = NULL;
+ TSize size;
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayMemoryAddress,address));
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayXPixels,size.iWidth));
+ User::LeaveIfError(HAL::Get(KDefaultScreenNo, HALData::EDisplayYPixels,size.iHeight));
+ ASSERT(size.iWidth > 0 && size.iHeight > 0 && address != NULL);
+
+ TPckgBuf<TScreenInfoV01> info;
+ info().iScreenAddressValid = ETrue;
+ info().iScreenAddress = REINTERPRET_CAST(TAny*,address);
+ info().iScreenSize = size;
+//
+ for (TInt nDispModeDev = 0; nDispModeDev < KNumDispModes; nDispModeDev++)
+ {
+ TDisplayMode dispModeDev = TestDisplayMode[nDispModeDev];
+ if (!TDisplayModeUtils::IsDisplayModeColor(dispModeDev) || TDisplayModeUtils::NumDisplayModeColors(dispModeDev)<65536)
+ continue; // Older modes have their quirks we don't want to mess with
+ Reset();
+ TRAPD(ret,iDrawDevice = CFbsDrawDevice::NewScreenDeviceL(info(),dispModeDev));
+ if (ret == KErrNotSupported)
+ continue;
+ for (TInt nDispMode = 0; nDispMode < KNumDispModes; nDispMode++)
+ {
+ TDisplayMode userDispMode = TestDisplayMode[nDispMode];
+ INFO_PRINTF3(_L("Testing devMode=%d, userMode=%d"), dispModeDev, userDispMode);
+ iDrawDevice->SetUserDisplayMode(userDispMode);
+ TUint rgbVal=0;
+ FOREVER
+ {
+ CheckMappedRgb(dispModeDev,userDispMode,rgbVal);
+ if (rgbVal==0xFFFFFF)
+ break;
+ rgbVal+=0x010305;
+ if (rgbVal>0xFFFFFF) // We want to make sure we test 0xFFFFFF as a special case
+ rgbVal=0xFFFFFF;
+ }
+ }
+ }
+ }
+
+void CTLowLevel::Test()
+ {
+ _LIT(KOrientation,"Orientation: %S");
+ TBuf<32> buf;
+ buf.Format(KOrientation,&RotationName(iOrientation));
+ INFO_PRINTF1(buf);
+
+ iTestNo = 1;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 1;
+ TestParams();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = KNumDispModes;
+ TestReadLine();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = KNumShadowModes * KNumDrawModes;
+ if(KFastFading && (iDispMode == EColor64K ||iDispMode == EColor16MU || iDispMode == EColor16MA || iDispMode == EColor16MAP))
+ {
+ iUseFastFade = ETrue;
+ }
+ TestWriteRgb();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ TestWriteLine();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ TestWriteBinary();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 4;
+ TestWriteRGBAlpha();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = KNumShadowModes;
+ TestShadow();
+ if(KFastFading && (iDispMode == EColor64K|| iDispMode == EColor16MU || iDispMode == EColor16MA || iDispMode == EColor16MAP))
+ {
+ iUseFastFade = EFalse;
+ }
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 1;
+ TestWriteAlphaLineEx();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 1;
+ TestWriteAlphaLineNoShadowEx();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 1;
+ TestWriteMaskLineNoShadowEx();
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = 1;
+ TRAPD(err,((CTLowLevelStep*)iStep)->RecordTestResultL(););
+ if (err!=KErrNone)
+ INFO_PRINTF1(_L("Failed to record test result"));
+
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0003"));
+ TestFastBlendBitmapMasked();
+ TRAPD(err1,((CTLowLevelStep*)iStep)->RecordTestResultL(););
+ if (err1!=KErrNone)
+ INFO_PRINTF1(_L("Failed to record test result"));
+
+ iTestNo++;
+ iIteration = 0;
+ iReportIteration = 1;
+ iTotalReportIterations = KNumBlendingColors;
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0002"));
+ TestWriteRgbOutlineAndShadow();
+ TRAP(err,((CTLowLevelStep*)iStep)->RecordTestResultL(););
+ if (err!=KErrNone)
+ INFO_PRINTF1(_L("Failed to record test result"));
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0001
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0001"));
+ }
+
+void CTLowLevel::TestParams()
+ {
+ Check(iDrawDevice->SizeInPixels()==iSize);
+ Check(iDrawDevice->DisplayMode()==iDispMode);
+ Check(iDrawDevice->LongWidth()==iLongWidth);
+ Check(iDrawDevice->ScanLineBuffer()!=NULL);
+ Check(iLongWidth%(iDrawDevice->ScanLineBytes())==0
+ || iDrawDevice->ScanLineBytes() == iLongWidth * 2
+ || iDrawDevice->ScanLineBytes() == iLongWidth * 3
+ || iDrawDevice->ScanLineBytes() == iLongWidth * 4);
+ TInt hT = iDrawDevice->HorzTwipsPerThousandPixels();
+ Check(hT >= 0);
+ TInt vT = iDrawDevice->VertTwipsPerThousandPixels();
+ Check(vT >= 0);
+ Report();
+ }
+
+void CTLowLevel::TestReadLine()
+ {
+ TInt byteSize = ByteSize();
+ TUint8* writeBuffer = new TUint8[byteSize];
+ TUint8* readBuffer = new TUint8[iSize.iWidth * sizeof(TRgb)];
+ Check(writeBuffer != NULL);
+ Check(readBuffer != NULL);
+
+ for (TInt nDispMode = 0; nDispMode < KNumDispModes; nDispMode++)
+ {
+ TDisplayMode dispMode = TestDisplayMode[nDispMode];
+ iDrawDevice->SetUserDisplayMode(dispMode);
+
+ if (dispMode == EColor16MU || dispMode == EColor16MAP || iDispMode == EColor16MU || iDispMode == EColor16MAP)
+ iFuzzyMatch=ETrue;
+ else
+ iFuzzyMatch=EFalse;
+ for (TInt cnt=0;cnt<2;cnt++)
+ {
+ if (cnt==0) //first time
+ iDrawDevice->SetUserDisplayMode(dispMode);
+ else
+ iDrawDevice->SetUserDisplayMode(iDispMode);
+
+ for (TInt nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ TRect rect = TestRect[nRect];
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ Clear(KRgbWhite);
+
+ FillBuffer(writeBuffer, byteSize, iDispMode, ETrue);
+ Mem::FillZ(readBuffer,byteSize);
+
+ //we select EDrawModeWriteAlpha because do not test blending here
+ iDrawDevice->WriteLine(rect.iTl.iX,yy,rect.Width(),(TUint32*)writeBuffer,CGraphicsContext::EDrawModeWriteAlpha);
+ iDrawDevice->ReadLine(rect.iTl.iX,yy,rect.Width(),(TUint32*)readBuffer,dispMode);
+
+ CheckBuffer(writeBuffer,iDispMode,readBuffer,dispMode,rect.Width());
+
+ Mem::FillZ(readBuffer,byteSize);
+
+ //we select EDrawModeWriteAlpha because do not test blending here
+ iDrawDevice->WriteLine(iSize.iWidth-rect.Width(),yy,rect.Width(),(TUint32*)writeBuffer,CGraphicsContext::EDrawModeWriteAlpha);
+ iDrawDevice->ReadLine(iSize.iWidth-rect.Width(),yy,rect.Width(),(TUint32*)readBuffer,dispMode);
+
+ CheckBuffer(writeBuffer,iDispMode,readBuffer,dispMode,rect.Width());
+ iIteration++;
+ }
+ }
+ }
+ if (iDispMode != EColor16MU && iDispMode != EColor16MAP)
+ iFuzzyMatch=EFalse;
+ Report();
+ }
+ delete [] writeBuffer;
+ delete [] readBuffer;
+ }
+
+void CTLowLevel::TestWriteRgb()
+ {
+ for (TInt shadowMode = 0; shadowMode < KNumShadowModes; shadowMode++)
+ {
+ for (TInt nMode = 0; nMode < KNumDrawModes; nMode++)
+ {
+ for (TInt nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ for (TInt nColor = 0; nColor < KNumTestColors; nColor++)
+ {
+
+ //for modes other than EColor16MAP skip the new colours which have alpha, and cause
+ //test failures. There are two types of colours which need to be skipped, nColor,
+ //and nBackColor. The additional colours were added specificially to test EColor16MAP mode,
+ //so the test coverage compared to previously is not reduced for non EColor16MAP modes.
+ if (((nColor>=KMaxNon16Colours)|| (nBackColor>=KMaxNon16BackColours)) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+
+ CGraphicsContext::TDrawMode dMode = TestDrawMode[nMode];
+
+ if ((iDispMode==EColor16MAP)&&(dMode!=CGraphicsContext::EDrawModePEN))
+ continue;
+
+
+ TRect rect = TestRect[nRect];
+ TRgb col = TestColor[nColor];
+
+ iDrawDevice->CFbsDrawDevice::SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->CFbsDrawDevice::SetFadingParameters(100,200);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->WriteRgb(rect.iTl.iX,rect.iTl.iY,col,dMode);
+
+ CheckRgb(rect.iTl,col,bakCol,dMode,shadowMode);
+ CheckBackground(TRect(rect.iTl,TSize(1,1)),bakCol);
+
+ Clear(bakCol);
+
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->WriteRgbMulti(rect.iTl.iX,rect.iTl.iY,rect.Width(),rect.Height(),col,dMode);
+
+ CheckRgb(rect,col,bakCol,dMode,shadowMode);
+ CheckBackground(rect,bakCol);
+ iIteration++;
+ }
+ }
+ }
+ Report();
+ }
+ }
+ }
+
+void CTLowLevel::TestWriteLine()
+ {
+ TInt byteSize = ByteSize();
+ TUint8* backBuffer = new TUint8[byteSize];
+ TUint8* writeBuffer = new TUint8[byteSize];
+ TUint8* copyBuffer = new TUint8[byteSize];
+ TUint8* readBuffer = new TUint8[byteSize];
+ Check(backBuffer != NULL);
+ Check(writeBuffer != NULL);
+ Check(copyBuffer != NULL);
+ Check(readBuffer != NULL);
+
+ for (TInt shadowMode = 0; shadowMode < KNumShadowModes; shadowMode++)
+ {
+ for (TInt nMode = 0; nMode < KNumDrawModes; nMode++)
+ {
+ CGraphicsContext::TDrawMode dMode = TestDrawMode[nMode];
+ for (TInt nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ //skip over new colours with alpha for modes other than EColor16MAP
+ //these were causing test failures
+ if ((nBackColor>=KMaxNon16BackColours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+ /*TBuf<128> buf; //Some extra logging that might be useful if this test fails
+ _LIT(KLog1,"Shadow=%d, DrawMode=%d, Rect=(%d,%d,%d,%d), Color=%d");
+ buf.Format(KLog1,shadowMode,dMode,rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,rect.iBr.iY,nBackColor);
+ INFO_PRINTF1(buf);*/
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->CFbsDrawDevice::SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->CFbsDrawDevice::SetFadingParameters(100,200);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->ReadLine(rect.iTl.iX,yy,rect.Width(),(TUint32*)backBuffer,iDispMode);
+
+ if (nRect != 7)
+ {
+ // make sure the alpha value is 0xFF when not blending the buffer into 16MU destination
+ TBool noAlpha16MU = dMode != CGraphicsContext::EDrawModePEN;
+ FillBuffer(writeBuffer, byteSize, iDispMode, noAlpha16MU);
+ }
+ else // Special check for losing leading 0s in 1 bpp mode at 31 pixel offset
+ {
+ Mem::Fill(writeBuffer,byteSize,0xff);
+ writeBuffer[0] = 0xfe;
+ }
+ Mem::Copy(copyBuffer,writeBuffer,byteSize);
+ iDrawDevice->WriteLine(rect.iTl.iX,yy,rect.Width(),(TUint32*)writeBuffer,dMode);
+ Shadow(copyBuffer,byteSize,shadowMode);
+
+ Mem::FillZ(readBuffer,byteSize);
+ iDrawDevice->ReadLine(rect.iTl.iX,yy,rect.Width(),(TUint32*)readBuffer,iDispMode);
+ CheckLine(copyBuffer,readBuffer,backBuffer,rect.Width(),dMode,iDispMode);
+
+ iIteration++;
+ }
+ CheckBackground(rect,bakCol);
+ }
+ }
+ Report();
+ }
+ }
+ delete [] backBuffer;
+ delete [] writeBuffer;
+ delete [] copyBuffer;
+ delete [] readBuffer;
+ }
+
+void CTLowLevel::TestWriteBinary()
+ {
+ TInt byteSize = ByteSize();
+ TInt wordSize = (byteSize + 3) / 4;
+ TUint32* writeBuffer = new TUint32[wordSize];
+ Check(writeBuffer != NULL);
+
+ for (TInt shadowMode = 0; shadowMode < KNumShadowModes; shadowMode++)
+ {
+ for (TInt nMode = 0; nMode < KNumDrawModes; nMode++)
+ {
+ for (TInt nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ for (TInt nColor = 0; nColor < KNumTestColors; nColor++)
+ {
+ if (((nColor>=KMaxNon16Colours)|| (nBackColor>=KMaxNon16BackColours)) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRect rect = TestRect[nRect];
+ if (rect.Width() > 32)
+ {
+ rect.iBr.iX = rect.iTl.iX + 32;
+ }
+ if (rect.Width() < 1)
+ rect.iBr.iX = rect.iTl.iX + 1;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ TRgb col = TestColor[nColor];
+ CGraphicsContext::TDrawMode dMode = TestDrawMode[nMode];
+
+ if ((iDispMode==EColor16MAP)&&(dMode!=CGraphicsContext::EDrawModePEN))
+ continue;
+
+ Clear(bakCol);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ FillBuffer((TUint8*)writeBuffer, byteSize, EGray2);
+ iDrawDevice->WriteBinary(rect.iTl.iX,rect.iTl.iY,writeBuffer,rect.Width(),rect.Height(),col,dMode);
+ CheckBinary(rect,writeBuffer,col,bakCol,dMode,shadowMode,ETrue,EFalse);
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ FillBuffer((TUint8*)writeBuffer, byteSize, EGray2);
+ iDrawDevice->WriteBinaryLine(rect.iTl.iX,rect.iTl.iY,writeBuffer,rect.Width(),col,dMode);
+ CheckBinary(TRect(rect.iTl,TSize(rect.Width(),1)),writeBuffer,col,bakCol,dMode,shadowMode,EFalse,EFalse);
+ CheckBackground(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,rect.iTl.iY + 1),bakCol);
+
+ Clear(bakCol);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ FillBuffer((TUint8*)writeBuffer, byteSize, EGray2);
+ iDrawDevice->WriteBinaryLineVertical(rect.iTl.iX,rect.iTl.iY,writeBuffer,rect.Height(),col,dMode,EFalse);
+ CheckBinary(TRect(rect.iTl,TSize(1,rect.Height())),writeBuffer,col,bakCol,dMode,shadowMode,EFalse,EFalse);
+ CheckBackground(TRect(rect.iTl.iX,rect.iTl.iY,rect.iTl.iX + 1,rect.iBr.iY),bakCol);
+
+ Clear(bakCol);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ FillBuffer((TUint8*)writeBuffer, byteSize, EGray2);
+ iDrawDevice->WriteBinaryLineVertical(rect.iTl.iX,rect.iBr.iY - 1,writeBuffer,rect.Height(),col,dMode,ETrue);
+ CheckBinary(TRect(rect.iTl,TSize(1,rect.Height())),writeBuffer,col,bakCol,dMode,shadowMode,EFalse,ETrue);
+ CheckBackground(TRect(rect.iTl.iX,rect.iTl.iY,rect.iTl.iX + 1,rect.iBr.iY),bakCol);
+
+ iIteration++;
+ }
+ }
+ }
+ Report();
+ }
+ }
+ delete [] writeBuffer;
+ }
+
+void CTLowLevel::TestWriteAlphaLineEx()
+ {
+ TAny* interface = NULL;
+ TInt err = iDrawDevice->GetInterface(KFastBlitInterfaceID, interface);
+ if(err == KErrNone)
+ {
+ INFO_PRINTF1(_L("START ---->TestWriteAlphaLineEx"));
+ TSize size = TSize(30,30);
+ TRect rect = TRect(size);
+
+ TUint16* writeBuffer = new TUint16[size.iWidth];
+ TUint8* maskBuffer = new TUint8[size.iWidth];
+
+ TInt nOffset = sizeof(TUint16)*size.iWidth/2;
+
+ Mem::Fill(writeBuffer,nOffset,0xff);
+ Mem::Fill((((TUint8*)writeBuffer)+nOffset),nOffset,0x00);
+ Mem::Fill(maskBuffer,size.iWidth/2,0x00);
+ Mem::Fill((maskBuffer+size.iWidth/2),size.iWidth/2,0xff);
+
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+ Clear(KRgbFadedBlack);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::EFade);
+
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ fastBlit->WriteAlphaLineEx(rect.iTl.iX,yy,rect.Width(),0,(TUint32*)writeBuffer,EColor64K,0,(TUint32*)maskBuffer,MAlphaBlend::EShdwBefore);
+ iIteration++;
+ }
+ CheckRgb(rect,KRgbBlack,KRgbFadedBlack,CGraphicsContext::EDrawModePEN,2);
+ CheckBackground(rect,KRgbFadedBlack);
+
+ Report();
+ INFO_PRINTF1(_L("END ---->TestWriteAlphaLineEx"));
+ delete [] writeBuffer;
+ delete [] maskBuffer;
+ }
+ }
+
+void CTLowLevel::TestWriteAlphaLineNoShadowEx()
+ {
+ TAny* interface = NULL;
+ TInt err = iDrawDevice->GetInterface(KFastBlitInterfaceID, interface);
+ if(err == KErrNone)
+ {
+ INFO_PRINTF1(_L("START ---->TestWriteAlphaLineNoShadowEx"));
+ TSize size = TSize(30,30);
+ TRect rect = TRect(size);
+
+ TUint16* writeBuffer = new TUint16[size.iWidth];
+ Check(writeBuffer != NULL);
+ TUint8* maskBuffer = new TUint8[size.iWidth];
+ Check(maskBuffer != NULL);
+ TInt nOffset = sizeof(TUint16) * size.iWidth;
+
+ Mem::Fill(writeBuffer,nOffset,0xff);
+ Mem::Fill(maskBuffer,size.iWidth/2,0x8e);
+ Mem::Fill((maskBuffer+size.iWidth/2),size.iWidth/2,0xff);
+
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+
+ Clear(KRgbWhite);
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ fastBlit->WriteAlphaLineEx(rect.iTl.iX,yy,rect.Width(),0,(TUint32*)writeBuffer,EColor64K,0,(TUint32*)maskBuffer,MAlphaBlend::EShdwBefore);
+ iIteration++;
+ }
+ CheckRgb(rect,KRgbWhite,KRgbWhite,CGraphicsContext::EDrawModePEN,0);
+
+ Report();
+ INFO_PRINTF1(_L("END ---->TestWriteAlphaLineNoShadowEx"));
+ delete [] writeBuffer;
+ delete [] maskBuffer;
+ }
+ }
+
+void CTLowLevel::TestWriteMaskLineNoShadowEx()
+ {
+ TAny* interface = NULL;
+ TInt err = iDrawDevice->GetInterface(KFastBlitInterfaceID, interface);
+ if(err == KErrNone)
+ {
+ INFO_PRINTF1(_L("START ---->TestWriteMaskLineNoShadowEx"));
+ TSize size = TSize(30,30);
+ TRect rect = TRect(size);
+
+ TUint16* writeBuffer = new TUint16[size.iWidth];
+ Check(writeBuffer != NULL);
+ TUint8* maskBuffer = new TUint8[size.iWidth];
+ Check(maskBuffer != NULL);
+
+ TInt nOffset = sizeof(TUint16) * size.iWidth;
+
+ Mem::Fill(writeBuffer,nOffset,0xff);
+ Mem::Fill(maskBuffer,size.iWidth/2,0x8e);
+ Mem::Fill((maskBuffer+size.iWidth/2),size.iWidth/2,0xff);
+
+ MFastBlit* fastBlit = reinterpret_cast<MFastBlit*>(interface);
+
+ Clear(KRgbWhite);
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ fastBlit->WriteMaskLineEx(rect.iTl.iX,yy,rect.Width(),0,(TUint32*)writeBuffer,EColor64K,0,(TUint32*)maskBuffer,EFalse);
+ iIteration++;
+ }
+ CheckRgb(rect,KRgbWhite,KRgbWhite,CGraphicsContext::EDrawModePEN,0);
+
+ Report();
+ INFO_PRINTF1(_L("END ---->TestWriteMaskLineNoShadowEx"));
+ delete [] writeBuffer;
+ delete [] maskBuffer;
+ }
+ }
+
+/**
+Overwrite the pixel in the buffer with a given mode with a value already in that
+mode.
+@param aX The offset in pixels from the start of the buffer.
+@param aPtr The start of the buffer.
+@param aMode The display mode of the buffer.
+@param aValue The new pixel value.
+*/
+void CTLowLevel::WriteBinaryValue(TUint32 aX, TAny* const aPtr,
+ TDisplayMode aMode, TUint32 aValue) const
+ {
+ TUint32* buffer32 = (TUint32*)aPtr;
+ TInt shift;
+ TUint32 mask;
+
+ switch (aMode)
+ {
+ case EGray2:
+ buffer32 += aX >> 5;
+ shift = aX & 0x1F;
+ mask = 0x1;
+ break;
+ case EGray4:
+ buffer32 += aX >> 4;
+ shift = (aX & 0xF) << 1;
+ mask = 0x3;
+ break;
+ case EGray16:
+ case EColor16:
+ buffer32 += aX >> 3;
+ shift = (aX & 0x7) << 2;
+ mask = 0xF;
+ break;
+ case EGray256:
+ case EColor256:
+ buffer32 += aX >> 2;
+ shift = (aX & 0x3) << 3;
+ mask = 0xFF;
+ break;
+ case EColor4K:
+ buffer32 += aX >> 1;
+ shift = (aX & 0x1) << 4;
+ mask = 0xFFF;
+ break;
+ case EColor64K:
+ buffer32 += aX >> 1;
+ shift = (aX & 0x1) << 4;
+ mask = 0xFFFF;
+ break;
+ case EColor16M:
+ {
+ // This mode requires special handling, because shifts and masks
+ // won't work.
+ TUint8* buffer8 = ((TUint8*)aPtr) + (aX * 3);
+ *buffer8++ = aValue & 0xFF;
+ *buffer8++ = (aValue >> 8) & 0xFF;
+ *buffer8++ = (aValue >> 16) & 0xFF;
+ // Return early as the buffer has been updated.
+ return;
+ }
+ case EColor16MU:
+ buffer32 += aX;
+ shift = 0;
+ mask = 0xFFFFFFFF;
+ aValue |= 0xFF000000; // Force alpha to opaque.
+ break;
+ default:
+ buffer32 += aX;
+ shift = 0;
+ mask = 0xFFFFFFFF;
+ break;
+ };
+
+ // Write pixel value into right part of word.
+ *buffer32 = (*buffer32 & ~(mask << shift)) | ((aValue & mask) << shift);
+ }
+
+/**
+Copy contents of one buffer over another, depending on a per-pixel mask bit.
+@param aSrc Source pixel buffer
+@param aSrcMode Display mode of source
+@param aDst Destination pixel buffer
+@param aDstMode Display mode of destination
+@param aMsk Mask buffer. Must be in EGray2 format
+@param aWidth Number of pixels to copy
+@param aInvert If ETrue, copy source where mask bit is clear, else copy where
+ it is set.
+*/
+void CTLowLevel::MaskedBlendBuffer(TAny* aSrc, TDisplayMode aSrcMode, TAny* aDst,
+ TDisplayMode aDstMode, TUint32* aMsk, TInt aWidth, TBool aInvert)
+ {
+ TColorConvertor& srcConvertor = ColorConvertor(aSrcMode);
+ TColorConvertor& dstConvertor = ColorConvertor(aDstMode);
+
+ for (TInt xx = 0; xx < aWidth; xx++)
+ {
+ TUint32 pixelMask = ExtractBinaryValue(xx, aMsk, EGray2);
+ if (aInvert)
+ {
+ pixelMask = !pixelMask;
+ }
+
+ if (pixelMask)
+ {
+ TUint32 dst32 = ExtractBinaryValue(xx, (TUint32*)aDst, aDstMode);
+ TUint32 src32 = ExtractBinaryValue(xx, (TUint32*)aSrc, aSrcMode);
+
+ switch (aSrcMode)
+ {
+ // Only blend for source modes with alpha
+ case EColor16MAP:
+ case EColor16MA:
+ {
+ // Convert source and destination pixel values to 16MAP
+ if (aDstMode != EColor16MAP)
+ {
+ dst32 = dstConvertor.Color(dst32).Color16MAP();
+ }
+ if (aSrcMode != EColor16MAP)
+ {
+ src32 = srcConvertor.Color(src32).Color16MAP();
+ }
+ // Both params must be 16MAP, output is likewise
+ dst32 = PMAPixelBlend(dst32, src32);
+ // Convert 16MAP to final format
+ dst32 = dstConvertor.Index(TRgb::Color16MAP(dst32));
+ }
+ break;
+ // Anything else is a copy (with format conversion)
+ default:
+ dst32 = dstConvertor.Index(srcConvertor.Color(src32));
+ break;
+ }
+
+ WriteBinaryValue(xx, aDst, aDstMode, dst32);
+ }
+ }
+ }
+
+/**
+Returns the minimum number of bytes to hold the given number of pixels,
+rounded up to the next word boundary.
+@param aPixels Number of pixels
+@param aMode Display mode of pixels
+@return Number of bytes to hold pixels
+*/
+TUint32 CTLowLevel::BytesForPixels(TUint32 aPixels, TDisplayMode aMode)
+ {
+ TUint32 bytes = LongWidth(aPixels, aMode);
+
+ switch (aMode)
+ {
+ case EGray2:
+ bytes /= 8;
+ break;
+ case EGray4:
+ bytes /= 4;
+ break;
+ case EGray16:
+ case EColor16:
+ bytes /= 2;
+ break;
+ case EColor4K:
+ case EColor64K:
+ bytes *= 2;
+ break;
+ case EColor16M:
+ bytes *= 3;
+ break;
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ bytes *= 4;
+ break;
+ }
+ return bytes;
+ }
+
+/**
+Compare the actual blend results with the expected ones, allowing for some
+blending errors. Both buffers must be in aMode format
+@param aActual Start of actual results
+@param aExpected Start of expected results
+@param aWidth Number of pixels to check
+@param aMode Display mode of the pixels in the buffers
+@param aBlended ETrue if pixels were blended, EFalse if they were opaque
+@return ETrue if buffers compared OK, EFalse if there was a mismatch.
+*/
+TBool CTLowLevel::CompareBlendMaskResults(TAny* aActual, TAny* aExpected,
+ TUint32 aWidth, TDisplayMode aMode, TBool aBlended, TDisplayMode aSrcMode)
+ {
+ if (aBlended)
+ {
+ // There can be blending rounding errors, so allow for these. In general
+ // allow for one bit of error, taking into account the precision of
+ // each component.
+ TInt maxRBErr;
+ TInt maxGErr;
+ switch (aMode)
+ {
+ case EColor4K:
+ // All components are four bits
+ maxRBErr = maxGErr = 17;
+ break;
+ case EColor64K:
+ // Six bits for green, five for the others, so error
+ // varies.
+ maxRBErr = 9;
+ maxGErr = 5;
+ break;
+ default:
+ // For 16MAP, it will be dependent on the alpha value.
+ maxRBErr = maxGErr = 1;
+ break;
+ }
+
+ // Compare each pixel, allowing for the error in each component.
+ for (TInt xx = 0; xx < aWidth; xx++)
+ {
+ TRgb exp = ExtractRgbValue(xx, (TUint8*)aExpected, aMode);
+ TRgb act = ExtractRgbValue(xx, (TUint8*)aActual, aMode);
+
+ if (aMode == EColor16MAP)
+ {
+ // Take into account that components have been premultiplied
+ TInt alpha = exp.Alpha();
+ if (alpha > 0)
+ {
+ maxRBErr = maxGErr = (0xFF + alpha - 1) / alpha;
+ }
+ if (aSrcMode == EColor16MA && (maxGErr < 3 || maxRBErr < 3))
+ {
+ maxGErr = 3;
+ maxRBErr = 3;
+ }
+ }
+
+ if (AbsDiff(exp.Red(), act.Red()) > maxRBErr ||
+ AbsDiff(exp.Green(), act.Green()) > maxGErr ||
+ AbsDiff(exp.Blue(), act.Blue()) > maxRBErr ||
+ exp.Alpha() != act.Alpha())
+ {
+ INFO_PRINTF4(_L("At %d, expected 0x%08.8x, got 0x%08.8x"),
+ xx, exp.Internal(), act.Internal());
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+ else
+ {
+ // For non-alpha sources there is no blending, so results
+ // should be exact.
+ TUint32 stride = BytesForPixels(aWidth, aMode);
+ return (Mem::Compare((TUint8*)aActual, stride, (TUint8*)aExpected, stride) == 0);
+ }
+ }
+
+class TFunctionThread
+ {
+protected:
+ TFunctionThread():iExitHow(ENotStarted)
+ {}
+ TInt LaunchThreadFunction(const TDesC& aName);
+private:
+ static TInt TheThreadFunction(TAny*);
+ virtual TInt ThreadFunctionL()=0;
+public:
+ enum {
+ ENotStarted,
+ ERunning, //should never see this
+ EReturn,
+ ELeave,
+ EPanic,
+ ETerminate,
+ };
+ TInt iExitHow;
+ TInt iExitCode; //Currently don't store the panic category string.
+ };
+
+TInt TFunctionThread::LaunchThreadFunction(const TDesC& aName)
+ {
+ RThread thrd;
+ TRequestStatus stat;
+ enum { //8kb to 2mb
+ KMinHeapSize=0x2000,
+ KMaxHeapSize=0x200000
+ };
+ TInt created=thrd.Create(aName,TheThreadFunction,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,this);
+ if (created<KErrNone)
+ {
+ iExitCode=created;
+ return created;
+ }
+ thrd.SetPriority(EPriorityMuchMore);
+ thrd.Logon(stat);
+ User::SetJustInTime(EFalse);
+ thrd.Resume();
+ User::WaitForRequest(stat);
+ if ( iExitHow!=ENotStarted || iExitHow==ERunning )
+ {
+ iExitCode=thrd.ExitReason();
+ switch (thrd.ExitType())
+ {
+ case EExitKill: iExitHow=EReturn; break;
+ case EExitPanic: iExitHow=EPanic; break;
+ case EExitTerminate: iExitHow=ETerminate; break;
+ default:
+ ASSERT(EFalse);
+ }
+ }
+ thrd.Close();
+ User::SetJustInTime(ETrue);
+ return KErrNone;
+ }
+
+TInt TFunctionThread::TheThreadFunction(TAny* aThis)
+ {
+ TFunctionThread* thisThis=(TFunctionThread*)aThis;
+ if (thisThis==NULL)
+ {
+ User::Panic(_L("NoThis"),0x1);
+ }
+ thisThis->iExitHow=thisThis->ERunning;
+ TInt returnErr = KErrNone;
+ TRAPD(leaveErr,returnErr=thisThis->ThreadFunctionL());
+ if (leaveErr)
+ {
+ thisThis->iExitHow=ELeave;
+ thisThis->iExitCode=leaveErr;
+ return leaveErr;
+ }
+ else
+ {
+ thisThis->iExitHow=EReturn;
+ thisThis->iExitCode=returnErr;
+ return returnErr;
+ }
+ }
+
+/** This thread verifies whether a range of memory is accessible
+ The range is read sequentially until it panics, or the range is completed.
+ It is useful to input a range of addresses where some are valid and some fail
+ in order to demonstrate an edge against which an algorithm that performs illegal reads can subsequently be tested.
+ The FailOffset() returned index indicates the offset from the start at which the memory access caused a panic.
+ **/
+class TTestMemThread:public TFunctionThread
+ {
+public:
+ TTestMemThread(TUint32* aStartAddress,TUint32* aEndAddress);
+ TInt FailOffset();
+private:
+ virtual TInt ThreadFunctionL();
+private:
+ TUint32* iStartAddress;
+ TUint32* iEndAddress;
+ volatile TUint32* iLastAddressTried;
+ volatile TUint32 iCopyValueHere;
+
+ };
+
+TTestMemThread::TTestMemThread(TUint32* aStartAddress,TUint32* aEndAddress):
+ iStartAddress(aStartAddress),
+ iEndAddress(aEndAddress),
+ iLastAddressTried(NULL)
+ {
+ ASSERT(aStartAddress);
+ ASSERT(aEndAddress);
+ LaunchThreadFunction(_L("MemTest"));
+ }
+
+/**
+ * Returns the number of successful memory reads before a panic occurred
+ * Or various error codes if the test didn't run or didn't panic.
+ *
+ **/
+TInt TTestMemThread::FailOffset()
+ {
+ if (iExitHow==EReturn)
+ {
+ return KErrCompletion;
+ }
+ else
+ {
+ if (iExitHow==EPanic)
+ {
+ if (iLastAddressTried)
+ {
+ TInt retval=iLastAddressTried-iStartAddress;
+ if (iEndAddress-iStartAddress<0)
+ {
+ retval=-retval;
+ }
+ if (retval<0)
+ {
+ return KErrCorrupt;
+ }
+ else
+ {
+ return retval;
+ }
+ }
+ else
+ {
+ return KErrNotFound;
+ }
+ }
+ else
+ {
+ return KErrGeneral;
+ }
+ }
+ }
+/*
+ * This thread function allows a test to verify that a particular address range
+ * is actually inaccessable.
+ * I.e. that attempting to read from the given address range causes a panic.
+ */
+TInt TTestMemThread::ThreadFunctionL()
+ {
+ if (iStartAddress && iEndAddress)
+ {
+ TInt delta=1;
+ if (iStartAddress>iEndAddress)
+ {
+ delta=-1;
+ }
+ for (TUint32 volatile* tryAddress=iStartAddress;tryAddress!=iEndAddress;tryAddress+=delta)
+ {
+ iLastAddressTried=tryAddress;
+ iCopyValueHere=*tryAddress;
+ }
+ return 0;
+ }
+ return KErrArgument;
+ }
+
+void CTLowLevel::ClosePanicDialogs()
+ {
+ RWsSession session;
+ TInt err = session.Connect();
+ TEST(err == KErrNone);
+ TInt idFocus = session.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))
+ {
+ session.SendEventToAllWindowGroups(event);
+ TInt idNewFocus = session.GetFocusWindowGroup();
+ idFocus=idNewFocus;
+ }
+ session.Flush();
+ session.Close();
+ }
+
+
+/**
+@SYMTestCaseID GRAPHICS-SCREENDRIVER-0003
+@SYMTestCaseDesc Test that FastBlendBitmapMasked masking works correctly
+@SYMDEF INC120146 PDEF120693 PDEF120680 INC120742 PDEF121725
+@SYMTestPriority High
+@SYMTestActions Test actions are:
+ Create pseudorandom initial contents, source and mask lines.
+ Set a line of the screen to the initial contents.
+ Use FastBlendBitmapMasked, with and without inverted bitmask, to write
+ source to target.
+ Read line contents back.
+ Check each pixel is either the initial value, or the source or a blend,
+ depending on corresponding mask pixel.
+ Repeat this whole sequence with supported source display modes.
+ NOTE - wrapped in memory check for edge case defect INC120742
+@SYMTestExpectedResults The correct pixel values are set, based on the mask.
+*/
+void CTLowLevel::TestFastBlendBitmapMasked(const TInt aRetry)
+ {
+ const TInt KRetryAmount = 10;
+
+ TAny* interface = NULL;
+ TInt err = iDrawDevice->GetInterface(KFastBlendInterfaceID, interface);
+ if(err == KErrNone)
+ {
+ if (aRetry == 0)
+ {
+ INFO_PRINTF1(_L("START ---->TestFastBlendBitmapMasked"));
+ }
+
+ MFastBlend* fastBlend = reinterpret_cast<MFastBlend*>(interface);
+ TInt yPos = iSize.iHeight / 2;
+ TPoint pt(0,yPos);
+ TSize lineSize(iSize.iWidth, 1);
+ TRect lineRect(lineSize);
+
+ TInt destStride = iDrawDevice->ScanLineBytes();
+ TInt maskStride = (iSize.iWidth + 7) / 8;
+ TInt maskPages = (maskStride/4096+1);
+ maskPages+=20;
+ // Allocate large enough buffers for all modes
+ TAny* source = User::Alloc(iSize.iWidth * 4);
+ TAny* expected = User::Alloc(destStride);
+ CFbsBitmap testBitmap;
+ testBitmap.Create(TSize(1024,maskPages),EColor16MA);
+ TUint32* mask = testBitmap.DataAddress()+1024-(maskStride%4096)/4;
+ TUint32* slb = iDrawDevice->ScanLineBuffer();
+
+ Check(source != NULL && expected != NULL && mask != NULL);
+
+ TUint32* bitmapData=testBitmap.DataAddress();
+ SEpocBitmapHeader header1 = testBitmap.Header();
+ TUint32* pastBitmapData=bitmapData+((header1.iBitmapSize-header1.iStructSize)>>2);
+ mask = pastBitmapData- (maskStride+3)/4;
+
+ TBool canGenerateDefectScenario = EFalse;
+ TTestMemThread memThread(pastBitmapData-2,pastBitmapData+2);
+ TInt failAt=memThread.FailOffset();
+ if (failAt<0)
+ {
+ INFO_PRINTF2(_L("Error generated by test thread! %i - BAD"),failAt);
+ }
+ else if (failAt<=1)
+ {
+ INFO_PRINTF1(_L("Bitmap memory is inaccessable - BAD"));
+ }
+ else if (failAt>2)
+ {
+ INFO_PRINTF1(_L("Memory after bitmap is accessable - BAD"));
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Memory after bitmap is inaccessable - GOOD"));
+ canGenerateDefectScenario=ETrue;
+ }
+ ClosePanicDialogs();
+
+ if (!canGenerateDefectScenario)
+ {
+ //if this doesn't work out then the memory allocator is not like it was when the defect was raised!
+ //so the test is no longer any good.
+ if (aRetry == KRetryAmount)
+ {
+ INFO_PRINTF2(_L("Failed %d times - Overall test failure"),KRetryAmount);
+ Check(EFalse);
+ }
+ else
+ {
+ INFO_PRINTF2(_L("RETRYING - attempt %d"),aRetry+2);
+ TestFastBlendBitmapMasked(aRetry+1);
+ }
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Performing test"));
+ for (TInt sourceModeIndex = 0; sourceModeIndex < KNumberDisplayModes1; sourceModeIndex++)
+ {
+ for (TInt invert = 0; invert < 2; invert++)
+ {
+ TDisplayMode sourceMode = TestDisplayMode1[sourceModeIndex];
+ TInt sourceStride = BytesForPixels(iSize.iWidth, sourceMode);
+ TBool blended = (sourceMode == EColor16MA || sourceMode == EColor16MAP);
+
+ // Initialise (randomise) the buffers for this iteration
+ FillBuffer((TUint8*)source, sourceStride, sourceMode, ETrue);
+ FillBuffer((TUint8*)expected, destStride, iDispMode, ETrue);
+ FillBuffer((TUint8*)mask, maskStride, EGray2, ETrue);
+
+ // Write out the initial contents
+ iDrawDevice->WriteLine(0, yPos, iSize.iWidth, (TUint32*)expected,
+ CGraphicsContext::EDrawModeWriteAlpha);
+
+ // Fast, masked overwrite, with or without mask inversion
+ TInt result = fastBlend->FastBlendBitmapMasked(pt,
+ (TUint32*)source, sourceStride, lineSize, lineRect,
+ sourceMode, mask, maskStride, EGray2, lineSize,
+ TPoint(), invert, CGraphicsContext::EDrawModePEN,
+ CFbsDrawDevice::ENoShadow);
+
+ if (result == KErrNotSupported)
+ {
+ // Unsupported combination of parameters, move on.
+ continue;
+ }
+
+ // Use mask to blend source with 'expected' to get the expected
+ // output
+ MaskedBlendBuffer(source, sourceMode, expected, iDispMode,
+ mask, iSize.iWidth, invert);
+
+ // Read back actual output and compare with expected.
+ iDrawDevice->ReadLine(0, yPos, iSize.iWidth, slb, iDispMode);
+
+ if (!CompareBlendMaskResults(slb, expected, iSize.iWidth,
+ iDispMode, blended, sourceMode))
+ {
+ INFO_PRINTF3(_L("Output mismatch: source mode %S, invert=%d"),
+ &DisplayModeNames1[sourceModeIndex], invert);
+ // Report other details, plus fail the overall test.
+ Check(EFalse);
+ }
+ iIteration++;
+ }
+
+ }
+ TTestMemThread memThreadAfter(pastBitmapData-2,pastBitmapData+2);
+ failAt=memThreadAfter.FailOffset();
+ if (failAt != 2)
+ {
+ INFO_PRINTF1(_L("Memory after bitmap is accessable - BAD"));
+ if (aRetry >= KRetryAmount)
+ {
+ INFO_PRINTF2(_L("Failed %d times - Overall test failure"),KRetryAmount);
+ Check(EFalse);
+ }
+ else
+ {
+ INFO_PRINTF2(_L("RETRYING - attempt %d"),aRetry+2);
+ TestFastBlendBitmapMasked(aRetry+1);
+ }
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Memory after bitmap is inaccessable - GOOD"));
+ }
+ ClosePanicDialogs();
+ }
+ if (aRetry == 0)
+ {
+ INFO_PRINTF1(_L("END ---->TestFastBlendBitmapMasked"));
+ Report();
+ }
+
+ User::Free(source);
+ User::Free(expected);
+ testBitmap.Reset();
+ }
+ }
+
+void CTLowLevel::TestWriteRGBAlpha()
+ {
+ TUint8* writeBuffer = new TUint8[iSize.iWidth * 4];
+ TUint8* writeBuffer2 = new TUint8[iSize.iWidth * 4];
+ TUint8* maskBuffer = new TUint8[iSize.iWidth];
+ Check(writeBuffer != NULL);
+ Check(maskBuffer != NULL);
+
+ TInt nRect;
+
+ //special test for EColor16MAP
+ if (iDispMode == EColor16MAP)
+ {
+ //mask fill has vaues 0x00, 0xff, and 0x3A. The mask is used for blending
+ for (TInt maskFillCount=0; maskFillCount<KMaskFill;maskFillCount++)
+ {
+ for (TInt userDispMode=0; userDispMode< KUserDispModes; userDispMode++)
+ {
+ for (TInt shadowMode = 0; shadowMode < KNumShadowModes; shadowMode++)
+ {
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ for (TInt nColor = 0; nColor < KNumTestColors; nColor++)
+ {
+ iDrawDevice->SetUserDisplayMode(UserDisplayModes[userDispMode]);
+ iUserDispMode = UserDisplayModes[userDispMode];
+ if (iUserDispMode == EColor16MA)
+ i16MAUserDispMode = ETrue;
+ else
+ i16MAUserDispMode = EFalse;
+
+ TRgb col = TestColor[nColor];
+ TUint32 internal = col.Internal();
+ TUint32 *writeBuf32 = (TUint32*)writeBuffer;
+ TInt cnt;
+ //fill the buffer with colour
+ for (cnt=0;cnt<iSize.iWidth;cnt++)
+ {
+ *writeBuf32=internal;
+ writeBuf32++;
+ }
+
+ Mem::Fill(maskBuffer,iSize.iWidth,MaskFill[maskFillCount]);
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+
+ iDrawDevice->CFbsDrawDevice::SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->CFbsDrawDevice::SetFadingParameters(100,200);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+
+ TInt yy;
+ for (yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),writeBuffer,maskBuffer,CGraphicsContext::EDrawModePEN);
+ iIteration++;
+ }
+
+ //ensure the colour has the 0xff mask value
+ TRgb checkColor;
+ //use a combined alpha for the check colour
+ TUint32 combinedAlpha = MaskFill[maskFillCount]*((internal&0xff000000)>>24);
+ combinedAlpha = ((combinedAlpha <<16) & 0xff000000);
+ checkColor.SetInternal((internal&0x00ffffff)|combinedAlpha);
+ //check colour is not a PMA colour, but has alpha
+ CheckRgb(rect,checkColor,bakCol,CGraphicsContext::EDrawModePEN,CFbsDrawDevice::TShadowMode(shadowMode));
+ CheckBackground(rect,bakCol);
+
+ //the other WriteRgbAlpha line uses the other shadow mode
+ TUint32 *writeBuf2 = (TUint32*)writeBuffer2;
+ TUint32 buf2val= NonPMA2PMAPixel(bakCol.Internal());
+ //fill the buffer with colour
+ for (cnt=0;cnt<iSize.iWidth;cnt++)
+ {
+ *writeBuf2=buf2val;
+ writeBuf2++;
+ }
+
+ iDrawDevice->CFbsDrawDevice::SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->CFbsDrawDevice::SetFadingParameters(100,200);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+
+ for (yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),
+ writeBuffer,
+ writeBuffer2,
+ maskBuffer,
+ CGraphicsContext::EDrawModeWriteAlpha);
+ iIteration++;
+ }
+ //require to Shadow After the checkColor, no shadow with a zero mask
+ TBool shadowModeChanged = EFalse;
+ if (MaskFill[maskFillCount])
+ {
+ iPostBlendShadow = (TPostShadowMode) shadowMode;
+ shadowMode = 0;
+ shadowModeChanged = ETrue;
+ }
+ CheckRgb(rect,checkColor,bakCol,CGraphicsContext::EDrawModePEN,shadowMode);
+ if(shadowModeChanged) shadowMode = iPostBlendShadow;
+ iPostBlendShadow = ENoPostShadow;
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+
+ iDrawDevice->CFbsDrawDevice::SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->CFbsDrawDevice::SetFadingParameters(100,200);
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),col,maskBuffer);
+ iIteration++;
+ }
+
+ CheckRgb(rect,checkColor,bakCol,CGraphicsContext::EDrawModePEN,CFbsDrawDevice::TShadowMode(shadowMode));
+ CheckBackground(rect,bakCol);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Report();
+ iDrawDevice->SetUserDisplayMode(iDispMode);
+ i16MAUserDispMode = EFalse;
+ iUserDispMode = ENone;
+ Mem::Fill(writeBuffer,iSize.iWidth * 4,0xff);
+ Mem::Fill(maskBuffer,iSize.iWidth,0xff);
+
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ if ((nBackColor>=KMaxNon16BackColours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),writeBuffer,maskBuffer,CGraphicsContext::EDrawModePEN);
+ iIteration++;
+ }
+
+ CheckRgb(rect,KRgbWhite,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),KRgbWhite,maskBuffer);
+ iIteration++;
+ }
+
+ CheckRgb(rect,KRgbWhite,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ }
+ }
+ Report();
+
+ Mem::FillZ(writeBuffer,iSize.iWidth * 3);
+
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ if ((nBackColor>=KMaxNon16BackColours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ //need to fill with 0xff alpha, so blending takes place
+ if (iDispMode== EColor16MAP)
+ {
+ const TUint32 black = 0xff000000;
+ TUint32 *writeBuf32 = (TUint32*) writeBuffer;
+ for (TInt cnt=0;cnt<iSize.iWidth;cnt++)
+ {
+ *writeBuf32=black;
+ writeBuf32++;
+ }
+ }
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),writeBuffer,maskBuffer,CGraphicsContext::EDrawModePEN);
+ iIteration++;
+ }
+
+ CheckRgb(rect,KRgbBlack,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),KRgbBlack,maskBuffer);
+ iIteration++;
+ }
+
+ CheckRgb(rect,KRgbBlack,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+ }
+ }
+ Report();
+
+ Mem::FillZ(maskBuffer,iSize.iWidth);
+
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ if ((nBackColor>=KMaxNon16BackColours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),writeBuffer,maskBuffer,CGraphicsContext::EDrawModePEN);
+ iIteration++;
+ }
+
+ TRgb checkColor2=bakCol;
+ if (iDispMode == EColor16MAP)
+ checkColor2.SetInternal (0);
+
+ CheckRgb(rect,checkColor2,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),KRgbBlack,maskBuffer);
+ iIteration++;
+ }
+
+ CheckRgb(rect,checkColor2,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ }
+ }
+ Report();
+
+ Mem::Fill(writeBuffer,iSize.iWidth * 3,0xff);
+
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ if ((nBackColor>=KMaxNon16BackColours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect = TestRect[nRect];
+
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ iDrawDevice->WriteRgbAlphaLine(rect.iTl.iX,yy,rect.Width(),writeBuffer,maskBuffer,CGraphicsContext::EDrawModePEN);
+ iIteration++;
+ }
+ TRgb checkColor3=bakCol;
+ if (iDispMode == EColor16MAP)
+ checkColor3.SetInternal (0xffffff);
+
+ CheckRgb(rect,checkColor3,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+
+ Clear(bakCol);
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),KRgbWhite,maskBuffer);
+ iIteration++;
+ }
+
+ CheckRgb(rect,checkColor3,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+ }
+ }
+ Report();
+
+ //Extra test for DEF082251
+ if (iDispMode==EColor16MU)
+ {
+ Mem::Fill(maskBuffer,iSize.iWidth,0x7f);
+
+ for (nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nBackColor = 0; nBackColor < KNumTestBackgrounds; nBackColor++)
+ {
+ TRgb bakCol = TestBackground[nBackColor];
+ Clear(bakCol);
+ TRect rect=TestRect[nRect];
+
+ const TInt red = 50;
+ const TInt green = 60;
+ const TInt blue = 70;
+ const TInt alpha = 80;
+
+ for (TInt yy2 = rect.iTl.iY; yy2 < rect.iBr.iY; yy2++)
+ {
+ iDrawDevice->WriteRgbAlphaMulti(rect.iTl.iX,yy2,rect.Width(),
+ TRgb(red,green,blue,alpha),maskBuffer);
+ iIteration++;
+ }
+
+ //work out the color - based on OptimizedBlend32 in the
+ //screendriver bmdraw32.cpp
+ TInt combinedAlpha = (alpha * 0x7f)>>8;
+
+ const TUint32 alphaValue = (combinedAlpha << 8) + combinedAlpha;
+ TUint32 secondary= bakCol.Value();
+
+ const TInt r2 = secondary & 0x000000ff;
+ const TInt g2 = (secondary & 0x0000ff00) >> 8;
+ const TInt b2 = (secondary & 0x00ff0000) >> 16;
+
+ const TInt r3 = ((alphaValue * (red - r2)) >> 16) + r2;
+ const TInt g3 = ((alphaValue * (green - g2)) >> 16) + g2;
+ const TInt b3 = ((alphaValue * (blue - b2)) >> 16) + b2;
+
+ TInt result= (b3 & 0xFF) | ((g3<<8) & 0xFF00) | ((r3<<16) & 0xFF0000) | 0xFF000000;
+ TRgb resultColor = TRgb(result,0);
+
+ CheckRgb(rect,resultColor,bakCol,CGraphicsContext::EDrawModePEN,0);
+ CheckBackground(rect,bakCol);
+ }
+ }
+ Report();
+ }
+ delete [] writeBuffer;
+ delete [] maskBuffer;
+ delete [] writeBuffer2;
+ }
+
+void CTLowLevel::TestShadow()
+ {
+ for (TInt shadowMode = 0; shadowMode < KNumShadowModes; shadowMode++)
+ {
+ for (TInt nRect = 0; nRect < KNumTestRects; nRect++)
+ {
+ for (TInt nColor = 0; nColor < KNumTestColors; nColor++)
+ {
+ if ((nColor>=KMaxNon16Colours) && (iDispMode!= EColor16MAP))
+ continue;
+
+ TRgb col = TestColor[nColor];
+ Clear(col);
+
+ TRect rect = TestRect[nRect];
+
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::TShadowMode(shadowMode));
+ iDrawDevice->ShadowArea(rect);
+
+ CheckShadowRgb(rect,col,shadowMode);
+
+ TRgb checkColor=col;
+ if (iDispMode == EColor16MAP)
+ {
+ checkColor.SetInternal (0); //only want contribution from one colour
+ }
+
+ TRect outside(0,0,iSize.iWidth,rect.iTl.iY);
+ if (!outside.IsEmpty())
+ CheckRgb(outside,checkColor,col,CGraphicsContext::EDrawModePEN,0);
+ outside.SetRect(0,rect.iBr.iY,iSize.iWidth,iSize.iHeight);
+ if (!outside.IsEmpty())
+ CheckRgb(outside,checkColor,col,CGraphicsContext::EDrawModePEN,0);
+ outside.SetRect(0,rect.iTl.iY,rect.iTl.iX,rect.iBr.iY);
+ if (!outside.IsEmpty())
+ CheckRgb(outside,checkColor,col,CGraphicsContext::EDrawModePEN,0);
+ outside.SetRect(rect.iBr.iX,rect.iTl.iY,iSize.iWidth,rect.iBr.iY);
+ if (!outside.IsEmpty())
+ CheckRgb(outside,checkColor,col,CGraphicsContext::EDrawModePEN,0);
+ iIteration++;
+ }
+ }
+ Report();
+ }
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0002
+
+ @SYMPREQ PREQ1543
+
+ @SYMTestCaseDesc This test code tests WriteRgbOutlineAndShadow() which blends the four colours.
+ Colours used for blending are outline, shadow, foreground and background.
+
+ @SYMTestPriority High
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions It compares the colour written by WriteRgbOutlineAndShadow() with colour
+ calculated using lookup table provided by Monotype.
+ API Calls:
+ CDrawBitmap::GetInterface()
+ MOutlineAndShadowBlend::WriteRgbOutlineAndShadow()
+ CDrawBitmap::ReadLine()
+
+ @SYMTestExpectedResults Test should pass and colour written by WriteRgbOutlineAndShadow should
+ match with the colour calculated through lookup table.
+*/
+void CTLowLevel::TestWriteRgbOutlineAndShadow()
+ {
+ MOutlineAndShadowBlend* outlineAndShadow = NULL;
+ TInt byteSize = ByteSize();
+ TUint8* writeBuffer = new TUint8[iSize.iWidth * sizeof(TRgb)];
+ TUint8* readBuffer = new TUint8[iSize.iWidth * sizeof(TRgb)];
+ TColorConvertor& colorConvertor = ColorConvertor(iDispMode);
+ Check(writeBuffer != NULL);
+ Check(readBuffer != NULL);
+ TInt err = iDrawDevice->GetInterface(KOutlineAndShadowInterfaceID, reinterpret_cast <TAny*&> (outlineAndShadow));
+ Check(err == KErrNone);
+
+ TRect rect = TestRect[0];
+ for (TInt nBlendingColors = 0; nBlendingColors < KNumBlendingColors; nBlendingColors++)
+ {
+ // Select different combinations of colours for testing from the array
+ TRgb outlinePenColor = TestOSFBColorsForBlending[nBlendingColors][0];
+ TRgb shadowColor = TestOSFBColorsForBlending[nBlendingColors][1];
+ TRgb fillColor = TestOSFBColorsForBlending[nBlendingColors][2];
+ TRgb backgroundColor = colorConvertor.Color(colorConvertor.Index(TestOSFBColorsForBlending[nBlendingColors][3]));
+ Clear(backgroundColor);
+ for (TInt yy = rect.iTl.iY; yy < rect.iBr.iY; yy++)
+ {
+ // Run the test for values from 0 to 255 so that it will cover all the entries
+ // of lookup table provided by Monotype
+ for (TInt index = 0; index < 256; index++)
+ {
+ // In case alpha is supported and if alpha value is less than 255 then the colour drawn will be different
+ // than the colour specified as it blends with the existing background pixel colour.
+ TRgb backgroundColorDrawn= iDrawDevice->ReadPixel(rect.iTl.iX, yy);
+
+ // Fill zeroes in the readBuffer so that we can make sure that there is no garbage value.
+ Mem::FillZ(readBuffer, iSize.iWidth * 3);
+
+ // We are writing index in writeBuffer to simulate the buffer provided by rasterizer
+ // This index should be a value between 0-255, It would be corresponding the entries of lookup table
+ Mem::Fill(writeBuffer, iSize.iWidth * 3, index);
+
+ // Below function blends outline, shadow, foreground and background colours, and writes aLength pixels with new colour
+ // starting from aX, aY.
+ err = outlineAndShadow->WriteRgbOutlineAndShadow(rect.iTl.iX, yy , rect.Width(), outlinePenColor.Internal(),
+ shadowColor.Internal(),fillColor.Internal(),writeBuffer);
+ Check(err == KErrNone);
+
+ // Read the whole line which has been written by WriteRgbOutlineAndShadow()
+ iDrawDevice->ReadLine(rect.iTl.iX, yy, rect.Width(), (TUint32*)readBuffer, iDispMode);
+
+ // Check colour of each pixel, it should be same as the colour which is calulated manually in CheckBlendedOutlineAndShadow()
+ TBool result = CheckBlendedOutlineAndShadow(outlinePenColor, shadowColor, fillColor, backgroundColorDrawn, index, rect.Width(), readBuffer);
+ Check(result);
+ if (!result)
+ {
+ Report();
+ delete [] writeBuffer;
+ delete [] readBuffer;
+ return;
+ }
+
+ iIteration++;
+ }
+ }
+ Report();
+ }
+ delete [] writeBuffer;
+ delete [] readBuffer;
+ }
+
+inline TInt CTLowLevel::ByteSize()
+ {
+ return ::ByteSize(iDispMode,iSize.iWidth);
+ }
+
+TInt CTLowLevel::LongWidth(TInt aWidth,TDisplayMode aDispMode)
+ {
+ switch (aDispMode)
+ {
+ case EGray2:
+ return (aWidth + 31) & ~31;
+ case EGray4:
+ return (aWidth + 15) & ~15;
+ case EGray16:
+ case EColor16:
+ return (aWidth + 7) & ~7;
+ case EGray256:
+ case EColor256:
+ return (aWidth + 3) & ~3;
+ case EColor4K:
+ case EColor64K:
+ return (aWidth + 1) & ~1;
+ case EColor16M:
+ return (((aWidth * 3) + 11) / 12) * 4;
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ return aWidth;
+ default:
+ break;
+ };
+ return 0;
+ }
+
+void CTLowLevel::Clear(TRgb aColor)
+ {
+ iDrawDevice->SetShadowMode(CFbsDrawDevice::ENoShadow);
+ iDrawDevice->WriteRgbMulti(0,0,iSize.iWidth,iSize.iHeight,aColor,CGraphicsContext::EDrawModeWriteAlpha);
+ }
+
+/*
+Fill aBuffer with aByteSize random bytes in such a way that the result is a
+valid scan line buffer for a driver of which the display mode is aDispMode.
+If aDispMode is EColor16MU, the alpha bytes will be 0xFF if aNoAlpha16MU is ETrue,
+or random bytes if aNoAlpha16MU is EFalse.
+*/
+void CTLowLevel::FillBuffer(TUint8* aBuffer, TInt aByteSize, TDisplayMode aDispMode, TBool aNoAlpha16MU)
+ {
+ TUint8* bufferLimit = aBuffer + aByteSize;
+ TUint8* buffer=aBuffer;
+
+ TInt64 seed = TInt64(TInt(aBuffer) * aByteSize * aDispMode * User::TickCount());
+
+ if (aDispMode != EColor16MU || !aNoAlpha16MU)
+ {
+ while (aBuffer < bufferLimit)
+ {
+ *aBuffer++ = (TUint8)Math::Rand(seed);
+ }
+ }
+ else
+ {
+ while (aBuffer < bufferLimit)
+ {
+ if (TInt(aBuffer) & 3 == 3)
+ *aBuffer++ = 0xFF;
+ else
+ *aBuffer++ = (TUint8)Math::Rand(seed);
+ }
+ }
+ if (aDispMode == EColor16MU && !aNoAlpha16MU || aDispMode == EColor16MAP)
+ {
+ //need to do the premultiply alpha to ensure that all the colours are valid
+ //in the colour space
+ for (;buffer < (bufferLimit-3);buffer+=4)
+ {
+ TUint alpha=*(buffer+3);
+ *(buffer)=((*(buffer))* alpha)/255; //do a pre multiply alpha operation
+ *(buffer+1)=((*(buffer+1))* alpha)/255;
+ *(buffer+2)=((*(buffer+2))* alpha)/255;
+ }
+ }
+
+ }
+
+void CTLowLevel::CheckBuffer(TUint8* aWriteBuffer,TDisplayMode aWriteDispMode,TUint8* aReadBuffer,TDisplayMode aReadDispMode,TInt aPixelLength)
+ {
+ switch (aWriteDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ if (aReadDispMode == EGray2)
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ else
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EGray16:
+ if (aReadDispMode == EGray2)
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ else if (aReadDispMode == EGray4)
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ else if (aReadDispMode == EColor16)
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ else
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray16);
+ break;
+ case EGray256:
+ switch (aReadDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EGray16:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray16);
+ break;
+ case EGray256:
+ case EColor16M:
+ case ERgb:
+ case EColor16MU:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray256);
+ break;
+ case EColor16:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ break;
+ case EColor256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor256);
+ break;
+ case EColor4K:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor4K);
+ break;
+ case EColor64K:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor64K);
+ break;
+ default:
+ break;
+ }
+ break;
+ case EColor16:
+ switch (aReadDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ case EGray16:
+ case EGray256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EColor16:
+ case EColor256:
+ case EColor4K:
+ case EColor64K:
+ case EColor16M:
+ case ERgb:
+ case EColor16MU:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ break;
+ default:
+ break;
+ }
+ break;
+ case EColor256:
+ switch (aReadDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EGray16:
+ case EGray256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray16);
+ break;
+ case EColor16:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ break;
+ case EColor256:
+ case EColor4K:
+ case EColor64K:
+ case EColor16M:
+ case ERgb:
+ case EColor16MU:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor256);
+ break;
+ default:
+ break;
+ }
+ break;
+ case EColor4K:
+ switch (aReadDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EGray16:
+ case EGray256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray16);
+ break;
+ case EColor16:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ break;
+ case EColor256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor256);
+ break;
+ case EColor4K:
+ case EColor64K:
+ case EColor16M:
+ case ERgb:
+ case EColor16MU:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor4K);
+ break;
+ default:
+ break;
+ }
+ break;
+ case EColor64K:
+ switch (aReadDispMode)
+ {
+ case EGray2:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray2);
+ break;
+ case EGray4:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray4);
+ break;
+ case EGray16:
+ case EGray256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EGray16);
+ break;
+ case EColor16:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor16);
+ break;
+ case EColor256:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor256);
+ break;
+ case EColor4K:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor4K);
+ break;
+ case EColor64K:
+ case EColor16M:
+ case ERgb:
+ case EColor16MU:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,EColor64K);
+ break;
+ default:
+ break;
+ }
+ break;
+ case EColor16M:
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ CheckPixel(aWriteBuffer,aWriteDispMode,aReadBuffer,aReadDispMode,aPixelLength,aReadDispMode);
+ break;
+ default:
+ break;
+ };
+ }
+
+void CTLowLevel::CheckPixel(TUint8* aWriteBuffer,TDisplayMode aWriteDispMode,TUint8* aReadBuffer,TDisplayMode aReadDispMode,TInt aPixelLength,TDisplayMode aCompareDispMode)
+ {
+ TColorConvertor& colorConvertor = ColorConvertor(aCompareDispMode);
+
+ for (TInt count = 0; count < aPixelLength; count++)
+ {
+ TRgb writeValue = ExtractRgbValue(count,aWriteBuffer,aWriteDispMode);
+ TRgb readValue = ExtractRgbValue(count,aReadBuffer,aReadDispMode);
+ CheckMatch(colorConvertor.Index(writeValue),colorConvertor.Index(readValue));
+ }
+ }
+
+void CTLowLevel::CheckRgb(const TPoint& aPoint,TRgb aColor,TRgb aBackgroundColor,CGraphicsContext::TDrawMode aDrawMode,TInt aShadowMode)
+ {
+ TRect rect(aPoint,TSize(1,1));
+ iDrawDevice->CFbsDrawDevice::SetDitherOrigin(aPoint);
+ CheckRgb(rect,aColor,aBackgroundColor,aDrawMode,aShadowMode);
+ }
+
+void CTLowLevel::CheckRgb(const TRect& aRect,TRgb aColor,TRgb aBackgroundColor,CGraphicsContext::TDrawMode aDrawMode,TInt aShadowMode)
+ {
+ Shadow(aColor,aShadowMode);
+
+ if (aDrawMode == CGraphicsContext::EDrawModeNOTPEN)
+ aColor = ~aColor;
+
+ TRgb foreColor[4];
+ Normalize(aColor,foreColor);
+
+ TRgb backColor[4];
+ Normalize(aBackgroundColor,backColor);
+
+ TRgb fore11 = foreColor[0];
+ TRgb fore21 = foreColor[1];
+ TRgb back11 = backColor[0];
+ TRgb back21 = backColor[1];
+ TRgb fore12 = foreColor[2];
+ TRgb fore22 = foreColor[3];
+ TRgb back12 = backColor[2];
+ TRgb back22 = backColor[3];
+
+ TInt startY = aRect.iTl.iY;
+ TInt endY = aRect.iBr.iY - 1;
+
+ if (startY & 1)
+ {
+ CheckScanline(aRect.iTl.iX,startY,aRect.Width(),fore12,fore22,back12,back22,aDrawMode);
+ startY++;
+ }
+
+ for (TInt yy = startY; yy < endY; yy += 2)
+ {
+ CheckScanline(aRect.iTl.iX,yy,aRect.Width(),fore11,fore21,back11,back21,aDrawMode);
+ CheckScanline(aRect.iTl.iX,yy + 1,aRect.Width(),fore12,fore22,back12,back22,aDrawMode);
+ }
+
+ if (aRect.iBr.iY & 1)
+ {
+ CheckScanline(aRect.iTl.iX,endY,aRect.Width(),fore11,fore21,back11,back21,aDrawMode);
+ }
+ }
+
+void CTLowLevel::CheckShadowRgb(const TRect& aRect,TRgb aColor,TInt aShadowMode)
+ {
+ TRgb foreColor[4];
+ Normalize(aColor,foreColor);
+
+ TRgb fore11 = foreColor[0];
+ TRgb fore21 = foreColor[1];
+ TRgb fore12 = foreColor[2];
+ TRgb fore22 = foreColor[3];
+
+ Shadow(fore11,aShadowMode & 2);
+ Shadow(fore21,aShadowMode & 2);
+ Shadow(fore12,aShadowMode & 2);
+ Shadow(fore22,aShadowMode & 2);
+
+ Normalize(fore11);
+ Normalize(fore21);
+ Normalize(fore12);
+ Normalize(fore22);
+
+ Shadow(fore11,aShadowMode & 1);
+ Shadow(fore21,aShadowMode & 1);
+ Shadow(fore12,aShadowMode & 1);
+ Shadow(fore22,aShadowMode & 1);
+
+ Normalize(fore11);
+ Normalize(fore21);
+ Normalize(fore12);
+ Normalize(fore22);
+
+ TInt startY = aRect.iTl.iY;
+ TInt endY = aRect.iBr.iY - 1;
+
+ iDrawDevice->CFbsDrawDevice::ShadowArea(aRect);
+
+ if (iDispMode== EColor16MAP)
+ {
+ //No dithering, no blending, just checking for a solid colour
+ fore12.SetAlpha(0);//do not want any blending to take place
+ fore22.SetAlpha(0);//do not want any blending to take place
+ for (TInt yy = startY; yy < endY; yy ++)
+ {
+ CheckScanline(aRect.iTl.iX,yy,aRect.Width(),fore11,fore11,fore22,fore22,CGraphicsContext::EDrawModePEN);
+ }
+ return;
+ }
+
+ if (startY & 1)
+ {
+ CheckScanline(aRect.iTl.iX,startY,aRect.Width(),fore12,fore22,fore12,fore22,CGraphicsContext::EDrawModePEN);
+ startY++;
+ }
+
+ for (TInt yy = startY; yy < endY; yy += 2)
+ {
+ CheckScanline(aRect.iTl.iX,yy,aRect.Width(),fore11,fore21,fore11,fore21,CGraphicsContext::EDrawModePEN);
+ CheckScanline(aRect.iTl.iX,yy + 1,aRect.Width(),fore12,fore22,fore12,fore22,CGraphicsContext::EDrawModePEN);
+ }
+
+ if (aRect.iBr.iY & 1)
+ {
+ CheckScanline(aRect.iTl.iX,endY,aRect.Width(),fore11,fore21,fore11,fore21,CGraphicsContext::EDrawModePEN);
+ }
+ }
+
+void CTLowLevel::CheckScanline(TInt aX,TInt aY,TInt aLength,TRgb aFore1,TRgb aFore2,TRgb aBack1,TRgb aBack2,CGraphicsContext::TDrawMode aDrawMode)
+ {
+ iDrawDevice->ReadLine(aX,aY,aLength,iDrawDevice->ScanLineBuffer(),iDispMode);
+
+ TUint32 binaryPixel1 = BinaryValue(aFore1,aBack1,aDrawMode);
+ TUint32 binaryPixel2 = BinaryValue(aFore2,aBack2,aDrawMode);
+ if (aX & 1)
+ {
+ TUint32 spare = binaryPixel1;
+ binaryPixel1 = binaryPixel2;
+ binaryPixel2 = spare;
+ }
+
+ TInt extra = aLength & 1;
+ aLength &= ~1;
+ TInt x = 0;
+
+ if (iPostBlendShadow)
+ {
+ PostBlendShadow(binaryPixel1);
+ PostBlendShadow(binaryPixel2);
+ }
+ if (i16MAUserDispMode)
+ {
+ binaryPixel1 = PMA2NonPMAPixel(binaryPixel1,PtrTo16BitNormalisationTable());
+ binaryPixel2 = PMA2NonPMAPixel(binaryPixel1,PtrTo16BitNormalisationTable());
+ }
+ while (x < aLength)
+ {
+ TUint32 binaryValue = ExtractBinaryValue(x,iDrawDevice->ScanLineBuffer(),iDispMode);
+ CheckMatch(binaryPixel1,binaryValue);
+ x++;
+
+ binaryValue = ExtractBinaryValue(x,iDrawDevice->ScanLineBuffer(),iDispMode);
+ CheckMatch(binaryPixel2,binaryValue);
+ x++;
+ }
+ if (extra)
+ {
+ TUint32 binaryValue = ExtractBinaryValue(x,iDrawDevice->ScanLineBuffer(),iDispMode);
+ CheckMatch(binaryPixel1,binaryValue);
+ }
+ }
+
+void CTLowLevel::CheckLine(TUint8* aWriteBuffer,TUint8* aReadBuffer,TUint8* aBackBuffer,TInt aPixelLength,CGraphicsContext::TDrawMode aDrawMode,TDisplayMode aDispMode)
+ {
+ TInt wholeBytes = 0;
+ TInt extraBits = 0;
+
+ switch (aDispMode)
+ {
+ case EGray2:
+ wholeBytes = aPixelLength / 8;
+ extraBits = aPixelLength & 7;
+ break;
+ case EGray4:
+ wholeBytes = aPixelLength / 4;
+ extraBits = (aPixelLength & 3) * 2;
+ break;
+ case EGray16:
+ case EColor16:
+ wholeBytes = aPixelLength / 2;
+ extraBits = (aPixelLength & 1) * 4;
+ break;
+ case EGray256:
+ case EColor256:
+ wholeBytes = aPixelLength;
+ break;
+ case EColor4K:
+ case EColor64K:
+ wholeBytes = aPixelLength * 2;
+ break;
+ case EColor16M:
+ wholeBytes = aPixelLength * 3;
+ break;
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ wholeBytes = aPixelLength * 4;
+ break;
+ default:
+ break;
+ };
+
+ TUint8* readLimit = aReadBuffer + wholeBytes;
+ TUint8 mask = TUint8(0xff >> (8 - extraBits));
+ TInt byteCounter = 0;
+
+ switch (aDrawMode)
+ {
+ case CGraphicsContext::EDrawModeAND:
+ if (iDispMode==EColor16MAP)
+ break; //logical opeations not supported for premultiplied alpha
+ for (; aReadBuffer < readLimit; aReadBuffer++, aWriteBuffer++, aBackBuffer++)
+ {
+ if(!((aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP)
+ && ++byteCounter % 4 == 0))
+ Check(*aReadBuffer == (*aWriteBuffer & *aBackBuffer));
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == (*aWriteBuffer & *aBackBuffer & mask));
+ break;
+ case CGraphicsContext::EDrawModePEN:
+ if(aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP)
+ {
+ for (; aReadBuffer<readLimit; aReadBuffer+=4, aWriteBuffer+=4)
+ {
+ TBool fail=EFalse;
+ Blend(aWriteBuffer,aBackBuffer,aDispMode);
+ if (!iFuzzyMatch)
+ {
+ fail|=Check(AbsDiff(*aReadBuffer,*aWriteBuffer)<2);
+ fail|=Check(AbsDiff(*(aReadBuffer+1),*(aWriteBuffer+1))<2);
+ fail|=Check(AbsDiff(*(aReadBuffer+2),*(aWriteBuffer+2))<2);
+ fail|=Check(AbsDiff(*(aReadBuffer+3),*(aWriteBuffer+3))<2);
+ }
+ else
+ {
+ fail|=Check(AbsDiff(*aReadBuffer,*aWriteBuffer)<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(aReadBuffer+1),*(aWriteBuffer+1))<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(aReadBuffer+2),*(aWriteBuffer+2))<KInaccuracyLimit);
+ fail|=Check(AbsDiff(*(aReadBuffer+3),*(aWriteBuffer+3))<KInaccuracyLimit);
+ }
+ if (fail)
+ {
+ _LIT(KLog,"The values 0x%x and 0x%x don't match, fuzzyMatch=%d (limit=%d), memory 0x%x 0x%x");
+ INFO_PRINTF7(KLog,*reinterpret_cast<TUint*>(aReadBuffer),*reinterpret_cast<TUint*>(aWriteBuffer),iFuzzyMatch,KInaccuracyLimit,aReadBuffer,aWriteBuffer);
+ }
+ }
+ }
+ else
+ {
+ for (; aReadBuffer < readLimit; aReadBuffer++, aWriteBuffer++)
+ {
+ if (Check(*aReadBuffer == *aWriteBuffer))
+ {
+ _LIT(KLog,"The values 0x%x and 0x%x don't match, memory 0x%x 0x%x");
+ INFO_PRINTF5(KLog,*aReadBuffer,*aWriteBuffer,aReadBuffer,aWriteBuffer);
+ }
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == (*aWriteBuffer & mask));
+ }
+ break;
+ case CGraphicsContext::EDrawModeNOTPEN:
+ if (iDispMode==EColor16MAP)
+ break; //logical opeations not supported for premultiplied alpha
+ if(aDispMode == EColor16MU || aDispMode == EColor16MA )
+ {
+ for (; aReadBuffer < readLimit; aReadBuffer +=4, aWriteBuffer+=4)
+ {
+ *aWriteBuffer ^= 0xff;
+ *(aWriteBuffer+1) ^= 0xff;
+ *(aWriteBuffer+2) ^= 0xff;
+
+ Blend(aWriteBuffer,aBackBuffer,aDispMode);
+
+ if (!iFuzzyMatch)
+ {
+ Check(AbsDiff(*aReadBuffer, *aWriteBuffer) < 2);
+ Check(AbsDiff(*(aReadBuffer+1), *(aWriteBuffer+1)) < 2);
+ Check(AbsDiff(*(aReadBuffer+2), *(aWriteBuffer+2)) < 2);
+ Check(AbsDiff(*(aReadBuffer+3), *(aWriteBuffer+3)) < 2);
+ }
+ else
+ {
+ Check(AbsDiff(*aReadBuffer, *aWriteBuffer) < KInaccuracyLimit);
+ Check(AbsDiff(*(aReadBuffer+1), *(aWriteBuffer+1)) < KInaccuracyLimit);
+ Check(AbsDiff(*(aReadBuffer+2), *(aWriteBuffer+2)) < KInaccuracyLimit);
+ Check(AbsDiff(*(aReadBuffer+3), *(aWriteBuffer+3)) < KInaccuracyLimit);
+ }
+ }
+ }
+ else
+ {
+
+ for (; aReadBuffer < readLimit; aReadBuffer++, aWriteBuffer++)
+ {
+ if(!((aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP) && ++byteCounter % 4 == 0))
+ Check(*aReadBuffer == (*aWriteBuffer ^ 0xff));
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == ((*aWriteBuffer ^ 0xff) & mask));
+ }
+ break;
+ case CGraphicsContext::EDrawModeXOR:
+ if (iDispMode==EColor16MAP)
+ break;//logical opeations not supported for premultiplied alpha
+ for (; aReadBuffer < readLimit; aReadBuffer++, aWriteBuffer++, aBackBuffer++)
+ {
+ if(!((aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP) && ++byteCounter % 4 == 0))
+ Check(*aReadBuffer == (*aWriteBuffer ^ *aBackBuffer));
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == ((*aWriteBuffer ^ *aBackBuffer) & mask));
+ break;
+ case CGraphicsContext::EDrawModeOR:
+ if (iDispMode==EColor16MAP)
+ break;//logical opeations not supported for premultiplied alpha
+ for (; aReadBuffer < readLimit; aReadBuffer++, aWriteBuffer++, aBackBuffer++)
+ {
+ if(!((aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP) && ++byteCounter % 4 == 0))
+ Check(*aReadBuffer == (*aWriteBuffer | *aBackBuffer));
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == ((*aWriteBuffer | *aBackBuffer) & mask));
+ break;
+ case CGraphicsContext::EDrawModeNOTSCREEN:
+ if (iDispMode==EColor16MAP)
+ break;//logical opeations not supported for premultiplied alpha
+ if (aDispMode != EColor4K)
+ {
+ for (; aReadBuffer < readLimit; aReadBuffer++, aBackBuffer++)
+ {
+ if(!((aDispMode == EColor16MU || aDispMode == EColor16MA || aDispMode == EColor16MAP) && ++byteCounter % 4 == 0))
+ {
+ if (iFuzzyMatch==EFalse)
+ Check(*aReadBuffer == (*aBackBuffer ^ 0xff));
+ else
+ {
+ TUint8 vals[3];
+ vals[0]=*aReadBuffer;
+ //put in some tolerance values, try with +/- 1, to begin with
+ if (vals[0]<255)
+ vals[1]=vals[0]+1;
+ else
+ vals[1]=vals[0];
+ if (vals[0]>0)
+ vals[2]=vals[0]-1;
+ else
+ vals[2]=vals[0];
+ Check((vals[0] == (*aBackBuffer ^ 0xff))||
+ (vals[1] == (*aBackBuffer ^ 0xff))||
+ (vals[2] == (*aBackBuffer ^ 0xff)));
+ }
+ }
+ }
+ if (extraBits > 0)
+ Check((*aReadBuffer & mask) == ((*aBackBuffer ^ 0xff) & mask));
+ }
+ else
+ {
+ while (aReadBuffer < readLimit)
+ {
+ if (TInt(aReadBuffer) & 1)
+ Check(*aReadBuffer++ == (*aBackBuffer++ ^ 0x0f));
+ else
+ Check(*aReadBuffer++ == (*aBackBuffer++ ^ 0xff));
+ }
+ }
+ break;
+ default:
+ break;
+ };
+ }
+
+void CTLowLevel::CheckBinary(const TRect& aRect,TUint32* aBuffer,TRgb aForeColor,TRgb aBackColor,CGraphicsContext::TDrawMode aDrawMode,TInt aShadowMode,TBool aWrapDataWords,TBool aUp)
+ {
+ Shadow(aForeColor,aShadowMode);
+
+ if (aDrawMode == CGraphicsContext::EDrawModeNOTPEN)
+ aForeColor = ~aForeColor;
+
+ TRgb foreColor[4];
+ Normalize(aForeColor,foreColor);
+
+ TRgb backColor[4];
+ Normalize(aBackColor,backColor);
+
+ foreColor[0] = RgbValue(foreColor[0],backColor[0],aDrawMode);
+ foreColor[1] = RgbValue(foreColor[1],backColor[1],aDrawMode);
+ foreColor[2] = RgbValue(foreColor[2],backColor[2],aDrawMode);
+ foreColor[3] = RgbValue(foreColor[3],backColor[3],aDrawMode);
+
+
+ if (iDispMode==EColor16MAP)
+ {
+ //pre-multiply and unpremultiply
+ TInt count;
+ for (count=0;count<4;count++)
+ {
+ TUint32 tempInt;
+ tempInt = backColor[count].Color16MAP(); //Now premultiplied
+ backColor[count] = TRgb::Color16MAP(tempInt);
+ }
+ }
+
+ TUint32 data = *aBuffer++;
+ TUint32 mask = 1;
+
+ TInt yy = (aUp) ? aRect.iBr.iY - 1 : aRect.iTl.iY;
+ TInt ylimit = (aUp) ? aRect.iTl.iY - 1 : aRect.iBr.iY;
+ TInt yinc = (aUp) ? -1 : 1;
+
+ TRgb pixelBuffer[KCheckBinaryPixelBufferSize];
+ __ASSERT_ALWAYS(aRect.Width() <= KCheckBinaryPixelBufferSize,User::Panic(_L("CheckBinary buffer"),KErrOverflow));
+
+ for (; yy != ylimit; yy += yinc)
+ {
+ TInt yoffset = 2 * (yy & 1);
+
+ iDrawDevice->ReadLine(aRect.iTl.iX,yy,aRect.Width(),pixelBuffer,ERgb);
+ TRgb* color = pixelBuffer;
+
+ for (TInt xx = aRect.iTl.iX; xx < aRect.iBr.iX; xx++)
+ {
+ if (!mask)
+ {
+ mask = 1;
+ data = *aBuffer++;
+ }
+
+ if (data & mask)
+ CheckMatch((*color).Internal(), foreColor[(xx & 1) + yoffset].Internal());
+ else
+ CheckMatch((*color).Internal(), backColor[(xx & 1) + yoffset].Internal());
+
+ color++;
+ mask <<= 1;
+ }
+
+ if (aWrapDataWords)
+ mask = 0;
+ }
+ }
+
+void CTLowLevel::CheckBackground(const TRect& aRect,TRgb aBackgroundColor)
+ {
+ iBlendTestColors= EFalse;
+ if (aRect.iTl.iX > 0)
+ CheckRgb(TRect(aRect.iTl.iX - 1,aRect.iTl.iY,aRect.iTl.iX,aRect.iBr.iY),aBackgroundColor,aBackgroundColor,CGraphicsContext::EDrawModePEN,0);
+ if (aRect.iTl.iY > 0)
+ CheckRgb(TRect(aRect.iTl.iX,aRect.iTl.iY - 1,aRect.iBr.iX,aRect.iTl.iY),aBackgroundColor,aBackgroundColor,CGraphicsContext::EDrawModePEN,0);
+ if (aRect.iBr.iX < iSize.iWidth - 1)
+ CheckRgb(TRect(aRect.iBr.iX,aRect.iTl.iY,aRect.iBr.iX + 1,aRect.iBr.iY),aBackgroundColor,aBackgroundColor,CGraphicsContext::EDrawModePEN,0);
+ if (aRect.iBr.iY < iSize.iHeight - 1)
+ CheckRgb(TRect(aRect.iTl.iX,aRect.iBr.iY,aRect.iBr.iX,aRect.iBr.iY + 1),aBackgroundColor,aBackgroundColor,CGraphicsContext::EDrawModePEN,0);
+ iBlendTestColors= ETrue;
+ }
+/**
+This function is copied as it is from BMDRAW32A.CPP which is used to test WriteRgbOutlineAndShadow for EColor16MA.
+It is used in CTLowLevel::CheckBlendedOutlineAndShadow.
+@param aBeneath The background pixel colour value
+@param aSrcColor The source pixel colour value
+@param aAlpha The alpha value
+*/
+FORCEINLINE TUint32 OptimizedBlend32A(TUint32 aBeneath,TUint32 aSrcColor,TUint8 aAlpha)
+ {
+ if(aAlpha)
+ {
+ if(aAlpha == 0xff) // opaque, so unchanged
+ {
+ //Still need to convert source to destination from non-multiplied to pre-multiplied
+ //But this code resolves to a copy. The ARM optimiser prefers shifts over big constants.
+ return (aSrcColor|(aAlpha<<24));
+ }
+ else
+ {
+ //0, 1, 2, 3
+ //b, g, rect, alpha
+
+ const TUint32 srcMult = aAlpha;
+ TUint32 destMult = ((255 - aAlpha) * ((aBeneath >> 24)));
+ //This gives a slightly more accurate result than ((aBeneath >> 24)+1)
+ destMult=destMult+(destMult>>8);
+ destMult+= 0x0080;
+ destMult >>= 8;
+
+ TUint32 rb =(((aSrcColor&0x00ff00ff)*srcMult)) + (((aBeneath&0x00ff00ff)*destMult));
+ rb = rb+((rb>>8)&0x00ff00ff);
+ rb+=0x00800080;
+ rb>>=8;
+ TUint32 ag = (((aSrcColor&0x0000ff00)*srcMult)) + (((aBeneath&0x0000ff00)*destMult));
+ ag>>=8; //Note that if alpha is processed here, this shift must be performed before the multiplies
+ ag = ag+((ag>>8)&0x00ff00ff);
+ ag+=0x00800080;
+ TUint32 aa = srcMult+destMult;
+ return (rb&0x00ff00ff) | (ag&0x0000ff00) | (aa << 24);
+
+ }
+ }
+ else // completely transparent
+ {
+ return aBeneath;
+ }
+
+ }
+
+/**
+Helper function for TestWriteRgbOutlineAndShadow(). Creates the final colour, blending the outline, shadow,
+fill and background colour using lookup table provided by Monotype and compares with the
+pixel colour drawn using WriteRgbOutlineAndShadow.
+
+@param aOutlinePenColor Colour used for drawing outline of font
+@param aShadowColor Colour used for drawing shadow of font
+@param aFillColor Colour used for filling of font
+@param aBackgroundColor Background colour of the pixel
+@param aLookupIndex Index of the lookup table to be used for generating final colour
+@param aLength Number of pixels to compare the pixel colour with the generated colour
+@param aReadBuffer Buffer containing the colours drawn using WriteRgbOutlineAndShadow.This will be used for comparing
+@return EFalse if pixel colour doesnt match with the calculated colour, otherwise ETrue on success.
+*/
+TBool CTLowLevel::CheckBlendedOutlineAndShadow(TRgb aOutlinePenColor, TRgb aShadowColor, TRgb aFillColor,
+ TRgb aBackgroundColor, TInt aLookupIndex, TInt aLength, TUint8* aReadBuffer)
+ {
+ TRgb finalColor;
+ TInt alpha = aOutlinePenColor.Internal() >> 24;
+
+ if (255 == FourColorBlendLookup[aLookupIndex][3])
+ {
+ //background colour
+ finalColor.SetInternal(aBackgroundColor.Internal());
+
+ /*Reset the alpha with background colour alpha as in product code in case of 255 == FourColorBlendLookup[aLookupIndex][3]
+ it doesnt draw and leaves the background colour as it is. So the alpha to be checked should be of background colour alpha*/
+ alpha = aBackgroundColor.Alpha();
+ }
+ else if (255 == FourColorBlendLookup[aLookupIndex][2])
+ {
+ //fill colour
+ finalColor.SetInternal(aFillColor.Internal());
+ }
+ else if (255 == FourColorBlendLookup[aLookupIndex][1])
+ {
+ //Shadow colour
+ finalColor.SetInternal(aShadowColor.Internal());
+ }
+ else if (255 == FourColorBlendLookup[aLookupIndex][0])
+ {
+ //Outline colour
+ finalColor.SetInternal(aOutlinePenColor.Internal());
+ }
+ else
+ {
+ TInt blendedRedColor = (aOutlinePenColor.Red() * FourColorBlendLookup[aLookupIndex][0] +
+ aShadowColor.Red() * FourColorBlendLookup[aLookupIndex][1] +
+ aFillColor.Red() * FourColorBlendLookup[aLookupIndex][2] +
+ aBackgroundColor.Red() * FourColorBlendLookup[aLookupIndex][3]) >> 8;
+
+ TInt blendedGreenColor = (aOutlinePenColor.Green() * FourColorBlendLookup[aLookupIndex][0] +
+ aShadowColor.Green() * FourColorBlendLookup[aLookupIndex][1] +
+ aFillColor.Green() * FourColorBlendLookup[aLookupIndex][2] +
+ aBackgroundColor.Green() * FourColorBlendLookup[aLookupIndex][3]) >> 8;
+
+ TInt blendedBlueColor = (aOutlinePenColor.Blue() * FourColorBlendLookup[aLookupIndex][0] +
+ aShadowColor.Blue() * FourColorBlendLookup[aLookupIndex][1] +
+ aFillColor.Blue() * FourColorBlendLookup[aLookupIndex][2] +
+ aBackgroundColor.Blue() * FourColorBlendLookup[aLookupIndex][3]) >> 8;
+
+ finalColor = TRgb(blendedRedColor, blendedGreenColor, blendedBlueColor);
+ }
+
+ //Set the alpha in the final colour
+ finalColor.SetAlpha(alpha);
+
+ //Alpha blending is not supported for display modes below EColor64K.
+ switch(iDispMode)
+ {
+ case EColor64K:
+ case EColor16M:
+ case EColor16MU:
+ if (alpha != 0xff)
+ {
+ finalColor = AlphaBlend(finalColor.Red(), finalColor.Green(), finalColor.Blue(), aBackgroundColor.Red(), aBackgroundColor.Green(), aBackgroundColor.Blue(), alpha);
+ }
+ break;
+ case EColor16MA:
+ //Just use the background color to draw in case 255 == FourColorBlendLookup[aLookupIndex][3]
+ if (255 != FourColorBlendLookup[aLookupIndex][3])
+ {
+ finalColor.SetInternal(OptimizedBlend32A(aBackgroundColor.Internal(), finalColor.Internal(), alpha));
+ }
+ break;
+ case EColor16MAP:
+ //Just use the background color to draw in case 255 == FourColorBlendLookup[aLookupIndex][3]
+ if (255 != FourColorBlendLookup[aLookupIndex][3])
+ {
+ TUint32 color16MAP = finalColor.Internal();
+ Convert2PMA(color16MAP);
+ finalColor.SetInternal(PMAPixelBlend(aBackgroundColor.Internal(), color16MAP));
+ }
+ break;
+ };
+
+ Normalize(finalColor);
+ TColorConvertor& colorConvertor = ColorConvertor(iDispMode);
+ // Check each pixel of the line, it should match with the calculated blended color.
+ for (TInt count = 0; count < aLength; count++)
+ {
+ TRgb readValue = ExtractRgbValue(count, aReadBuffer, iDispMode);
+ if (colorConvertor.Index(finalColor) != colorConvertor.Index(readValue))
+ {
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+
+TRgb CTLowLevel::RgbValue(TRgb aFore,TRgb aBack,CGraphicsContext::TDrawMode aDrawMode)
+ {
+ TUint32 value = BinaryValue(aFore,aBack,aDrawMode);
+
+ switch (iDispMode)
+ {
+ case EGray2:
+ return TRgb::Gray2(value);
+ case EGray4:
+ return TRgb::Gray4(value);
+ case EGray16:
+ return TRgb::Gray16(value);
+ case EGray256:
+ return TRgb::Gray256(value);
+ case EColor16:
+ return TRgb::Color16(value);
+ case EColor256:
+ return TRgb::Color256(value);
+ case EColor4K:
+ return TRgb::Color4K(value);
+ case EColor64K:
+ return TRgb::Color64K(value);
+ case EColor16M:
+ return TRgb::Color16M(value);
+ case EColor16MU:
+ return TRgb::Color16MU(value);
+ case EColor16MA:
+ return TRgb::Color16MA(value);
+ case EColor16MAP:
+ return TRgb::Color16MAP(value);
+ default:
+ break;
+ };
+ return KRgbBlack;
+ }
+
+TUint32 CTLowLevel::BinaryValue(TRgb aFore,TRgb aBack,CGraphicsContext::TDrawMode aDrawMode)
+ {
+ TUint32 f = 0;
+ TUint32 b = 0;
+ TUint32 notVal = 0;
+
+ switch (iDispMode)
+ {
+ case EGray2:
+ f = aFore.Gray2();
+ b = aBack.Gray2();
+ notVal = 1;
+ break;
+ case EGray4:
+ f = aFore.Gray4();
+ b = aBack.Gray4();
+ notVal = 3;
+ break;
+ case EGray16:
+ f = aFore.Gray16();
+ b = aBack.Gray16();
+ notVal = 0xf;
+ break;
+ case EGray256:
+ f = aFore.Gray256();
+ b = aBack.Gray256();
+ notVal = 0xff;
+ break;
+ case EColor16:
+ f = aFore.Color16();
+ b = aBack.Color16();
+ notVal = 0xf;
+ break;
+ case EColor256:
+ f = aFore.Color256();
+ b = aBack.Color256();
+ notVal = 0xff;
+ break;
+ case EColor4K:
+ f = aFore.Color4K();
+ b = aBack.Color4K();
+ notVal = 0xfff;
+ break;
+ case EColor64K:
+ f = aFore.Color64K();
+ b = aBack.Color64K();
+ notVal = 0xffff;
+ break;
+ case EColor16M:
+ f = aFore.Color16M();
+ b = aBack.Color16M();
+ notVal = 0xffffff;
+ break;
+ case EColor16MU:
+ f = aFore.Color16MU();
+ b = aBack.Color16MU();
+ notVal = 0x00ffffff;
+ break;
+ case EColor16MA:
+ f = aFore.Color16MA();
+ b = aBack.Color16MA();
+ notVal = 0xffffffff;
+ break;
+ case EColor16MAP:
+ f = aFore.Color16MAP();
+ b = aBack.Color16MAP();
+
+ //do not want to blend backgound colours for testing
+ if (iBlendTestColors && (aDrawMode&CGraphicsContext::EDrawModePEN))
+ {
+ Blend((TUint8*)(&f),(TUint8*)(&b),iDispMode);
+ }
+ notVal = 0xffffffff;
+ break;
+ default:
+ break;
+ };
+
+ switch (aDrawMode)
+ {
+ case CGraphicsContext::EDrawModeAND: return f & b;
+ case CGraphicsContext::EDrawModePEN: return f;
+ case CGraphicsContext::EDrawModeWriteAlpha: return f;
+ case CGraphicsContext::EDrawModeXOR: return f ^ b;
+ case CGraphicsContext::EDrawModeOR: return f | b;
+ case CGraphicsContext::EDrawModeNOTSCREEN: return b ^ notVal;
+ case CGraphicsContext::EDrawModeNOTPEN: return f;
+ default:
+ break;
+ };
+ return 0;
+ }
+
+TRgb CTLowLevel::ExtractRgbValue(TInt aX,TUint8* aBuffer,TDisplayMode aDispMode)
+ {
+ TUint32 value = ExtractBinaryValue(aX,(TUint32*)aBuffer,aDispMode);
+
+ switch (aDispMode)
+ {
+ case EGray2:
+ return TRgb::Gray2(value);
+ case EGray4:
+ return TRgb::Gray4(value);
+ case EGray16:
+ return TRgb::Gray16(value);
+ case EGray256:
+ return TRgb::Gray256(value);
+ case EColor16:
+ return TRgb::Color16(value);
+ case EColor256:
+ return TRgb::Color256(value);
+ case EColor4K:
+ return TRgb::Color4K(value);
+ case EColor64K:
+ return TRgb::Color64K(value);
+ case EColor16M:
+ return TRgb::Color16M(value);
+ case ERgb:
+ return TRgb(value, value>>24);
+ case EColor16MU:
+ return TRgb::Color16MU(value);
+ case EColor16MA:
+ return TRgb::Color16MA(value);
+ case EColor16MAP:
+ return TRgb::Color16MAP(value);
+ default:
+ break;
+ };
+ return KRgbBlack;
+ }
+
+TUint32 CTLowLevel::ExtractBinaryValue(TInt aX,TUint32* aBuffer,TDisplayMode aDispMode)
+ {
+ switch (aDispMode)
+ {
+ case EGray2:
+ return ((*(aBuffer + (aX >> 5))) >> (aX & 0x1f)) & 1;
+ case EGray4:
+ return ((*(aBuffer + (aX >> 4))) >> ((aX & 0xf) * 2)) & 3;
+ case EGray16:
+ case EColor16:
+ return ((*(aBuffer + (aX >> 3))) >> ((aX & 7) * 4)) & 0xf;
+ case EGray256:
+ case EColor256:
+ return ((*(aBuffer + (aX >> 2))) >> ((aX & 3) * 8)) & 0xff;
+ case EColor4K:
+ return ((*(aBuffer + (aX >> 1))) >> ((aX & 1) * 16)) & 0xfff;
+ case EColor64K:
+ return ((*(aBuffer + (aX >> 1))) >> ((aX & 1) * 16)) & 0xffff;
+ case EColor16M:
+ {
+ TUint8* buffer = ((TUint8*)aBuffer) + (aX * 3);
+ return *buffer | (*(buffer + 1) << 8) | (*(buffer + 2) << 16);
+ }
+ case ERgb:
+ return *(aBuffer + aX);
+ case EColor16MU:
+ return *(aBuffer + aX) & 0x00FFFFFF;
+ case EColor16MA:
+ case EColor16MAP:
+ return *(aBuffer + aX);
+ default:
+ break;
+ };
+ return 0;
+ }
+
+void CTLowLevel::Normalize(TRgb& aColor)
+ {
+ return(Normalize(aColor,iDispMode));
+ }
+
+void CTLowLevel::Normalize(TRgb& aColor, TDisplayMode aDispMode)
+ {
+ switch (aDispMode)
+ {
+ case EGray2:
+ aColor = TRgb::Gray2(aColor.Gray2());
+ break;
+ case EGray4:
+ aColor = TRgb::Gray4(aColor.Gray4());
+ break;
+ case EGray16:
+ aColor = TRgb::Gray16(aColor.Gray16());
+ break;
+ case EGray256:
+ aColor = TRgb::Gray256(aColor.Gray256());
+ break;
+ case EColor16:
+ aColor = TRgb::Color16(aColor.Color16());
+ break;
+ case EColor256:
+ aColor = TRgb::Color256(aColor.Color256());
+ break;
+ case EColor4K:
+ aColor = TRgb::Color4K(aColor.Color4K());
+ break;
+ case EColor64K:
+ aColor = TRgb::Color64K(aColor.Color64K());
+ break;
+ case EColor16M:
+ aColor = TRgb::Color16M(aColor.Color16M());
+ break;
+ case EColor16MU:
+ aColor = TRgb::Color16MU(aColor.Color16MU());
+ break;
+ case EColor16MA:
+ aColor = TRgb::Color16MA(aColor.Color16MA());
+ break;
+ case EColor16MAP:
+ //do nothing, because TRGb is already unpremultiplied
+ break;
+ default:
+ break;
+ };
+ }
+
+void CTLowLevel::Normalize(TRgb& aColor,TRgb aDitherColors[4])
+ {
+ switch (iDispMode)
+ {
+ case EGray2:
+ FillArray(TRgb::Gray2(aColor.Gray2()),aDitherColors);
+ break;
+ case EGray4:
+ if (iUserDispMode == EGray2)
+ FillArray(TRgb::Gray2(aColor.Gray2()),aDitherColors);
+ else
+ {
+ TInt gray16 = aColor.Gray16();
+ aDitherColors[0] = TRgb::Gray4(ditherlutab[gray16][0]);
+ aDitherColors[1] = TRgb::Gray4(ditherlutab[gray16][1]);
+ aDitherColors[2] = TRgb::Gray4(ditherlutab[gray16][2]);
+ aDitherColors[3] = TRgb::Gray4(ditherlutab[gray16][3]);
+ }
+ break;
+ case EGray16:
+ if (iUserDispMode == EGray2)
+ FillArray(TRgb::Gray2(aColor.Gray2()),aDitherColors);
+ else if (iUserDispMode == EGray4)
+ {
+ TInt gray16 = aColor.Gray16();
+ aDitherColors[0] = TRgb::Gray4(ditherlutab[gray16][0]);
+ aDitherColors[1] = TRgb::Gray4(ditherlutab[gray16][1]);
+ aDitherColors[2] = TRgb::Gray4(ditherlutab[gray16][2]);
+ aDitherColors[3] = TRgb::Gray4(ditherlutab[gray16][3]);
+ }
+ else
+ FillArray(TRgb::Gray16(aColor.Gray16()),aDitherColors);
+ break;
+ case EGray256:
+ FillArray(TRgb::Gray256(aColor.Gray256()),aDitherColors);
+ break;
+ case EColor16:
+ FillArray(TRgb::Color16(aColor.Color16()),aDitherColors);
+ break;
+ case EColor256:
+ FillArray(TRgb::Color256(aColor.Color256()),aDitherColors);
+ break;
+ case EColor4K:
+ FillArray(TRgb::Color4K(aColor.Color4K()),aDitherColors);
+ break;
+ case EColor64K:
+ FillArray(TRgb::Color64K(aColor.Color64K()),aDitherColors);
+ break;
+ case EColor16M:
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ FillArray(aColor,aDitherColors);
+ break;
+ default:
+ break;
+ };
+ }
+
+void CTLowLevel::FillArray(TRgb aColor,TRgb aArray[4])
+ {
+ aArray[0] = aColor;
+ aArray[1] = aColor;
+ aArray[2] = aColor;
+ aArray[3] = aColor;
+ }
+
+
+void CTLowLevel::PostBlendShadow(TUint32 &aPmaColor)
+ {
+ //this function should only be called for PMA colours
+ const TInt alpha = aPmaColor >> 24;
+ TUint32 value = aPmaColor & 0x00ffffff;
+
+ if (iPostBlendShadow & CFbsDrawDevice::EFade)
+ {
+#if defined(SYMBIAN_USE_FAST_FADING)
+ TUint32 fast_fade_offset = ((SYMBIAN_USE_FAST_FADING & 0xff) * alpha) >>8;
+ fast_fade_offset = fast_fade_offset | (fast_fade_offset << 8) | (fast_fade_offset <<16);
+ value = ((value >> 1) & ~0x00808080) + (fast_fade_offset);
+ value = value | (((TUint32)alpha)<<24);
+#else
+ /*
+ here blackmap = 200,
+ whitemap = 100
+ iFadeMapFactor = aWhiteMap - aBlackMap + 1;
+ iFadeMapOffset = aBlackMap;
+ */
+
+ const TInt fadeMapOffset = ((alpha * 0x7f) >> 8) & 0xff;
+ const TInt wordFadeMapOffset = ((fadeMapOffset) << 16) | (fadeMapOffset);
+ const TInt rb = ((((value & 0x00ff00ff) * 0x7f) >> 8) + wordFadeMapOffset) & 0x00ff00ff;
+ const TInt g = ((((value & 0x0000ff00) * 0x7f) >> 16) + fadeMapOffset) << 8;
+ value = rb | g | (((TUint32)alpha)<<24);
+#endif
+ }
+
+ if (iPostBlendShadow & CFbsDrawDevice::EShadow)
+ {
+ TInt alpha = (aPmaColor>>24);
+ TInt red = (value>>16)&0xff;
+ TInt green = (value>>8)&0xff;
+ TInt blue = value &0xff;
+
+ TInt shadow= (alpha*0x40)>>8;
+ red = Max(0,red-shadow);
+ green = Max (0,green-shadow);
+ blue = Max (0,blue-shadow);
+ value = (((TUint32)alpha)<<24)|(((TUint32)red)<<16)|(((TUint32)green)<<8)|((TUint32)blue);
+ }
+ aPmaColor = value;
+ }
+
+void CTLowLevel::Shadow(TRgb& aColor,TInt aShadowMode)
+ {
+ if (aShadowMode & 2)
+ {
+ switch (iDrawDevice->DisplayMode())
+ {
+ case EGray2:
+ aColor = TRgb::Gray256(FadeGray(aColor.Gray2() * 255));
+ break;
+ case EGray4:
+ case EGray16:
+ aColor = TRgb::Gray256(FadeGray(aColor.Gray16() * 17));
+ break;
+ case EGray256:
+ aColor = TRgb::Gray256(FadeGray(aColor.Gray256()));
+ break;
+ case EColor16:
+ aColor = FadeRgb(TRgb::Color16(aColor.Color16()));
+ break;
+ case EColor256:
+ aColor = FadeRgb(TRgb::Color256(aColor.Color256()));
+ break;
+ case EColor4K:
+ aColor = FadeRgb(TRgb::Color4K(aColor.Color4K()));
+ break;
+ case EColor64K:
+ aColor = FadeRgb(TRgb::Color64K(aColor.Color64K()),KFastFading && iUseFastFade);
+ break;
+ case EColor16M:
+ aColor = FadeRgb(TRgb::Color16M(aColor.Color16M()));
+ break;
+ case EColor16MU:
+ aColor = FadeRgb(TRgb::Color16MU(aColor.Color16MU()),KFastFading && iUseFastFade);
+ break;
+ case EColor16MA:
+ aColor = FadeRgb(TRgb::Color16MA(aColor.Color16MA()),KFastFading && iUseFastFade);
+ break;
+ case EColor16MAP:
+ aColor = FadeRgb(TRgb::Color16MAP(aColor.Color16MAP()),KFastFading && iUseFastFade);
+ break;
+ default:
+ break;
+ };
+ }
+
+ if (aShadowMode & 1)
+ {
+ switch (iDrawDevice->DisplayMode())
+ {
+ case EGray2:
+ aColor = KRgbBlack;
+ break;
+ case EGray4:
+ case EGray16:
+ aColor = TRgb::Gray16(Max(0,aColor.Gray16()-5));
+ break;
+ case EGray256:
+ aColor = TRgb::Gray256(Max(0,aColor.Gray256()-85));
+ break;
+ case EColor16:
+ {
+ TInt color = aColor.Color16();
+ if (color == 15) color--;
+ else if (color == 14) color = 1;
+ else if (color > 7) color += 3;
+ else if (color > 4) color -= 3;
+ else color = 0;
+ aColor = TRgb::Color16(color);
+ }
+ break;
+ case EColor256:
+ {
+ aColor = TRgb::Color256(aColor.Color256());
+ TInt red = aColor.Red();
+ TInt green = aColor.Green();
+ TInt blue = aColor.Blue();
+ red = Max(0,red-0x33);
+ green = Max(0,green-0x33);
+ blue = Max(0,blue-0x33);
+ aColor = TRgb(red,green,blue);
+ }
+ break;
+ case EColor4K:
+ {
+ TInt color = aColor.Color4K();
+ TInt red = (color & 0xf00) >> 8;
+ TInt green = (color & 0x0f0) >> 4;
+ TInt blue = color & 0x00f;
+
+ red = Max(0,red-5);
+ green = Max(0,green-5);
+ blue = Max(0,blue-5);
+
+ aColor = TRgb::Color4K((red << 8) | (green << 4) | blue);
+ }
+ break;
+ case EColor64K:
+ {
+ TInt color = aColor.Color64K();
+ TInt red = (color & 0xf800) >> 11;
+ TInt green = (color & 0x07e0) >> 5;
+ TInt blue = color & 0x001f;
+
+ red = Max(0,red-8);
+ green = Max(0,green-16);
+ blue = Max(0,blue-8);
+
+ aColor = TRgb::Color64K((red << 11) | (green << 5) | blue);
+ }
+ break;
+ case EColor16M:
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ {
+ TInt red = aColor.Red();
+ TInt green = aColor.Green();
+ TInt blue = aColor.Blue();
+ red = Max(0,red-0x40);
+ green = Max(0,green-0x40);
+ blue = Max(0,blue-0x40);
+ aColor = TRgb(red,green,blue,aColor.Alpha());
+ }
+ break;
+ default:
+ break;
+ };
+ }
+ }
+
+void CTLowLevel::Blend(TUint8* aBuffer,TUint8* aBufferDest, TDisplayMode aDispMode)
+ {
+ TUint32* buffer = reinterpret_cast<TUint32*> (aBuffer);
+ TUint32* bufferDest = reinterpret_cast<TUint32*> (aBufferDest);
+ TInt mask = (*buffer & 0xff000000) >> 24;
+ TRgb rgbDest;
+
+ switch(aDispMode)
+ {
+ case EColor16MU:
+ {
+ // src + ((255 - mask) * dest) / 255
+ if(mask!=255)
+ {
+ rgbDest=TRgb::Color16MU(*bufferDest);
+ if(mask)
+ {
+ TRgb rgbSrc=TRgb::Color16MU(*buffer);
+ rgbDest.SetRed(rgbSrc.Red() + ((255 - mask) * rgbDest.Red()) / 255);
+ rgbDest.SetGreen(rgbSrc.Green() + ((255 - mask) * rgbDest.Green()) / 255);
+ rgbDest.SetBlue(rgbSrc.Blue() + ((255 - mask) * rgbDest.Blue()) / 255);
+ }
+ *buffer=rgbDest.Internal();
+ }
+ }
+ break;
+ case EColor16MA:
+ {
+ // (mask * src + (255 - mask) * dest) / 255
+ if(mask!=255)
+ {
+ rgbDest=TRgb::Color16MA(*bufferDest);
+ if(mask)
+ {
+ TRgb rgbSrc=TRgb::Color16MA(*buffer);
+ rgbDest.SetRed((mask * rgbSrc.Red() + (255 - mask) * rgbDest.Red()) / 255);
+ rgbDest.SetGreen((mask * rgbSrc.Green() + (255 - mask) * rgbDest.Green()) / 255);
+ rgbDest.SetBlue((mask * rgbSrc.Blue() + (255 - mask) * rgbDest.Blue()) / 255);
+ }
+ *buffer=rgbDest.Internal();
+ }
+ }
+ break;
+ case EColor16MAP:
+ {
+ /*
+ * Blend function uses the Porter Duff composition equation
+ * This blends two pixels with alphas:
+ * Ar = As + Ad * (1 - As) (Blended Alpha)
+ * Cr = Cs + Cd(1 - As) (Blended Colour)
+ * Cr = Cs + Cd(255-As)/255 : for alpha 0-255
+ * where Ar = alpha result
+ * where Cr = colour result
+ * where Cs = source colour
+ * where Cd = destination colour
+ * The function assumes that the mask buffer is the alpha value of the source pixel.
+ */
+ if(mask!=255)
+ {
+ rgbDest=TRgb::Color16MA(*bufferDest);
+ if(mask)
+ {
+ TInt destAlpha = (*bufferDest & 0xff000000) >> 24;
+ TInt sourceAlpha = (*buffer & 0xff000000) >> 24;
+ TRgb rgbSrc;
+ rgbSrc.SetInternal(*buffer);
+ rgbDest.SetInternal(*bufferDest);
+ TInt resultAlpha = sourceAlpha +((255-sourceAlpha)*destAlpha)/255;
+ rgbDest.SetRed(rgbSrc.Red() + ((255 - sourceAlpha) * rgbDest.Red()) / 255);
+ rgbDest.SetGreen(rgbSrc.Green() + ((255 - sourceAlpha) * rgbDest.Green()) / 255);
+ rgbDest.SetBlue(rgbSrc.Blue() + ((255 - sourceAlpha) * rgbDest.Blue())/ 255);
+ rgbDest.SetAlpha(resultAlpha);
+ }
+ *buffer=rgbDest.Internal();
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+
+void CTLowLevel::Shadow(TUint8* aBuffer,TInt aByteLength,TInt aShadowMode)
+ {
+ TUint8* buffer = aBuffer;
+ const TUint8* bufferLimit = aBuffer + aByteLength;
+
+ if (aShadowMode & 2)
+ {
+ switch (iDrawDevice->DisplayMode())
+ {
+ case EGray2:
+ while (buffer < bufferLimit)
+ *buffer++ = 0xff;
+ break;
+ case EGray4:
+ while (buffer < bufferLimit)
+ {
+ TInt first = FadeGray((buffer[0] & 0x03) * 85) >> 6;
+ TInt second = FadeGray(((buffer[0] >> 2) & 0x03) * 85) >> 6;
+ TInt third = FadeGray(((buffer[0] >> 4) & 0x03) * 85) >> 6;
+ TInt fourth = FadeGray(((buffer[0] >> 6) & 0x03) * 85) >> 6;
+ *buffer++ = TUint8(first | (second << 2) | (third << 4) | (fourth << 6));
+ }
+ break;
+ case EGray16:
+ while (buffer < bufferLimit)
+ {
+ TInt low = FadeGray((buffer[0] & 0x0f) * 17) >> 4;
+ TInt high = FadeGray((buffer[0] >> 4) * 17) >> 4;
+ *buffer++ = TUint8((high << 4) | low);
+ }
+ break;
+ case EGray256:
+ while (buffer < bufferLimit)
+ *buffer++ = FadeGray(*buffer);
+ break;
+ case EColor16:
+ while (buffer < bufferLimit)
+ {
+ TInt low = FadeRgb(TRgb::Color16(buffer[0] & 0x0f)).Color16();
+ TInt high = FadeRgb(TRgb::Color16(buffer[0] >> 4)).Color16();
+ *buffer++ = TUint8((high << 4) | low);
+ }
+ break;
+ case EColor256:
+ while (buffer < bufferLimit)
+ *buffer++ = TUint8(FadeRgb(TRgb::Color256(buffer[0])).Color256());
+ break;
+ case EColor4K:
+ while (buffer < bufferLimit)
+ {
+ TInt color4K = FadeRgb(TRgb::Color4K(buffer[0] | (buffer[1] << 8))).Color4K();
+ buffer[0] = TUint8(color4K);
+ buffer[1] = TUint8(color4K >> 8);
+ buffer += 2;
+ }
+ break;
+ case EColor64K:
+ while (buffer < bufferLimit)
+ {
+ TInt color64K = FadeRgb(TRgb::Color64K(buffer[0] | (buffer[1] << 8)),ETrue).Color64K();
+ buffer[0] = TUint8(color64K);
+ buffer[1] = TUint8(color64K >> 8);
+ buffer += 2;
+ }
+ break;
+ case EColor16M:
+ {
+ while (buffer < bufferLimit)
+ *buffer++ = FadeGray(buffer[0]);
+ }
+ break;
+ case EColor16MU:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ // scanline buffer for 16MU driver is pre-multiplied
+ TRgb color = FadeRgb(TRgb::Color16MAP(*buffer32),ETrue);
+ // avoid rounding errors with EDrawModeAND etc.
+ *buffer32++ = color.Alpha() == 255 ? color.Internal() : color.Color16MAP();
+ }
+ }
+ break;
+ case EColor16MA:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ TRgb color = FadeRgb(TRgb::Color16MA(*buffer32),ETrue);
+ *buffer32++ = color.Color16MA();
+ }
+ }
+ break;
+ case EColor16MAP:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ TRgb color = FadeRgb(TRgb::Color16MAP(*buffer32),ETrue);
+ *buffer32++ = color.Color16MAP();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ buffer = aBuffer;
+
+ if (aShadowMode & 1)
+ {
+ switch (iDrawDevice->DisplayMode())
+ {
+ case EGray2:
+ while (buffer < bufferLimit)
+ {
+ *buffer++ = 0;
+ }
+ break;
+ case EGray4:
+ while (buffer < bufferLimit)
+ {
+ TInt first = buffer[0] & 0x03;
+ TInt second = buffer[0] & 0x0c;
+ TInt third = buffer[0] & 0x30;
+ TInt fourth = buffer[0] & 0xc0;
+ first = Max(0,first-1);
+ second = Max(0,second-4);
+ third = Max(0,third-16);
+ fourth = Max(0,fourth-64);
+ *buffer++ = TUint8(fourth | third | second | first);
+ }
+ break;
+ case EGray16:
+ while (buffer < bufferLimit)
+ {
+ TInt low = buffer[0] & 0x0f;
+ TInt high = buffer[0] >> 4;
+ low = Max(0,low-5);
+ high = Max(0,high-5);
+ *buffer++ = TUint8((high << 4) | low);
+ }
+ break;
+ case EGray256:
+ while (buffer < bufferLimit)
+ {
+ buffer[0] = TUint8(Max(0,buffer[0]-85));
+ buffer++;
+ }
+ break;
+ case EColor16:
+ while (buffer < bufferLimit)
+ {
+ TInt low = buffer[0] & 0x0f;
+ TInt high = buffer[0] >> 4;
+ if (low == 15) low = 14;
+ else if (low == 14) low = 1;
+ else if (low >= 11) low = 0;
+ else if (low >= 8) low += 3;
+ else if (low >= 5) low -= 3;
+ else low = 0;
+ if (high == 15) high = 14;
+ else if (high == 14) high = 1;
+ else if (high >= 11) high = 0;
+ else if (high >= 8) high += 3;
+ else if (high >= 5) high -= 3;
+ else high = 0;
+ *buffer++ = TUint8((high << 4) | low);
+ }
+ break;
+ case EColor256:
+ while (buffer < bufferLimit)
+ {
+ TRgb color(TRgb::Color256(buffer[0]));
+ TInt red = color.Red();
+ TInt green = color.Green();
+ TInt blue = color.Blue();
+ red = Max(0,red-0x33);
+ green = Max(0,green-0x33);
+ blue = Max(0,blue-0x33);
+ *buffer++ = TUint8(TRgb(red,green,blue).Color256());
+ }
+ break;
+ case EColor4K:
+ while (buffer < bufferLimit)
+ {
+ TInt data = (buffer[1] << 8) | buffer[0];
+ TInt red = (data & 0xf00) >> 8;
+ TInt green = (data & 0x0f0) >> 4;
+ TInt blue = data & 0x00f;
+ red = Max(0,red-5);
+ green = Max(0,green-5);
+ blue = Max(0,blue-5);
+ data = (red << 8) | (green << 4) | blue;
+ buffer[0] = TUint8(data);
+ buffer[1] = TUint8(data >> 8);
+ buffer += 2;
+ }
+ break;
+ case EColor64K:
+ while (buffer < bufferLimit)
+ {
+ TInt data = (buffer[1] << 8) | buffer[0];
+ TInt red = (data & 0xf800) >> 11;
+ TInt green = (data & 0x07e0) >> 5;
+ TInt blue = data & 0x001f;
+ red = Max(0,red-8);
+ green = Max(0,green-16);
+ blue = Max(0,blue-8);
+ data = (red << 11) | (green << 5) | blue;
+ buffer[0] = TUint8(data);
+ buffer[1] = TUint8(data >> 8);
+ buffer += 2;
+ }
+ break;
+ case EColor16M:
+ while (buffer < bufferLimit)
+ {
+ buffer[0] = TUint8(Max(0,buffer[0]-0x40));
+ buffer++;
+ }
+ break;
+ case EColor16MU:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ // scanline buffer for 16MU driver is pre-multiplied
+ TRgb color = TRgb::Color16MAP(*buffer32);
+ color = TRgb(Max(0,color.Red()-0x40),Max(0,color.Green()-0x40),Max(0,color.Blue()-0x40), color.Alpha());
+ // avoid rounding errors with EDrawModeAND etc.
+ *buffer32++ = color.Alpha() == 255 ? color.Internal() : color.Color16MAP();
+ }
+ }
+ break;
+ case EColor16MA:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ TRgb color = TRgb::Color16MA(*buffer32);
+ color = TRgb(Max(0,color.Red()-0x40),Max(0,color.Green()-0x40),Max(0,color.Blue()-0x40), color.Alpha());
+ *buffer32++ = color.Color16MA();
+ }
+ }
+ break;
+ case EColor16MAP:
+ {
+ TUint32* buffer32 = reinterpret_cast <TUint32*> (buffer);
+ TUint32* bufferLimit32 = buffer32 + aByteLength / 4;
+ while (buffer32 < bufferLimit32)
+ {
+ TRgb color = TRgb::Color16MAP(*buffer32);
+ color = TRgb(Max(0,color.Red()-0x40),Max(0,color.Green()-0x40),Max(0,color.Blue()-0x40), color.Alpha());
+ *buffer32++ = color.Color16MAP();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+TUint8 CTLowLevel::FadeGray(TInt aGray256)
+ {
+ return TUint8((aGray256 >> 1) + 128);
+ }
+
+/**
+A test code function for Fading colour values.
+@param aColor Colour value for which faded colour is needed.
+@param aFastFade Used to check whether Fast Fading method is required or not.
+ aFastFade flag should be true only when there is a corresponding Fast Fading
+ implementation in product code and the fading method uses the Fast Fading method.
+@return TRgb Faded colour value.
+*/
+TRgb CTLowLevel::FadeRgb(TRgb aColor, TBool aFastFade/*=EFalse*/)
+ {
+ if(aFastFade)
+ {
+#if defined(SYMBIAN_USE_FAST_FADING)
+ TUint32 value = ((aColor.Internal() >> 1) & ~0x00808080) + SYMBIAN_USE_FAST_FADING;
+ TInt alpha = aColor.Alpha();
+ return TRgb(value, alpha);
+#endif
+ }
+ TInt red = (aColor.Red() >> 1) + 128;
+ TInt green = (aColor.Green() >> 1) + 128;
+ TInt blue = (aColor.Blue() >> 1) + 128;
+ TInt alpha = aColor.Alpha();
+ return TRgb(red,green,blue,alpha);
+ }
+
+TColorConvertor& CTLowLevel::ColorConvertor(TDisplayMode aDisplayMode)
+ {
+ return *iColorConvertor[aDisplayMode];
+ }
+
+void CTLowLevel::Report()
+ {
+ INFO_PRINTF4(_L("Test %d: %d/%d"),iTestNo,iReportIteration,iTotalReportIterations);
+ if (iReportIteration < iTotalReportIterations)
+ iReportIteration++;
+ }
+
+inline TBool CTLowLevel::Check(TBool aValue)
+ {
+ if (iLastFailTestNo!=iIteration)
+ {
+ if (!aValue)
+ {
+ _LIT(KLog,"Test %d, iteration %d failed iDispMode %d iUserDispMode %d iOrientation %d");
+ INFO_PRINTF6(KLog,iTestNo,iIteration,iDispMode,iUserDispMode,iOrientation);
+ iLastFailTestNo=iIteration;
+ }
+ TEST(aValue);
+ }
+ return !aValue;
+ }
+
+//-----------
+CTLowLevel1::CTLowLevel1(CTestStep* aStep):
+ CTLowLevel(aStep)
+ {
+ iOrientation = CFbsDrawDevice::EOrientationRotated180;
+ iOrientationEnd = CFbsDrawDevice::EOrientationRotated270;
+ }
+
+void CTLowLevel1::RunTestCaseL(TInt /*aCurTestCase*/)
+ {
+ if(iOrientation <= iOrientationEnd)
+ {
+ INFO_PRINTF2(_L("Screen device : %S"), &DisplayModeNames1[iCurScreenDeviceModeIndex]);
+ TDisplayMode display = TestDisplayMode1[iCurScreenDeviceModeIndex++];
+/**
+ @SYMTestCaseID GRAPHICS-SCREENDRIVER-0018
+*/
+ ((CTLowLevelStep*)iStep)->SetTestStepID(_L("GRAPHICS-SCREENDRIVER-0018"));
+ TestScreenDrawL(display);
+ if(iCurScreenDeviceModeIndex >= KNumberDisplayModes1)
+ {
+ iCurScreenDeviceModeIndex = 0;
+ iOrientation ++;
+ }
+ ((CTLowLevelStep*)iStep)->RecordTestResultL();
+ }
+ else
+ {
+ ((CTLowLevelStep*)iStep)->CloseTMSGraphicsStep();
+ TestComplete();
+ }
+ }
+
+//--------------
+__CONSTRUCT_STEP__(LowLevel)
+
+__CONSTRUCT_STEP__(LowLevel1)