diff -r 000000000000 -r 5d03bc08d59c fbs/fontandbitmapserver/tfbs/TFBS.CPP --- /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 +#include +#include +#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 XTCallCounter::XTCallCounter(CTGraphicsBase& aTestBase) + : iTestBase(aTestBase), iVFCallsOutsideFBServ(0) + {} + +template void XTCallCounter::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::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(;countResourceCount()==0); + for(count=0;countResourceCount()==0); + for(TInt count2=0;count2ResourceCount()==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(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;countTypefaceSupport(info,count); + INFO_PRINTF1(_L(" ")); + TBuf 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(;indexFontHeightInTwips(count,index); + for(index=1;indexheightarray[index-1]); + for(index=0;indexFontHeightInPixels(count,index); + for(index=1;index=heightarray[index-1]); + delete [] heightarray; + for(index=0;indexFontHeightInTwips(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 defaultName; + TBuf 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(;countReleaseFont(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 (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 (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;countImplementationUid(); + // 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 (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 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(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)