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