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