fontservices/fontstore/tfs/T_SHAPERCACHE.CPP
changeset 0 1fb32624e06b
child 37 6be019398652
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     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 		
       
   445 		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
       
   446 		while(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() < KMaxShaperSesssionCacheMemory)
       
   447 			{
       
   448 			memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
       
   449 			// Change the cached entries slightly to distinguish between each entry
       
   450 			shape->iGlyphCount++;
       
   451 			input.iEnd++;
       
   452 			chached_header3 = glyphCache->Insert(0,iHeap, input, shape, addedBytes);
       
   453 			if (chached_header3 != NULL)
       
   454 				openFont->File()->GetFontStore()->SetShaperCacheMemUsage(memoryUsed + addedBytes);
       
   455 			((CBitmapFont*)font)->DeleteShape(0, chached_header3);
       
   456 			chached_header3 = NULL;
       
   457 			}
       
   458 		
       
   459 		/* Now try to add a new entry, and check that the entry replaced was the last entry in the cache */
       
   460 		TInt last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
       
   461 		shape->iGlyphCount++;
       
   462 		params->iEnd = input.iEnd + 1;
       
   463 		
       
   464 		/* Calculate the memory needed for the new entry */
       
   465 		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
       
   466 				* shape->iGlyphCount + sizeof(TInt16) * 2;
       
   467 		TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
       
   468 			sizeof(TShapeHeader) + sizeof(TUint16)*params->iText->Length();
       
   469 		
       
   470 		TInt bytesToDelete = 0;
       
   471 		COpenFontShaperCacheEntry* previous = glyphCache->iShaperCacheSentinel->iPrevious;
       
   472 		/* Calculate the memory that will be freed to accommodate the new entry,
       
   473 		   and the position of the last entry in the cache once deletion is done */
       
   474 		while (bytesToDelete <= bytes_needed)
       
   475 			{
       
   476 			bytesToDelete += (((sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2) * previous->iShapeHeader->iGlyphCount + sizeof(TInt16) * 2) + 
       
   477 				(sizeof(COpenFontShaperCacheEntry) + sizeof(TShapeHeader) + sizeof(TUint16)*params->iText->Length()));
       
   478 			previous = previous->iPrevious;
       
   479 			}
       
   480 			
       
   481 		/* Find the glyphcount of the expected new last entry in the cache */
       
   482 		expectedGlyphCount = previous->iShapeHeader->iGlyphCount;
       
   483 		
       
   484 		/* Finally, do the insertion, and test */
       
   485 		TShapeHeader* cached_header4 = openFont->InsertShapedDataIntoCache(0, params, shape);
       
   486 		
       
   487 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 4: LRU cache replacement policy test"));
       
   488 		TEST(glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
       
   489 
       
   490 		/* Call DeleteShape to decrement the reference cout */
       
   491 		((CBitmapFont*)font)->DeleteShape(0, cached_header4);
       
   492 		
       
   493 		
       
   494 		/**************************Fifth Test**************************
       
   495 		Simply test the FreeShaperCacheMemory API
       
   496 		*/
       
   497 				
       
   498 		/* Calculate the memory of occupied by the last entry in the cache. This is the memory that will
       
   499 		   be released when the last entry is deleted
       
   500 		 */
       
   501 		last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
       
   502 		bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
       
   503 				* last_entry_glyph_count + sizeof(TInt16) * 2;
       
   504 
       
   505 		bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
       
   506 			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
       
   507 		
       
   508 		memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
       
   509 		expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iPrevious->iShapeHeader->iGlyphCount;
       
   510 		TInt memoryReleased = openFont->FreeShaperCacheMemory(bytes_needed);
       
   511 		
       
   512 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 5: FreeShaperCacheMemory API test\n"));
       
   513 		TEST(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() == memoryUsed - memoryReleased &&
       
   514 			 glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
       
   515 	
       
   516 		__UHEAP_MARKEND;
       
   517 		}
       
   518 		
       
   519 	INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 2: Testing cache with a two COpentFont caches"));
       
   520 	/* Now test with multiple open fonts with caches */
       
   521 	/* Create the new font */
       
   522 	height = 4;
       
   523 	iFontStore->TypefaceSupport(support,typeface);
       
   524 	fs.iTypeface = support.iTypeface;
       
   525 
       
   526 	INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height);
       
   527 
       
   528 	CFont* font2 = NULL;
       
   529 	fs.iHeight = iFontStore->FontHeightInTwips(typeface,height);
       
   530 	iFontStore->GetNearestFontToDesignHeightInPixels(font2, fs);	
       
   531 	CleanupStack::PushL(font2);
       
   532 	
       
   533 	COpenFont* openFont2;
       
   534 	/* Do the testing only if the font is a COpenFont */
       
   535 	if (((CBitmapFont*)font2)->IsOpenFont())
       
   536 		{
       
   537 		__UHEAP_MARK;
       
   538 		openFont2 = ((CBitmapFont*)font2)->OpenFont();
       
   539 		
       
   540 		/***************************Sixth Test***************************
       
   541 		Attempt to put a new entry into the second shaper cache and test if it was successful
       
   542 		*/
       
   543 		
       
   544 		/* Create a pseudo-new shape header to put into the cache of this new open font */
       
   545 		shape->iGlyphCount++;
       
   546 		params->iEnd++;
       
   547 		
       
   548 		/* Insert an entry into the cache */
       
   549 		TShapeHeader* cached_header5 = openFont2->InsertShapedDataIntoCache(0, params, shape);
       
   550 		((CBitmapFont*)font2)->DeleteShape(0, cached_header5);
       
   551 
       
   552 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 6: Second cache insertion test"));
       
   553 		TEST(cached_header5 != NULL && openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
       
   554 
       
   555 		/***************************Seventh, Eighth and Ninth Tests***************************
       
   556 		Test cache memory freeing policy, i.e. delete from all other caches except the current one
       
   557 		*/
       
   558 		
       
   559 		/* First find out how much memory needs freeing, i.e. how much was just added */
       
   560 		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
       
   561 					* shape->iGlyphCount + sizeof(TInt16) * 2;
       
   562 
       
   563 		TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
       
   564 			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
       
   565 
       
   566 		
       
   567 		/* Now try to free memory from the original open font cache. The result should be that
       
   568 		   memory should be freed from openFont2 cache, and not openFont cache
       
   569 		 */
       
   570 		TInt memoryUsed = openFont2->GetGlyphCache()->iShapingInfoCacheMemory;
       
   571 		TInt expectedGlyphCount = openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
       
   572 		TInt deletedMemory = openFont->FreeShaperCacheMemory(bytes_needed);
       
   573 		
       
   574 		/* Now check:
       
   575 		   a) if the memory used by openFont2 cache has reduced, i.e. back to original memory
       
   576 		   b) if the last entry from openFont2 cache has been deleted
       
   577 		   c) last entry from openFont cache is intact
       
   578 		*/
       
   579 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 7: Test if memory is freed from second COpenFont"));
       
   580 		TEST(memoryUsed - openFont2->GetGlyphCache()->iShapingInfoCacheMemory ==  deletedMemory &&
       
   581 			openFont2->GetGlyphCache()->iShapingInfoCacheMemory == 0);
       
   582 
       
   583 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 8: Test if last entry of second COpenFont is deleted"));
       
   584 		TEST(openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 1);
       
   585 
       
   586 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 9: Test if the last entry of the first COpenFont is intact"));
       
   587 		TEST(openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
       
   588 		
       
   589 		/***********************************Tenth Tests*****************************************
       
   590 		Test cache memory consistency and that there are no leakages when deleting memory from the cache
       
   591 		*/
       
   592 		
       
   593 		/* Continue adding entries to second open font cache until the memory used by the first one
       
   594 		   goes down to zero, at which point the number of cache entries should be 1, and memory from
       
   595 		   the current open font should start getting released and eventually reach 0 when the number
       
   596 		   of cached entries reaches 1.
       
   597 		*/
       
   598 		TShapeHeader* cached_header6 = NULL;
       
   599 		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
       
   600 		while(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries > 1)
       
   601 			{
       
   602 			memoryUsed = openFont2->File()->GetFontStore()->GetShaperCacheMemUsage();
       
   603 			// Change the cached entries slightly to distinguish between each entry
       
   604 			shape->iGlyphCount++;
       
   605 			params->iEnd++;
       
   606 			cached_header6 = openFont2->InsertShapedDataIntoCache(0, params, shape);
       
   607 			((CBitmapFont*)font2)->DeleteShape(0, cached_header6);
       
   608 			cached_header6 = NULL;
       
   609 			}
       
   610 			
       
   611 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 10: Test consistency of cache memory"));
       
   612 		TEST(openFont->GetGlyphCache()->iShapingInfoCacheMemory == 0);
       
   613 		
       
   614 		
       
   615 		/**
       
   616 		@SYMTestCaseID          GRAPHICS-SYSLIB-FNTSTORE-UT-4001
       
   617 		@SYMTestCaseDesc        Test that when trying to delete a shape not in the cache it
       
   618 								does not loop infinitely trying to find it.
       
   619 		@SYMTestPriority        Medium
       
   620 		@SYMTestActions         Pass a null shape header to the DeleteShape function.
       
   621 		@SYMTestExpectedResults	The function call should return instead of looping infinitely.
       
   622 		@SYMDEF                 PDEF125354
       
   623 		*/
       
   624 		((CTShaperCacheStep*)iStep)->RecordTestResultL();
       
   625 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-SYSLIB-FNTSTORE-UT-4001"));
       
   626 		INFO_PRINTF1(_L("SHAPER CACHE API TEST 11: Test that shape not found does not loop infinitely."));
       
   627 		TShapeHeader* null_header = NULL;
       
   628 		// Timeout set in TEF script to catch infinite loop.
       
   629 		((CBitmapFont*)font2)->DeleteShape(0, null_header);
       
   630 		
       
   631 		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
       
   632 		__UHEAP_MARKEND;
       
   633 		}
       
   634 	
       
   635 	/* Cleanup font2*/
       
   636 	CleanupStack::Pop(font2);
       
   637 	iFontStore->ReleaseFont(font2);
       
   638 	
       
   639 	/* Cleanup font1 */	
       
   640 	CleanupStack::Pop(font);
       
   641 	iFontStore->ReleaseFont(font);
       
   642 
       
   643 	// Remove the fonts
       
   644 	iFontStore->RemoveFile(id1);
       
   645 	iFontStore->RemoveFile(id2);
       
   646 	iFontStore->RemoveFile(id3);
       
   647 	iFontStore->RemoveFile(id4);
       
   648 	}
       
   649 
       
   650 void CTShaperCache::RunTestCaseL(TInt aCurTestCase)
       
   651 	{
       
   652 	((CTShaperCacheStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
       
   653 	switch(aCurTestCase)
       
   654 		{
       
   655 	case 1:
       
   656 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0043"));
       
   657 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 1 ########################\n"));
       
   658 		TRAPD(err,Test1L());
       
   659 		TEST(err == KErrNone);
       
   660 		break;
       
   661 	case 2:
       
   662 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0044"));
       
   663 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 2 ########################\n"));
       
   664 		TRAP(err,Test2L());
       
   665 		TEST(err == KErrNone);
       
   666 		break;
       
   667 	case 3:
       
   668 		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0045"));		
       
   669 		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 3 ########################"));
       
   670 		TRAP(err,TestShaperCacheAPIsL());
       
   671 		TEST(err == KErrNone);
       
   672 		break;		
       
   673 	case 4:
       
   674         	((CTShaperCacheStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
       
   675     		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
       
   676 		TestComplete();				
       
   677 		break;
       
   678 		}
       
   679 	((CTShaperCacheStep*)iStep)->RecordTestResultL();
       
   680 	}
       
   681 
       
   682 
       
   683 //--------------
       
   684 __CONSTRUCT_STEP__(ShaperCache)
       
   685 
       
   686 
       
   687