os/textandloc/fontservices/fontstore/tfs/T_SHAPERCACHE.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/fontservices/fontstore/tfs/T_SHAPERCACHE.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,698 @@
     1.4 +/*
     1.5 +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +/**
    1.23 + @file
    1.24 + @test
    1.25 + @internalComponent Internal Symbian test code
    1.26 +*/
    1.27 +
    1.28 +
    1.29 +#include <f32file.h>
    1.30 +#include <e32test.h>
    1.31 +#include <fntstore.h>
    1.32 +#include <graphics/shapeimpl.h>
    1.33 +#include "ShaperCache.H"
    1.34 +#include "openfontsprivate.h"
    1.35 +
    1.36 +#include "T_SHAPERCACHE.H"
    1.37 +#include "T_FSOPEN.H"
    1.38 +
    1.39 +_LIT(KFontDummy,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy");
    1.40 +_LIT(KFontDummy_b,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_b");
    1.41 +_LIT(KFontDummy_i,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_i");
    1.42 +_LIT(KFontDummy_bi,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_bi");
    1.43 +
    1.44 +const TUint32 KDevanagariScriptCode = 0x64657661;
    1.45 +_LIT16(KTextToShape, "\x0915\x094D\x0937\x0924\x094D\x0930\x093F\x092F");
    1.46 +const TInt KResultNumberOfGlyphs = 4;
    1.47 +
    1.48 +CTShaperCache::~CTShaperCache()
    1.49 +	{
    1.50 +	delete iFontStore;
    1.51 +	iHeap->__DbgMarkEnd(0);
    1.52 +	iHeap->Close();
    1.53 +	__UHEAP_MARKEND;
    1.54 +	User::Heap().Check();
    1.55 +	}
    1.56 +
    1.57 +CTShaperCache::CTShaperCache(CTestStep* aStep):
    1.58 +	CTGraphicsBase(aStep)
    1.59 +	{
    1.60 +	INFO_PRINTF1(_L("FontStore T_ShaperCache test\n"));
    1.61 +	}
    1.62 +	
    1.63 +void CTShaperCache::ConstructL()
    1.64 +	{
    1.65 +	__UHEAP_MARK;
    1.66 +	iHeap = UserHeap::ChunkHeap(NULL,0x10000,0x100000);
    1.67 +	if (iHeap == NULL)
    1.68 +		User::Leave(KErrGeneral);
    1.69 +	iHeap->__DbgMarkStart();
    1.70 +	iFontStore = CFontStore::NewL(iHeap);
    1.71 +	
    1.72 +	// Install the dummy rasterizer.
    1.73 +	COpenFontRasterizer* r = CDummyRasterizer::NewL();
    1.74 +	CleanupStack::PushL(r);
    1.75 +	iFontStore->InstallRasterizerL(r);
    1.76 +	CleanupStack::Pop();
    1.77 +
    1.78 +	// Install the dummy shaper
    1.79 +	CShaperFactory* shaperFactory = CDummyShaperFactory::NewL();
    1.80 +	CleanupStack::PushL(shaperFactory);
    1.81 +	iFontStore->InstallShaperFactoryL(shaperFactory);
    1.82 +	CleanupStack::Pop();
    1.83 +	}
    1.84 +
    1.85 +/**
    1.86 +	@SYMTestCaseID
    1.87 +	GRAPHICS-FNTSTORE-0043
    1.88 +
    1.89 +	@SYMTestCaseDesc
    1.90 +	Tests creating and deleting a new shaper cache entry.
    1.91 +	
    1.92 +	@SYMTestActions
    1.93 +	1. Allocated a TShapeHeader object on the heap/
    1.94 +	2. Creates a CShaper object on the stack.
    1.95 +	3. Allocates an entry for the TShapeHeader object in the cache.
    1.96 +	4. Frees memory taken up by the entry to the cache.
    1.97 +	5. The heap is checked for memory leaks.
    1.98 +	
    1.99 +	@SYMTestExpectedResults
   1.100 +	No memory leaks should exist.
   1.101 +*/
   1.102 +void CTShaperCache::Test1L()
   1.103 +	{
   1.104 +	INFO_PRINTF1(_L("ShaperCache Test1"));
   1.105 +	__UHEAP_MARK;
   1.106 +
   1.107 +	TShapeHeader* shapeHeader=new TShapeHeader();
   1.108 +	shapeHeader->iGlyphCount=10;
   1.109 +	shapeHeader->iCharacterCount=20;
   1.110 +
   1.111 +	_LIT(KDummyText,"dummy");
   1.112 +	CShaper::TInput input;
   1.113 +	input.iStart=0;
   1.114 +	input.iEnd=10;
   1.115 +	input.iText=&(KDummyText());
   1.116 +
   1.117 +	//create/delete test a new shaper cache entry	
   1.118 +	COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader);
   1.119 +	COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry);
   1.120 +	
   1.121 +	delete shapeHeader;
   1.122 +
   1.123 +	__UHEAP_MARKEND;
   1.124 +	}
   1.125 +
   1.126 +/**
   1.127 +	@SYMTestCaseID
   1.128 +	GRAPHICS-FNTSTORE-0044
   1.129 +
   1.130 +	@SYMTestCaseDesc
   1.131 +	Tests ncrementation and decrementation of the reference 
   1.132 +	count for a particular session handle.
   1.133 +
   1.134 +	@SYMTestActions
   1.135 +	1. Creates a TShapeHeader object on the heap.
   1.136 +	2. Set som values to the object.
   1.137 +	3. Creates a CShaper object on the stack.
   1.138 +	4. Creates a new shaper cache entry.
   1.139 +	5. Associates a session with this entry.
   1.140 +	6. Increments the reference count for a particular session (A) handle.
   1.141 +	7. Increments the reference count for another session (B).
   1.142 +	8. Decrements an instance from session (A).
   1.143 +	9. Adds another session to the list (C).
   1.144 +	10. Decrements the ref count for a particular session handle (C).
   1.145 +	11. Tests decrement on non-existent session.
   1.146 +	12. Frees memory taken up by the entry to the cache.
   1.147 +	13. The heap is checked for memory leaks.
   1.148 +	
   1.149 +	@SYMTestExpectedResults
   1.150 +	The decrementation of the non-existent session should return KErrNotFound.
   1.151 +*/
   1.152 +void CTShaperCache::Test2L()
   1.153 +	{
   1.154 +	INFO_PRINTF1(_L("ShaperCache Test2"));
   1.155 +	__UHEAP_MARK;
   1.156 +
   1.157 +	TShapeHeader* shapeHeader=new TShapeHeader();
   1.158 +	shapeHeader->iGlyphCount=10;
   1.159 +	shapeHeader->iCharacterCount=20;
   1.160 +
   1.161 +	_LIT(KDummyText,"dummy");
   1.162 +	CShaper::TInput input;
   1.163 +	input.iStart=0;
   1.164 +	input.iEnd=10;
   1.165 +	input.iText=&(KDummyText());
   1.166 +
   1.167 +	//create a new shaper cache entry	
   1.168 +	COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader);
   1.169 +	
   1.170 +	//now associate a session with this entry
   1.171 +	TInt dummySession=12;
   1.172 +	TEST(shapeEntry->IncRefCount(dummySession)==KErrNone);
   1.173 +	TEST(shapeEntry->iHandleRefCount==1);
   1.174 +	TEST(shapeEntry->iHandleRefList!=NULL);
   1.175 +	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession);
   1.176 +	TEST(shapeEntry->iHandleRefList->iRefCount==1);	
   1.177 +	//increment for another session, the THandleCount::iRef for this session should be 2
   1.178 +	TEST(shapeEntry->IncRefCount(dummySession)==KErrNone);
   1.179 +	TEST(shapeEntry->iHandleRefCount==1);
   1.180 +	TEST(shapeEntry->iHandleRefList->iRefCount==2);				
   1.181 +
   1.182 +	//another entry for different session
   1.183 +	TInt dummySession2=13;
   1.184 +	TEST(shapeEntry->IncRefCount(dummySession2)==KErrNone);
   1.185 +	TEST(shapeEntry->iHandleRefCount==2);
   1.186 +	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession);
   1.187 +	TEST(shapeEntry->iHandleRefList->iRefCount==2);
   1.188 +	TEST(shapeEntry->iHandleRefList->iNext->iSessionHandle==dummySession2);
   1.189 +	TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1);	
   1.190 +	
   1.191 +	//now decrement an instance from this session(DELETE FIRST ENTRY)
   1.192 +	TEST(shapeEntry->DecRefCount(dummySession)==KErrNone);
   1.193 +	TEST(shapeEntry->iHandleRefCount==2);
   1.194 +	TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1);		
   1.195 +	TEST(shapeEntry->DecRefCount(dummySession)==KErrNone);
   1.196 +	TEST(shapeEntry->iHandleRefCount==1);
   1.197 +	TEST(shapeEntry->iHandleRefList->iRefCount==1);			
   1.198 +	TEST(shapeEntry->iHandleRefList->iSessionHandle=dummySession2);
   1.199 +
   1.200 +	//now add another session to this list
   1.201 +	TInt dummySession3=14;
   1.202 +	TEST(shapeEntry->IncRefCount(dummySession3)==KErrNone);
   1.203 +	TEST(shapeEntry->iHandleRefCount==2);
   1.204 +	//test delete this last entry in the list(DELETE LAST ENTRY)
   1.205 +	TEST(shapeEntry->DecRefCount(dummySession3)==KErrNone);
   1.206 +	TEST(shapeEntry->iHandleRefCount==1);	
   1.207 +	TEST(shapeEntry->iHandleRefList->iRefCount==1);
   1.208 +	TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession2);
   1.209 +
   1.210 +
   1.211 +	//test Dec on non-existent session
   1.212 +	TEST(shapeEntry->DecRefCount(100)==KErrNotFound);
   1.213 +
   1.214 +	COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry);
   1.215 +	delete shapeHeader;
   1.216 +	
   1.217 +	__UHEAP_MARKEND;		
   1.218 +	}
   1.219 +	
   1.220 +/**
   1.221 +	@SYMTestCaseID
   1.222 +	GRAPHICS-FNTSTORE-0045
   1.223 +
   1.224 +	@SYMTestCaseDesc
   1.225 +	Tests the shaper cache APIs.
   1.226 +
   1.227 +	@SYMTestActions
   1.228 +	1. Creates a dummy TShapeHeader object that will be cached and reused through the test.
   1.229 +	2. Gets some memory to pass back the results. It needs to be big enough for a TShapeHeader
   1.230 +	   object plus 10 bytes for every glyph returned.
   1.231 +	3. Finds or creates four font file objects to support a font file.
   1.232 +	4. Gets the number of supported typefaces.
   1.233 +	5. Creates a font.
   1.234 +	6. Gets a COpenFont object.
   1.235 +	7. For COpenFonts it attempts to put this into the shaper cache and test if it was successful.
   1.236 +	8. Calls DeleteShape to decrement the reference count.
   1.237 +	9. Changes the shaped data slightly to make it into a new shaped data and insert into the
   1.238 +	   cache as a new entry.
   1.239 +	10. Tests if the LRU cache is working by seeing if the first entry in the cache is the newest one.
   1.240 +	11. Calls DeleteShape to decrement the reference count
   1.241 +	12. Calls the GetShapedData API and tests the returned TShapeHeader. Also checks if the returned
   1.242 +		cache entry is at the top of the cache.
   1.243 +    13. Searches the cache for the first entry using the GetShapedData API.
   1.244 +    14. Calls DeleteShape to decrement the reference count.
   1.245 +    15. Brings the end value back to its original value.
   1.246 +	16. Fills the cache and then tests replacement policy by attempting to add a new entry.
   1.247 +	17. Prepares a raw input data structure.
   1.248 +	18. Keeps inserting pseudo-new shaped entries into the cache to fill it up.
   1.249 +	19. Changes the cached entries slightly to distinguish between each entry.
   1.250 +	20. Tries to add a new entry and checks that the entry replaced was the last entry in the cache.
   1.251 +	21. Calculates the memory needed for the new entry.
   1.252 +	22. Calculates the memory that will be freed to accommodate the new entry and the 
   1.253 +	    position of the last entry in the cache once deletion is done.
   1.254 +	23. Finds the glyphcount of the expected new last entry in the cache.
   1.255 +	24. Does the insertion and tests.
   1.256 +	25. Calls DeleteShape to decrement the reference count.
   1.257 +	26. Calculates the memory occupied by the last entry in the cache. This is the memory that will
   1.258 +		be released when the last entry is deleted.
   1.259 +	27. Tests with multiple open fonts with caches. Creates the new font.
   1.260 +	28. Does the testing only if the font is a COpenFont.
   1.261 +	29. Attempts to put a new entry into the second shaper cache and test if it was successful.
   1.262 +	30. Creates a pseudo-new shape header to put into the cache of this new open font.
   1.263 +	31. Inserst an entry into the cache.
   1.264 +	32. Tests cache memory freeing policy, i.e. delete from all other caches except the current one.
   1.265 +	33. Finds out how much memory needs freeing, i.e. how much was just added.
   1.266 +	34. Tries to free memory from the original open font cache. The result should be that
   1.267 +		memory should be freed from openFont2 cache, and not openFont cache.
   1.268 +	35. Checks
   1.269 +		a) if the memory used by openFont2 cache has reduced, i.e. back to original memory.
   1.270 +		b) if the last entry from openFont2 cache has been deleted.
   1.271 +		c) last entry from openFont cache is intact.
   1.272 +	36. Cleans up font2, font1 and removes all fonts.	
   1.273 +		
   1.274 +	@SYMTestExpectedResults
   1.275 +	All tests shall pass.
   1.276 +
   1.277 +*/
   1.278 +void CTShaperCache::TestShaperCacheAPIsL()
   1.279 +	{
   1.280 +	INFO_PRINTF1(_L("The following results are for shaper cache API tests\n"));
   1.281 +	
   1.282 +	// Create a dummy TShapeHeader object that will be cached, and reused all through this test
   1.283 +	TShapeHeader* shape = 0;
   1.284 +	
   1.285 +	// get some memory to pass back the results,  
   1.286 +	// This needs to be big enough for a TShapeHeader
   1.287 +	// plus 10 bytes for every glyph returned (-1 for the 1 byte allocated in TShapeHeader for iBuffer)
   1.288 +	shape = reinterpret_cast<TShapeHeader*>( iHeap->AllocL(sizeof(TShapeHeader) + (KResultNumberOfGlyphs * 10) + 3) );
   1.289 +
   1.290 +	// get the results into the shaper structure 'shape'
   1.291 +	shape->iGlyphCount = KResultNumberOfGlyphs;
   1.292 +	shape->iCharacterCount = 8;
   1.293 + 	shape->iReserved0 = 0;
   1.294 +	shape->iReserved1 = 0;
   1.295 +
   1.296 + 	// iBuffer contains 10 bytes for every glyph
   1.297 + 	// the glyph code (4 bytes), position X(2 bytes) Y(2 bytes) and indices(2 bytes)
   1.298 +  	// first is glyph count * 4 byte glyph codes
   1.299 + 	TUint32* glyphOut = reinterpret_cast<TUint32*>(shape->iBuffer);
   1.300 + 	TInt16* posOut = reinterpret_cast<TInt16*>(shape->iBuffer +
   1.301 + 		(4 * KResultNumberOfGlyphs));
   1.302 + 	TInt16* indicesOut = reinterpret_cast<TInt16*>(shape->iBuffer +
   1.303 + 		(8 * KResultNumberOfGlyphs) + 4);
   1.304 + 	
   1.305 + 	*glyphOut++ = (TUint32)1461;
   1.306 +	*posOut++ = (TInt16)0;
   1.307 +	*posOut++ = (TInt16)0;
   1.308 +	*indicesOut++ = (TInt16)0;
   1.309 +	
   1.310 +	*glyphOut++ = (TUint32)1778;
   1.311 +	*posOut++ = (TInt16)12;
   1.312 +	*posOut++ = (TInt16)0;
   1.313 +	*indicesOut++ = (TInt16)7;
   1.314 +	
   1.315 +	*glyphOut++ = (TUint32)1550;
   1.316 +	*posOut++ = (TInt16)16;
   1.317 +	*posOut++ = (TInt16)0;
   1.318 +	*indicesOut++ = (TInt16)3;
   1.319 +	
   1.320 +	*glyphOut++ = (TUint32)1362;
   1.321 +	*posOut++ = (TInt16)28;
   1.322 +	*posOut++ = (TInt16)0;
   1.323 +	*indicesOut++ = (TInt16)7;
   1.324 + 		
   1.325 + 	// There is an extra pair of positions: this is the total advance
   1.326 +	posOut[0] = (TInt16)28;
   1.327 +	posOut[1] = (TInt16)0;
   1.328 +	
   1.329 +	TFontShapeFunctionParameters* params;
   1.330 +	params = reinterpret_cast<TFontShapeFunctionParameters*>( iHeap->AllocL(sizeof(TFontShapeFunctionParameters)));
   1.331 +	params->iEnd = 8;
   1.332 +	params->iLanguage = 0;
   1.333 +	params->iScript = KDevanagariScriptCode;
   1.334 +	params->iStart = 0;
   1.335 +	//TBufC16<9> text(KTextToShape);
   1.336 +	params->iText = &KTextToShape();
   1.337 +
   1.338 +		// Add fonts
   1.339 +	TUid id1 = iFontStore->AddFileL(KFontDummy);
   1.340 +	TUid id2 = iFontStore->AddFileL(KFontDummy_b);
   1.341 +	TUid id3 = iFontStore->AddFileL(KFontDummy_i);
   1.342 +	TUid id4 = iFontStore->AddFileL(KFontDummy_bi);
   1.343 +	
   1.344 +	INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 1: Testing cache with a single COpentFont cache"));
   1.345 +
   1.346 +	TInt typefaces = iFontStore->NumTypefaces();
   1.347 +	TInt typeface = 0;
   1.348 +	TInt height = 12;
   1.349 +
   1.350 +	TTypefaceSupport support;
   1.351 +	iFontStore->TypefaceSupport(support,typeface);
   1.352 +	TFontSpec fs;
   1.353 +	fs.iTypeface = support.iTypeface;
   1.354 +
   1.355 +	INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height);
   1.356 +	//Create a font
   1.357 +	CFont* font = NULL;
   1.358 +	fs.iHeight = iFontStore->FontHeightInTwips(typeface,height);
   1.359 +	// get a COpenFont object
   1.360 +	iFontStore->GetNearestFontToDesignHeightInPixels(font, fs);	
   1.361 +	CleanupStack::PushL(font);
   1.362 +	
   1.363 +	
   1.364 +	// Do the testing only if the font is a COpenFont
   1.365 +	COpenFont* openFont = NULL;
   1.366 +	CShaper::TInput input;
   1.367 +	if (((CBitmapFont*)font)->IsOpenFont())
   1.368 +		{
   1.369 +		__UHEAP_MARK;
   1.370 +		openFont = ((CBitmapFont*)font)->OpenFont();
   1.371 +		
   1.372 +		/***************************First Test***************************
   1.373 +		Attempt to put this into the shaper cache and then delete it. Test if it was successful
   1.374 +		*/
   1.375 +		TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(0,params, shape);
   1.376 +
   1.377 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 1: Simple cache insertion test"));
   1.378 +		TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   1.379 +		
   1.380 +		/* Call DeleteShape to decrement the reference count */
   1.381 +		((CBitmapFont*)font)->DeleteShape(0, cached_header);
   1.382 +		
   1.383 +		// Now delete this data
   1.384 +		openFont->FreeShaperCacheMemory(openFont->GetGlyphCache()->iShapingInfoCacheMemory);
   1.385 +		TEST(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 1);
   1.386 +		// Put the shaped data back into the cache to continue with testing
   1.387 +		cached_header = openFont->InsertShapedDataIntoCache(0,params, shape);
   1.388 +		TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   1.389 +		((CBitmapFont*)font)->DeleteShape(0, cached_header);		
   1.390 +		
   1.391 +		/**************************Second Test**************************
   1.392 +		Now change the shaped data slightly to make it into a new shaped data and insert into the
   1.393 +		cache as a new entry
   1.394 +		*/
   1.395 +		shape->iGlyphCount++;
   1.396 +		params->iEnd++;
   1.397 +		TShapeHeader* cached_header2 = openFont->InsertShapedDataIntoCache(0,params, shape);
   1.398 +		
   1.399 +		/* Now test if the LRU cache is working by seeing if the first entry in the cache is the newest one */
   1.400 +		COpenFontGlyphCache* glyphCache = openFont->GetGlyphCache();
   1.401 +		
   1.402 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 2: Test the LRU (Least Recently Used) cache structure"));
   1.403 +		TEST(glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount == KResultNumberOfGlyphs + 1);
   1.404 +		
   1.405 +		/* Call DeleteShape to decrement the reference count */
   1.406 +		((CBitmapFont*)font)->DeleteShape(0, cached_header2);
   1.407 +		
   1.408 +		
   1.409 +		/**************************Third Test**************************
   1.410 +		Call the GetShapedData API and test the returned TShapeHeader, and also check if the returned
   1.411 +		cache entry is now at the top of the cache
   1.412 +		*/
   1.413 +		
   1.414 +		/* Now search the cache for the first entry using the GetShapedData API */
   1.415 +		params->iEnd --;
   1.416 +		TInt expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   1.417 +		TShapeHeader* searchedCachedHeader = openFont->GetShapedData(0,params);
   1.418 +
   1.419 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 3: GetShapedData API test"));
   1.420 +		TEST(searchedCachedHeader->iGlyphCount == expectedGlyphCount &&
   1.421 +			 searchedCachedHeader->iGlyphCount ==glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount);
   1.422 +		
   1.423 +		/* Call DeleteShape to decrement the reference count */
   1.424 +		((CBitmapFont*)font)->DeleteShape(0, searchedCachedHeader);
   1.425 +		
   1.426 +		/* Bring the end value back to its original value */
   1.427 +		params->iEnd ++;
   1.428 +		
   1.429 +		
   1.430 +		/**************************Fourth Test**************************
   1.431 +		Fill the cache and then test replacement policy by attempting to add a new entry
   1.432 +		*/
   1.433 +	
   1.434 +		/* First prepare a raw input data structure */
   1.435 +		TInt memoryUsed = 0;
   1.436 +		input.iText = &KTextToShape();
   1.437 +		input.iStart = 0;
   1.438 +		input.iEnd = params->iEnd;
   1.439 +		input.iScript= KDevanagariScriptCode;
   1.440 +		input.iLanguage = 0;
   1.441 +		input.iMaximumAdvance = KMaxTInt;
   1.442 +		input.iFlags = 0;
   1.443 +		input.iSessionHandle = 0;
   1.444 +		input.iReserved1 = 0;
   1.445 +		TInt addedBytes = 0;
   1.446 +		TShapeHeader* chached_header3 = 0;
   1.447 +		openFont->FreeShaperCacheMemory(KMaxShaperSesssionCacheMemory);
   1.448 +		openFont->File()->GetFontStore()->SetShaperCacheMemUsage(0);
   1.449 +		RArray<TInt> cacheMemUsage;
   1.450 +		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
   1.451 +		while(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() < KMaxShaperSesssionCacheMemory)
   1.452 +			{
   1.453 +			memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
   1.454 +			// Change the cached entries slightly to distinguish between each entry
   1.455 +			shape->iGlyphCount++;
   1.456 +			input.iEnd++;
   1.457 +			chached_header3 = glyphCache->Insert(0,iHeap, input, shape, addedBytes);
   1.458 +			if (chached_header3 != NULL)
   1.459 +				openFont->File()->GetFontStore()->SetShaperCacheMemUsage(memoryUsed + addedBytes);
   1.460 +			((CBitmapFont*)font)->DeleteShape(0, chached_header3);
   1.461 +			cacheMemUsage.AppendL(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() - memoryUsed);
   1.462 +			chached_header3 = NULL;
   1.463 +			}
   1.464 +		
   1.465 +		/* Now try to add a new entry, and check that the entry replaced was the last entry in the cache */
   1.466 +		TInt last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   1.467 +		shape->iGlyphCount++;
   1.468 +		input.iEnd++;
   1.469 +		params->iEnd = input.iEnd;
   1.470 +		
   1.471 +		/* Calculate the memory needed for the new entry */
   1.472 +
   1.473 +		
   1.474 +        TInt heapSizeBefAloc = 0;
   1.475 +        iHeap->AllocSize(heapSizeBefAloc);      
   1.476 +        COpenFontShaperCacheEntry *tempEntry = COpenFontShaperCacheEntry::New(iHeap, input, shape);
   1.477 +        TInt heapSizeAftAloc = 0;
   1.478 +        iHeap->AllocSize(heapSizeAftAloc);
   1.479 +        TInt bytes_needed = heapSizeAftAloc - heapSizeBefAloc;
   1.480 +        COpenFontShaperCacheEntry::Delete(iHeap, tempEntry);
   1.481 +        
   1.482 +		TInt bytesToDelete = 0;    
   1.483 +	    
   1.484 +		COpenFontShaperCacheEntry* previous = glyphCache->iShaperCacheSentinel->iPrevious;
   1.485 +		/* Calculate the memory that will be freed to accommodate the new entry,
   1.486 +		   and the position of the last entry in the cache once deletion is done */
   1.487 +		TInt index = 0;
   1.488 +		while (bytesToDelete <= bytes_needed)
   1.489 +			{
   1.490 +
   1.491 +             bytesToDelete += cacheMemUsage[index++];
   1.492 +			 previous = previous->iPrevious;
   1.493 +			}
   1.494 +		cacheMemUsage.Close();	
   1.495 +		/* Find the glyphcount of the expected new last entry in the cache */
   1.496 +		expectedGlyphCount = previous->iShapeHeader->iGlyphCount;
   1.497 +		
   1.498 +		/* Finally, do the insertion, and test */
   1.499 +		TShapeHeader* cached_header4 = openFont->InsertShapedDataIntoCache(0, params, shape);
   1.500 +		
   1.501 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 4: LRU cache replacement policy test"));
   1.502 +		TEST(glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   1.503 +
   1.504 +		/* Call DeleteShape to decrement the reference cout */
   1.505 +		((CBitmapFont*)font)->DeleteShape(0, cached_header4);
   1.506 +		
   1.507 +		
   1.508 +		/**************************Fifth Test**************************
   1.509 +		Simply test the FreeShaperCacheMemory API
   1.510 +		*/
   1.511 +				
   1.512 +		/* Calculate the memory of occupied by the last entry in the cache. This is the memory that will
   1.513 +		   be released when the last entry is deleted
   1.514 +		 */
   1.515 +		last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   1.516 +		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
   1.517 +				* last_entry_glyph_count + sizeof(TInt16) * 2;
   1.518 +
   1.519 +		bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
   1.520 +			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
   1.521 +		
   1.522 +		memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage();
   1.523 +		expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iPrevious->iShapeHeader->iGlyphCount;
   1.524 +		TInt memoryReleased = openFont->FreeShaperCacheMemory(bytes_needed);
   1.525 +		
   1.526 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 5: FreeShaperCacheMemory API test\n"));
   1.527 +		TEST(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() == memoryUsed - memoryReleased &&
   1.528 +			 glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   1.529 +	
   1.530 +		__UHEAP_MARKEND;
   1.531 +		}
   1.532 +		
   1.533 +	INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 2: Testing cache with a two COpentFont caches"));
   1.534 +	/* Now test with multiple open fonts with caches */
   1.535 +	/* Create the new font */
   1.536 +	height = 4;
   1.537 +	iFontStore->TypefaceSupport(support,typeface);
   1.538 +	fs.iTypeface = support.iTypeface;
   1.539 +
   1.540 +	INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height);
   1.541 +
   1.542 +	CFont* font2 = NULL;
   1.543 +	fs.iHeight = iFontStore->FontHeightInTwips(typeface,height);
   1.544 +	iFontStore->GetNearestFontToDesignHeightInPixels(font2, fs);	
   1.545 +	CleanupStack::PushL(font2);
   1.546 +	
   1.547 +	COpenFont* openFont2;
   1.548 +	/* Do the testing only if the font is a COpenFont */
   1.549 +	if (((CBitmapFont*)font2)->IsOpenFont())
   1.550 +		{
   1.551 +		__UHEAP_MARK;
   1.552 +		openFont2 = ((CBitmapFont*)font2)->OpenFont();
   1.553 +		
   1.554 +		/***************************Sixth Test***************************
   1.555 +		Attempt to put a new entry into the second shaper cache and test if it was successful
   1.556 +		*/
   1.557 +		
   1.558 +		/* Create a pseudo-new shape header to put into the cache of this new open font */
   1.559 +		shape->iGlyphCount++;
   1.560 +		params->iEnd++;
   1.561 +		
   1.562 +		/* Insert an entry into the cache */
   1.563 +		TShapeHeader* cached_header5 = openFont2->InsertShapedDataIntoCache(0, params, shape);
   1.564 +		((CBitmapFont*)font2)->DeleteShape(0, cached_header5);
   1.565 +
   1.566 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 6: Second cache insertion test"));
   1.567 +		TEST(cached_header5 != NULL && openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 2);
   1.568 +
   1.569 +		/***************************Seventh, Eighth and Ninth Tests***************************
   1.570 +		Test cache memory freeing policy, i.e. delete from all other caches except the current one
   1.571 +		*/
   1.572 +		
   1.573 +		/* First find out how much memory needs freeing, i.e. how much was just added */
   1.574 +		TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2)
   1.575 +					* shape->iGlyphCount + sizeof(TInt16) * 2;
   1.576 +
   1.577 +		TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + 
   1.578 +			sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length();
   1.579 +
   1.580 +		
   1.581 +		/* Now try to free memory from the original open font cache. The result should be that
   1.582 +		   memory should be freed from openFont2 cache, and not openFont cache
   1.583 +		 */
   1.584 +		TInt memoryUsed = openFont2->GetGlyphCache()->iShapingInfoCacheMemory;
   1.585 +		TInt expectedGlyphCount = openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount;
   1.586 +		TInt deletedMemory = openFont->FreeShaperCacheMemory(bytes_needed);
   1.587 +		
   1.588 +		/* Now check:
   1.589 +		   a) if the memory used by openFont2 cache has reduced, i.e. back to original memory
   1.590 +		   b) if the last entry from openFont2 cache has been deleted
   1.591 +		   c) last entry from openFont cache is intact
   1.592 +		*/
   1.593 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 7: Test if memory is freed from second COpenFont"));
   1.594 +		TEST(memoryUsed - openFont2->GetGlyphCache()->iShapingInfoCacheMemory ==  deletedMemory &&
   1.595 +			openFont2->GetGlyphCache()->iShapingInfoCacheMemory == 0);
   1.596 +
   1.597 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 8: Test if last entry of second COpenFont is deleted"));
   1.598 +		TEST(openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 1);
   1.599 +
   1.600 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 9: Test if the last entry of the first COpenFont is intact"));
   1.601 +		TEST(openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount);
   1.602 +		
   1.603 +		/***********************************Tenth Tests*****************************************
   1.604 +		Test cache memory consistency and that there are no leakages when deleting memory from the cache
   1.605 +		*/
   1.606 +		
   1.607 +		/* Continue adding entries to second open font cache until the memory used by the first one
   1.608 +		   goes down to zero, at which point the number of cache entries should be 1, and memory from
   1.609 +		   the current open font should start getting released and eventually reach 0 when the number
   1.610 +		   of cached entries reaches 1.
   1.611 +		*/
   1.612 +		TShapeHeader* cached_header6 = NULL;
   1.613 +		/* Keep inserting pseudo-new shaped entries into the cache to fill it up */
   1.614 +		while(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries > 1)
   1.615 +			{
   1.616 +			memoryUsed = openFont2->File()->GetFontStore()->GetShaperCacheMemUsage();
   1.617 +			// Change the cached entries slightly to distinguish between each entry
   1.618 +			shape->iGlyphCount++;
   1.619 +			params->iEnd++;
   1.620 +			cached_header6 = openFont2->InsertShapedDataIntoCache(0, params, shape);
   1.621 +			((CBitmapFont*)font2)->DeleteShape(0, cached_header6);
   1.622 +			cached_header6 = NULL;
   1.623 +			}
   1.624 +			
   1.625 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 10: Test consistency of cache memory"));
   1.626 +		TEST(openFont->GetGlyphCache()->iShapingInfoCacheMemory == 0);
   1.627 +		
   1.628 +		
   1.629 +		/**
   1.630 +		@SYMTestCaseID          GRAPHICS-SYSLIB-FNTSTORE-UT-4001
   1.631 +		@SYMTestCaseDesc        Test that when trying to delete a shape not in the cache it
   1.632 +								does not loop infinitely trying to find it.
   1.633 +		@SYMTestPriority        Medium
   1.634 +		@SYMTestActions         Pass a null shape header to the DeleteShape function.
   1.635 +		@SYMTestExpectedResults	The function call should return instead of looping infinitely.
   1.636 +		@SYMDEF                 PDEF125354
   1.637 +		*/
   1.638 +		((CTShaperCacheStep*)iStep)->RecordTestResultL();
   1.639 +		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-SYSLIB-FNTSTORE-UT-4001"));
   1.640 +		INFO_PRINTF1(_L("SHAPER CACHE API TEST 11: Test that shape not found does not loop infinitely."));
   1.641 +		TShapeHeader* null_header = NULL;
   1.642 +		// Timeout set in TEF script to catch infinite loop.
   1.643 +		((CBitmapFont*)font2)->DeleteShape(0, null_header);
   1.644 +		
   1.645 +		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
   1.646 +		__UHEAP_MARKEND;
   1.647 +		}
   1.648 +	
   1.649 +	/* Cleanup font2*/
   1.650 +	CleanupStack::Pop(font2);
   1.651 +	iFontStore->ReleaseFont(font2);
   1.652 +	
   1.653 +	/* Cleanup font1 */	
   1.654 +	CleanupStack::Pop(font);
   1.655 +	iFontStore->ReleaseFont(font);
   1.656 +
   1.657 +	// Remove the fonts
   1.658 +	iFontStore->RemoveFile(id1);
   1.659 +	iFontStore->RemoveFile(id2);
   1.660 +	iFontStore->RemoveFile(id3);
   1.661 +	iFontStore->RemoveFile(id4);
   1.662 +	}
   1.663 +
   1.664 +void CTShaperCache::RunTestCaseL(TInt aCurTestCase)
   1.665 +	{
   1.666 +	((CTShaperCacheStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
   1.667 +	switch(aCurTestCase)
   1.668 +		{
   1.669 +	case 1:
   1.670 +		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0043"));
   1.671 +		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 1 ########################\n"));
   1.672 +		TRAPD(err,Test1L());
   1.673 +		TEST(err == KErrNone);
   1.674 +		break;
   1.675 +	case 2:
   1.676 +		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0044"));
   1.677 +		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 2 ########################\n"));
   1.678 +		TRAP(err,Test2L());
   1.679 +		TEST(err == KErrNone);
   1.680 +		break;
   1.681 +	case 3:
   1.682 +		((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0045"));		
   1.683 +		INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 3 ########################"));
   1.684 +		TRAP(err,TestShaperCacheAPIsL());
   1.685 +		TEST(err == KErrNone);
   1.686 +		break;		
   1.687 +	case 4:
   1.688 +        	((CTShaperCacheStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
   1.689 +    		((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep();
   1.690 +		TestComplete();				
   1.691 +		break;
   1.692 +		}
   1.693 +	((CTShaperCacheStep*)iStep)->RecordTestResultL();
   1.694 +	}
   1.695 +
   1.696 +
   1.697 +//--------------
   1.698 +__CONSTRUCT_STEP__(ShaperCache)
   1.699 +
   1.700 +
   1.701 +