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