--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/tfonttableandglyph.cpp Fri Apr 16 16:21:04 2010 +0300
@@ -0,0 +1,771 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <gdi.h>
+#include <fbs.h>
+#include <e32test.h>
+#include <e32property.h>
+#include <graphics/openfontconstants.h>
+#include <graphics/openfontrasterizer.h>
+#include <graphics/gdi/gdiplatapi.h>
+#include "fbsmessage.h"
+#include "tfonttableandglyph.h"
+
+//global variable
+_LIT16(KTestFontFile, "C:\\DejaVuSans.ttf");
+_LIT16(KTestFontFaceName, "DejaVu Sans");
+
+_LIT16(KTestFontFile2, "C:\\DejaVuSerif.ttf");
+_LIT16(KTestFontFaceName2, "DejaVu Serif");
+
+static void LoadOpenFontLibraries(CFontStore* aFontStore);
+
+LOCAL_C const TInt KFontHeight = 12;
+LOCAL_C const TInt KInvalidGlyphId = 0xffff;
+
+CTFontAndGlyph::CTFontAndGlyph(CTestStep* aStep) :
+ CTGraphicsBase(aStep),
+ iBmp(NULL),
+ iBmp2(NULL),
+ iDevice(NULL),
+ iDevice2(NULL),
+ iFont(NULL),
+ iFont2(NULL),
+ iFontStore(NULL),
+ iFontSpec(KTestFontFaceName, KFontHeight),
+ iFontSpec2(KTestFontFaceName2, KFontHeight)
+ {
+ // a null constructor
+ }
+
+CTFontAndGlyph::~CTFontAndGlyph()
+ {
+ CleanEnv();
+ }
+
+void CTFontAndGlyph::RunTestCaseL(TInt aCurTestCase)
+ {
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+
+ switch(aCurTestCase)
+ {
+ case 1:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4079"));
+ INFO_PRINTF1(_L("GetHintedGlyphById"));
+ GetHintedGlyphById();
+ break;
+
+ case 2:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4080"));
+ INFO_PRINTF1(_L("GetUnHintedGlyphById"));
+ GetUnHintedGlyphById();
+ break;
+
+ case 3:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4081"));
+ INFO_PRINTF1(_L("GetHintedGlyphByWrongId"));
+ GetHintedGlyphByWrongId();
+ break;
+
+ case 4:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4082"));
+ INFO_PRINTF1(_L("GetGlyphWithNoMem"));
+ GetGlyphWithNoMem();
+ break;
+
+ case 5:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4083"));
+ INFO_PRINTF1(_L("GetFontTable"));
+ GetFontTable();
+ break;
+
+
+ case 6:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4084"));
+ INFO_PRINTF1(_L("GetFontTableByWrongTag"));
+ GetFontTableByWrongTag();
+ break;
+
+ case 7:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4085"));
+ INFO_PRINTF1(_L("GetFontTableWithNoMem"));
+ GetFontTableWithNoMem();
+ break;
+
+ case 8:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4089"));
+ INFO_PRINTF1(_L("GlyphOutlineIteratorPanics"));
+ GlyphOutlineIteratorPanics();
+ break;
+
+ case 9:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4090"));
+ INFO_PRINTF1(_L("WDPAndSMPSafeTest"));
+ SMPAndWDPSafeTest();
+ break;
+
+ case 10:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4087"));
+ INFO_PRINTF1(_L("TestFbsFontHandleIsZeroForFont"));
+ TestFbsFontHandleIsZeroForFont();
+ break;
+
+ case 11:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(_L("TI18N-GDI-CIT-4088"));
+ INFO_PRINTF1(_L("TestFbsFontHandleIsZeroForGlyph"));
+ TestFbsFontHandleIsZeroForGlyph();
+ break;
+
+ case 12:
+ ((CTFontAndGlyphStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+ ((CTFontAndGlyphStep*)iStep)->CloseTMSGraphicsStep();
+ TestComplete();
+ break;
+ default:
+ INFO_PRINTF1(_L("Invalid test case id found."));
+ }
+ ((CTFontAndGlyphStep*)iStep)->RecordTestResultL();
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4083
+ @SYMTestCaseDesc Get font table.
+ @SYMTestActions Get font table using the new RFontTable class and test
+ the return value.
+ @SYMTestExpectedResults Open() returns KErrNone. TableContent returns the
+ table content.
+*/
+void CTFontAndGlyph::GetFontTable()
+ {
+ __UHEAP_MARK;
+ RFontTable fontTable;
+ TInt err = fontTable.Open(*iFont, 0x68656164);
+ TEST(err == KErrNone);
+ TUint32* tablePtr = (TUint32*)fontTable.TableContent();
+ TEST(tablePtr != NULL);
+ TEST(tablePtr[3] == 0xF53C0F5F); //magic number is correct
+ RFontTable fontTableInCache;
+ err = fontTableInCache.Open(*iFont, 0x68656164);
+ TEST(err == KErrNone);
+ TUint32* tablePtr2 = (TUint32*)fontTableInCache.TableContent();
+ TEST(tablePtr2[3] == 0xF53C0F5F);
+ TEST(tablePtr == tablePtr2);
+
+ RFontTable fontTable2;
+ err = fontTable2.Open(*iFont2, 0x68656164);
+ TEST(err == KErrNone);
+ tablePtr = (TUint32*)fontTable2.TableContent();
+ TEST(tablePtr != NULL);
+ TEST(tablePtr[3] == 0xF53C0F5F); //magic number is correct
+ RFontTable fontTableInCache2;
+ err = fontTableInCache2.Open(*iFont2, 0x68656164);
+ TEST(err == KErrNone);
+ tablePtr2 = (TUint32*)fontTableInCache2.TableContent();
+ TEST(tablePtr2[3] == 0xF53C0F5F);
+ TEST(tablePtr == tablePtr2);
+
+ fontTableInCache.Close();
+ fontTable.Close();
+ fontTableInCache2.Close();
+ fontTable2.Close();
+ __UHEAP_MARKEND;
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4084
+ @SYMTestCaseDesc Get font table, providing an invalid tag.
+ @SYMTestActions Get font table, providing an invalid tag (0).
+ Test the return value.
+ @SYMTestExpectedResults Open() returns KErrNotFound.
+*/
+void CTFontAndGlyph::GetFontTableByWrongTag()
+ {
+ __UHEAP_MARK;
+ RFontTable fontTableForWrongID;
+ TInt err = fontTableForWrongID.Open(*iFont, 0);
+ fontTableForWrongID.Close();
+ TEST(KErrNotFound == err);
+ __UHEAP_MARKEND;
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4085
+ @SYMTestCaseDesc Get font table, when system is OOM.
+ @SYMTestActions Get font table, simulate OOM conditions using debug macros,
+ and test return value.
+ @SYMTestExpectedResults Open() returns KErrNoMemory. TableContent() and
+ TableLength() return NULL/0.
+*/
+void CTFontAndGlyph::GetFontTableWithNoMem()
+ {
+#ifdef _DEBUG
+ __UHEAP_MARK;
+ RFontTable aFontTableForMem;
+ RFbsSession *fbsSession = RFbsSession::GetSession();
+ fbsSession->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeHeapMemory, 1);
+ TInt err = aFontTableForMem.Open(*iFont, 0x68656164); /* 'head' in ascii (hex) */
+ TEST(KErrNoMemory == err);
+ TEST(0 == aFontTableForMem.TableLength());
+ TEST(0 == aFontTableForMem.TableContent());
+ aFontTableForMem.Close();
+ fbsSession->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeHeapMemory);
+ __UHEAP_MARKEND;
+#else
+ INFO_PRINTF1(_L("Skipping test GetFontTableWithNoMem in release mode"));
+#endif
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4082
+ @SYMTestCaseDesc Get glyph outline when system is out of memory.
+ @SYMTestActions Get glyph outline. Simulate OOM faliures using debug
+ macros to check if the program logic is correct.
+ @SYMTestExpectedResults Open() always returns KErrNoMemory.
+*/
+void CTFontAndGlyph::GetGlyphWithNoMem()
+ {
+#ifdef _DEBUG
+ __UHEAP_MARK;
+ RFbsSession *fbsSession = RFbsSession::GetSession();
+
+ TUint glyphIndex[] = {4, 4, KInvalidGlyphId};
+ __UHEAP_FAILNEXT(1);
+ RGlyphOutlineIterator it1;
+ TInt err = it1.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(err == KErrNoMemory);
+ it1.Close();
+
+ __UHEAP_FAILNEXT(2);
+ RGlyphOutlineIterator it2;
+ err = it2.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]));
+ TEST(err == KErrNoMemory);
+ TEST(KErrNotFound == it2.Next());
+ it2.Close();
+
+ __UHEAP_FAILNEXT(3);
+ RGlyphOutlineIterator it3;
+ err = it3.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(err == KErrNoMemory);
+ TEST(KErrNotFound == it2.Next());
+ it3.Close();
+
+ RGlyphOutlineIterator it4;
+ fbsSession = RFbsSession::GetSession();
+ fbsSession->SendCommand(EFbsMessSetHeapFail, RFbsSession::EHeapFailTypeServerMemory, 1);
+ err = it4.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]));
+ TEST(KErrNoMemory == err);
+ TEST(KErrNotFound == it2.Next());
+ fbsSession->SendCommand(EFbsMessSetHeapReset, RFbsSession::EHeapFailTypeServerMemory);
+ it4.Close();
+
+ __UHEAP_FAILNEXT(4);
+ RGlyphOutlineIterator it5;
+ err = it5.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]));
+ TEST(err == KErrNoMemory);
+ TEST(KErrNotFound == it2.Next());
+ it5.Close();
+ __UHEAP_MARKEND;
+#else
+ INFO_PRINTF1(_L("Skipping test GetGlyphWithNoMem in release mode"));
+#endif
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4079
+ @SYMTestCaseDesc Get hinted glyph outline
+ @SYMTestActions Get hinted glyph outline for glyph 4 and 65536.
+ Pass NULL for the 'aCodes' argument, and 0 for the 'aCount' to test
+ param validation. Check return values in each situation.
+ @SYMTestExpectedResults Open() returns KErrNone. Outline() returns a
+ valid pointer to the string representing the outline. OutlineLength() returns
+ the corresponding string length.
+*/
+void CTFontAndGlyph::GetHintedGlyphById()
+ {
+ __UHEAP_MARK;
+ RGlyphOutlineIterator glyphIterator1;
+ TUint glyphIndex[] = {4, 4, KInvalidGlyphId}; //two 4 to ensure the 2nd glyph is in cache.
+ TInt err = glyphIterator1.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(err == KErrNone);
+ TInt len1 = glyphIterator1.OutlineLength();
+ const TUint8* ptr1 = glyphIterator1.Outline();
+ TInt end = glyphIterator1.Next();
+ const TUint8* ptr2 = glyphIterator1.Outline();
+ TInt len2= glyphIterator1.OutlineLength();
+ TEST(len1 > 0);
+ TEST(ptr1 != NULL);
+ TEST(ptr1 == ptr2);
+ TEST(len1 == len2);
+
+ RGlyphOutlineIterator glyphIterator1b; // for font file 2
+ TUint glyphIndex_2[] = {0x41, 0x41, KInvalidGlyphId};
+ err = glyphIterator1b.Open(*iFont2, glyphIndex_2,
+ sizeof(glyphIndex_2)/sizeof(glyphIndex_2[0]), ETrue);
+ TEST(err == KErrNone);
+ len1 = glyphIterator1b.OutlineLength();
+ ptr1 = glyphIterator1b.Outline();
+ end = glyphIterator1b.Next();
+ ptr2 = glyphIterator1b.Outline();
+ len2= glyphIterator1b.OutlineLength();
+ TEST(len1 > 0);
+ TEST(ptr1 != NULL);
+ TEST(ptr1 == ptr2);
+ TEST(len1 == len2);
+
+ end = glyphIterator1.Next();
+ len1 = glyphIterator1.OutlineLength();
+ ptr1 = glyphIterator1.Outline();
+ // for the invalid glyph id, len1<0 indicates an error.
+ TEST(NULL == ptr1);
+ TEST(len1 < 0);
+ end = glyphIterator1.Next();
+ TEST(KErrNotFound == end);
+ // calling Outline() or OutlineLength() causes panic if Next()
+ // returns KErrNotFound
+ glyphIterator1.Close();
+
+ end = glyphIterator1b.Next();
+ len1 = glyphIterator1b.OutlineLength();
+ ptr1 = glyphIterator1b.Outline();
+ // for the invalid glyph id, len1<0 indicates an error.
+ TEST(NULL == ptr1);
+ TEST(len1 < 0);
+ end = glyphIterator1b.Next();
+ TEST(KErrNotFound == end);
+ // calling Outline() or OutlineLength() causes panic if Next()
+ // returns KErrNotFound
+ glyphIterator1b.Close();
+
+ RGlyphOutlineIterator glyphIterator3;
+ err = glyphIterator3.Open(*iFont, glyphIndex, 0, ETrue);
+ TEST(KErrArgument == err);
+ TEST(KErrNotFound == glyphIterator3.Next());
+ glyphIterator3.Close();
+
+ RGlyphOutlineIterator glyphIterator4;
+ err = glyphIterator4.Open(*iFont, NULL, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(KErrArgument == err);
+ TEST(KErrNotFound == glyphIterator4.Next());
+ glyphIterator4.Close();
+ __UHEAP_MARKEND;
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4081
+ @SYMTestCaseDesc Get hinted glyph outline, passing in invalid IDs.
+ @SYMTestActions Get hinted glyph outline, passing in invalid IDs. Check
+ the return values.
+ @SYMTestExpectedResults Open() returns KErrNone. Outline() returns NULL.
+ OutlineLength() returns KErrGeneral.
+*/
+void CTFontAndGlyph::GetHintedGlyphByWrongId()
+ {
+ __UHEAP_MARK;
+ RGlyphOutlineIterator glyphIterator;
+ TUint glyphIndex[] = {KInvalidGlyphId, KInvalidGlyphId};
+ TInt err = glyphIterator.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(err == KErrNone);
+ const TUint8* ptr = glyphIterator.Outline();
+ TInt len = glyphIterator.OutlineLength();
+ TEST(KErrGeneral == len);
+ TEST(ptr == NULL);
+ TInt ret = glyphIterator.Next();
+ TEST(KErrNone == ret);
+ glyphIterator.Close();
+ __UHEAP_MARKEND;
+ }
+
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4080
+ @SYMTestCaseDesc Get unhinted glyph outline
+ @SYMTestActions Get unhinted glyph outline for glyph 4 and 5.
+ @SYMTestExpectedResults Open() returns KErrNone. Outline() and
+ OutlineLength() returns the outline string and corresponding length.
+*/
+void CTFontAndGlyph::GetUnHintedGlyphById()
+ {
+ __UHEAP_MARK;
+ RGlyphOutlineIterator glyphIterator2;
+ TUint glyphIndex[] = {4, 4, 5}; //two '4' to ensure the 2nd is in cache.
+ TInt err = glyphIterator2.Open(*iFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), EFalse);
+ TEST(err == KErrNone);
+ const TUint8* ptr1 = glyphIterator2.Outline();
+ TInt len1 = glyphIterator2.OutlineLength();
+ err = glyphIterator2.Next();
+ TEST(err == KErrNone);
+ const TUint8* ptr2 = glyphIterator2.Outline();
+ TInt len2= glyphIterator2.OutlineLength();
+ err = glyphIterator2.Next();
+ TEST(err == KErrNone);
+ TEST(len1 > 0);
+ TEST(ptr1 == ptr2);
+ TEST(ptr1 != NULL);
+ TEST(len1 == len2);
+
+ RGlyphOutlineIterator glyphIterator2b; // for the 2nd font file
+ TUint glyphIndex2[] = {0x41, 0x41, 0x42};
+ err = glyphIterator2b.Open(*iFont2, glyphIndex2,
+ sizeof(glyphIndex2)/sizeof(glyphIndex2[0]), EFalse);
+ TEST(err == KErrNone);
+ ptr1 = glyphIterator2b.Outline();
+ len1 = glyphIterator2b.OutlineLength();
+ err = glyphIterator2b.Next();
+ TEST(err == KErrNone);
+ ptr2 = glyphIterator2b.Outline();
+ len2= glyphIterator2b.OutlineLength();
+ err = glyphIterator2b.Next();
+ TEST(err == KErrNone);
+ TEST(len1 > 0);
+ TEST(ptr1 == ptr2);
+ TEST(ptr1 != NULL);
+ TEST(len1 == len2);
+
+ glyphIterator2.Close();
+ glyphIterator2b.Close();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4087
+ @SYMTestCaseDesc Pass invalid font handle to FBS when getting font table.
+ @SYMTestActions Pass invalid font handle to FBS when getting font table.
+ And check the return value.
+ @SYMTestExpectedResults Open returns KErrNotFound.
+*/
+void CTFontAndGlyph::TestFbsFontHandleIsZeroForFont()
+ {
+ __UHEAP_MARK;
+ CFbsTestForFont* fbsFont = reinterpret_cast<CFbsTestForFont*> (iFont);
+ TEST(NULL != fbsFont);
+ fbsFont->SetHandle(0);
+ TInt handle = fbsFont->Handle();
+ CFbsTestForFont tempFsbFont;
+ tempFsbFont.Duplicate(handle);
+ tempFsbFont.SetHandle(0);
+ RFontTable ft1;
+ TInt err = ft1.Open(tempFsbFont, 0x11667730);
+ TEST(err == KErrNotFound);
+ ft1.Close();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4088
+ @SYMTestCaseDesc Pass invalid font handle to FBS when getting glyph outline.
+ @SYMTestActions Pass invalid font handle to FBS when getting glyph outline.
+ And check the return value.
+ @SYMTestExpectedResults Open() returns KErrNotFound.
+*/
+void CTFontAndGlyph::TestFbsFontHandleIsZeroForGlyph()
+ {
+ __UHEAP_MARK;
+ CFbsTestForFont* fbsFont = reinterpret_cast<CFbsTestForFont*> (iFont);
+ TEST(NULL != fbsFont);
+ TInt handle = fbsFont->Handle();
+ CFbsTestForFont tempFsbFont;
+ tempFsbFont.Duplicate(handle);
+ tempFsbFont.SetHandle(0);
+ RGlyphOutlineIterator glyphIterator1;
+ TUint glyphIndex[] = {1, 1, KInvalidGlyphId};
+ TInt err = glyphIterator1.Open(tempFsbFont, glyphIndex, sizeof(glyphIndex)/sizeof(glyphIndex[0]), ETrue);
+ TEST(err == KErrNotFound);
+ glyphIterator1.Close();
+ __UHEAP_MARKEND;
+ }
+
+static TInt OutlinePanicThread(TAny* /* ptr */)
+ {
+ CTrapCleanup* trapCleanup=CTrapCleanup::New();
+ RGlyphOutlineIterator it;
+ it.Outline();
+ delete trapCleanup;
+ return 0;
+ }
+
+static TInt OutlineLengthPanicThread(TAny* /* ptr */)
+ {
+ CTrapCleanup* trapCleanup=CTrapCleanup::New();
+ RGlyphOutlineIterator it;
+ it.OutlineLength();
+ delete trapCleanup;
+ return 0;
+ }
+
+void CTFontAndGlyph::OutlinePanics(TInt (*aThreadFun)(TAny*))
+ {
+ __UHEAP_MARK;
+ RThread thread;
+ TThreadFunction fun(aThreadFun);
+ TAny* ptr = NULL;
+ thread.Create(_L("RGlyphOutlineIterator"), fun, 0x1000, 0x20000, 0x20000, ptr);
+
+ TRequestStatus status;
+ thread.Logon(status);
+ thread.Resume();
+ User::WaitForRequest(status);
+
+ TInt err = thread.ExitReason();
+ TEST(err == 0);
+ TExitCategoryName name = thread.ExitCategory();
+ TEST(name == _L("GDI"));
+ thread.Close();
+ __UHEAP_MARKEND;
+ }
+
+
+void CTFontAndGlyph::OutlineLengthPanics(TInt (*aThreadFun)(TAny*))
+ {
+ __UHEAP_MARK;
+ RThread thread;
+ TThreadFunction fun(aThreadFun);
+ TAny* ptr = NULL;
+ thread.Create(_L("RGlyphOutlineLengthIterator"), fun, 0x1000, 0x20000, 0x20000, ptr);
+
+ TRequestStatus status;
+ thread.Logon(status);
+ thread.Resume();
+ User::WaitForRequest(status);
+
+ TInt err = thread.ExitReason();
+ TEST(err == 0);
+ TExitCategoryName name = thread.ExitCategory();
+ TEST(name == _L("GDI"));
+ thread.Close();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4089
+ @SYMTestCaseDesc Try to get glyph outline's length and content when
+ the glyph is not found in font file.
+ @SYMTestActions Try to get glyph outline's length and content when
+ the glyph is not found in font file. This should cause a client panic.
+ @SYMTestExpectedResults Both cases exit with ExitCategory 'GDI' and
+ reason code 0.
+*/
+void CTFontAndGlyph::GlyphOutlineIteratorPanics()
+ {
+ __UHEAP_MARK;
+ OutlinePanics(OutlinePanicThread);
+ OutlineLengthPanics(OutlineLengthPanicThread);
+ __UHEAP_MARKEND;
+ }
+
+void CTFontAndGlyph::ConstructL()
+ {
+ INFO_PRINTF1(_L("Calling CTFontAndGlyph::ConstructL()"));
+ iFontStore = CFontStore::NewL(&User::Heap());
+ LoadOpenFontLibraries(iFontStore);
+ iFontStore->iKPixelWidthInTwips = 11860;
+ iBmp = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iBmp->Create(TSize(100,100),EGray2));
+ iDevice = CFbsBitmapDevice::NewL(iBmp);
+ iUid = iFontStore->AddFileL(KTestFontFile);
+ TInt err = iDevice->GetNearestFontToMaxHeightInTwips(iFont,iFontSpec,0);
+ if (KErrNone != err)
+ {
+ iFontStore->RemoveFile(iUid);
+ User::Leave(err);
+ }
+
+ iBmp2 = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iBmp2->Create(TSize(100,100),EGray2));
+ iDevice2 = CFbsBitmapDevice::NewL(iBmp2);
+ iUid2 = iFontStore->AddFileL(KTestFontFile2);
+ err = iDevice2->GetNearestFontToMaxHeightInTwips(iFont2,iFontSpec2,0);
+ if (KErrNone != err)
+ {
+ iFontStore->RemoveFile(iUid);
+ iFontStore->RemoveFile(iUid2);
+ User::Leave(err);
+ }
+ }
+
+void CTFontAndGlyph::CleanEnv()
+ {
+ iDevice->ReleaseFont(iFont);
+ delete iDevice;
+ delete iBmp;
+ iFontStore->RemoveFile(iUid);
+
+ iDevice2->ReleaseFont(iFont2);
+ delete iDevice2;
+ delete iBmp2;
+ iFontStore->RemoveFile(iUid2);
+
+ delete iFontStore;
+ iDevice = NULL;
+ iBmp = NULL;
+ iFontStore = NULL;
+
+ iDevice2 = NULL;
+ iBmp2 = NULL;
+
+ REComSession::FinalClose();
+ }
+
+//--------------
+CTFontAndGlyphStep::CTFontAndGlyphStep()
+ {
+ SetTestStepName(KTFontTableAndGlyphStep);
+ }
+
+CTGraphicsBase* CTFontAndGlyphStep::CreateTestL()
+ {
+ return new (ELeave) CTFontAndGlyph(this);
+ }
+
+static void LoadOpenFontLibraries(CFontStore* aFontStore)
+ {
+
+ RImplInfoPtrArray implementationArray;
+ TInt error;
+ TInt ecomerror;
+ TInt ecomnotready;
+ TUid uid = {KUidOpenFontRasterizerPlunginInterface};
+
+ // Making sure that no race situation arises
+ // If ECom is not ready, give it another chance and try again. if it still doesn't work
+ // after the third try, then it just carries on quietly and fails...
+ for (ecomnotready =0; ecomnotready <3; ecomnotready++)
+ {
+ TRAP(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
+ if (!ecomerror)
+ {
+ break;
+ }
+ else
+ {
+ ecomerror = 0;
+ User::After(0);
+ }
+ }
+
+ const TInt availCount = implementationArray.Count();
+ for (TInt count=0;count<availCount;++count)
+ {
+ const CImplementationInformation* info = implementationArray[count];
+ TUid rasterizerUid = info->ImplementationUid();
+ // Create a rasterizer
+ COpenFontRasterizer* rasterizer=0;
+ TRAP(error,rasterizer = COpenFontRasterizer::NewL(rasterizerUid));
+ if (!error)
+ {
+ // Install it in the font store.
+ TRAP(error,aFontStore->InstallRasterizerL(rasterizer));
+ if (error)
+ {
+ RDebug::Printf("tfonttableandglyph: failed to load rasterizer.");
+ delete rasterizer;
+ }
+ }
+ }
+
+ implementationArray.ResetAndDestroy();
+ }
+
+static TInt SMPAndWDPSafeTestFun(TAny* /*aParam*/)
+ {
+ CFbsBitmapDevice* device1 = NULL;
+ CFont* font;
+ TInt err = 0;
+ CTrapCleanup* trapCleanup=CTrapCleanup::New();
+
+ err = RFbsSession::Connect();
+ if(err != KErrNone)
+ User::Panic(_L("FbsSession connection error"), -1);
+
+ CFbsBitmap* bmp = NULL;
+ TRAPD(ret1, bmp = new (ELeave) CFbsBitmap);
+ if (bmp == NULL)
+ User::Panic(_L("new CFbsBitmap error"), -1);
+ err = bmp->Create(TSize(100,100),EGray2);
+ if(err != KErrNone)
+ User::Panic(_L("bitmap creation error"), -1);
+ TRAP(err,device1 = CFbsBitmapDevice::NewL(bmp));
+ if(err != KErrNone)
+ User::Panic(_L("fbs device new error"), -1);
+ TFontSpec fontSpec(KTestFontFaceName,KFontHeight);
+ err = device1->GetNearestFontToMaxHeightInTwips(font,fontSpec,0);
+ if(err != KErrNone)
+ User::Panic(_L("Get CFont error"), -1);
+
+ err = KErrNone;
+ for(TInt i = 0; i < 100; i++)
+ {
+ RFontTable fontTable;
+ err = fontTable.Open(*font, 0x68656164);
+ if (KErrNone != err)
+ {
+ User::Panic(_L("Font table opening failed with error"), err);
+ }
+ TUint32* ptr = (TUint32*)fontTable.TableContent();
+ if (ptr == NULL)
+ {
+ User::Panic(_L("Font table content NULL"), -1);
+ }
+ fontTable.Close();
+ }
+
+ delete device1;
+ delete bmp;
+ delete trapCleanup;
+ device1 = NULL;
+ bmp = NULL;
+ return err;
+ }
+
+/**
+ @SYMTestCaseID TI18N-GDI-CIT-4090
+ @SYMTestCaseDesc Test if the new code is SMP and WDP safe.
+ @SYMTestActions Create two threads to access the new interfaces concurrently.
+ @SYMTestExpectedResults The threads run to the end correctly. All the
+ Open() operations succeed.
+*/
+void CTFontAndGlyph::SMPAndWDPSafeTest()
+ {
+ RThread thread1;
+ RThread thread2;
+ TThreadFunction fun(SMPAndWDPSafeTestFun);
+
+ TInt ret1 = thread1.Create(_L("SMPAndWDPSafeThread1"), fun, 0x2000, 0x20000, 0x80000, iFontStore);
+ TEST(KErrNone == ret1);
+ TInt ret2 = thread2.Create(_L("SMPAndWDPSafeThread2"), fun, 0x2000, 0x20000, 0x80000, iFontStore);
+ TEST(KErrNone == ret2);
+
+ TRequestStatus status1;
+ TRequestStatus status2;
+ thread1.Logon(status1);
+ thread2.Logon(status2);
+ thread1.Resume();
+ thread2.Resume();
+ User::WaitForRequest(status1);
+ User::WaitForRequest(status2);
+
+ TEST(EExitKill == thread1.ExitType());
+ TEST(KErrNone == thread1.ExitReason());
+ TEST(EExitKill == thread2.ExitType());
+ TEST(KErrNone == thread2.ExitReason());
+
+ thread1.Close();
+ thread2.Close();
+ }