diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/bitgdi/tbit/TDefect2.cpp --- /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 +#include +#include +#include +#include +#include +#include +#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;fillIndexBitBltMasked(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;fillIndexBitBltMasked(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;fillIndexBitBltMasked(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 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 (creatediExitHow = 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;iCurrX0;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=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;row4) + { + 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=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+srcxCopyRect(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(mode)==ERgb) + { + continue; //mode number not good. + } + //want to generate a length of 768/8=96 bytes per scanline to repro the defect... + while (guessBytesEMonoBytesWidth) + { + if (guessBytes>=EMonoBytesWidth*2) + { + guessPixels>>=1; + } + else + { + guessPixels--; + } + guessBytes=CFbsBitmap::ScanLineLength(guessPixels,TDisplayMode(mode)); + } + + if (testBitmap.Create(TSize(guessPixels,EMonoHeight),TDisplayMode(mode))>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; indexExternalizeL(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;iiSetScanLine(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;jjIsCompressedInRAM()); + //Fill bitmap + TBitmapUtil bmpUtil(iBitmap); + TTime now; + now.UniversalTime(); + TInt64 seed = now.Int64(); + bmpUtil.Begin(TPoint(0, 0)); + for(TInt j1=0;j1GetPixel(color, pt); + } + } + time = User::TickCount() - time; + INFO_PRINTF3(KLog,&ColorModeName(mode[ii]),time); + //Destroy bitmap + DeleteBitmap(); + }//end of - for(TInt ii=0;iiSetOrientation(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;iiSwapWidthAndHeight(); + TEST(err == KErrNone); + }//end of - for(TInt ii=0;iiScreenNo() == 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;xGetPixel(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(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(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); + }