diff -r 000000000000 -r 5d03bc08d59c fbs/fontandbitmapserver/sfbs/FBSTOP.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fbs/fontandbitmapserver/sfbs/FBSTOP.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,726 @@ +// 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: +// + +#include +#include +#include +#include +#include +#include "fbsmessage.h" +#include +#include "SERVER.H" +#include "BackGroundCompression.h" +#include "BitwiseBitmap.inl" +#include "bitmapconst.h" +#include +#include +#include + +// Local utility functions +void ListImplementationsWithRetry(TUid& aInterfaceUid, RImplInfoPtrArray &aImplementationArray, TBool aRomOnly); + + +CFbTop::CFbTop(): + iDefaultLanguageForMetrics(ELangNone) + { + } + +CFbTop::~CFbTop() + { + if (iConIx) + { + iConIx->Remove(iBitmapCon); + iConIx->Remove(iFontCon); + } + // there are no bitmap objects left, so the background compression queue must be empty + delete iBackgroundCompression; + delete iMBMCache; + delete iFontStore; + iFilesys.Close(); + iHeap->Check(); + __RHEAP_MARKEND(iHeap); + delete iPile; + iHeap->Close(); + iChunk.Close(); + iLargeBitmapChunk.Close(); + delete iConIx; +#ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP + iDebugMutex.Close(); +#endif + iFontNameAlias.ResetAndDestroy(); + iBitmapObjectIndex.Reset(); + REComSession::FinalClose(); + } + +CFbTop* CFbTop::NewL() + { + CFbTop* pT=new(ELeave) CFbTop; + CleanupStack::PushL(pT); + pT->ConstructL(); + CleanupStack::Pop(); + return(pT); + } + +void CFbTop::ConstructL() + { + TInt maxmem = 0; + HAL::Get(HALData::EMemoryRAM, maxmem); + ASSERT(maxmem > 0); + TInt maxHeapSize = Min(maxmem, KFbServSharedHeapMaxSize); + + TChunkHeapCreateInfo sharedHeapCreateInfo(KFBSERVInitialHeapSize, maxHeapSize); + sharedHeapCreateInfo.SetCreateChunk(&KFBSERVSharedChunkName); + sharedHeapCreateInfo.SetSingleThread(EFalse); + sharedHeapCreateInfo.SetAlignment(0); + sharedHeapCreateInfo.SetGrowBy(KMinHeapGrowBy * KFBSERVHeapGrowByMultiplier); + + if(KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataAndSharedHeapChunksOnly) + { + //Request that the shared heap chunk is paged. + sharedHeapCreateInfo.SetPaging(TChunkHeapCreateInfo::EPaged); + } + else + { + //Use the creating process's paging attributes. + sharedHeapCreateInfo.SetPaging(TChunkHeapCreateInfo::EUnspecified); + } + + iHeap = UserHeap::ChunkHeap(sharedHeapCreateInfo); + + User::LeaveIfError(iChunk.OpenGlobal(KFBSERVSharedChunkName,ETrue)); + TInt virtualSize = CChunkPile::VirtualSize(); + + TChunkCreateInfo createInfo; + createInfo.SetDisconnected(0, 0, virtualSize); + createInfo.SetGlobal(KFBSERVLargeChunkName); + createInfo.SetOwner(EOwnerProcess); + createInfo.SetClearByte(0xff); // clear to white on creation + + if(KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataChunkOnly || + KFbServWritableDataPagingMode == EFbsWdpPageBitmapDataAndSharedHeapChunksOnly) + { + //Request that large bitmap chunk is paged. + createInfo.SetPaging(TChunkCreateInfo::EPaged); + } + else + { + //Use the creating process's paging attributes. + createInfo.SetPaging(TChunkCreateInfo::EUnspecified); + } + + User::LeaveIfError(iLargeBitmapChunk.Create(createInfo)); + __RHEAP_MARK(iHeap); + iConIx=CObjectConIx::NewL(); + iBitmapCon=iConIx->CreateL(); + iFontCon=iConIx->CreateL(); + User::LeaveIfError(iFilesys.Connect()); +#ifdef SYMBIAN_DEBUG_FBS_LOCKHEAP + User::LeaveIfError(iDebugMutex.CreateGlobal(KFBSERVDebugMutexName)); +#endif + iPile = CChunkPile::NewL(iLargeBitmapChunk); + iFontStore=CFontStore::NewL(iHeap); + //Constructing a cache to store the stream ids of the bitmaps from a mbm file. + //The cache here will store maximum 30 bitmaps before & maximum 30 after the + //current loaded bitmap.These values are chosen as to optimize the boottime performance + //as we notice during the boottime logs,sequential loading of bitmaps never exceed 30 bitmaps. + // The cache will also store maximum 5 mbm files. This number must be as low as possible + // while trying to minimize flushing of the cache due to mbm file switching. + iMBMCache=new (ELeave) CFbTopStreamIdCache(30,30,5); + + LoadOpenFontLibraries(); + + iFontStore->LoadFontsAtStartupL(); + LoadShaperFactories(); + + // start a new thread for background compression after all the other objects have been created + iBackgroundCompression = CFbsBackgroundCompression::NewL(*this); + } + + + + +/* +Load all ECOM implemented rasterizer DLLs. +*/ + +void CFbTop::LoadOpenFontLibraries() + { + RImplInfoPtrArray implementationArray; + TUid uid = {KUidOpenFontRasterizerPlunginInterface}; + + // get implementation list + ListImplementationsWithRetry(uid, implementationArray, EFalse); + + const TInt availCount = implementationArray.Count(); + for (TInt count=0; count < availCount; ++count) + { + const CImplementationInformation* info = implementationArray[count]; + // Create & install a rasterizer + // ignore Leaves, as any necessary cleanup will have already been done through the cleanup stack + TRAP_IGNORE(SafeInstallOfRasterizerL(info->ImplementationUid())); + } + + // free memory + implementationArray.ResetAndDestroy(); + } + + +/* +Load all ECOM implemented shaper factory DLLs. +*/ +void CFbTop::LoadShaperFactories() + { + RImplInfoPtrArray implementationArray; + TUid uid = {KUidShaperFactoryPlunginInterface}; + + // get implementation list + ListImplementationsWithRetry(uid, implementationArray, ETrue); + + const TInt availCount = implementationArray.Count(); + for (TInt count=0;countImplementationUid())); + } + + // free memory + implementationArray.ResetAndDestroy(); + } + + +void ListImplementationsWithRetry(TUid& aInterfaceUid, RImplInfoPtrArray &aImplementationArray, TBool aRomOnly) + { + // Making sure that no race situation arises between FBserv and Ecom + // If ECom is not ready, give it another chance and try again. if it still doesn't work + // after the third try, then it just carries on quietly and fails... + for (TInt ecomnotready =0; ecomnotready <3; ecomnotready++) + { + TInt ecomError = KErrNone; + if (aRomOnly) + { + TEComResolverParams resParams; + TRAP(ecomError, REComSession::ListImplementationsL(aInterfaceUid, resParams, KRomOnlyResolverUid, aImplementationArray)); + } + else + { // default resolver + TRAP(ecomError, REComSession::ListImplementationsL(aInterfaceUid, aImplementationArray)); + } + + if (!ecomError) + { + return; + } + else + { + User::After(0); + } + } + } + +// utility methods to transfer ownership, or destroy object on failure +void CFbTop::SafeInstallOfRasterizerL(TUid aInterfaceImplUid) + { + COpenFontRasterizer* rasterizer = COpenFontRasterizer::NewL(aInterfaceImplUid); + CleanupStack::PushL(rasterizer); + // Install it in the font store. + iFontStore->InstallRasterizerL(rasterizer); + CleanupStack::Pop(rasterizer); + } + + +void CFbTop::SafeInstallOfShaperFactoryL(TUid aInterfaceImplUid) + { + CShaperFactory* shaperFactory = CShaperFactory::NewL(aInterfaceImplUid); + CleanupStack::PushL(shaperFactory); + // Install it in the font store. + iFontStore->InstallShaperFactoryL(shaperFactory); + CleanupStack::Pop(shaperFactory); + } + +/** +Gets the nearest matching font for a given font specification. If the named font cannot be found +font aliases are checked. + +@param aFontObjPtr On success this contains the font object that is the closest match. +@param aMessage The font request message. +@param aFontSpec The font spec to match. +@param aMaxHeight The maximum height of the font to match. +@return KErrNone if successful, KErrNotFound if the font is not found, or one of the other System Error codes. + */ +TInt CFbTop::GetNearestFont( + CFontObject*& aFontObjPtr, + TFbsMessage aMessage, + const TFontSpec& aFontSpec, + TInt aMaxHeight) + { +#ifdef _DEBUG + User::Heap().Check(); + iHeap->Check(); +#endif + aFontObjPtr = NULL; + + TFontSpec fontSpec(aFontSpec); + + // Check if the font typeface is empty and if so use the system default font if it is set + if (fontSpec.iTypeface.iName.Length() == 0 && iSystemDefaultFontTypefaceName.Length() != 0) + { + fontSpec.iTypeface.iName = iSystemDefaultFontTypefaceName; + } + + if (GlyphSample::EScriptDefault == fontSpec.ScriptTypeForMetrics()) + { + fontSpec.SetScriptTypeForMetrics(iDefaultLanguageForMetrics); + } + + // Find the requested font + TBool familyNameExistsInTypefaceStore = iFontStore->HaveTypefaceFamilyName(fontSpec.iTypeface.iName); + + // If the font is not found try finding an alias font + if (!familyNameExistsInTypefaceStore) + { + TInt aliasIndex = FindFontNameAlias(fontSpec.iTypeface.iName); + //KErrNotFound is the only error which can be returned + if (aliasIndex != KErrNotFound) + { + fontSpec.iTypeface.iName = *iFontNameAlias[aliasIndex + 1]; + } + } + + CFont* font = NULL; + TInt ret = GetNearestNonAliasedFont(font, aMessage, fontSpec, aMaxHeight); + + if (ret != KErrNone) + { + return ret; + } + + return CreateFontObjectFromFont(aFontObjPtr, font); + } + +/** +Gets the nearest matching loaded font for a given font specification. + +@param aFont On success this contains the font object that is the closest match. +@param aMessage The font request message. +@param aFontSpec The font spec to match. +@param aMaxHeight The maximum height of the font to match. +@return KErrNone if successful, KErrNotFound if the font is not found, or one of the other System Error codes. +*/ +TInt CFbTop::GetNearestNonAliasedFont(CFont*& aFont, TFbsMessage aMessage, const TFontSpec& aFontSpec, TInt aMaxHeight) + { + TInt ret = KErrNotSupported; + switch (aMessage) + { + case EFbsMessGetNearestFontToDesignHeightInTwips: + { + ret = iFontStore->GetNearestFontToDesignHeightInTwips(aFont, aFontSpec); + break; + } + case EFbsMessGetNearestFontToDesignHeightInPixels: + { + ret = iFontStore->GetNearestFontToDesignHeightInPixels(aFont, aFontSpec); + break; + } + case EFbsMessGetNearestFontToMaxHeightInTwips: + { + ret = iFontStore->GetNearestFontToMaxHeightInTwips(aFont, aFontSpec, aMaxHeight); + break; + } + case EFbsMessGetNearestFontToMaxHeightInPixels: + { + ret = iFontStore->GetNearestFontToMaxHeightInPixels(aFont, aFontSpec, aMaxHeight); + break; + } + } + return ret; + } + +TInt CFbTop::CreateFontObjectFromFont(CFontObject*& aFontObjPtr, CFont* aFont) + { + CFontObject* fontObjPtr = new CFontObject(iFontStore); + if (!fontObjPtr) + { + iFontStore->ReleaseFont(aFont); + return KErrNoMemory; + } + + fontObjPtr->iAddressPointer = reinterpret_cast(aFont); + fontObjPtr->iHeightInTwips = ((aFont->HeightInPixels() * iFontStore->iKPixelHeightInTwips) + 667) / 1000; + TRAPD(ret, iFontCon->AddL(fontObjPtr)); + if (ret != KErrNone) + { + fontObjPtr->Close(); + } + else + { // transfer ownership + aFontObjPtr = fontObjPtr; + } + return ret; + } + + +/** Create a Bitmap Font, from a UID and Algorithmic drawing Style see CFontStore::GetFontById() +@internalComponent +*/ +TInt CFbTop::GetFontById(CFontObject*& aFontObjPtr,TUid aUid,const TAlgStyle& aAlgStyle) + { +#ifdef _DEBUG + User::Heap().Check(); + iHeap->Check(); +#endif + aFontObjPtr=NULL; + CBitmapFont* font=NULL; + TInt ret=iFontStore->GetFontById((CFont*&)font,aUid,(TAlgStyle&)aAlgStyle); + if (ret != KErrNone) + { + return ret; + } + return CreateFontObjectFromFont(aFontObjPtr, font); + } + + +/** Create a bitmap with the given size, display mode and UID. + +@param aSize Size of the bitmap in pixels. +@param aDispMode Display mode of the bitmap. +@param aUid The UID to use for bitmap creation. This can be: + - KUidCFbsBitmapCreation for standard bitmaps. + - The application UID for hardware bitmaps. + - The data type UID for extended bitmaps. +@param aReplacement If ETrue the bitmap is being created as a replacement + for a bitmap being made dirty by a resize or compress operation. +@param aDataSize If different from zero, it indicates that the bitmap to create + is an extended bitmap and specifies the size in bytes of the bitmap. + If equal to zero, it indicates that the bitmap to create is a standard + bitmap or a hardware bitmap, depending on the value of aUid, and the size + in bytes is calculated from the size in pixels and the display mode. +@internalComponent +*/ +CBitmapObject* CFbTop::CreateBitmapL(const TSize& aSize, TDisplayMode aDispMode, TUid aUid, TBool aReplacement, TInt aDataSize) + { +#ifdef _DEBUG + User::Heap().Check(); + iHeap->Check(); +#endif + CBitwiseBitmap* bmp=(CBitwiseBitmap*)iHeap->AllocL(sizeof(CBitwiseBitmap) + sizeof(CBitwiseBitmap::TExtra)); + new(bmp) CBitwiseBitmap(iHeap,iPile); + CleanupDeletePushL(bmp); // CBitwiseBitmap is not derived from CBase! + + if (aDataSize == 0) + User::LeaveIfError(bmp->Construct(aSize, aDispMode, aUid)); + else + User::LeaveIfError(bmp->ConstructExtended(aSize, aDispMode, aUid, aDataSize)); + // bmp popped out of the clean-up stack by NewL + CBitmapObject* bmpObj = CBitmapObject::NewL(*this, bmp, aReplacement); + if (!aReplacement) + { + bmp->Extra()->iSerialNumber = iNextAvailableSerialNumber++; + } + + return bmpObj; + } + +CBitmapObject* CFbTop::LoadBitmapL(const TDesC& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle) + { + CBitwiseBitmap* bmp=DoLoadBitmapLC(aFilename, aId, aFileOffset, aFile, aSessionHandle); + // bmp popped out of the clean-up stack by NewL + CBitmapObject* bmpObj = CBitmapObject::NewL(*this, bmp, EFalse); + + return bmpObj; + } + +_LIT(KZDrive, "z:"); + +CBitwiseBitmap* CFbTop::DoLoadBitmapLC(const TDesC& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle) + { +#ifdef _DEBUG + User::Heap().Check(); + iHeap->Check(); +#endif + CBitwiseBitmap* bmp=(CBitwiseBitmap*)iHeap->AllocL(sizeof(CBitwiseBitmap) + sizeof(CBitwiseBitmap::TExtra)); + new(bmp) CBitwiseBitmap(iHeap,iPile); + bmp->Extra()->iSerialNumber = iNextAvailableSerialNumber++; + CleanupDeletePushL(bmp); // CBitwiseBitmap is not derived from CBase! + + if (NULL == aFile) + { + // In this case file should be in z: drive + // so load the bitmap from the mbm cache + TStreamId streamid(0); + streamid=iMBMCache->GetStreamIdL(iFilesys,aFilename,aId,aFileOffset,aSessionHandle); + bmp->ConstructL(iMBMCache->MruFileStore(),streamid); + } + else + { + //only use the cache when it is Rom File which is read only because when using + //the cache the file store is always opened as read access until it is replaced by + //another different file, Trying to write it(RAM file) will cause access violation + //and therefore we have to split the implementation into two parts one for ROM + //and one for RAM + if (aFilename.Left(2).CompareF(KZDrive)) + { + // File is not in ROFS + bmp->ConstructL(*aFile,aId,aFileOffset); + } + else + { + // File is in ROFS + TStreamId streamid(0); + streamid=iMBMCache->GetStreamIdL(*aFile,aFilename,aId,aFileOffset,aSessionHandle); + + bmp->ConstructL(iMBMCache->MruFileStore(),streamid); + } + } + return bmp; + } + + +/* Similar to LoadBitmap. +This function only performs a load the first time it is called for a +particular bitmap. Subsequent calls increment a reference counting object. + +Upon return, aBmpObjPtr points to an object containing a pointer to the loaded bitmap. +*/ +CSharedBitmapObject* CFbTop::ShareBitmapL(TDes& aFilename, TInt32 aId, TUint aFileOffset, RFile* aFile, TInt aSessionHandle) + { + TTime modtime(0); + if (aFilename.Left(2).CompareF(KZDrive))// instead of Compare, CompareF is used to perform folding prior to Compare which is safe with Unicode. + { + // file is not in z: drive so it should not be null. + __ASSERT_DEBUG(aFile != NULL, User::Panic(KFBSERVPanicCategory, KErrBadHandle)); + // File is not in ROM so ModTime is needed to identify it + User::LeaveIfError(aFile->Modified(modtime)); + } + + // Creation of the key is performed here so that it can potentially be + // reused in both object lookup and object creation + HBufC* key = CSharedBitmapObject::KeyLC(aFilename, aId, modtime); + + // Calculation of the hash value is performed here so that it can + // potentially be reused in both object lookup and object insert. + const TUint hash = iSharedBitmapObjectHashMap.Hash(*key); + + CSharedBitmapObject* bmpObj = iSharedBitmapObjectHashMap.Lookup(*key, hash); + + if (bmpObj) + { + // Bitmap already in memory + CleanupStack::PopAndDestroy(key); // key will not be needed + User::LeaveIfError(bmpObj->Open()); // increase reference count + } + else + { + // Bitmap not in memory + CBitwiseBitmap* bmp = DoLoadBitmapLC(aFilename, aId, aFileOffset, aFile, aSessionHandle); + // bmp and key popped out of the clean-up stack by NewL + bmpObj = CSharedBitmapObject::NewL(*this, bmp, key, hash); + } + + return bmpObj; + } + +TInt CFbTop::GetCleanBitmap(CBitmapObject*& aBmpObjPtr) + { + while (aBmpObjPtr->CleanBitmap() != NULL) + { + aBmpObjPtr = aBmpObjPtr->CleanBitmap(); + } + if (aBmpObjPtr->IsInCompressionQueue()) + return KErrInUse; + return KErrNone; + } + +CBitmapObject* CFbTop::FindBitmap(TInt aHandle) + { + TInt index = iBitmapObjectIndex.FindInOrder(aHandle, CBitmapObject::Compare); + if (index != KErrNotFound) + return iBitmapObjectIndex[index]; + return NULL; + } + +TBool CFbTop::ValidFontHandle(TInt aHandle) + { + TInt limit=iFontCon->Count(); + for(TInt count=0;countCount(); + for(TInt count=0;count((*iFontCon)[count]); + if(aHandle==(TInt)(fontObjPtr->iAddressPointer)) + return(ETrue); + } + return(EFalse); + } + +CFontStore* CFbTop::FontStore() const + { + return(iFontStore); + } + +RHeap* CFbTop::Heap() const + { + return(iHeap); + } + +CChunkPile* CFbTop::Pile() const + { + return(iPile); + } + +TInt CFbTop::HeapBase() const + { + return(TInt(iChunk.Base())); + } + +void CFbTop::SetFontNameAliasL(const RMessage2& aMessage) + { + const TInt aliasNameLength = aMessage.Int1(); + if (aliasNameLength <= 0) + return; // No alias name to set + + if(aliasNameLength * sizeof(TText) * 2 >= KMaxTInt) + { + aMessage.Panic(KFBSERVPanicCategory,KErrArgument); + return; + } + + HBufC* aliasName = HBufC::NewMaxLC(aliasNameLength); + TPtr aliasNamePtr(aliasName->Des()); + aMessage.ReadL(0,aliasNamePtr); + + const TInt aliasIndex = FindFontNameAlias(*aliasName); + + const TInt fontNameLength = aMessage.Int3(); + + if (fontNameLength > 0) + { // Set or change an alias + HBufC* fontName = HBufC::NewMaxLC(fontNameLength); + TPtr fontNamePtr(fontName->Des()); + aMessage.ReadL(2,fontNamePtr); + + if (aliasIndex != KErrNotFound) + { // Change an existing alias + delete iFontNameAlias[aliasIndex + 1]; + iFontNameAlias[aliasIndex + 1] = fontName; + + CleanupStack::Pop(); // fontName + CleanupStack::PopAndDestroy(); // aliasName + } + else + { // Set a new alias + User::LeaveIfError(iFontNameAlias.Append(aliasName)); + TInt ret = iFontNameAlias.Append(fontName); + if (ret != KErrNone) + { + iFontNameAlias.Remove(iFontNameAlias.Count() - 1); + User::Leave(ret); + } + + CleanupStack::Pop(); // fontName + CleanupStack::Pop(); // aliasName + } + } + else + { // No fontName so delete the alias + CleanupStack::PopAndDestroy(); // aliasName + if (aliasIndex != KErrNotFound) + { + delete iFontNameAlias[aliasIndex]; + iFontNameAlias.Remove(aliasIndex); + delete iFontNameAlias[aliasIndex]; + iFontNameAlias.Remove(aliasIndex); + } + } + } + +TInt CFbTop::FindFontNameAlias(const TDesC& aAlias) + { + const TInt fontNameAliasCount = iFontNameAlias.Count(); + + for (TInt index = 0; index < fontNameAliasCount; index += 2) + { + if ((*iFontNameAlias[index]).CompareF(aAlias)==0) + { + return index; + } + } + + return KErrNotFound; + } + +void CFbTop::SetDefaultLanguageForMetrics(const RMessage2& aMessage) + { + iDefaultLanguageForMetrics = static_cast(aMessage.Int0()); + } + +void CFbTop::CloseFileStores(TInt aSessionHandle) + { + iMBMCache->CloseFileStores(aSessionHandle); + } + +void CFbTop::SetSystemDefaultTypefaceName(const TDesC& aFontTypefaceName) + { + iSystemDefaultFontTypefaceName = aFontTypefaceName; + } + +TInt CFbTop::GetAllBitmapHandles(const RMessage2& aMessage) const + { + TPckgBuf handleBuffer; // Use this buffer to store the bitmap handles to write to the message buffer + const TInt numBitmaps = iBitmapObjectIndex.Count(); + TInt ret = KErrNone; + for (TInt count=0; countHandle(); + ret = aMessage.Write(0, handleBuffer, KNumBytesPerBitmapHandle * count); + if (ret!=KErrNone) + break; + } + return ret; + } + +void CFbTop::AddClientHelper(TFbClientHelper& aHelper) + { + iClientHelpers.AddLast(aHelper); + } + +void CFbTop::NotifyDirtyBitmap(CBitmapObject& aBmpObj, CFbClient* aClient) + { + TDblQueIter iterator(iClientHelpers); + TFbClientHelper* helper; + while ((helper = iterator++) != NULL) + { + if (aClient != &helper->iClient) + helper->iClient.NotifyDirtyBitmap(aBmpObj); + } + } + +TInt CFbTop::BitmapConUniqueID() const + { + return iBitmapCon->UniqueID(); + } + +TInt CFbTop::FontConUniqueID() const + { + return iFontCon->UniqueID(); + }