--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/tbit/TDefect2.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2641 @@
+// Copyright (c) 2003-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 <random.h>
+#include <s32file.h>
+#include <e32math.h>
+#include <hal.h>
+#include <s32mem.h>
+#include <graphics/gdi/gdiconsts.h>
+#include <e32cmn.h>
+#include "BITPANIC.H"
+#include "TDefect2.h"
+#include "fbsmessage.h"
+
+//===================================================================
+//In order to test multiple screens creation process on the Emulator,
+//you have to extend your epoc.ini file with the following lines
+//_NewScreen_
+//ScreenWidth 640
+//ScreenHeight 480
+//===================================================================
+
+//
+//
+//Globals
+LOCAL_D RFs FServSession;
+
+//
+//
+//Test file names
+_LIT(KArchiveFileName, "C:\\FbsBitGcArchive.dat");
+
+//
+//
+//Create/Destroy test environment global functions
+
+//Delete "aFullName" file.
+LOCAL_C void DeleteDataFile(const TDesC& aFullName)
+ {
+ RFs fsSession;
+ TInt err = fsSession.Connect();
+ if(err == KErrNone)
+ {
+ TEntry entry;
+ if(fsSession.Entry(aFullName, entry) == KErrNone)
+ {
+ RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
+ err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
+ }
+ err = fsSession.Delete(aFullName);
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
+ }
+ }
+ fsSession.Close();
+ }
+ else
+ {
+ RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
+ }
+ }
+
+//
+CTDefect2::CTDefect2(CTestStep* aStep):
+ CTGraphicsBase(aStep),
+ iScrDev(NULL),
+ iGc(NULL),
+ iSize(0, 0),
+ iCurrentMode(ENone),
+ iBitmap(NULL),
+ iBmpDevice(NULL)
+ {
+ }
+
+CTDefect2::~CTDefect2()
+ {
+ DestroyFont();
+ DeleteBitmap();
+ DeleteGraphicsContext();
+ DeleteBitmapDevice();
+ DeleteScreenDevice();
+ }
+
+void CTDefect2::ConstructL()
+ {
+ User::LeaveIfError(::FServSession.Connect());
+ }
+
+void CTDefect2::RunTestCaseL(TInt aCurTestCase)
+ {
+ ((CTDefect2Step*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+ _LIT(KTest1,"SubTest %d: DEF039237");
+ _LIT(KTest2,"SubTest %d: DEF039331");
+ _LIT(KTest3,"SubTest %d: DEF039650");
+ _LIT(KTest4,"SubTest %d: CFbsBitmap::GetPixel() performance");
+ _LIT(KTest5,"SubTest %d: Rotate/Move text");
+ _LIT(KTest6,"SubTest %d: SwapWidthAndHeight");
+ _LIT(KTest7,"SubTest %d: Create multiple screens");
+ _LIT(KTest8,"SubTest %d: Clear with non-zero origin");
+ _LIT(KTest9,"SubTest %d: DEF115395: DrawBitmap & DrawBitmapMasked with a sourceRect out of the Bitmap bounds");
+ _LIT(KTest10,"SubTest %d: INC119063: General test CopyRect rewrite for low color depth (8,4,2, pixels per byte)");
+ _LIT(KTest11,"SubTest %d: INC120917: Dirty Mask Bitmap not remapped in BitBltMasked");
+ _LIT(KTest12,"SubTest %d: Zero-sized brush pattern bitmaps");
+ _LIT(KTest13,"SubTest %d: CopyRect with non-trivial alpha");
+ _LIT(KTest14,"SubTest %d: INC119063: CopyRect reading past end of bitmap data at unallocated pages");
+ _LIT(KTest15,"SubTest %d: INC128813 : CFbsBitGc::InternalizeL handle duplicate fail testing");
+ _LIT(KTest16,"SubTest %d: DEF132331 : CFbsScreenDevice PixelsToTwips conversions faulty with large inputs");
+ _LIT(KTest17,"SubTest %d: DEF137103: CFbsBitmapDevice::SetBits() should check bitmap size");
+ switch(aCurTestCase)
+ {
+ case 1:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0066"));
+ INFO_PRINTF2(KTest1,aCurTestCase);
+ DEF039237L();
+ break;
+ case 2:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0067"));
+ INFO_PRINTF2(KTest2,aCurTestCase);
+ DEF039331L();
+ break;
+ case 3:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0068"));
+ INFO_PRINTF2(KTest3,aCurTestCase);
+ DEF039650L();
+ break;
+ case 4:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0069"));
+ INFO_PRINTF2(KTest4,aCurTestCase);
+ GetPixelPerformance1L();
+ break;
+ case 5:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0070"));
+ INFO_PRINTF2(KTest5,aCurTestCase);
+ RotateMoveTextL();
+ break;
+ case 6:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0071"));
+ INFO_PRINTF2(KTest6,aCurTestCase);
+ SwapWidthAndHeightL();
+ break;
+ case 7:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0072"));
+ INFO_PRINTF2(KTest7,aCurTestCase);
+ CreateScreenDeviceL();
+ break;
+ case 8:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0073"));
+ INFO_PRINTF2(KTest8,aCurTestCase);
+ NonZeroOriginClearL();
+ break;
+ case 9:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0097"));
+ INFO_PRINTF2(KTest9,aCurTestCase);
+ DEF115395L();
+ break;
+ case 10:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0099"));
+ INFO_PRINTF2(KTest10,aCurTestCase);
+ ExerciseCopyRect();
+ break;
+ case 11:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0101"));
+ INFO_PRINTF2(KTest11,aCurTestCase);
+ TestDirtyMaskBitmapL();
+ break;
+ case 12:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0108"));
+ INFO_PRINTF2(KTest12,aCurTestCase);
+ ZeroSizedPatternBrushL();
+ break;
+ case 13:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0113"));
+ INFO_PRINTF2(KTest13,aCurTestCase);
+ CopyRectAlphaL();
+ break;
+ case 14:
+ //Note: This test generates panic windows... you may need to put your test before it.
+ //They will be closed at the end of the test set, but they may get in the way of your next test, sorry.
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0098"));
+ INFO_PRINTF2(KTest14,aCurTestCase);
+ CopyRectReadOutsideBitmap();
+ break;
+ case 15:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0110"));
+ INFO_PRINTF2(KTest15,aCurTestCase);
+ CFbsBitGcInternalizeLFailL();
+ break;
+ case 16:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0111"));
+ INFO_PRINTF2(KTest16,aCurTestCase);
+ PixelsToTwipsConversionCheck();
+ break;
+ case 17:
+ ((CTDefect2Step*)iStep)->SetTestStepID(_L("GRAPHICS-BITGDI-0112"));
+ INFO_PRINTF2(KTest17,aCurTestCase);
+ TestSetBitsL();
+ break;
+
+ case 18:
+ INFO_PRINTF1(_L("PDEF141192: test CFbsBitGc::DrawBitmapMasked()"));
+ INFO_PRINTF1(_L("Test Red Channel"));
+ TestMaskForSelectedValuesL(0);
+ INFO_PRINTF1(_L("Test Green Channel"));
+ TestMaskForSelectedValuesL(1);
+ INFO_PRINTF1(_L("Test Blue Channel"));
+ TestMaskForSelectedValuesL(2);
+ break;
+
+ //Insert tests here
+
+ case 19:
+ ((CTDefect2Step*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+ ((CTDefect2Step*)iStep)->CloseTMSGraphicsStep();
+ TestComplete();
+ break;
+ }
+ ((CTDefect2Step*)iStep)->RecordTestResultL();
+ }
+
+/**
+ * @SYMTestCaseID GRAPHICS-BITGDI-0101
+ *
+ * @SYMDEF INC120917
+ *
+ * @SYMTestCaseDesc If mask bitmap has been dirtied (by resize/compress)
+ * then bitbltmasked should not read old memory contents
+ *
+ * @SYMTestPriority Normal
+ *
+ * @SYMTestStatus Implemented
+ *
+ * @SYMTestActions Create image and mask bitmap with pattern and blit them for reference
+ * create duplicate handle
+ * resize the mask on duplicate
+ * verify that blit produces same result for same area on larger mask
+ * and change pattern
+ * blit using duplicate handle and source
+ * blit using original handle and source
+ * in defect scenario these results are different (original same as reference)
+ * in fix scenario they should be same (different to reference)
+ * revalidate original handle reblit and verify now correct
+ *
+ * repeat above steps:
+ * (this proves duplicate change causes original flag, not just duplication)
+ * resize the mask on duplicate
+ * verify that blit produces same result for same area on larger mask
+ * and change pattern
+ * blit using duplicate handle and source
+ * blit using original handle and source
+ * in defect scenario these results are different (original same as reference)
+ * in fix scenario they should be same (different to reference)
+ * revalidate original handle reblit and verify now correct
+ */
+void CTDefect2::TestDirtyMaskBitmapL()
+ {
+ const TInt KWidth=120;
+ const TInt KHeight=50;
+ const TInt KBigger=50;
+ enum
+ {
+ EStepBefore=0,
+ EStepVerifyDupGrow,
+ EStepDupDiffAfterRefill,
+ EStepOriginalDiffAfterRefill,
+ EStepOriginalDiffAfterRefillAndGetAddress,
+ EStepDupDiffAfterRefill2,
+ EStepOriginalDiffAfterRefill2,
+ ENumSteps
+ };
+ TInt pushcount=0;
+ //set up the target
+ CFbsBitmap* targetBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(targetBmp);pushcount++;
+ User::LeaveIfError(targetBmp->Create(TSize(KWidth,KHeight*ENumSteps), EColor16MU));
+ CFbsBitmapDevice* bmpDevice=CFbsBitmapDevice::NewL(targetBmp);
+ CleanupStack::PushL(bmpDevice);pushcount++;
+ CBitmapContext* bmpContext;
+ User::LeaveIfError(bmpDevice->CreateBitmapContext(bmpContext));
+ CleanupStack::PushL(bmpContext);pushcount++;
+ bmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmpContext->SetBrushColor(KRgbRed);
+ bmpContext->Clear();
+
+ //set up source and mask
+ CFbsBitmap* sourceBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(sourceBmp);pushcount++;
+ User::LeaveIfError(sourceBmp->Create(TSize(KWidth,KHeight), EColor16MU));
+ TUint32* sourceData=sourceBmp->DataAddress();
+ TInt sourceLength=(sourceBmp->DataStride()>>2)*KHeight;
+ CFbsBitmap* maskBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(maskBmp);pushcount++;
+ User::LeaveIfError(maskBmp->Create(TSize(KWidth,KHeight), EGray2));
+ TUint32* maskDataStart=maskBmp->DataAddress();
+ TInt maskLength=(maskBmp->DataStride()>>2)*KHeight;
+
+ TUint32* targetData=targetBmp->DataAddress();
+ TInt targetCopySize=((targetBmp->DataStride()+3)>>2)*KHeight;
+
+ TUint32 blueint=KRgbBlue.Color16MU();
+ for (TInt fillIndex=0;fillIndex<sourceLength;fillIndex++)
+ {
+ sourceData[fillIndex]=blueint;
+ }
+ TInt maskPattern=0x12345678;
+ for (TInt fillIndex=0;fillIndex<maskLength;fillIndex++)
+ {
+ maskDataStart[fillIndex]=maskPattern;
+ }
+
+ //Initial result of blit operation
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepBefore),sourceBmp,TSize(KWidth,KHeight),maskBmp,EFalse);
+
+ //duplicate the mask handle
+ CFbsBitmap* maskBmpDup=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(maskBmpDup);pushcount++;
+ maskBmpDup->Duplicate(maskBmp->Handle());
+ TUint32* maskDataDup=maskBmpDup->DataAddress();
+ TEST(maskDataDup==maskDataStart); //not expected to fail
+ //resize duplicate handle bigger
+ maskBmpDup->Resize(TSize(KWidth+KBigger,KHeight));
+ maskDataDup=maskBmpDup->DataAddress();
+ TEST(maskDataDup!=maskDataStart); //not expected to fail
+
+ //At this point the duplicate handle is referencing a different address to the original handle.
+ //With the defect in place this remains uncorrected,
+ //and is demonstrated by comparing the output contents of blitting using each of the handles.
+
+ //verify that the resizing of the mask preserved the original mask data, so the resize has no effect on small area blit
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepVerifyDupGrow),sourceBmp,TSize(KWidth,KHeight),maskBmpDup,EFalse);
+
+ //If this cmp fails: blit or resize is not working properly on the duplicate handle - not caused by this defect (very unexpected)
+ TEST(0==Mem::Compare((TUint8*)(targetData),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepVerifyDupGrow),targetCopySize*4));
+
+ //Change the mask using the address in the duplicate handle
+ //As we want to fill the whole mask with a known pattern we need to recalculate the mask size.
+ TInt newMaskLength=(maskBmpDup->DataStride()>>2)*KHeight;
+ maskPattern=0xAAAAAAAA;
+ for (TInt fillIndex=0;fillIndex<newMaskLength;fillIndex++)
+ {
+ maskDataDup[fillIndex]=maskPattern;
+ }
+
+ //compare the results of blitting using this new mask using each of the two handles to the same mask
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepDupDiffAfterRefill),sourceBmp,TSize(KWidth,KHeight),maskBmpDup,EFalse);
+ //This blit should not crash, even if the defect is present because the previous sized bitmap should not be released until all references have been updated.
+
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepOriginalDiffAfterRefill),sourceBmp,TSize(KWidth,KHeight),maskBmp,EFalse);
+
+ //If this cmp fails: data change had no effect for duplicate handle (very unexpected)
+ TEST(0!=Mem::Compare((TUint8*)(targetData),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill),targetCopySize*4));
+
+ //Check that the result of both blits is the same.
+ //If this cmp fails: defect is demonstrated. This is the main defect demonstration test.
+ TEST(0==Mem::Compare((TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepOriginalDiffAfterRefill),targetCopySize*4));
+
+ //This revalidates the original handle, hiding the defect
+ TUint32* maskDataRevalid=maskBmp->DataAddress();
+ TEST(maskDataDup==maskDataRevalid);
+
+ //This blit should not crash as the original handle has now been revalidated to point to allocated data.
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepOriginalDiffAfterRefillAndGetAddress),sourceBmp,TSize(KWidth,KHeight),maskBmp,EFalse);
+ //If this cmp fails: original was not revalidated by DataAddress - content is not same as duplicate
+ TEST(0==Mem::Compare((TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepOriginalDiffAfterRefillAndGetAddress),targetCopySize*4));
+
+ //Extra testing... do we handle situation where the duplicated handle is changed more than once?
+
+ //Basically repeats the test sequence above.
+
+ //Repeat the resize even bigger using duplicate handle
+ //resize duplicate handle bigger
+ maskBmpDup->Resize(TSize(KWidth+KBigger,KHeight+KBigger));
+ maskDataDup=maskBmpDup->DataAddress();
+ TEST(maskDataDup!=maskDataRevalid);
+
+ //Change the mask using the address in the duplicate handle
+ //As we want to fill the whole mask with a known pattern we need to recalculate the mask size.
+ newMaskLength=(maskBmpDup->DataStride()>>2)*(KHeight+KBigger);
+ maskPattern=0x55555555;
+ for (TInt fillIndex=0;fillIndex<newMaskLength;fillIndex++)
+ {
+ maskDataDup[fillIndex]=maskPattern;
+ }
+
+ //compare the results of blitting using this new mask using each of the two handles to the same mask
+
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepDupDiffAfterRefill2),sourceBmp,TSize(KWidth,KHeight),maskBmpDup,EFalse);
+ //This blit should not crash, even if the defect is present because the previous sized bitmap should not be released until all references have been updated.
+ //If it does crash then this demonstrates the defect in that the original address is being used in error and has been freed and paged out
+ bmpContext->BitBltMasked(TPoint(0,KHeight*EStepOriginalDiffAfterRefill2),sourceBmp,TSize(KWidth,KHeight),maskBmp,EFalse);
+
+ //If this cmp fails: data change had no effect for duplicate handle (very unexpected)
+ TEST(0!=Mem::Compare((TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill2),targetCopySize*4));
+
+ //Check that the result of both blits is the same.
+ //If this cmp fails: defect is demonstrated. This is the main defect demonstration test.
+ TEST(0==Mem::Compare((TUint8*)(targetData+targetCopySize*EStepDupDiffAfterRefill2),targetCopySize*4,(TUint8*)(targetData+targetCopySize*EStepOriginalDiffAfterRefill2),targetCopySize*4));
+
+
+ CleanupStack::PopAndDestroy(pushcount,targetBmp);
+ }
+
+ /**
+ * @SYMTestCaseID GRAPHICS-BITGDI-0097
+ *
+ * @SYMDEF DEF115395
+ *
+ * @SYMTestCaseDesc Robustness in the CFbsBitGc::DrawBitmap & CFbsBitGc::DrawBitmapMasked functions:
+ * when a sourceRect is used to capture only a part of the bitmap,
+ * we have to make sure that the sourceRect is not out of border of the image!
+ * (if it's the case, we just draw nothing)
+ *
+ * @SYMTestPriority Normal
+ *
+ * @SYMTestStatus Implemented
+ *
+ * @SYMTestActions We create a 8x8 KRgbRed Bitmap and 8x8 Mask (color TRgb(30, 30, 30))
+ * We try the 2 functions CFbsBitGc::DrawBitmap and CFbsBitGc::DrawBitmapMasked
+ * with a out of bounds source rectangle on a white output image.
+ * The output should stay all white.
+ *
+ */
+void CTDefect2::DEF115395L()
+ {
+ const TSize size=TSize(8, 8);
+ const TPoint origin=TPoint(0, 0);
+ const TPoint vector=TPoint(2, 2);
+ const TRect destRect=TRect(origin, size);
+ const TRect srcRect=TRect(origin-vector, size);
+ const TBool invertMask=EFalse;
+ const TRgb maskColor=TRgb(30, 30, 30);
+ TBool succeed=ETrue;
+
+ // Bitmap creation
+ CFbsBitmap* myBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(myBmp);
+ User::LeaveIfError(myBmp->Create(size, EColor16MU));
+ CFbsBitmapDevice* bmpDevice=CFbsBitmapDevice::NewL(myBmp);
+ CleanupStack::PushL(bmpDevice);
+ CBitmapContext* bmpContext;
+ User::LeaveIfError(bmpDevice->CreateBitmapContext(bmpContext));
+ CleanupStack::PushL(bmpContext);
+ bmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmpContext->SetBrushColor(KRgbRed);
+ bmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, bmpDevice); // bmpContext, bmpDevice
+
+ // Mask creation
+ CFbsBitmap* myMaskBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(myMaskBmp);
+ User::LeaveIfError(myMaskBmp->Create(size, EGray256));
+ bmpDevice = CFbsBitmapDevice::NewL(myMaskBmp);
+ CleanupStack::PushL(bmpDevice);
+ User::LeaveIfError(bmpDevice->CreateBitmapContext(bmpContext));
+ CleanupStack::PushL(bmpContext);
+ bmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmpContext->SetBrushColor(maskColor);
+ bmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, bmpDevice); // bmpContext, bmpDevice
+
+ // Output Image
+ CFbsBitmap* outputImg=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(outputImg);
+ User::LeaveIfError(outputImg->Create(size, EColor16MU));
+ bmpDevice = CFbsBitmapDevice::NewL(outputImg);
+ CleanupStack::PushL(bmpDevice);
+ User::LeaveIfError(bmpDevice->CreateBitmapContext(bmpContext));
+ CleanupStack::PushL(bmpContext);
+ bmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ bmpContext->SetBrushColor(KRgbWhite);
+ bmpContext->Clear();
+
+ bmpContext->DrawBitmapMasked(destRect, myBmp, srcRect, myMaskBmp, invertMask);
+ TRgb pixelColor;
+ TInt ii,jj;
+ for (ii=0;ii<=size.iWidth;ii++)
+ {
+ for (jj=0;jj<=size.iHeight;jj++)
+ {
+ outputImg->GetPixel(pixelColor, TPoint(ii,jj));
+ if (pixelColor!=KRgbWhite)
+ {
+ succeed=EFalse;
+ break;
+ }
+ }
+ if (!succeed)
+ {
+ break;
+ }
+ }
+
+ bmpContext->Clear();
+ bmpContext->DrawBitmap(destRect, myBmp, srcRect);
+ for (ii=0;ii<=size.iWidth;ii++)
+ {
+ for (jj=0;jj<=size.iHeight;jj++)
+ {
+ outputImg->GetPixel(pixelColor, TPoint(ii,jj));
+ if (pixelColor!=KRgbWhite)
+ {
+ succeed=EFalse;
+ break;
+ }
+ }
+ if (!succeed)
+ {
+ break;
+ }
+ }
+
+ TEST(succeed);
+ CleanupStack::PopAndDestroy(5);
+}
+
+/**
+ @SYMDEF PDEF141192, INC140310
+
+ @SYMTestCaseDesc Test that the alpha merge method CFbsBitGc::DrawBitmapMasked() works accurately.
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Create an alpha capable bitmap and throw sample values at the merge function
+
+ @SYMTestExpectedResults
+ 1a) The merge resultant alpha values do not wrap through 256
+ 1b) The merge resultant alpha values closely match an equivalent floating-point calculation
+ 2a) The merge resultant colours do not wrap through 256
+ 2b) The merge resultant colours do not exceed the resultant alpha if premultiplied output is expected
+ 2c) The merge resultant colours closely match an equivalent floating-point calculation
+ 2d) The other resultant colour values are not affected (stay black)
+
+ @param aChannelControl which channel is controlled (0=red, 1= green, 2=blue)
+
+ The input tested format is EColor64K, but could easily be changesd to test other formats.
+ The input mask is EGray256. If optimised internally, this could be changed to EGray16.
+ The tested output format is EColor16MAP. This should not be changed.
+
+ This test is an optimised version of CTDefect2::TestMaskForAllCombinationL(TInt aChannelControl)
+*/
+void CTDefect2::TestMaskForSelectedValuesL(TInt aChannelControl)
+ {
+ const TSize size=TSize(1, 1);
+
+ // Bitmap creation
+ CFbsBitmap* srcBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(srcBmp);
+ User::LeaveIfError(srcBmp->Create(size, EColor64K));
+ CFbsBitmapDevice* sourceBmpDevice=CFbsBitmapDevice::NewL(srcBmp);
+ CleanupStack::PushL(sourceBmpDevice);
+ CBitmapContext* sourceBmpContext;
+ User::LeaveIfError(sourceBmpDevice->CreateBitmapContext(sourceBmpContext));
+ CleanupStack::PushL(sourceBmpContext);
+ sourceBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ sourceBmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, sourceBmpDevice); // sourceBmpContext, sourceBmpDevice
+
+ // Mask creation
+ CFbsBitmap* maskBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(maskBmp);
+ User::LeaveIfError(maskBmp->Create(size, EGray256));
+ CFbsBitmapDevice* maskBmpDevice=CFbsBitmapDevice::NewL(maskBmp);
+ CleanupStack::PushL(maskBmpDevice);
+ CBitmapContext* maskBmpContext;
+ User::LeaveIfError(maskBmpDevice->CreateBitmapContext(maskBmpContext));
+ CleanupStack::PushL(maskBmpContext);
+ maskBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ maskBmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, maskBmpDevice); // maskBmpContext, maskBmpDevice
+
+ // Target Bitmap
+ CFbsBitmap* targetBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(targetBmp);
+ User::LeaveIfError(targetBmp->Create(size, EColor16MAP));
+ CFbsBitmapDevice* targetBmpDevice=CFbsBitmapDevice::NewL(targetBmp);
+ CleanupStack::PushL(targetBmpDevice);
+ CBitmapContext* targetBmpContext;
+ User::LeaveIfError(targetBmpDevice->CreateBitmapContext(targetBmpContext));
+ CleanupStack::PushL(targetBmpContext);
+ targetBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ targetBmpContext->Clear();
+
+ TSize screenSize = targetBmpDevice->SizeInPixels();
+
+ TInt channelMask;
+ TInt channelMul;
+
+ if (aChannelControl<1)
+ {
+ channelMask=0xFF0000;
+ }
+ else
+ {
+ if(aChannelControl==1)
+ {
+ channelMask=0x00FF00;
+ }
+ else
+ {
+ channelMask=0x0000FF;
+ }
+ }
+ channelMul=channelMask&0x01010101;
+ TInt previousTargetMask = -1;
+ const TInt otherMask=0xFFFFFF^channelMask;
+
+ for (TInt targetMask=0;targetMask<256;targetMask++)
+ {
+ //bkgrdChannel is background channel input value.
+ for (TInt targetChannel=0;targetChannel<=targetMask;targetChannel++)
+ {
+ if(targetChannel>(targetMask-10)) // Optimise the loop to test values specific for this defect
+ {
+ TInt failsPerPass=10;
+
+ //srcMask is the source mask/alpha
+ for (TInt srcMask=0;srcMask<256;srcMask++)
+ {
+ if((srcMask<=10)||(srcMask>=250)) // Optimise the loop to test values specific for this defect
+ {
+ TReal step;
+ if (aChannelControl == 1)
+ {
+ step = 255.0/63; // Only for blue channel for EColor64K source colour
+ }
+ else
+ {
+ step = 255.0/31;
+ }
+ TReal srcChannelReal = 0.0;
+ for (TInt srcChannel=0;srcChannel<256;srcChannel=(TInt)srcChannelReal)
+ {
+ if (targetMask != previousTargetMask)
+ {
+ //uncomment it to print log for each targetMask loop
+ //INFO_PRINTF2(_L("Processing source colours for targetMask=%i"),targetMask);
+ previousTargetMask = targetMask;
+ }
+ srcChannelReal += step;
+
+ //test blending of one-pixel bitmap
+ DoMaskTestL(srcChannel, srcMask, targetMask, targetChannel, aChannelControl, srcBmp, maskBmp, targetBmp, targetBmpContext);
+
+ TBuf8<4> readBuffer;
+ TUint* readPixel = (TUint*)readBuffer.Ptr();
+ targetBmp->GetScanLine(readBuffer, TPoint(0, 0), 1, EColor16MAP);
+
+ //channelPixelValue is the channel pixel value as generated from the library code under test
+ TUint channelPixelValue=((*readPixel)&channelMask)/channelMul;
+ //alphaPixelValue is the alpha pixel value as generated from the library code under test
+ TUint alphaPixelValue = (*readPixel)>>24;
+
+ //check if channelPixelValue and alphaPixelValue match the expected ones
+ CheckValues(alphaPixelValue, channelPixelValue, failsPerPass, targetMask, targetChannel, srcMask, srcChannel, otherMask, readPixel);
+ }
+ }
+ }
+ if (failsPerPass<0)
+ { //note that this count may be out by 1...
+ INFO_PRINTF2(_L("Additional %i errors not reported in this pass."),-failsPerPass);
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(5);
+ }
+
+void CTDefect2::CheckValues(TUint aAlphaPixelValue, TUint aChannelPixelValue, TInt& aFailsPerPass, TInt aTargetMask, TInt aTargetChannel, TInt aSrcMask, TInt aSrcChannel, TInt aOtherMask, TUint* aReadPixel)
+ {
+ const TReal KGross=1.95;
+ TReal srcMultiplier;
+ TReal alphaOutputValue;
+ //source multiplier factor for alpha that can then be used to optimise non-multiplied input calculations.
+ srcMultiplier=aSrcMask/255.0;
+ //destination/background multiplier factor for alpha that can then be used to optimise non-multiplied input calculations.
+ TReal destMultiplier=(aTargetMask/255.0)*(1.0-srcMultiplier);
+ //alphaOutputValue is a floating-point calculation of the alpha output value using 255.0 as the scaling factor.
+ alphaOutputValue=(srcMultiplier+destMultiplier)*255.0;
+
+ //alphaDiff is the difference in alpha between pixel and float calcuation, i.e. the error. This can be less than 1 level of brightness, i.e. insignificant.
+ TReal alphaDiff=0.0;
+ alphaDiff=alphaOutputValue-aAlphaPixelValue;
+ if (alphaDiff>KGross || alphaDiff<-KGross)
+ {
+ if (--aFailsPerPass>0)
+ {
+ LogColourEvent(aTargetMask,aTargetChannel,aSrcMask,-1,alphaOutputValue,aAlphaPixelValue,alphaDiff,_L("Big Alpha error: expected %f, got %f"),ETrue);
+ }
+ }
+ //channelOutputValue is a floating-point calculation of the channel output value using 255.0 as the scaling factor.
+ TReal channelOutputValue=aSrcChannel*srcMultiplier;
+ channelOutputValue+=aTargetChannel*(1.0-srcMultiplier);
+
+ if (aChannelPixelValue>aAlphaPixelValue)
+ {
+ if (--aFailsPerPass>0)
+ {
+ LogColourEvent(aTargetMask,aTargetChannel,aSrcMask,aSrcChannel,aAlphaPixelValue,channelOutputValue,aChannelPixelValue,_L("Output multiplied colour exceeds alpha %f: expected %f got %f"),EFalse);
+ INFO_PRINTF1(_L("channelPixelValue>alphaPixelValue"));
+ }
+ }
+
+ if((aOtherMask&(*aReadPixel))!=0)
+ {
+ if (--aFailsPerPass>0)
+ {
+ LogColourEvent(aTargetMask,aTargetChannel,aSrcMask,aSrcChannel,aAlphaPixelValue,channelOutputValue,aChannelPixelValue,_L("Other colours damaged - NOT Zero"),EFalse);
+ }
+ }
+
+ //channelDiff is the difference in channel between pixel and float calcuation, i.e. the error. This can be less than 1 level of brightness, i.e. insignificant.
+ TReal channelDiff=channelOutputValue-aChannelPixelValue;
+
+ if (channelDiff>KGross || channelDiff<-KGross)
+ {
+ if (--aFailsPerPass>0)
+ {
+ LogColourEvent(aTargetMask,aTargetChannel,aSrcMask,aSrcChannel,channelOutputValue,aChannelPixelValue,channelDiff,_L("Big Colour error: expected %f, got %f"),EFalse);
+ }
+ }
+ }
+
+/**
+Test of Blending function DrawBitmapMasked().
+@param aSrcChannel source channel
+@param aSrcMask source mask
+@param aTargetMask target mask
+@param aTargetChannel target channel
+@param aChannelControl which channel is controlled (0=red, 1= green, 2=blue)
+@param aSrcBmp source bitmap
+@param aMaskBmp mask bitmap
+@param aTargetBmp target bitmap
+@param aTargetBmpContext gc for target bitmap
+**/
+void CTDefect2::DoMaskTestL(TInt aSrcChannel, TInt aSrcMask, TInt aTargetMask, TInt aTargetChannel, TInt aChannelControl,
+ CFbsBitmap* aSrcBmp, CFbsBitmap* aMaskBmp, CFbsBitmap* aTargetBmp, CBitmapContext* aTargetBmpContext)
+ {
+ const TSize size=TSize(1, 1);
+ const TRect destRect=TRect(size);
+ const TRect srcRect=TRect(size);
+
+ const TInt scanLineLengthEColor16MAP = CFbsBitmap::ScanLineLength(1, EColor16MAP);
+ HBufC8* targetBuffer = HBufC8::NewL(scanLineLengthEColor16MAP);
+ CleanupStack::PushL(targetBuffer);
+ TPtr8 targetDes = targetBuffer->Des();
+ targetDes.SetLength(scanLineLengthEColor16MAP);
+ TUint32* targetP = (TUint32*)targetDes.Ptr();
+ TRgb targetColour(0, 0);
+ if (aChannelControl<1)
+ {
+ targetColour.SetRed(aTargetChannel);
+ }
+ else
+ {
+ if (aChannelControl==1)
+ {
+ targetColour.SetGreen(aTargetChannel);
+ }
+ else
+ {
+ targetColour.SetBlue(aTargetChannel);
+ }
+ }
+ targetColour.SetAlpha(aTargetMask);
+ *targetP = targetColour.Internal();
+ aTargetBmp->SetScanLine(targetDes, 0);
+
+ const TInt scanLineLengthEGray256 = CFbsBitmap::ScanLineLength(1, EGray256);
+ HBufC8* maskBuffer = HBufC8::NewL(scanLineLengthEGray256);
+ CleanupStack::PushL(maskBuffer);
+ TPtr8 maskDes = maskBuffer->Des();
+ maskDes.SetLength(scanLineLengthEGray256);
+ TUint8* maskP = (TUint8*)maskDes.Ptr();
+ *maskP = aSrcMask;
+ aMaskBmp->SetScanLine(maskDes, 0);
+
+ const TInt scanLineLengthEColor64K = CFbsBitmap::ScanLineLength(1, EColor64K);
+ HBufC8* srcBuffer = HBufC8::NewL(scanLineLengthEColor64K);
+ CleanupStack::PushL(srcBuffer);
+ TPtr8 srcDes = srcBuffer->Des();
+ srcDes.SetLength(scanLineLengthEColor64K);
+ TUint16* srcP = (TUint16*)srcDes.Ptr();
+ TRgb srcColour(0);
+ if (aChannelControl<1)
+ {
+ srcColour.SetRed(aSrcChannel);
+ }
+ else
+ {
+ if (aChannelControl==1)
+ {
+ srcColour.SetGreen(aSrcChannel);
+ }
+ else
+ {
+ srcColour.SetBlue(aSrcChannel);
+ }
+ }
+
+ *srcP = srcColour.Color64K();
+ aSrcBmp->SetScanLine(srcDes, 0);
+ aTargetBmpContext->DrawBitmapMasked(destRect, aSrcBmp, srcRect, aMaskBmp, EFalse);
+
+ CleanupStack::PopAndDestroy(3);
+ }
+
+/**
+ @SYMDEF PDEF141192, INC140310
+
+ @SYMTestCaseDesc Test that the alpha merge method CFbsBitGc::DrawBitmapMasked() works accurately.
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Create an alpha capable bitmap and throw sample values at the merge function
+
+ @SYMTestExpectedResults
+ 1a) The merge resultant alpha values do not wrap through 256
+ 1b) The merge resultant alpha values closely match an equivalent floating-point calculation
+ 2a) The merge resultant colours do not wrap through 256
+ 2b) The merge resultant colours do not exceed the resultant alpha if premultiplied output is expected
+ 2c) The merge resultant colours closely match an equivalent floating-point calculation
+ 2d) The other resultant colour values are not affected (stay black)
+ @param aChannelControl which channel is controlled (0=red, 1= green, 2=blue)
+
+ The input tested format is EColor64K, but could easily be changesd to test other formats.
+ The input mask is EGray256. If optimised internally, this could be changed to EGray16.
+ The tested output format is EColor16MAP. This should not be changed.
+
+ This test takes up to 40 minutes to run per channel control. Therefore, it is only kept for local reference, not scheduled for ONB.
+ An optimised version CTDefect2::TestMaskForSelectedValuesL(TInt aChannelControl) is run instead for selected combinations of channel and mask values.
+*/
+void CTDefect2::TestMaskForAllCombinationL(TInt aChannelControl)
+ {
+ const TSize size=TSize(1, 1);
+
+ // Bitmap creation
+ CFbsBitmap* srcBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(srcBmp);
+ User::LeaveIfError(srcBmp->Create(size, EColor64K));
+ CFbsBitmapDevice* sourceBmpDevice=CFbsBitmapDevice::NewL(srcBmp);
+ CleanupStack::PushL(sourceBmpDevice);
+ CBitmapContext* sourceBmpContext;
+ User::LeaveIfError(sourceBmpDevice->CreateBitmapContext(sourceBmpContext));
+ CleanupStack::PushL(sourceBmpContext);
+ sourceBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ sourceBmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, sourceBmpDevice); // sourceBmpContext, sourceBmpDevice
+
+ // Mask creation
+ CFbsBitmap* maskBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(maskBmp);
+ User::LeaveIfError(maskBmp->Create(size, EGray256));
+ CFbsBitmapDevice* maskBmpDevice=CFbsBitmapDevice::NewL(maskBmp);
+ CleanupStack::PushL(maskBmpDevice);
+ CBitmapContext* maskBmpContext;
+ User::LeaveIfError(maskBmpDevice->CreateBitmapContext(maskBmpContext));
+ CleanupStack::PushL(maskBmpContext);
+ maskBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ maskBmpContext->Clear();
+ CleanupStack::PopAndDestroy(2, maskBmpDevice); // maskBmpContext, maskBmpDevice
+
+ // Target Bitmap
+ CFbsBitmap* targetBmp=new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(targetBmp);
+ User::LeaveIfError(targetBmp->Create(size, EColor16MAP));
+ CFbsBitmapDevice* targetBmpDevice=CFbsBitmapDevice::NewL(targetBmp);
+ CleanupStack::PushL(targetBmpDevice);
+ CBitmapContext* targetBmpContext;
+ User::LeaveIfError(targetBmpDevice->CreateBitmapContext(targetBmpContext));
+ CleanupStack::PushL(targetBmpContext);
+ targetBmpContext->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ targetBmpContext->Clear();
+
+ TSize screenSize = targetBmpDevice->SizeInPixels();
+
+ TInt channelMask;
+ TInt channelMul;
+
+ if (aChannelControl<1)
+ {
+ channelMask=0xFF0000;
+ }
+ else
+ {
+ if(aChannelControl==1)
+ {
+ channelMask=0x00FF00;
+ }
+ else
+ {
+ channelMask=0x0000FF;
+ }
+ }
+ channelMul=channelMask&0x01010101;
+ TInt previousTargetMask = -1;
+ const TInt otherMask=0xFFFFFF^channelMask;
+
+ for (TInt targetMask=0;targetMask<256;targetMask++)
+ {
+ //bkgrdChannel is background channel input value.
+ for (TInt targetChannel=0;targetChannel<=targetMask;targetChannel++)
+ {
+ TInt failsPerPass=10;
+
+ //srcMask is the source mask/alpha
+ for (TInt srcMask=0;srcMask<256;srcMask++)
+ {
+ TReal step;
+ if (aChannelControl == 1)
+ {
+ step = 255.0/63; // Only for blue channel for EColor64K source colour
+ }
+ else
+ {
+ step = 255.0/31;
+ }
+ TReal srcChannelReal = 0.0;
+
+ for (TInt srcChannel=0;srcChannel<256;srcChannel=(TInt)srcChannelReal)
+ {
+ if (targetMask != previousTargetMask)
+ {
+ INFO_PRINTF2(_L("Processing source colours for targetMask=%i"),targetMask);
+ previousTargetMask = targetMask;
+ }
+ srcChannelReal += step;
+
+ //test blending of one-pixel bitmap
+ DoMaskTestL(srcChannel, srcMask, targetMask, targetChannel, aChannelControl, srcBmp, maskBmp, targetBmp, targetBmpContext);
+
+ TBuf8<4> readBuffer;
+ TUint* readPixel = (TUint*)readBuffer.Ptr();
+ targetBmp->GetScanLine(readBuffer, TPoint(0, 0), 1, EColor16MAP);
+
+ //channelPixelValue is the channel pixel value as generated from the library code under test
+ TUint channelPixelValue=((*readPixel)&channelMask)/channelMul;
+ //alphaPixelValue is the alpha pixel value as generated from the library code under test
+ TUint alphaPixelValue = (*readPixel)>>24;
+
+ //check if channelPixelValue and alphaPixelValue match the expected ones
+ CheckValues(alphaPixelValue, channelPixelValue, failsPerPass, targetMask, targetChannel, srcMask, srcChannel, otherMask, readPixel);
+
+ if (failsPerPass<0)
+ { //note that this count may be out by 1...
+ INFO_PRINTF2(_L("Additional %i errors not reported in this pass."),-failsPerPass);
+ }
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(5);
+ }
+
+/**
+This function is used to write to the log file
+@param aNonPreMulDestPixColor non pre multiplied destination pixel colour
+@param aPreMulSrcPixelColor pre multiplied source pixel colour
+@param aNonPreMulSrcPixelColor non pre multiplied source pixel colour
+@param aVal1 it contains the value of the first variable of the message to be displayed
+@param aVal2 it contains the value of the second variable of the message to be displayed
+@param aVal3 it contains the value of the third variable of the message to be displayed
+@param aMsg it contains the message to be printed to the log file
+@param aErr if true then the test case fails, if false test passes. log is printed in both the case. TEST does not abort, just reports test case failure
+*/
+void CTDefect2::LogColourEvent(TInt aPreMulDestPixColor,TInt aNonPreMulDestPixColor,TInt aPreMulSrcPixelColor,TInt aNonPreMulSrcPixelColor,TReal aVal1,TReal aVal2,TReal aVal3,TRefByValue<const TDesC> aMsg,TBool aErr)
+ {
+ TEST(aErr==EFalse); // if aErr=True, then the previous test step failed.
+ INFO_PRINTF4(aMsg,aVal1,aVal2,aVal3);
+ if (aNonPreMulSrcPixelColor<0)
+ {
+ INFO_PRINTF4(_L("Processing source colours for MDest=%i, CDest=%i, MSrc=%i"),aPreMulDestPixColor,aNonPreMulDestPixColor,aPreMulSrcPixelColor);
+ }
+ else
+ {
+ INFO_PRINTF5(_L("Processing colour set MDest=%i, CDest=%i, MSrc=%i, CSrc=%i"),aPreMulDestPixColor,aNonPreMulDestPixColor,aPreMulSrcPixelColor,aNonPreMulSrcPixelColor);
+ }
+ }
+
+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);
+ }
+ TInt leaveErr = RFbsSession::Connect();
+ if (leaveErr != KErrNone)
+ {
+ thisThis->iExitHow = ELeave;
+ thisThis->iExitCode = leaveErr;
+ return leaveErr;
+ }
+ thisThis->iExitHow=thisThis->ERunning;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ TInt returnErr=KErrNone;
+ TRAP(leaveErr, returnErr = thisThis->ThreadFunctionL());
+ if (leaveErr)
+ {
+ thisThis->iExitHow=ELeave;
+ thisThis->iExitCode=leaveErr;
+ delete cleanup;
+ RFbsSession::Disconnect();
+ return leaveErr;
+ }
+ else
+ {
+ thisThis->iExitHow=EReturn;
+ thisThis->iExitCode=returnErr;
+ delete cleanup;
+ RFbsSession::Disconnect();
+ 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 -iExitHow*100;
+ }
+ }
+ }
+/*
+ * 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;
+ }
+
+/** This thread verifies the function of CopyRect
+ A series of operations are performed on the given bitmap.
+ If the operation panics the launcher is able to retrieve the parameters that caused the panic and report
+ The FailOffset() returned index indicates the offset from the start at which the memory access caused a panic.
+ **/
+class TTestCopyRectThread:public TFunctionThread
+ {
+public:
+ TTestCopyRectThread(CFbsBitGc* aBitmapContext,TInt aStartX,TInt aStopX,TInt aY1,TInt aY2,TPoint aOffset);
+private:
+ virtual TInt ThreadFunctionL();
+private:
+ CFbsBitGc* iBitmapContext;
+ TInt iStartX;
+ TInt iStopX;
+ TInt iY1;
+ TInt iY2;
+ TPoint iOffset;
+public:
+ volatile TInt iCurrX;
+ volatile TInt iCurrWidth;
+
+ };
+
+TTestCopyRectThread::TTestCopyRectThread(CFbsBitGc* aBitmapContext,TInt aStartX,TInt aStopX,TInt aY1,TInt aY2,TPoint aOffset):
+ iBitmapContext(aBitmapContext),
+ iStartX(aStartX),
+ iStopX(aStopX),
+ iY1(aY1),
+ iY2(aY2),
+ iOffset(aOffset)
+ {
+ LaunchThreadFunction(_L("CopyRectTest"));
+ }
+TInt TTestCopyRectThread::ThreadFunctionL()
+ {
+ for (iCurrX=iStartX;iCurrX<iStopX;iCurrX++)
+ {
+ for (iCurrWidth=iStopX-iCurrX;iCurrWidth>0;iCurrWidth--)
+ {
+ iBitmapContext->CopyRect(iOffset,TRect(iCurrX,iY1,iCurrX+iCurrWidth,iY2));
+ }
+ }
+ return KErrNone;
+}
+
+class CTestExecuteLogger;
+
+struct WrapCTestExecuteLogger
+ {
+ WrapCTestExecuteLogger(): iLogger(NULL) {}
+ WrapCTestExecuteLogger(CTestExecuteLogger&aLogger): iLogger(&aLogger) {}
+ WrapCTestExecuteLogger(CTestExecuteLogger*aLogger): iLogger(aLogger) {}
+
+ operator int() {return (iLogger!=NULL);}
+ CTestExecuteLogger& operator()() { return *iLogger; }
+
+ CTestExecuteLogger* iLogger;
+
+ };
+static const TInt KCopyTestHeight=20;
+static const TInt KCopyTestWidth=256; //should be some multiple of 32...
+/** Compares the pixels in the source rectangle and its copy.
+ * The copy is at an offset from the source.
+ * The compare is not complete as this was found to be too slow.
+ * Instead only a few pixels on the left and right edges are compared.
+ *
+ **/
+TBool CmpBitmapRectL(CFbsBitmap& aTestBitmap,TRect aSource,TPoint aTrgOffset,WrapCTestExecuteLogger Logger=NULL,TBool aExpectedPass=EFalse)
+ {
+ //Comparing all the pixels in a large rectangle using GetPixel() is too slow.
+ //So now, only a few pixels on the edges of the rectangle are compared,
+ //and the ones in between are skipped.
+ //Using any faster method to get the pixels is dubious
+ //as it it may ultimately use GetLine, which is the method under test...
+ const TInt processSize=6;
+ TBool returnState=ETrue;
+ TUint16 printcompareresultbuffers[KCopyTestHeight][2][processSize*2+1]={{{0}}};
+ TInt resultRow=KCopyTestHeight-aSource.Height();
+ TInt skipMiddleStart=aSource.iTl.iX+processSize;
+ TInt skipMiddleEnd=aSource.iBr.iX-processSize-1;
+ if (skipMiddleStart>=skipMiddleEnd)
+ {
+ skipMiddleStart+=processSize+processSize; //make skip irrelivent
+ }
+ //verify inputs valid
+ TRect bitmapRect=aTestBitmap.SizeInPixels();
+ TRect sourceRectIntersect=aSource;
+ TRect targetRect=aSource;
+ targetRect.Move(aTrgOffset);
+ TRect targetRectIntersect=targetRect;
+ targetRectIntersect.Intersection(bitmapRect);
+ sourceRectIntersect.Intersection(bitmapRect);
+ ASSERT(sourceRectIntersect==aSource);
+ ASSERT(targetRectIntersect==targetRect);
+
+ for (TInt sy=aSource.iTl.iY;sy<aSource.iBr.iY;sy++)
+ {
+ TInt resultCol=0;
+ for (TInt sx=aSource.iTl.iX;sx<aSource.iBr.iX;sx++)
+ {
+ if (sx==skipMiddleStart)
+ {
+ sx=skipMiddleEnd;
+ }
+ else
+ {
+ TRgb sourceColor;
+ aTestBitmap.GetPixel(sourceColor,TPoint(sx,sy));
+ TRgb targetColor;
+ aTestBitmap.GetPixel(targetColor,TPoint(sx,sy)+aTrgOffset);
+ if (sourceColor!=targetColor)
+ {
+ if (Logger)
+ {
+ returnState=EFalse;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+ if (Logger&&resultRow>=0)
+ {
+ printcompareresultbuffers[resultRow][0][resultCol]=L'@'+sourceColor.Color16();
+ printcompareresultbuffers[resultRow][1][resultCol]=L'@'+targetColor.Color16();
+ }
+ }
+
+ }
+ resultRow++;
+ }
+ if (Logger && returnState!=aExpectedPass)
+ {
+ INFO_PRINTF4(_L("Case: srcx=%i targx=%i width=%i result compare has failed! Content dump follows: [src] [trg] "),
+ aSource.iTl.iX,targetRect.iTl.iX,aSource.Width());
+ for (TInt row=(KCopyTestHeight-aSource.Height()>0)?KCopyTestHeight-aSource.Height():0;row<KCopyTestHeight;row++)
+ {
+ INFO_PRINTF5(_L("Row: %2i %s %s (%s)"),
+ row,printcompareresultbuffers[row][0],printcompareresultbuffers[row][1],
+ Mem::Compare(printcompareresultbuffers[row][0],processSize*2,printcompareresultbuffers[row][1],processSize*2)
+ ?L"differ":L"same"
+ );
+
+ }
+ }
+ return returnState;
+ }
+
+/**
+ * @SYMTestCaseID GRAPHICS-BITGDI-0099
+ *
+ * @SYMDEF INC119063, pdef120353
+ *
+ * @SYMTestCaseDesc CopyRect could read bytes past the end of the source bitmap
+ * This is a general test of the rewrite of CopyRect
+ * Note that this test says well within the boundaries of the bitmap,
+ * and does not test the exception condition detected in the defect.
+ * @SYMTestPriority Normal
+ *
+ * @SYMTestStatus Implemented
+ *
+ * @SYMTestActions
+ * Repeat the test for 4 affected bitmap resolutions: Gray2, Gray4, Gray16, Color16
+ * Allocate a bitmap big enough to process the test
+ * Repeat:
+ * Fill the whole image with random data
+ * Pixel compare the source rectangle wiith the target rectangle
+ * - they should NOT be identical - very unlucky!
+ * Pixel compare the left and right edge pixels outside the copy rect
+ * - these should not be all identical - very unlucky!
+ * Copyrect a region from the bottom half to the top half (not to edges)
+ * Pixel compare the source rectangle wiith the target rectangle
+ * - they should be identical - copy was successful
+ * Pixel compare the left and right edge pixels outside the copy rect
+ * - these should not be all identical - or too much was copied
+ * Repeat for values of target x 0 to 32
+ * Repeat for values of source x 0 to 32
+ * Repeat for values of source/target width 1 to 96
+ * Guess: 4x32x32x96 tests=400000 iterations
+*/
+void CTDefect2::ExerciseCopyRect()
+ {
+ for (TInt mode=1;mode<EColorLast;mode++)
+ {
+ CFbsBitmap testBitmap;
+
+ //The exact dimensions of this bitmap are not important...
+ //The width should ensure that the range of tests work (max 32+32+96=160 pixels)
+ //The height should be enough to ensure there is enough variability in the random data
+ //Note that the smallest data used in a uniqueness test is a 1-pixel-width column half the height of the image.
+ //The whole height will be used if this is changed.
+ if (testBitmap.Create(TSize(KCopyTestWidth,KCopyTestHeight*2),TDisplayMode(mode))<KErrNone)
+ {
+ continue; //some mode numbers are bad!
+ }
+
+
+ SEpocBitmapHeader header1 = testBitmap.Header();
+ //We could run this test for other modes, but the defect and fix only applies to low bit depths
+ if (header1.iBitsPerPixel>4)
+ {
+ continue;
+ }
+ INFO_PRINTF3(_L("Bitmap color depth: %i bits. Color flag: %i"),header1.iBitsPerPixel,header1.iColor);
+
+
+ TUint32* bitmapData=testBitmap.DataAddress();
+ TUint32* pastBitmapData=bitmapData+((header1.iBitmapSize-header1.iStructSize)>>2);
+
+ TInt splitHeight=header1.iSizeInPixels.iHeight/2;
+
+ CFbsBitGc* bitmapContext = NULL;
+ CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(&testBitmap);
+ CleanupStack::PushL(bitmapDevice);
+ User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
+ CleanupStack::PushL(bitmapContext);
+ TInt skippedCases=0;
+ TInt totalCases=0;
+ //These counts have been tweaked based on knowledge of the algorithm.
+ //The target position is shifted in bits by up to 1 word (32 bits)
+ //Bigger changes than this just change the target pointer and modulo the shift.
+ //[I don't think that the target position influences the result, but it might]
+ //The source position is shifted in bits by up to 1 word (32 bits)
+ //Bigger changes than this just change the source pointer and modulo the shift.
+ //The copy width is made up of a copy words element and a remainder bytes element.
+ //The difference in shift element between source and target is used to shift the
+ //source to a temporary buffer.
+ //So the copy width element is also influenced by the source position and target position.
+ //Testing 96 possible bit widths should exercise it for zero and non-zero word counts adequately.
+ const TInt
+ KTargXMin=32,
+ KTargXMax=32+32/header1.iBitsPerPixel,
+ KSrcXMin=32,
+ KSrcXMax=32+32/header1.iBitsPerPixel,
+ KWidthMin=1,
+ KWidthMax=96/header1.iBitsPerPixel;
+ for (TInt targx=KTargXMin;targx<KTargXMax;targx++)
+ {
+ for (TInt srcx=KSrcXMin;srcx<KSrcXMax;srcx++)
+ {
+ for (TInt width=KWidthMin;width<KWidthMax;width++)
+ {
+ totalCases++;
+ TInt offsetx=targx-srcx;
+ //fill the buffer with random data
+ TInt64 randomSeed=MAKE_TINT64(0xdeadbeef,0xbaadf00d);
+ Math::Rand(randomSeed);
+ TInt maxRetries=3;
+ TInt rndCount=0;
+ while (--maxRetries>=0)
+ {
+ for (TUint32* fillData=bitmapData;fillData!=pastBitmapData;fillData++)
+ {
+ rndCount++;
+ //Rand only sets 31 bits of the integer - no negative values - no top bit set!
+ //This solution wastes some of the seed, but it should still produce valid results.
+ TInt rnd=Math::Rand(randomSeed)^(Math::Rand(randomSeed)<<8);
+ *fillData=rnd;
+ }
+ TInt colOffSrc=0;
+ TInt colOffTrg=0;
+ //verify that the data is different inside the copy area and outside each copy area
+ if (TInt failCode= CmpBitmapRectL(testBitmap,TRect(srcx,splitHeight,srcx+width,splitHeight*2),TPoint(offsetx,-splitHeight))
+ + 2*CmpBitmapRectL(testBitmap,TRect(srcx-1,splitHeight,srcx,splitHeight*2),TPoint(offsetx,-splitHeight))
+ + 4*CmpBitmapRectL(testBitmap,TRect(srcx+width,splitHeight,srcx+width+1,splitHeight*2),TPoint(offsetx,-splitHeight))
+ )
+ {
+ //OK.. need to find another pair of bits where the source and target columns are non-identical
+ INFO_PRINTF5(_L("First random data failed... (code %i) Trying alternale columns: srcx=%i targx=%i width=%i"),failCode,srcx,targx,width);
+ for (TInt tryOffSrc=0;tryOffSrc+srcx<KCopyTestWidth-(KWidthMax+1) && (colOffSrc==0&&colOffTrg==0);tryOffSrc+=32)
+ for (TInt tryOffTrg=0;tryOffTrg+targx<KCopyTestWidth-(KWidthMax+1) && (colOffSrc==0&&colOffTrg==0);tryOffTrg+=32)
+ {
+ TInt offsetx=(tryOffTrg+targx)-(tryOffSrc+srcx);
+ TInt trysrcx=tryOffSrc+srcx;
+ if ( CmpBitmapRectL(testBitmap,TRect(trysrcx,splitHeight,trysrcx+width,splitHeight*2),TPoint(offsetx,-splitHeight))
+ | CmpBitmapRectL(testBitmap,TRect(trysrcx-1,splitHeight,trysrcx,splitHeight*2),TPoint(offsetx,-splitHeight))
+ | CmpBitmapRectL(testBitmap,TRect(trysrcx+width,splitHeight,trysrcx+width+1,splitHeight*2),TPoint(offsetx,-splitHeight))
+ )
+ {
+ }
+ else
+ {
+ colOffSrc=tryOffSrc;
+ colOffTrg=tryOffTrg;
+ }
+ }
+ if (colOffSrc||colOffTrg)
+ {
+ offsetx=(colOffTrg+targx)-(colOffSrc+srcx);
+ INFO_PRINTF4(_L("Found a safe equivalent column: srcx=%i targx=%i width=%i"),colOffSrc+srcx,colOffTrg+targx,width);
+ }
+ else
+ {
+ INFO_PRINTF4(_L("Didn't find a safe column! Trying next random numbers"),srcx,targx,width);
+ continue; //Try next random number...
+ }
+ }
+ TInt trysrcx=colOffSrc+srcx;
+ //Copy the region in question
+ bitmapContext->CopyRect(TPoint(offsetx,-splitHeight), TRect(trysrcx,splitHeight,trysrcx+width,splitHeight*2));
+ //verify the copied region is an exact match
+ TBool copySame=CmpBitmapRectL(testBitmap,TRect(trysrcx,splitHeight,trysrcx+width,splitHeight*2),TPoint(offsetx,-splitHeight));
+ //verify the area outside has not been copied
+ TBool leftSame=CmpBitmapRectL(testBitmap,TRect(trysrcx-1,splitHeight,trysrcx,splitHeight*2),TPoint(offsetx,-splitHeight));
+ TBool rightSame=CmpBitmapRectL(testBitmap,TRect(trysrcx+width,splitHeight,trysrcx+width+1,splitHeight*2),TPoint(offsetx,-splitHeight));
+ if (!copySame||leftSame||rightSame)
+ {
+ INFO_PRINTF4(_L("Case: srcx=%i targx=%i width=%i result compare has failed!"),srcx,targx,width);
+ if (!copySame)
+ {
+ INFO_PRINTF1(_L("Copied data is not same as source data!"));
+ }
+ if (leftSame)
+ {
+ INFO_PRINTF1(_L("Data to left of copy is now same as source data!"));
+ }
+ if (rightSame)
+ {
+ INFO_PRINTF1(_L("Data to right of copy is now same as source data!"));
+ }
+ TEST(EFalse);
+ }
+ break; //out of "try next random number" loop
+ }
+ if (maxRetries<0)
+ {
+ INFO_PRINTF4(_L("Case skipped TOO MANY TIMES because random data not unique: srcx=%i targx=%i width=%i."),srcx,targx,width);
+ skippedCases++;
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(bitmapContext);
+ CleanupStack::PopAndDestroy(bitmapDevice);
+
+ testBitmap.Reset();
+ if (skippedCases)
+ {
+ INFO_PRINTF3(_L("%i / %i cases skipped because random picture data not unique enough! 10%% will cause test fail."),skippedCases,totalCases );
+ TEST(skippedCases*10<totalCases);
+ }
+ }
+ }
+/**
+ * @SYMTestCaseID GRAPHICS-BITGDI-0098
+ *
+ * @SYMDEF INC119063, PDEF120353
+ *
+ * @SYMTestCaseDesc CopyRect could previously read bytes past the end of the source bitmap
+ * This would exception if the page is not mapped.
+ * This particular image size allocation reproduces this exception.
+ * Any changes to the allocation mechanism may mean the crash condition is not reproducable.
+ * It is likely that it is changes to the allocator that have caused this defect to occur
+ * in the first place.
+ *
+ * @SYMTestPriority Normal
+ *
+ * @SYMTestStatus Implemented
+ *
+ * @SYMTestActions Create 768x1280 1 bit image, (also 384x1280x2bit and 192x1280x4bit ?)
+ * In a seperate thread try to read past the end of the data.
+ * If this panics then the test is valid.
+ * Now, make a number of copyrect calls
+ * that attempt to read data from near the end of the last scanline
+ * Expected result: these reads should not exception.
+ * Enhancement to improve reproducability:
+ * Occasionally, the "next location" is addressable when the test is run in the overnight script
+ * To address this, the test will recurse and repeat, forcing the image allocation to a different address if this occurs
+*/
+TBool CTDefect2::CopyRectReadOutsideBitmap(TInt aSingleMode /*=0*/,TInt aRetriesLeft /*=5*/)
+ {
+ TBool testShouldUltimatelyFail=EFalse;
+ TInt startMode=aSingleMode?aSingleMode:1;
+ TInt stopMode=aSingleMode?aSingleMode+1:EColorLast;
+ for (TInt mode=startMode;mode<stopMode;mode++)
+ {
+ CFbsBitmap testBitmap;
+ enum
+ {
+ EMonoPixelsWidth=768,
+ EMonoBytesWidth=96,
+ EMonoHeight=1280
+ };
+ TInt guessPixels=EMonoPixelsWidth;
+ TInt guessBytes=CFbsBitmap::ScanLineLength(guessPixels,TDisplayMode(mode));
+ if (guessBytes<=0 || reinterpret_cast<TDisplayMode&>(mode)==ERgb)
+ {
+ continue; //mode number not good.
+ }
+ //want to generate a length of 768/8=96 bytes per scanline to repro the defect...
+ while (guessBytes<EMonoBytesWidth)
+ {
+ if (guessBytes<=EMonoBytesWidth/2)
+ {
+ guessPixels*=2;
+ }
+ else
+ {
+ guessPixels++;
+ }
+ guessBytes=CFbsBitmap::ScanLineLength(guessPixels,TDisplayMode(mode));
+ }
+ while (guessBytes>EMonoBytesWidth)
+ {
+ if (guessBytes>=EMonoBytesWidth*2)
+ {
+ guessPixels>>=1;
+ }
+ else
+ {
+ guessPixels--;
+ }
+ guessBytes=CFbsBitmap::ScanLineLength(guessPixels,TDisplayMode(mode));
+ }
+
+ if (testBitmap.Create(TSize(guessPixels,EMonoHeight),TDisplayMode(mode))<KErrNone)
+ {
+ _LIT(KFail,"Failed to create bitmap for color depth: %S");
+ INFO_PRINTF2(KFail,&ColorModeName(mode));
+ if (aSingleMode)
+ {
+ testShouldUltimatelyFail=ETrue;
+ }
+ continue; //some mode numbers are bad!
+ }
+
+ SEpocBitmapHeader header1 = testBitmap.Header();
+
+ TUint32* bitmapData=testBitmap.DataAddress();
+ TUint32* pastBitmapData=bitmapData+((header1.iBitmapSize-header1.iStructSize)>>2);
+
+ //The defect and fix only applies to low bit depths, but it is quick enough to run it for all color depths
+ if (aSingleMode)
+ {
+ User::After(1000000); //Pause is in microseconds! //A small pause to try to get the bad operation completed
+ INFO_PRINTF3(_L("Retry Bitmap: Address 0x%08x, past 0x%08x"),
+ bitmapData,pastBitmapData );
+
+ }
+ else
+ {
+ INFO_PRINTF7(_L("Bitmap: color depth: %i bits. Color mode= %i. Width=%i Height=%i Address 0x%08x, past 0x%08x"),
+ header1.iBitsPerPixel,header1.iColor,
+ header1.iSizeInPixels.iWidth,header1.iSizeInPixels.iHeight,
+ bitmapData,pastBitmapData );
+ }
+ TBool canGenerateDefectScenario=EFalse;
+
+
+ //So now we hope that we have created a test bitmap on the bottom of a memory page,
+ //as per the defect, but at different color depths as well.
+ //Any number of factors could change the way this block is allocated and disguise the defect.
+ //Equally, the next block of memory may be already mapped, and again the defect will not occurr.
+ //There is no way to influence the result, so the next ting to do is to verify that an exception will occur.
+ //Could assert that the address matches a 4K page, but I need to check if the page is mapped anyway!
+ TTestMemThread memThread(pastBitmapData-2,pastBitmapData+2);
+ TInt failAt=memThread.FailOffset();
+ if (failAt<0)
+ {
+ INFO_PRINTF2(_L(" Scenario invalid - error code generated by test thread! %i"),failAt);
+ }
+ else if (failAt<=1)
+ {
+ INFO_PRINTF1(_L(" Scenario invalid - didn't manage to read a safe location near the end of the bitmap!"));
+ }
+ else if (failAt>2)
+ {
+ INFO_PRINTF1(_L(" Scenario invalid - managed to read right past the test location!"));
+ }
+ else
+ {
+ INFO_PRINTF1(_L(" Verified that end address is bad memory"));
+ canGenerateDefectScenario=ETrue;
+ }
+ if (!canGenerateDefectScenario)
+ {
+ if (!aRetriesLeft || !CopyRectReadOutsideBitmap(mode,aRetriesLeft-1)) //repeat attempt with nested bitmap alocation to new address
+ {
+ //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.
+ //Can't return "Inconclusive" as other tests in the test set may reset the state.
+ INFO_PRINTF2(_L("Error!!: Couldn't generate the defect scenario for the end address at 0x%08x."),(TInt)pastBitmapData);
+ testShouldUltimatelyFail=ETrue;
+ }
+ }
+ else
+ {
+ //These writes should succeed if the end of the bitmap is where it should be:
+ //these colour values will be transferred in the copied data in the subsequent test
+ //The test does not explicitly look for these patterns,
+ //but they are useful to identify in the copied data if manually debugging.
+ pastBitmapData[-2]=0xBAADF00D;
+ pastBitmapData[-1]=0xdeadbeef;
+
+ CFbsBitGc* bitmapContext = NULL;
+ CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(&testBitmap);
+ CleanupStack::PushL(bitmapDevice);
+ User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
+ CleanupStack::PushL(bitmapContext);
+ //for the last scanline, try to copy various permutations of the last few pixels
+ //note that there is no check to see if the "right" contents are copied, only that it doesn't abort.
+ //In fact most of the bitmap is uninitialised...
+ TTestCopyRectThread copythread(bitmapContext,guessPixels-64,guessPixels,EMonoHeight-5,EMonoHeight,TPoint(-5,-5));
+ if (copythread.iExitHow!=copythread.EReturn)
+ {
+ testShouldUltimatelyFail=ETrue;
+ INFO_PRINTF7(_L("Error: (probably panic) when using CopyRect(TPoint(%i,%i),TRect(%i,%i,%i,%i)"),
+ -5,-5,
+ copythread.iCurrX,EMonoHeight-5, copythread.iCurrX+copythread.iCurrWidth,EMonoHeight);
+ _LIT(KLog,"Thread Exit Reason %d, expected %d");
+ INFO_PRINTF3(KLog,copythread.iExitHow,copythread.EReturn);
+ }
+
+ CleanupStack::PopAndDestroy(bitmapContext);
+ CleanupStack::PopAndDestroy(bitmapDevice);
+
+ //For the purposes of verification, check that the memory location is still considered a valid scenario.
+ //Again , the test is repeated nested if the scenario has become invalid
+ TTestMemThread memThread2(pastBitmapData-2,pastBitmapData+2);
+ TInt failAt=memThread2.FailOffset();
+ canGenerateDefectScenario=EFalse;
+ if (failAt<0)
+ {
+ INFO_PRINTF2(_L(" After Test: Scenario invalid - error code generated by test thread! %i"),failAt);
+ INFO_PRINTF1(_L("Warning: This may mean that bad copys may not have been detected??"));
+ }
+ else if (failAt<=1)
+ {
+ INFO_PRINTF1(_L(" After Test: Scenario invalid - didn't manage to read a safe location near the end of the bitmap!"));
+ INFO_PRINTF1(_L("Warning: This may mean that bad copys may not have been detected??"));
+ }
+ else if (failAt>2)
+ {
+ INFO_PRINTF1(_L(" After Test: Scenario invalid - managed to read right past the test location!"));
+ INFO_PRINTF1(_L("Warning: This may mean that bad copys may not have been detected??"));
+ }
+ else
+ {
+ INFO_PRINTF1(_L(" After Test: Verified that end address is still bad memory"));
+ canGenerateDefectScenario=ETrue;
+ }
+ if (!canGenerateDefectScenario)
+ {
+ if (!aRetriesLeft || !CopyRectReadOutsideBitmap(mode,aRetriesLeft-1)) //repeat attempt with nested bitmap alocation to new address
+ {
+ //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.
+ //Can't return "Inconclusive" as other tests in the test set may reset the state.
+ INFO_PRINTF2(_L("Warning!!: Couldn't maintain the defect scenario for the end address at 0x%08x after retries."),(TInt)pastBitmapData);
+ INFO_PRINTF1(_L("Test may have read from end of bitmap after it was made accessible."));
+ //Ultimately, this refuses to stabilise on ONB scenario, so I won't have this retry of the test fail.
+ }
+ }
+
+ }
+ testBitmap.Reset();
+ }
+ if (!aSingleMode)
+ {
+ TEST(!testShouldUltimatelyFail);
+ }
+ return (!testShouldUltimatelyFail);
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0066
+
+ @SYMDEF DEF039237
+
+ @SYMTestCaseDesc Memory leak in CFbsScreenDevice (occurs on Lubbock, but not WINS)
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Creates a screen device in each colour mode
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::DEF039237L()
+ {
+ __UHEAP_MARK;
+ const TInt KNumDisplayModes = 11;
+ const TDisplayMode KDisplayMode[KNumDisplayModes] =
+ { EGray2, EGray4, EGray16, EGray256, EColor16, EColor256,
+ EColor4K, EColor64K, EColor16M, EColor16MA, EColor16MAP };
+
+ CFbsScreenDevice* device = NULL;
+ TInt err = KErrNotSupported;
+ TInt index;
+
+ for (index=0; index<KNumDisplayModes && err==KErrNotSupported; ++index)
+ {
+ ASSERT(device==NULL);
+ TRAP(err,device = CFbsScreenDevice::NewL(KNullDesC,KDisplayMode[index]));
+ }
+ --index;
+ if (device)
+ {
+ _LIT(KLog,"Created device with color depth %S");
+ INFO_PRINTF2(KLog,&ColorModeName(KDisplayMode[index]));
+ }
+ else
+ {
+ _LIT(KLog,"Failed to create screen device, last color depth tried %S gave return value %d");
+ INFO_PRINTF3(KLog,&ColorModeName(KDisplayMode[index]),err);
+ }
+
+ User::LeaveIfError(err);
+ ASSERT(device);
+
+ delete device;
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0067
+
+ @SYMDEF DEF039331
+
+ @SYMTestCaseDesc bitgdi fails to deal correctly with screen orientation changes
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions
+ DEF039604 - CFbsBitGc::InternalizeL/ExternalizeL - comments, version number
+ Default region externalization/internalization related code was removed, so
+ I want to check that everything is OK calling
+ CFbsBitGc::ExternalizeL()/CFbsBitGc::InternalizeL().
+ The test may also fail in the future if somebody changes CFbsBitGc data members
+ and fail to update ExternalizeL/InternalizeL methods.
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::DEF039331L()
+ {
+ CreateScrDevAndContextL();
+
+ //Make sure that the archive file does not exist.
+ FServSession.Delete(KArchiveFileName);
+
+ RFileWriteStream wrStream;
+ ::CleanupClosePushL(wrStream);
+ User::LeaveIfError(wrStream.Create(FServSession, KArchiveFileName, EFileWrite | EFileRead));
+
+ iGc->ExternalizeL(wrStream);
+ wrStream.CommitL();
+ CleanupStack::PopAndDestroy();//wrStream
+
+ RFileReadStream rdStream;
+ ::CleanupClosePushL(rdStream);
+ User::LeaveIfError(rdStream.Open(FServSession, KArchiveFileName, EFileRead));
+ iGc->InternalizeL(rdStream);
+ CleanupStack::PopAndDestroy();//rdStream
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0068
+
+ @SYMDEF DEF039650
+
+ @SYMTestCaseDesc CFbsDevice::RectCompare says don't match when they do
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Creates a bitmap, calls scanlinedata then checks that the scanline returns the correct amount of data
+
+ @SYMTestExpectedResults Test should return correct number of bytes
+*/
+//DEF039650 - .
+void CTDefect2::DEF039650L()
+ {
+ enum {KHeight = 1};//Bitmaps height - in pixels
+ TDisplayMode testMode[] = {EGray2, EGray4, EGray16, EColor16, EColor4K, EColor64K, EColor16M, EColor16MU, EColor256};//tested display modes
+ const TInt pixelPerByte[] ={8, 4, 2, 2, 0, 0, 0, 0, 1};
+ const TInt bytePerPixel[] ={0, 0, 0, 0, 2, 2, 3, 4, 0};
+ const TInt bitmapWidth[] = {22, 7, 11, 11, 3, 3, 1, 1, 10};//bitmaps width
+ const TUint8 KTestVal1 = 0xA3;//test value
+ const TUint8 KTestVal2 = 0xF7;//test value
+ TUint8 scanLineData[100];//100 should be enough for all possible modes which are tested
+ for(TInt ii=0;ii<TInt(sizeof(testMode)/sizeof(testMode[0]));ii++)
+ {
+ TSize size(bitmapWidth[ii], KHeight);//bitmap size - in pixels
+ CreateBitmapL(size, testMode[ii]);
+ //Initialize the bitmap scanline
+ TInt scanLineLen = 0;
+ if(pixelPerByte[ii])
+ {
+ scanLineLen = bitmapWidth[ii] / pixelPerByte[ii] + (bitmapWidth[ii] % pixelPerByte[ii] ? 1 : 0);
+ }
+ else
+ {
+ scanLineLen = bitmapWidth[ii] * bytePerPixel[ii];
+ }
+ const TInt KAddBytes = 10;
+ Mem::Fill(scanLineData, scanLineLen, KTestVal1);
+ TPtr8 p(scanLineData, scanLineLen, scanLineLen + KAddBytes);
+ iBitmap->SetScanLine(p, 0);
+ //Create bitmap device (KWidth, KHeight) size
+ DeleteBitmapDevice();
+ iBmpDevice = CFbsBitmapDevice::NewL(iBitmap);
+ //Fill the scanLineData with control values
+ Mem::Fill(scanLineData, sizeof(scanLineData), KTestVal2);
+ //GetScanLine test - check the KAddBytes bytes
+ iBmpDevice->GetScanLine(p, TPoint(), bitmapWidth[ii], testMode[ii]);
+ for(TInt jj=0;jj<KAddBytes;jj++)
+ {
+ TEST(scanLineData[scanLineLen+jj] == KTestVal2);
+ }
+ }//end of - for(TInt ii=0;ii<TInt(sizeof(testMode)/sizeof(testMode[0]));ii++)
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0069
+
+ @SYMDEF
+
+ @SYMTestCaseDesc Tests the performance of getting and setting pixels in different display modes
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions draws a number opf pixels to a bitmap then reads them back. Time is recorded
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::GetPixelPerformance1L()
+ {
+ TDisplayMode mode[] = {EColor16MA, EColor16MAP, EColor256, EColor4K, EColor16M, EColor16MU, EColor64K,
+ EGray256, EGray16, EGray4, EGray2, EColor16};
+ _LIT(KLog,"Mode %S. Uncompressed bitmap. Time=%d");
+ for(TInt ii=0;ii<TInt(sizeof(mode)/sizeof(mode[0]));ii++)
+ {
+ //Create bitmap
+ enum {KWidth = 600, KHeight = 400};
+ TSize size(KWidth, KHeight);
+ CreateBitmapL(size, mode[ii]);
+ TEST(!iBitmap->IsCompressedInRAM());
+ //Fill bitmap
+ TBitmapUtil bmpUtil(iBitmap);
+ TTime now;
+ now.UniversalTime();
+ TInt64 seed = now.Int64();
+ bmpUtil.Begin(TPoint(0, 0));
+ for(TInt j1=0;j1<KWidth;j1++)
+ {
+ for(TInt j2=0;j2<KHeight;j2++)
+ {
+ bmpUtil.SetPos(TPoint(j1, j2));
+ bmpUtil.SetPixel(Math::Rand(seed));
+ }
+ }
+ bmpUtil.End();
+ //Performance test
+ TUint time = User::TickCount();
+ TPoint pt;
+ TRgb color(0);
+ for(TInt jj=0;jj<size.iWidth;jj++)
+ {
+ for(TInt kk=0;kk<size.iHeight;kk++)
+ {
+ pt.iX = jj;
+ pt.iY = kk;
+ iBitmap->GetPixel(color, pt);
+ }
+ }
+ time = User::TickCount() - time;
+ INFO_PRINTF3(KLog,&ColorModeName(mode[ii]),time);
+ //Destroy bitmap
+ DeleteBitmap();
+ }//end of - for(TInt ii=0;ii<TInt(sizeof(mode)/sizeof(mode[0]));ii++)
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0070
+
+ @SYMDEF
+
+ @SYMTestCaseDesc Draws text to the screen device in different orientations
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Creates a screen device and gc, changes the gc orientation then draws some text to it
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::RotateMoveTextL()
+ {
+ TInt err=CreateScrDevAndContext(EColor64K);
+ if (err!=KErrNone)
+ err=CreateScrDevAndContext(EColor256);
+ if (err!=KErrNone)
+ err=CreateScrDevAndContext(EColor16MA);
+ if (err!=KErrNone)
+ err=CreateScrDevAndContext(EColor16MAP);
+ TEST(err==KErrNone);
+ DoRotateMoveTextL();
+ }
+
+void CTDefect2::DoRotateMoveTextL()
+ {
+ __ASSERT_ALWAYS(iScrDev, User::Invariant());
+ __ASSERT_ALWAYS(iGc, User::Invariant());
+
+ CreateFontL();
+
+ const CFbsBitGc::TGraphicsOrientation KOrientation[] =
+ {
+ CFbsBitGc::EGraphicsOrientationNormal,
+ CFbsBitGc::EGraphicsOrientationRotated90,
+ CFbsBitGc::EGraphicsOrientationRotated180,
+ CFbsBitGc::EGraphicsOrientationRotated270
+ };
+
+ for(TInt ii=0;ii<TInt(sizeof(KOrientation)/sizeof(KOrientation[0]));++ii)
+ {
+ if(!iGc->SetOrientation(KOrientation[ii]))
+ {
+ continue;
+ }
+ _LIT(KRotation,"===EOrientation%S===");
+ INFO_PRINTF2(KRotation,&RotationName(KOrientation[ii]));
+
+ TSize size = iScrDev->SizeInPixels();
+ RDebug::Print(_L("Size: %d, %d\r\n"), size.iWidth, size.iHeight);
+ for(TInt x=-40;x<(size.iWidth+30);x+=27)
+ {
+ for(TInt y=-40;y<(size.iHeight+30);y+=23)
+ {
+ iGc->Clear();
+ iGc->SetPenStyle(CGraphicsContext::ESolidPen);
+ iGc->SetPenColor(TRgb(0x00, 0x00, 0x00));
+ iGc->SetPenSize(TSize(1, 1));
+
+ iGc->DrawText(_L("Test text"), TPoint(x, y));
+
+ iScrDev->Update();
+ }
+ }
+ }
+ iGc->SetOrientation(CFbsBitGc::EGraphicsOrientationNormal);
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0071
+
+ @SYMDEF
+
+ @SYMTestCaseDesc Swaps width and height of a bitmap
+
+ @SYMTestPriority normal
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Test to swap the width and height of a bitmap
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::SwapWidthAndHeightL()
+ {
+ TDisplayMode testMode[] = {EColor4K, EColor64K, EColor16M, EColor16MU,
+ EColor256, EColor16MA, EColor16MAP, EColor16, EGray16, EGray4, EGray2};//tested display modes
+ _LIT(KLog,"Mode %S");
+ for(TInt ii=0;ii<TInt(sizeof(testMode)/sizeof(testMode[0]));ii++)
+ {
+ INFO_PRINTF2(KLog,&ColorModeName(testMode[ii]));
+ TSize size(40, 12);//bitmap size - in pixels
+ CreateBitmapL(size, testMode[ii]);//iBitmap - created
+ //Create bitmap device
+ DeleteBitmapDevice();
+ iBmpDevice = CFbsBitmapDevice::NewL(iBitmap);
+ TInt err = iBmpDevice->SwapWidthAndHeight();
+ TEST(err == KErrNone);
+ }//end of - for(TInt ii=0;ii<TInt(sizeof(testMode)/sizeof(testMode[0]));ii++)
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0072
+
+ @SYMDEF
+
+ @SYMTestCaseDesc Multiple screen test
+
+ @SYMTestPriority High
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions creates some screens in different modes then writes some rotated text to them and test.
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::CreateScreenDeviceL()
+ {
+ TDisplayMode testMode[] = {EColor4K, EColor64K, EColor16M, EColor16MU, EColor256, EColor16MA, EColor16MAP};//tested display modes
+ for(TInt ii=0;ii<TInt(sizeof(testMode)/sizeof(testMode[0]));ii++)
+ {
+ TInt screenCnt = 0;
+ TEST(HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCnt) == KErrNone);
+ for(TInt screenNo=0;screenNo<screenCnt;++screenNo)
+ {
+ TInt err = CreateScrDevAndContext(screenNo, testMode[ii]);
+ if(err == KErrNone)
+ {
+ DoRotateMoveTextL();
+ }
+ DeleteGraphicsContext();
+ DeleteScreenDevice();
+ }
+ }
+ }
+
+void CTDefect2::CreateScrDevAndContextL()
+ {
+ DeleteGraphicsContext();
+ DeleteScreenDevice();
+ TDisplayMode mode[] = {EColor256, EColor4K, EColor16M, EColor16MU, EColor64K,
+ EGray256, EGray16, EGray4, EGray2, EColor16, EColor16MA, EColor16MAP};
+ TInt ii;
+ TInt err = KErrNotSupported;
+ for(ii=0;(ii<TInt(sizeof(mode)/sizeof(mode[0]))) && (err == KErrNotSupported);++ii)
+ {
+ err = CreateScrDevAndContext(mode[ii]);
+ }
+ TEST(err == KErrNone);
+ }
+
+TInt CTDefect2::CreateScrDevAndContext(TInt aScreenNo, TDisplayMode aDisplayMode)
+ {
+ DeleteGraphicsContext();
+ DeleteScreenDevice();
+ TRAPD(err, iScrDev = CFbsScreenDevice::NewL(aScreenNo, aDisplayMode));
+ if(err == KErrNotSupported)
+ {
+ return err;
+ }
+ TEST(err == KErrNone);
+ TEST(iScrDev->ScreenNo() == aScreenNo);
+ err = iScrDev->CreateContext((CGraphicsContext*&)iGc);
+ TEST(err == KErrNone);
+ iGc->SetUserDisplayMode(aDisplayMode);
+ iScrDev->ChangeScreenDevice(NULL);
+ iScrDev->SetAutoUpdate(EFalse);
+ iSize = iScrDev->SizeInPixels();
+ iCurrentMode = aDisplayMode;
+ return err;
+ }
+
+TInt CTDefect2::CreateScrDevAndContext(TDisplayMode aDisplayMode)
+ {
+ return CreateScrDevAndContext(KDefaultScreenNo,aDisplayMode);
+ }
+
+void CTDefect2::DeleteScreenDevice()
+ {
+ delete iScrDev;
+ iScrDev = NULL;
+ }
+
+void CTDefect2::DeleteGraphicsContext()
+ {
+ delete iGc;
+ iGc = NULL;
+ }
+
+void CTDefect2::CreateBitmapL(const TSize& aSize, TDisplayMode aMode)
+ {
+ DeleteBitmap();
+ iBitmap = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iBitmap->Create(aSize, aMode));
+ }
+
+void CTDefect2::DeleteBitmap()
+ {
+ if(iBitmap)
+ {
+ iBitmap->Reset();
+ }
+ delete iBitmap;
+ iBitmap = NULL;
+ }
+
+void CTDefect2::DeleteBitmapDevice()
+ {
+ delete iBmpDevice;
+ iBmpDevice = NULL;
+ }
+
+void CTDefect2::CreateFontL()
+ {
+ CFbsFont* font = NULL;
+ TFontSpec fs(_L("Swiss"), 12);
+ User::LeaveIfError(iScrDev->GetNearestFontToDesignHeightInPixels(font, fs));
+ iGc->UseFont(font);
+ }
+
+void CTDefect2::DestroyFont()
+ {
+ if(iGc)
+ {
+ iGc->DiscardFont();
+ }
+ }
+
+/**
+ @SYMTestCaseID GRAPHICS-BITGDI-0073
+
+ @SYMDEF
+
+ @SYMTestCaseDesc Clear with non-zero origin
+
+ @SYMTestPriority High
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions Creates a gc, setes its origin off (0,0) then clears it
+
+ @SYMTestExpectedResults Test should perform graphics operations succesfully.
+*/
+void CTDefect2::NonZeroOriginClearL()
+ {
+ TInt err=CreateScrDevAndContext(EColor64K);
+ if (err==KErrNotSupported)
+ err=CreateScrDevAndContext(EColor16MA);
+ if (err==KErrNotSupported)
+ err=CreateScrDevAndContext(EColor16MAP);
+ if (err!=KErrNone)
+ {
+ _LIT(KLog,"Failed to create screen device, err=%d");
+ INFO_PRINTF2(KLog,err);
+ }
+ TRgb setColor(TRgb::Color64K(13897));
+ iGc->SetBrushColor(setColor);
+ iGc->SetOrigin(TPoint(100,100));
+ iGc->Clear();
+ iScrDev->Update();
+
+ //Check samples of the screen that it is the right color
+ TSize size=iScrDev->SizeInPixels();
+ TInt x;
+ TInt y;
+
+ for (x=0;x<size.iWidth;x+=10)
+ {
+ for (y=0;y<size.iHeight;y+=10)
+ {
+ TRgb gotColor;
+ iScrDev->GetPixel(gotColor, TPoint(x,y));
+ TEST(gotColor==setColor);
+ }
+ }
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-BITGDI-0108
+
+@SYMDEF PDEF127874
+
+@SYMTestCaseDesc Use pattern brush bitmaps with zero widths or zero height or both
+
+@SYMTestPriority High
+
+@SYMTestStatus Implemented
+
+@SYMTestActions Creates 3 bitmaps:
+ One with zero width, one with zero height, one width zero width and height.
+ Each bitmap should automatically be cleared to white.
+ Clear the screen to black.
+ Set the GC to use patterned brush.
+ In turn, set the brush pattern to be one of the bitmap and draw a rectangle.
+@SYMTestExpectedResults Each rectangle drawn should remain black as each pattern brush should not be used.
+*/
+void CTDefect2::ZeroSizedPatternBrushL()
+ {
+ // Create a source bitmap with zero width
+ CFbsBitmap* bmp1 = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp1);
+ User::LeaveIfError(bmp1->Create(TSize(0,1), EColor16MU));
+
+ // Create a source bitmap with zero height
+ CFbsBitmap* bmp2 = new(ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp2);
+ User::LeaveIfError(bmp2->Create(TSize(1,0), EColor16MU));
+
+ // Create a source bitmap with zero width and height
+ CFbsBitmap* bmp3 = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(bmp3);
+ User::LeaveIfError(bmp3->Create(TSize(0,0), EColor16MU));
+
+ //Create a screen device & gc
+ CreateScrDevAndContextL();
+
+ TRgb clearColor = KRgbBlack;
+ iGc->SetBrushColor(clearColor);
+ iGc->Clear();
+ iScrDev->Update();
+ iGc->SetPenStyle(CGraphicsContext::ENullPen);
+ iGc->SetBrushStyle(CGraphicsContext::EPatternedBrush);
+ TSize drawRectSize(10,3);
+ // Draw a rectangle using each bitmap as a brush pattern
+ // Each rectangle does not overlap
+ iGc->UseBrushPattern(bmp1);
+ iGc->DrawRect(TRect(TPoint(0,0),drawRectSize));
+
+ iGc->UseBrushPattern(bmp2);
+ iGc->DrawRect(TRect(TPoint(0,4),drawRectSize));
+
+ iGc->UseBrushPattern(bmp3);
+ iGc->DrawRect(TRect(TPoint(0,8),drawRectSize));
+
+ iScrDev->Update();
+ // Bitmaps should be cleared to white when created, so if they are drawn
+ // will show up different to cleared screen.
+ for(TInt y=0; y<12; ++y)
+ {
+ for(TInt x=0; x<10; ++x)
+ {
+ TRgb pixelColor;
+ iScrDev->GetPixel(pixelColor,TPoint(x,y));
+ TEST(pixelColor==clearColor);
+ }
+ }
+ CleanupStack::PopAndDestroy(3, bmp1);
+ DeleteGraphicsContext();
+ DeleteScreenDevice();
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-BITGDI-0110
+
+@SYMDEF INC128813,PDEF129382
+
+@SYMTestCaseDesc Test CFbsBitGc::InternalizeL() when the font duplicate called from
+CFbsBitGc::Internalize:() fails.
+
+@SYMTestPriority Normal
+
+@SYMTestStatus Implemented (udeb/ debug versions only)
+
+@SYMTestActions Create and externalize a the CFbsBitGc*.
+ Then send a message to the font and bitmap server to force
+ CFbsBitGcFont::Duplicate() calls to fail.
+ Internalize the CFbsBitGc*()
+ Then send a message to the font and bitmap server to allow
+ CFbsBitGcFont::Duplicate() calls to succeed.
+ If the test runs to completion without any panics, then it has passed.
+*/
+void CTDefect2::CFbsBitGcInternalizeLFailL()
+ {
+ // this code is based on test CTDefect2::DEF039331L();
+#ifndef _DEBUG
+ INFO_PRINTF1(_L("Cannot run CFbsBitGcInternalizeLFailL test because test needs udeb for fbserv"));
+ return;
+
+#else
+ CreateScrDevAndContextL();
+
+ //Make sure that the archive file does not exist.
+ FServSession.Delete(KArchiveFileName);
+
+ CBufFlat* flatBuf = CBufFlat::NewL(256);
+ CleanupStack::PushL(flatBuf);
+ RBufWriteStream wrStream(*flatBuf);
+ ::CleanupClosePushL(wrStream);
+
+ CreateFontL();
+
+ iGc->ExternalizeL(wrStream);
+ wrStream.CommitL();
+ CleanupStack::PopAndDestroy();//wrStream
+
+ RBufReadStream rdStream(*flatBuf);
+ ::CleanupClosePushL(rdStream);
+
+ RFbsSession::GetSession()->SendCommand(static_cast<TInt>(EFbsMessSetDuplicateFail),1);
+
+ TInt ret=KErrNone;
+ TRAP(ret, (void)(iGc->InternalizeL(rdStream)));
+ INFO_PRINTF2(_L("CFbsBitGcInternalizeLFailL test returned %d: should have an error code"),ret);
+
+ RFbsSession::GetSession()->SendCommand(static_cast<TInt>(EFbsMessSetDuplicateFail),0);
+
+ //Without the fix there is a Kern-Exec3 panic.
+ TEST (ETrue);
+ CleanupStack::PopAndDestroy(2,flatBuf);
+#endif
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-BITGDI-0111
+
+@SYMDEF DEF132331
+
+@SYMTestCaseDesc Compare output from CFbsScreenDevice::HorizontalPixelsToTwips() and
+ VerticalPixelsToTwips() with the same methods in CWsScreenDevice with
+ large input numbers.
+
+@SYMTestPriority Normal
+
+@SYMTestStatus Implemented
+
+@SYMTestActions Creates an instance of CWsScreenDevice (instance of CFbsScreenDevice already prepared for
+ other tests). Call the pixels to twips and twips to pixels conversion methods on each with same
+ number. Compare the resulting output.
+@SYMTestExpectedResults Outputs should be within a small tolerance.
+*/
+void CTDefect2::PixelsToTwipsConversionCheck()
+ {
+ const TInt KHorizontalTestPixels=64000000;
+ const TInt KVerticalTestPixels=24000000;
+ const TReal32 KTolerance=0.10; // Percent difference permitted
+ TInt cFbsScreenDeviceResult = 1;
+ TInt cWsScreenDeviceResult = 1;
+ TReal32 percentDifference = 0.0;
+ CreateScrDevAndContextL();
+
+ RWsSession wsSession;
+ if (KErrNone == wsSession.Connect())
+ {
+ CWsScreenDevice* wsScrDev = new (ELeave) CWsScreenDevice(wsSession);
+ wsScrDev->Construct(0);
+
+ // first compare results of the two class's HorizontalPixelsToTwips and pass
+ // the test if they are within tolerance
+ cFbsScreenDeviceResult = iScrDev->HorizontalPixelsToTwips(KHorizontalTestPixels);
+ cWsScreenDeviceResult = wsScrDev->HorizontalPixelsToTwips(KHorizontalTestPixels);
+ percentDifference = Abs((TReal32)(cFbsScreenDeviceResult - cWsScreenDeviceResult)/cFbsScreenDeviceResult*100.0);
+ TEST(percentDifference < KTolerance);
+
+ // convert the CWsScreenDevice result back again using each class's HorizontalTwipsToPixels
+ // and pass the test if these results are within tolerance
+ cFbsScreenDeviceResult = iScrDev->HorizontalTwipsToPixels(cWsScreenDeviceResult);
+ cWsScreenDeviceResult = wsScrDev->HorizontalTwipsToPixels(cWsScreenDeviceResult);
+ percentDifference = Abs((TReal32)(cFbsScreenDeviceResult - cWsScreenDeviceResult)/cFbsScreenDeviceResult*100.0);
+ TEST(percentDifference < KTolerance);
+
+ // next compare results of the two class's VerticalPixelsToTwips and pass the test
+ // if they are within tolerance
+ cFbsScreenDeviceResult = iScrDev->VerticalPixelsToTwips(KVerticalTestPixels);
+ cWsScreenDeviceResult= wsScrDev->VerticalPixelsToTwips(KVerticalTestPixels);
+ percentDifference = Abs((TReal32)(cFbsScreenDeviceResult - cWsScreenDeviceResult)/cFbsScreenDeviceResult*100.0);
+ TEST(percentDifference < KTolerance);
+
+ // convert the CWsScreenDevice result back again using each class's VerticalTwipsToPixels
+ // and pass the test if these results are within tolerance
+ cFbsScreenDeviceResult = iScrDev->VerticalTwipsToPixels(cWsScreenDeviceResult);
+ cWsScreenDeviceResult = wsScrDev->VerticalTwipsToPixels(cWsScreenDeviceResult);
+ percentDifference = Abs((TReal32)(cFbsScreenDeviceResult - cWsScreenDeviceResult)/cFbsScreenDeviceResult*100.0);
+ TEST(percentDifference < KTolerance);
+
+ delete wsScrDev;
+ wsSession.Close();
+ }
+ else
+ {
+ iStep->SetTestStepResult(EFail);
+ _LIT(KMessage,"ERROR: Test Failed");
+ Logger().LogExtra((TText8*)__FILE__, __LINE__, ESevrErr,KMessage);
+ }
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-BITGDI-0113
+
+@SYMDEF PDEF138111
+
+@SYMTestCaseDesc Test CFbsBitGc::CopyRect() with non-trivial alpha channel
+
+@SYMTestPriority Normal
+
+@SYMTestStatus Implemented
+
+@SYMTestActions Create a 128 by 128 pixel bitmap with display mode EColor16MA.
+ Fill the upper half of the bitmap with semi-transparent gray.
+ Call CFbsBitGc::CopyRect() to copy the upper half to the lower half.
+ Sample one pixel from both the upper and lower half of the bitmap.
+
+@SYMTestExpectedResults The two pixels should be the same. Without the fix the lower part
+ would show a lighter shade of the gray.
+*/
+void CTDefect2::CopyRectAlphaL()
+ {
+ TSize size = TSize(128, 128);
+
+ CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(bitmap);
+ User::LeaveIfError(bitmap->Create(size, EColor16MA));
+
+ CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap);
+ CleanupStack::PushL(bitmapDevice);
+
+ CFbsBitGc* bitmapContext = NULL;
+ User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
+ CleanupStack::PushL(bitmapContext);
+
+ bitmap->BeginDataAccess();
+ Mem::Fill(bitmap->DataAddress(), 128 * 4 * 64, 0x80);
+ bitmap->EndDataAccess();
+ bitmapContext->CopyRect(TPoint(0, 64), TRect(0, 0, 128, 64));
+
+ //sample a pixel from the lower part of the bitmap and it should be the same as the upper half
+ TRgb pixelColorUpper;
+ bitmap->GetPixel(pixelColorUpper, TPoint(2, 3));
+ TRgb pixelColorLower;
+ bitmap->GetPixel(pixelColorLower, TPoint(80, 90));
+ TEST(pixelColorUpper == pixelColorLower);
+
+ CleanupStack::PopAndDestroy(3, bitmap);
+ }
+
+//
+
+class TTestSetBitsThread: public TFunctionThread
+ {
+public:
+ TTestSetBitsThread(TDisplayMode aDisplayMode, TBool aVerticalResize, TBool aScaling);
+private:
+ virtual TInt ThreadFunctionL();
+private:
+ TDisplayMode iDisplayMode;
+ TBool iVerticalResize;
+ TBool iScaling;
+ };
+
+TTestSetBitsThread::TTestSetBitsThread(TDisplayMode aDisplayMode, TBool aVerticalResize, TBool aScaling)
+ : iDisplayMode(aDisplayMode), iVerticalResize(aVerticalResize), iScaling(aScaling)
+ {
+ TBuf<32> threadName;
+ threadName.Format(_L("TestSetBits-%d-%d-%d"), TInt(aDisplayMode), TInt(aVerticalResize), TInt(aScaling));
+ LaunchThreadFunction(threadName);
+ }
+
+TInt TTestSetBitsThread::ThreadFunctionL()
+ {
+ CFbsBitmap* bmp = new(ELeave) CFbsBitmap;
+ CleanupStack::PushL(bmp);
+ User::LeaveIfError(bmp->Create(TSize(256, 256), iDisplayMode));
+ CFbsBitmapDevice* bmpDev = CFbsBitmapDevice::NewL(bmp);
+ CleanupStack::PushL(bmpDev);
+ if (iScaling)
+ {
+ User::LeaveIfError(bmpDev->SetScalingFactor(TPoint(0, 0), 2, 2, 1, 1));
+ }
+ if (iVerticalResize)
+ {
+ User::LeaveIfError(bmp->Resize(TSize(256, 128)));
+ }
+ else
+ {
+ User::LeaveIfError(bmp->Resize(TSize(128, 256)));
+ }
+ bmpDev->DrawingBegin();
+ bmpDev->DrawingEnd();
+ CleanupStack::PopAndDestroy(2);
+ return 0;
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-BITGDI-0112
+
+@SYMDEF PDEF138375
+
+@SYMTestCaseDesc Makes sure that CFbsBitmapDevice::SetBits() checks that the bitmap size is consistent.
+
+@SYMTestPriority Normal
+
+@SYMTestStatus Implemented
+
+@SYMTestActions 1. Creates a bitmap and an associated bitmap device.
+ 2. Resizes the bitmap directly.
+ 3. Calls DrawingBegin()/DrawingEnd() on the bitmap device.
+
+@SYMTestExpectedResults The call to DrawingBegin() should panic in debug builds.
+*/
+void CTDefect2::TestSetBitsL()
+ {
+#ifdef _DEBUG
+ for (TBool verticalResize = 0; verticalResize <= 1; ++verticalResize)
+ {
+ for (TBool scaling = 0; scaling <= 1; ++scaling)
+ {
+ TTestSetBitsThread testThread1(EGray2, verticalResize, scaling);
+ TEST(testThread1.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread1.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread2(EGray4, verticalResize, scaling);
+ TEST(testThread2.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread2.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread3(EGray16, verticalResize, scaling);
+ TEST(testThread3.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread3.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread4(EColor16, verticalResize, scaling);
+ TEST(testThread4.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread4.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread5(EGray256, verticalResize, scaling);
+ TEST(testThread5.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread5.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread6(EColor256, verticalResize, scaling);
+ TEST(testThread6.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread6.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread7(EColor4K, verticalResize, scaling);
+ TEST(testThread7.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread7.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread8(EColor64K, verticalResize, scaling);
+ TEST(testThread8.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread8.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread9(EColor16M, verticalResize, scaling);
+ TEST(testThread9.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread9.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread10(EColor16MU, verticalResize, scaling);
+ TEST(testThread10.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread10.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread11(EColor16MA, verticalResize, scaling);
+ TEST(testThread11.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread11.iExitCode == EBitgdiPanicInvalidBitmap);
+
+ TTestSetBitsThread testThread12(EColor16MAP, verticalResize, scaling);
+ TEST(testThread12.iExitHow == TFunctionThread::EPanic);
+ TEST(testThread12.iExitCode == EBitgdiPanicInvalidBitmap);
+ }
+ }
+#else
+ WARN_PRINTF1(_L("Test skipped because it needs udeb build"));
+#endif
+ }
+
+//--------------
+__CONSTRUCT_STEP__(Defect2)
+
+void CTDefect2Step::TestSetupL()
+ {
+ }
+
+void CTDefect2Step::TestClose()
+ {
+ ::DeleteDataFile(KArchiveFileName);
+ }