--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/tfbs/TFBS.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2501 @@
+// Copyright (c) 1995-2009 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:
+//
+
+/**
+ @file
+ @internalComponent - Internal Symbian test code
+*/
+
+#include "TFBS.H"
+#include "../sfbs/UTILS.H"
+#include "../sfbs/fbshelper.h"
+#include <shapeinfo.h>
+#include <graphics/openfontrasterizer.h>
+#include <graphics/openfontconstants.h>
+#include "fbsdefs.h"
+#include "fbsmessage.h"
+
+TInt buffer[2];
+
+_LIT(KFBSERVFontFileDir, "\\resource\\fonts\\");
+_LIT(KTypefaceName, "DejaVu Sans Condensed");
+
+// TLS Handle for TestFlushCallback test, from tfbsserver.mmp
+const TInt KTlsHandle = 0x10273364;
+
+
+#ifdef __WINS__
+template<class C> XTCallCounter<C>::XTCallCounter(CTGraphicsBase& aTestBase)
+ : iTestBase(aTestBase), iVFCallsOutsideFBServ(0)
+ {}
+
+template<class C> void XTCallCounter<C>::ExecuteShellcode(TInt aFromFunction)
+ {
+ const TUint32 KFBServId = 0x10003A16;
+ const TUint32 KTFbsServerId = 0x10273364;
+ TSecureId id = RProcess().SecureId();
+ if (id != KFBServId)
+ {
+ User::LockedInc(iVFCallsOutsideFBServ);
+ if (id == KTFbsServerId)
+ {
+ TBuf<128> name;
+ XVtableInjector<C>::GetVirtualFunctionName(aFromFunction, name);
+ iTestBase.INFO_PRINTF2(_L("Virtual function call to %S from outside FBServ"), &name);
+ }
+ }
+ }
+#endif
+
+
+void CTFbs::DeleteScanLineBuffer()
+ {
+ delete iFbs->iScanLineBuffer;
+ iFbs->iScanLineBuffer = 0;
+ };
+
+CTFbs::CTFbs(CTestStep* aStep):
+ CTGraphicsBase(aStep),
+ iHandle(0),
+ iFbs(NULL),
+ iTs(NULL),
+ iHeap(NULL),
+ iFs(NULL),
+ iResourceCount(0),
+ iAllocs(0)
+#ifdef __WINS__
+ , iFontCallCounter(*this), iOpenFontCallCounter(*this)
+#endif
+ {
+ }
+
+void CTFbs::ConstructL()
+ {
+ ExpandCleanupStackL();
+
+ TestConstruction();
+ AllocScanLineBuf();
+
+ INFO_PRINTF1(_L("FBSERV testing"));
+ }
+
+CTFbs::~CTFbs()
+ {
+ delete iTs;
+ }
+
+void CTFbs::RunTestCaseL(TInt aCurTestCase)
+ {
+ ((CTFbsStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
+ switch(aCurTestCase)
+ {
+ case 1:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0555"));
+ TestConnection();
+ break;
+ case 2:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0558"));
+ TestInvalidFiles();
+ break;
+ case 3:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0556"));
+ TestFlushCallBack();
+ break;
+ case 4:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0568"));
+ TestMultiThread();
+ break;
+ case 5:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0559"));
+ TestGetFont();
+ break;
+ case 6:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0560"));
+ TestFontStore();
+ break;
+ case 7:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-PREQ807_1_Load_all_fonts-0001"));
+ TestAllFontsLoaded();
+ break;
+ case 8:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0561"));
+ TestFontNameAlias();
+ break;
+ case 9:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0557"));
+ TestAddFontFile();
+ break;
+ case 10:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0562"));
+ TestBufferedFont();
+ break;
+ case 11:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0563"));
+ TestMultipleFont();
+ break;
+ case 12:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0564"));
+ TestCreateBitmap();
+ break;
+ case 13:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0565"));
+ TestLoadBitmap();
+ break;
+ case 14:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0566"));
+ TestQueryBitmap();
+ TRAPD(errCode, TestRomBitmapL());
+ if(errCode==KErrNone)
+ {
+ TestHeapCompression();
+ }
+ break;
+ case 15:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0570"));
+ TestDefaultLanguageForMetrics();
+ break;
+ case 16:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-CTFbs-TestDuplicateFontFileEntries-0001"));
+ TestDuplicateFontFileEntries();
+ break;
+ //COMMENTED OUT FOR NOW BECAUSE DEF084095 FIX MAKES THIS TEST REDUNDANT
+ /*case 17:
+ TestShapeHeaderMemoryLeakAtClientDeath();
+ break;*/
+ case 17:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0506"));
+ TestBitmapHandleImmutable();
+ break;
+ case 18:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0507"));
+ TestBitmapBeginEnd();
+ break;
+ case 19:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0508"));
+ TestSingletonServer();
+ break;
+ case 21:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0620"));
+ TestFontSessionCacheLookupL();
+ break;
+ case 22:
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0650"));
+ TestInvalidHandlesInIpcCallsL();
+ break;
+ case 23:
+ // this one should always be the last test, since it checks the final virtual function call count
+ ((CTFbsStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0619"));
+ TestNoVFCallsToGlobalObjects();
+ break;
+ case 24:
+ ((CTFbsStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
+ ((CTFbsStep*)iStep)->CloseTMSGraphicsStep();
+ TestComplete();
+ break;
+ }
+ ((CTFbsStep*)iStep)->RecordTestResultL();
+ }
+
+CFbsFontEx* CTFbs::SelectFont()
+ {
+ CFbsFontEx* font=NULL;
+ TInt ret=iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
+ TEST(ret==KErrNone);
+#ifdef __WINS__
+ CBitmapFont* bitmapFont = font->Address();
+ iFontCallCounter.iInjector.InjectShellcode(bitmapFont, &iFontCallCounter);
+ if (bitmapFont->IsOpenFont())
+ {
+ iOpenFontCallCounter.iInjector.InjectShellcode(bitmapFont->OpenFont(), &iOpenFontCallCounter);
+ }
+#endif
+ TEST(font->MaxCharWidthInPixels()>0);
+ TEST(font->MaxNormalCharWidthInPixels()>0);
+ return(font);
+ }
+
+CFbsFontEx* CTFbs::SelectOpenTypeFont()
+ {
+ CFbsFontEx* font=NULL;
+ TFontSpec fsp;
+ fsp.iTypeface.iName=_L("Series 60 Sans");
+ fsp.iHeight=15;
+ TInt ret=iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font,fsp);
+ TEST(ret==KErrNone);
+#ifdef __WINS__
+ CBitmapFont* bitmapFont = font->Address();
+ iFontCallCounter.iInjector.InjectShellcode(bitmapFont, &iFontCallCounter);
+ if (bitmapFont->IsOpenFont())
+ {
+ iOpenFontCallCounter.iInjector.InjectShellcode(bitmapFont->OpenFont(), &iOpenFontCallCounter);
+ }
+#endif
+ TEST(font->MaxCharWidthInPixels()>0);
+ TEST(font->MaxNormalCharWidthInPixels()>0);
+ return(font);
+ }
+
+void CTFbs::TestConstruction()
+ {
+ CFbsBitmap bmp;
+ iTestBitmapName = KTestBitmapOnZ;
+ TInt ret=bmp.Load(iTestBitmapName,ETfbs,NULL);
+ if (ret != KErrNone)
+ User::Panic(_L("Could not load bitmap"),ret);
+ bmp.Reset();
+
+ iFbs = RFbsSession::GetSession();
+ TRAP(ret,iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL));
+ TEST(iTs != NULL);
+ CFbsFontEx* font = SelectFont();
+ iTs->ReleaseFont(font);
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0555
+
+ @SYMTestCaseDesc
+ Tests the connections to the FbsSession
+
+ @SYMTestActions
+ Allocates a 100 RFbsSession objects and
+ connects to the server and checks if
+ all connections succeeded. Frees the memory
+ and checks the heap memory.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestConnection()
+ {
+ INFO_PRINTF1(_L("class RFbsSession"));
+ __UHEAP_MARK;
+ const TInt numconnects=100;
+ RFbsSession* connections=(RFbsSession*)User::Alloc(sizeof(RFbsSession)*numconnects);
+ TEST(connections!=NULL);
+ TInt count=0;
+ for(;count<numconnects;count++)
+ new(&connections[count]) RFbsSession;
+ TEST(iFbs->ResourceCount()==0);
+ for(count=0;count<numconnects;count++)
+ {
+ TInt ret=connections[count].Connect();
+ if(ret!=KErrNone)
+ break;
+ }
+ INFO_PRINTF2(_L(" %d connections created.\n"),count);
+ TEST(iFbs->ResourceCount()==0);
+ for(TInt count2=0;count2<count;count2++)
+ connections[count2].Disconnect();
+ TEST(iFbs->ResourceCount()==0);
+ User::Free(connections);
+ User::Heap().Check();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0556
+
+ @SYMTestCaseDesc
+ Tests if the flush callback function
+ is called properly.
+
+ @SYMTestActions
+ Sets the flush callback, fills the cache with different
+ fonts until the cache is full.
+ Create one more font which forces an eviction of a font
+ in the cache.
+ Check call back is called.
+ Reset the flush callback, create another new font,
+ check that the callback was not called.
+ Check for memory and resource leaks.
+
+ @SYMTestExpectedResults
+ Callback function should be called once at end of loop.
+*/
+void CTFbs::TestFlushCallBack()
+ {
+ INFO_PRINTF1(_L("Test Flush CallBack"));
+
+ __UHEAP_MARK;
+ CFbsTypefaceStore* tfs=NULL;
+ TRAPD(ret,tfs=CFbsTypefaceStore::NewL(NULL));
+ TEST(ret==KErrNone);
+ TEST(tfs!=NULL);
+
+ UserSvr::DllSetTls(KTlsHandle, this);
+ INFO_PRINTF1(_L("Testing Flush CallBack mechanism..."));
+ iFbs->SetCallBack(TCallBack(FlushCallBack, NULL));
+ CFbsFontEx* font=NULL;
+
+ // Fill up the fontcache so that on the final iteration, the first
+ // font is evicted, thereby destroying it server-side and executing the
+ // callback.
+ iFlushCallbackReceived = EFalse;
+ TInt fontSize = 10;
+ for (TInt fontEntries = 0; fontEntries < KMaxFontCacheEntries+1; fontEntries++)
+ {
+ ret=tfs->GetNearestFontToDesignHeightInTwips((CFont*&)font, TFontSpec(KTypefaceName, fontSize));
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+ tfs->ReleaseFont(font);
+ fontSize += 15;
+ }
+ TEST(iFlushCallbackReceived);
+
+ // Now check callback is correctly reset and callback function is not executed
+ // when another font is evicted from the cache.
+ // Resource count wont increase as although a new font is being created, another
+ // will be evicted from the cache.
+ iFlushCallbackReceived = EFalse;
+ iFbs->ResetCallBack();
+ ret=tfs->GetNearestFontToDesignHeightInTwips((CFont*&)font, TFontSpec(KTypefaceName, fontSize));
+ TEST(ret==KErrNone);
+ tfs->ReleaseFont(font);
+ TEST(!iFlushCallbackReceived);
+ CheckResourceCount();
+
+ UserSvr::DllFreeTls(KTlsHandle);
+ delete tfs;
+ iResourceCount = 0;
+ CheckResourceCount();
+ __UHEAP_MARKEND;
+ }
+
+TInt CTFbs::FlushCallBack(TAny* /*aPtr*/)
+ {
+ CTFbs* tfbs = static_cast<CTFbs*>(UserSvr::DllTls(KTlsHandle));
+ tfbs->INFO_PRINTF1(_L(" ...Flush CallBack called successfully"));
+ tfbs->iFlushCallbackReceived = ETrue;
+ --tfbs->iResourceCount;
+ return(0);
+ }
+
+
+#ifdef __WINS__
+_LIT(KCTFbsTestFont,"z:\\resource\\fonts\\eon14.gdr");
+#else
+_LIT(KCTFbsTestFont,"z:\\resource\\fonts\\eon.gdr");
+#endif
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0557
+
+ @SYMTestCaseDesc
+ Tests adding of a font file
+ to the font store
+
+ @SYMTestActions
+ Creates a type face store and adds
+ font files to it. Checks if adding
+ the files succeeded. Removes the files
+ from the store. Checks if succeeded.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestAddFontFile()
+ {
+ INFO_PRINTF1(_L("Test Add File"));
+ __UHEAP_MARK;
+ CFbsTypefaceStore* tfs=NULL;
+ TRAPD(ret,tfs=CFbsTypefaceStore::NewL(NULL));
+ TEST(ret==KErrNone);
+ TEST(tfs!=NULL);
+ TInt id1=0;
+ TInt id2=0;
+ TInt id3=0;
+ TInt id4=0;
+ ret=tfs->AddFile(KCTFbsTestFont,id1);
+ TEST(ret==KErrNone);
+ TEST(id1!=0);
+ ret=tfs->AddFile(KCTFbsTestFont,id2);
+ TEST(ret==KErrNone);
+ TEST(id2==id1);
+ ret=tfs->AddFile(KCTFbsTestFont,id3);
+ TEST(ret==KErrNone);
+ TEST(id3==id2);
+ tfs->RemoveFile(id1);
+ tfs->RemoveFile(id2);
+ tfs->RemoveFile(id3);
+ ret=tfs->AddFile(KCTFbsTestFont,id4);
+ TEST(ret==KErrNone);
+ TEST(id4==id1);
+ tfs->RemoveFile(id4);
+ delete tfs;
+ __UHEAP_MARKEND;
+
+ //test the sequence AddFile, GetNearestFont, ReleaseFont, RemoveFile
+ CFbsTypefaceStore* tfs1=NULL;
+ TRAPD(ret1,tfs1=CFbsTypefaceStore::NewL(NULL));
+ TEST(ret1==KErrNone);
+ TEST(tfs1!=NULL);
+ TInt id5=0;
+ ret1=tfs1->AddFile(_L("z:\\resource\\fonts\\DejaVuSerifCondensed.ttf"),id5);
+ TEST(ret1==KErrNone);
+ TEST(id5!=0);
+
+ TInt id6=0;
+ ret1=tfs1->AddFile(_L("z:\\resource\\fonts\\DejaVuSansCondensed.ttf"), id6);
+ TEST(ret1==KErrNone);
+ TEST(id6!=0);
+
+ TFontSpec fsp1;
+ fsp1.iTypeface.iName=_L("DejaVu Serif Condensed");
+ fsp1.iHeight=15;
+ CFont* font1;
+ ret1=tfs1->GetNearestFontToDesignHeightInTwips((CFont*&)font1,fsp1);
+ TEST(ret1==KErrNone);
+
+ TFontSpec fsp2;
+ fsp2.iTypeface.iName=_L("DejaVu Serif Condensed");
+ fsp2.iHeight=30;
+ CFont *font2;
+ ret1=tfs1->GetNearestFontToDesignHeightInTwips((CFont*&)font2,fsp2);
+ TEST(ret1==KErrNone);
+
+ TFontSpec fsp3;
+ fsp3.iTypeface.iName=_L("DejaVu Sans Condensed");
+ fsp3.iHeight=20;
+ CFont *font3;
+ ret1=tfs1->GetNearestFontToDesignHeightInTwips((CFont*&)font3,fsp3);
+ TEST(ret1==KErrNone);
+
+ TFontSpec fsp4;
+ fsp4.iTypeface.iName=_L("DejaVu Serif Condensed");
+ fsp4.iHeight=35;
+ CFont *font4;
+ ret1=tfs1->GetNearestFontToDesignHeightInTwips((CFont*&)font4,fsp4);
+ TEST(ret1==KErrNone);
+
+ if (font1)
+ tfs1->ReleaseFont(font1);
+ if (font2)
+ tfs1->ReleaseFont(font2);
+ if (font4)
+ tfs1->ReleaseFont(font4);
+
+ if (id6)
+ tfs1->RemoveFile(id6);
+ if (id5)
+ tfs1->RemoveFile(id5);
+ delete tfs1;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0558
+
+ @SYMTestCaseDesc
+ Tries to add and load a nonexisting
+ file to the FbsTypeFaceStore and checks
+ if it fails.
+
+ @SYMTestActions
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestInvalidFiles()
+ {
+ INFO_PRINTF1(_L("Test Invalid Files"));
+ __UHEAP_MARK;
+ CFbsTypefaceStore* tfs=NULL;
+ TRAPD(ret,tfs=CFbsTypefaceStore::NewL(NULL));
+ TEST(ret==KErrNone);
+ TEST(tfs!=NULL);
+ TInt id=0;
+ ret=tfs->AddFile(_L("\\nonexist.gdr"),id);
+ TEST(ret!=KErrNone);
+ delete tfs;
+ CFbsBitmapEx bmp;
+ ret=bmp.Load(_L("\\nonexist.mbm"),0);
+ TEST(ret!=KErrNone);
+ User::Heap().Check();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0559
+
+ @SYMTestCaseDesc
+ Gets a font and tests all its properties.
+
+ @SYMTestActions
+ Tests the char width, text width, handles, verifies
+ the resource count and the heap for memory leaks
+ CharWidthInPixels() and TextWidthInPixels() may return
+ different values depending on the hardware used.
+ Therefore, when comparing these values for the same character,
+ allow a margin of 1 pixel difference.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestGetFont()
+ {
+ INFO_PRINTF1(_L("Test Get Font"));
+ CFbsFontEx* font=SelectFont();
+ iResourceCount++;
+ TEST(font->Handle()!=0);
+ CheckResourceCount();
+ TUid uid;
+ uid=KCFbsFontUid;
+ TEST(font->TypeUid()==uid);
+ TInt w=font->TextWidthInPixels(_L(" "));
+ TEST(w>0);
+ // Now test the same use case with context
+ CFont::TMeasureTextInput param;
+ param.iStartInputChar = 34;
+ TInt wContext=font->TextWidthInPixels(_L("->This text will not be measured<- "),¶m);
+ TEST(wContext==w);
+ // End of first use case with context
+
+ TInt x=font->TextCount(_L(" "),10);
+ TEST(10/w==x);
+ TInt y,z;
+ y=font->TextCount(_L(" "),10,z);
+ TEST(y==x);
+ TInt cwidth=font->CharWidthInPixels('i');
+ TInt twidth=font->TextWidthInPixels(_L("i"));
+ TInt charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ TInt twidthContext=font->TextWidthInPixels(_L("->This text will not be measured<-i"),¶m);
+ TEST(twidth==twidthContext);
+ cwidth=font->CharWidthInPixels('p');
+ twidth=font->TextWidthInPixels(_L("p"));
+ charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ twidthContext=font->TextWidthInPixels(_L("->This text will not be measured<-p"),¶m);
+ TEST(twidth==twidthContext);
+ cwidth=font->CharWidthInPixels('W');
+ twidth=font->TextWidthInPixels(_L("W"));
+ charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ twidthContext=font->TextWidthInPixels(_L("->This text will not be measured<-W"),¶m);
+ TEST(twidth==twidthContext);
+ cwidth=font->CharWidthInPixels(' ');
+ twidth=font->TextWidthInPixels(_L(" "));
+ charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ SCharWidth chwid;
+ font->TextWidthInPixels(_L(" "),chwid);
+ TEST(chwid.iMove==w);
+ TEST(chwid.iWidth+chwid.iLeftAdjust+chwid.iRightAdjust==chwid.iMove);
+ font->TextWidthInPixels(_L("->This text will not be measured<- "),¶m,chwid);
+ TEST(chwid.iMove==w);
+ TEST(chwid.iWidth+chwid.iLeftAdjust+chwid.iRightAdjust==chwid.iMove);
+
+ // Now do all these tests with an OpenType font where the width with context is different from the
+ // width without context
+ // NOTE: These tests are performed for WINS and WINSCW only because we are using a TrueType font, and the bounds of
+ // the text returned is different for different hardware devices, including different h4's and hence
+ // cannot be measured.
+ #if defined __WINS__ || defined __WINSCW__
+ CFbsFontEx* openFont = SelectOpenTypeFont();
+ iResourceCount++;
+ TEST(font->Handle()!=0);
+ CheckResourceCount();
+ uid=KCFbsFontUid;
+ TEST(font->TypeUid()==uid);
+ cwidth=openFont->CharWidthInPixels('.');
+ twidth=openFont->TextWidthInPixels(_L("."));
+ charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ param.iStartInputChar = 1;
+ twidthContext=openFont->TextWidthInPixels(_L("\x0915."),¶m);
+ TEST(twidth!=twidthContext);
+ cwidth=openFont->CharWidthInPixels(',');
+ twidth=openFont->TextWidthInPixels(_L(","));
+ charTextdiff = cwidth - twidth;
+ TEST(1>=charTextdiff && -1<=charTextdiff);
+ twidthContext=openFont->TextWidthInPixels(_L("\x0915,"),¶m);
+ TEST(cwidth!=twidthContext);
+ TEST(twidth!=twidthContext);
+ openFont->TextWidthInPixels(_L("\x0915."),¶m,chwid);
+ TEST(chwid.iMove!=cwidth);
+ #endif
+
+ CFbsFontEx* font2=SelectFont(); // Don't increment iResourceCount as the font is already in the cache
+ CheckResourceCount();
+ iTs->ReleaseFont(font2);
+ RFbsSession* fbsalt=RFbsSession::GetSession();
+ CFbsFontEx* font3=new CFbsFontEx;
+ font3->Duplicate(font->Handle());
+ iResourceCount++;
+ TEST(font3->Handle());
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+ iTs->ReleaseFont(font);
+ iResourceCount--;
+ TEST(w==font3->TextWidthInPixels(_L(" ")));
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+ font3->Reset();
+ User::Free(font3);
+ iResourceCount--;
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+ User::Heap().Check();
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0560
+
+ @SYMTestCaseDesc
+ Tests the font store.
+
+ @SYMTestActions
+ Allocates an array of pointers which is
+ used to store the font height. It tests
+ the font height and gets the nearest font
+ available. The heap is checked for
+ memory leaks.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestFontStore()
+ {
+ INFO_PRINTF1(_L("Test Font Store"));
+ CFbsFontEx* font=NULL;
+ TFontSpec fs;
+ TInt typefaces=iTs->NumTypefaces();
+ TTypefaceSupport info;
+ for(TInt count=0;count<typefaces;count++)
+ {
+ iTs->TypefaceSupport(info,count);
+ INFO_PRINTF1(_L(" "));
+ TBuf<KMaxTypefaceNameLength> tname;
+ tname.Copy(info.iTypeface.iName);
+ INFO_PRINTF1(tname);
+ INFO_PRINTF1(_L("\n"));
+ TInt* heightarray=(TInt*)User::Alloc(info.iNumHeights*sizeof(TInt));
+ TInt index=0;
+ for(;index<info.iNumHeights;index++)
+ heightarray[index]=iTs->FontHeightInTwips(count,index);
+ for(index=1;index<info.iNumHeights;index++)
+ TEST(heightarray[index]>heightarray[index-1]);
+ for(index=0;index<info.iNumHeights;index++)
+ heightarray[index]=iTs->FontHeightInPixels(count,index);
+ for(index=1;index<info.iNumHeights;index++)
+ TEST(heightarray[index]>=heightarray[index-1]);
+ delete [] heightarray;
+ for(index=0;index<info.iNumHeights;index++)
+ {
+ TInt height=iTs->FontHeightInTwips(count,index);
+ fs.iTypeface=info.iTypeface;
+ fs.iHeight=height;
+ TInt ret=iTs->GetNearestFontToDesignHeightInTwips((CFont*&)font,fs);
+ TEST(ret==KErrNone);
+ TEST(font->Handle());
+ iTs->ReleaseFont(font);
+
+ height=iTs->FontHeightInPixels(count,index);
+ fs.iTypeface=info.iTypeface;
+ fs.iHeight=height;
+ ret=iTs->GetNearestFontToDesignHeightInPixels((CFont*&)font,fs);
+ TEST(ret==KErrNone);
+ TEST(font->Handle());
+ iTs->ReleaseFont(font);
+ }
+ }
+ iResourceCount = iFbs->ResourceCount(); // Allow for fonts left in the typeface store cache
+ User::Heap().Check();
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0561
+
+ @SYMTestCaseDesc
+ Tests the font name alias
+
+ @SYMTestActions
+ Creates three different font name alias with a
+ mixture of caps and small letters. Checks the font
+ name aliases using the different names.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestFontNameAlias()
+ {
+ INFO_PRINTF1(_L("Test Font Name Alias"));
+
+ TInt size = 20;
+ _LIT(KFontAlias0,"Font alias 0");
+ _LIT(KFontAlias1,"Font alias 1");
+ _LIT(KFontAlias2,"FOnT AlIaS 0");//Alias name in mixture of caps & small letters for KFontAlias0
+
+ TBuf<KMaxTypefaceNameLength> defaultName;
+ TBuf<KMaxTypefaceNameLength> fontName[3];
+
+ CFbsFontEx* font = NULL;
+ TFontSpec fs(KNullDesC,200);
+ TInt ret = iTs->GetNearestFontToDesignHeightInTwips((CFont*&)font,fs);
+ TEST(ret == KErrNone);
+ TEST(font->Handle());
+ fs = font->FontSpecInTwips();
+ defaultName = fs.iTypeface.iName;
+ iTs->ReleaseFont(font);
+
+ TTypefaceSupport info;
+ for (TInt index = 0, nameIndex = 0; nameIndex < 3; index++)
+ {
+ iTs->TypefaceSupport(info,index);
+ if (info.iTypeface.iName != defaultName)
+ fontName[nameIndex++] = info.iTypeface.iName;
+ }
+
+ TRAP(ret,iTs->SetFontNameAliasL(KFontAlias0,fontName[0]));
+ TEST(ret == KErrNone);
+ CheckFontNameAlias(KFontAlias0,fontName[0],size);
+ //Testing if it works even if the alias name passed differs in case
+ CheckFontNameAlias(KFontAlias2,fontName[0],size);
+
+ TRAP(ret,iTs->SetFontNameAliasL(KFontAlias1,fontName[1]));
+ TEST(ret == KErrNone);
+ CheckFontNameAlias(KFontAlias0,fontName[0],size);
+ CheckFontNameAlias(KFontAlias1,fontName[1],size);
+
+ TRAP(ret,iTs->SetFontNameAliasL(KFontAlias0,fontName[2]));
+ TEST(ret == KErrNone);
+ CheckFontNameAlias(KFontAlias0,fontName[2],size);
+ CheckFontNameAlias(KFontAlias1,fontName[1],size);
+
+ TRAP(ret,iTs->SetFontNameAliasL(KFontAlias1,KNullDesC));
+ TEST(ret == KErrNone);
+ CheckFontNameAlias(KFontAlias0,fontName[2],size);
+ CheckFontNameAlias(KFontAlias1,defaultName,size);
+
+ TRAP(ret,iTs->SetFontNameAliasL(KFontAlias0,KNullDesC));
+ TEST(ret == KErrNone);
+ CheckFontNameAlias(KFontAlias0,defaultName,size);
+ CheckFontNameAlias(KFontAlias1,defaultName,size);
+ iResourceCount--; // Allow for a cache eviction because the last check fills the cache
+
+ CheckResourceCount();
+ User::Heap().Check();
+ }
+
+void CTFbs::CheckFontNameAlias(const TDesC& aFontAlias, const TDesC& aFontName, TInt& aSize)
+ {
+ CFbsFontEx* font = NULL;
+ TFontSpec fs(aFontAlias,aSize);
+ aSize += 20;
+
+ TInt ret = iTs->GetNearestFontToDesignHeightInTwips((CFont*&)font,fs);
+ TEST(ret == KErrNone);
+ TEST(font->Handle());
+
+ TFontSpec checkFS = font->FontSpecInTwips();
+ TEST(checkFS.iTypeface.iName == aFontName);
+
+ iTs->ReleaseFont(font);
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0562
+
+ @SYMTestCaseDesc
+ Tests the width of a font stored in a buffer
+
+ @SYMTestActions
+ Gets how much of the specified descriptor can be
+ displayed for a specified font without
+ exceeding the specified width.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestBufferedFont()
+ {
+ INFO_PRINTF1(_L("Test Buffered Font"));
+ CFbsFontEx* font=SelectFont();
+ TBuf<1280> largebuf;
+ TInt count=0;
+ for(;count<1280;count++)
+ largebuf.Append(32);
+ TInt width,lcount,rcount,lwidth,rwidth;
+ width=font->TextWidthInPixels(largebuf);
+ for(count=0;count<1280;count+=500)
+ {
+ lcount=font->TextCount(largebuf.Left(count),100000);
+ TEST(lcount==count);
+ rcount=font->TextCount(largebuf.Right(1280-count),100000);
+ TEST(rcount==1280-count);
+ lwidth=font->TextWidthInPixels(largebuf.Left(count));
+ rwidth=font->TextWidthInPixels(largebuf.Right(1280-count));
+ TEST(rwidth+lwidth==width);
+ }
+ iTs->ReleaseFont(font);
+ CheckResourceCount();
+ User::Heap().Check();
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0563
+
+ @SYMTestCaseDesc
+ Tests having multiple fonts allocated
+ and deallocated
+
+ @SYMTestActions
+ Gets multiple font. Releases the hold of a
+ typeface store client on a specified font.
+ Decrements the access-count for the specified
+ font by one. If this reduces the access-count
+ to zero then the font is no longer needed by any
+ client, and is deleted from the typeface store list.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestMultipleFont()
+ {
+ INFO_PRINTF1(_L("Test Multiple Font"));
+ const TInt numfonts=100;
+ CFbsFontEx* fonts[numfonts];
+ TInt count=0;
+ for(;count<numfonts;count++)
+ fonts[count]=SelectFont();
+ for(count=0;count<numfonts;count++)
+ iTs->ReleaseFont(fonts[count]);
+ INFO_PRINTF2(_L(" %d font handles created.\n"),numfonts);
+ CheckResourceCount();
+ User::Heap().Check();
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0564
+
+ @SYMTestCaseDesc
+ Tests creation of unique bitmaps with
+ no handles already to them. Also tests
+ and verifies defects DEF069571 and DEF076347.
+
+ @SYMDEF DEF069571 DEF076347
+
+ @SYMTestActions
+ Test creation of original bitmaps. Destroys
+ existing bitmap and creates a new one. Tests
+ creation of bitmap by duplicating an already
+ existing bitmap. Tests creation of different
+ sized bitmaps and resizes them.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestCreateBitmap()
+ {
+ INFO_PRINTF1(_L("Test Create Bitmap"));
+ __UHEAP_MARK;
+
+ CFbsBitmapEx bmp1;
+ CFbsBitmapEx bmp2;
+
+ // Test creation of original bitmaps (ie handles are unique)
+ TInt ret=bmp1.Create(TSize(0,0),EGray2);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+
+ ret=bmp2.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ TEST(bmp2.Handle()!=bmp1.Handle());
+ CheckResourceCount();
+
+ ret=bmp2.Create(TSize(0,0),EGray2); // Destroys existing and creates new
+ TEST(ret==KErrNone);
+ TEST(bmp2.Handle()!=bmp1.Handle());
+ CheckResourceCount();
+ bmp2.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+
+ // Test creation by duplication
+ RFbsSession* fbsalt=RFbsSession::GetSession();
+ CFbsBitmapEx bmp3;
+
+ ret=bmp3.Duplicate(bmp1.Handle());
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+ TEST((TInt)bmp1.BitmapAddress());
+ CBitwiseBitmap* bmp3add=bmp3.BitmapAddress();
+ CBitwiseBitmap* bmp1add=bmp1.BitmapAddress();
+ TEST(bmp3add==bmp1add);
+ TEST(bmp3.Handle()==bmp1.Handle());
+ bmp3.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+ bmp1.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+ TEST(fbsalt->ResourceCount()==iResourceCount);
+
+ //Testing the DEF069571
+
+ CFbsBitmapEx bmp0;
+ //Test creation of large bitmaps (>65536)
+ TInt ret0=bmp0.Create(TSize(65536,1),EGray256);
+ bmp0.Reset();
+
+ //Testcode for DEF076347
+ CFbsBitmapEx bmp01;
+ TInt ret01=bmp01.Create(TSize(65536,1),EColor16MU);
+ TInt ret02=bmp01.SetDisplayMode(EColor16MA);
+ bmp01.Reset();
+
+
+
+ // Test creation of different sizes and resizing them
+ DoResizeBitmap(EGray2);
+ DoResizeBitmap(EGray4);
+ DoResizeBitmap(EGray16);
+ DoResizeBitmap(EGray256);
+ DoResizeBitmap(EColor16);
+ DoResizeBitmap(EColor256);
+ DoResizeBitmap(EColor4K);
+ DoResizeBitmap(EColor64K);
+ DoResizeBitmap(EColor16M);
+
+ User::Heap().Check();
+ __UHEAP_MARKEND;
+ }
+
+void CTFbs::DoResizeBitmap(TDisplayMode aDispMode)
+ {
+ const TInt numNewSizes = 5;
+ const TSize newSizes[numNewSizes] = { TSize(0,0), TSize(1,1), TSize(17,20), TSize(32,32), TSize(32,1025) };
+ const TInt numTwipsSizes = 4;
+ const TSize twipsSizes[numTwipsSizes] = { TSize(100,100), TSize(1440,1440), TSize(1000000,1000000), TSize(0,0) };
+
+ __UHEAP_MARK;
+
+ CFbsBitmapEx bmp;
+
+ TInt count;
+ for(count = 0; count < numNewSizes; count++)
+ {
+ TSize size = newSizes[count];
+ TInt ret = bmp.Create(size,aDispMode);
+ TEST(ret == KErrNone);
+ TEST(bmp.Handle() != 0);
+ TEST(bmp.SizeInPixels() == size);
+ TEST(bmp.DisplayMode() == aDispMode);
+ }
+
+ for(count = 0; count < numNewSizes; count++)
+ {
+ TInt ret = bmp.Create(TSize(0,0),aDispMode);
+ TSize size = newSizes[count];
+ ret = bmp.Resize(size);
+ TEST(ret == KErrNone);
+ TEST(bmp.SizeInPixels() == size);
+ }
+
+ for(count = 0; count < numTwipsSizes; count++)
+ {
+ TSize size = twipsSizes[count];
+ bmp.SetSizeInTwips(size);
+ TEST(bmp.SizeInTwips() == size);
+ }
+
+ bmp.Reset();
+ CheckResourceCount();
+
+ User::Heap().Check();
+ DeleteScanLineBuffer();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0565
+
+ @SYMTestCaseDesc
+ Tests loading of bitmaps
+
+ @SYMTestActions
+ Loads a specific bitmap from a multi-bitmap
+ file. Retrieves the bitmap addresses for the
+ bitmap and check if they are valid.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestLoadBitmap()
+ {
+ INFO_PRINTF1(_L("Test Load Bitmap"));
+ __UHEAP_MARK;
+ CFbsBitmapEx bmp1;
+ CFbsBitmapEx bmp2;
+ CFbsBitmapEx bmp3;
+ CFbsBitmapEx bmp4;
+ CFbsBitmapEx bmp5;
+ TInt ret=bmp1.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ TEST(bmp1.Handle()!=0);
+ ret=bmp2.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CBitwiseBitmap* bmp1add=bmp1.BitmapAddress();
+ TEST((TInt)bmp1add);
+ CBitwiseBitmap* bmp2add=bmp2.BitmapAddress();
+ TEST(bmp1add==bmp2add);
+ TEST(bmp1.Handle()==bmp2.Handle());
+ ret=bmp3.Load(iTestBitmapName,ETblank);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ TEST(bmp1.Handle()!=bmp3.Handle());
+ bmp2.Reset();
+ iResourceCount--;
+ ret=bmp4.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CBitwiseBitmap* bmp4add=bmp4.BitmapAddress();
+ TEST(bmp1add==bmp4add);
+ TEST(bmp4.Handle()==bmp1.Handle());
+ ret=bmp5.Load(iTestBitmapName,ETblank);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CBitwiseBitmap* bmp3add=bmp3.BitmapAddress();
+ CBitwiseBitmap* bmp5add=bmp5.BitmapAddress();
+ TEST((TInt)bmp3add);
+ TEST(bmp3add==bmp5add);
+ TEST(bmp5.Handle()==bmp3.Handle());
+ CheckResourceCount();
+ bmp3.Reset();
+ iResourceCount--;
+ bmp4.Reset();
+ iResourceCount--;
+ bmp5.Reset();
+ iResourceCount--;
+ ret=bmp2.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ bmp2add=bmp2.BitmapAddress();
+ TEST(bmp1add==bmp2add);
+ TEST(bmp1.Handle()==bmp2.Handle());
+ CheckResourceCount();
+ bmp1.Reset();
+ iResourceCount--;
+ bmp2.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+
+ ret=bmp1.Load(iTestBitmapName,ETfbs,EFalse);
+ TEST(ret==KErrNone);
+ ret=bmp2.Load(iTestBitmapName,ETfbs,ETrue);
+ TEST(ret==KErrNone);
+ ret=bmp3.Load(iTestBitmapName,ETfbs,ETrue);
+ TEST(ret==KErrNone);
+ ret=bmp4.Load(iTestBitmapName,ETfbs,EFalse);
+ TEST(ret==KErrNone);
+ ret=bmp5.Load(iTestBitmapName,ETfbs,ETrue);
+ TEST(ret==KErrNone);
+ bmp1add=bmp1.BitmapAddress();
+ bmp2add=bmp2.BitmapAddress();
+ bmp3add=bmp3.BitmapAddress();
+ bmp4add=bmp4.BitmapAddress();
+ bmp5add=bmp5.BitmapAddress();
+ TEST(bmp1add!=bmp2add);
+ TEST(bmp1add!=bmp3add);
+ TEST(bmp1add!=bmp4add);
+ TEST(bmp1add!=bmp5add);
+ TEST(bmp2add==bmp3add);
+ TEST(bmp2add!=bmp4add);
+ TEST(bmp2add==bmp5add);
+ TEST(bmp3add!=bmp4add);
+ TEST(bmp3add==bmp5add);
+ TEST(bmp4add!=bmp5add);
+ bmp1.Reset();
+ bmp2.Reset();
+ bmp3.Reset();
+ bmp4.Reset();
+ bmp5.Reset();
+ User::Heap().Check();
+ DeleteScanLineBuffer();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0566
+
+ @SYMTestCaseDesc
+ Checks the properties of a created bitmap.
+
+ @SYMTestActions
+ Creates a bitmap. Checks the resource count.
+ Checks the handle, size, display mode and
+ conversion methods for twips to pixels. Checks
+ the heap for memory leaks.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestQueryBitmap()
+ {
+ INFO_PRINTF1(_L("Test Query Bitmap"));
+ __UHEAP_MARK;
+ CheckResourceCount();
+ CFbsBitmapEx bmp;
+ TInt ret=bmp.Create(TSize(100,100),EGray16);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+ TEST(bmp.Handle()!=0);
+ TEST(bmp.SizeInPixels()==TSize(100,100));
+ TEST(bmp.DisplayMode()==EGray16);
+ bmp.SetSizeInTwips(TSize(1000,1000));
+ TEST(bmp.SizeInTwips()==TSize(1000,1000));
+ TEST(bmp.HorizontalPixelsToTwips(10)==100);
+ TEST(bmp.VerticalPixelsToTwips(10)==100);
+ TEST(bmp.HorizontalTwipsToPixels(100)==10);
+ TEST(bmp.VerticalTwipsToPixels(100)==10);
+ TEST(bmp.ScanLineLength(100,EGray16)==52);
+ bmp.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+ User::Heap().Check();
+ DeleteScanLineBuffer();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0567
+
+ @SYMTestCaseDesc
+ Extended test to check scan line buffer in
+ session allocated correctly for SetRomBitmapL
+
+ @SYMTestActions
+ Loads a specific bitmap from a multi-bitmap
+ file. Reset the bitmap and checks the resource
+ count. Loads new bitmaps, checks the handle
+ the bitmap address and data address.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestRomBitmapL()
+ {
+ _LIT(KBmpFile, "z:\\system\\data\\tfbs.rbm");
+ INFO_PRINTF1(_L("Test Rom Bitmap"));
+ CheckResourceCount();
+ CFbsBitmapEx bmpx;
+ TInt ret=bmpx.Load(KBmpFile,ETfbs);
+ if (ret != KErrNone)
+ {
+ INFO_PRINTF2(_L("Rom bitmap tfbs.mbm not loaded %d\r\n"),ret);
+ return;
+ }
+ bmpx.Reset();
+ CheckResourceCount();
+ __UHEAP_MARK;
+ CFbsBitmapEx bmp1;
+ CFbsBitmapEx bmp2;
+ CFbsBitmapEx bmp3;
+ CFbsBitmapEx bmp4;
+ CFbsBitmapEx bmp5;
+ ret=bmp1.Load(KBmpFile,ETfbs);
+ TEST(ret==KErrNone);
+ TEST(bmp1.Handle()!=0);
+ ret=bmp2.Load(KBmpFile,ETfbs);
+ TEST(ret==KErrNone);
+ CBitwiseBitmap* bmp1add=bmp1.BitmapAddress();
+ TEST((TInt)bmp1add);
+ CBitwiseBitmap* bmp2add=bmp2.BitmapAddress();
+ TEST(bmp1add==bmp2add);
+ TEST(bmp1.Handle()==bmp2.Handle());
+ CheckResourceCount();
+
+ ret=bmp3.Load(KBmpFile,ETblank);
+ TEST(ret==KErrNone);
+ TEST(bmp1.Handle()!=bmp3.Handle());
+ bmp2.Reset();
+ ret=bmp4.Load(KBmpFile,ETfbs);
+ TEST(ret==KErrNone);
+ CBitwiseBitmap* bmp4add=bmp4.BitmapAddress();
+ TEST(bmp1add==bmp4add);
+ TEST(bmp4.Handle()==bmp1.Handle());
+
+ ret=bmp5.Load(KBmpFile,ETblank);
+ TEST(ret==KErrNone);
+ CBitwiseBitmap* bmp3add=bmp3.BitmapAddress();
+ CBitwiseBitmap* bmp5add=bmp5.BitmapAddress();
+ TEST((TInt)bmp3add);
+ TEST(bmp3add==bmp5add);
+ TEST(bmp5.Handle()==bmp3.Handle());
+
+ CheckResourceCount();
+ bmp3.Reset();
+ bmp4.Reset();
+ bmp5.Reset();
+ ret=bmp2.Load(KBmpFile,ETfbs);
+ TEST(ret==KErrNone);
+ bmp2add=bmp2.BitmapAddress();
+ TEST(bmp1add==bmp2add);
+ TEST(bmp1.Handle()==bmp2.Handle());
+
+ CheckResourceCount();
+ bmp2.Reset();
+ ret=bmp2.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ bmp2add=bmp2.BitmapAddress();
+ TSize bmpsize=bmp1.SizeInPixels();
+ TInt sllen=CFbsBitmap::ScanLineLength(bmpsize.iWidth,bmp1.DisplayMode());
+ sllen*=bmpsize.iHeight;
+ bmp1.LockHeap();
+ TUint32* bmp1bits=bmp1.DataAddress();
+ bmp1.UnlockHeap();
+ bmp2.LockHeap();
+ TUint32* bmp2bits=bmp2.DataAddress();
+ bmp2.UnlockHeap();
+ TEST(Mem::Compare((TUint8*)bmp1bits,sllen,(TUint8*)bmp2bits,sllen)==0);
+ bmp1.Reset();
+ bmp2.Reset();
+
+ ret=bmp1.Load(KBmpFile,ETfbs);
+ TEST(ret==KErrNone);
+ // Extended test to check scan line buffer in session allocated
+ // correctly for SetRomBitmapL()
+ DeleteScanLineBuffer();
+ TInt size = 0;
+ bmp2.SetRomBitmapL(bmp1.BitmapAddress(),size);
+ TEST(iFbs->iScanLineBuffer != 0);
+ TEST(Mem::Compare((TUint8*)bmp1.BitmapAddress(),size,(TUint8*)bmp2.BitmapAddress(),size)==0);
+ bmp1.Reset();
+ bmp2.Reset();
+
+ User::Heap().Check();
+ DeleteScanLineBuffer();
+ __UHEAP_MARKEND;
+ }
+
+TInt AlternateThreadTest(TAny* aAny)
+ {
+ CTFbs* alt = static_cast<CTFbs*> (aAny);
+ __UHEAP_MARK;
+
+ TInt ret=RFbsSession::Connect();
+ alt->TEST(ret==KErrNone);
+ RFbsSession* fbs=RFbsSession::GetSession();
+ alt->TEST(fbs!=NULL);
+ alt->TEST(fbs->ResourceCount()==0);
+
+ CFbsFontEx* font=new CFbsFontEx;
+ ret=font->Duplicate(buffer[0]);
+ alt->TEST(ret==KErrNone);
+ alt->TEST(fbs->ResourceCount()==1);
+
+ CFbsBitmapEx bmp;
+ ret=bmp.Duplicate(buffer[1]);
+ alt->TEST(ret==KErrNone);
+#if defined(__WINS__)
+ alt->TEST(fbs->ResourceCount()==2);
+#endif
+
+ CFbsFontEx* font2=new CFbsFontEx;
+ ret=font2->Duplicate(buffer[0]);
+ alt->TEST(ret==KErrNone);
+ font->Reset();
+ User::Free(font);
+ font2->Reset();
+ User::Free(font2);
+#if defined(__WINS__)
+ alt->TEST(fbs->ResourceCount()==1);
+#endif
+ CFbsBitmapEx bmp2;
+ ret=bmp2.Duplicate(buffer[1]);
+ alt->TEST(ret==KErrNone);
+ bmp.Reset();
+ bmp2.Reset();
+ alt->TEST(fbs->ResourceCount()==0);
+ RFbsSession::Disconnect();
+ __UHEAP_MARKEND;
+ return(KErrNone);
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0568
+
+ @SYMTestCaseDesc
+ Tests the resource counting of font objects
+ during multi threading
+
+ @SYMTestActions
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestMultiThread()
+ {
+ INFO_PRINTF1(_L("Test Multiple Threads"));
+ CFbsFontEx* font=SelectFont();
+ TEST(font->Handle()!=0);
+ iResourceCount++;
+ CheckResourceCount();
+
+ CFbsBitmapEx bmp;
+ TInt ret=bmp.Load(iTestBitmapName,ETfbs);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+
+ buffer[0]=font->Handle();
+ buffer[1]=bmp.Handle();
+ RThread thrd;
+ TRequestStatus stat;
+ thrd.Create(_L("AlternateThreadTest"),AlternateThreadTest,KDefaultStackSize,0x2000,0x2000,this);
+ thrd.SetPriority(EPriorityMuchMore);
+ thrd.Logon(stat);
+ thrd.Resume();
+ User::WaitForRequest(stat);
+ thrd.Close();
+ bmp.Reset();
+ iResourceCount--;
+ iTs->ReleaseFont(font);
+ iResourceCount--;
+ CheckResourceCount();
+ User::Heap().Check();
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0569
+
+ @SYMTestCaseDesc
+ Tests compression of bitmaps on the heap.
+
+ @SYMTestActions
+ Creates a bitmap. Checks the resource count.
+ Allocates memory on the heap. Locks the heap and
+ stores the bitmaps data address. The heap is unlocked.
+ Copies data from the stored data address and compares
+ the copied data with the original data. The heap is
+ checked for memory leaks.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestHeapCompression()
+ {
+ INFO_PRINTF1(_L("Test Heap Compression"));
+ __UHEAP_MARK;
+ CheckResourceCount();
+ CFbsBitmapEx bmp1;
+ TInt ret=bmp1.Create(TSize(100,100),EGray16);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+ CFbsBitmapEx bmp2;
+ ret=bmp2.Create(TSize(100,100),EGray16);
+ TEST(ret==KErrNone);
+ iResourceCount++;
+ CheckResourceCount();
+ TUint32* data=(TUint32*)User::Alloc(5200);
+ TEST(data!=NULL);
+ bmp2.LockHeap();
+ TUint32* sladd=bmp2.DataAddress();
+ bmp2.UnlockHeap();
+ TUint32* slptr=sladd;
+ for(TInt count=0;count<1300;count++)
+ *slptr++=count;
+ Mem::Copy(data,sladd,5200);
+ bmp1.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+ bmp2.LockHeap();
+ TUint32* newdata=bmp2.DataAddress();
+ bmp2.UnlockHeap();
+ TEST(Mem::Compare((TUint8*)data,5200,(TUint8*)newdata,5200)==0);
+ bmp2.Reset();
+ iResourceCount--;
+ CheckResourceCount();
+ delete data;
+ User::Heap().Check();
+ DeleteScanLineBuffer();
+ __UHEAP_MARKEND;
+ }
+
+void CTFbs::ExpandCleanupStackL()
+ {
+ TInt count=0;
+ for(;count<10;count++)
+ CleanupStack::PushL((TUint32*)0x1);
+ CleanupStack::Pop(count);
+ }
+
+void CTFbs::CheckResourceCount()
+ {
+ const TInt serverResourceCount = iFbs->ResourceCount();
+ TEST(serverResourceCount == iResourceCount);
+ }
+
+//
+// DoCreateBitmap(), CreateBitmap(), DoAllocScanLineBufL(), CTFbs::AllocScanLineBuf() are
+// used to show "INC044388 SymbianOS week 12 Fbserv crashes (on HW only)" defect
+// (problem with NULL scanline buffer) and to prove its fix.
+// The idea of the test:
+// A second thread ("CreateBitmap" is the thread name) is created and when resumed it
+// creates a bitmap and initializes ComprBitmap pointer to point to it.
+// The "CreateBitmap" thread signals the main thread, that the bitmap has been created,
+// and waits until receiving "Die" signal and then dies.
+// The main thread waits for a signal from the second thread and then duplicates the bitmap and
+// calls GetScanLine() on duplicated bitmap object. If the call fails, the defect is not fixed!
+
+CFbsBitmap* ComprBitmap = NULL;//Shared between threads bitmap pointer.
+_LIT(KRamComprBitmap, "z:\\system\\data\\16bit20col.mbm");
+RSemaphore BitmapCreatedSyncObj;//It is used to signal when the bitmap, created by the thread,
+ //is ready for use
+RSemaphore DieSyncObj;//It is used to signal that "CreateBitmapThread" can die.
+
+//Thread function. It is used by AllocScanLineBuf() test to create a test bitmap and share
+//it with the main thread. This function is called from CreateBitmap().
+static TInt DoCreateBitmapL(CTFbs* aTest)
+ {
+ aTest->TEST(::ComprBitmap == NULL);
+
+ ComprBitmap = new (ELeave) CFbsBitmap;
+
+ CleanupStack::PushL(::ComprBitmap);
+ User::LeaveIfError(::ComprBitmap->Load(KRamComprBitmap, 0));
+ CleanupStack::Pop(::ComprBitmap);
+
+ return KErrNone;
+ }
+
+//Thread function. It prepares the cleanup stack and traps the call to DoCreateBitmap().
+static TInt CreateBitmap(TAny* aTest)
+ {
+ CTFbs* test = static_cast <CTFbs*> (aTest);
+
+ CTrapCleanup* trapCleanup = CTrapCleanup::New();
+ test->TEST(trapCleanup != NULL);
+ TInt err = RFbsSession::Connect();
+ test->TEST(err == KErrNone);
+
+ TRAP(err, DoCreateBitmapL(test));
+
+ ::BitmapCreatedSyncObj.Signal();//Signal the main thread, that the bitmap has been created
+ ::DieSyncObj.Wait();//Wait "Die" command from the main thread
+
+ delete ::ComprBitmap;
+ ::ComprBitmap = NULL;
+ RFbsSession::Disconnect();
+ delete trapCleanup;
+ return err;
+ }
+
+static void DoAllocScanLineBufL(CTFbs& aTest)
+ {
+ aTest.TEST(::ComprBitmap == NULL);
+ //Create semaphores
+ ::CleanupClosePushL(::BitmapCreatedSyncObj);
+ ::CleanupClosePushL(::DieSyncObj);
+ User::LeaveIfError(::BitmapCreatedSyncObj.CreateLocal(0));
+ User::LeaveIfError(::DieSyncObj.CreateLocal(0));
+ //Create "CreateBitmap" thread. The tread will create "ComprBitmap" bitmap.
+ RThread createBitmapThread;
+ _LIT(KName, "CreateBitmap");
+ User::LeaveIfError(createBitmapThread.Create(KName,
+ (TThreadFunction)CreateBitmap, KDefaultStackSize, KMinHeapSize, 0x00100000, &aTest));
+ RDebug::Print(_L("CreateBitmap thread started\r\n"));
+ //Request notification when the tread dies.
+ TRequestStatus status;
+ createBitmapThread.Logon(status);
+ //Resume the thread
+ createBitmapThread.Resume();
+ ::BitmapCreatedSyncObj.Wait();//Wait "bitmap created" signal
+ //The bitmap "ComprBitmap" should be already created
+ aTest.TEST(::ComprBitmap != NULL);
+ //Duplicate the bitmap
+ CFbsBitmap* bmp = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL(bmp);
+ TInt err = bmp->Duplicate(::ComprBitmap->Handle());
+ aTest.TEST(err == KErrNone);
+ //Call GetScanLine(). It will fail if the defect is not fixed.
+ TBuf8<100> buf;
+ bmp->GetScanLine(buf, TPoint(0, 0), 10, EColor256);
+ //Cleanup
+ CleanupStack::PopAndDestroy(bmp);
+ //Signal & Wait until "CreateBitmap" thread dies.
+ ::DieSyncObj.Signal();
+ User::WaitForRequest(status);
+ aTest.TEST(::ComprBitmap == NULL);
+ CleanupStack::PopAndDestroy(&::DieSyncObj);
+ CleanupStack::PopAndDestroy(&::BitmapCreatedSyncObj);
+ }
+
+//INC044388 - SymbianOS week 12 Fbserv crashes (on HW only)
+void CTFbs::AllocScanLineBuf()
+ {
+ TRAPD(err, ::DoAllocScanLineBufL(*this));
+ TEST(err == KErrNone);
+ }
+// End of INC044388 test.
+
+
+int CTFbs::LoadOpenFontLibraries()
+ {
+ RImplInfoPtrArray implementationArray;
+ TInt error = KErrNone;
+ TUid uid = {KUidOpenFontRasterizerPlunginInterface};
+
+ TRAPD(ecomerror,REComSession::ListImplementationsL(uid,implementationArray));
+ TEST(ecomerror==KErrNone);
+
+ 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,iFs->InstallRasterizerL(rasterizer));
+ if (error)
+ delete rasterizer;
+ }
+ }
+ implementationArray.ResetAndDestroy();
+ return error;
+ }
+
+TBool CTFbs::CheckTypefacesSupport(const TTypefaceSupport& aInfo1, const TTypefaceSupport& aInfo2)
+ {
+ if ((aInfo1.iTypeface == aInfo2.iTypeface) &&
+ (aInfo1.iIsScalable == aInfo2.iIsScalable) &&
+ (aInfo1.iMaxHeightInTwips == aInfo2.iMaxHeightInTwips) &&
+ (aInfo1.iMinHeightInTwips == aInfo2.iMinHeightInTwips) &&
+ (aInfo1.iNumHeights == aInfo2.iNumHeights))
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+void CTFbs::LoadFontsL(const TDesC& aFontsDir)
+ {
+ TUid id1 = TUid::Uid(0);
+
+ RFs fileSys;
+ User::LeaveIfError(fileSys.Connect());
+
+ TFindFile fileFinder(fileSys);
+ CDir* foundFileList = NULL;
+
+ _LIT(KFBSERVFontFilePattern, "*");
+ TInt findFileComplete = fileFinder.FindWildByDir(KFBSERVFontFilePattern,aFontsDir,foundFileList);
+
+ while (!findFileComplete)
+ {
+ CleanupStack::PushL(foundFileList);
+
+ const TInt foundFileCount = foundFileList->Count();
+ for (TInt i = 0; i < foundFileCount; i++)
+ {
+ TParse parse;
+ if (parse.Set((*foundFileList)[i].iName,&fileFinder.File(),NULL) == KErrNone)
+ {
+ // Get filename and extension of font proposing to be loaded
+ TPtrC fontFilename = parse.NameAndExt();
+ INFO_PRINTF2(_L("CTFbs::LoadFontsL to load font filename: %S\r\n"), &fontFilename);
+ TRAPD(addFileError,id1=iFs->AddFileL(parse.FullName()));
+ if (addFileError != KErrNone)
+ {
+ // Log error in the "corrupt font" file
+ User::Panic(_L("Wrong font file"), addFileError);
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(foundFileList);
+ findFileComplete = fileFinder.FindWild(foundFileList);
+ }
+ fileSys.Close();
+ }
+
+ /**
+ @SYMTestCaseID GRAPHICS-PREQ807_1_Load_all_fonts-0001
+
+ @SYMPREQ REQ4723
+
+ @SYMTestCaseDesc The test manually scans the font folders and loads all font files available.
+ Once all the fonts have been loaded and stored in a CFontStore, the TTypefaces stored in this
+ CFontStore object are compared to the TTypefaces stored in an existing CFbsTypefaceStore.
+
+ @SYMTestPriority High
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions \n
+ API Calls:\n
+
+ @SYMTestExpectedResults The test expects that all the font files loaded by the test matches the ones
+ that FBserv loaded during the startup initialisation.
+ */
+void CTFbs::TestAllFontsLoaded()
+ {
+ INFO_PRINTF1(_L("Test Load all fonts files"));
+ __UHEAP_MARK;
+
+ iHeap=UserHeap::ChunkHeap(NULL,0x10000,0x10000);
+ TRAPD(ret,iFs=CFontStore::NewL(iHeap));
+ TEST(ret==KErrNone);
+ TEST(iFs != NULL);
+
+ ret = LoadOpenFontLibraries();
+ TEST(ret==KErrNone);
+
+ TRAP(ret, LoadFontsL(KFBSERVFontFileDir));
+ TEST(ret==KErrNone);
+
+ // Check the Typefaces are the same both in the newly CFontStore and existing CFbsTypefaceStore
+ TInt fsTypefaceNum = iFs->NumTypefaces();
+ TInt tsTypefaceNum = iTs->NumTypefaces();
+ TEST(fsTypefaceNum == tsTypefaceNum);
+
+ TBool equal = EFalse;
+ for (TInt i = 0; i < fsTypefaceNum; i++)
+ {
+ TTypefaceSupport infoFs;
+ iFs->TypefaceSupport(infoFs,i);
+ for (TInt j = 0; j < tsTypefaceNum; j++)
+ {
+ TTypefaceSupport infoTs;
+ iTs->TypefaceSupport(infoTs,j);
+
+ equal = CheckTypefacesSupport(infoFs, infoTs);
+ if (equal)
+ {
+ break;
+ }
+ }
+ // Check if the CFontStore typeface has been found in the CFbsTypefaceStore
+ TEST(equal);
+ }
+
+ delete iFs;
+ iHeap->Close();
+
+ REComSession::FinalClose();
+
+ User::Heap().Check();
+ __UHEAP_MARKEND;
+ }
+
+/**
+ @SYMTestCaseID
+ GRAPHICS-FBSERV-0570
+
+ @SYMTestCaseDesc
+ Tests default language for metrics.
+
+ @SYMTestActions
+ Constructs a TFontSpec object with the specified
+ typeface and height. Gets the font which is the
+ nearest to the given font specification. Checks
+ that the maximum font height is correct for a
+ specified language.
+
+ @SYMTestExpectedResults
+ Test should pass
+*/
+void CTFbs::TestDefaultLanguageForMetrics()
+ {
+ static const TInt KRequiredHeight = 24;
+ static const TInt KReturnedMaxHeight = 36;
+ TInt rc = KErrGeneral;
+
+ // Case 00
+ // No languages are set on font spec and typeface store
+ //
+ TFontSpec fontSpec0(KTypefaceName, KRequiredHeight);
+ CFont* font0 = NULL;
+ rc = iTs->GetNearestFontToDesignHeightInPixels(font0, fontSpec0);
+ TEST(KErrNone == rc);
+ TEST(NULL != font0);
+ TEST(KReturnedMaxHeight == font0->FontMaxHeight());
+ INFO_PRINTF2(_L("FontMaxHeight returns %d"), font0->FontMaxHeight());
+
+ // Case 01
+ // Set language on font spec will suppress that on typeface store
+ //
+ fontSpec0.SetScriptTypeForMetrics(ELangGreek);
+ CFont* font1 = NULL;
+ rc = iTs->GetNearestFontToDesignHeightInPixels(font1, fontSpec0);
+ TEST(KErrNone == rc);
+ TEST(NULL != font1);
+ TEST(KReturnedMaxHeight == font1->FontMaxHeight());
+ INFO_PRINTF2(_L("FontMaxHeight returns %d"), font1->FontMaxHeight());
+
+ // Set language on typeface store
+ iTs->SetDefaultLanguageForMetrics(ELangEnglish);
+
+ // Case 10
+ // Language on typeface store will suppress that on font spec
+ // _if_ its not specified
+ //
+ TFontSpec fontSpec1(KTypefaceName, KRequiredHeight);
+ CFont* font2 = NULL;
+ rc = iTs->GetNearestFontToDesignHeightInPixels(font2, fontSpec1);
+ TEST(KErrNone == rc);
+ TEST(NULL != font2);
+ TEST(KReturnedMaxHeight == font2->FontMaxHeight());
+ INFO_PRINTF2(_L("FontMaxHeight returns %d"), font2->FontMaxHeight());
+
+ // Case 11 - Negative test of case 10
+ //
+ fontSpec1.SetScriptTypeForMetrics(ELangRussian);
+ CFont* font3 = NULL;
+ rc = iTs->GetNearestFontToDesignHeightInPixels(font3, fontSpec1);
+ TEST(KErrNone == rc);
+ TEST(NULL != font3);
+ TEST(KReturnedMaxHeight == font3->FontMaxHeight());
+ INFO_PRINTF2(_L("FontMaxHeight returns %d"), font3->FontMaxHeight());
+
+ iTs->ReleaseFont(font0);
+ iTs->ReleaseFont(font1);
+ iTs->ReleaseFont(font2);
+ iTs->ReleaseFont(font3);
+
+ CheckResourceCount();
+ User::Heap().Check();
+ }
+
+
+//The "bad" versions of these standard fonts have been hacked to give specific results
+_LIT(KFBSERVFontFileOpen, "Z:\\resource\\fonts\\DejaVuSansCondensed.ttf");
+
+//This file is identical to DejaVuSansCondensed.ttf
+_LIT(KFBSERVFontFileBadOpen, "Z:\\PlatTest\\Graphics\\TestData\\uniquified_fonts\\xx_dejavusanscondensed.ttf");
+
+ /**
+ @SYMTestCaseID GRAPHICS-CTFbs-TestDuplicateFontFileEntries-0001
+
+ @SYMDEF DEF094692
+
+ @SYMTestCaseDesc If Open fonts are loaded that are marginally unique compared to the
+ existing fonts then they are not actually added to the typeface system, and may even be discarded.
+ The fix is actually in FNTSTORE, but I need to test in an environment with full Open font support,
+ which is not provided in the fontstore test code.
+ Bi9tmap fon ts are tested in fntstore\tfs\t_fntmem.cpp
+
+ @SYMTestPriority Med
+
+ @SYMTestStatus Implemented
+
+ @SYMTestActions \n
+ The original versions of the Open fonts are first loaded to ensure that they have actually been loaded.
+ The original versions of the Open fonts are loaded again to demobnstrate they have the same IDs.
+ A version of the open font which is identical except for a different filename should be rejected
+
+
+ API Calls: AddFile\n
+
+ @SYMTestExpectedResults The test expects:
+ The original versions should load without changing the number of typefaces
+ The second load should return the same UID for the font
+ The identical fonts should return captured fail codes, and not change the typeface counts
+ The semi-identical font should perform a single increase to UIDs and typefaces
+ */
+void CTFbs::TestDuplicateFontFileEntries()
+ {
+
+ INFO_PRINTF1(_L("Test Load semi-duplicate fonts files"));
+ TInt numFacesBefore=iTs->NumTypefaces();
+ TInt aIdOpen1=0;
+ TInt aIdOpen1b=0;
+ TInt aIdOpen2=0;
+ //make sure the originals of these fonts were safely opened
+ //both should simply cause a reference-count increase on the originator files.
+ TInt err2=iTs->AddFile(KFBSERVFontFileOpen,aIdOpen1);
+ TEST(err2==KErrNone);
+ if (err2)
+ {
+ INFO_PRINTF1(_L("One of the expected fonts was missing. Test abandoned."));
+ }
+ else
+ {
+ TInt numFacesAfterLoadOriginals=iTs->NumTypefaces();
+ //TEST(numFacesBefore==numFacesAfterLoadOriginals);
+ if (numFacesBefore!=numFacesAfterLoadOriginals)
+ INFO_PRINTF2(_L("Warning: reinstalling the system fonts added %d typefaces!"), numFacesAfterLoadOriginals-numFacesBefore);
+
+ //load the originals again just to prove the UIDs are re-used - only makes sense for open font where UID is generated!
+ TInt err2=iTs->AddFile(KFBSERVFontFileOpen,aIdOpen1b);
+ TEST(err2==KErrNone);
+ TEST(aIdOpen1==aIdOpen1b);
+
+ TInt numFacesAfterLoadBadFile3=iTs->NumTypefaces();
+ TEST(numFacesBefore==numFacesAfterLoadBadFile3);
+
+ //This open font file contains no new fonts, so will ultimately be discarded
+ //The pathname is different so it won't be considered identical to its originator
+ TInt err4=iTs->AddFile(KFBSERVFontFileBadOpen,aIdOpen2);
+ TEST(err4==KErrAlreadyExists && aIdOpen2==0);
+ if (err4!=KErrAlreadyExists)
+ INFO_PRINTF2(_L("Unexpected error code was %d"),err4);
+
+ TInt numFacesAfterLoadBadFile4=iTs->NumTypefaces();
+ TEST(numFacesBefore==numFacesAfterLoadBadFile4);
+
+ }
+
+ if (aIdOpen1) iTs->RemoveFile(aIdOpen1);
+ if (aIdOpen1b) iTs->RemoveFile(aIdOpen1b);
+ if (aIdOpen2) iTs->RemoveFile(aIdOpen2);
+
+ //The added typeface should have been uninstalled
+ TInt numFacesAfterUninstall=iTs->NumTypefaces();
+ TEST(numFacesAfterUninstall==numFacesBefore);
+
+
+ }
+
+
+/*
+COMMENTED OUT FOR NOW BECAUSE DEF084095 FIX MAKES THIS TEST REDUNDANT
+//DEF078039: Workwer function: Hindi - Risk of memory leak (RShapeInfo) if client thread dies
+TInt TShapeHeaderMemoryLeakTest(TAny* aTest)
+ {
+ _LIT16(KHindi1,"\x0915\x094D\x0937\x0924\x094D\x0930\x093F\x092F\x0020\x0909\x0926\x094D\x0926\x0947\x0936\x094D\x0020\x0915\x094D\x0937\x093F\x092A\x094D\x0930");
+ _LIT(KDevFontFace, "Devanagari OT Eval");
+
+ CTFbs* test = static_cast<CTFbs*> (aTest);
+
+ __UHEAP_MARK;
+
+ const TDesC16& Hindi1 = KHindi1;
+ RShapeInfo shapeInfo;
+ TBool isOpen = EFalse;
+
+ // Create a cleanup stack for this thread
+ CTrapCleanup* trapCleanup = CTrapCleanup::New();
+ test->TEST(trapCleanup != NULL);
+
+ // Create a new session with FBSERV
+ TInt ret=RFbsSession::Connect();
+ test->TEST(ret==KErrNone);
+ RFbsSession* fbs=RFbsSession::GetSession();
+ test->TEST(fbs!=NULL);
+
+ // Create a FbsFont to use for shaping
+ TFontSpec testFontSpec(KDevFontFace,200);
+ CFbsBitmap* bmp = new(ELeave) CFbsBitmap;
+ ret = bmp->Create(TSize(100,100),EGray2);
+ if (ret == KErrNotSupported)
+ return ret;
+ else
+ User::LeaveIfError(ret);
+
+ CFbsBitmapDevice* device = NULL;
+ TRAPD(err,device = CFbsBitmapDevice::NewL(bmp));
+ User::LeaveIfError(err);
+
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(device->CreateContext(gc));
+
+ CFbsFont* font = NULL;
+ User::LeaveIfError(device->GetNearestFontToDesignHeightInTwips(font,testFontSpec));
+ gc->UseFont(font);
+
+ // Open shapeInfo by calling GetCharacterPosition2. This makes an IPC call to the
+ // server and shapes Hindi, resulting in memory being allocated for a TShapeHeader object
+ CFont::TPositionParam param;
+ param.iDirection = CFont::EHorizontal;
+ param.iFlags = CFont::TPositionParam::EFLogicalOrder;
+ param.iText.Set(Hindi1);
+ param.iPosInText = 0;
+ param.iPen.iX = param.iPen.iY = 0;
+ TBool r = font->GetCharacterPosition2(param, shapeInfo);
+
+ // Test is memory was allocated to a TShapeHeader object
+ isOpen = shapeInfo.IsOpen();
+ test->TEST(isOpen == 1);
+
+ // Tidy up and close
+ delete bmp;
+ delete device;
+ delete gc;
+
+ // Disconnect from the server. i.e. end ther session, without calling
+ // RShapeInfo::Close(), to simulate a client death
+ RFbsSession::Disconnect();
+
+ // Check to see is TShapeHeader has been freed.
+ // Since a pointer the the TShapeHeader object is stored with the
+ // COpenFontSessionCache, when the client disconnects, the TShapeHeader
+ // object is freed along with the session cache.
+ isOpen = shapeInfo.IsOpen();
+ test->TEST(isOpen == 0);
+
+ delete trapCleanup;
+
+ __UHEAP_MARKEND;
+ return(KErrNone);
+ }
+*/
+/*
+COMMENTED OUT FOR NOW BECAUSE DEF084095 FIX MAKES THIS TEST REDUNDANT
+
+//DEF078039: Hindi - Risk of memory leak (RShapeInfo) if client thread dies
+void CTFbs::TestShapeHeaderMemoryLeakAtClientDeath()
+ {
+ INFO_PRINTF1(_L("Test Shape Header Memory Leak At Client Death"));
+ RThread shaperThread;
+ TRequestStatus stat;
+ shaperThread.Create(_L("Shaper Thread"),TShapeHeaderMemoryLeakTest,KDefaultStackSize, KMinHeapSize, 0x00100000,this);
+ shaperThread.SetPriority(EPriorityMuchMore);
+ shaperThread.Logon(stat);
+ shaperThread.Resume();
+ User::WaitForRequest(stat);
+ shaperThread.Close();
+ User::Heap().Check();
+ }
+// End of DEF078039 test.
+*/
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0506
+
+@SYMDEF INC103815
+
+@SYMTestCaseDesc Tests that the value returned by CFbsBitmap::Handle()
+ does not change after resizing or compression
+
+@SYMTestPriority High
+
+@SYMTestType UT
+
+@SYMTestStatus Implemented
+
+@SYMTestActions 1. Create a bitmap and store its handle number
+ 2. Resize the bitmap and compare its handle number with the stored value
+ 3. Compress the bitmap and compare its handle number with the stored value
+
+@SYMTestExpectedResults All the handle numbers returned should be the same
+*/
+void CTFbs::TestBitmapHandleImmutable()
+ {
+ INFO_PRINTF1(_L("Test fix for INC103815"));
+ CFbsBitmap *bmp = new CFbsBitmap;
+ TEST(bmp != NULL);
+ if (bmp == NULL)
+ return;
+ TEST(bmp->Create(TSize(200, 200), EColor256) == KErrNone);
+ TInt handle = bmp->Handle();
+ TEST(bmp->Resize(TSize(400, 400)) == KErrNone);
+ TEST(handle == bmp->Handle());
+ TEST(bmp->Compress() == KErrNone);
+ TEST(handle == bmp->Handle());
+ delete bmp;
+ }
+
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0507
+@SYMTestPriority High
+@SYMTestType UT
+@SYMTestStatus Implemented
+@SYMDEF PDEF102570
+
+@SYMTestCaseDesc
+ Tests that the attributes and the data address of a bitmap do not change between
+ calls to CFbsBitmap::BeginDataAccess() and CFbsBitmap::EndDataAccess() due to resizing
+ or compression by other clients
+
+@SYMTestActions
+ 1: Create a bitmap and a second CFbsBitmap object that refers to the same bitmap.
+ 2: Call BeginDataAccess() on the first CFbsBitmap object.
+ 3: Call Resize() on the second CFbsBitmap object.
+ 4: Call EndDataAccess() on the first CFbsBitmap object checking its state before and after.
+ 5: Call BeginDataAccess() on the first CFbsBitmap object.
+ 6: Call Compress() on the second CFbsBitmap object.
+ 7: Call EndDataAccess() on the first CFbsBitmap object checking its state before and after.
+
+@SYMTestExpectedResults
+ The affected attributes and the data address of the bitmap should change only
+ after the calls to EndDataAccess()
+*/
+void CTFbs::TestBitmapBeginEnd()
+ {
+ INFO_PRINTF1(_L("Test CFbsBitmap::BeginDataAccess()-EndDataAccess()"));
+ CFbsBitmap *bmp1 = new CFbsBitmap;
+ CFbsBitmap *bmp2 = new CFbsBitmap;
+ TEST(bmp1 != NULL && bmp2 != NULL);
+ if (bmp1 == NULL || bmp2 == NULL)
+ return;
+ TEST(bmp1->Create(TSize(200, 200), EColor256) == KErrNone);
+ TEST(bmp2->Duplicate(bmp1->Handle()) == KErrNone);
+ TUint32* dataAddress1 = bmp1->DataAddress();
+ TUint32* dataAddress2 = bmp2->DataAddress();
+ TEST(dataAddress1 == dataAddress2);
+ bmp1->BeginDataAccess();
+ TEST(bmp2->Resize(TSize(400, 400)) == KErrNone);
+ dataAddress2 = bmp2->DataAddress();
+ TEST(bmp1->SizeInPixels() == TSize(200, 200));
+ TEST(bmp1->DataAddress() == dataAddress1);
+ bmp1->EndDataAccess();
+ TEST(bmp1->SizeInPixels() == TSize(400, 400));
+ dataAddress1 = bmp1->DataAddress();
+ TEST(dataAddress1 == dataAddress2);
+ bmp1->BeginDataAccess();
+ TEST(bmp2->Compress() == KErrNone);
+ dataAddress2 = bmp2->DataAddress();
+ TEST(bmp1->Header().iCompression == ENoBitmapCompression);
+ TEST(bmp1->DataAddress() == dataAddress1);
+ bmp1->EndDataAccess();
+ TEST(bmp1->Header().iCompression != ENoBitmapCompression);
+ dataAddress1 = bmp1->DataAddress();
+ TEST(dataAddress1 == dataAddress2);
+ delete bmp1;
+ delete bmp2;
+ }
+
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0508
+@SYMTestPriority High
+@SYMTestType UT
+@SYMTestStatus Implemented
+@SYMDEF DEF104752
+
+@SYMTestCaseDesc
+ Tests that trying to launch a second instance of FBServ fails gracefully
+
+@SYMTestActions
+ Start a new instance of FBSERV.EXE. Since the Font and Bitmap Server should
+ already be running, the created process should panic immediately.
+
+@SYMTestExpectedResults
+ Panic FBSERV 5
+*/
+void CTFbs::TestSingletonServer()
+ {
+ INFO_PRINTF1(_L("Test singleton FBServ process"));
+ _LIT(KFBSERVServerExe, "z:\\sys\\bin\\fbserv.exe");
+ RProcess fbs;
+ TInt ret = fbs.Create(KFBSERVServerExe, KNullDesC);
+#ifdef __WINS__
+ // On the emulator it's not possible to load the same EXEXP twice
+ // DWin32CodeSeg::DoCreate() returns KErrAlreadyExists in that case
+ if (ret == KErrAlreadyExists)
+ return;
+#endif
+ TEST(ret == KErrNone);
+ TRequestStatus status;
+ fbs.Logon(status);
+ TEST(status == KRequestPending);
+ fbs.Resume();
+ User::WaitForRequest(status);
+ TExitType exitType = fbs.ExitType();
+ TExitCategoryName exitCategory = fbs.ExitCategory();
+ TInt exitReason = fbs.ExitReason();
+ TEST(exitType == EExitPanic);
+ TEST(exitCategory == KFBSERVPanicCategory);
+ TEST(exitReason == EFbsPanicStartupFailed);
+ fbs.Close();
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0620
+@SYMTestPriority High
+@SYMTestStatus Implemented
+@SYMDEF DEF140138
+
+@SYMTestCaseDesc
+ A positive test that shows in cases where the font glyph cache is full and the
+ session cache becomes used, client-side CFbsFont calls that query the session cache
+ successfully find the glyph, proving that the session handles used client-side and server-side
+ are the same, thereby avoiding any unneccessary IPC calls.
+
+@SYMTestActions
+ Create a large font which consumes a lot of memory.
+ Create a CFbsBitGc and a CFbsBitmap target.
+ Use the CFbsBitGc to render some text, thereby filling the font glyph cache.
+ Renders enough glyphs to fill up the font glyph cache, so that the session cache is used
+ for later characters.
+ Call CBitmapFont::CharacterNeedsToBeRasterized() with a NULL session handle.
+ Call CBitmapFont::CharacterNeedsToBeRasterized() with the RFbsSession handle.
+ Call CFbsFont::GetCharacterData() to retrieve a pointer to the bitmap data. Compare this with the data
+ returned from CBitmapFont::GetCharacterData().
+
+@SYMTestExpectedResults
+ When using KNullHandle, CharacterNeedsToBeRasterized() with the first character, is expected to pass
+ proving that the font cache is working as expected when glyphs can fit into it.
+ When using KNullHandle, CharacterNeedsToBeRasterized() with the last character, it expected to fail,
+ proving that the glyph has not been cached in the font glyph cache. (If it had, it would find a
+ match regardless of the session handle as it looks in the font cache before the session cache).
+ When using the correct session handle with CharacterNeedsToBeRasterized() with the last character,
+ should return ETrue, proving that the glyph has been cached, and was found because the correct
+ session handle was supplied, therefore must be in the session cache.
+ The bitmap pointers returned by CFbsFont::GetCharacterData() and CBitmapFont::GetCharacterData() should match,
+ proving the public API CFbsFont::GetCharacterData() is correctly using the data stored in the session cache,
+ and not returning the data of a separately-rasterized glyph.
+*/
+void CTFbs::TestFontSessionCacheLookupL()
+ {
+ INFO_PRINTF1(_L("Test Font Session-cache Lookup"));
+
+ User::LeaveIfError(RFbsSession::Connect());
+ RFbsSession* fbsSession = RFbsSession::GetSession();
+ CFbsTypefaceStore* ts = CFbsTypefaceStore::NewL(NULL);
+ CleanupStack::PushL(ts);
+
+ TFontSpec fs(_L("DejaVu Sans Mono"), 80);
+ fs.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ CFbsFont* font = NULL;
+ TEST(KErrNone == ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, fs));
+
+ CFbsBitmap* target = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL(target);
+ User::LeaveIfError(target->Create(TSize(100, 100), EColor16MU));
+ CFbsBitmapDevice* bgDevice = CFbsBitmapDevice::NewL(target);
+ CleanupStack::PushL(bgDevice);
+ CFbsBitGc* bgGc = NULL;
+ User::LeaveIfError(bgDevice->CreateContext(bgGc));
+ bgGc->UseFont(font);
+ CleanupStack::PushL(bgGc);
+ _LIT(KTestText, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ");
+
+ // Draw the text, forcing the glyphs into the font and session caches.
+ bgGc->DrawText(KTestText, TPoint(0, 10));
+
+ CBitmapFont* bmFont = CTFbsFont::FontAddress(font);
+
+ // Check that the first character in KTestText has been rasterized, and is in the font cache.
+ TBool glyphIsInFontCache = !bmFont->CharacterNeedsToBeRasterized(KNullHandle, KTestText()[0]);
+ TEST(glyphIsInFontCache);
+
+ // Check that the last character in KTestText has been rasterized, and is not in the font cache
+ // because it did not fit, therefore it should be in the session cache.
+ const TChar KTestChar = KTestText()[KTestText().Length() - 1];
+ glyphIsInFontCache = !bmFont->CharacterNeedsToBeRasterized(KNullHandle, KTestChar);
+ TEST(!glyphIsInFontCache);
+ TBool glyphIsInSessionCache = !bmFont->CharacterNeedsToBeRasterized(fbsSession->iHelper->iServerSessionHandle, KTestChar);
+ TEST(glyphIsInSessionCache);
+
+ // Test that when calling GetCharacterData() on CFbsFont, it returns the same rasterized data as
+ // the bitmap in the session cache, proving that the client API is using the session cache handle correctly.
+ TSize bitmapSize;
+ const TUint8* bitmapDataClient;
+ const TUint8* bitmapDataSessionCache;
+ TOpenFontCharMetrics metrics;
+ font->GetCharacterData(KTestChar,metrics,bitmapDataClient,bitmapSize);
+ bmFont->GetCharacterData(fbsSession->iHelper->iServerSessionHandle, KTestChar, metrics, bitmapDataSessionCache);
+ TEST(bitmapDataClient != NULL && bitmapDataClient == bitmapDataSessionCache);
+
+ bgGc->DiscardFont();
+ CleanupStack::PopAndDestroy(4); // bgGc, bgDevice, target, ts
+ RFbsSession::Disconnect();
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0650
+@SYMTestPriority High
+@SYMTestStatus Implemented
+@SYMDEF DEF141816
+
+@SYMTestCaseDesc
+ A negative test that shows that IPC calls from CFbsBitmap which uses a
+ CFbsFont handle fail and that IPC calls from CFbsFont which use a
+ CFbsBitmap handle fail.
+
+@SYMTestActions
+ i. Create a bitmap.
+ ii. Create a font.
+ iii. Send a bitmap-related IPC message to server with bitmap handle.
+ iv. Send a bitmap-related IPC message to server with font handle.
+ v. Send a font-related IPC message to server with font handle.
+ vi. In a separate thread, send a font-related IPC message to server with
+ bitmap handle.
+
+@SYMTestExpectedResults
+ Steps iii. and v. should return KErrNone.
+ Step iv. should return KErrUnknown.
+ Step vi. should panic with FBSERV -6.
+*/
+void CTFbs::TestInvalidHandlesInIpcCallsL()
+ {
+ INFO_PRINTF1(_L("Test Bitmap and Font IPC calls with invalid handles"));
+ CFbsFontEx* font = SelectFont();
+
+ CFbsBitmapEx* bmp = new(ELeave) CFbsBitmapEx();
+ TEST(KErrNone == bmp->Create(TSize(1,1),EGray2));
+
+ TInt fontHandle = font->FontHandle();
+ TInt bitmapHandle = bmp->BitmapHandle();
+
+ // Send a IPC command to resize a bitmap with a font handle
+ TPckgBuf<TBmpHandles> handlebuf;
+ TIpcArgs args1(fontHandle, 2, 2, &handlebuf);
+ // Send a IPC command to resize a bitmap with the bitmap's handle
+ TEST(KErrNone == iFbs->SendCommand(EFbsMessBitmapBgCompress, bitmapHandle));
+ // Send a IPC command to resize a bitmap with the font's handle
+ TEST(KErrUnknown == iFbs->SendCommand(EFbsMessBitmapBgCompress, fontHandle));
+
+ // Send a IPC command to set the font's height with the font's handle
+ TEST(KErrNone == iFbs->SendCommand(EFbsMessSetTwipsHeight, fontHandle, 49));
+ // In a second thread, send a IPC command to set the font's height with the
+ // bitmap's handle. Should panic with FBServ -6.
+ TFbsTestThreadInfo threadInfo = {EFbsSecondThreadInvalidHandleInIpcCall};
+ TExitCategoryName exitCategoryName(KFbsPanicCategory);
+ _LIT(KTestName, "TestInvalidHandlesInIpcCall");
+ CreateSecondThreadAndCheckPanicL(threadInfo, -6, exitCategoryName, KTestName);
+
+ iTs->ReleaseFont(font);
+ delete bmp;
+ }
+
+/**
+Creates a second thread and do some panic tests in it.
+@param aTestInfo The information for the tests
+@param aPanicCode The expected panic code
+@param aExitCategory The expected panic category
+@param aThreadName The name of the new thread
+@leave Gets system wide error code
+*/
+void CTFbs::CreateSecondThreadAndCheckPanicL(TFbsTestThreadInfo& aTestInfo, TInt aPanicCode, TExitCategoryName aExitCategory, const TDesC &aThreadName)
+ {
+ RThread secondThread;
+ User::LeaveIfError(secondThread.Create(aThreadName, SecondThreadStart, KDefaultStackSize, 0x1000, 0x1000, &aTestInfo));
+ // Launch second thread
+ TRequestStatus statusSecondThread;
+ secondThread.Logon(statusSecondThread);
+ secondThread.SetPriority(EPriorityLess);
+ secondThread.Resume();
+
+ User::WaitForRequest(statusSecondThread);
+
+ if(EExitPanic != secondThread.ExitType())
+ {
+ ERR_PRINTF3(_L("Expected exit type: %d, Actual exit type: %d"), EExitPanic, secondThread.ExitType());
+ TEST(EFalse);
+ }
+
+ if(aPanicCode != secondThread.ExitReason())
+ {
+ ERR_PRINTF3(_L("Expected panic code: %d, Actual panic code: %d"), aPanicCode, secondThread.ExitReason());
+ TEST(EFalse);
+ }
+
+ TExitCategoryName secondThreadExitCategory = secondThread.ExitCategory();
+ if(aExitCategory != secondThreadExitCategory)
+ {
+ ERR_PRINTF3(_L("Expected panic category: %S, Actual panic category: %S"), &aExitCategory, &secondThreadExitCategory);
+ TEST(EFalse);
+ }
+
+ //Close the handle
+ secondThread.Close();
+ }
+
+/**
+Second thread entry function.
+*/
+TInt CTFbs::SecondThreadStart(TAny* aTestInfo)
+ {
+
+ __UHEAP_MARK;
+ TInt procHandles1 =0;
+ TInt threadHandles1=0;
+ RThread().HandleCount(procHandles1, threadHandles1);
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+
+ if (!cleanupStack)
+ {
+ __UHEAP_MARKEND;
+ return KErrNoMemory;
+ }
+
+ TInt result = KErrNone;
+ TRAP(result, SecondThreadMainL(static_cast<TFbsTestThreadInfo*>(aTestInfo)));
+
+ delete cleanupStack;
+
+ TInt procHandles2 =0;
+ TInt threadHandles2=0;
+ RThread().HandleCount(procHandles2,threadHandles2);
+ if (threadHandles1 != threadHandles2)
+ {
+ result = KErrGeneral; // Thread-owned handles not closed
+ }
+ __UHEAP_MARKEND;
+
+ return result;
+ }
+
+/**
+Run the test contained within the TFbsTestThreadInfo object. A new thread is
+created for each test and only one of the cases in the switch statements
+below will be used.
+
+@param aTestInfo The parameters for the test
+@return One of the system wide error codes or an enumeration of passed tests.
+ */
+TInt CTFbs::SecondThreadMainL(TFbsTestThreadInfo* aTestInfo)
+ {
+ TInt result = 0;
+ TFbsMultiThreadTestCase testcase = aTestInfo->iTestCase;
+
+ //test cases without the need of an initialised driver
+ switch (testcase)
+ {
+ case EFbsSecondThreadInvalidHandleInIpcCall:
+ result = SecondThreadPanicInvalidHandleInIpcCall();
+ break;
+ }
+ return result;
+ }
+
+/**
+Implementation of SecondThread test EFbsSecondThreadInvalidHandleInIpcCall
+
+@panic FBSERV -6 If the test is successful
+
+@return One of the system wide error codes.
+ */
+TInt CTFbs::SecondThreadPanicInvalidHandleInIpcCall()
+ {
+ TInt result = RFbsSession::Connect();
+ if (KErrNone != result)
+ {
+ return result;
+ }
+ RFbsSession* fbs = RFbsSession::GetSession();
+ CFbsBitmapEx* bmp = new CFbsBitmapEx();
+ if (!bmp)
+ {
+ return KErrGeneral;
+ }
+ result = bmp->Create(TSize(1,1),EGray2);
+ if(KErrNone != result)
+ {
+ delete bmp;
+ return KErrGeneral;
+ }
+
+ CFbsTypefaceStore* ts = NULL;
+ ts = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
+ if (!ts)
+ {
+ delete bmp;
+ return KErrGeneral;
+ }
+
+ CFbsFontEx* font=NULL;
+ result = ts->GetNearestFontToDesignHeightInPixels((CFont*&)font, TFontSpec(KTypefaceName, 15));
+ if (!font)
+ {
+ delete bmp;
+ delete ts;
+ return KErrGeneral;
+ }
+
+ TInt fontHandle = font->FontHandle();
+ TInt bitmapHandle = bmp->BitmapHandle();
+
+ // Send a IPC command to set twips height of font with a bitmap handle
+ result = fbs->SendCommand(EFbsMessSetTwipsHeight, bitmapHandle, 49);
+
+ ts->ReleaseFont(font);
+ delete bmp;
+ delete ts;
+ return result;
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-FBSERV-0619
+@SYMTestPriority High
+@SYMTestType UT
+@SYMTestStatus Implemented
+@SYMDEF EI0014
+
+@SYMTestCaseDesc
+ Tests that there are no virtual function calls to objects in FBServ's shared heap from outside
+ the FBServ process. Such function calls only work if DLLs are guaranteed to be mapped at the
+ same logical address in every process. This is not necessarily true for all memory models.
+
+@SYMTestActions
+ Selects a font, intercepts the VF table in the corresponding CBitmapFont and COpenFont objects
+ to record virtual function calls from outside the FBServ process, calls the vulnerable functions
+ on the created CFbsFont object and releases the font.
+
+@SYMTestExpectedResults
+ Number of virtual function calls to CBitmapFont and COpenFont from outside FBServ is 0
+*/
+void CTFbs::TestNoVFCallsToGlobalObjects()
+ {
+#ifdef __WINS__
+ INFO_PRINTF1(_L("Test no virtual function calls to objects in FBServ's shared heap from outside FBServ process"));
+ CFbsFontEx* font = SelectFont();
+ (void)font->TypeUid();
+ (void)font->HeightInPixels();
+ (void)font->AscentInPixels();
+ (void)font->DescentInPixels();
+ (void)font->CharWidthInPixels('A');
+ (void)font->TextWidthInPixels(_L("A"));
+ (void)font->BaselineOffsetInPixels();
+ (void)font->TextCount(_L("A"), 10);
+ TInt excess;
+ (void)font->TextCount(_L("A"), 10, excess);
+ (void)font->MaxCharWidthInPixels();
+ (void)font->MaxNormalCharWidthInPixels();
+ (void)font->FontSpecInTwips();
+ TOpenFontCharMetrics metrics;
+ const TUint8* bitmap;
+ TSize size;
+ (void)font->GetCharacterData('A', metrics, bitmap, size);
+ CFont::TPositionParam param;
+ param.iText.Set(_L("A"));
+ (void)font->GetCharacterPosition(param);
+ (void)font->FontCapitalAscent();
+ (void)font->FontMaxAscent();
+ (void)font->FontStandardDescent();
+ (void)font->FontMaxDescent();
+ (void)font->FontLineGap();
+ iTs->ReleaseFont(font);
+ TEST(iFontCallCounter.iVFCallsOutsideFBServ == 0);
+ TEST(iOpenFontCallCounter.iVFCallsOutsideFBServ == 0);
+#else
+ INFO_PRINTF1(_L("Test no virtual function calls to objects in FBServ's shared heap from outside FBServ process - skipped on target"));
+#endif
+ }
+
+//--------------
+__CONSTRUCT_STEP__(Fbs)