fbs/fontandbitmapserver/sfbs/FBSCLI.CPP
branchRCL_3
changeset 163 bbf46f59e123
parent 150 57c618273d5c
child 164 25ffed67c7ef
--- a/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP	Thu Aug 19 11:11:18 2010 +0300
+++ b/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP	Tue Aug 31 16:31:06 2010 +0300
@@ -16,11 +16,13 @@
 #include <fntstore.h>
 #include <bitmap.h>
 #include <openfont.h>
-#include "fbsmessage.h"
+#include <graphics/fbsoogmmessage.h>
+#include "FbsMessage.H"
 #include "SERVER.H"
 #include "BackGroundCompression.h"
 #include <shapeinfo.h>
 #include <graphics/shaperparams.h>
+#include "glyphatlas.h"
 #include "OstTraceDefinitions.h"
 #include "fbstrace.h"
 #ifdef OST_TRACE_COMPILER_IN_USE
@@ -28,6 +30,12 @@
 #endif
 
 
+/**
+Bitwise mask that sets the MSB to indicate to a font rasterizer
+that a code is a glyphcode and not a character code
+*/
+const TUint32 KTreatAsGlyphCodeFlag = 1UL << 31;
+
 /** Helper function for converting a pointer to an offset from the passed
 heap base. Use OffsetToPointer() to convert the returned offset back to a
 useable pointer.
@@ -39,11 +47,12 @@
  */
 LOCAL_C TInt PointerToOffset(const TAny* aAny, TInt aHeapBase)
 	{
+	TInt offset = 0;
 	if (aAny && aHeapBase)
 		{
-		return reinterpret_cast<TInt>(aAny) - aHeapBase;
+		offset = reinterpret_cast<TInt>(aAny) - aHeapBase;
 		}
-	return 0;
+	return offset;
 	}
 
 /** Helper function for converting an offset (that was calculated using
@@ -64,9 +73,6 @@
 
 CFbClient::CFbClient(RHeap* aHeap):
 	CSession2(),
-	iConnectionHandle(0),
-	iIx(NULL),
-	iResourceCount(0),
 	iHeap(aHeap)
 #ifdef _DEBUG
 	,iOwnHeapFailNumber(-1),
@@ -77,14 +83,24 @@
 
 CFbClient* CFbClient::NewL(RHeap* aHeap)
 	{
-	CFbClient* c = new(ELeave) CFbClient(aHeap);
-	c->iOpenFontGlyphData = TOpenFontGlyphData::New(aHeap,4 * 1024);
-	if (!c->iOpenFontGlyphData)
+	CFbClient* self = new (ELeave) CFbClient(aHeap);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self;
+	return self;
+	}
+
+/**
+Two-phase constructor.
+@leave KErrNoMemory if TOpenFontGlyphData construction failed.
+*/
+void CFbClient::ConstructL()
+	{
+	iOpenFontGlyphData = TOpenFontGlyphData::New(iHeap, 4 * 1024);
+	if (!iOpenFontGlyphData)
 		{
-		delete c;
 		User::Leave(KErrNoMemory);
 		}
-	return c;
 	}
 
 CFbClient::~CFbClient()
@@ -101,30 +117,40 @@
 		}
 	
 	if (font_store)
+		{
 		font_store->DeleteSessionCache(iSessionHandle);
+		font_store->CleanupCacheOnFbsSessionTermination(iSessionHandle);
+		
+		// If the font store doesn't exist, neither will the shared heap owned by FBSERV.
+		iHeap->Free(iOpenFontGlyphData);
+		}
 	
-	// If the font store doesn't exist, neither will the shared heap owned by FBSERV.
-	if (font_store)
-		iHeap->Free(iOpenFontGlyphData);
-	
-	// delete fonts hold by the client
+	// delete fonts held by the client
 	delete iIx;
 	
-	// delete font files hold by the client
-    if (iFontFileIndex)
-        {
-        TInt count = iFontFileIndex->Count();
-        for (TInt index = 0;index < count; index++)
-            {
-            if (font_store)
-                font_store->RemoveFile(iFontFileIndex->At(0).iUid);
-            iFontFileIndex->Delete(0);
-            }
-        delete iFontFileIndex;
-        }
+	// delete font files held by the client
+	if (iFontFileIndex)
+		{
+		TInt count = iFontFileIndex->Count();
+		for (TInt index = 0;index < count; index++)
+			{
+			if (font_store)
+				{
+				font_store->RemoveFile(iFontFileIndex->At(0).iUid);
+				}
+			iFontFileIndex->Delete(0);
+			}
+		delete iFontFileIndex;
+		}
 
-	// Close the buffer used to hold the text thats needs shaping.
+	// Close the buffer used to hold the text that needs shaping.
 	iTextToShape.Close();
+
+	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
+		{
+		iGlyphImagesInTransit[i].Close();
+		}
+	iGlyphImagesInTransit.Close();
 	}
 
 void CFbClient::Init(TUint aConnectionHandle)
@@ -147,9 +173,13 @@
 	{
 	CFontBitmapServer* server = FontBitmapServer();
 	if (server)
+		{
 		return server->TopLevelStore();
+		}
 	else
+		{
 		return NULL;
+		}
 	}
 
 void CFbClient::CopyFontInfo(CFontObject* aFontObjPtr,TInt aHandle,TFontInfo& aFontInfo)
@@ -162,6 +192,7 @@
 
 void CFbClient::ServiceL(const RMessage2& aMessage)
 	{
+
 #ifdef _DEBUG
 	TBool resetOwnHeap=EFalse;
 	TBool resetSharedHeap=EFalse;
@@ -193,6 +224,14 @@
 		__RHEAP_MARK(iHeap);
 		}		
 #endif		
+	//Call close on RSgImage handles being used to share glyph data with clients.
+	//The glyph images are held open to prevent the GlyphAtlas from closing them
+	//before a client can use them.
+	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
+		{
+		iGlyphImagesInTransit[i].Close();
+		iGlyphImagesInTransit.Remove(i);
+		}
 	
 	switch(aMessage.Function())
 		{
@@ -251,6 +290,7 @@
 	case EFbsMessFetchLinkedTypeface:
 	case EFbsMessRegisterLinkedTypeface:
 	case EFbsMessUpdateLinkedTypeface:
+
 #ifdef _DEBUG
 		FontBitmapServer()->ProcMessage(aMessage,iSessionHandle,iRet);
 #else
@@ -275,9 +315,15 @@
 	case EFbsMessSetTwipsHeight:
 	case EFbsMessGetTwipsHeight:
 	case EFbsSetSystemDefaultTypefaceName:
+	case EFbsMessGetFontTable:
+	case EFbsMessReleaseFontTable:
+	case EFbsMessGetGlyphOutline:
+	case EFbsMessReleaseGlyphOutline: 
 #if (_DEBUG)
 	case EFbsMessSetDuplicateFail:
 #endif
+	case EFbsMessGetGlyphs:
+	case EFbsMessGetGlyphMetrics:
 		ProcFontMessage(aMessage);
 		break;
 // bitmap messages
@@ -306,6 +352,31 @@
 		aMessage.Complete(KErrNone);
 #endif	
 		break;
+// Glyph Atlas messages (debug-only)
+	case EFbsMessAtlasFontCount:
+	case EFbsMessAtlasGlyphCount:
+#ifdef _DEBUG
+		ProcAtlasMessage(aMessage);
+#else
+		aMessage.Complete(KErrNotSupported);
+#endif
+		break;
+    case EFbsMessOogmNotification:
+
+        aMessage.Complete( HandleMesgOogmStatus( aMessage ) );
+        break;
+    case EFbsMessGetGlyphCacheMetrics:
+
+        HandleMesgGlyphCacheMetrics( aMessage );
+        break;
+
+//No-op message
+	case EFbsMessNoOp:
+#ifdef _DEBUG
+		iRet = KErrNone;
+#endif
+		aMessage.Complete(KErrNone);
+		break;
 	default:
 		aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
 		break;
@@ -373,7 +444,9 @@
 	{
 #if _DEBUG
 	if (iFontDuplicateToFail)
+		{
 		return KErrNoMemory; //return with this error since this error is possible
+		}
 #endif
 	CFontObject* fontptr = (CFontObject*) aMessage.Int0();
 	if(!TopLevelStore()->ValidFontHandle((TInt)fontptr))
@@ -381,7 +454,7 @@
 		return KErrUnknown;
 		}
 
-	TPckgBuf<TFontInfo> foninfo;
+	TPckgBuf<TFontInfo> fontinfo;
 	TInt localhandle = 0;
 	TInt ret = fontptr->Open();
 	if (ret != KErrNone)
@@ -394,9 +467,9 @@
 		fontptr->Close();
 		return ret;
 		}
-	CopyFontInfo(fontptr,localhandle,foninfo());
+	CopyFontInfo(fontptr,localhandle,fontinfo());
 	fontptr->iHeightInTwips = ((fontptr->iAddressPointer->HeightInPixels() * fontptr->iFontStore->iKPixelHeightInTwips) + 667) / 1000;
-	ret = aMessage.Write(1, foninfo);
+	ret = aMessage.Write(1, fontinfo);
 	if(ret != KErrNone)
 		{
 		iIx->Remove(localhandle);
@@ -424,14 +497,14 @@
 	TInt pckgMaxHeight;
 	TPckgBuf<TSizeInfo> info;
 
-	const TFbsMessage	fbsMessage = static_cast<TFbsMessage>(aMessage.Function());
+	const TFbsMessage fbsMessage = static_cast<TFbsMessage>(aMessage.Function());
 
 	TInt ret = aMessage.Read(0, pckgFontSpec);
 	TFontSpec& fontSpec = pckgFontSpec();
 	if (ret == KErrNone )
 		{
 		TInt length = fontSpec.iTypeface.iName.Length();
-		if(length < 0 || length > TOpenFontFaceAttribBase::ENameLength)
+		if((length < 0) || (length > TOpenFontFaceAttribBase::ENameLength))
 			{
 			aPanicRequired = ETrue;
 			return KErrArgument;
@@ -647,6 +720,183 @@
 	return EFalse;
 	}
 
+/** Handler for EFbsMessGetGlyphs message.
+Reads a batch of up to KMaxGlyphBatchSize glyph codes, and on success returns
+the corresponding TGlyphImageInfo objects.
+ @param aMessage input parameters
+ @param aPanicRequired flag that is set if a client panic is required
+ @return KErrNone if successful, otherwise any system-wide error code.
+ */
+TInt CFbClient::HandleMesgGetGlyphs(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	CFbTop* fbtop = TopLevelStore();
+	// Previously requested glyphs were closed in ServiceL()
+	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
+	if (!glyphAtlas)
+		{
+		return KErrNotSupported;
+		}
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrBadHandle;
+		}
+
+	TUint glyphCodes[KMaxGlyphBatchSize];
+	TGlyphImageInfo glyphImageInfo[KMaxGlyphBatchSize];
+	TPckg<TUint[KMaxGlyphBatchSize]> glyphBatchPckg(glyphCodes);
+
+	TInt err = aMessage.Read(1, glyphBatchPckg);
+	if (err != KErrNone)
+		{
+		aPanicRequired = ETrue;
+		return err;
+		}
+	TInt glyphCodesCount = glyphBatchPckg.Length() / sizeof(TUint);
+	if (glyphCodesCount > KMaxGlyphBatchSize)
+		{
+		aPanicRequired = ETrue;
+		return KErrOverflow;
+		}
+
+	TInt glyphsProcessed = 0;
+	CBitmapFont* font = fontptr->iAddressPointer;
+	for (; (glyphsProcessed < glyphCodesCount); ++glyphsProcessed)
+		{
+		TUint32 glyphCode = glyphCodes[glyphsProcessed];
+		err = glyphAtlas->GetGlyph(*font, glyphCode, glyphImageInfo[glyphsProcessed]);
+		// Search for glyph in glyph atlas
+		if (KErrNone != err)
+			{
+			const TUint8* bitmapData = NULL;
+			TOpenFontCharMetrics metrics;
+			// search for glyph in font glyph cache and session cache.
+			if (!font->GetCharacterData(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, metrics, bitmapData))
+				{
+				// Rasterize the glyph
+				if(!font->Rasterize(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
+					{
+					err = KErrNoMemory;
+					break;
+					}
+				metrics = *(iOpenFontGlyphData->Metrics());
+				bitmapData = iOpenFontGlyphData->BitmapPointer();
+				}
+			CGlyphAtlas::TAddGlyphArgs args(bitmapData, glyphCode, metrics);
+			err = glyphAtlas->AddGlyph(*font, args, glyphImageInfo[glyphsProcessed]);
+			}
+		if ((err == KErrNone) && (glyphImageInfo[glyphsProcessed].iImageId != KSgNullDrawableId))
+			{
+			// To prevent other threads closing the glyph image in the glyph atlas 
+			// before client has had chance to open the drawable id, open a local
+			// handle to the glyph image for the session, which will be closed either
+			// next time a request is made or when EFbsMessCloseGlyphs is handled.
+			RSgImage glyphImage;
+			err = glyphImage.Open(glyphImageInfo[glyphsProcessed].iImageId);
+			if (err == KErrNone)
+				{
+				err = iGlyphImagesInTransit.Append(glyphImage);
+				}
+			}
+		// If an error occurred during this iteration, abort now before the glyphsProcessed
+		// counter is incremented, which would give one too many processed glyphs.
+		if (KErrNone != err)
+			{
+			break;
+			}
+		}
+
+	// Even if there was an error, if at least one glyph was processed successfully
+	// send that back to the client, and reset the error code.
+	if (glyphsProcessed > 0)
+		{
+		TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> glyphImageInfoPckg(glyphImageInfo);
+		glyphImageInfoPckg.SetLength(glyphsProcessed * sizeof(TGlyphImageInfo));
+		err = aMessage.Write(2, glyphImageInfoPckg);
+		if (err != KErrNone)
+			{
+			aPanicRequired = ETrue;
+			return err;
+			}
+		}
+	else
+		{
+		// No glyphs being returned, so an error code must be returned.
+		__ASSERT_DEBUG(err != KErrNone, User::Panic(KFBSERVPanicCategory, err));
+		}
+	return err;
+	}
+
+/**
+Handler for EFbsMessGetGlyphMetrics message.
+Reads an array of glyph codes, and returns the offset from the heap base for the 
+corresponding metrics object.
+@pre The glyph codes have already been searched client-side in the font glyph
+	cache and the session cache.
+@param aMessage input parameters
+@param aPanicRequired flag that is set if a client panic is required
+@return KErrNone if successful, otherwise any system-wide error code.
+ */
+TInt CFbClient::HandleMesgGetGlyphMetrics(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	CFbTop* fbtop = TopLevelStore();
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrBadHandle;
+		}
+	
+	TInt err = KErrNone;
+	TUint glyphCodes[KMaxMetricsBatchSize];
+	TPckg<TUint[KMaxMetricsBatchSize]> glyphBatchPckg(glyphCodes);
+	err = aMessage.Read(1, glyphBatchPckg);
+	if (err != KErrNone)
+		{
+		aPanicRequired = ETrue;
+		return err;
+		}
+	
+	TInt numGlyphCodes = glyphBatchPckg.Length() / sizeof(TUint);	
+	if (numGlyphCodes > KMaxMetricsBatchSize)
+		{
+		aPanicRequired = ETrue;
+		return KErrOverflow;
+		}
+	
+	CBitmapFont* font = fontptr->iAddressPointer;
+	const TInt heapbase = fbtop->HeapBase();
+
+	TInt glyphProcessed;
+	TInt glyphMetricsOffsets[KMaxMetricsBatchSize];
+	for (glyphProcessed = 0; (glyphProcessed < numGlyphCodes) && (err == KErrNone); ++glyphProcessed)
+		{
+		if (font->Rasterize(iSessionHandle, glyphCodes[glyphProcessed] | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
+			{
+			// Convert all pointers to be passed back to the client to offsets from
+			// the heap base so that they can be recreated client side relative to the
+			// client's heap base
+			glyphMetricsOffsets[glyphProcessed] = PointerToOffset(iOpenFontGlyphData->Metrics(), heapbase);
+			}
+		else
+			{
+			err = KErrNoMemory;
+			}
+		}
+
+	if (err == KErrNone)
+		{
+		TPckg<TInt[KMaxMetricsBatchSize]> glyphMetricsOffsetsPckg(glyphMetricsOffsets);
+		glyphMetricsOffsetsPckg.SetLength(glyphProcessed * sizeof(TInt));
+		err = aMessage.Write(2, glyphMetricsOffsetsPckg);
+		if (err != KErrNone)
+			{
+			aPanicRequired = ETrue;
+			}
+		}	
+	return err;
+	}
 
 /** Handler for EFbsMessFaceAttrib message
  @param aMessage Input and output parameters
@@ -664,21 +914,21 @@
 		}
 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 
+	TInt ret = EFalse;
 	TPckgBuf<TOpenFontFaceAttrib> package;
 	if ( (bitmapFont != NULL) && (bitmapFont->GetFaceAttrib(package())) )
 		{
-		TInt ret = aMessage.Write(1,package);
+		ret = aMessage.Write(1,package);
 		if (ret == KErrNone)
 			{
-			return ETrue;
+			ret = ETrue;
 			}
 		else
 			{
 			aPanicRequired = ETrue;
-			return ret;
 			}
 		}
-	return EFalse;
+	return ret;
 	}
 
 
@@ -720,7 +970,6 @@
 	{
 	TInt error = KErrNone;
 	TShapeHeader* shape = 0;
-	TPckgBuf<TShapeMessageParameters> sp;
 	if (aMessage.GetDesLength(2) != sizeof(TShapeMessageParameters))
 		{
 		aPanicRequired = ETrue;
@@ -734,7 +983,6 @@
 		aPanicRequired = ETrue;
 		return KErrArgument;
 		}
-	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 
 	TInt inputTextLength = aMessage.GetDesLength(1);
 	if (inputTextLength < 0)
@@ -747,7 +995,9 @@
 		{
 		iTextToShape.Zero();
 		if (iTextToShape.MaxLength() < inputTextLength)
+			{
 			error = iTextToShape.ReAlloc(inputTextLength);
+			}
 		}
 	if (error == KErrNone)
 		{
@@ -757,12 +1007,14 @@
 			aPanicRequired = ETrue;
 			return error;
 			}
+		TPckgBuf<TShapeMessageParameters> sp;
 		error = aMessage.Read(2, sp);
 		if (error != KErrNone)
 			{
 			aPanicRequired = ETrue;
 			return error;
 			}
+		CBitmapFont* bitmapFont = fontptr->iAddressPointer;
 		TRAP(error, shape = bitmapFont->ShapeTextL(iTextToShape, iSessionHandle, sp()) );
 		if (error == KErrNone)
 			{
@@ -801,10 +1053,225 @@
 	return KErrNone;
 	}
 
+TInt CFbClient::HandleMesgReleaseGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	TInt ret = KErrNone;
+	CFbTop* fbtop = TopLevelStore();
+	TPckgBuf<TFBSGlyphOutlineParam> params;
+	ret = aMessage.Read(0, params);
+	if (KErrNone != ret)
+		{
+		aPanicRequired = ETrue;
+		return ret;
+		}
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(params().iHandle, fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrArgument;
+		}
+	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
+
+	TInt count = params().iCount;
+	TUint *glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint));
+	if (NULL == glyphCodes)
+		{
+		return KErrNoMemory;
+		}
+	// copy the glyph codes out of the IPC buffer...
+	TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint));
+	ret = aMessage.Read(1, ptr);  
+
+	if (KErrNone == ret)
+		{
+		bitmapFont->ReleaseGlyphOutlines(count, glyphCodes,  
+				params().iHinted, iSessionHandle);
+		}
+	else 
+		{
+		aPanicRequired = ETrue;
+		}
+
+	User::Free(glyphCodes);
+	return ret;
+	}
+
+TInt CFbClient::HandleMesgGetGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired) 
+	{
+	TInt ret = KErrNone;
+	CFbTop* fbtop = TopLevelStore();
+	TPckgBuf<TFBSGlyphOutlineParam> params;
+	ret = aMessage.Read(0, params);
+	if (KErrNone != ret)
+		{
+		aPanicRequired = ETrue;
+		return ret;
+		}
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(params().iHandle, fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrArgument;
+		}
+	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
+
+	TInt count = params().iCount;
+	TUint* glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint));
+	if (NULL == glyphCodes)
+		{
+		return KErrNoMemory;
+		}
+	// copy the glyph codes out of the IPC buffer...
+	TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint));
+	ret = aMessage.Read(1, ptr);
+	if (KErrNone != ret)
+		{
+		User::Free(glyphCodes);
+		aPanicRequired = ETrue;
+		return ret;
+		}
+
+	TOffsetLen* offsetLens = 
+		(TOffsetLen *)User::Alloc(count * sizeof(TOffsetLen));
+	if (NULL == offsetLens)
+		{
+		User::Free(glyphCodes);
+		return KErrNoMemory;
+		}
+
+	TInt len = 0;
+	TAny* outline = NULL;
+	for (TInt i = 0; i < count; ++i)
+		{
+		bitmapFont->GetGlyphOutline(glyphCodes[i],  
+			params().iHinted, outline, len, iSessionHandle);
+		
+		offsetLens[i].iLen = len;
+		offsetLens[i].iOffset = PointerToOffset((outline), fbtop->HeapBase());
+		}
+	TPtr8 pkg2((TUint8 *)offsetLens, count * sizeof(TOffsetLen), 
+			count * sizeof(TOffsetLen));
+	ret = aMessage.Write(2, pkg2);
+	if (KErrNone != ret)
+		{
+		aPanicRequired = ETrue;
+		}
+
+	User::Free(glyphCodes);
+	User::Free(offsetLens);
+	return ret;  
+	}
+
+TInt CFbClient::HandleMesgReleaseFontTable(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	CFbTop* fbtop = TopLevelStore();
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrArgument;
+		}
+	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
+
+	TUint32 tag = aMessage.Int1();
+
+	bitmapFont->ReleaseFontTable(tag, iSessionHandle);
+
+	return KErrNone;
+	}
+
+TInt CFbClient::HandleMesgGetFontTable(const RMessage2& aMessage, TBool& aPanicRequired)
+	{
+	TInt ret = KErrNone;
+	CFbTop* fbtop = TopLevelStore();
+	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
+	if(!fontptr)
+		{
+		aPanicRequired = ETrue;
+		return KErrArgument;
+		}
+	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
+
+	TInt len = 0;
+	TAny* tablePtr = NULL;
+	ret = bitmapFont->GetFontTable((TUint32)aMessage.Int1(), tablePtr, len, iSessionHandle);
+
+	if (KErrNone == ret) 
+		{
+		TPckgBuf<TOffsetLen> params;
+		params().iLen = len;
+		params().iOffset = PointerToOffset(tablePtr, fbtop->HeapBase());
+		ret = aMessage.Write(2, params);
+		aPanicRequired = (KErrNone != ret);
+		}
+
+	return ret;
+	}
+
+
+/**
+ Called in response to the GoomMonitor framework's call into FbsOogmPlugin.
+ We wish to either free some GPU memory, or reinstate its normal usage.
+
+@param  aMessage The IPC message.
+@return KErrNone If the value contained in the TFbsOogmMessage enumeration member is meaningful and the glyph atlas is present.
+        KErrNotSupported if there is no glyph atlas.
+        KErrUnknown if the value contained in the TFbsOogmMessage enumeration member is not meaningful.
+ */
+TInt CFbClient::HandleMesgOogmStatus( const RMessage2& aMessage )
+    {
+    TInt ret = KErrNone;
+    CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
+
+    if ( NULL == glyphAtlas )
+        {
+        return KErrNotSupported;
+        }
+
+
+    TPckgBuf<TFbsOogmMessage> oogmMessage;
+    aMessage.Read( 0, oogmMessage );
+
+    switch( oogmMessage().iOogmNotification )
+        {
+    case TFbsOogmMessage::EFbsOogmNoAction:
+        break;
+
+    case TFbsOogmMessage::EFbsOogmLowNotification:
+        {
+        glyphAtlas->ReleaseGpuMemory( oogmMessage().iBytesToFree, oogmMessage().iFlags );
+        }
+         break;
+
+    case TFbsOogmMessage::EFbsOogmOkayNotification:
+        {
+        glyphAtlas->InstateGpuMemory( oogmMessage().iFlags );
+        }
+        break;
+
+    default:
+        ret = KErrUnknown;
+        break;
+        }
+
+    return ret;
+    }
+
+
+void CFbClient::HandleMesgGlyphCacheMetrics( const RMessage2& aMessage )
+    {
+    CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
+    TPckgBuf<TGlyphCacheMetrics>  metrics;
+
+    glyphAtlas->GetGlyphCacheMetrics( metrics() );
+
+    aMessage.Complete( aMessage.Write(0, metrics) );
+    }
+
 
 void CFbClient::ProcFontMessage(const RMessage2& aMessage)
 	{
-	TInt ret = KErrUnknown;
+	TInt ret = KErrNone;
 	TBool panicRequired = EFalse;
 
 	switch(aMessage.Function())
@@ -911,9 +1378,40 @@
 
 			break;
 			}
+		case EFbsMessGetFontTable:
+			{
+			ret = HandleMesgGetFontTable(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessGetGlyphOutline:
+			{
+			ret = HandleMesgGetGlyphOutline(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessReleaseGlyphOutline:
+			{
+			ret = HandleMesgReleaseGlyphOutline(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessReleaseFontTable:
+			{
+			ret = HandleMesgReleaseFontTable(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessGetGlyphs:
+			{
+			ret = HandleMesgGetGlyphs(aMessage, panicRequired);
+			break;
+			}
+		case EFbsMessGetGlyphMetrics:
+			{
+			ret = HandleMesgGetGlyphMetrics(aMessage, panicRequired);
+			break;
+			}
 
 #ifdef _DEBUG
 		case EFbsMessSetDuplicateFail:
+			{
 			TInt argument =aMessage.Int0();
 			if (argument)
 				{
@@ -925,7 +1423,10 @@
 				}
 			ret=KErrNone;
 			break;
+			}
 #endif
+		default:
+			ret = KErrUnknown;
 		}
 
 	// either have a result or an error code to panic the client with
@@ -949,7 +1450,7 @@
 	{
 	CBitmapObject* bmpptr=NULL;
 	TInt localhandle=0;
-	TInt ret=KErrUnknown;
+	TInt ret = KErrNone;
 	switch(aMessage.Function())
 		{
 	case EFbsMessBitmapCreate:
@@ -1115,14 +1616,18 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TSize newsize(aMessage.Int1(),aMessage.Int2());
  		const TBool compressedInRam = bmpptr->Address()->IsCompressedInRAM();  //It must be set before the resizing is done.
 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
 		CBitmapObject* newbmpptr = NULL;
 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(newsize, dispMode, KUidCFbsBitmapCreation, ETrue));
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
 		if (ret != KErrNone)
 			{
@@ -1157,7 +1662,9 @@
 			}
 		bmpptr->SetCleanBitmap(newbmpptr);
 		if (bmpptr->AccessCount() >= 2)
+			{
 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
+			}
 		iIx->Remove(localhandle);
 		TPckgBuf<TBmpHandles> handlebuffer;
 		handlebuffer().iHandle = newlocalhandle;
@@ -1186,7 +1693,9 @@
 		TopLevelStore()->GetCleanBitmap(bmpptr);
 		ret = bmpptr->Open();
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TPckgBuf<TBmpHandles> handlebuffer;
 		TRAP(ret,localhandle=iIx->AddL(bmpptr));
 		if(ret!=KErrNone)
@@ -1220,13 +1729,17 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		const TSize size = bmpptr->Address()->SizeInPixels();
 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
 		CBitmapObject* newbmpptr = NULL;
 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(size, dispMode, KUidCFbsBitmapCreation, ETrue));
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
 		if (ret != KErrNone)
 			{
@@ -1254,7 +1767,9 @@
 			}
 		bmpptr->SetCleanBitmap(newbmpptr);
 		if (bmpptr->AccessCount() >= 2)
+			{
 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
+			}
 		iIx->Remove(localhandle);
 		TPckgBuf<TBmpHandles> handlebuffer;
 		handlebuffer().iHandle = newlocalhandle;
@@ -1286,7 +1801,9 @@
 		if (ret != KErrNone)
 			{
 			if (!async)
+				{
 				ret = KErrNone;
+				}
 			break;
 			}
 		ret = bmpptr->Address()->CheckBackgroundCompressData();
@@ -1294,10 +1811,14 @@
 			{
 			ret = fbtop->BackgroundCompression()->AddToCompressionQueue(bmpptr, scheme, async ? &aMessage : NULL);
 			if (ret == KErrNone && async)
+				{
 				return; // do not complete the client's request - that will be done by the background compression thread
+				}
 			}
 		if (KErrAlreadyExists == ret)
+			{
 			ret = KErrNone;
+			}
 		break;
 		}
 	case EFbsMessBitmapClean:
@@ -1312,10 +1833,14 @@
 			}
 		ret = fbtop->GetCleanBitmap(bmpptr);
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		ret = bmpptr->Open();
 		if (ret != KErrNone)
+			{
 			break;
+			}
 		TInt cleanlocalhandle = 0;
 		TRAP(ret, cleanlocalhandle = iIx->AddL(bmpptr));
 		if (ret != KErrNone)
@@ -1366,17 +1891,19 @@
 			iHelper->iMessage = aMessage;
 			return; // do not complete the client's request yet - that will be done when a bitmap becomes dirty
 			}
-		ret = KErrNone;
 		iHelper->iDirty = EFalse;
 		}
 		break;
 	case EFbsMessBitmapCancelNotifyDirty:
 		{
 		if (iHelper != NULL && !iHelper->iMessage.IsNull())
+			{
 			iHelper->iMessage.Complete(KErrCancel);
-		ret = KErrNone;
+			}
 		}
 		break;
+	default:
+		ret = KErrUnknown;
 		}
 		
 	if(!aMessage.IsNull())
@@ -1452,7 +1979,9 @@
 	if (iHelper)
 		{
 		if (!iHelper->iMessage.IsNull())
+			{
 			iHelper->iMessage.Complete(KErrDisconnected);
+			}
 		iHelper->Deque();
 		delete iHelper;
 		iHelper = NULL;
@@ -1514,7 +2043,58 @@
 			break;
 		case EFbsMessHeap:
 			ret=(TInt)iHeap;
-			break;			
+			break;
+		default:
+			ret = KErrUnknown;
+		}
+	aMessage.Complete(ret);
+	iRet=ret;
+	}
+
+/**
+Processes messages associated with the Glyph Atlas.
+@param aMessage The message used to perform IPC to the client.
+ */
+void CFbClient::ProcAtlasMessage(const RMessage2 &aMessage)
+	{
+	TInt ret = KErrNone;
+	CFbTop* fbtop = TopLevelStore();
+	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
+	if (!glyphAtlas)
+		{
+		ret = KErrNotSupported;
+		}
+	else
+		{
+		switch(aMessage.Function())
+			{
+			case EFbsMessAtlasFontCount:
+				ret = glyphAtlas->FontCount();
+				break;
+			case EFbsMessAtlasGlyphCount:
+				{
+				TInt fontHandle = aMessage.Int0();
+				if (fontHandle != 0)
+					{
+					if (fbtop->ValidFontHandle(fontHandle))
+						{
+						CFontObject* fontptr = reinterpret_cast<CFontObject*>(fontHandle);
+						ret = glyphAtlas->GlyphCount(static_cast<CBitmapFont&>(*(fontptr->iAddressPointer)));
+						}
+					else
+						{
+						ret = KErrNotFound;
+						}
+					}
+				else
+					{
+					ret = glyphAtlas->GlyphCount();
+					}
+				}
+				break;
+			default:
+				ret = KErrUnknown;
+			}
 		}
 	aMessage.Complete(ret);
 	iRet=ret;