os/graphics/fbs/fontandbitmapserver/tfbs/tfonttableandglyph.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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     }