diff -r 000000000000 -r 1fb32624e06b fontservices/fontstore/tfs/T_SHAPERCACHE.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fontservices/fontstore/tfs/T_SHAPERCACHE.CPP Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,687 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +/** + @file + @test + @internalComponent Internal Symbian test code +*/ + + +#include +#include +#include +#include +#include "ShaperCache.H" +#include "openfontsprivate.h" + +#include "T_SHAPERCACHE.H" +#include "T_FSOPEN.H" + +_LIT(KFontDummy,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy"); +_LIT(KFontDummy_b,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_b"); +_LIT(KFontDummy_i,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_i"); +_LIT(KFontDummy_bi,"z:\\PlatTest\\Graphics\\TestData\\dummy_fonts\\dummy_bi"); + +const TUint32 KDevanagariScriptCode = 0x64657661; +_LIT16(KTextToShape, "\x0915\x094D\x0937\x0924\x094D\x0930\x093F\x092F"); +const TInt KResultNumberOfGlyphs = 4; + +CTShaperCache::~CTShaperCache() + { + delete iFontStore; + iHeap->__DbgMarkEnd(0); + iHeap->Close(); + __UHEAP_MARKEND; + User::Heap().Check(); + } + +CTShaperCache::CTShaperCache(CTestStep* aStep): + CTGraphicsBase(aStep) + { + INFO_PRINTF1(_L("FontStore T_ShaperCache test\n")); + } + +void CTShaperCache::ConstructL() + { + __UHEAP_MARK; + iHeap = UserHeap::ChunkHeap(NULL,0x10000,0x100000); + if (iHeap == NULL) + User::Leave(KErrGeneral); + iHeap->__DbgMarkStart(); + iFontStore = CFontStore::NewL(iHeap); + + // Install the dummy rasterizer. + COpenFontRasterizer* r = CDummyRasterizer::NewL(); + CleanupStack::PushL(r); + iFontStore->InstallRasterizerL(r); + CleanupStack::Pop(); + + // Install the dummy shaper + CShaperFactory* shaperFactory = CDummyShaperFactory::NewL(); + CleanupStack::PushL(shaperFactory); + iFontStore->InstallShaperFactoryL(shaperFactory); + CleanupStack::Pop(); + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0043 + + @SYMTestCaseDesc + Tests creating and deleting a new shaper cache entry. + + @SYMTestActions + 1. Allocated a TShapeHeader object on the heap/ + 2. Creates a CShaper object on the stack. + 3. Allocates an entry for the TShapeHeader object in the cache. + 4. Frees memory taken up by the entry to the cache. + 5. The heap is checked for memory leaks. + + @SYMTestExpectedResults + No memory leaks should exist. +*/ +void CTShaperCache::Test1L() + { + INFO_PRINTF1(_L("ShaperCache Test1")); + __UHEAP_MARK; + + TShapeHeader* shapeHeader=new TShapeHeader(); + shapeHeader->iGlyphCount=10; + shapeHeader->iCharacterCount=20; + + _LIT(KDummyText,"dummy"); + CShaper::TInput input; + input.iStart=0; + input.iEnd=10; + input.iText=&(KDummyText()); + + //create/delete test a new shaper cache entry + COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader); + COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry); + + delete shapeHeader; + + __UHEAP_MARKEND; + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0044 + + @SYMTestCaseDesc + Tests ncrementation and decrementation of the reference + count for a particular session handle. + + @SYMTestActions + 1. Creates a TShapeHeader object on the heap. + 2. Set som values to the object. + 3. Creates a CShaper object on the stack. + 4. Creates a new shaper cache entry. + 5. Associates a session with this entry. + 6. Increments the reference count for a particular session (A) handle. + 7. Increments the reference count for another session (B). + 8. Decrements an instance from session (A). + 9. Adds another session to the list (C). + 10. Decrements the ref count for a particular session handle (C). + 11. Tests decrement on non-existent session. + 12. Frees memory taken up by the entry to the cache. + 13. The heap is checked for memory leaks. + + @SYMTestExpectedResults + The decrementation of the non-existent session should return KErrNotFound. +*/ +void CTShaperCache::Test2L() + { + INFO_PRINTF1(_L("ShaperCache Test2")); + __UHEAP_MARK; + + TShapeHeader* shapeHeader=new TShapeHeader(); + shapeHeader->iGlyphCount=10; + shapeHeader->iCharacterCount=20; + + _LIT(KDummyText,"dummy"); + CShaper::TInput input; + input.iStart=0; + input.iEnd=10; + input.iText=&(KDummyText()); + + //create a new shaper cache entry + COpenFontShaperCacheEntry* shapeEntry=COpenFontShaperCacheEntry::New(&User::Heap(),input,shapeHeader); + + //now associate a session with this entry + TInt dummySession=12; + TEST(shapeEntry->IncRefCount(dummySession)==KErrNone); + TEST(shapeEntry->iHandleRefCount==1); + TEST(shapeEntry->iHandleRefList!=NULL); + TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession); + TEST(shapeEntry->iHandleRefList->iRefCount==1); + //increment for another session, the THandleCount::iRef for this session should be 2 + TEST(shapeEntry->IncRefCount(dummySession)==KErrNone); + TEST(shapeEntry->iHandleRefCount==1); + TEST(shapeEntry->iHandleRefList->iRefCount==2); + + //another entry for different session + TInt dummySession2=13; + TEST(shapeEntry->IncRefCount(dummySession2)==KErrNone); + TEST(shapeEntry->iHandleRefCount==2); + TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession); + TEST(shapeEntry->iHandleRefList->iRefCount==2); + TEST(shapeEntry->iHandleRefList->iNext->iSessionHandle==dummySession2); + TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1); + + //now decrement an instance from this session(DELETE FIRST ENTRY) + TEST(shapeEntry->DecRefCount(dummySession)==KErrNone); + TEST(shapeEntry->iHandleRefCount==2); + TEST(shapeEntry->iHandleRefList->iNext->iRefCount==1); + TEST(shapeEntry->DecRefCount(dummySession)==KErrNone); + TEST(shapeEntry->iHandleRefCount==1); + TEST(shapeEntry->iHandleRefList->iRefCount==1); + TEST(shapeEntry->iHandleRefList->iSessionHandle=dummySession2); + + //now add another session to this list + TInt dummySession3=14; + TEST(shapeEntry->IncRefCount(dummySession3)==KErrNone); + TEST(shapeEntry->iHandleRefCount==2); + //test delete this last entry in the list(DELETE LAST ENTRY) + TEST(shapeEntry->DecRefCount(dummySession3)==KErrNone); + TEST(shapeEntry->iHandleRefCount==1); + TEST(shapeEntry->iHandleRefList->iRefCount==1); + TEST(shapeEntry->iHandleRefList->iSessionHandle==dummySession2); + + + //test Dec on non-existent session + TEST(shapeEntry->DecRefCount(100)==KErrNotFound); + + COpenFontShaperCacheEntry::Delete(&User::Heap(),shapeEntry); + delete shapeHeader; + + __UHEAP_MARKEND; + } + +/** + @SYMTestCaseID + GRAPHICS-FNTSTORE-0045 + + @SYMTestCaseDesc + Tests the shaper cache APIs. + + @SYMTestActions + 1. Creates a dummy TShapeHeader object that will be cached and reused through the test. + 2. Gets some memory to pass back the results. It needs to be big enough for a TShapeHeader + object plus 10 bytes for every glyph returned. + 3. Finds or creates four font file objects to support a font file. + 4. Gets the number of supported typefaces. + 5. Creates a font. + 6. Gets a COpenFont object. + 7. For COpenFonts it attempts to put this into the shaper cache and test if it was successful. + 8. Calls DeleteShape to decrement the reference count. + 9. Changes the shaped data slightly to make it into a new shaped data and insert into the + cache as a new entry. + 10. Tests if the LRU cache is working by seeing if the first entry in the cache is the newest one. + 11. Calls DeleteShape to decrement the reference count + 12. Calls the GetShapedData API and tests the returned TShapeHeader. Also checks if the returned + cache entry is at the top of the cache. + 13. Searches the cache for the first entry using the GetShapedData API. + 14. Calls DeleteShape to decrement the reference count. + 15. Brings the end value back to its original value. + 16. Fills the cache and then tests replacement policy by attempting to add a new entry. + 17. Prepares a raw input data structure. + 18. Keeps inserting pseudo-new shaped entries into the cache to fill it up. + 19. Changes the cached entries slightly to distinguish between each entry. + 20. Tries to add a new entry and checks that the entry replaced was the last entry in the cache. + 21. Calculates the memory needed for the new entry. + 22. Calculates the memory that will be freed to accommodate the new entry and the + position of the last entry in the cache once deletion is done. + 23. Finds the glyphcount of the expected new last entry in the cache. + 24. Does the insertion and tests. + 25. Calls DeleteShape to decrement the reference count. + 26. Calculates the memory occupied by the last entry in the cache. This is the memory that will + be released when the last entry is deleted. + 27. Tests with multiple open fonts with caches. Creates the new font. + 28. Does the testing only if the font is a COpenFont. + 29. Attempts to put a new entry into the second shaper cache and test if it was successful. + 30. Creates a pseudo-new shape header to put into the cache of this new open font. + 31. Inserst an entry into the cache. + 32. Tests cache memory freeing policy, i.e. delete from all other caches except the current one. + 33. Finds out how much memory needs freeing, i.e. how much was just added. + 34. Tries to free memory from the original open font cache. The result should be that + memory should be freed from openFont2 cache, and not openFont cache. + 35. Checks + a) if the memory used by openFont2 cache has reduced, i.e. back to original memory. + b) if the last entry from openFont2 cache has been deleted. + c) last entry from openFont cache is intact. + 36. Cleans up font2, font1 and removes all fonts. + + @SYMTestExpectedResults + All tests shall pass. + +*/ +void CTShaperCache::TestShaperCacheAPIsL() + { + INFO_PRINTF1(_L("The following results are for shaper cache API tests\n")); + + // Create a dummy TShapeHeader object that will be cached, and reused all through this test + TShapeHeader* shape = 0; + + // get some memory to pass back the results, + // This needs to be big enough for a TShapeHeader + // plus 10 bytes for every glyph returned (-1 for the 1 byte allocated in TShapeHeader for iBuffer) + shape = reinterpret_cast( iHeap->AllocL(sizeof(TShapeHeader) + (KResultNumberOfGlyphs * 10) + 3) ); + + // get the results into the shaper structure 'shape' + shape->iGlyphCount = KResultNumberOfGlyphs; + shape->iCharacterCount = 8; + shape->iReserved0 = 0; + shape->iReserved1 = 0; + + // iBuffer contains 10 bytes for every glyph + // the glyph code (4 bytes), position X(2 bytes) Y(2 bytes) and indices(2 bytes) + // first is glyph count * 4 byte glyph codes + TUint32* glyphOut = reinterpret_cast(shape->iBuffer); + TInt16* posOut = reinterpret_cast(shape->iBuffer + + (4 * KResultNumberOfGlyphs)); + TInt16* indicesOut = reinterpret_cast(shape->iBuffer + + (8 * KResultNumberOfGlyphs) + 4); + + *glyphOut++ = (TUint32)1461; + *posOut++ = (TInt16)0; + *posOut++ = (TInt16)0; + *indicesOut++ = (TInt16)0; + + *glyphOut++ = (TUint32)1778; + *posOut++ = (TInt16)12; + *posOut++ = (TInt16)0; + *indicesOut++ = (TInt16)7; + + *glyphOut++ = (TUint32)1550; + *posOut++ = (TInt16)16; + *posOut++ = (TInt16)0; + *indicesOut++ = (TInt16)3; + + *glyphOut++ = (TUint32)1362; + *posOut++ = (TInt16)28; + *posOut++ = (TInt16)0; + *indicesOut++ = (TInt16)7; + + // There is an extra pair of positions: this is the total advance + posOut[0] = (TInt16)28; + posOut[1] = (TInt16)0; + + TFontShapeFunctionParameters* params; + params = reinterpret_cast( iHeap->AllocL(sizeof(TFontShapeFunctionParameters))); + params->iEnd = 8; + params->iLanguage = 0; + params->iScript = KDevanagariScriptCode; + params->iStart = 0; + //TBufC16<9> text(KTextToShape); + params->iText = &KTextToShape(); + + // Add fonts + TUid id1 = iFontStore->AddFileL(KFontDummy); + TUid id2 = iFontStore->AddFileL(KFontDummy_b); + TUid id3 = iFontStore->AddFileL(KFontDummy_i); + TUid id4 = iFontStore->AddFileL(KFontDummy_bi); + + INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 1: Testing cache with a single COpentFont cache")); + + TInt typefaces = iFontStore->NumTypefaces(); + TInt typeface = 0; + TInt height = 12; + + TTypefaceSupport support; + iFontStore->TypefaceSupport(support,typeface); + TFontSpec fs; + fs.iTypeface = support.iTypeface; + + INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height); + //Create a font + CFont* font = NULL; + fs.iHeight = iFontStore->FontHeightInTwips(typeface,height); + // get a COpenFont object + iFontStore->GetNearestFontToDesignHeightInPixels(font, fs); + CleanupStack::PushL(font); + + + // Do the testing only if the font is a COpenFont + COpenFont* openFont = NULL; + CShaper::TInput input; + if (((CBitmapFont*)font)->IsOpenFont()) + { + __UHEAP_MARK; + openFont = ((CBitmapFont*)font)->OpenFont(); + + /***************************First Test*************************** + Attempt to put this into the shaper cache and then delete it. Test if it was successful + */ + TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(0,params, shape); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 1: Simple cache insertion test")); + TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2); + + /* Call DeleteShape to decrement the reference count */ + ((CBitmapFont*)font)->DeleteShape(0, cached_header); + + // Now delete this data + openFont->FreeShaperCacheMemory(openFont->GetGlyphCache()->iShapingInfoCacheMemory); + TEST(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 1); + // Put the shaped data back into the cache to continue with testing + cached_header = openFont->InsertShapedDataIntoCache(0,params, shape); + TEST(cached_header != NULL && openFont->GetGlyphCache()->iNumberOfShaperCacheEntries == 2); + ((CBitmapFont*)font)->DeleteShape(0, cached_header); + + /**************************Second Test************************** + Now change the shaped data slightly to make it into a new shaped data and insert into the + cache as a new entry + */ + shape->iGlyphCount++; + params->iEnd++; + TShapeHeader* cached_header2 = openFont->InsertShapedDataIntoCache(0,params, shape); + + /* Now test if the LRU cache is working by seeing if the first entry in the cache is the newest one */ + COpenFontGlyphCache* glyphCache = openFont->GetGlyphCache(); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 2: Test the LRU (Least Recently Used) cache structure")); + TEST(glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount == KResultNumberOfGlyphs + 1); + + /* Call DeleteShape to decrement the reference count */ + ((CBitmapFont*)font)->DeleteShape(0, cached_header2); + + + /**************************Third Test************************** + Call the GetShapedData API and test the returned TShapeHeader, and also check if the returned + cache entry is now at the top of the cache + */ + + /* Now search the cache for the first entry using the GetShapedData API */ + params->iEnd --; + TInt expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount; + TShapeHeader* searchedCachedHeader = openFont->GetShapedData(0,params); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 3: GetShapedData API test")); + TEST(searchedCachedHeader->iGlyphCount == expectedGlyphCount && + searchedCachedHeader->iGlyphCount ==glyphCache->iShaperCacheSentinel->iNext->iShapeHeader->iGlyphCount); + + /* Call DeleteShape to decrement the reference count */ + ((CBitmapFont*)font)->DeleteShape(0, searchedCachedHeader); + + /* Bring the end value back to its original value */ + params->iEnd ++; + + + /**************************Fourth Test************************** + Fill the cache and then test replacement policy by attempting to add a new entry + */ + + /* First prepare a raw input data structure */ + TInt memoryUsed = 0; + input.iText = &KTextToShape(); + input.iStart = 0; + input.iEnd = params->iEnd; + input.iScript= KDevanagariScriptCode; + input.iLanguage = 0; + input.iMaximumAdvance = KMaxTInt; + input.iFlags = 0; + input.iSessionHandle = 0; + input.iReserved1 = 0; + TInt addedBytes = 0; + TShapeHeader* chached_header3 = 0; + + /* Keep inserting pseudo-new shaped entries into the cache to fill it up */ + while(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() < KMaxShaperSesssionCacheMemory) + { + memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage(); + // Change the cached entries slightly to distinguish between each entry + shape->iGlyphCount++; + input.iEnd++; + chached_header3 = glyphCache->Insert(0,iHeap, input, shape, addedBytes); + if (chached_header3 != NULL) + openFont->File()->GetFontStore()->SetShaperCacheMemUsage(memoryUsed + addedBytes); + ((CBitmapFont*)font)->DeleteShape(0, chached_header3); + chached_header3 = NULL; + } + + /* Now try to add a new entry, and check that the entry replaced was the last entry in the cache */ + TInt last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount; + shape->iGlyphCount++; + params->iEnd = input.iEnd + 1; + + /* Calculate the memory needed for the new entry */ + TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2) + * shape->iGlyphCount + sizeof(TInt16) * 2; + TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + + sizeof(TShapeHeader) + sizeof(TUint16)*params->iText->Length(); + + TInt bytesToDelete = 0; + COpenFontShaperCacheEntry* previous = glyphCache->iShaperCacheSentinel->iPrevious; + /* Calculate the memory that will be freed to accommodate the new entry, + and the position of the last entry in the cache once deletion is done */ + while (bytesToDelete <= bytes_needed) + { + bytesToDelete += (((sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2) * previous->iShapeHeader->iGlyphCount + sizeof(TInt16) * 2) + + (sizeof(COpenFontShaperCacheEntry) + sizeof(TShapeHeader) + sizeof(TUint16)*params->iText->Length())); + previous = previous->iPrevious; + } + + /* Find the glyphcount of the expected new last entry in the cache */ + expectedGlyphCount = previous->iShapeHeader->iGlyphCount; + + /* Finally, do the insertion, and test */ + TShapeHeader* cached_header4 = openFont->InsertShapedDataIntoCache(0, params, shape); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 4: LRU cache replacement policy test")); + TEST(glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount); + + /* Call DeleteShape to decrement the reference cout */ + ((CBitmapFont*)font)->DeleteShape(0, cached_header4); + + + /**************************Fifth Test************************** + Simply test the FreeShaperCacheMemory API + */ + + /* Calculate the memory of occupied by the last entry in the cache. This is the memory that will + be released when the last entry is deleted + */ + last_entry_glyph_count = glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount; + bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2) + * last_entry_glyph_count + sizeof(TInt16) * 2; + + bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + + sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length(); + + memoryUsed = openFont->File()->GetFontStore()->GetShaperCacheMemUsage(); + expectedGlyphCount = glyphCache->iShaperCacheSentinel->iPrevious->iPrevious->iShapeHeader->iGlyphCount; + TInt memoryReleased = openFont->FreeShaperCacheMemory(bytes_needed); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 5: FreeShaperCacheMemory API test\n")); + TEST(openFont->File()->GetFontStore()->GetShaperCacheMemUsage() == memoryUsed - memoryReleased && + glyphCache->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount); + + __UHEAP_MARKEND; + } + + INFO_PRINTF1(_L("SHAPER CACHE API TESTS SET 2: Testing cache with a two COpentFont caches")); + /* Now test with multiple open fonts with caches */ + /* Create the new font */ + height = 4; + iFontStore->TypefaceSupport(support,typeface); + fs.iTypeface = support.iTypeface; + + INFO_PRINTF3(_L("Typeface is %d and height is %d"), typeface, height); + + CFont* font2 = NULL; + fs.iHeight = iFontStore->FontHeightInTwips(typeface,height); + iFontStore->GetNearestFontToDesignHeightInPixels(font2, fs); + CleanupStack::PushL(font2); + + COpenFont* openFont2; + /* Do the testing only if the font is a COpenFont */ + if (((CBitmapFont*)font2)->IsOpenFont()) + { + __UHEAP_MARK; + openFont2 = ((CBitmapFont*)font2)->OpenFont(); + + /***************************Sixth Test*************************** + Attempt to put a new entry into the second shaper cache and test if it was successful + */ + + /* Create a pseudo-new shape header to put into the cache of this new open font */ + shape->iGlyphCount++; + params->iEnd++; + + /* Insert an entry into the cache */ + TShapeHeader* cached_header5 = openFont2->InsertShapedDataIntoCache(0, params, shape); + ((CBitmapFont*)font2)->DeleteShape(0, cached_header5); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 6: Second cache insertion test")); + TEST(cached_header5 != NULL && openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 2); + + /***************************Seventh, Eighth and Ninth Tests*************************** + Test cache memory freeing policy, i.e. delete from all other caches except the current one + */ + + /* First find out how much memory needs freeing, i.e. how much was just added */ + TInt bufferSize = (sizeof(TUint32) + sizeof(TInt16) + sizeof(TInt16) * 2) + * shape->iGlyphCount + sizeof(TInt16) * 2; + + TInt bytes_needed = bufferSize + sizeof(COpenFontShaperCacheEntry) + + sizeof(TShapeHeader) + sizeof(TUint16)*input.iText->Length(); + + + /* Now try to free memory from the original open font cache. The result should be that + memory should be freed from openFont2 cache, and not openFont cache + */ + TInt memoryUsed = openFont2->GetGlyphCache()->iShapingInfoCacheMemory; + TInt expectedGlyphCount = openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount; + TInt deletedMemory = openFont->FreeShaperCacheMemory(bytes_needed); + + /* Now check: + a) if the memory used by openFont2 cache has reduced, i.e. back to original memory + b) if the last entry from openFont2 cache has been deleted + c) last entry from openFont cache is intact + */ + INFO_PRINTF1(_L("SHAPER CACHE API TEST 7: Test if memory is freed from second COpenFont")); + TEST(memoryUsed - openFont2->GetGlyphCache()->iShapingInfoCacheMemory == deletedMemory && + openFont2->GetGlyphCache()->iShapingInfoCacheMemory == 0); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 8: Test if last entry of second COpenFont is deleted")); + TEST(openFont2->GetGlyphCache()->iNumberOfShaperCacheEntries == 1); + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 9: Test if the last entry of the first COpenFont is intact")); + TEST(openFont->GetGlyphCache()->iShaperCacheSentinel->iPrevious->iShapeHeader->iGlyphCount == expectedGlyphCount); + + /***********************************Tenth Tests***************************************** + Test cache memory consistency and that there are no leakages when deleting memory from the cache + */ + + /* Continue adding entries to second open font cache until the memory used by the first one + goes down to zero, at which point the number of cache entries should be 1, and memory from + the current open font should start getting released and eventually reach 0 when the number + of cached entries reaches 1. + */ + TShapeHeader* cached_header6 = NULL; + /* Keep inserting pseudo-new shaped entries into the cache to fill it up */ + while(openFont->GetGlyphCache()->iNumberOfShaperCacheEntries > 1) + { + memoryUsed = openFont2->File()->GetFontStore()->GetShaperCacheMemUsage(); + // Change the cached entries slightly to distinguish between each entry + shape->iGlyphCount++; + params->iEnd++; + cached_header6 = openFont2->InsertShapedDataIntoCache(0, params, shape); + ((CBitmapFont*)font2)->DeleteShape(0, cached_header6); + cached_header6 = NULL; + } + + INFO_PRINTF1(_L("SHAPER CACHE API TEST 10: Test consistency of cache memory")); + TEST(openFont->GetGlyphCache()->iShapingInfoCacheMemory == 0); + + + /** + @SYMTestCaseID GRAPHICS-SYSLIB-FNTSTORE-UT-4001 + @SYMTestCaseDesc Test that when trying to delete a shape not in the cache it + does not loop infinitely trying to find it. + @SYMTestPriority Medium + @SYMTestActions Pass a null shape header to the DeleteShape function. + @SYMTestExpectedResults The function call should return instead of looping infinitely. + @SYMDEF PDEF125354 + */ + ((CTShaperCacheStep*)iStep)->RecordTestResultL(); + ((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-SYSLIB-FNTSTORE-UT-4001")); + INFO_PRINTF1(_L("SHAPER CACHE API TEST 11: Test that shape not found does not loop infinitely.")); + TShapeHeader* null_header = NULL; + // Timeout set in TEF script to catch infinite loop. + ((CBitmapFont*)font2)->DeleteShape(0, null_header); + + ((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep(); + __UHEAP_MARKEND; + } + + /* Cleanup font2*/ + CleanupStack::Pop(font2); + iFontStore->ReleaseFont(font2); + + /* Cleanup font1 */ + CleanupStack::Pop(font); + iFontStore->ReleaseFont(font); + + // Remove the fonts + iFontStore->RemoveFile(id1); + iFontStore->RemoveFile(id2); + iFontStore->RemoveFile(id3); + iFontStore->RemoveFile(id4); + } + +void CTShaperCache::RunTestCaseL(TInt aCurTestCase) + { + ((CTShaperCacheStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName); + switch(aCurTestCase) + { + case 1: + ((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0043")); + INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 1 ########################\n")); + TRAPD(err,Test1L()); + TEST(err == KErrNone); + break; + case 2: + ((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0044")); + INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 2 ########################\n")); + TRAP(err,Test2L()); + TEST(err == KErrNone); + break; + case 3: + ((CTShaperCacheStep*)iStep)->SetTestStepID(_L("GRAPHICS-FNTSTORE-0045")); + INFO_PRINTF1(_L("#################### T_SHAPERCACHE test case 3 ########################")); + TRAP(err,TestShaperCacheAPIsL()); + TEST(err == KErrNone); + break; + case 4: + ((CTShaperCacheStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName); + ((CTShaperCacheStep*)iStep)->CloseTMSGraphicsStep(); + TestComplete(); + break; + } + ((CTShaperCacheStep*)iStep)->RecordTestResultL(); + } + + +//-------------- +__CONSTRUCT_STEP__(ShaperCache) + + +