fbs/fontandbitmapserver/sfbs/SERVER.CPP
changeset 0 5d03bc08d59c
child 36 01a6848ebfd7
child 163 bbf46f59e123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/SERVER.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,591 @@
+// 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 <fntstore.h>
+#include <bitmap.h>
+#include "FBSVER.H"
+#include "SERVER.H"
+#include "BackGroundCompression.h"
+#include "linkedfonts.h"
+#include "BitwiseBitmap.inl"
+
+const TInt KFbsPriority = 0;
+
+// Setup security policies
+const TInt KRanges[] = 
+	{
+	0,
+	EFbsMessShutdown,
+	EFbsMessClose,
+	EFbsSetSystemDefaultTypefaceName,
+	EFbsGetAllBitmapHandles,
+	EFbsMessUnused1,
+	EFbsMessUnused2,
+	EFbsMessRegisterLinkedTypeface,
+	EFbsMessFetchLinkedTypeface,
+	EFbsMessUpdateLinkedTypeface,
+	};
+const TUint KRangeCount = sizeof(KRanges)/sizeof(TInt);
+const TUint8 KElementsIndex[KRangeCount] = 
+	{
+	0,
+	3, // For EFbsMessShutdown
+	0,
+	1, // For EFbsSetSystemDefaultTypefaceName
+	2, // For EFbsGetAllBitmapHandles
+	0, // ECapability_None for EFbsMessUnused1
+	0, // ECapability_None for EFbsMessUnused2 and beyond
+	1, // ECapabilityWriteDeviceData for EFbsMessRegisterLinkedTypeface
+	2, // ECapabilityReadDeviceData for EFbsMessFetchLinkedTypeface
+	1, // ECapabilityWriteDeviceData for EFbsMessUpdateLinkedTypeface
+	};
+const CPolicyServer::TPolicyElement KElements[] = 
+	{
+	{_INIT_SECURITY_POLICY_C1(ECapability_None), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_C1(ECapabilityReadDeviceData), CPolicyServer::EFailClient},
+	{_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient},	
+ 	};
+const CPolicyServer::TPolicy KFbsPolicy =
+	{
+	CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
+	KRangeCount,
+	KRanges,
+	KElementsIndex,
+	KElements,
+	};
+
+CFontBitmapServer::CFontBitmapServer():
+	CPolicyServer(KFbsPriority, KFbsPolicy),
+	iConnectionId(0),
+	iTopLevelStore(NULL)
+	{
+	}
+
+CFontBitmapServer::~CFontBitmapServer()
+	{
+	delete iTopLevelStore;
+	iTopLevelStore = NULL;	// so that CFBClient::~CFbClient can avoid using this pointer;
+							// it may be called inside CFontBitmapServer::~CFontBitmapServer
+	}
+
+CFontBitmapServer* CFontBitmapServer::NewL()
+	{
+	CFontBitmapServer* fbs=new(ELeave) CFontBitmapServer;
+	CleanupStack::PushL(fbs);
+	fbs->iTopLevelStore=CFbTop::NewL();
+	
+	// If fbserv data paging is configured as unpaged, automatically pin client descriptors 
+	if(!RProcess().DefaultDataPaged())
+		{
+		fbs->SetPinClientDescriptors(ETrue);
+		}
+
+	fbs->StartL(KFBSERVGlobalThreadName);
+	CleanupStack::Pop();
+	return(fbs);
+	}
+
+CFbTop* CFontBitmapServer::TopLevelStore()
+	{
+	return(iTopLevelStore);
+	}
+CSession2* CFontBitmapServer::NewSessionL(const TVersion& aVersion,const RMessage2& /*aMessage*/ ) const
+	{
+	TVersion v(KFbsMajorVersionNumber,KFbsMinorVersionNumber,KFbsBuildVersionNumber);
+	if(!User::QueryVersionSupported(v,aVersion))
+		User::Leave(KErrNotSupported);
+
+	CSession2* pSession2 = CFbClient::NewL(iTopLevelStore->Heap());
+	return pSession2;
+	}
+
+TInt CFontBitmapServer::Init()
+	{
+	return(iConnectionId++);
+	}
+
+
+TInt CFontBitmapServer::HandleMesgTypefaceSupport(const RMessage2& aMessage, TBool& aClientPanicRequired)
+	{
+	TTypefaceSupport tfi;
+	TPckgBuf<TTypefaceSupport> ttipckg(tfi);
+	TPckgBuf<TSize> pixelSize;
+	TInt index=aMessage.Int0();
+	TInt limit=iTopLevelStore->FontStore()->NumTypefaces();
+	if(index<0 || index>limit)
+		{
+		return KErrArgument;
+		}
+	TInt ret = aMessage.Read(2, pixelSize);
+	if (ret != KErrNone)
+		{
+		return ret;
+		}
+	iTopLevelStore->FontStore()->iKPixelHeightInTwips = pixelSize().iHeight;
+	iTopLevelStore->FontStore()->iKPixelWidthInTwips = pixelSize().iWidth;
+	iTopLevelStore->FontStore()->TypefaceSupport(ttipckg(),index);
+	ret = aMessage.Write(1,ttipckg);
+	if(ret!=KErrNone)
+		{
+		aClientPanicRequired = ETrue;
+		}
+	return ret;
+	}
+
+
+TInt CFontBitmapServer::HandleMesgFontHeight(const RMessage2& aMessage, TBool aInTwips)
+	{
+	TInt typefaceindex = aMessage.Int0();
+	TInt fontsize = aMessage.Int1();
+
+	if(typefaceindex < 0)
+		{
+		aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
+		return KErrArgument;
+		}
+	
+	// pixel size (used to be set in a separate call)
+	TPckgBuf<TSize> size;
+	TInt ret = aMessage.Read(2, size);
+	if (ret != KErrNone)
+		{
+		return ret;
+		}
+		
+	if(size().iHeight <=  0 || size().iWidth < 0)
+		{
+		aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
+		return KErrArgument;
+		}
+			
+	iTopLevelStore->FontStore()->iKPixelHeightInTwips = size().iHeight;
+	iTopLevelStore->FontStore()->iKPixelWidthInTwips = size().iWidth;
+	if (aInTwips)
+		{
+		return iTopLevelStore->FontStore()->FontHeightInTwips(typefaceindex,fontsize);
+		}
+	else
+		{
+		return iTopLevelStore->FontStore()->FontHeightInPixels(typefaceindex,fontsize);
+		}
+	}
+
+
+#ifdef _DEBUG
+//aRet is used in debug builds to allow the server to know if the call was successful.
+//On success there should be no panics from out of memory testing, since memory
+//may have been genuinely allocated.
+void CFontBitmapServer::ProcMessage(const RMessage2& aMessage, TInt aSession, TInt& aRet)
+#else
+void CFontBitmapServer::ProcMessage(const RMessage2& aMessage, TInt aSession)
+#endif
+	{
+	TInt ret=KErrNone;
+	TBool clientPanicRequired = EFalse;
+#ifdef _DEBUG
+	TInt num=0;
+#endif
+	switch (aMessage.Function())
+		{
+	case EFbsMessShutdown:
+		CActiveScheduler::Stop();
+		break;
+	case EFbsMessNumTypefaces:
+		ret=iTopLevelStore->FontStore()->NumTypefaces();
+		break;
+	case EFbsMessTypefaceSupport:
+		ret = HandleMesgTypefaceSupport(aMessage, clientPanicRequired);
+		break;
+
+	case EFbsMessFontHeightInTwips:
+		ret = HandleMesgFontHeight(aMessage, ETrue);
+		break;
+
+	case EFbsMessFontHeightInPixels:
+		ret = HandleMesgFontHeight(aMessage, EFalse);
+		break;
+
+	case EFbsMessSetPixelHeight:
+		iTopLevelStore->FontStore()->iKPixelWidthInTwips=aMessage.Int0();
+		iTopLevelStore->FontStore()->iKPixelHeightInTwips=aMessage.Int1();
+		break;
+#ifdef _DEBUG
+	case EFbsMessDefaultAllocFail:
+		num=aMessage.Int0();
+		if(num) __UHEAP_FAILNEXT(num);
+		else __UHEAP_RESET;
+		break;
+	case EFbsMessDefaultMark:
+		__UHEAP_MARK;
+		break;
+	case EFbsMessDefaultMarkEnd:
+		num=aMessage.Int0();
+		if(num) __UHEAP_MARKENDC(num);
+		else __UHEAP_MARKEND;
+		break;
+	case EFbsMessUserAllocFail:
+		num=aMessage.Int0();
+		if(num) __RHEAP_FAILNEXT(iTopLevelStore->Heap(),num);
+		else __RHEAP_RESET(iTopLevelStore->Heap());
+		break;
+	case EFbsMessUserMark:
+		__RHEAP_MARK(iTopLevelStore->Heap());
+		break;
+	case EFbsMessUserMarkEnd:
+		num=aMessage.Int0();
+		if(num) __RHEAP_MARKENDC(iTopLevelStore->Heap(),num);
+		else __RHEAP_MARKEND(iTopLevelStore->Heap());
+		break;
+#endif
+	case EFbsMessHeapCheck:
+		iTopLevelStore->Heap()->Check();
+		User::Heap().Check();
+		break;
+	case EFbsMessSetDefaultGlyphBitmapType:
+		iTopLevelStore->FontStore()->SetDefaultBitmapType((TGlyphBitmapType)aMessage.Int0());
+		break;
+	case EFbsMessGetDefaultGlyphBitmapType:
+		ret = iTopLevelStore->FontStore()->DefaultBitmapType();
+		break;
+	case EFbsMessFontNameAlias:
+		TRAP(ret, iTopLevelStore->SetFontNameAliasL(aMessage));
+		break;
+	case EFbsMessGetHeapSizes:
+		TRAP(ret, GetHeapSizesL(aMessage));
+		break;
+	case EFbsMessDefaultLanguageForMetrics:
+		iTopLevelStore->SetDefaultLanguageForMetrics(aMessage);
+		break;
+	case EFbsCompress:
+		iTopLevelStore->BackgroundCompression()->CompressAll();
+		break;
+	case EFbsMessRegisterLinkedTypeface:
+		{
+		TPckgBuf<TLinkedTypefaceSpecificationArgs> buf;
+		ret=aMessage.Read(0,buf);
+		if (ret==KErrNone)
+			{
+			//Id used by original font linking; now unused.
+			TInt id;
+			ret=iTopLevelStore->FontStore()->CreateLinkedTypeface(buf(),aSession,id);
+			}
+		}
+		break;
+	case EFbsMessFetchLinkedTypeface:
+			{
+			TBuf<KMaxTypefaceNameLength> name;
+			ret = aMessage.GetDesLength(0);
+				
+			if (ret < 0) 
+				break;
+				
+			if (ret > KMaxTypefaceNameLength)
+				{
+				clientPanicRequired = ETrue;
+				ret = KErrTooBig;
+				break;
+				}
+				
+			ret = aMessage.Read(0,name);
+	
+			TLinkedTypefaceSpecificationArgs spec;
+				
+			spec.iName = name;
+				
+			if (ret==KErrNone)
+				{
+				TRAP(ret, iTopLevelStore->FontStore()->GetLinkedTypefaceL(spec));
+	
+				if (ret == KErrNone)
+					{
+					TPckgBuf<TLinkedTypefaceSpecificationArgs> specArgs = spec;					
+					ret = aMessage.Write(2,specArgs);
+					}
+				}
+			}
+		break;
+		case EFbsMessUpdateLinkedTypeface:
+			{
+			TPckgBuf<TLinkedTypefaceSpecificationArgs> buf;
+			ret=aMessage.Read(0,buf);
+			if (ret==KErrNone)
+				{
+				TRAP(ret, iTopLevelStore->FontStore()->UpdateLinkedTypefaceL(buf()));
+				}
+			}
+		break;
+	}
+
+	if (clientPanicRequired)
+		{
+		aMessage.Panic(KFBSERVPanicCategory,ret);
+		}
+	else
+		{
+		if(!aMessage.IsNull())
+			{
+			aMessage.Complete(ret);
+			}		
+		}
+
+#ifdef _DEBUG
+	aRet=ret;
+#endif	
+	}
+
+/**
+Returns the current sizes of the FBServ default heap, the heap for large bitmaps, 
+and the heap for small bitmaps.
+
+Not supported in release builds.
+
+@internalComponent
+@test
+@param aMessage Encapsulates references to integers supplied by the caller, which will on return contain the sizes of the default heap, heap for small bitmaps, and heap for large bitmaps.
+@leave KErrNotSupported when used in release mode.
+*/
+#ifdef _DEBUG
+void CFontBitmapServer::GetHeapSizesL(const RMessage2& aMessage)
+	{
+	TPckgBuf<THeapSizes> data;
+	TInt defaultHeapSize;
+	TInt smallBmpHeapSize;		
+	TInt bigBmpHeapSize;		
+	
+	User::Heap().AllocSize(defaultHeapSize);
+	bigBmpHeapSize = iTopLevelStore->iLargeBitmapChunk.Size();
+	iTopLevelStore->Heap()->AllocSize(smallBmpHeapSize);
+	
+	data().iDefault = defaultHeapSize;
+	data().iBig = bigBmpHeapSize;
+	data().iSmall = smallBmpHeapSize;
+	
+	aMessage.WriteL(0, data);
+	}
+#else
+void CFontBitmapServer::GetHeapSizesL(const RMessage2&)
+	{
+	User::Leave(KErrNotSupported);	
+	}	
+#endif
+
+
+CFontObject::CFontObject(CFontStore* aFontStore):
+	CObject(),
+	iAddressPointer(NULL),
+	iFontStore(aFontStore)
+	{
+	}
+
+CFontObject::~CFontObject()
+	{
+	if (AccessCount()==1)
+		Dec();
+	iFontStore->ReleaseFont(iAddressPointer);
+	}
+
+// CBitmapObject constructor - takes ownership of aBmp
+CBitmapObject::CBitmapObject(CFbTop& aFbTop, CBitwiseBitmap* aBmp):
+	CObject(),
+	iFbTop(&aFbTop),
+	iAddressPointer(aBmp)
+	{
+	__ASSERT_DEBUG(iAddressPointer, User::Invariant());
+	}
+
+/** Second-phase constructor of reference counting objects for bitmaps.
+Adds the CBitmapObject to the bitmap object container and, if it is not a
+replacement for a dirty bitmap, assigns a server-wide handle to it and adds
+it to the server's bitmap index. When a replacement bitmap is attached to
+the corresponding dirty bitmap with a call to SetCleanBitmap(), then it is
+assigned the same server-wide handle as the bitmap to be replaced.
+
+@param aReplacement If ETrue the bitmap is being created as a replacement
+	for a bitmap being made dirty by a resize or compress operation.
+@internalComponent
+*/
+void CBitmapObject::ConstructL(TBool aReplacement)
+	{
+	iFbTop->iBitmapCon->AddL(this);
+	if (!aReplacement)
+		{
+		iHandle = reinterpret_cast<TInt>(this);
+		while (iFbTop->iBitmapObjectIndex.FindInOrder(this, Compare) != KErrNotFound)
+			++iHandle;
+		User::LeaveIfError(iFbTop->iBitmapObjectIndex.InsertInOrder(this, Compare));
+		}
+	}
+
+void CleanupBitmapObject(TAny* aPtr)
+	{
+	CBitmapObject* ptr = static_cast<CBitmapObject*>(aPtr);	
+	ptr->Close();
+	}
+
+/** Create a reference counting object for a new bitmap.
+
+@param aFbTop Reference to the CFbTop singleton.
+@param aBmp Bitmap to be attached to the new reference counting object.
+	The bitmap must have been pushed on the clean-up stack and it will be
+	popped out of the stack by this function. Ownership will be transferred
+	to the reference counting object.
+@param aReplacement If ETrue the bitmap is being created as a replacement
+	for a bitmap being made dirty by a resize or compress operation.
+@internalComponent
+*/
+CBitmapObject* CBitmapObject::NewL(CFbTop& aFbTop, CBitwiseBitmap* aBmp, TBool aReplacement)
+	{
+	CBitmapObject* bmpObj = new(ELeave) CBitmapObject(aFbTop, aBmp);
+	CleanupStack::Pop(aBmp); // aBmp is owned now by bmpObj
+	TCleanupItem bitmapObjectCleanupItem(CleanupBitmapObject, bmpObj);
+	CleanupStack::PushL(bitmapObjectCleanupItem);
+	bmpObj->ConstructL(aReplacement);
+	CleanupStack::Pop(bmpObj);
+	return bmpObj;
+	}
+
+CBitmapObject::~CBitmapObject()
+	{
+	iFbTop->BackgroundCompression()->RemoveFromCompressionQueue(this);
+	// the associated clean bitmap object cannot possibly be now in the background compression queue
+	if (iHandle)
+		{
+		if (Owner() == NULL)
+			{
+			TInt index = iFbTop->iBitmapObjectIndex.FindInOrder(this, Compare);
+			if (index != KErrNotFound)
+				{
+				if (iCleanBitmap)
+					iFbTop->iBitmapObjectIndex[index] = iCleanBitmap;
+				else
+					iFbTop->iBitmapObjectIndex.Remove(index);
+				}
+			}
+		if (iCleanBitmap != NULL)
+			{
+			iCleanBitmap->SetOwner(NULL);
+			iCleanBitmap->Close();
+			}
+		}
+	delete iAddressPointer;
+	}
+
+void CBitmapObject::SetCleanBitmap(CBitmapObject* aNewBmpObj)
+	{
+	__ASSERT_DEBUG(iHandle, User::Invariant());
+	__ASSERT_DEBUG(iCleanBitmap == NULL, User::Invariant());
+	__ASSERT_DEBUG(aNewBmpObj->Owner() == NULL, User::Invariant());
+	__ASSERT_DEBUG(aNewBmpObj->iHandle == 0, User::Invariant());
+	__ASSERT_DEBUG(aNewBmpObj->iCleanBitmap == NULL, User::Invariant());
+	iCleanBitmap = aNewBmpObj;
+	aNewBmpObj->SetOwner(this);
+	aNewBmpObj->iHandle = iHandle;
+	iAddressPointer->iSettings.SetDirtyBitmap();
+	aNewBmpObj->iAddressPointer->Extra()->iSerialNumber = iAddressPointer->Extra()->iSerialNumber;
+	aNewBmpObj->iAddressPointer->Extra()->iTouchCount = iAddressPointer->Extra()->iTouchCount + 1;
+	}
+
+void CBitmapObject::Close()
+	{
+	if (iCleanBitmap != NULL && Owner() != NULL && AccessCount() == 2)
+		{
+		static_cast<CBitmapObject*>(Owner())->iCleanBitmap = iCleanBitmap;
+		iCleanBitmap->SetOwner(Owner());
+		iHandle = 0;
+		Dec();
+		}
+	CObject::Close();
+	}
+
+TInt CBitmapObject::Compare(const CBitmapObject& aBmpObj1, const CBitmapObject& aBmpObj2)
+	{
+	return aBmpObj1.iHandle - aBmpObj2.iHandle;
+	}
+
+TInt CBitmapObject::Compare(const TInt* aHandle, const CBitmapObject& aBmpObj)
+	{
+	return *aHandle - aBmpObj.iHandle;
+	}
+
+// CSharedBitmapObject constructor - takes ownership of aBmp and aKey
+CSharedBitmapObject::CSharedBitmapObject(CFbTop& aFbTop, CBitwiseBitmap* aBmp, TDesC* aKey):
+	CBitmapObject(aFbTop, aBmp),
+	iKey(aKey),
+	iNext(NULL)
+	{
+	__ASSERT_DEBUG(iKey, User::Invariant());	
+	}
+
+/** Second-phase constructor of reference counting objects for bitmaps
+loaded to share from a file. Adds the CSharedBitmapObject to the bitmap
+object container, assigns a server-wide handle to it and adds it to the
+server's bitmap index and to the server's shared bitmap hash map.
+
+@param aHash Hash value of the key associated with the bitmap.
+@internalComponent
+*/
+void CSharedBitmapObject::ConstructL(TUint aHash)
+	{
+	CBitmapObject::ConstructL(EFalse);
+	iFbTop->iSharedBitmapObjectHashMap.Insert(*this, aHash);
+	}
+
+/** Create a reference counting object for a bitmap loaded to share from a file.
+
+@param aFbTop Reference to the CFbTop singleton.
+@param aBmp Bitmap to be attached to the new reference counting object.
+	The bitmap must have been pushed on the clean-up stack and it will be
+	popped out of the stack by this function. Ownership will be transferred
+	to the reference counting object.
+@param aKey Key associated with the bitmap. The key must have been pushed on
+	the clean-up stack and it will be popped out of the stack by this function.
+	Ownership will be transferred to the reference counting object.
+@param aHash Hash value of the key associated with the bitmap.
+@internalComponent
+*/
+CSharedBitmapObject* CSharedBitmapObject::NewL(CFbTop& aFbTop, CBitwiseBitmap* aBmp, TDesC* aKey, TUint aHash)
+	{
+	CSharedBitmapObject* bmpObj = new(ELeave) CSharedBitmapObject(aFbTop, aBmp, aKey);
+	CleanupStack::Pop(2, aKey); // aBmp and aKey are owned now by bmpObj
+	TCleanupItem bitmapObjectCleanupItem(CleanupBitmapObject, bmpObj);
+	CleanupStack::PushL(bitmapObjectCleanupItem);
+	bmpObj->ConstructL(aHash);
+	CleanupStack::Pop(bmpObj);
+	return bmpObj;
+	}
+
+CSharedBitmapObject::~CSharedBitmapObject()
+	{
+	iFbTop->iSharedBitmapObjectHashMap.Remove(*this);
+	delete iKey;
+	}
+
+// Constructs a single key object from constituent parts that uniquely identify a bitmap
+HBufC* CSharedBitmapObject::KeyLC(const TDesC& aFileName, TInt aId, const TTime& aModTime)
+	{
+	static const TInt K16BitSizeOfTInt  = sizeof(TInt) /sizeof(TUint16);
+	static const TInt K16BitSizeOfTTime = sizeof(TTime)/sizeof(TUint16);
+	
+	HBufC* key = HBufC::NewLC(K16BitSizeOfTInt + K16BitSizeOfTTime + aFileName.Length());
+	
+	TPtr keyPtr = key->Des();
+	
+	keyPtr.Append(reinterpret_cast<const TUint16*>(&aId),      K16BitSizeOfTInt);
+	keyPtr.Append(reinterpret_cast<const TUint16*>(&aModTime), K16BitSizeOfTTime);
+	keyPtr.Append(aFileName);
+
+	return key;
+	}