graphicsdeviceinterface/directgdi/test/tglyphimagecache.cpp
changeset 0 5d03bc08d59c
--- /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);
+	}