--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdi/test/tglyphimagecache.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1084 @@
+// Copyright (c) 2007-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:
+// This test is designed to run in environment with monotype font support.
+// To set up environment launch ityperast.cmd from epoc32\winscw\, and
+// then follow instruction on the screen.
+//
+//
+
+#include "tglyphimagecache.h"
+#include <graphics/directgdiengine.h>
+#include <e32base.h>
+#include <VG/openvg.h>
+
+// The size of the target in pixels to use for these tests
+const TSize KGlyphCacheWindowSize(400, 400);
+
+enum TFontParam
+ {
+ ENormal,
+ EUnderline = 0x1,
+ EStrikeThrough = 0x2,
+ EBold = 0x4,
+ EUnderlineBold = 0x5,
+ EItalic = 0x8,
+ EItalicStrikeThrough = 0xa,
+ };
+
+class TFontType
+ {
+public:
+ TInt iFontSize;
+ TFontParam iFontParam;
+ };
+
+LOCAL_C void CleanCache(TAny* aPtr)
+ {
+ MFontGlyphImageStorage* glyphImageStorage = reinterpret_cast<MFontGlyphImageStorage*> (aPtr);
+ glyphImageStorage->CleanGlyphImageCache();
+ }
+
+CTGlyphImageCache::CTGlyphImageCache()
+ {
+ SetTestStepName(KTGlyphImageCacheStep);
+ }
+
+CTGlyphImageCache::~CTGlyphImageCache()
+ {
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9201
+ REQ9202
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Test requests Glyph Image elements from storage according their Glyph Key.
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ Create Font Image Storage. In the cycle request aGlyph Image entry for a particular Glyph
+ code and a font ID.
+ Delete Glyph Storage.
+
+@SYMTestExpectedResults
+ GlyphImage function must succeed; foreground, shadow and outlined images (if applicable) must be created
+*/
+void CTGlyphImageCache::TestRetrieveEntryL(MFontGlyphImageStorage* aGlyphStorage, TGlyphBitmapType aGlyphType)
+ {
+ if(!aGlyphStorage)
+ return;
+ _LIT(KTestName, "GlyphCache_RetrieveEntry");
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(KTestName);
+ }
+
+ TSize size(20, 30);
+ TInt bufferLength = size.iWidth * size.iHeight;
+ TUint8* buffer = (TUint8*)User::AllocL(bufferLength);
+ CleanupStack::PushL(buffer);
+ if(aGlyphType == EMonochromeGlyphBitmap)
+ {//to make decoding mechanizm work properly we need to fill the buffer
+ Mem::Fill(buffer, bufferLength, 0x1);
+ }
+
+ TInt fontListId[] =
+ {
+ 1, 5, 3, 5
+ };
+ TInt numFont = sizeof(fontListId) / sizeof(fontListId[0]);
+ TUint charCodeList[] =
+ {
+ 1, 2, 3, 2, 3,
+ };
+ TInt numGlyphCode = sizeof(charCodeList) / sizeof(charCodeList[0]);
+
+ for(TInt jj = 0; jj < numFont; jj++)
+ {
+ TInt fontId = fontListId[jj];
+ for(TInt ii = 0; ii < numGlyphCode; ii++)
+ {
+ TChar glyphCode = TChar(charCodeList[ii]);
+ VGImage foregroundImg = VG_INVALID_HANDLE;
+ VGImage shadowImg = VG_INVALID_HANDLE;
+ VGImage outlineImg = VG_INVALID_HANDLE;
+ TBool res = aGlyphStorage->GlyphImage(fontId, glyphCode, aGlyphType, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERROR(res);
+ if(res != KErrNone)
+ {
+ User::Leave(res);
+ }
+ else
+ {
+ TEST(foregroundImg);
+ if(aGlyphType == EFourColourBlendGlyphBitmap)
+ {
+ TEST(shadowImg);
+ TEST(outlineImg);
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9201
+ REQ9202
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Drawing monochrome, anti-aliased and four colour fonts with different styles
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ Text is output with different effects (strikethrough, underline) and orientation
+ (horizontal, vertical up, vertical down) and at different sizes and positions.
+ Clip region is also specified.
+
+@SYMTestExpectedResults
+ Test and reference images must match
+*/
+void CTGlyphImageCache::TestDrawGlyphL(MFontGlyphImageStorage* aGlyphStorage, TGlyphBitmapType aGlyphBitmapType, DrawTextDirection aDirection, DrawTextAdjustment aDrawAdjustment, TBool aClipText)
+ {
+ _LIT(KTestNameTemplate, "DrawGlyph%S_Dir%d_Clip%d_Adjust%d");
+ TBuf<128> testName;
+ _LIT(KTextOutput, "Hello world! Hello world! Hello world! Hello world! Hello world! Hello world!");
+
+ switch(aGlyphBitmapType)
+ {
+ case EMonochromeGlyphBitmap:
+ _LIT(KMonochromeName, "Monochrome");
+ testName.Format(KTestNameTemplate, &KMonochromeName, aDirection, aClipText, aDrawAdjustment);
+ break;
+ case EAntiAliasedGlyphBitmap:
+ _LIT(KAntiAliasedName, "AntiAliased");
+ testName.Format(KTestNameTemplate, &KAntiAliasedName, aDirection, aClipText, aDrawAdjustment);
+ break;
+ case EFourColourBlendGlyphBitmap:
+ _LIT(KFourColourName, "FourColour");
+ testName.Format(KTestNameTemplate, &KFourColourName, aDirection, aClipText, aDrawAdjustment);
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(testName);
+ }
+
+ ResetGc();
+ _LIT(KTestFontTypefaceName,"DejaVu Sans Condensed");
+ const TFontType fontType[] =
+ {
+ 18, EStrikeThrough, 48, EUnderline, 16, EItalic, 78, EItalicStrikeThrough,
+
+ 18, EStrikeThrough, 48, EUnderlineBold, 16, ENormal, 78, EStrikeThrough, 78, EBold,
+ };
+
+ TPoint pt(5, 5);
+ TInt *coord = & (pt.iY);
+
+ TSize size = iGdiTarget->SizeInPixels();
+ TRect rect = size;
+ rect.Shrink(20, 5);
+ RRegion region(rect);
+ TRect rect1;
+ if(aDirection == EDrawTextHorizontal)
+ {
+ rect1 = TRect(size.iWidth / 2 - 40, 40, size.iWidth / 2 + 40, size.iHeight - 40);
+ }
+ else
+ {
+ rect1 = TRect(20, size.iHeight / 2 - 40, size.iWidth - 20, size.iHeight / 2 + 40);
+ }
+ region.SubRect(rect1);
+
+ if(aDirection == EDrawTextVerticalUp || aDirection == EDrawTextVerticalDown)
+ {
+ if(aDirection == EDrawTextVerticalUp)
+ {
+ pt.iY = size.iHeight - 5;
+ }
+ coord = &(pt.iX);
+ }
+
+ TInt arraySize = sizeof(fontType) / sizeof(fontType[0]);
+
+ for(TInt ii = 0; ii < arraySize; ii++)
+ {
+ CFont *font = NULL;
+ TFontSpec fspec(KTestFontTypefaceName, fontType[ii].iFontSize);
+ fspec.iFontStyle.SetBitmapType(aGlyphBitmapType);
+
+ iGc->Reset();
+
+ if(aClipText)
+ {
+ iGc->SetClippingRegion(region);
+ }
+
+ if(aGlyphBitmapType == EFourColourBlendGlyphBitmap)
+ {
+ fspec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ fspec.iFontStyle.SetEffects(FontEffect::EOutline, ETrue);
+ fspec.iFontStyle.SetEffects(FontEffect::EDropShadow, ETrue);
+ TRgb shadowColor = TRgb(0, 0, 255);
+ iGc->SetTextShadowColor(shadowColor);
+ TEST(shadowColor == iGc->TextShadowColor());
+ iGc->SetBrushColor(TRgb(255, 0, 0));
+ TEST(TRgb(255, 0, 0) == iGc->BrushColor());
+ }
+ else
+ {
+ iGc->SetBrushStyle(DirectGdi::ENullBrush);
+ iGc->SetPenStyle(DirectGdi::ESolidPen);
+ }
+ iGc->SetPenColor(TRgb(0, 255, 0));
+ if(fontType[ii].iFontParam & EItalic)
+ {
+ fspec.iFontStyle.SetPosture(EPostureItalic);
+ }
+ if(fontType[ii].iFontParam & EBold)
+ {
+ fspec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+ }
+
+ User::LeaveIfError(iFontStore->GetNearestFontToDesignHeightInPixels((CFont*&) font, fspec));
+ if(iUseDirectGdi)
+ {
+ if(ii == 2)
+ {
+ iGc->SetFontNoDuplicate(font);
+ (reinterpret_cast <CTestDirectGdiContext*> (iGc))->NoJustifyAutoUpdate();
+ }
+ else
+ {
+ iGc->SetFont(font);
+ iGc->SetFontNoDuplicate(font);//shoudn't have any impact
+ (reinterpret_cast <CTestDirectGdiContext*> (iGc))->SetJustifyAutoUpdate();
+ }
+ }
+ else
+ {
+ iGc->SetFont(font);
+ iGc->SetFontNoDuplicate(font);//shoudn't have any impact
+ }
+ TEST(iGc->HasFont());
+
+ TFontSpec fontSpec = font->FontSpecInTwips();
+ TGlyphBitmapType glyphBitmapType = fontSpec.iFontStyle.BitmapType();
+
+ TEST(glyphBitmapType == aGlyphBitmapType);
+ if(fontType[ii].iFontParam & EUnderline)
+ {
+ iGc->SetUnderlineStyle(DirectGdi::EUnderlineOn);
+ }
+ else if(fontType[ii].iFontParam & EStrikeThrough)
+ {
+ iGc->SetStrikethroughStyle(DirectGdi::EStrikethroughOn);
+ }
+
+ if(EDrawTextVerticalDown != aDirection)
+ {
+ *coord += font->HeightInPixels() + 5;
+ }
+
+ if(aGlyphStorage && (ii == 0) && (arraySize > 1))
+ {
+ aGlyphStorage->CleanGlyphImageCache();
+ aGlyphStorage->EnforceOOMFailure(ETrue);
+ }
+ DrawText(KTextOutput, pt, aDirection, aDrawAdjustment, ii == 1);
+ if(aGlyphStorage)
+ {
+ aGlyphStorage->EnforceOOMFailure(EFalse);
+ }
+
+ if(EDrawTextVerticalDown == aDirection)
+ {
+ *coord += font->HeightInPixels() + 5;
+ }
+
+ if(fontType[ii].iFontParam == ENormal)
+ {
+ iGc->SetUnderlineStyle(DirectGdi::EUnderlineOff);
+ iGc->SetStrikethroughStyle(DirectGdi::EStrikethroughOff);
+ }
+ iGc->ResetFont();
+ iFontStore->ReleaseFont(font);
+
+ TEST(!iGc->HasFont());
+ }
+ region.Close();
+ if(aClipText)
+ {
+ iGc->ResetClippingRegion();
+ }
+
+ // Write the output to file.
+ //
+ TESTNOERROR(WriteTargetOutput(iTestParams, testName));
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0003
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9201
+ REQ9202
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Filling up the glyph image cache
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ 1. Fill glyph image storage with the same font but different glyphs until it exceeds its limit and resets the cache.
+ Repeat this operation for other glyph types
+
+ 2. Fill glyph image storage with different font and different glyph codes
+
+@SYMTestExpectedResults
+ Check that Glyph cache storage increments cache size correctly and deletes the least
+ usable tree.
+*/
+void CTGlyphImageCache::FillUpCacheL(MFontGlyphImageStorage* aGlyphStorage)
+ {
+ if(!aGlyphStorage)
+ return;
+
+ aGlyphStorage->CleanGlyphImageCache();
+ TBuf<128> testName;
+ _LIT(KTestName, "GlyphCache_FillUpCache");
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(KTestName);
+ }
+
+ const TSize size(12, 16);
+ TUint8* buffer = (TUint8*)User::AllocL(size.iWidth * size.iHeight);
+ CleanupStack::PushL(buffer);
+ TInt fontId = 10;
+ TGlyphBitmapType glyphTypeList[] =
+ {
+ EMonochromeGlyphBitmap,
+ EAntiAliasedGlyphBitmap,
+ EFourColourBlendGlyphBitmap,
+ };
+ const TInt numGlyphType = sizeof(glyphTypeList) / sizeof(glyphTypeList[0]);
+ TESTL(aGlyphStorage->GlyphCacheSize() == 0);
+
+ TInt glyphSizeInByte = 0;
+ TInt expectedSize = 0;
+ TUint32 glyphCode = 1;
+
+ VGImage foregroundImg = VG_INVALID_HANDLE;
+ VGImage shadowImg = VG_INVALID_HANDLE;
+ VGImage outlineImg = VG_INVALID_HANDLE;
+ for(TInt ii = 0; ii < numGlyphType; ii++)
+ {
+ TGlyphBitmapType glyphType = glyphTypeList[ii];
+ //calculate the actual size of the glyph
+ glyphSizeInByte = GlyphImageSizeInByte(glyphType, size);
+
+ TUint maxGlyphSize = aGlyphStorage->MaxGlyphCacheSize() + glyphSizeInByte;
+ do
+ {
+ TEST(expectedSize == aGlyphStorage->GlyphCacheSize());
+ TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), (TGlyphBitmapType)glyphType, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ glyphCode++;
+ expectedSize+= glyphSizeInByte;
+ foregroundImg = VG_INVALID_HANDLE;
+ shadowImg = VG_INVALID_HANDLE;
+ outlineImg = VG_INVALID_HANDLE;
+ }while(expectedSize <= maxGlyphSize);
+ glyphCode = 1;
+ expectedSize = 0;
+ TEST(glyphSizeInByte == aGlyphStorage->GlyphCacheSize());
+ aGlyphStorage->CleanGlyphImageCache();
+ }
+
+ //now try to filling cache with different fonts and check that last usable font wont be removed
+ TUint maxGlyphSize = aGlyphStorage->MaxGlyphCacheSize();
+ glyphSizeInByte = GlyphImageSizeInByte(EMonochromeGlyphBitmap, size);
+ do
+ {
+ TEST(expectedSize == aGlyphStorage->GlyphCacheSize());
+ TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), EMonochromeGlyphBitmap, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ glyphCode++;
+ expectedSize+= glyphSizeInByte;
+ foregroundImg = VG_INVALID_HANDLE;
+ shadowImg = VG_INVALID_HANDLE;
+ outlineImg = VG_INVALID_HANDLE;
+ }while(expectedSize <= maxGlyphSize);
+
+ fontId += 10;
+ glyphCode = 1;
+
+ TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), EMonochromeGlyphBitmap, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
+ TEST(glyphSizeInByte == aGlyphStorage->GlyphCacheSize());
+ TESTNOERROR(res);
+
+ RArray<TUint32> listFontId;
+ aGlyphStorage->FontIdInOrder(listFontId);
+ TESTL(listFontId.Count() == 1);
+ TEST(listFontId[0] == fontId);
+ listFontId.Reset();
+
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0004
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9201
+ REQ9202
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Tests filling the glyph image cache with different glyph images
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ Specify glyphs which correspond to different fonts, glyph codes.
+ Request related VGImages.
+ Test the cache size is correct after each operation.
+ Get the driver's MDirectGdiDriverCacheSize interface.
+ Attempt to set the maximum size of the glyph cache to a size smaller than
+ the existing cache size.
+ Attempt to set the maximum size of the glyph cache to a size the same as
+ the existing cache size.
+
+
+@SYMTestExpectedResults
+ Obtained glyph code and cache size must be correct each time.
+ Setting the maximum glyph cache size to a smaller size than the existing cache
+ size should fail with error KErrArgument.
+ Setting the maximum glyph cache size to a size the same as the existing cache
+ size should pass.
+*/
+void CTGlyphImageCache::FillCacheL(MFontGlyphImageStorage* aGlyphStorage)
+ {
+ ASSERT(aGlyphStorage);
+
+ aGlyphStorage->CleanGlyphImageCache();
+ TBuf<128> testName;
+ _LIT(KTestName, "GlyphCache_FillCache");
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(KTestName);
+ }
+
+ const TSize smallFontSize = TSize(12, 16);
+ const TSize smallFont1Size = TSize(10, 14);
+ const TSize bigFontSize = TSize(18, 24);
+ const TSize bigFont1Size = TSize(20, 26);
+ const TInt smallFontId = 10;
+ const TInt bigFontId = 20;
+ const TInt smallFont1Id = 30;
+ const TInt bigFont1Id = 40;
+ VGImage foregroundImg = VG_INVALID_HANDLE;
+ VGImage shadowImg = VG_INVALID_HANDLE;
+ VGImage outlineImg = VG_INVALID_HANDLE;
+
+ TUint8* buffer = (TUint8*)User::AllocL(bigFontSize.iWidth * bigFontSize.iHeight);
+ CleanupStack::PushL(buffer);
+ TESTL(aGlyphStorage->GlyphCacheSize() == 0);
+
+ TInt expectedCacheSize = 0;
+ TChar glyphCode = TChar(1);
+ TGlyphBitmapType glyphType = EMonochromeGlyphBitmap;
+ TBool res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize = GlyphImageSizeInByte(glyphType, smallFontSize);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //try to retrieve the same glyph
+ res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ //the size should be the same
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //now retrieving the same glyphCode but for the different font
+ res = aGlyphStorage->GlyphImage(bigFontId, glyphCode, glyphType, buffer, bigFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFontSize);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //last font but different glyphCode
+ glyphCode = TChar(2);
+ res = aGlyphStorage->GlyphImage(bigFontId, glyphCode, glyphType, buffer, bigFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFontSize);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //small font and last glyphCode
+ res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize += GlyphImageSizeInByte(glyphType, smallFontSize);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //now change the type
+ glyphType = EAntiAliasedGlyphBitmap;
+ res = aGlyphStorage->GlyphImage(smallFont1Id, glyphCode, glyphType, buffer, smallFont1Size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize += GlyphImageSizeInByte(glyphType, smallFont1Size);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+ //try again
+ res = aGlyphStorage->GlyphImage(smallFont1Id, glyphCode, glyphType, buffer, smallFont1Size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //now change the type again
+ glyphType = EFourColourBlendGlyphBitmap;
+ res = aGlyphStorage->GlyphImage(bigFont1Id, glyphCode, glyphType, buffer, bigFont1Size, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFont1Size);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //using initial value.
+ glyphType = EMonochromeGlyphBitmap;
+ glyphCode = TChar(1);
+ res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+ TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
+
+ //get the driver's MDirectGdiDriverCacheSize extension interface and attempt
+ //to set the maximum cache size to be smaller than the existing cache size
+ CDirectGdiDriver* driver = CDirectGdiDriver::Static();
+ TESTL(driver != NULL);
+ MDirectGdiDriverCacheSize* driverCacheSize = NULL;
+ res = driver->GetInterface(TUid::Uid(KDirectGdiDriverCacheSizeUid), (TAny*&)driverCacheSize);
+ TESTNOERRORL(res);
+ //save the original cache size
+ TInt originalCacheSize = driverCacheSize->MaxGlyphCacheSize();
+ //setting the cache size to a size smaller than the existing cache should fail
+ res = driverCacheSize->SetMaxGlyphCacheSize(aGlyphStorage->GlyphCacheSize()-1);
+ TEST(res == KErrArgument);
+ //setting the cache size to the same size as the existing cache should pass
+ res = driverCacheSize->SetMaxGlyphCacheSize(aGlyphStorage->GlyphCacheSize());
+ TESTNOERROR(res);
+ TEST(aGlyphStorage->GlyphCacheSize() == driverCacheSize->MaxGlyphCacheSize());
+ //reset the original driver cache size
+ res = driverCacheSize->SetMaxGlyphCacheSize(originalCacheSize);
+ TESTNOERROR(res);
+
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0005
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9201
+ REQ9202
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Tests the ordering font IDs in the glyph image cache.
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ Request glyph images for different fonts.
+
+@SYMTestExpectedResults
+ List of glyph cache trees must be arranged in order from most used to least used.
+*/
+void CTGlyphImageCache::FontListIdOrderL(MFontGlyphImageStorage* aGlyphStorage)
+ {
+ if(!aGlyphStorage)
+ return;
+
+ aGlyphStorage->CleanGlyphImageCache();
+ TBuf<128> testName;
+ _LIT(KTestName, "GlyphCache_FontListIdOrder");
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(KTestName);
+ }
+
+ const TSize fontSize = TSize(12, 16);
+ TUint8* buffer = (TUint8*)User::AllocL(fontSize.iWidth * fontSize.iHeight);
+ CleanupStack::PushL(buffer);
+
+ TChar glyphCode = TChar(10);
+ TInt fontId = 10;
+ VGImage foregroundImg = VG_INVALID_HANDLE;
+ VGImage shadowImg = VG_INVALID_HANDLE;
+ VGImage outlineImg = VG_INVALID_HANDLE;
+
+ TGlyphBitmapType glyphType = EMonochromeGlyphBitmap;
+ TInt res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 20;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 30;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ RArray<TUint32> fontListId;
+ res = aGlyphStorage->FontIdInOrder(fontListId);
+ if(res != KErrNone)
+ {
+ fontListId.Reset();
+ User::Leave(res);
+ }
+
+ TESTL(fontListId.Count() == 3);
+ TEST(fontListId[0] == 30);
+ TEST(fontListId[1] == 20);
+ TEST(fontListId[2] == 10);
+ fontListId.Reset();
+
+ //call entries again to reorder font id list
+ fontId = 30;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 20;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 40;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 10;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ fontId = 50;
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TESTNOERRORL(res);
+
+ res = aGlyphStorage->FontIdInOrder(fontListId);
+ if(res != KErrNone)
+ {
+ fontListId.Reset();
+ User::Leave(res);
+ }
+
+ TESTL(fontListId.Count() == 5);
+ TEST(fontListId[0] == 50);
+ TEST(fontListId[1] == 10);
+ TEST(fontListId[2] == 40);
+ TEST(fontListId[3] == 20);
+ TEST(fontListId[4] == 30);
+ fontListId.Reset();
+
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+/**
+@SYMTestCaseID
+ GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0006
+
+@SYMPREQ
+ PREQ39
+
+@SYMREQ
+ REQ9195
+ REQ9222
+ REQ9223
+ REQ9236
+ REQ9237
+
+@SYMTestCaseDesc
+ Test the operation of the glyph image cache when sent wrong parameters.
+
+@SYMTestStatus
+ Implemented
+
+@SYMTestPriority
+ High
+
+@SYMTestActions
+ Test requesting of glyph images with invalid paramaters - test an invalid glyph type
+ and test requesting a glyph image with zero height and one with zero width.
+
+@SYMTestExpectedResults
+ The function must identify wrong arguments and return the expected error.
+*/
+void CTGlyphImageCache::WrongParameterL(MFontGlyphImageStorage* aGlyphStorage)
+ {
+ _LIT(KTestName, "GlyphCache_WrongParameters");
+ if(!iRunningOomTests)
+ {
+ INFO_PRINTF1(KTestName);
+ }
+
+ aGlyphStorage->CleanGlyphImageCache();
+
+ TChar glyphCode = TChar(10);
+ TInt fontId = 10;
+ VGImage foregroundImg = VG_INVALID_HANDLE;
+ VGImage shadowImg = VG_INVALID_HANDLE;
+ VGImage outlineImg = VG_INVALID_HANDLE;
+ TSize fontSize = TSize(10, 12);
+ TUint8* buffer = (TUint8*)User::AllocL(fontSize.iWidth * fontSize.iHeight);
+ CleanupStack::PushL(buffer);
+
+ TGlyphBitmapType glyphType = EDefaultGlyphBitmap; // unsupported
+
+ TInt res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
+ TEST(res == KErrNotSupported);
+ TEST(foregroundImg == VG_INVALID_HANDLE);
+ TEST(shadowImg == VG_INVALID_HANDLE);
+ TEST(outlineImg == VG_INVALID_HANDLE);
+
+ glyphType = EMonochromeGlyphBitmap; // supported
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, TSize(12, 0), &foregroundImg, &shadowImg, &outlineImg);
+ TEST(res == KErrArgument);
+ res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, TSize(0, 12), &foregroundImg, &shadowImg, &outlineImg);
+ TEST(res == KErrArgument);
+ TEST(foregroundImg == VG_INVALID_HANDLE);
+ TEST(shadowImg == VG_INVALID_HANDLE);
+ TEST(outlineImg == VG_INVALID_HANDLE);
+
+ CleanupStack::PopAndDestroy(buffer);
+ }
+
+TInt CTGlyphImageCache::GlyphImageSizeInByte(TGlyphBitmapType aGlyphType, const TSize& aSize) const
+ {
+ TInt glyphSizeInByte = 0;
+ //calculate the actual size of the glyph
+ switch(aGlyphType)
+ {
+ case EMonochromeGlyphBitmap:
+ glyphSizeInByte = (((aSize.iWidth + 31) / 32) << 2) * aSize.iHeight;
+ break;
+ case EAntiAliasedGlyphBitmap:
+ glyphSizeInByte = aSize.iWidth * aSize.iHeight;
+ break;
+ case EFourColourBlendGlyphBitmap:
+ glyphSizeInByte = aSize.iWidth * aSize.iHeight;
+ //we have to allocate memory for shadow and outline bitmap as well
+ glyphSizeInByte *= 3;
+ break;
+ default :
+ break;
+ }
+ return glyphSizeInByte;
+ }
+/**
+Draws the text on the screen according its direction and alignment.
+*/
+void CTGlyphImageCache::DrawText(const TDesC& aText, const TPoint& aPt, DrawTextDirection aDirection, DrawTextAdjustment aDrawAdjustment, TBool aUpdateJustification)
+ {
+ const TSize size = iGdiTarget->SizeInPixels();
+ TRect rect = size;
+
+ if(aDirection == EDrawTextHorizontal)
+ {
+ switch(aDrawAdjustment)
+ {
+ case EDrawFromPoint:
+ iGc->DrawText(aText, NULL, aPt);
+ break;
+ case EDrawInBox:
+ iGc->SetOrigin(aPt);
+ rect = TRect(-aPt, size);
+ iGc->DrawText(aText, NULL, rect);
+ break;
+ case EDrawRightAlignment:
+ rect.iTl = aPt;
+ rect.iBr.iX -= 30;
+ iGc->DrawText(aText, NULL, rect, 0, DirectGdi::ERight);
+ break;
+ }
+ }
+ else if ((aDirection == EDrawTextVerticalDown) || (aDirection == EDrawTextVerticalUp))
+ {
+ TBool up = (aDirection==EDrawTextVerticalUp);
+ switch(aDrawAdjustment)
+ {
+ case EDrawFromPoint:
+ iGc->DrawTextVertical(aText, NULL, aPt, up);
+ break;
+ case EDrawInBox:
+ iGc->SetOrigin(aPt);
+ rect = TRect(-aPt, size);
+ if(aUpdateJustification)
+ {
+ iGc->SetCharJustification(80, aText.Length());
+ iGc->UpdateJustificationVertical(aText, NULL, up);
+ }
+
+ iGc->DrawTextVertical(aText, NULL, rect, up);
+ iGc->SetOrigin(TPoint());
+ break;
+ case EDrawRightAlignment:
+ rect.iTl = aPt;
+ rect.iBr.iY -= 30;
+ iGc->DrawTextVertical(aText, NULL, rect, 0, DirectGdi::ERight);
+ break;
+ }
+ }
+ }
+
+/**
+Overrides of base class virtual
+@leave Gets system wide error code
+@return - TVerdict code
+*/
+TVerdict CTGlyphImageCache::doTestStepPreambleL()
+ {
+ CTDirectGdiStepBase::doTestStepPreambleL();
+ return TestStepResult();
+ }
+
+/**
+Overrides of base class pure virtual
+Our implementation only gets called if the base class doTestStepPreambleL() did
+not leave. That being the case, the current test result value will be EPass.
+@leave Gets system wide error code
+@return TVerdict code
+*/
+TVerdict CTGlyphImageCache::doTestStepL()
+ {
+ // Test for each pixel format
+ TInt maxPixelFormat = iTargetPixelFormatArray.Count() - 1;
+ for(TInt targetPixelFormatIndex = maxPixelFormat; targetPixelFormatIndex >= 0 ; targetPixelFormatIndex--)
+ {
+ iTestParams.iTargetPixelFormat = iTargetPixelFormatArray[targetPixelFormatIndex];
+ SetTargetL(iTestParams.iTargetPixelFormat, EOneContextOneTarget, KGlyphCacheWindowSize);
+
+ if(maxPixelFormat == targetPixelFormatIndex)
+ {
+ iMonotypeFont = DetectMonotypeFontL();
+
+ if(!iMonotypeFont)
+ {
+ WARN_PRINTF1(_L("!! Due to running the test in environment without monotype fonts, some test cases will not \
+be executed! To set up environment with monotype font support, launch ityperast.cmd \
+from epoc32\\winscw\\c\\, and then follow the instruction on the screen!!"));
+ }
+ else
+ {
+ INFO_PRINTF1(_L("Monotype fonts have been detected"));
+ }
+ }
+
+ RunTestsL();
+ if(targetPixelFormatIndex == 0)
+ {
+ RunOomTestsL();
+ }
+ }
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+/**
+Overrides of base class pure virtual function
+Lists the tests to be run
+*/
+void CTGlyphImageCache::RunTestsL()
+ {
+ MFontGlyphImageStorage* glyphStorage = NULL;
+ TBool testImageCache = (iUseDirectGdi && !iUseSwDirectGdi);
+ if(testImageCache)
+ {
+ TInt err = iGc->GetInterface(TUid::Uid(KDirectGdiGetGlyphStorageUid), (TAny*&) glyphStorage);
+ if(err != KErrNone)
+ {
+ ERR_PRINTF2(_L("Error while retrieving Glyph Storage Interface, err = %d"), err);
+ TESTNOERRORL(err);
+ }
+ User::LeaveIfNull(glyphStorage);
+ CleanupStack::PushL(TCleanupItem(CleanCache, glyphStorage));
+ glyphStorage->CleanGlyphImageCache();
+ }
+
+ if(testImageCache)
+ {
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
+ TestRetrieveEntryL(glyphStorage, EAntiAliasedGlyphBitmap);
+ RecordTestResultL();
+ glyphStorage->CleanGlyphImageCache();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
+ TestRetrieveEntryL(glyphStorage, EFourColourBlendGlyphBitmap);
+ RecordTestResultL();
+ glyphStorage->CleanGlyphImageCache();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
+ TestRetrieveEntryL(glyphStorage, EMonochromeGlyphBitmap);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0006"));
+ WrongParameterL(glyphStorage);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0005"));
+ FontListIdOrderL(glyphStorage);
+ RecordTestResultL();
+ glyphStorage->CleanGlyphImageCache();
+ }
+
+ if(!iRunningOomTests)//fonts are cached in the array, where memory won't be freed even if the font is released
+ {
+ if(testImageCache)
+ {
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0004"));
+ FillCacheL(glyphStorage);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0003"));
+ FillUpCacheL(glyphStorage);
+ RecordTestResultL();
+ glyphStorage->CleanGlyphImageCache();
+ }
+ for(TInt ii = EDrawTextHorizontal; ii < EDrawTextLast; ii++)
+ {
+ for(TInt kk = EDrawFromPoint; kk <= EDrawInBox; kk++)
+ {
+ DrawTextDirection direction = (DrawTextDirection) ii;
+ DrawTextAdjustment adjustment = (DrawTextAdjustment) kk;
+
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EMonochromeGlyphBitmap, direction, adjustment, EFalse);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EMonochromeGlyphBitmap, direction, adjustment, ETrue);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EAntiAliasedGlyphBitmap, direction, adjustment, EFalse);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EAntiAliasedGlyphBitmap, direction, adjustment, ETrue);
+ RecordTestResultL();
+
+ if(iMonotypeFont)
+ {
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EFourColourBlendGlyphBitmap, direction, adjustment, EFalse);
+ RecordTestResultL();
+ SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
+ TestDrawGlyphL(glyphStorage, EFourColourBlendGlyphBitmap, direction, adjustment, ETrue);
+ RecordTestResultL();
+ }
+ }
+ }
+ }
+
+ //next set of tests should start from clean cache to garantee consistent results
+ if(testImageCache)
+ {
+ glyphStorage->CleanGlyphImageCache();
+ CleanupStack::Pop(glyphStorage);
+ }
+ }
+
+/**
+See if monotype font is installed on the platform we are running on. Monotype font is required
+to run the glyph tests that use the glyph bitmap type EFourColourBlendGlyphBitmap to draw
+outlined and shadowed fonts.
+@return ETrue if monotype is installed, EFalse if it is not installed.
+ */
+TBool CTGlyphImageCache::DetectMonotypeFontL()
+ {
+ CFont *font = NULL;
+ _LIT(KTestFontTypefaceName,"DejaVu Sans Condensed");
+ TFontSpec fspec(KTestFontTypefaceName, 12);
+ fspec.iFontStyle.SetBitmapType(EFourColourBlendGlyphBitmap);
+
+ fspec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ fspec.iFontStyle.SetEffects(FontEffect::EOutline, ETrue);
+ fspec.iFontStyle.SetEffects(FontEffect::EDropShadow, ETrue);
+
+ User::LeaveIfError(iFontStore->GetNearestFontToDesignHeightInPixels((CFont*&) font, fspec));
+
+ TFontSpec fontSpec = font->FontSpecInTwips();
+ TGlyphBitmapType glyphBitmapType = fontSpec.iFontStyle.BitmapType();
+ iFontStore->ReleaseFont(font);
+
+ return (EFourColourBlendGlyphBitmap==glyphBitmapType);
+ }