os/textandloc/fontservices/fontstore/tfs/T_SHAPERCACHE.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 /**
    20  @file
    21  @test
    22  @internalComponent Internal Symbian test code
    23 */
    24 
    25 
    26 #include <f32file.h>
    27 #include <e32test.h>
    28 #include <fntstore.h>
    29 #include <graphics/shapeimpl.h>
    30 #include "ShaperCache.H"
    31 #include "openfontsprivate.h"
    32 
    33 #include "T_SHAPERCACHE.H"
    34 #include "T_FSOPEN.H"
    35 
    36 _LIT(KFontDummy,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy");
    37 _LIT(KFontDummy_b,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_b");
    38 _LIT(KFontDummy_i,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_i");
    39 _LIT(KFontDummy_bi,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_bi");
    40 
    41 const TUint32 KDevanagariScriptCode = 0x64657661;
    42 _LIT16(KTextToShape, "\x0915\x094D\x0937\x0924\x094D\x0930\x093F\x092F");
    43 const TInt KResultNumberOfGlyphs = 4;
    44 
    45 CTShaperCache::~CTShaperCache()
    46 	{
    47 	delete iFontStore;
    48 	iHeap->__DbgMarkEnd(0);
    49 	iHeap->Close();
    50 	__UHEAP_MARKEND;
    51 	User::Heap().Check();
    52 	}
    53 
    54 CTShaperCache::CTShaperCache(CTestStep* aStep):
    55 	CTGraphicsBase(aStep)
    56 	{
    57 	INFO_PRINTF1(_L("FontStore T_ShaperCache test\n"));
    58 	}
    59 	
    60 void CTShaperCache::ConstructL()
    61 	{
    62 	__UHEAP_MARK;
    63 	iHeap = UserHeap::ChunkHeap(NULL,0x10000,0x100000);
    64 	if (iHeap == NULL)
    65 		User::Leave(KErrGeneral);
    66 	iHeap->__DbgMarkStart();
    67 	iFontStore = CFontStore::NewL(iHeap);
    68 	
    69 	// Install the dummy rasterizer.
    70 	COpenFontRasterizer* r = CDummyRasterizer::NewL();
    71 	CleanupStack::PushL(r);
    72 	iFontStore->InstallRasterizerL(r);
    73 	CleanupStack::Pop();
    74 
    75 	// Install the dummy shaper
    76 	CShaperFactory* shaperFactory = CDummyShaperFactory::NewL();
    77 	CleanupStack::PushL(shaperFactory);
    78 	iFontStore->InstallShaperFactoryL(shaperFactory);
    79 	CleanupStack::Pop();
    80 	}
    81 
    82 /**
    83 	@SYMTestCaseID
    84 	GRAPHICS-FNTSTORE-0043
    85 
    86 	@SYMTestCaseDesc
    87 	Tests creating and deleting a new shaper cache entry.
    88 	
    89 	@SYMTestActions
    90 	1. Allocated a TShapeHeader object on the heap/
    91 	2. Creates a CShaper object on the stack.
    92 	3. Allocates an entry for the TShapeHeader object in the cache.
    93 	4. Frees memory taken up by the entry to the cache.
    94 	5. The heap is checked for memory leaks.
    95 	
    96 	@SYMTestExpectedResults
    97 	No memory leaks should exist.
    98 */
    99 void CTShaperCache::Test1L()
   100 	{
   101 	INFO_PRINTF1(_L("ShaperCache Test1"));
   102 	__UHEAP_MARK;
   103 
   104 	TShapeHeader* shapeHeader=new TShapeHeader();
   105 	shapeHeader->iGlyphCount=10;
   106 	shapeHeader->iCharacterCount=20;
   107 
   108 	_LIT(KDummyText,"dummy");
   109 	CShaper::TInput input;
   110 	input.iStart=0;
   111 	input.iEnd=10;
   112 	input.iText=&(KDummyText());
   113 
   114 	//create/delete test a new shaper cache entry	
   115 	COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader);
   116 	COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry);
   117 	
   118 	delete shapeHeader;
   119 
   120 	__UHEAP_MARKEND;
   121 	}
   122 
   123 /**
   124 	@SYMTestCaseID
   125 	GRAPHICS-FNTSTORE-0044
   126 
   127 	@SYMTestCaseDesc
   128 	Tests ncrementation and decrementation of the reference 
   129 	count for a particular session handle.
   130 
   131 	@SYMTestActions
   132 	1. Creates a TShapeHeader object on the heap.
   133 	2. Set som values to the object.
   134 	3. Creates a CShaper object on the stack.
   135 	4. Creates a new shaper cache entry.
   136 	5. Associates a session with this entry.
   137 	6. Increments the reference count for a particular session (A) handle.
   138 	7. Increments the reference count for another session (B).
   139 	8. Decrements an instance from session (A).
   140 	9. Adds another session to the list (C).
   141 	10. Decrements the ref count for a particular session handle (C).
   142 	11. Tests decrement on non-existent session.
   143 	12. Frees memory taken up by the entry to the cache.
   144 	13. The heap is checked for memory leaks.
   145 	
   146 	@SYMTestExpectedResults
   147 	The decrementation of the non-existent session should return KErrNotFound.
   148 */
   149 void CTShaperCache::Test2L()
   150 	{
   151 	INFO_PRINTF1(_L("ShaperCache Test2"));
   152 	__UHEAP_MARK;
   153 
   154 	TShapeHeader* shapeHeader=new TShapeHeader();
   155 	shapeHeader->iGlyphCount=10;
   156 	shapeHeader->iCharacterCount=20;
   157 
   158 	_LIT(KDummyText,"dummy");
   159 	CShaper::TInput input;
   160 	input.iStart=0;
   161 	input.iEnd=10;
   162 	input.iText=&(KDummyText());
   163 
   164 	//create a new shaper cache entry	
   165 	COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader);
   166 	
   167 	//now associate a session with this entry
   168 	TInt dummySession=12;
   169 	TEST(shapeEntry->IncRefCount(dummySession)==KErrNone);
   170 	TEST(shapeEntry->iHandleRefCount==1);
   171 	TEST(shapeEntry->iHandleRefList!=NULL);
   172 	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession);
   173 	TEST(shapeEntry->iHandleRefList->iRefCount==1);	
   174 	//increment for another session, the THandleCount::iRef for this session should be 2
   175 	TEST(shapeEntry->IncRefCount(dummySession)==KErrNone);
   176 	TEST(shapeEntry->iHandleRefCount==1);
   177 	TEST(shapeEntry->iHandleRefList->iRefCount==2);				
   178 
   179 	//another entry for different session
   180 	TInt dummySession2=13;
   181 	TEST(shapeEntry->IncRefCount(dummySession2)==KErrNone);
   182 	TEST(shapeEntry->iHandleRefCount==2);
   183 	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession);
   184 	TEST(shapeEntry->iHandleRefList->iRefCount==2);
   185 	TEST(shapeEntry->iHandleRefList->iNext->iSessionHandle==dummySession2);
   186 	TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1);	
   187 	
   188 	//now decrement an instance from this session(DELETE FIRST ENTRY)
   189 	TEST(shapeEntry->DecRefCount(dummySession)==KErrNone);
   190 	TEST(shapeEntry->iHandleRefCount==2);
   191 	TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1);		
   192 	TEST(shapeEntry->DecRefCount(dummySession)==KErrNone);
   193 	TEST(shapeEntry->iHandleRefCount==1);
   194 	TEST(shapeEntry->iHandleRefList->iRefCount==1);			
   195 	TEST(shapeEntry->iHandleRefList->iSessionHandle=dummySession2);
   196 
   197 	//now add another session to this list
   198 	TInt dummySession3=14;
   199 	TEST(shapeEntry->IncRefCount(dummySession3)==KErrNone);
   200 	TEST(shapeEntry->iHandleRefCount==2);
   201 	//test delete this last entry in the list(DELETE LAST ENTRY)
   202 	TEST(shapeEntry->DecRefCount(dummySession3)==KErrNone);
   203 	TEST(shapeEntry->iHandleRefCount==1);	
   204 	TEST(shapeEntry->iHandleRefList->iRefCount==1);
   205 	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession2);
   206 
   207 
   208 	//test Dec on non-existent session
   209 	TEST(shapeEntry->DecRefCount(100)==KErrNotFound);
   210 
   211 	COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry);
   212 	delete shapeHeader;
   213 	
   214 	__UHEAP_MARKEND;		
   215 	}
   216 	
   217 /**
   218 	@SYMTestCaseID
   219 	GRAPHICS-FNTSTORE-0045
   220 
   221 	@SYMTestCaseDesc
   222 	Tests the shaper cache APIs.
   223 
   224 	@SYMTestActions
   225 	1. Creates a dummy TShapeHeader object that will be cached and reused through the test.
   226 	2. Gets some memory to pass back the results. It needs to be big enough for a TShapeHeader
   227 	   object plus 10 bytes for every glyph returned.
   228 	3. Finds or creates four font file objects to support a font file.
   229 	4. Gets the number of supported typefaces.
   230 	5. Creates a font.
   231 	6. Gets a COpenFont object.
   232 	7. For COpenFonts it attempts to put this into the shaper cache and test if it was successful.
   233 	8. Calls DeleteShape to decrement the reference count.
   234 	9. Changes the shaped data slightly to make it into a new shaped data and insert into the
   235 	   cache as a new entry.
   236 	10. Tests if the LRU cache is working by seeing if the first entry in the cache is the newest one.
   237 	11. Calls DeleteShape to decrement the reference count
   238 	12. Calls the GetShapedData API and tests the returned TShapeHeader. Also checks if the returned
   239 		cache entry is at the top of the cache.
   240     13. Searches the cache for the first entry using the GetShapedData API.
   241     14. Calls DeleteShape to decrement the reference count.
   242     15. Brings the end value back to its original value.
   243 	16. Fills the cache and then tests replacement policy by attempting to add a new entry.
   244 	17. Prepares a raw input data structure.
   245 	18. Keeps inserting pseudo-new shaped entries into the cache to fill it up.
   246 	19. Changes the cached entries slightly to distinguish between each entry.
   247 	20. Tries to add a new entry and checks that the entry replaced was the last entry in the cache.
   248 	21. Calculates the memory needed for the new entry.
   249 	22. Calculates the memory that will be freed to accommodate the new entry and the 
   250 	    position of the last entry in the cache once deletion is done.
   251 	23. Finds the glyphcount of the expected new last entry in the cache.
   252 	24. Does the insertion and tests.
   253 	25. Calls DeleteShape to decrement the reference count.
   254 	26. Calculates the memory occupied by the last entry in the cache. This is the memory that will
   255 		be released when the last entry is deleted.
   256 	27. Tests with multiple open fonts with caches. Creates the new font.
   257 	28. Does the testing only if the font is a COpenFont.
   258 	29. Attempts to put a new entry into the second shaper cache and test if it was successful.
   259 	30. Creates a pseudo-new shape header to put into the cache of this new open font.
   260 	31. Inserst an entry into the cache.
   261 	32. Tests cache memory freeing policy, i.e. delete from all other caches except the current one.
   262 	33. Finds out how much memory needs freeing, i.e. how much was just added.
   263 	34. Tries to free memory from the original open font cache. The result should be that
   264 		memory should be freed from openFont2 cache, and not openFont cache.
   265 	35. Checks
   266 		a) if the memory used by openFont2 cache has reduced, i.e. back to original memory.
   267 		b) if the last entry from openFont2 cache has been deleted.
   268 		c) last entry from openFont cache is intact.
   269 	36. Cleans up font2, font1 and removes all fonts.	
   270 		
   271 	@SYMTestExpectedResults
   272 	All tests shall pass.
   273 
   274 */
   275 void CTShaperCache::TestShaperCacheAPIsL()
   276 	{
   277 	INFO_PRINTF1(_L("The following results are for shaper cache API tests\n"));
   278 	
   279 	// Create a dummy TShapeHeader object that will be cached, and reused all through this test
   280 	TShapeHeader* shape = 0;
   281 	
   282 	// get some memory to pass back the results,  
   283 	// This needs to be big enough for a TShapeHeader
   284 	// plus 10 bytes for every glyph returned (-1 for the 1 byte allocated in TShapeHeader for iBuffer)
   285 	shape = reinterpret_cast<TShapeHeader*>( iHeap->AllocL(sizeof(TShapeHeader) + (KResultNumberOfGlyphs * 10) + 3) );
   286 
   287 	// get the results into the shaper structure 'shape'
   288 	shape->iGlyphCount = KResultNumberOfGlyphs;
   289 	shape->iCharacterCount = 8;
   290  	shape->iReserved0 = 0;
   291 	shape->iReserved1 = 0;
   292 
   293  	// iBuffer contains 10 bytes for every glyph
   294  	// the glyph code (4 bytes), position X(2 bytes) Y(2 bytes) and indices(2 bytes)
   295   	// first is glyph count * 4 byte glyph codes
   296  	TUint32* glyphOut = reinterpret_cast<TUint32*>(shape->iBuffer);
   297  	TInt16* posOut = reinterpret_cast<TInt16*>(shape->iBuffer +
   298  		(4 * KResultNumberOfGlyphs));
   299  	TInt16* indicesOut = reinterpret_cast<TInt16*>(shape->iBuffer +
   300  		(8 * KResultNumberOfGlyphs) + 4);
   301  	
   302  	*glyphOut++ = (TUint32)1461;
   303 	*posOut++ = (TInt16)0;
   304 	*posOut++ = (TInt16)0;
   305 	*indicesOut++ = (TInt16)0;
   306 	
   307 	*glyphOut++ = (TUint32)1778;
   308 	*posOut++ = (TInt16)12;
   309 	*posOut++ = (TInt16)0;
   310 	*indicesOut++ = (TInt16)7;
   311 	
   312 	*glyphOut++ = (TUint32)1550;
   313 	*posOut++ = (TInt16)16;
   314 	*posOut++ = (TInt16)0;
   315 	*indicesOut++ = (TInt16)3;
   316 	
   317 	*glyphOut++ = (TUint32)1362;
   318 	*posOut++ = (TInt16)28;
   319 	*posOut++ = (TInt16)0;
   320 	*indicesOut++ = (TInt16)7;
   321  		
   322  	// There is an extra pair of positions: this is the total advance
   323 	posOut[0] = (TInt16)28;
   324 	posOut[1] = (TInt16)0;
   325 	
   326 	TFontShapeFunctionParameters* params;
   327 	params = reinterpret_cast<TFontShapeFunctionParameters*>( iHeap->AllocL(sizeof(TFontShapeFunctionParameters)));
   328 	params->iEnd = 8;
   329 	params->iLanguage = 0;
   330 	params->iScript = KDevanagariScriptCode;
   331 	params->iStart = 0;
   332 	//TBufC16<9> text(KTextToShape);
   333 	params->iText = &KTextToShape();
   334 
   335 		// Add fonts
   336 	TUid id1 = iFontStore->AddFileL(KFontDummy);
   337 	TUid id2 = iFontStore->AddFileL(KFontDummy_b);
   338 	TUid id3 = iFontStore->AddFileL(KFontDummy_i);
   339 	TUid id4 = iFontStore->AddFileL(KFontDummy_bi);
   340 	
   341 	INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 1: Testing cache with a single COpentFont cache"));
   342 
   343 	TInt typefaces = iFontStore->NumTypefaces();
   344 	TInt typeface = 0;
   345 	TInt height = 12;
   346 
   347 	TTypefaceSupport support;
   348 	iFontStore->TypefaceSupport(support,typeface);
   349 	TFontSpec fs;
   350 	fs.iTypeface = support.iTypeface;
   351 
   352 	INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height);
   353 	//Create a font
   354 	CFont* font = NULL;
   355 	fs.iHeight = iFontStore->FontHeightInTwips(typeface,height);
   356 	// get a COpenFont object
   357 	iFontStore->GetNearestFontToDesignHeightInPixels(font, fs);	
   358 	CleanupStack::PushL(font);
   359 	
   360 	
   361 	// Do the testing only if the font is a COpenFont
   362 	COpenFont* openFont = NULL;
   363 	CShaper::TInput input;
   364 	if (((CBitmapFont*)font)->IsOpenFont())
   365 		{
   366 		__UHEAP_MARK;
   367 		openFont = ((CBitmapFont*)font)->OpenFont();
   368 		
   369 		/***************************First Test***************************
   370 		Attempt to put this into the shaper cache and then delete it. Test if it was successful
   371 		*/
   372 		TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(0,params, shape);
   373 
   374 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 1: Simple cache insertion test"));
   375 		TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   376 		
   377 		/* Call DeleteShape to decrement the reference count */
   378 		((CBitmapFont*)font)->DeleteShape(0, cached_header);
   379 		
   380 		// Now delete this data
   381 		openFont->FreeShaperCacheMemory(openFont->GetGlyphCache()->iShapingInfoCacheMemory);
   382 		TEST(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 1);
   383 		// Put the shaped data back into the cache to continue with testing
   384 		cached_header = openFont->InsertShapedDataIntoCache(0,params, shape);
   385 		TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   386 		((CBitmapFont*)font)->DeleteShape(0, cached_header);		
   387 		
   388 		/**************************Second Test**************************
   389 		Now change the shaped data slightly to make it into a new shaped data and insert into the
   390 		cache as a new entry
   391 		*/
   392 		shape->iGlyphCount++;
   393 		params->iEnd++;
   394 		TShapeHeader* cached_header2 = openFont->InsertShapedDataIntoCache(0,params, shape);
   395 		
   396 		/* Now test if the LRU cache is working by seeing if the first entry in the cache is the newest one */
   397 		COpenFontGlyphCache* glyphCache = openFont->GetGlyphCache();
   398 		
   399 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 2: Test the LRU (Least Recently Used) cache structure"));
   400 		TEST(glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount == KResultNumberOfGlyphs + 1);
   401 		
   402 		/* Call DeleteShape to decrement the reference count */
   403 		((CBitmapFont*)font)->DeleteShape(0, cached_header2);
   404 		
   405 		
   406 		/**************************Third Test**************************
   407 		Call the GetShapedData API and test the returned TShapeHeader, and also check if the returned
   408 		cache entry is now at the top of the cache
   409 		*/
   410 		
   411 		/* Now search the cache for the first entry using the GetShapedData API */
   412 		params->iEnd --;
   413 		TInt expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   414 		TShapeHeader* searchedCachedHeader = openFont->GetShapedData(0,params);
   415 
   416 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 3: GetShapedData API test"));
   417 		TEST(searchedCachedHeader->iGlyphCount == expectedGlyphCount &&
   418 			 searchedCachedHeader->iGlyphCount ==glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount);
   419 		
   420 		/* Call DeleteShape to decrement the reference count */
   421 		((CBitmapFont*)font)->DeleteShape(0, searchedCachedHeader);
   422 		
   423 		/* Bring the end value back to its original value */
   424 		params->iEnd ++;
   425 		
   426 		
   427 		/**************************Fourth Test**************************
   428 		Fill the cache and then test replacement policy by attempting to add a new entry
   429 		*/
   430 	
   431 		/* First prepare a raw input data structure */
   432 		TInt memoryUsed = 0;
   433 		input.iText = &KTextToShape();
   434 		input.iStart = 0;
   435 		input.iEnd = params->iEnd;
   436 		input.iScript= KDevanagariScriptCode;
   437 		input.iLanguage = 0;
   438 		input.iMaximumAdvance = KMaxTInt;
   439 		input.iFlags = 0;
   440 		input.iSessionHandle = 0;
   441 		input.iReserved1 = 0;
   442 		TInt addedBytes = 0;
   443 		TShapeHeader* chached_header3 = 0;
   444 		openFont->FreeShaperCacheMemory(KMaxShaperSesssionCacheMemory);
   445 		openFont->File()->GetFontStore()->SetShaperCacheMemUsage(0);
   446 		RArray<TInt> cacheMemUsage;
   447 		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
   448 		while(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() < KMaxShaperSesssionCacheMemory)
   449 			{
   450 			memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
   451 			// Change the cached entries slightly to distinguish between each entry
   452 			shape->iGlyphCount++;
   453 			input.iEnd++;
   454 			chached_header3 = glyphCache->Insert(0,iHeap, input, shape, addedBytes);
   455 			if (chached_header3 != NULL)
   456 				openFont->File()->GetFontStore()->SetShaperCacheMemUsage(memoryUsed + addedBytes);
   457 			((CBitmapFont*)font)->DeleteShape(0, chached_header3);
   458 			cacheMemUsage.AppendL(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() - memoryUsed);
   459 			chached_header3 = NULL;
   460 			}
   461 		
   462 		/* Now try to add a new entry, and check that the entry replaced was the last entry in the cache */
   463 		TInt last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   464 		shape->iGlyphCount++;
   465 		input.iEnd++;
   466 		params->iEnd = input.iEnd;
   467 		
   468 		/* Calculate the memory needed for the new entry */
   469 
   470 		
   471         TInt heapSizeBefAloc = 0;
   472         iHeap->AllocSize(heapSizeBefAloc);      
   473         COpenFontShaperCacheEntry *tempEntry = COpenFontShaperCacheEntry::New(iHeap, input, shape);
   474         TInt heapSizeAftAloc = 0;
   475         iHeap->AllocSize(heapSizeAftAloc);
   476         TInt bytes_needed = heapSizeAftAloc - heapSizeBefAloc;
   477         COpenFontShaperCacheEntry::Delete(iHeap, tempEntry);
   478         
   479 		TInt bytesToDelete = 0;    
   480 	    
   481 		COpenFontShaperCacheEntry* previous = glyphCache->iShaperCacheSentinel->iPrevious;
   482 		/* Calculate the memory that will be freed to accommodate the new entry,
   483 		   and the position of the last entry in the cache once deletion is done */
   484 		TInt index = 0;
   485 		while (bytesToDelete <= bytes_needed)
   486 			{
   487 
   488              bytesToDelete += cacheMemUsage[index++];
   489 			 previous = previous->iPrevious;
   490 			}
   491 		cacheMemUsage.Close();	
   492 		/* Find the glyphcount of the expected new last entry in the cache */
   493 		expectedGlyphCount = previous->iShapeHeader->iGlyphCount;
   494 		
   495 		/* Finally, do the insertion, and test */
   496 		TShapeHeader* cached_header4 = openFont->InsertShapedDataIntoCache(0, params, shape);
   497 		
   498 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 4: LRU cache replacement policy test"));
   499 		TEST(glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   500 
   501 		/* Call DeleteShape to decrement the reference cout */
   502 		((CBitmapFont*)font)->DeleteShape(0, cached_header4);
   503 		
   504 		
   505 		/**************************Fifth Test**************************
   506 		Simply test the FreeShaperCacheMemory API
   507 		*/
   508 				
   509 		/* Calculate the memory of occupied by the last entry in the cache. This is the memory that will
   510 		   be released when the last entry is deleted
   511 		 */
   512 		last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   513 		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
   514 				* last_entry_glyph_count + sizeof(TInt16) * 2;
   515 
   516 		bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
   517 			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
   518 		
   519 		memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
   520 		expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iPrevious->iShapeHeader->iGlyphCount;
   521 		TInt memoryReleased = openFont->FreeShaperCacheMemory(bytes_needed);
   522 		
   523 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 5: FreeShaperCacheMemory API test\n"));
   524 		TEST(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() == memoryUsed - memoryReleased &&
   525 			 glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   526 	
   527 		__UHEAP_MARKEND;
   528 		}
   529 		
   530 	INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 2: Testing cache with a two COpentFont caches"));
   531 	/* Now test with multiple open fonts with caches */
   532 	/* Create the new font */
   533 	height = 4;
   534 	iFontStore->TypefaceSupport(support,typeface);
   535 	fs.iTypeface = support.iTypeface;
   536 
   537 	INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height);
   538 
   539 	CFont* font2 = NULL;
   540 	fs.iHeight = iFontStore->FontHeightInTwips(typeface,height);
   541 	iFontStore->GetNearestFontToDesignHeightInPixels(font2, fs);	
   542 	CleanupStack::PushL(font2);
   543 	
   544 	COpenFont* openFont2;
   545 	/* Do the testing only if the font is a COpenFont */
   546 	if (((CBitmapFont*)font2)->IsOpenFont())
   547 		{
   548 		__UHEAP_MARK;
   549 		openFont2 = ((CBitmapFont*)font2)->OpenFont();
   550 		
   551 		/***************************Sixth Test***************************
   552 		Attempt to put a new entry into the second shaper cache and test if it was successful
   553 		*/
   554 		
   555 		/* Create a pseudo-new shape header to put into the cache of this new open font */
   556 		shape->iGlyphCount++;
   557 		params->iEnd++;
   558 		
   559 		/* Insert an entry into the cache */
   560 		TShapeHeader* cached_header5 = openFont2->InsertShapedDataIntoCache(0, params, shape);
   561 		((CBitmapFont*)font2)->DeleteShape(0, cached_header5);
   562 
   563 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 6: Second cache insertion test"));
   564 		TEST(cached_header5 != NULL && openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   565 
   566 		/***************************Seventh, Eighth and Ninth Tests***************************
   567 		Test cache memory freeing policy, i.e. delete from all other caches except the current one
   568 		*/
   569 		
   570 		/* First find out how much memory needs freeing, i.e. how much was just added */
   571 		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
   572 					* shape->iGlyphCount + sizeof(TInt16) * 2;
   573 
   574 		TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
   575 			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
   576 
   577 		
   578 		/* Now try to free memory from the original open font cache. The result should be that
   579 		   memory should be freed from openFont2 cache, and not openFont cache
   580 		 */
   581 		TInt memoryUsed = openFont2->GetGlyphCache()->iShapingInfoCacheMemory;
   582 		TInt expectedGlyphCount = openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   583 		TInt deletedMemory = openFont->FreeShaperCacheMemory(bytes_needed);
   584 		
   585 		/* Now check:
   586 		   a) if the memory used by openFont2 cache has reduced, i.e. back to original memory
   587 		   b) if the last entry from openFont2 cache has been deleted
   588 		   c) last entry from openFont cache is intact
   589 		*/
   590 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 7: Test if memory is freed from second COpenFont"));
   591 		TEST(memoryUsed - openFont2->GetGlyphCache()->iShapingInfoCacheMemory ==  deletedMemory &&
   592 			openFont2->GetGlyphCache()->iShapingInfoCacheMemory == 0);
   593 
   594 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 8: Test if last entry of second COpenFont is deleted"));
   595 		TEST(openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 1);
   596 
   597 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 9: Test if the last entry of the first COpenFont is intact"));
   598 		TEST(openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   599 		
   600 		/***********************************Tenth Tests*****************************************
   601 		Test cache memory consistency and that there are no leakages when deleting memory from the cache
   602 		*/
   603 		
   604 		/* Continue adding entries to second open font cache until the memory used by the first one
   605 		   goes down to zero, at which point the number of cache entries should be 1, and memory from
   606 		   the current open font should start getting released and eventually reach 0 when the number
   607 		   of cached entries reaches 1.
   608 		*/
   609 		TShapeHeader* cached_header6 = NULL;
   610 		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
   611 		while(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries > 1)
   612 			{
   613 			memoryUsed = openFont2->File()->GetFontStore()->GetShaperCacheMemUsage();
   614 			// Change the cached entries slightly to distinguish between each entry
   615 			shape->iGlyphCount++;
   616 			params->iEnd++;
   617 			cached_header6 = openFont2->InsertShapedDataIntoCache(0, params, shape);
   618 			((CBitmapFont*)font2)->DeleteShape(0, cached_header6);
   619 			cached_header6 = NULL;
   620 			}
   621 			
   622 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 10: Test consistency of cache memory"));
   623 		TEST(openFont->GetGlyphCache()->iShapingInfoCacheMemory == 0);
   624 		
   625 		
   626 		/**
   627 		@SYMTestCaseID          GRAPHICS-SYSLIB-FNTSTORE-UT-4001
   628 		@SYMTestCaseDesc        Test that when trying to delete a shape not in the cache it
   629 								does not loop infinitely trying to find it.
   630 		@SYMTestPriority        Medium
   631 		@SYMTestActions         Pass a null shape header to the DeleteShape function.
   632 		@SYMTestExpectedResults	The function call should return instead of looping infinitely.
   633 		@SYMDEF                 PDEF125354
   634 		*/
   635 		((CTShaperCacheStep*)iStep)->RecordTestResultL();
   636 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-SYSLIB-FNTSTORE-UT-4001"));
   637 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 11: Test that shape not found does not loop infinitely."));
   638 		TShapeHeader* null_header = NULL;
   639 		// Timeout set in TEF script to catch infinite loop.
   640 		((CBitmapFont*)font2)->DeleteShape(0, null_header);
   641 		
   642 		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
   643 		__UHEAP_MARKEND;
   644 		}
   645 	
   646 	/* Cleanup font2*/
   647 	CleanupStack::Pop(font2);
   648 	iFontStore->ReleaseFont(font2);
   649 	
   650 	/* Cleanup font1 */	
   651 	CleanupStack::Pop(font);
   652 	iFontStore->ReleaseFont(font);
   653 
   654 	// Remove the fonts
   655 	iFontStore->RemoveFile(id1);
   656 	iFontStore->RemoveFile(id2);
   657 	iFontStore->RemoveFile(id3);
   658 	iFontStore->RemoveFile(id4);
   659 	}
   660 
   661 void CTShaperCache::RunTestCaseL(TInt aCurTestCase)
   662 	{
   663 	((CTShaperCacheStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
   664 	switch(aCurTestCase)
   665 		{
   666 	case 1:
   667 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0043"));
   668 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 1 ########################\n"));
   669 		TRAPD(err,Test1L());
   670 		TEST(err == KErrNone);
   671 		break;
   672 	case 2:
   673 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0044"));
   674 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 2 ########################\n"));
   675 		TRAP(err,Test2L());
   676 		TEST(err == KErrNone);
   677 		break;
   678 	case 3:
   679 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0045"));		
   680 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 3 ########################"));
   681 		TRAP(err,TestShaperCacheAPIsL());
   682 		TEST(err == KErrNone);
   683 		break;		
   684 	case 4:
   685         	((CTShaperCacheStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
   686     		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
   687 		TestComplete();				
   688 		break;
   689 		}
   690 	((CTShaperCacheStep*)iStep)->RecordTestResultL();
   691 	}
   692 
   693 
   694 //--------------
   695 __CONSTRUCT_STEP__(ShaperCache)
   696 
   697 
   698