|
1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <gdi.h> |
|
17 #include <fbs.h> |
|
18 #include <e32test.h> |
|
19 #include <e32property.h> |
|
20 #include <graphics/openfontconstants.h> |
|
21 #include <graphics/openfontrasterizer.h> |
|
22 #include <graphics/gdi/gdiplatapi.h> |
|
23 #include "fbsmessage.h" |
|
24 #include "tfonttableandglyph.h" |
|
25 |
|
26 //global variable |
|
27 _LIT16(KTestFontFile, "C:\\DejaVuSans.ttf"); |
|
28 _LIT16(KTestFontFaceName, "DejaVu Sans"); |
|
29 |
|
30 _LIT16(KTestFontFile2, "C:\\DejaVuSerif.ttf"); |
|
31 _LIT16(KTestFontFaceName2, "DejaVu Serif"); |
|
32 |
|
33 static void LoadOpenFontLibraries(CFontStore* aFontStore); |
|
34 |
|
35 LOCAL_C const TInt KFontHeight = 12; |
|
36 LOCAL_C const TInt KInvalidGlyphId = 0xffff; |
|
37 |
|
38 CTFontAndGlyph::CTFontAndGlyph(CTestStep* aStep) : |
|
39 CTGraphicsBase(aStep), |
|
40 iBmp(NULL), |
|
41 iBmp2(NULL), |
|
42 iDevice(NULL), |
|
43 iDevice2(NULL), |
|
44 iFont(NULL), |
|
45 iFont2(NULL), |
|
46 iFontStore(NULL), |
|
47 iFontSpec(KTestFontFaceName, KFontHeight), |
|
48 iFontSpec2(KTestFontFaceName2, KFontHeight) |
|
49 { |
|
50 // a null constructor |
|
51 } |
|
52 |
|
53 CTFontAndGlyph::~CTFontAndGlyph() |
|
54 { |
|
55 CleanEnv(); |
|
56 } |
|
57 |
|
58 void CTFontAndGlyph::RunTestCaseL(TInt aCurTestCase) |
|
59 { |
|
60 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName); |
|
61 |
|
62 switch(aCurTestCase) |
|
63 { |
|
64 case 1: |
|
65 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4079")); |
|
66 INFO_PRINTF1(_L("GetHintedGlyphById")); |
|
67 GetHintedGlyphById(); |
|
68 break; |
|
69 |
|
70 case 2: |
|
71 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4080")); |
|
72 INFO_PRINTF1(_L("GetUnHintedGlyphById")); |
|
73 GetUnHintedGlyphById(); |
|
74 break; |
|
75 |
|
76 case 3: |
|
77 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4081")); |
|
78 INFO_PRINTF1(_L("GetHintedGlyphByWrongId")); |
|
79 GetHintedGlyphByWrongId(); |
|
80 break; |
|
81 |
|
82 case 4: |
|
83 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4082")); |
|
84 INFO_PRINTF1(_L("GetGlyphWithNoMem")); |
|
85 GetGlyphWithNoMem(); |
|
86 break; |
|
87 |
|
88 case 5: |
|
89 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4083")); |
|
90 INFO_PRINTF1(_L("GetFontTable")); |
|
91 GetFontTable(); |
|
92 break; |
|
93 |
|
94 |
|
95 case 6: |
|
96 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4084")); |
|
97 INFO_PRINTF1(_L("GetFontTableByWrongTag")); |
|
98 GetFontTableByWrongTag(); |
|
99 break; |
|
100 |
|
101 case 7: |
|
102 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4085")); |
|
103 INFO_PRINTF1(_L("GetFontTableWithNoMem")); |
|
104 GetFontTableWithNoMem(); |
|
105 break; |
|
106 |
|
107 case 8: |
|
108 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4089")); |
|
109 INFO_PRINTF1(_L("GlyphOutlineIteratorPanics")); |
|
110 GlyphOutlineIteratorPanics(); |
|
111 break; |
|
112 |
|
113 case 9: |
|
114 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4090")); |
|
115 INFO_PRINTF1(_L("WDPAndSMPSafeTest")); |
|
116 SMPAndWDPSafeTest(); |
|
117 break; |
|
118 |
|
119 case 10: |
|
120 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4087")); |
|
121 INFO_PRINTF1(_L("TestFbsFontHandleIsZeroForFont")); |
|
122 TestFbsFontHandleIsZeroForFont(); |
|
123 break; |
|
124 |
|
125 case 11: |
|
126 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4088")); |
|
127 INFO_PRINTF1(_L("TestFbsFontHandleIsZeroForGlyph")); |
|
128 TestFbsFontHandleIsZeroForGlyph(); |
|
129 break; |
|
130 |
|
131 case 12: |
|
132 ((CTFontAndGlyphStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName); |
|
133 ((CTFontAndGlyphStep*)iStep)->CloseTMSGraphicsStep(); |
|
134 TestComplete(); |
|
135 break; |
|
136 default: |
|
137 INFO_PRINTF1(_L("Invalid test case id found.")); |
|
138 } |
|
139 ((CTFontAndGlyphStep*)iStep)->RecordTestResultL(); |
|
140 } |
|
141 |
|
142 |
|
143 /** |
|
144 @SYMTestCaseID TI18N-GDI-CIT-4083 |
|
145 @SYMTestCaseDesc Get font table. |
|
146 @SYMTestActions Get font table using the new RFontTable class and test |
|
147 the return value. |
|
148 @SYMTestExpectedResults Open() returns KErrNone. TableContent returns the |
|
149 table content. |
|
150 */ |
|
151 void CTFontAndGlyph::GetFontTable() |
|
152 { |
|
153 __UHEAP_MARK; |
|
154 RFontTable fontTable; |
|
155 TInt err = fontTable.Open(*iFont, 0x68656164); |
|
156 TEST(err == KErrNone); |
|
157 TUint32* tablePtr = (TUint32*)fontTable.TableContent(); |
|
158 TEST(tablePtr != NULL); |
|
159 TEST(tablePtr[3] == 0xF53C0F5F); //magic number is correct |
|
160 RFontTable fontTableInCache; |
|
161 err = fontTableInCache.Open(*iFont, 0x68656164); |
|
162 TEST(err == KErrNone); |
|
163 TUint32* tablePtr2 = (TUint32*)fontTableInCache.TableContent(); |
|
164 TEST(tablePtr2[3] == 0xF53C0F5F); |
|
165 TEST(tablePtr == tablePtr2); |
|
166 |
|
167 RFontTable fontTable2; |
|
168 err = fontTable2.Open(*iFont2, 0x68656164); |
|
169 TEST(err == KErrNone); |
|
170 tablePtr = (TUint32*)fontTable2.TableContent(); |
|
171 TEST(tablePtr != NULL); |
|
172 TEST(tablePtr[3] == 0xF53C0F5F); //magic number is correct |
|
173 RFontTable fontTableInCache2; |
|
174 err = fontTableInCache2.Open(*iFont2, 0x68656164); |
|
175 TEST(err == KErrNone); |
|
176 tablePtr2 = (TUint32*)fontTableInCache2.TableContent(); |
|
177 TEST(tablePtr2[3] == 0xF53C0F5F); |
|
178 TEST(tablePtr == tablePtr2); |
|
179 |
|
180 fontTableInCache.Close(); |
|
181 fontTable.Close(); |
|
182 fontTableInCache2.Close(); |
|
183 fontTable2.Close(); |
|
184 __UHEAP_MARKEND; |
|
185 } |
|
186 |
|
187 |
|
188 /** |
|
189 @SYMTestCaseID TI18N-GDI-CIT-4084 |
|
190 @SYMTestCaseDesc Get font table, providing an invalid tag. |
|
191 @SYMTestActions Get font table, providing an invalid tag (0). |
|
192 Test the return value. |
|
193 @SYMTestExpectedResults Open() returns KErrNotFound. |
|
194 */ |
|
195 void CTFontAndGlyph::GetFontTableByWrongTag() |
|
196 { |
|
197 __UHEAP_MARK; |
|
198 RFontTable fontTableForWrongID; |
|
199 TInt err = fontTableForWrongID.Open(*iFont, 0); |
|
200 fontTableForWrongID.Close(); |
|
201 TEST(KErrNotFound == err); |
|
202 __UHEAP_MARKEND; |
|
203 } |
|
204 |
|
205 |
|
206 /** |
|
207 @SYMTestCaseID TI18N-GDI-CIT-4085 |
|
208 @SYMTestCaseDesc Get font table, when system is OOM. |
|
209 @SYMTestActions Get font table, simulate OOM conditions using debug macros, |
|
210 and test return value. |
|
211 @SYMTestExpectedResults Open() returns KErrNoMemory. TableContent() and |
|
212 TableLength() return NULL/0. |
|
213 */ |
|
214 void CTFontAndGlyph::GetFontTableWithNoMem() |
|
215 { |
|
216 #ifdef _DEBUG |
|
217 __UHEAP_MARK; |
|
218 RFontTable aFontTableForMem; |
|
219 RFbsSession *fbsSession = RFbsSession::GetSession(); |
|
220 fbsSession->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeHeapMemory, 1); |
|
221 TInt err = aFontTableForMem.Open(*iFont, 0x68656164); /* 'head' in ascii (hex) */ |
|
222 TEST(KErrNoMemory == err); |
|
223 TEST(0 == aFontTableForMem.TableLength()); |
|
224 TEST(0 == aFontTableForMem.TableContent()); |
|
225 aFontTableForMem.Close(); |
|
226 fbsSession->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeHeapMemory); |
|
227 __UHEAP_MARKEND; |
|
228 #else |
|
229 INFO_PRINTF1(_L("Skipping test GetFontTableWithNoMem in release mode")); |
|
230 #endif |
|
231 } |
|
232 |
|
233 |
|
234 /** |
|
235 @SYMTestCaseID TI18N-GDI-CIT-4082 |
|
236 @SYMTestCaseDesc Get glyph outline when system is out of memory. |
|
237 @SYMTestActions Get glyph outline. Simulate OOM faliures using debug |
|
238 macros to check if the program logic is correct. |
|
239 @SYMTestExpectedResults Open() always returns KErrNoMemory. |
|
240 */ |
|
241 void CTFontAndGlyph::GetGlyphWithNoMem() |
|
242 { |
|
243 #ifdef _DEBUG |
|
244 __UHEAP_MARK; |
|
245 RFbsSession *fbsSession = RFbsSession::GetSession(); |
|
246 |
|
247 TUint glyphIndex[] = {4, 4, KInvalidGlyphId}; |
|
248 __UHEAP_FAILNEXT(1); |
|
249 RGlyphOutlineIterator it1; |
|
250 TInt err = it1.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
251 TEST(err == KErrNoMemory); |
|
252 it1.Close(); |
|
253 |
|
254 __UHEAP_FAILNEXT(2); |
|
255 RGlyphOutlineIterator it2; |
|
256 err = it2.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0])); |
|
257 TEST(err == KErrNoMemory); |
|
258 TEST(KErrNotFound == it2.Next()); |
|
259 it2.Close(); |
|
260 |
|
261 __UHEAP_FAILNEXT(3); |
|
262 RGlyphOutlineIterator it3; |
|
263 err = it3.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
264 TEST(err == KErrNoMemory); |
|
265 TEST(KErrNotFound == it2.Next()); |
|
266 it3.Close(); |
|
267 |
|
268 RGlyphOutlineIterator it4; |
|
269 fbsSession = RFbsSession::GetSession(); |
|
270 fbsSession->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, 1); |
|
271 err = it4.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0])); |
|
272 TEST(KErrNoMemory == err); |
|
273 TEST(KErrNotFound == it2.Next()); |
|
274 fbsSession->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory); |
|
275 it4.Close(); |
|
276 |
|
277 __UHEAP_FAILNEXT(4); |
|
278 RGlyphOutlineIterator it5; |
|
279 err = it5.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0])); |
|
280 TEST(err == KErrNoMemory); |
|
281 TEST(KErrNotFound == it2.Next()); |
|
282 it5.Close(); |
|
283 __UHEAP_MARKEND; |
|
284 #else |
|
285 INFO_PRINTF1(_L("Skipping test GetGlyphWithNoMem in release mode")); |
|
286 #endif |
|
287 } |
|
288 |
|
289 |
|
290 /** |
|
291 @SYMTestCaseID TI18N-GDI-CIT-4079 |
|
292 @SYMTestCaseDesc Get hinted glyph outline |
|
293 @SYMTestActions Get hinted glyph outline for glyph 4 and 65536. |
|
294 Pass NULL for the 'aCodes' argument, and 0 for the 'aCount' to test |
|
295 param validation. Check return values in each situation. |
|
296 @SYMTestExpectedResults Open() returns KErrNone. Outline() returns a |
|
297 valid pointer to the string representing the outline. OutlineLength() returns |
|
298 the corresponding string length. |
|
299 */ |
|
300 void CTFontAndGlyph::GetHintedGlyphById() |
|
301 { |
|
302 __UHEAP_MARK; |
|
303 RGlyphOutlineIterator glyphIterator1; |
|
304 TUint glyphIndex[] = {4, 4, KInvalidGlyphId}; //two 4 to ensure the 2nd glyph is in cache. |
|
305 TInt err = glyphIterator1.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
306 TEST(err == KErrNone); |
|
307 TInt len1 = glyphIterator1.OutlineLength(); |
|
308 const TUint8* ptr1 = glyphIterator1.Outline(); |
|
309 TInt end = glyphIterator1.Next(); |
|
310 const TUint8* ptr2 = glyphIterator1.Outline(); |
|
311 TInt len2= glyphIterator1.OutlineLength(); |
|
312 TEST(len1 > 0); |
|
313 TEST(ptr1 != NULL); |
|
314 TEST(ptr1 == ptr2); |
|
315 TEST(len1 == len2); |
|
316 |
|
317 RGlyphOutlineIterator glyphIterator1b; // for font file 2 |
|
318 TUint glyphIndex_2[] = {0x41, 0x41, KInvalidGlyphId}; |
|
319 err = glyphIterator1b.Open(*iFont2, glyphIndex_2, |
|
320 sizeof(glyphIndex_2)/sizeof(glyphIndex_2[0]), ETrue); |
|
321 TEST(err == KErrNone); |
|
322 len1 = glyphIterator1b.OutlineLength(); |
|
323 ptr1 = glyphIterator1b.Outline(); |
|
324 end = glyphIterator1b.Next(); |
|
325 ptr2 = glyphIterator1b.Outline(); |
|
326 len2= glyphIterator1b.OutlineLength(); |
|
327 TEST(len1 > 0); |
|
328 TEST(ptr1 != NULL); |
|
329 TEST(ptr1 == ptr2); |
|
330 TEST(len1 == len2); |
|
331 |
|
332 end = glyphIterator1.Next(); |
|
333 len1 = glyphIterator1.OutlineLength(); |
|
334 ptr1 = glyphIterator1.Outline(); |
|
335 // for the invalid glyph id, len1<0 indicates an error. |
|
336 TEST(NULL == ptr1); |
|
337 TEST(len1 < 0); |
|
338 end = glyphIterator1.Next(); |
|
339 TEST(KErrNotFound == end); |
|
340 // calling Outline() or OutlineLength() causes panic if Next() |
|
341 // returns KErrNotFound |
|
342 glyphIterator1.Close(); |
|
343 |
|
344 end = glyphIterator1b.Next(); |
|
345 len1 = glyphIterator1b.OutlineLength(); |
|
346 ptr1 = glyphIterator1b.Outline(); |
|
347 // for the invalid glyph id, len1<0 indicates an error. |
|
348 TEST(NULL == ptr1); |
|
349 TEST(len1 < 0); |
|
350 end = glyphIterator1b.Next(); |
|
351 TEST(KErrNotFound == end); |
|
352 // calling Outline() or OutlineLength() causes panic if Next() |
|
353 // returns KErrNotFound |
|
354 glyphIterator1b.Close(); |
|
355 |
|
356 RGlyphOutlineIterator glyphIterator3; |
|
357 err = glyphIterator3.Open(*iFont, glyphIndex, 0, ETrue); |
|
358 TEST(KErrArgument == err); |
|
359 TEST(KErrNotFound == glyphIterator3.Next()); |
|
360 glyphIterator3.Close(); |
|
361 |
|
362 RGlyphOutlineIterator glyphIterator4; |
|
363 err = glyphIterator4.Open(*iFont, NULL, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
364 TEST(KErrArgument == err); |
|
365 TEST(KErrNotFound == glyphIterator4.Next()); |
|
366 glyphIterator4.Close(); |
|
367 __UHEAP_MARKEND; |
|
368 } |
|
369 |
|
370 |
|
371 /** |
|
372 @SYMTestCaseID TI18N-GDI-CIT-4081 |
|
373 @SYMTestCaseDesc Get hinted glyph outline, passing in invalid IDs. |
|
374 @SYMTestActions Get hinted glyph outline, passing in invalid IDs. Check |
|
375 the return values. |
|
376 @SYMTestExpectedResults Open() returns KErrNone. Outline() returns NULL. |
|
377 OutlineLength() returns KErrGeneral. |
|
378 */ |
|
379 void CTFontAndGlyph::GetHintedGlyphByWrongId() |
|
380 { |
|
381 __UHEAP_MARK; |
|
382 RGlyphOutlineIterator glyphIterator; |
|
383 TUint glyphIndex[] = {KInvalidGlyphId, KInvalidGlyphId}; |
|
384 TInt err = glyphIterator.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
385 TEST(err == KErrNone); |
|
386 const TUint8* ptr = glyphIterator.Outline(); |
|
387 TInt len = glyphIterator.OutlineLength(); |
|
388 TEST(KErrGeneral == len); |
|
389 TEST(ptr == NULL); |
|
390 TInt ret = glyphIterator.Next(); |
|
391 TEST(KErrNone == ret); |
|
392 glyphIterator.Close(); |
|
393 __UHEAP_MARKEND; |
|
394 } |
|
395 |
|
396 |
|
397 /** |
|
398 @SYMTestCaseID TI18N-GDI-CIT-4080 |
|
399 @SYMTestCaseDesc Get unhinted glyph outline |
|
400 @SYMTestActions Get unhinted glyph outline for glyph 4 and 5. |
|
401 @SYMTestExpectedResults Open() returns KErrNone. Outline() and |
|
402 OutlineLength() returns the outline string and corresponding length. |
|
403 */ |
|
404 void CTFontAndGlyph::GetUnHintedGlyphById() |
|
405 { |
|
406 __UHEAP_MARK; |
|
407 RGlyphOutlineIterator glyphIterator2; |
|
408 TUint glyphIndex[] = {4, 4, 5}; //two '4' to ensure the 2nd is in cache. |
|
409 TInt err = glyphIterator2.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), EFalse); |
|
410 TEST(err == KErrNone); |
|
411 const TUint8* ptr1 = glyphIterator2.Outline(); |
|
412 TInt len1 = glyphIterator2.OutlineLength(); |
|
413 err = glyphIterator2.Next(); |
|
414 TEST(err == KErrNone); |
|
415 const TUint8* ptr2 = glyphIterator2.Outline(); |
|
416 TInt len2= glyphIterator2.OutlineLength(); |
|
417 err = glyphIterator2.Next(); |
|
418 TEST(err == KErrNone); |
|
419 TEST(len1 > 0); |
|
420 TEST(ptr1 == ptr2); |
|
421 TEST(ptr1 != NULL); |
|
422 TEST(len1 == len2); |
|
423 |
|
424 RGlyphOutlineIterator glyphIterator2b; // for the 2nd font file |
|
425 TUint glyphIndex2[] = {0x41, 0x41, 0x42}; |
|
426 err = glyphIterator2b.Open(*iFont2, glyphIndex2, |
|
427 sizeof(glyphIndex2)/sizeof(glyphIndex2[0]), EFalse); |
|
428 TEST(err == KErrNone); |
|
429 ptr1 = glyphIterator2b.Outline(); |
|
430 len1 = glyphIterator2b.OutlineLength(); |
|
431 err = glyphIterator2b.Next(); |
|
432 TEST(err == KErrNone); |
|
433 ptr2 = glyphIterator2b.Outline(); |
|
434 len2= glyphIterator2b.OutlineLength(); |
|
435 err = glyphIterator2b.Next(); |
|
436 TEST(err == KErrNone); |
|
437 TEST(len1 > 0); |
|
438 TEST(ptr1 == ptr2); |
|
439 TEST(ptr1 != NULL); |
|
440 TEST(len1 == len2); |
|
441 |
|
442 glyphIterator2.Close(); |
|
443 glyphIterator2b.Close(); |
|
444 __UHEAP_MARKEND; |
|
445 } |
|
446 |
|
447 /** |
|
448 @SYMTestCaseID TI18N-GDI-CIT-4087 |
|
449 @SYMTestCaseDesc Pass invalid font handle to FBS when getting font table. |
|
450 @SYMTestActions Pass invalid font handle to FBS when getting font table. |
|
451 And check the return value. |
|
452 @SYMTestExpectedResults Open returns KErrNotFound. |
|
453 */ |
|
454 void CTFontAndGlyph::TestFbsFontHandleIsZeroForFont() |
|
455 { |
|
456 __UHEAP_MARK; |
|
457 CFbsTestForFont* fbsFont = reinterpret_cast<CFbsTestForFont*> (iFont); |
|
458 TEST(NULL != fbsFont); |
|
459 fbsFont->SetHandle(0); |
|
460 TInt handle = fbsFont->Handle(); |
|
461 CFbsTestForFont tempFsbFont; |
|
462 tempFsbFont.Duplicate(handle); |
|
463 tempFsbFont.SetHandle(0); |
|
464 RFontTable ft1; |
|
465 TInt err = ft1.Open(tempFsbFont, 0x11667730); |
|
466 TEST(err == KErrNotFound); |
|
467 ft1.Close(); |
|
468 __UHEAP_MARKEND; |
|
469 } |
|
470 |
|
471 /** |
|
472 @SYMTestCaseID TI18N-GDI-CIT-4088 |
|
473 @SYMTestCaseDesc Pass invalid font handle to FBS when getting glyph outline. |
|
474 @SYMTestActions Pass invalid font handle to FBS when getting glyph outline. |
|
475 And check the return value. |
|
476 @SYMTestExpectedResults Open() returns KErrNotFound. |
|
477 */ |
|
478 void CTFontAndGlyph::TestFbsFontHandleIsZeroForGlyph() |
|
479 { |
|
480 __UHEAP_MARK; |
|
481 CFbsTestForFont* fbsFont = reinterpret_cast<CFbsTestForFont*> (iFont); |
|
482 TEST(NULL != fbsFont); |
|
483 TInt handle = fbsFont->Handle(); |
|
484 CFbsTestForFont tempFsbFont; |
|
485 tempFsbFont.Duplicate(handle); |
|
486 tempFsbFont.SetHandle(0); |
|
487 RGlyphOutlineIterator glyphIterator1; |
|
488 TUint glyphIndex[] = {1, 1, KInvalidGlyphId}; |
|
489 TInt err = glyphIterator1.Open(tempFsbFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue); |
|
490 TEST(err == KErrNotFound); |
|
491 glyphIterator1.Close(); |
|
492 __UHEAP_MARKEND; |
|
493 } |
|
494 |
|
495 static TInt OutlinePanicThread(TAny* /* ptr */) |
|
496 { |
|
497 CTrapCleanup* trapCleanup=CTrapCleanup::New(); |
|
498 RGlyphOutlineIterator it; |
|
499 it.Outline(); |
|
500 delete trapCleanup; |
|
501 return 0; |
|
502 } |
|
503 |
|
504 static TInt OutlineLengthPanicThread(TAny* /* ptr */) |
|
505 { |
|
506 CTrapCleanup* trapCleanup=CTrapCleanup::New(); |
|
507 RGlyphOutlineIterator it; |
|
508 it.OutlineLength(); |
|
509 delete trapCleanup; |
|
510 return 0; |
|
511 } |
|
512 |
|
513 void CTFontAndGlyph::OutlinePanics(TInt (*aThreadFun)(TAny*)) |
|
514 { |
|
515 __UHEAP_MARK; |
|
516 RThread thread; |
|
517 TThreadFunction fun(aThreadFun); |
|
518 TAny* ptr = NULL; |
|
519 thread.Create(_L("RGlyphOutlineIterator"), fun, 0x1000, 0x20000, 0x20000, ptr); |
|
520 |
|
521 TRequestStatus status; |
|
522 thread.Logon(status); |
|
523 thread.Resume(); |
|
524 User::WaitForRequest(status); |
|
525 |
|
526 TInt err = thread.ExitReason(); |
|
527 TEST(err == 0); |
|
528 TExitCategoryName name = thread.ExitCategory(); |
|
529 TEST(name == _L("GDI")); |
|
530 thread.Close(); |
|
531 __UHEAP_MARKEND; |
|
532 } |
|
533 |
|
534 |
|
535 void CTFontAndGlyph::OutlineLengthPanics(TInt (*aThreadFun)(TAny*)) |
|
536 { |
|
537 __UHEAP_MARK; |
|
538 RThread thread; |
|
539 TThreadFunction fun(aThreadFun); |
|
540 TAny* ptr = NULL; |
|
541 thread.Create(_L("RGlyphOutlineLengthIterator"), fun, 0x1000, 0x20000, 0x20000, ptr); |
|
542 |
|
543 TRequestStatus status; |
|
544 thread.Logon(status); |
|
545 thread.Resume(); |
|
546 User::WaitForRequest(status); |
|
547 |
|
548 TInt err = thread.ExitReason(); |
|
549 TEST(err == 0); |
|
550 TExitCategoryName name = thread.ExitCategory(); |
|
551 TEST(name == _L("GDI")); |
|
552 thread.Close(); |
|
553 __UHEAP_MARKEND; |
|
554 } |
|
555 |
|
556 /** |
|
557 @SYMTestCaseID TI18N-GDI-CIT-4089 |
|
558 @SYMTestCaseDesc Try to get glyph outline's length and content when |
|
559 the glyph is not found in font file. |
|
560 @SYMTestActions Try to get glyph outline's length and content when |
|
561 the glyph is not found in font file. This should cause a client panic. |
|
562 @SYMTestExpectedResults Both cases exit with ExitCategory 'GDI' and |
|
563 reason code 0. |
|
564 */ |
|
565 void CTFontAndGlyph::GlyphOutlineIteratorPanics() |
|
566 { |
|
567 __UHEAP_MARK; |
|
568 OutlinePanics(OutlinePanicThread); |
|
569 OutlineLengthPanics(OutlineLengthPanicThread); |
|
570 __UHEAP_MARKEND; |
|
571 } |
|
572 |
|
573 void CTFontAndGlyph::ConstructL() |
|
574 { |
|
575 INFO_PRINTF1(_L("Calling CTFontAndGlyph::ConstructL()")); |
|
576 iFontStore = CFontStore::NewL(&User::Heap()); |
|
577 LoadOpenFontLibraries(iFontStore); |
|
578 iFontStore->iKPixelWidthInTwips = 11860; |
|
579 iBmp = new (ELeave) CFbsBitmap; |
|
580 User::LeaveIfError(iBmp->Create(TSize(100,100),EGray2)); |
|
581 iDevice = CFbsBitmapDevice::NewL(iBmp); |
|
582 iUid = iFontStore->AddFileL(KTestFontFile); |
|
583 TInt err = iDevice->GetNearestFontToMaxHeightInTwips(iFont,iFontSpec,0); |
|
584 if (KErrNone != err) |
|
585 { |
|
586 iFontStore->RemoveFile(iUid); |
|
587 User::Leave(err); |
|
588 } |
|
589 |
|
590 iBmp2 = new (ELeave) CFbsBitmap; |
|
591 User::LeaveIfError(iBmp2->Create(TSize(100,100),EGray2)); |
|
592 iDevice2 = CFbsBitmapDevice::NewL(iBmp2); |
|
593 iUid2 = iFontStore->AddFileL(KTestFontFile2); |
|
594 err = iDevice2->GetNearestFontToMaxHeightInTwips(iFont2,iFontSpec2,0); |
|
595 if (KErrNone != err) |
|
596 { |
|
597 iFontStore->RemoveFile(iUid); |
|
598 iFontStore->RemoveFile(iUid2); |
|
599 User::Leave(err); |
|
600 } |
|
601 } |
|
602 |
|
603 void CTFontAndGlyph::CleanEnv() |
|
604 { |
|
605 iDevice->ReleaseFont(iFont); |
|
606 delete iDevice; |
|
607 delete iBmp; |
|
608 iFontStore->RemoveFile(iUid); |
|
609 |
|
610 iDevice2->ReleaseFont(iFont2); |
|
611 delete iDevice2; |
|
612 delete iBmp2; |
|
613 iFontStore->RemoveFile(iUid2); |
|
614 |
|
615 delete iFontStore; |
|
616 iDevice = NULL; |
|
617 iBmp = NULL; |
|
618 iFontStore = NULL; |
|
619 |
|
620 iDevice2 = NULL; |
|
621 iBmp2 = NULL; |
|
622 |
|
623 REComSession::FinalClose(); |
|
624 } |
|
625 |
|
626 //-------------- |
|
627 CTFontAndGlyphStep::CTFontAndGlyphStep() |
|
628 { |
|
629 SetTestStepName(KTFontTableAndGlyphStep); |
|
630 } |
|
631 |
|
632 CTGraphicsBase* CTFontAndGlyphStep::CreateTestL() |
|
633 { |
|
634 return new (ELeave) CTFontAndGlyph(this); |
|
635 } |
|
636 |
|
637 static void LoadOpenFontLibraries(CFontStore* aFontStore) |
|
638 { |
|
639 |
|
640 RImplInfoPtrArray implementationArray; |
|
641 TInt error; |
|
642 TInt ecomerror; |
|
643 TInt ecomnotready; |
|
644 TUid uid = {KUidOpenFontRasterizerPlunginInterface}; |
|
645 |
|
646 // Making sure that no race situation arises |
|
647 // If ECom is not ready, give it another chance and try again. if it still doesn't work |
|
648 // after the third try, then it just carries on quietly and fails... |
|
649 for (ecomnotready =0; ecomnotready <3; ecomnotready++) |
|
650 { |
|
651 TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray)); |
|
652 if (!ecomerror) |
|
653 { |
|
654 break; |
|
655 } |
|
656 else |
|
657 { |
|
658 ecomerror = 0; |
|
659 User::After(0); |
|
660 } |
|
661 } |
|
662 |
|
663 const TInt availCount = implementationArray.Count(); |
|
664 for (TInt count=0;count<availCount;++count) |
|
665 { |
|
666 const CImplementationInformation* info = implementationArray[count]; |
|
667 TUid rasterizerUid = info->ImplementationUid(); |
|
668 // Create a rasterizer |
|
669 COpenFontRasterizer* rasterizer=0; |
|
670 TRAP(error,rasterizer = COpenFontRasterizer::NewL(rasterizerUid)); |
|
671 if (!error) |
|
672 { |
|
673 // Install it in the font store. |
|
674 TRAP(error,aFontStore->InstallRasterizerL(rasterizer)); |
|
675 if (error) |
|
676 { |
|
677 RDebug::Printf("tfonttableandglyph: failed to load rasterizer."); |
|
678 delete rasterizer; |
|
679 } |
|
680 } |
|
681 } |
|
682 |
|
683 implementationArray.ResetAndDestroy(); |
|
684 } |
|
685 |
|
686 /** |
|
687 Worker function that implements the threads executed by SMPAndWDPSafeTest. |
|
688 @leave If a leave occurs, either the test failed to be set-up successfully, |
|
689 or the test itself failed. |
|
690 */ |
|
691 static void DoSMPAndWDPSafeTestFunL() |
|
692 { |
|
693 User::LeaveIfError(RFbsSession::Connect()); |
|
694 CFbsBitmap* bmp = new (ELeave) CFbsBitmap; |
|
695 CleanupStack::PushL(bmp); |
|
696 User::LeaveIfError(bmp->Create(TSize(100,100), EGray2)); |
|
697 CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL(bmp); |
|
698 CleanupStack::PushL(bmpDevice); |
|
699 CFont* font = NULL; |
|
700 TFontSpec fontSpec(KTestFontFaceName, KFontHeight); |
|
701 User::LeaveIfError(bmpDevice->GetNearestFontToMaxHeightInTwips(font, fontSpec, 0)); |
|
702 |
|
703 for(TInt i = 0; i < 100; i++) |
|
704 { |
|
705 RFontTable fontTable; |
|
706 CleanupClosePushL(fontTable); |
|
707 User::LeaveIfError(fontTable.Open(*font, 0x68656164)); |
|
708 TUint32* ptr = (TUint32*)fontTable.TableContent(); |
|
709 if (!ptr) |
|
710 { |
|
711 User::Leave(KErrGeneral); |
|
712 } |
|
713 CleanupStack::PopAndDestroy(1); // fontTable; |
|
714 } |
|
715 bmpDevice->ReleaseFont(font); |
|
716 CleanupStack::PopAndDestroy(2); // bmpDevice, bmp |
|
717 RFbsSession::Disconnect(); |
|
718 } |
|
719 |
|
720 static TInt SMPAndWDPSafeTestFun(TAny* /*aParam*/) |
|
721 { |
|
722 CTrapCleanup* trapCleanup = CTrapCleanup::New(); |
|
723 if (!trapCleanup) |
|
724 { |
|
725 return KErrNoMemory; |
|
726 } |
|
727 TRAPD(err, DoSMPAndWDPSafeTestFunL()); |
|
728 delete trapCleanup; |
|
729 return err; |
|
730 } |
|
731 |
|
732 /** |
|
733 @SYMTestCaseID TI18N-GDI-CIT-4090 |
|
734 @SYMTestCaseDesc Test if the new code is SMP and WDP safe. |
|
735 @SYMTestActions Create two threads to access the new interfaces concurrently. |
|
736 @SYMTestExpectedResults The threads run to the end correctly. All the |
|
737 Open() operations succeed. |
|
738 */ |
|
739 void CTFontAndGlyph::SMPAndWDPSafeTest() |
|
740 { |
|
741 RThread thread1; |
|
742 RThread thread2; |
|
743 TThreadFunction fun(SMPAndWDPSafeTestFun); |
|
744 |
|
745 TInt ret1 = thread1.Create(_L("SMPAndWDPSafeThread1"), fun, 0x2000, 0x20000, 0x80000, iFontStore); |
|
746 TEST(KErrNone == ret1); |
|
747 TInt ret2 = thread2.Create(_L("SMPAndWDPSafeThread2"), fun, 0x2000, 0x20000, 0x80000, iFontStore); |
|
748 TEST(KErrNone == ret2); |
|
749 |
|
750 TRequestStatus status1; |
|
751 TRequestStatus status2; |
|
752 thread1.Logon(status1); |
|
753 thread2.Logon(status2); |
|
754 thread1.Resume(); |
|
755 thread2.Resume(); |
|
756 User::WaitForRequest(status1); |
|
757 User::WaitForRequest(status2); |
|
758 |
|
759 TEST(EExitKill == thread1.ExitType()); |
|
760 TEST(KErrNone == thread1.ExitReason()); |
|
761 TEST(EExitKill == thread2.ExitType()); |
|
762 TEST(KErrNone == thread2.ExitReason()); |
|
763 |
|
764 thread1.Close(); |
|
765 thread2.Close(); |
|
766 } |