os/graphics/fbs/fontandbitmapserver/sfbs/FBSCLI.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1995-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include <fntstore.h>
    17 #include <bitmap.h>
    18 #include <openfont.h>
    19 #include <graphics/fbsoogmmessage.h>
    20 #include "FbsMessage.H"
    21 #include "SERVER.H"
    22 #include "BackGroundCompression.h"
    23 #include <shapeinfo.h>
    24 #include <graphics/shaperparams.h>
    25 #include "glyphatlas.h"
    26 #include "OstTraceDefinitions.h"
    27 #include "fbstrace.h"
    28 #ifdef OST_TRACE_COMPILER_IN_USE
    29 #include "FBSCLITraces.h"
    30 #endif
    31 
    32 
    33 /**
    34 Bitwise mask that sets the MSB to indicate to a font rasterizer
    35 that a code is a glyphcode and not a character code
    36 */
    37 const TUint32 KTreatAsGlyphCodeFlag = 1UL << 31;
    38 
    39 /** Helper function for converting a pointer to an offset from the passed
    40 heap base. Use OffsetToPointer() to convert the returned offset back to a
    41 useable pointer.
    42 @param aAny A pointer to be converted to an offset.
    43 @param aHeapBase The heap base of the current process.
    44 @return An offset representing the passed pointer that can be converted
    45 back to a pointer using the function OffsetToPointer(). 
    46 @see OffsetToPointer()
    47  */
    48 LOCAL_C TInt PointerToOffset(const TAny* aAny, TInt aHeapBase)
    49 	{
    50 	TInt offset = 0;
    51 	if (aAny && aHeapBase)
    52 		{
    53 		offset = reinterpret_cast<TInt>(aAny) - aHeapBase;
    54 		}
    55 	return offset;
    56 	}
    57 
    58 /** Helper function for converting an offset (that was calculated using
    59 PointerToOffset()) back to a pointer relative to the passed heap base.
    60 @param aOffset The offset to be converted to a pointer.
    61 @param aHeapBase The heap base of the current process.
    62 @return A pointer relative to the passed heap base.
    63 @see PointerToOffset()
    64  */
    65 LOCAL_C TAny* OffsetToPointer(TInt aOffset, TInt aHeapBase)
    66 	{
    67 	if (aOffset && aHeapBase)
    68 		{
    69 		return reinterpret_cast<TAny*>(aOffset + aHeapBase);
    70 		}
    71 	return NULL;
    72 	}
    73 
    74 CFbClient::CFbClient(RHeap* aHeap):
    75 	CSession2(),
    76 	iHeap(aHeap)
    77 #ifdef _DEBUG
    78 	,iOwnHeapFailNumber(-1),
    79 	iSharedHeapFailNumber(-1)
    80 #endif	
    81 	{
    82 	}
    83 
    84 CFbClient* CFbClient::NewL(RHeap* aHeap)
    85 	{
    86 	CFbClient* self = new (ELeave) CFbClient(aHeap);
    87 	CleanupStack::PushL(self);
    88 	self->ConstructL();
    89 	CleanupStack::Pop(); // self;
    90 	return self;
    91 	}
    92 
    93 /**
    94 Two-phase constructor.
    95 @leave KErrNoMemory if TOpenFontGlyphData construction failed.
    96 */
    97 void CFbClient::ConstructL()
    98 	{
    99 	iOpenFontGlyphData = TOpenFontGlyphData::New(iHeap, 4 * 1024);
   100 	if (!iOpenFontGlyphData)
   101 		{
   102 		User::Leave(KErrNoMemory);
   103 		}
   104 	}
   105 
   106 CFbClient::~CFbClient()
   107 	{
   108 	/*
   109 	Don't call any CFontStore functions if CFbClient::NewL has left, or if FBSERV has already deleted the
   110 	font store, which happens in test programs like TFBS when FBSERV is closed before the client(s).
   111 	*/
   112 	CFontStore* font_store = NULL;
   113 	CFbTop* fbTop = TopLevelStore();
   114 	if (fbTop)
   115 		{
   116 		font_store = fbTop->FontStore();
   117 		}
   118 	
   119 	if (font_store)
   120 		{
   121 		font_store->DeleteSessionCache(iSessionHandle);
   122 		font_store->CleanupCacheOnFbsSessionTermination(iSessionHandle);
   123 		
   124 		// If the font store doesn't exist, neither will the shared heap owned by FBSERV.
   125 		iHeap->Free(iOpenFontGlyphData);
   126 		}
   127 	
   128 	// delete fonts held by the client
   129 	delete iIx;
   130 	
   131 	// delete font files held by the client
   132 	if (iFontFileIndex)
   133 		{
   134 		TInt count = iFontFileIndex->Count();
   135 		for (TInt index = 0;index < count; index++)
   136 			{
   137 			if (font_store)
   138 				{
   139 				font_store->RemoveFile(iFontFileIndex->At(0).iUid);
   140 				}
   141 			iFontFileIndex->Delete(0);
   142 			}
   143 		delete iFontFileIndex;
   144 		}
   145 
   146 	// Close the buffer used to hold the text that needs shaping.
   147 	iTextToShape.Close();
   148 
   149 	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
   150 		{
   151 		iGlyphImagesInTransit[i].Close();
   152 		}
   153 	iGlyphImagesInTransit.Close();
   154 	}
   155 
   156 void CFbClient::Init(TUint aConnectionHandle)
   157 	{
   158 	iConnectionHandle=aConnectionHandle;
   159 	}
   160 
   161 void CFbClient::CreateL()
   162 	{
   163 	iIx=CObjectIx::NewL();
   164 	iFontFileIndex=new(ELeave) CArrayFixFlat<TFontFileIndex>(1);
   165 	}
   166 
   167 CFontBitmapServer* CFbClient::FontBitmapServer()
   168 	{
   169 	return((CFontBitmapServer*)Server());
   170 	}
   171 
   172 CFbTop* CFbClient::TopLevelStore()
   173 	{
   174 	CFontBitmapServer* server = FontBitmapServer();
   175 	if (server)
   176 		{
   177 		return server->TopLevelStore();
   178 		}
   179 	else
   180 		{
   181 		return NULL;
   182 		}
   183 	}
   184 
   185 void CFbClient::CopyFontInfo(CFontObject* aFontObjPtr,TInt aHandle,TFontInfo& aFontInfo)
   186 	{
   187 	CBitmapFont* font=aFontObjPtr->iAddressPointer;
   188 	aFontInfo.iHandle = aHandle;
   189 	aFontInfo.iServerHandle=(TInt)aFontObjPtr;
   190 	aFontInfo.iAddressOffset=TInt(font)-TopLevelStore()->HeapBase();
   191 	}
   192 
   193 void CFbClient::ServiceL(const RMessage2& aMessage)
   194 	{
   195 
   196 #ifdef _DEBUG
   197 	TBool resetOwnHeap=EFalse;
   198 	TBool resetSharedHeap=EFalse;
   199 	
   200 	//the memory tests have been mostly written to have start and end memory
   201 	//function calls (or macros) at the start of this function call (ServiceL)
   202 	//and the matching call (or macro) is at the end of this function.
   203 	
   204 	if (iOwnHeapFailNumber!=-1)
   205 		{
   206 		//if this not -1 then know to set the heap to fail on
   207 		//the given number of allocations
   208 		
   209 		resetOwnHeap=ETrue;
   210 		__UHEAP_SETFAIL(RHeap::EDeterministic,iOwnHeapFailNumber);
   211 		}
   212 	if (iSharedHeapFailNumber!=-1)
   213 		{
   214 		resetSharedHeap=ETrue;
   215 		__RHEAP_SETFAIL (iHeap, RHeap::EDeterministic,iSharedHeapFailNumber);
   216 		}	
   217 
   218 	if (iOwnHeapCheck)
   219 		{
   220 		__UHEAP_MARK;
   221 		}					
   222 	if (iHeapCheck)
   223 		{
   224 		__RHEAP_MARK(iHeap);
   225 		}		
   226 #endif		
   227 	//Call close on RSgImage handles being used to share glyph data with clients.
   228 	//The glyph images are held open to prevent the GlyphAtlas from closing them
   229 	//before a client can use them.
   230 	for (TInt i = iGlyphImagesInTransit.Count() - 1; i >= 0; --i)
   231 		{
   232 		iGlyphImagesInTransit[i].Close();
   233 		iGlyphImagesInTransit.Remove(i);
   234 		}
   235 	
   236 	switch(aMessage.Function())
   237 		{
   238 // client messages
   239 	case EFbsMessInit:
   240 		Init(FontBitmapServer()->Init());
   241 		iSessionHandle = (TInt)this;
   242 		aMessage.Complete(iSessionHandle);
   243 #ifdef _DEBUG
   244 		iRet=KErrNone;
   245 #endif		
   246 		break;
   247 	case EFbsMessClose:
   248 		{
   249 		TInt localhandle=aMessage.Int0();
   250 		if(!iIx->At(localhandle))
   251 			{
   252 			aMessage.Panic(KFBSERVPanicCategory,KErrNotFound);
   253 			break;
   254 			}
   255 		iIx->Remove(localhandle);
   256 		iResourceCount--;
   257 		aMessage.Complete(KErrNone);
   258 		FBS_OST(OstTraceExt3( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_SERVICEL_INFO, "# Server resource destroyed; iSSH=0x%08x; rc=%d; iH=0x%08x;", iSessionHandle, iResourceCount, localhandle);)
   259 #ifdef _DEBUG
   260 		iRet=KErrNone;
   261 #endif				
   262 		break;
   263 		}
   264 	case EFbsMessResourceCount:
   265 		aMessage.Complete(iResourceCount);
   266 #ifdef _DEBUG
   267 		iRet=iResourceCount;
   268 #endif			
   269 		break;
   270 // server messages
   271 	case EFbsMessShutdown:
   272 	case EFbsMessNumTypefaces:
   273 	case EFbsMessTypefaceSupport:
   274 	case EFbsMessFontHeightInTwips:
   275 	case EFbsMessFontHeightInPixels:
   276 	case EFbsMessSetPixelHeight:
   277 	case EFbsMessDefaultAllocFail:
   278 	case EFbsMessDefaultMark:
   279 	case EFbsMessDefaultMarkEnd:
   280 	case EFbsMessUserAllocFail:
   281 	case EFbsMessUserMark:
   282 	case EFbsMessUserMarkEnd:
   283 	case EFbsMessHeapCheck:
   284 	case EFbsMessSetDefaultGlyphBitmapType:
   285 	case EFbsMessGetDefaultGlyphBitmapType:
   286 	case EFbsMessFontNameAlias:
   287 	case EFbsMessGetHeapSizes:
   288 	case EFbsMessDefaultLanguageForMetrics:
   289 	case EFbsCompress:
   290 	case EFbsMessFetchLinkedTypeface:
   291 	case EFbsMessRegisterLinkedTypeface:
   292 	case EFbsMessUpdateLinkedTypeface:
   293 
   294 #ifdef _DEBUG
   295 		FontBitmapServer()->ProcMessage(aMessage,iSessionHandle,iRet);
   296 #else
   297 		FontBitmapServer()->ProcMessage(aMessage,iSessionHandle);
   298 #endif			
   299 		break;
   300 // font messages
   301 	case EFbsMessFontDuplicate:
   302 	case EFbsMessGetNearestFontToDesignHeightInTwips:
   303 	case EFbsMessGetNearestFontToDesignHeightInPixels:
   304 	case EFbsMessGetNearestFontToMaxHeightInTwips:
   305 	case EFbsMessGetNearestFontToMaxHeightInPixels:
   306 	case EFbsMessGetFontById:
   307 	case EFbsMessInstallFontStoreFile:
   308 	case EFbsMessAddFontStoreFile:
   309 	case EFbsMessRemoveFontStoreFile:
   310 	case EFbsMessRasterize:
   311 	case EFbsMessFaceAttrib:
   312 	case EFbsMessHasCharacter:
   313 	case EFbsMessShapeText:
   314 	case EFbsMessShapeDelete:
   315 	case EFbsMessSetTwipsHeight:
   316 	case EFbsMessGetTwipsHeight:
   317 	case EFbsSetSystemDefaultTypefaceName:
   318 	case EFbsMessGetFontTable:
   319 	case EFbsMessReleaseFontTable:
   320 	case EFbsMessGetGlyphOutline:
   321 	case EFbsMessReleaseGlyphOutline: 
   322 #if (_DEBUG)
   323 	case EFbsMessSetDuplicateFail:
   324 #endif
   325 	case EFbsMessGetGlyphs:
   326 	case EFbsMessGetGlyphMetrics:
   327 		ProcFontMessage(aMessage);
   328 		break;
   329 // bitmap messages
   330 	case EFbsMessBitmapCreate:
   331 	case EFbsMessBitmapResize:
   332 	case EFbsMessBitmapDuplicate:
   333 	case EFbsMessBitmapLoad:
   334 	case EFbsMessBitmapCompress:
   335 	case EFbsMessBitmapBgCompress:
   336 	case EFbsMessBitmapClean:
   337 	case EFbsGetAllBitmapHandles:
   338 	case EFbsMessBitmapLoadFast:
   339 	case EFbsMessBitmapNotifyDirty:
   340 	case EFbsMessBitmapCancelNotifyDirty:
   341 		ProcBitmapMessage(aMessage);
   342 		break;
   343 //Memory messages		
   344 	case EFbsMessSetHeapFail:
   345 	case EFbsMessHeapCount:
   346 	case EFbsMessSetHeapReset:
   347 	case EFbsMessSetHeapCheck:
   348 	case EFbsMessHeap:
   349 #ifdef _DEBUG	
   350 		ProcMemMessage(aMessage);
   351 #else
   352 		aMessage.Complete(KErrNone);
   353 #endif	
   354 		break;
   355 // Glyph Atlas messages (debug-only)
   356 	case EFbsMessAtlasFontCount:
   357 	case EFbsMessAtlasGlyphCount:
   358 #ifdef _DEBUG
   359 		ProcAtlasMessage(aMessage);
   360 #else
   361 		aMessage.Complete(KErrNotSupported);
   362 #endif
   363 		break;
   364     case EFbsMessOogmNotification:
   365 
   366         aMessage.Complete( HandleMesgOogmStatus( aMessage ) );
   367         break;
   368     case EFbsMessGetGlyphCacheMetrics:
   369 
   370         HandleMesgGlyphCacheMetrics( aMessage );
   371         break;
   372 
   373 //No-op message
   374 	case EFbsMessNoOp:
   375 #ifdef _DEBUG
   376 		iRet = KErrNone;
   377 #endif
   378 		aMessage.Complete(KErrNone);
   379 		break;
   380 	default:
   381 		aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
   382 		break;
   383 		}
   384 #ifdef _DEBUG
   385 
   386 	//do not want a memory panic if the return code is OK
   387 	//__UHEAP_MARKEND does this
   388 	
   389 	if (iOwnHeapCheck)
   390 		{
   391 		TUint32 badCell=User::Heap().__DbgMarkEnd(0);
   392 		if (iRet<0)
   393 			{
   394 			//if the function call was a success, there may have been valid memory allocations,
   395 			//so only panic if the call failed, and the memory is not the same before and after the
   396 			//function call
   397 			__ASSERT_DEBUG (badCell==NULL,User::Panic(KFBSERVPanicCategory, KErrGeneral));
   398 			}
   399 		}					
   400 	if (iHeapCheck)
   401 		{
   402 		TUint32 badCell2=0;
   403 		badCell2= __RHEAP_MARKEND(iHeap);
   404 		//the above function call does not panic if there is a failure, this is
   405 		//only for the user heap
   406 		if (iRet<0)
   407 			{
   408 			__ASSERT_DEBUG (badCell2==NULL,User::Panic(KFBSERVPanicCategory, KErrGeneral));
   409 			}
   410 		}
   411 	//change the state of the memory check?	
   412 	if (iOwnHeapCheckFlip)
   413 		{
   414 		//change the state of the memory testing
   415 		//if the mark was set still need to have a mark end
   416 		iOwnHeapCheckFlip=EFalse;
   417 		iOwnHeapCheck=!iOwnHeapCheck;
   418 		}
   419 	if (iHeapCheckFlip)
   420 		{
   421 		iHeapCheckFlip=EFalse;
   422 		iHeapCheck=!iHeapCheck;
   423 		}
   424 		
   425 	if (resetOwnHeap)
   426 		{
   427 		//previously set failures, reset
   428 		__UHEAP_RESET;
   429 		}
   430 	if (resetSharedHeap)
   431 		{		
   432 		__RHEAP_RESET (iHeap);
   433 		}		
   434 #endif		
   435 	}
   436 
   437 
   438 /** Handler for EFbsMessFontDuplicate message
   439  @param aMessage input parameters
   440  @param aPanicRequired flag that is set if a client panic is required
   441  @return KErrNone if successful, otherwise a system wide error code
   442  */
   443 TInt CFbClient::HandleMesgFontDuplicate(const RMessage2& aMessage, TBool& aPanicRequired)
   444 	{
   445 #if _DEBUG
   446 	if (iFontDuplicateToFail)
   447 		{
   448 		return KErrNoMemory; //return with this error since this error is possible
   449 		}
   450 #endif
   451 	CFontObject* fontptr = (CFontObject*) aMessage.Int0();
   452 	if(!TopLevelStore()->ValidFontHandle((TInt)fontptr))
   453 		{
   454 		return KErrUnknown;
   455 		}
   456 
   457 	TPckgBuf<TFontInfo> fontinfo;
   458 	TInt localhandle = 0;
   459 	TInt ret = fontptr->Open();
   460 	if (ret != KErrNone)
   461 		{
   462 		return ret;
   463 		}
   464 	TRAP(ret, localhandle=iIx->AddL(fontptr));
   465 	if (ret != KErrNone)
   466 		{
   467 		fontptr->Close();
   468 		return ret;
   469 		}
   470 	CopyFontInfo(fontptr,localhandle,fontinfo());
   471 	fontptr->iHeightInTwips = ((fontptr->iAddressPointer->HeightInPixels() * fontptr->iFontStore->iKPixelHeightInTwips) + 667) / 1000;
   472 	ret = aMessage.Write(1, fontinfo);
   473 	if(ret != KErrNone)
   474 		{
   475 		iIx->Remove(localhandle);
   476 		aPanicRequired = ETrue;
   477 		return ret;
   478 		}
   479 
   480 	// success
   481 	iResourceCount++;
   482     FBS_OST(OstTraceExt3( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_HANDLEMESGFONTDUPLICATE_INFO, "# Server font duplicated; iSSH=0x%08x; rc=%d; iH=0x%08x;", iSessionHandle, iResourceCount, localhandle);)
   483 	return KErrNone;
   484 	}
   485 
   486 
   487 /** Handler for EFbsMessGetNearestFontToDesignHeightInTwips, EFbsMessGetNearestFontToDesignHeightInPixels, 
   488  EFbsMessGetNearestFontToMaxHeightInTwips or EFbsMessGetNearestFontToMaxHeightInPixels messages
   489  @param aMessage input and output parameters
   490  @param aPanicRequired flag that is set if a client panic is required
   491  @return KErrNone if successful, otherwise a system wide error code
   492  */
   493 TInt CFbClient::HandleMesgGetNearestFont(const RMessage2& aMessage, TBool& aPanicRequired)
   494 	{
   495 	CFontObject* fontptr = NULL;
   496 	TPckgBuf<TFontSpec> pckgFontSpec;
   497 	TInt pckgMaxHeight;
   498 	TPckgBuf<TSizeInfo> info;
   499 
   500 	const TFbsMessage fbsMessage = static_cast<TFbsMessage>(aMessage.Function());
   501 
   502 	TInt ret = aMessage.Read(0, pckgFontSpec);
   503 	TFontSpec& fontSpec = pckgFontSpec();
   504 	if (ret == KErrNone )
   505 		{
   506 		TInt length = fontSpec.iTypeface.iName.Length();
   507 		if((length < 0) || (length > TOpenFontFaceAttribBase::ENameLength))
   508 			{
   509 			aPanicRequired = ETrue;
   510 			return KErrArgument;
   511 			}	
   512 		
   513 		ret = aMessage.Read(2, info);
   514 		if (ret == KErrNone)
   515 			{
   516 			pckgMaxHeight = info().iMaxHeight;
   517 			TopLevelStore()->FontStore()->iKPixelHeightInTwips=info().iDevSize.iHeight;
   518 			TopLevelStore()->FontStore()->iKPixelWidthInTwips=info().iDevSize.iWidth;
   519 			}
   520 		}
   521 
   522 	if (KErrNone != ret)
   523 		{
   524 		aPanicRequired = ETrue;
   525 		return ret;
   526 		}
   527 	if ( (EFbsMessGetNearestFontToMaxHeightInTwips == fbsMessage) || (EFbsMessGetNearestFontToMaxHeightInPixels == fbsMessage) )
   528 		{
   529 		ret = TopLevelStore()->GetNearestFont(fontptr, fbsMessage, fontSpec, pckgMaxHeight);
   530 		}
   531 	else
   532 		{
   533 		ret = TopLevelStore()->GetNearestFont(fontptr, fbsMessage, fontSpec);
   534 		}
   535 
   536 	if (ret == KErrNone)
   537 		{ // package up the result
   538 		ret = CopyFontInfoIntoReturnMessage(aMessage, aPanicRequired, fontptr, 1);
   539 		}
   540 
   541 	return ret;
   542 	}
   543 
   544 
   545  /** package up the font that was found - includes cleanup handling in case of error
   546  @param aMessage input and output parameters
   547  @param aPanicRequired flag that is set if a client panic is required
   548  @param aFontObj the object that is to be returned
   549  @param aWritePosition the slot position in the message pointing to the receiving object
   550  @return KErrNone if successful, otherwise a system wide error code
   551  */
   552 TInt CFbClient::CopyFontInfoIntoReturnMessage(const RMessage2& aMessage, TBool& aPanicRequired, CFontObject* aFontObj, TInt aWritePosition)
   553 	{
   554 	TInt localhandle = 0;
   555 	TRAPD(ret, localhandle = iIx->AddL(aFontObj));
   556 	if (KErrNone != ret)
   557 		{
   558 		aFontObj->Close();
   559 		return ret;
   560 		}
   561 	TPckgBuf<TFontInfo> pckgFontInfo;
   562 	CopyFontInfo(aFontObj, localhandle, pckgFontInfo());
   563 	ret = aMessage.Write(aWritePosition, pckgFontInfo);
   564 	if (KErrNone != ret)
   565 		{
   566 		iIx->Remove(localhandle);
   567 		aPanicRequired = ETrue;
   568 		return ret;
   569 		}
   570 	// success
   571 	iResourceCount++;
   572 	FBS_OST(OstTraceExt3( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_COPYFONTINFOINTORETURNMESSAGE_INFO, "# Server font duplicated; iSSH=0x%08x; rc=%d; iH=0x%08x;", iSessionHandle, iResourceCount, localhandle);)
   573 	return KErrNone;
   574 	}
   575 
   576 
   577 /** Handler for EFbsMessGetFontById message
   578  Works for Bitmap fonts only, see implementation in CFbTop::GetFontById() & CFontStore::GetFontById().
   579  @param aMessage input and output parameters
   580  @param aPanicRequired flag that is set if a client panic is required
   581  @return KErrNone if successful, otherwise a system wide error code
   582  */
   583 TInt CFbClient::HandleMesgGetFontById(const RMessage2& aMessage, TBool& aPanicRequired)
   584 	{
   585 	CFontObject* fontptr = NULL;
   586 	TPckgBuf<TAlgStyle> algstyle;
   587 	TPckgBuf<TSize> size;
   588 
   589 	TInt ret = aMessage.Read(1, algstyle);
   590 	if (ret == KErrNone)
   591 		{ // get font size
   592 		ret = aMessage.Read(3, size);
   593 		if (ret == KErrNone)
   594 			{
   595 			TopLevelStore()->FontStore()->iKPixelHeightInTwips = size().iHeight;
   596 			TopLevelStore()->FontStore()->iKPixelWidthInTwips = size().iWidth;
   597 			}
   598 		}
   599 	if (ret != KErrNone)
   600 		{
   601 		aPanicRequired = ETrue;
   602 		return ret;
   603 		}
   604 	TUid fileid;
   605 	fileid.iUid = aMessage.Int2();
   606 	ret = TopLevelStore()->GetFontById(fontptr,fileid,algstyle());
   607 
   608 	if (ret == KErrNone)
   609 		{ // package up the result
   610 		ret = CopyFontInfoIntoReturnMessage(aMessage, aPanicRequired, fontptr, 0);
   611 		}
   612 
   613 	return ret;
   614 	}
   615 
   616 
   617 /** Handler for EFbsMessInstallFontStoreFile or EFbsMessAddFontStoreFile messages
   618  @param aMessage input and output parameters
   619  @param aPanicRequired flag that is set if a client panic is required
   620  @return KErrNone if successful, otherwise a system wide error code
   621  */
   622 TInt CFbClient::HandleMesgAddOrInstallFontFile(const RMessage2& aMessage, TBool& aPanicRequired)
   623 	{
   624 	TPckgBuf<TIntParcel> id;
   625 	TInt length=aMessage.Int1();
   626 	
   627 	if(length < 0 || length * sizeof(TText) >= KMaxTInt/2)
   628 		{
   629 		aPanicRequired = ETrue;
   630 		return KErrArgument;
   631 		}
   632 	
   633 	TText* buffer=(TText*)User::Alloc(length*sizeof(TText));
   634 	if(buffer==NULL)
   635 		{
   636 		return KErrNoMemory;
   637 		}
   638 	TPtr filename(buffer,length,length);
   639 	TInt ret = aMessage.Read(0,filename);
   640 	if(ret!=KErrNone)
   641 		{
   642 		User::Free(buffer);
   643 		aPanicRequired = ETrue;
   644 		return ret;
   645 		}
   646 	TRAP(ret, id().iInt = TopLevelStore()->FontStore()->AddFileL(filename).iUid);
   647 	User::Free(buffer);
   648 	if (ret != KErrNone)
   649 		{
   650 		return ret;
   651 		}
   652 	TUid uid;
   653 	uid.iUid=id().iInt;
   654 	if (aMessage.Function() == EFbsMessAddFontStoreFile)
   655 		{
   656 		TRAP(ret, AddFontFileIndexL(uid));
   657 		if (ret!=KErrNone)
   658 			{
   659 			TopLevelStore()->FontStore()->RemoveFile(uid);
   660 			return ret;
   661 			}
   662 		}
   663 	ret = aMessage.Write(2,id);
   664 	if (ret!=KErrNone)
   665 		{
   666 		RemoveFontFileIndex(uid);
   667 		aPanicRequired = ETrue;
   668 		}
   669 	return ret;
   670 	}
   671 
   672 
   673 /** Handler for EFbsMessRemoveFontStoreFile message
   674  @param aMessage input parameters
   675  @return KErrNone if successful
   676  */
   677 TInt CFbClient::HandleMesgRemoveFontFile(const RMessage2& aMessage)
   678 	{
   679 	TUid uid;
   680 	uid.iUid=aMessage.Int0();
   681 	RemoveFontFileIndex(uid);
   682 	return KErrNone;
   683 	}
   684 
   685 
   686 /** Handler for EFbsMessRasterize message
   687  @param aMessage input parameters
   688  @param aPanicRequired flag that is set if a client panic is required
   689  @return ETrue if successful, EFalse or any system-wide error code if not successful.
   690  */
   691 TInt CFbClient::HandleMesgRasterize(const RMessage2& aMessage, TBool& aPanicRequired)
   692 	{
   693 	CFbTop* fbtop = TopLevelStore();
   694 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
   695 	if(!fontptr)
   696 		{
   697 		aPanicRequired = ETrue;
   698 		return KErrArgument;
   699 		}
   700 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
   701 	const TUint charCode = aMessage.Int1();
   702 
   703 	if ( (bitmapFont != NULL) && (bitmapFont->Rasterize(iSessionHandle, charCode, iOpenFontGlyphData)) )
   704 		{
   705 		// Convert all pointers to be passed back to the client to offsets from
   706 		// the heap base so that they can be recreated client side relative to the
   707 		// client's heap base
   708 		TInt heapbase = fbtop->HeapBase();
   709 		TPckgBuf<TRasterizeParams> params;
   710 		params().iMetricsOffset = PointerToOffset(iOpenFontGlyphData->Metrics(), heapbase);
   711 		params().iBitmapPointerOffset = PointerToOffset(iOpenFontGlyphData->BitmapPointer(), heapbase);;
   712 		TInt err = aMessage.Write(2, params);
   713 		if (KErrNone != err)
   714 			{
   715 			aPanicRequired = ETrue;
   716 			return err;
   717 			}
   718 		return ETrue;
   719 		}
   720 	return EFalse;
   721 	}
   722 
   723 /** Handler for EFbsMessGetGlyphs message.
   724 Reads a batch of up to KMaxGlyphBatchSize glyph codes, and on success returns
   725 the corresponding TGlyphImageInfo objects.
   726  @param aMessage input parameters
   727  @param aPanicRequired flag that is set if a client panic is required
   728  @return KErrNone if successful, otherwise any system-wide error code.
   729  */
   730 TInt CFbClient::HandleMesgGetGlyphs(const RMessage2& aMessage, TBool& aPanicRequired)
   731 	{
   732 	CFbTop* fbtop = TopLevelStore();
   733 	// Previously requested glyphs were closed in ServiceL()
   734 	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
   735 	if (!glyphAtlas)
   736 		{
   737 		return KErrNotSupported;
   738 		}
   739 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
   740 	if(!fontptr)
   741 		{
   742 		aPanicRequired = ETrue;
   743 		return KErrBadHandle;
   744 		}
   745 
   746 	TUint glyphCodes[KMaxGlyphBatchSize];
   747 	TGlyphImageInfo glyphImageInfo[KMaxGlyphBatchSize];
   748 	TPckg<TUint[KMaxGlyphBatchSize]> glyphBatchPckg(glyphCodes);
   749 
   750 	TInt err = aMessage.Read(1, glyphBatchPckg);
   751 	if (err != KErrNone)
   752 		{
   753 		aPanicRequired = ETrue;
   754 		return err;
   755 		}
   756 	TInt glyphCodesCount = glyphBatchPckg.Length() / sizeof(TUint);
   757 	if (glyphCodesCount > KMaxGlyphBatchSize)
   758 		{
   759 		aPanicRequired = ETrue;
   760 		return KErrOverflow;
   761 		}
   762 
   763 	TInt glyphsProcessed = 0;
   764 	CBitmapFont* font = fontptr->iAddressPointer;
   765 	for (; (glyphsProcessed < glyphCodesCount); ++glyphsProcessed)
   766 		{
   767 		TUint32 glyphCode = glyphCodes[glyphsProcessed];
   768 		err = glyphAtlas->GetGlyph(*font, glyphCode, glyphImageInfo[glyphsProcessed]);
   769 		// Search for glyph in glyph atlas
   770 		if (KErrNone != err)
   771 			{
   772 			const TUint8* bitmapData = NULL;
   773 			TOpenFontCharMetrics metrics;
   774 			// search for glyph in font glyph cache and session cache.
   775 			if (!font->GetCharacterData(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, metrics, bitmapData))
   776 				{
   777 				// Rasterize the glyph
   778 				if(!font->Rasterize(iSessionHandle, glyphCode | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
   779 					{
   780 					err = KErrNoMemory;
   781 					break;
   782 					}
   783 				metrics = *(iOpenFontGlyphData->Metrics());
   784 				bitmapData = iOpenFontGlyphData->BitmapPointer();
   785 				}
   786 			CGlyphAtlas::TAddGlyphArgs args(bitmapData, glyphCode, metrics);
   787 			err = glyphAtlas->AddGlyph(*font, args, glyphImageInfo[glyphsProcessed]);
   788 			}
   789 		if ((err == KErrNone) && (glyphImageInfo[glyphsProcessed].iImageId != KSgNullDrawableId))
   790 			{
   791 			// To prevent other threads closing the glyph image in the glyph atlas 
   792 			// before client has had chance to open the drawable id, open a local
   793 			// handle to the glyph image for the session, which will be closed either
   794 			// next time a request is made or when EFbsMessCloseGlyphs is handled.
   795 			RSgImage glyphImage;
   796 			err = glyphImage.Open(glyphImageInfo[glyphsProcessed].iImageId);
   797 			if (err == KErrNone)
   798 				{
   799 				err = iGlyphImagesInTransit.Append(glyphImage);
   800 				}
   801 			}
   802 		// If an error occurred during this iteration, abort now before the glyphsProcessed
   803 		// counter is incremented, which would give one too many processed glyphs.
   804 		if (KErrNone != err)
   805 			{
   806 			break;
   807 			}
   808 		}
   809 
   810 	// Even if there was an error, if at least one glyph was processed successfully
   811 	// send that back to the client, and reset the error code.
   812 	if (glyphsProcessed > 0)
   813 		{
   814 		TPckg<TGlyphImageInfo[KMaxGlyphBatchSize]> glyphImageInfoPckg(glyphImageInfo);
   815 		glyphImageInfoPckg.SetLength(glyphsProcessed * sizeof(TGlyphImageInfo));
   816 		err = aMessage.Write(2, glyphImageInfoPckg);
   817 		if (err != KErrNone)
   818 			{
   819 			aPanicRequired = ETrue;
   820 			return err;
   821 			}
   822 		}
   823 	else
   824 		{
   825 		// No glyphs being returned, so an error code must be returned.
   826 		__ASSERT_DEBUG(err != KErrNone, User::Panic(KFBSERVPanicCategory, err));
   827 		}
   828 	return err;
   829 	}
   830 
   831 /**
   832 Handler for EFbsMessGetGlyphMetrics message.
   833 Reads an array of glyph codes, and returns the offset from the heap base for the 
   834 corresponding metrics object.
   835 @pre The glyph codes have already been searched client-side in the font glyph
   836 	cache and the session cache.
   837 @param aMessage input parameters
   838 @param aPanicRequired flag that is set if a client panic is required
   839 @return KErrNone if successful, otherwise any system-wide error code.
   840  */
   841 TInt CFbClient::HandleMesgGetGlyphMetrics(const RMessage2& aMessage, TBool& aPanicRequired)
   842 	{
   843 	CFbTop* fbtop = TopLevelStore();
   844 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
   845 	if(!fontptr)
   846 		{
   847 		aPanicRequired = ETrue;
   848 		return KErrBadHandle;
   849 		}
   850 	
   851 	TInt err = KErrNone;
   852 	TUint glyphCodes[KMaxMetricsBatchSize];
   853 	TPckg<TUint[KMaxMetricsBatchSize]> glyphBatchPckg(glyphCodes);
   854 	err = aMessage.Read(1, glyphBatchPckg);
   855 	if (err != KErrNone)
   856 		{
   857 		aPanicRequired = ETrue;
   858 		return err;
   859 		}
   860 	
   861 	TInt numGlyphCodes = glyphBatchPckg.Length() / sizeof(TUint);	
   862 	if (numGlyphCodes > KMaxMetricsBatchSize)
   863 		{
   864 		aPanicRequired = ETrue;
   865 		return KErrOverflow;
   866 		}
   867 	
   868 	CBitmapFont* font = fontptr->iAddressPointer;
   869 	const TInt heapbase = fbtop->HeapBase();
   870 
   871 	TInt glyphProcessed;
   872 	TInt glyphMetricsOffsets[KMaxMetricsBatchSize];
   873 	for (glyphProcessed = 0; (glyphProcessed < numGlyphCodes) && (err == KErrNone); ++glyphProcessed)
   874 		{
   875 		if (font->Rasterize(iSessionHandle, glyphCodes[glyphProcessed] | KTreatAsGlyphCodeFlag, iOpenFontGlyphData))
   876 			{
   877 			// Convert all pointers to be passed back to the client to offsets from
   878 			// the heap base so that they can be recreated client side relative to the
   879 			// client's heap base
   880 			glyphMetricsOffsets[glyphProcessed] = PointerToOffset(iOpenFontGlyphData->Metrics(), heapbase);
   881 			}
   882 		else
   883 			{
   884 			err = KErrNoMemory;
   885 			}
   886 		}
   887 
   888 	if (err == KErrNone)
   889 		{
   890 		TPckg<TInt[KMaxMetricsBatchSize]> glyphMetricsOffsetsPckg(glyphMetricsOffsets);
   891 		glyphMetricsOffsetsPckg.SetLength(glyphProcessed * sizeof(TInt));
   892 		err = aMessage.Write(2, glyphMetricsOffsetsPckg);
   893 		if (err != KErrNone)
   894 			{
   895 			aPanicRequired = ETrue;
   896 			}
   897 		}	
   898 	return err;
   899 	}
   900 
   901 /** Handler for EFbsMessFaceAttrib message
   902  @param aMessage Input and output parameters
   903  @param aPanicRequired Flag that is set to ETrue if a client panic is required
   904  @return ETrue if successful, EFalse or any system-wide error code if not successful.
   905 	 An error code is only returned if aPanicRequired is set to ETrue.
   906  */
   907 TInt CFbClient::HandleMesgFaceAttrib(const RMessage2& aMessage, TBool& aPanicRequired)
   908 	{
   909 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), TopLevelStore()->FontConUniqueID()));
   910 	if(!fontptr)
   911 		{
   912 		aPanicRequired = ETrue;
   913 		return KErrArgument;
   914 		}
   915 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
   916 
   917 	TInt ret = EFalse;
   918 	TPckgBuf<TOpenFontFaceAttrib> package;
   919 	if ( (bitmapFont != NULL) && (bitmapFont->GetFaceAttrib(package())) )
   920 		{
   921 		ret = aMessage.Write(1,package);
   922 		if (ret == KErrNone)
   923 			{
   924 			ret = ETrue;
   925 			}
   926 		else
   927 			{
   928 			aPanicRequired = ETrue;
   929 			}
   930 		}
   931 	return ret;
   932 	}
   933 
   934 
   935 /** Handler for EFbsMessHasCharacter message
   936  @param aMessage Input parameters
   937  @param aPanicRequired Flag that is set to ETrue if a client panic is required
   938  @return ETrue if the font has the character, EFalse if the font does not have
   939   the character, or any system-wide error code if not successful. An error code
   940   is only returned if aPanicRequired is set to ETrue.
   941  */
   942 TInt CFbClient::HandleMesgHasCharacter(const RMessage2& aMessage, TBool& aPanicRequired)
   943 	{
   944 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), TopLevelStore()->FontConUniqueID()));
   945 	if(!fontptr)
   946 		{
   947 		aPanicRequired = ETrue;
   948 		return KErrArgument;
   949 		}
   950 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
   951 
   952 	TInt ret = 0;
   953 	TRAPD(error, ret = bitmapFont->HasCharacterL(aMessage.Int1()));
   954 	if (error != KErrNone)
   955 		{
   956 		return EFalse;
   957 		}
   958 	return ret;
   959 	}
   960 
   961 
   962 /** Handler for EFbsMessShapeText message
   963  @param aMessage Input and output parameters
   964  @param aPanicRequired Flag that is set to ETrue if a client panic is required
   965  @return An offset from the heap base where the pointer to the shape is located
   966 	if successful, otherwise 0 or any system-wide error code. An error code is
   967 	only returned if aPanicRequired is set to ETrue.
   968  */
   969 TInt CFbClient::HandleMesgShapeText(const RMessage2& aMessage, TBool& aPanicRequired)
   970 	{
   971 	TInt error = KErrNone;
   972 	TShapeHeader* shape = 0;
   973 	if (aMessage.GetDesLength(2) != sizeof(TShapeMessageParameters))
   974 		{
   975 		aPanicRequired = ETrue;
   976 		return KErrArgument;
   977 		}
   978 
   979 	CFbTop* fbtop = TopLevelStore();
   980 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
   981 	if(!fontptr)
   982 		{
   983 		aPanicRequired = ETrue;
   984 		return KErrArgument;
   985 		}
   986 
   987 	TInt inputTextLength = aMessage.GetDesLength(1);
   988 	if (inputTextLength < 0)
   989 		{
   990 		error = inputTextLength;
   991 		aPanicRequired = ETrue;
   992 		return error;
   993 		}
   994 	else
   995 		{
   996 		iTextToShape.Zero();
   997 		if (iTextToShape.MaxLength() < inputTextLength)
   998 			{
   999 			error = iTextToShape.ReAlloc(inputTextLength);
  1000 			}
  1001 		}
  1002 	if (error == KErrNone)
  1003 		{
  1004 		error = aMessage.Read(1, iTextToShape);
  1005 		if (error != KErrNone)
  1006 			{
  1007 			aPanicRequired = ETrue;
  1008 			return error;
  1009 			}
  1010 		TPckgBuf<TShapeMessageParameters> sp;
  1011 		error = aMessage.Read(2, sp);
  1012 		if (error != KErrNone)
  1013 			{
  1014 			aPanicRequired = ETrue;
  1015 			return error;
  1016 			}
  1017 		CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1018 		TRAP(error, shape = bitmapFont->ShapeTextL(iTextToShape, iSessionHandle, sp()) );
  1019 		if (error == KErrNone)
  1020 			{
  1021 			// Convert the pointer to be passed back to the client to an offset from
  1022 			// the heap base so that it can be recreated client side relative to the
  1023 			// client's heap base
  1024 			return PointerToOffset(shape, fbtop->HeapBase());
  1025 			}
  1026 		}
  1027 	return 0;
  1028 	}
  1029 
  1030 
  1031 /** Handler for EFbsMessShapeDelete message
  1032  @param aMessage input and output parameters
  1033  @param aPanicRequired flag that is set to ETrue if a client panic is required
  1034  @return KErrNone if successful, otherwise a system wide error code
  1035 	 An error code is only returned if aPanicRequired is set to ETrue.
  1036  */
  1037 TInt CFbClient::HandleMesgShapeDelete(const RMessage2& aMessage, TBool& aPanicRequired)
  1038 	{
  1039 	CFbTop* fbtop = TopLevelStore();
  1040 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
  1041 	if(!fontptr)
  1042 		{
  1043 		aPanicRequired = ETrue;
  1044 		return KErrArgument;
  1045 		}
  1046 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1047 
  1048 	// Combine the passed shape offset with the current heap base to get
  1049 	// a valid pointer to a shape header for use in this process			
  1050 	TShapeHeader* shapeheader = reinterpret_cast<TShapeHeader*>(OffsetToPointer(aMessage.Int1(), fbtop->HeapBase()));
  1051 
  1052 	bitmapFont->DeleteShape(iSessionHandle,shapeheader);
  1053 	return KErrNone;
  1054 	}
  1055 
  1056 TInt CFbClient::HandleMesgReleaseGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired)
  1057 	{
  1058 	TInt ret = KErrNone;
  1059 	CFbTop* fbtop = TopLevelStore();
  1060 	TPckgBuf<TFBSGlyphOutlineParam> params;
  1061 	ret = aMessage.Read(0, params);
  1062 	if (KErrNone != ret)
  1063 		{
  1064 		aPanicRequired = ETrue;
  1065 		return ret;
  1066 		}
  1067 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(params().iHandle, fbtop->FontConUniqueID()));
  1068 	if(!fontptr)
  1069 		{
  1070 		aPanicRequired = ETrue;
  1071 		return KErrArgument;
  1072 		}
  1073 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1074 
  1075 	TInt count = params().iCount;
  1076 	TUint *glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint));
  1077 	if (NULL == glyphCodes)
  1078 		{
  1079 		return KErrNoMemory;
  1080 		}
  1081 	// copy the glyph codes out of the IPC buffer...
  1082 	TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint));
  1083 	ret = aMessage.Read(1, ptr);  
  1084 
  1085 	if (KErrNone == ret)
  1086 		{
  1087 		bitmapFont->ReleaseGlyphOutlines(count, glyphCodes,  
  1088 				params().iHinted, iSessionHandle);
  1089 		}
  1090 	else 
  1091 		{
  1092 		aPanicRequired = ETrue;
  1093 		}
  1094 
  1095 	User::Free(glyphCodes);
  1096 	return ret;
  1097 	}
  1098 
  1099 TInt CFbClient::HandleMesgGetGlyphOutline(const RMessage2& aMessage, TBool& aPanicRequired) 
  1100 	{
  1101 	TInt ret = KErrNone;
  1102 	CFbTop* fbtop = TopLevelStore();
  1103 	TPckgBuf<TFBSGlyphOutlineParam> params;
  1104 	ret = aMessage.Read(0, params);
  1105 	if (KErrNone != ret)
  1106 		{
  1107 		aPanicRequired = ETrue;
  1108 		return ret;
  1109 		}
  1110 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(params().iHandle, fbtop->FontConUniqueID()));
  1111 	if(!fontptr)
  1112 		{
  1113 		aPanicRequired = ETrue;
  1114 		return KErrArgument;
  1115 		}
  1116 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1117 
  1118 	TInt count = params().iCount;
  1119 	TUint* glyphCodes = (TUint *)User::Alloc(count * sizeof(TUint));
  1120 	if (NULL == glyphCodes)
  1121 		{
  1122 		return KErrNoMemory;
  1123 		}
  1124 	// copy the glyph codes out of the IPC buffer...
  1125 	TPtr8 ptr((TUint8 *)glyphCodes, count * sizeof(TUint), count * sizeof(TUint));
  1126 	ret = aMessage.Read(1, ptr);
  1127 	if (KErrNone != ret)
  1128 		{
  1129 		User::Free(glyphCodes);
  1130 		aPanicRequired = ETrue;
  1131 		return ret;
  1132 		}
  1133 
  1134 	TOffsetLen* offsetLens = 
  1135 		(TOffsetLen *)User::Alloc(count * sizeof(TOffsetLen));
  1136 	if (NULL == offsetLens)
  1137 		{
  1138 		User::Free(glyphCodes);
  1139 		return KErrNoMemory;
  1140 		}
  1141 
  1142 	TInt len = 0;
  1143 	TAny* outline = NULL;
  1144 	for (TInt i = 0; i < count; ++i)
  1145 		{
  1146 		bitmapFont->GetGlyphOutline(glyphCodes[i],  
  1147 			params().iHinted, outline, len, iSessionHandle);
  1148 		
  1149 		offsetLens[i].iLen = len;
  1150 		offsetLens[i].iOffset = PointerToOffset((outline), fbtop->HeapBase());
  1151 		}
  1152 	TPtr8 pkg2((TUint8 *)offsetLens, count * sizeof(TOffsetLen), 
  1153 			count * sizeof(TOffsetLen));
  1154 	ret = aMessage.Write(2, pkg2);
  1155 	if (KErrNone != ret)
  1156 		{
  1157 		aPanicRequired = ETrue;
  1158 		}
  1159 
  1160 	User::Free(glyphCodes);
  1161 	User::Free(offsetLens);
  1162 	return ret;  
  1163 	}
  1164 
  1165 TInt CFbClient::HandleMesgReleaseFontTable(const RMessage2& aMessage, TBool& aPanicRequired)
  1166 	{
  1167 	CFbTop* fbtop = TopLevelStore();
  1168 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
  1169 	if(!fontptr)
  1170 		{
  1171 		aPanicRequired = ETrue;
  1172 		return KErrArgument;
  1173 		}
  1174 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1175 
  1176 	TUint32 tag = aMessage.Int1();
  1177 
  1178 	bitmapFont->ReleaseFontTable(tag, iSessionHandle);
  1179 
  1180 	return KErrNone;
  1181 	}
  1182 
  1183 TInt CFbClient::HandleMesgGetFontTable(const RMessage2& aMessage, TBool& aPanicRequired)
  1184 	{
  1185 	TInt ret = KErrNone;
  1186 	CFbTop* fbtop = TopLevelStore();
  1187 	CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(aMessage.Int0(), fbtop->FontConUniqueID()));
  1188 	if(!fontptr)
  1189 		{
  1190 		aPanicRequired = ETrue;
  1191 		return KErrArgument;
  1192 		}
  1193 	CBitmapFont* bitmapFont = fontptr->iAddressPointer;
  1194 
  1195 	TInt len = 0;
  1196 	TAny* tablePtr = NULL;
  1197 	ret = bitmapFont->GetFontTable((TUint32)aMessage.Int1(), tablePtr, len, iSessionHandle);
  1198 
  1199 	if (KErrNone == ret) 
  1200 		{
  1201 		TPckgBuf<TOffsetLen> params;
  1202 		params().iLen = len;
  1203 		params().iOffset = PointerToOffset(tablePtr, fbtop->HeapBase());
  1204 		ret = aMessage.Write(2, params);
  1205 		aPanicRequired = (KErrNone != ret);
  1206 		}
  1207 
  1208 	return ret;
  1209 	}
  1210 
  1211 
  1212 /**
  1213  Called in response to the GoomMonitor framework's call into FbsOogmPlugin.
  1214  We wish to either free some GPU memory, or reinstate its normal usage.
  1215 
  1216 @param  aMessage The IPC message.
  1217 @return KErrNone If the value contained in the TFbsOogmMessage enumeration member is meaningful and the glyph atlas is present.
  1218         KErrNotSupported if there is no glyph atlas.
  1219         KErrUnknown if the value contained in the TFbsOogmMessage enumeration member is not meaningful.
  1220  */
  1221 TInt CFbClient::HandleMesgOogmStatus( const RMessage2& aMessage )
  1222     {
  1223     TInt ret = KErrNone;
  1224     CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
  1225 
  1226     if ( NULL == glyphAtlas )
  1227         {
  1228         return KErrNotSupported;
  1229         }
  1230 
  1231 
  1232     TPckgBuf<TFbsOogmMessage> oogmMessage;
  1233     aMessage.Read( 0, oogmMessage );
  1234 
  1235     switch( oogmMessage().iOogmNotification )
  1236         {
  1237     case TFbsOogmMessage::EFbsOogmNoAction:
  1238         break;
  1239 
  1240     case TFbsOogmMessage::EFbsOogmLowNotification:
  1241         {
  1242         glyphAtlas->ReleaseGpuMemory( oogmMessage().iBytesToFree, oogmMessage().iFlags );
  1243         }
  1244          break;
  1245 
  1246     case TFbsOogmMessage::EFbsOogmOkayNotification:
  1247         {
  1248         glyphAtlas->InstateGpuMemory( oogmMessage().iFlags );
  1249         }
  1250         break;
  1251 
  1252     default:
  1253         ret = KErrUnknown;
  1254         break;
  1255         }
  1256 
  1257     return ret;
  1258     }
  1259 
  1260 
  1261 void CFbClient::HandleMesgGlyphCacheMetrics( const RMessage2& aMessage )
  1262     {
  1263     CGlyphAtlas* glyphAtlas = TopLevelStore()->GlyphAtlas();
  1264     TPckgBuf<TGlyphCacheMetrics>  metrics;
  1265 
  1266     glyphAtlas->GetGlyphCacheMetrics( metrics() );
  1267 
  1268     aMessage.Complete( aMessage.Write(0, metrics) );
  1269     }
  1270 
  1271 
  1272 void CFbClient::ProcFontMessage(const RMessage2& aMessage)
  1273 	{
  1274 	TInt ret = KErrNone;
  1275 	TBool panicRequired = EFalse;
  1276 
  1277 	switch(aMessage.Function())
  1278 		{
  1279 		case EFbsMessFontDuplicate:
  1280 			ret = HandleMesgFontDuplicate(aMessage, panicRequired);
  1281 			break;
  1282 
  1283 		case EFbsMessGetNearestFontToDesignHeightInTwips:
  1284 		case EFbsMessGetNearestFontToDesignHeightInPixels:
  1285 		case EFbsMessGetNearestFontToMaxHeightInTwips:
  1286 		case EFbsMessGetNearestFontToMaxHeightInPixels:
  1287 			ret = HandleMesgGetNearestFont(aMessage, panicRequired);
  1288 			break;
  1289 
  1290 		case EFbsMessGetFontById:
  1291 			ret = HandleMesgGetFontById(aMessage, panicRequired);
  1292 			break;
  1293 
  1294 		case EFbsMessInstallFontStoreFile:
  1295 		case EFbsMessAddFontStoreFile:
  1296 			ret = HandleMesgAddOrInstallFontFile(aMessage, panicRequired);
  1297 			break;
  1298 
  1299 		case EFbsMessRemoveFontStoreFile:
  1300 			ret = HandleMesgRemoveFontFile(aMessage);
  1301 			break;
  1302 
  1303 		case EFbsMessRasterize:
  1304 			ret = HandleMesgRasterize(aMessage, panicRequired);
  1305 			break;
  1306 
  1307 		case EFbsMessFaceAttrib:
  1308 			ret = HandleMesgFaceAttrib(aMessage, panicRequired);
  1309 			break;
  1310 
  1311 		case EFbsMessHasCharacter:
  1312 			ret = HandleMesgHasCharacter(aMessage, panicRequired);
  1313 			break;
  1314 
  1315 		case EFbsMessShapeText:
  1316 			ret = HandleMesgShapeText(aMessage, panicRequired);
  1317 			break;
  1318 
  1319 		case EFbsMessShapeDelete:
  1320 			ret = HandleMesgShapeDelete(aMessage, panicRequired);
  1321 			break;
  1322 
  1323 		case EFbsMessSetTwipsHeight:
  1324 			{
  1325 			TInt localhandle=aMessage.Int0();
  1326 			CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(localhandle, TopLevelStore()->FontConUniqueID()));
  1327 			if(!fontptr)
  1328 				{
  1329 				panicRequired = ETrue;
  1330 				ret = KErrArgument;
  1331 				break;
  1332 				}
  1333 			fontptr->iHeightInTwips = aMessage.Int1();
  1334 			ret = KErrNone;
  1335 			break;	
  1336 			}
  1337 		case EFbsMessGetTwipsHeight:
  1338 			{
  1339 			TInt localhandle=aMessage.Int0();
  1340 			CFontObject* fontptr = static_cast<CFontObject*>(iIx->At(localhandle, TopLevelStore()->FontConUniqueID()));
  1341 			if(!fontptr)
  1342 				{
  1343 				panicRequired = ETrue;
  1344 				ret = KErrArgument;
  1345 				break;
  1346 				}
  1347 			TPckgBuf<TInt> height;
  1348 			height() = fontptr->iHeightInTwips;
  1349 			ret = aMessage.Write(1,height);
  1350 			if (KErrNone != ret)
  1351 				{
  1352 				panicRequired = ETrue;
  1353 				}
  1354 			break;
  1355 			}
  1356 		case EFbsSetSystemDefaultTypefaceName:
  1357 			{
  1358 			TBuf<KMaxTypefaceNameLength> fontTypefaceName;
  1359 			ret = aMessage.GetDesLength(0);
  1360 			if (ret < 0)
  1361 				{
  1362 				panicRequired = ETrue;
  1363 				break;
  1364 				}
  1365 			if (ret <= KMaxTypefaceNameLength) // Size in characters i.e. 2 bytes for unicode
  1366 				{
  1367 				ret = aMessage.Read(0, fontTypefaceName);
  1368 				if (ret == KErrNone)
  1369 					{
  1370 					TopLevelStore()->SetSystemDefaultTypefaceName(fontTypefaceName);
  1371 					}
  1372 				}
  1373 			else
  1374 				{
  1375 				panicRequired = ETrue;
  1376 				ret = KErrTooBig;
  1377 				}
  1378 
  1379 			break;
  1380 			}
  1381 		case EFbsMessGetFontTable:
  1382 			{
  1383 			ret = HandleMesgGetFontTable(aMessage, panicRequired);
  1384 			break;
  1385 			}
  1386 		case EFbsMessGetGlyphOutline:
  1387 			{
  1388 			ret = HandleMesgGetGlyphOutline(aMessage, panicRequired);
  1389 			break;
  1390 			}
  1391 		case EFbsMessReleaseGlyphOutline:
  1392 			{
  1393 			ret = HandleMesgReleaseGlyphOutline(aMessage, panicRequired);
  1394 			break;
  1395 			}
  1396 		case EFbsMessReleaseFontTable:
  1397 			{
  1398 			ret = HandleMesgReleaseFontTable(aMessage, panicRequired);
  1399 			break;
  1400 			}
  1401 		case EFbsMessGetGlyphs:
  1402 			{
  1403 			ret = HandleMesgGetGlyphs(aMessage, panicRequired);
  1404 			break;
  1405 			}
  1406 		case EFbsMessGetGlyphMetrics:
  1407 			{
  1408 			ret = HandleMesgGetGlyphMetrics(aMessage, panicRequired);
  1409 			break;
  1410 			}
  1411 
  1412 #ifdef _DEBUG
  1413 		case EFbsMessSetDuplicateFail:
  1414 			{
  1415 			TInt argument =aMessage.Int0();
  1416 			if (argument)
  1417 				{
  1418 				iFontDuplicateToFail = ETrue;
  1419 				}
  1420 			else
  1421 				{
  1422 				iFontDuplicateToFail = EFalse;
  1423 				}
  1424 			ret=KErrNone;
  1425 			break;
  1426 			}
  1427 #endif
  1428 		default:
  1429 			ret = KErrUnknown;
  1430 		}
  1431 
  1432 	// either have a result or an error code to panic the client with
  1433 	if (panicRequired)
  1434 		{
  1435 		aMessage.Panic(KFBSERVPanicCategory, ret);
  1436 		}
  1437 	else
  1438 		{
  1439 		if(!aMessage.IsNull())
  1440 			{
  1441 			aMessage.Complete(ret);
  1442 			}		
  1443 		}
  1444 #ifdef _DEBUG
  1445 	iRet=ret;
  1446 #endif	
  1447 	}
  1448 
  1449 void CFbClient::ProcBitmapMessage(const RMessage2 &aMessage)
  1450 	{
  1451 	CBitmapObject* bmpptr=NULL;
  1452 	TInt localhandle=0;
  1453 	TInt ret = KErrNone;
  1454 	switch(aMessage.Function())
  1455 		{
  1456 	case EFbsMessBitmapCreate:
  1457 		{
  1458 		TPckgBuf<TBmpSpec> bs;
  1459 		ret = aMessage.Read(0,bs);
  1460 		if(ret!=KErrNone)
  1461 			{
  1462 			aMessage.Panic(KFBSERVPanicCategory,ret);
  1463 			return;
  1464 			}
  1465 			
  1466 		TBmpSpec& bmpSpec = bs();	
  1467 		
  1468 		if(!TDisplayModeUtils::IsDisplayModeValid(bmpSpec.iDispMode))
  1469 			{
  1470 			aMessage.Panic(KFBSERVPanicCategory,KErrArgument);
  1471 			return;
  1472 			}
  1473 
  1474 		// client uses iHandle to pass UID and iServerHandle to pass data size
  1475 		TRAP(ret, bmpptr = TopLevelStore()->CreateBitmapL(bmpSpec.iSizeInPixels, bmpSpec.iDispMode, TUid::Uid(bmpSpec.iHandle), EFalse, bmpSpec.iServerHandle));
  1476 		if(ret!=KErrNone)
  1477 			break;
  1478 		TRAP(ret,localhandle=iIx->AddL(bmpptr));
  1479 		if(ret!=KErrNone)
  1480 			{
  1481 			bmpptr->Close();
  1482 			break;
  1483 			}
  1484 		
  1485 		bmpSpec.iHandle=localhandle;
  1486 		bmpSpec.iServerHandle = bmpptr->Handle();
  1487 		bmpSpec.iAddressOffset=TInt(bmpptr->Address())-TopLevelStore()->HeapBase();
  1488 		ret = aMessage.Write(0,bs);
  1489 		if(ret!=KErrNone)
  1490 			{
  1491 			iIx->Remove(localhandle);
  1492 			aMessage.Panic(KFBSERVPanicCategory,ret);
  1493 			return;
  1494 			}
  1495 		iResourceCount++;
  1496 		FBS_OST(OstTraceExt5( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO, "# Server bitmap created; iSSH=0x%08x; rc=%d; iH=0x%08x; iSH=0x%08x; bytes=%d;", iSessionHandle, iResourceCount, bmpSpec.iHandle, bmpSpec.iServerHandle, bmpptr->Address()->DataStride() * bmpSpec.iSizeInPixels.iHeight);)		
  1497 		break;
  1498 		}
  1499 
  1500 	case EFbsMessBitmapLoad:
  1501 	case EFbsMessBitmapLoadFast:
  1502 		{
  1503 		TPckgBuf<TLoadBitmapArg> loadBitmapArg;
  1504 		ret = aMessage.Read(1,loadBitmapArg);
  1505 		if(ret!=KErrNone)
  1506 			{
  1507 			aMessage.Panic(KFBSERVPanicCategory,ret);
  1508 			return;
  1509 			}
  1510 		const TInt32 id=loadBitmapArg().iBitmapId;
  1511 		const TBool shareifloaded=loadBitmapArg().iShareIfLoaded;
  1512 		const TUint fileOffset = loadBitmapArg().iFileOffset;
  1513 		if(aMessage.Function() == EFbsMessBitmapLoad)
  1514 			{
  1515 			RFile file;
  1516 			ret=file.AdoptFromClient(aMessage,2,3);
  1517 			if (ret!=KErrNone)
  1518 				{
  1519 				break;
  1520 				}
  1521 			TFileName filename;
  1522 			ret=file.FullName(filename);
  1523 			if (ret!=KErrNone)
  1524 				{
  1525 				break;
  1526 				}
  1527 
  1528 			if(shareifloaded)
  1529 				{
  1530 				TRAP(ret, bmpptr=TopLevelStore()->ShareBitmapL(filename, id, fileOffset,&file, iSessionHandle));
  1531 				}
  1532 			else
  1533 				{
  1534 				TRAP(ret, bmpptr=TopLevelStore()->LoadBitmapL(filename, id, fileOffset, &file, iSessionHandle));
  1535 				}
  1536 			file.Close();
  1537 			}
  1538 		else
  1539 			{
  1540 			TFileName filename;
  1541 			ret = aMessage.Read(2,filename);
  1542 			if (ret!=KErrNone)
  1543 				{
  1544 				aMessage.Panic(KFBSERVPanicCategory,ret);
  1545 				return;
  1546 				}
  1547 			_LIT(KZDrive, "z:");
  1548 			if (filename.Left(2).CompareF(KZDrive))
  1549 				{
  1550 				// File is not in the Z: drive.
  1551 				// So open the file and pass the file handle to LoadBitmapL() or ShareBitmapL() and close it afterwards.
  1552 				// The reason is that the cache cannot be used for files that are writable,
  1553 				// since they can't be kept open in the cache.
  1554 				RFile file;
  1555 				ret = file.Open(TopLevelStore()->FileSession(),filename,EFileShareReadersOnly);
  1556 				if (ret!=KErrNone)
  1557 					{
  1558 					break;
  1559 					}
  1560 				if(shareifloaded)
  1561 					{
  1562 					TRAP(ret, bmpptr=TopLevelStore()->ShareBitmapL(filename, id, fileOffset,&file, iSessionHandle));
  1563 					}
  1564 				else
  1565 					{
  1566 					TRAP(ret, bmpptr=TopLevelStore()->LoadBitmapL(filename, id, fileOffset, &file, iSessionHandle));
  1567 					}
  1568 				file.Close();
  1569 				}
  1570 			else
  1571 				{
  1572 				if(shareifloaded)
  1573 					{
  1574 					TRAP(ret, bmpptr=TopLevelStore()->ShareBitmapL(filename, id, fileOffset, NULL, iSessionHandle));
  1575 					}
  1576 				else
  1577 					{
  1578 					TRAP(ret, bmpptr=TopLevelStore()->LoadBitmapL(filename, id, fileOffset, NULL, iSessionHandle));
  1579 					}
  1580 				}
  1581 			}
  1582 		if(ret!=KErrNone)
  1583 			{
  1584 			break;
  1585 			}
  1586 		TRAP(ret,localhandle=iIx->AddL(bmpptr));
  1587 		if(ret!=KErrNone)
  1588 			{
  1589 			bmpptr->Close();
  1590 			break;
  1591 			}
  1592 		TPckgBuf<TBmpHandles> handlebuffer;
  1593 		handlebuffer().iHandle=localhandle;
  1594 		handlebuffer().iServerHandle = bmpptr->Handle();
  1595 		handlebuffer().iAddressOffset=TInt(bmpptr->Address())-TopLevelStore()->HeapBase();
  1596 		ret = aMessage.Write(0,handlebuffer);
  1597 		if(ret!=KErrNone)
  1598 			{
  1599 			iIx->Remove(localhandle);
  1600 			aMessage.Panic(KFBSERVPanicCategory,ret);
  1601 			return;
  1602 			}
  1603 		iResourceCount++;
  1604         FBS_OST(OstTraceExt5( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO2, "# Server bitmap loaded; iSSH=0x%08x; rc=%d; iH=0x%08x; iSH=0x%08x; bytes=%d;", iSessionHandle, iResourceCount, handlebuffer().iHandle, handlebuffer().iServerHandle, bmpptr->Address()->DataStride() * bmpptr->Address()->SizeInPixels().iHeight);)
  1605 		break;
  1606 		}
  1607 	case EFbsMessBitmapResize:
  1608 		{
  1609 		localhandle=aMessage.Int0();
  1610 		CFbTop* fbtop = TopLevelStore();
  1611 		bmpptr = static_cast<CBitmapObject*>(iIx->At(localhandle, fbtop->BitmapConUniqueID()));
  1612 		if(!bmpptr)
  1613 			{
  1614 			ret=KErrUnknown;
  1615 			break;
  1616 			}
  1617 		ret = fbtop->GetCleanBitmap(bmpptr);
  1618 		if (ret != KErrNone)
  1619 			{
  1620 			break;
  1621 			}
  1622 		TSize newsize(aMessage.Int1(),aMessage.Int2());
  1623  		const TBool compressedInRam = bmpptr->Address()->IsCompressedInRAM();  //It must be set before the resizing is done.
  1624 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
  1625 		CBitmapObject* newbmpptr = NULL;
  1626 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(newsize, dispMode, KUidCFbsBitmapCreation, ETrue));
  1627 		if (ret != KErrNone)
  1628 			{
  1629 			break;
  1630 			}
  1631 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
  1632 		if (ret != KErrNone)
  1633 			{
  1634 			newbmpptr->Close();
  1635 			break;
  1636 			}
  1637  		if (compressedInRam)
  1638 			{
  1639 			// if the header says PaletteCompression specify.
  1640 			TBitmapfileCompressionScheme scheme = ERLECompression;
  1641 			if (bmpptr->Address()->iHeader.iCompression == EGenericPaletteCompression)
  1642 				scheme = EPaletteCompression;
  1643 			ret = newbmpptr->Address()->CompressData(scheme); // re-compress
  1644 			if (ret != KErrNone)
  1645 				{
  1646 				newbmpptr->Close();
  1647 				break;
  1648 				}
  1649 			}
  1650 		TInt newlocalhandle = 0;
  1651 		TRAP(ret, newlocalhandle = iIx->AddL(newbmpptr));
  1652 		if (ret != KErrNone)
  1653 			{
  1654 			newbmpptr->Close();
  1655 			break;
  1656 			}
  1657 		ret = newbmpptr->Open();
  1658 		if (ret != KErrNone)
  1659 			{
  1660 			iIx->Remove(newlocalhandle);
  1661 			break;
  1662 			}
  1663 		bmpptr->SetCleanBitmap(newbmpptr);
  1664 		if (bmpptr->AccessCount() >= 2)
  1665 			{
  1666 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
  1667 			}
  1668 		iIx->Remove(localhandle);
  1669 		TPckgBuf<TBmpHandles> handlebuffer;
  1670 		handlebuffer().iHandle = newlocalhandle;
  1671 		handlebuffer().iServerHandle = newbmpptr->Handle();
  1672 		handlebuffer().iAddressOffset = TInt(newbmpptr->Address()) - fbtop->HeapBase();
  1673 		ret = aMessage.Write(3, handlebuffer);
  1674 		if (ret != KErrNone)
  1675 			{
  1676 			iIx->Remove(newlocalhandle);
  1677 			aMessage.Panic(KFBSERVPanicCategory, ret);
  1678 			return;
  1679 			}
  1680         FBS_OST(OstTraceExt5( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO4, "# Server bitmap resized; iSSH=0x%08x; iOldH=0x%08x; iNewH=0x%08x; iNewSH=0x%08x; newbytes=%d;", iSessionHandle, localhandle, newlocalhandle, newbmpptr->Handle(), newbmpptr->Address()->DataStride() * newsize.iHeight);)
  1681 		break;
  1682 		}
  1683 	case EFbsMessBitmapDuplicate:
  1684 		{
  1685 		bmpptr = TopLevelStore()->FindBitmap(aMessage.Int0());
  1686 		if (bmpptr == NULL)
  1687 			{
  1688 			ret=KErrUnknown;
  1689 			break;
  1690 			}
  1691 		//coverity [check_return]
  1692 		//coverity [unchecked_value]
  1693 		TopLevelStore()->GetCleanBitmap(bmpptr);
  1694 		ret = bmpptr->Open();
  1695 		if (ret != KErrNone)
  1696 			{
  1697 			break;
  1698 			}
  1699 		TPckgBuf<TBmpHandles> handlebuffer;
  1700 		TRAP(ret,localhandle=iIx->AddL(bmpptr));
  1701 		if(ret!=KErrNone)
  1702 			{
  1703 			bmpptr->Close();
  1704 			break;
  1705 			}
  1706 		handlebuffer().iHandle = localhandle;
  1707 		handlebuffer().iServerHandle = bmpptr->Handle();
  1708 		handlebuffer().iAddressOffset = TInt(bmpptr->Address()) - TopLevelStore()->HeapBase();
  1709 		ret = aMessage.Write(1, handlebuffer);
  1710 		if(ret!=KErrNone)
  1711 			{
  1712 			iIx->Remove(localhandle);
  1713 			aMessage.Panic(KFBSERVPanicCategory,ret);
  1714 			return;
  1715 			}
  1716 		iResourceCount++;
  1717         FBS_OST(OstTraceExt5( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO3, "# Server bitmap duplicated; iSSH=0x%08x; rc=%d; iH=0x%08x; iSH=0x%08x; bytes=%d;", iSessionHandle, iResourceCount, handlebuffer().iHandle, handlebuffer().iServerHandle, bmpptr->Address()->DataStride() * bmpptr->Address()->SizeInPixels().iHeight);)
  1718 		break;
  1719 		}
  1720 	case EFbsMessBitmapCompress:
  1721 		{
  1722 		localhandle = aMessage.Int0();
  1723 		CFbTop* fbtop = TopLevelStore();
  1724 		bmpptr = static_cast<CBitmapObject*>(iIx->At(localhandle, fbtop->BitmapConUniqueID()));
  1725 		if(!bmpptr)
  1726 			{
  1727 			ret = KErrUnknown;
  1728 			break;
  1729 			}
  1730 		ret = fbtop->GetCleanBitmap(bmpptr);
  1731 		if (ret != KErrNone)
  1732 			{
  1733 			break;
  1734 			}
  1735 		const TSize size = bmpptr->Address()->SizeInPixels();
  1736 		const TDisplayMode dispMode = bmpptr->Address()->DisplayMode();
  1737 		CBitmapObject* newbmpptr = NULL;
  1738 		TRAP(ret, newbmpptr = fbtop->CreateBitmapL(size, dispMode, KUidCFbsBitmapCreation, ETrue));
  1739 		if (ret != KErrNone)
  1740 			{
  1741 			break;
  1742 			}
  1743 		ret = newbmpptr->Address()->CopyData(*bmpptr->Address());
  1744 		if (ret != KErrNone)
  1745 			{
  1746 			newbmpptr->Close();
  1747 			break;
  1748 			}
  1749 		ret = newbmpptr->Address()->CompressData((TBitmapfileCompressionScheme)aMessage.Int1());
  1750 		if (ret != KErrNone)
  1751 			{
  1752 			newbmpptr->Close();
  1753 			break;
  1754 			}
  1755 		TInt newlocalhandle = 0;
  1756 		TRAP(ret, newlocalhandle = iIx->AddL(newbmpptr));
  1757 		if (ret != KErrNone)
  1758 			{
  1759 			newbmpptr->Close();
  1760 			break;
  1761 			}
  1762 		ret = newbmpptr->Open();
  1763 		if (ret != KErrNone)
  1764 			{
  1765 			iIx->Remove(newlocalhandle);
  1766 			break;
  1767 			}
  1768 		bmpptr->SetCleanBitmap(newbmpptr);
  1769 		if (bmpptr->AccessCount() >= 2)
  1770 			{
  1771 			fbtop->NotifyDirtyBitmap(*bmpptr, this);
  1772 			}
  1773 		iIx->Remove(localhandle);
  1774 		TPckgBuf<TBmpHandles> handlebuffer;
  1775 		handlebuffer().iHandle = newlocalhandle;
  1776 		handlebuffer().iServerHandle = newbmpptr->Handle();
  1777 		handlebuffer().iAddressOffset = TInt(newbmpptr->Address()) - fbtop->HeapBase();
  1778 		ret = aMessage.Write(2, handlebuffer);
  1779 		if (ret != KErrNone)
  1780 			{
  1781 			iIx->Remove(newlocalhandle);
  1782 			aMessage.Panic(KFBSERVPanicCategory, ret);
  1783 			return;
  1784 			}
  1785         FBS_OST(OstTraceExt4( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO5, "# Server bitmap compressed; iSSH=0x%08x; iOldH=0x%08x; iNewH=0x%08x; iNewSH=0x%08x;", (TUint)iSessionHandle, localhandle, newlocalhandle, handlebuffer().iServerHandle);)
  1786 		break;
  1787 		}
  1788 	case EFbsMessBitmapBgCompress:
  1789 		{
  1790 		localhandle = aMessage.Int0();
  1791 		TBitmapfileCompressionScheme scheme = (TBitmapfileCompressionScheme)aMessage.Int1();
  1792 		TBool async = aMessage.Int2();
  1793 		CFbTop* fbtop = TopLevelStore();
  1794 		bmpptr = static_cast<CBitmapObject*>(iIx->At(localhandle, fbtop->BitmapConUniqueID()));
  1795 		if(!bmpptr)
  1796 			{
  1797 			ret = KErrUnknown;
  1798 			break;
  1799 			}
  1800 		ret = fbtop->GetCleanBitmap(bmpptr);
  1801 		if (ret != KErrNone)
  1802 			{
  1803 			if (!async)
  1804 				{
  1805 				ret = KErrNone;
  1806 				}
  1807 			break;
  1808 			}
  1809 		ret = bmpptr->Address()->CheckBackgroundCompressData();
  1810 		if (KErrNone == ret)
  1811 			{
  1812 			ret = fbtop->BackgroundCompression()->AddToCompressionQueue(bmpptr, scheme, async ? &aMessage : NULL);
  1813 			if (ret == KErrNone && async)
  1814 				{
  1815 				return; // do not complete the client's request - that will be done by the background compression thread
  1816 				}
  1817 			}
  1818 		if (KErrAlreadyExists == ret)
  1819 			{
  1820 			ret = KErrNone;
  1821 			}
  1822 		break;
  1823 		}
  1824 	case EFbsMessBitmapClean:
  1825 		{
  1826 		TInt localhandle = aMessage.Int0();
  1827 		CFbTop* fbtop = TopLevelStore();
  1828 		bmpptr = static_cast<CBitmapObject*>(iIx->At(localhandle, fbtop->BitmapConUniqueID()));
  1829 		if(!bmpptr)
  1830 			{
  1831 			ret = KErrUnknown;
  1832 			break;
  1833 			}
  1834 		ret = fbtop->GetCleanBitmap(bmpptr);
  1835 		if (ret != KErrNone)
  1836 			{
  1837 			break;
  1838 			}
  1839 		ret = bmpptr->Open();
  1840 		if (ret != KErrNone)
  1841 			{
  1842 			break;
  1843 			}
  1844 		TInt cleanlocalhandle = 0;
  1845 		TRAP(ret, cleanlocalhandle = iIx->AddL(bmpptr));
  1846 		if (ret != KErrNone)
  1847 			{
  1848 			bmpptr->Close();
  1849 			break;
  1850 			}
  1851 		iIx->Remove(localhandle);
  1852 		TPckgBuf<TBmpHandles> handlebuffer;
  1853 		handlebuffer().iHandle = cleanlocalhandle;
  1854 		handlebuffer().iServerHandle = bmpptr->Handle();
  1855 		handlebuffer().iAddressOffset = TInt(bmpptr->Address()) - fbtop->HeapBase();
  1856 		ret = aMessage.Write(1, handlebuffer);
  1857 		if (ret != KErrNone)
  1858 			{
  1859 			iIx->Remove(cleanlocalhandle);
  1860 			aMessage.Panic(KFBSERVPanicCategory, ret);
  1861 			return;
  1862 			}
  1863 		FBS_OST(OstTraceExt3( GRAPHICS_RESOURCE_MANAGEMENT_SEMANTICS, CFBCLIENT_PROCBITMAPMESSAGE_INFO6, "# Server bitmap cleaned; iSSH=0x%08x; iOldH=0x%08x; iNewH=0x%08x;", iSessionHandle, localhandle, cleanlocalhandle);)
  1864 		break;
  1865 		}
  1866 	case EFbsGetAllBitmapHandles:
  1867 		{
  1868 		ret = TopLevelStore()->GetAllBitmapHandles(aMessage);		
  1869 		break;	
  1870 		}	
  1871 
  1872 	case EFbsMessBitmapNotifyDirty:
  1873 		{
  1874 		if (iHelper == NULL)
  1875 			{
  1876 			iHelper = new TFbClientHelper(*this);
  1877 			if (iHelper == NULL)
  1878 				{
  1879 				ret = KErrNoMemory;
  1880 				break;
  1881 				}
  1882 			TopLevelStore()->AddClientHelper(*iHelper);
  1883 			}
  1884 		if (!iHelper->iMessage.IsNull())
  1885 			{
  1886 			aMessage.Panic(KFBSERVPanicCategory, KErrAlreadyExists);
  1887 			return;
  1888 			}
  1889 		if (!iHelper->iDirty)
  1890 			{
  1891 			iHelper->iMessage = aMessage;
  1892 			return; // do not complete the client's request yet - that will be done when a bitmap becomes dirty
  1893 			}
  1894 		iHelper->iDirty = EFalse;
  1895 		}
  1896 		break;
  1897 	case EFbsMessBitmapCancelNotifyDirty:
  1898 		{
  1899 		if (iHelper != NULL && !iHelper->iMessage.IsNull())
  1900 			{
  1901 			iHelper->iMessage.Complete(KErrCancel);
  1902 			}
  1903 		}
  1904 		break;
  1905 	default:
  1906 		ret = KErrUnknown;
  1907 		}
  1908 		
  1909 	if(!aMessage.IsNull())
  1910 		{
  1911 		aMessage.Complete(ret);
  1912 		}
  1913 	
  1914 #ifdef _DEBUG
  1915 	iRet=ret;
  1916 #endif		
  1917 	}
  1918 
  1919 void CFbClient::NotifyDirtyBitmap(CBitmapObject& aBmpObj)
  1920 	{
  1921 	if (iHelper != NULL && iIx->At(&aBmpObj) != KErrNotFound)
  1922 		{
  1923 		iHelper->iDirty = ETrue;
  1924 		if (!iHelper->iMessage.IsNull())
  1925 			{
  1926 			iHelper->iMessage.Complete(KErrNone);
  1927 			iHelper->iDirty = EFalse;
  1928 			}
  1929 		}
  1930 	}
  1931 
  1932 void CFbClient::AddFontFileIndexL(TUid aId)
  1933 	{
  1934 	TInt count=iFontFileIndex->Count();
  1935 	for (TInt index=0;index<count;index++)
  1936 		{
  1937 		if (iFontFileIndex->At(index).iUid==aId)
  1938 			{
  1939 			iFontFileIndex->At(index).iAccessCount++;
  1940 			TopLevelStore()->FontStore()->RemoveFile(aId);
  1941 			return;
  1942 			}
  1943 		}
  1944 
  1945 	TFontFileIndex fontFileIndex;
  1946 	fontFileIndex.iUid=aId;
  1947 	fontFileIndex.iAccessCount=1;
  1948 	iFontFileIndex->AppendL(fontFileIndex);
  1949 	}
  1950 
  1951 void CFbClient::RemoveFontFileIndex(TUid aId)
  1952 	{
  1953 	TInt count=iFontFileIndex->Count();
  1954 	for (TInt index=0;index<count;index++)
  1955 		{
  1956 		TFontFileIndex* fontFileIndex=&iFontFileIndex->At(index);
  1957 		if (fontFileIndex->iUid==aId)
  1958 			{
  1959 			fontFileIndex->iAccessCount--;
  1960 			if (fontFileIndex->iAccessCount<1)
  1961 				{
  1962 				TopLevelStore()->FontStore()->RemoveFile(fontFileIndex->iUid);
  1963 				iFontFileIndex->Delete(index);
  1964 				}
  1965 			return;
  1966 			}
  1967 		}
  1968 	// not found - must be an installed file or rubbish, so try anyway
  1969 	TopLevelStore()->FontStore()->RemoveFile(aId);
  1970 	}
  1971 
  1972 void CFbClient::Disconnect(const RMessage2 &aMessage)
  1973 	{
  1974 	// if any bitmaps are in the background compression queue with a to-be-completed RMessage2 from this session,
  1975 	// the RMessage2 must be completed now as it is only possible to complete messages on existing sessions
  1976 	TopLevelStore()->BackgroundCompression()->CompleteOutstandingRequests(this);
  1977 
  1978 	// if there is a to-be-completed request for dirty bitmap notification complete it now
  1979 	if (iHelper)
  1980 		{
  1981 		if (!iHelper->iMessage.IsNull())
  1982 			{
  1983 			iHelper->iMessage.Complete(KErrDisconnected);
  1984 			}
  1985 		iHelper->Deque();
  1986 		delete iHelper;
  1987 		iHelper = NULL;
  1988 		}
  1989 
  1990 	// Clear the mbm file store cache resources that corresponds to this session
  1991 	TopLevelStore()->CloseFileStores(iSessionHandle);
  1992 
  1993 	CSession2::Disconnect(aMessage);
  1994 	}
  1995 
  1996 #ifdef _DEBUG
  1997 void CFbClient::ProcMemMessage(const RMessage2 &aMessage)
  1998 	{
  1999 	TInt ret=KErrNone;
  2000 	TInt parameterForFunctionCall;
  2001 	TInt cells = User::Heap().Available(parameterForFunctionCall);
  2002 	switch(aMessage.Function())
  2003 		{
  2004 		case EFbsMessSetHeapFail:
  2005 			if (aMessage.Int0()==RFbsSession::EHeapFailTypeServerMemory)
  2006 				{
  2007 				iOwnHeapFailNumber=aMessage.Int1();
  2008 				}
  2009 			else
  2010 				{
  2011 				iSharedHeapFailNumber=aMessage.Int1();
  2012 				}
  2013 			break;
  2014 		case EFbsMessHeapCount:
  2015 			if (aMessage.Int0()==RFbsSession::EHeapFailTypeServerMemory)
  2016 				{
  2017 				ret=User::CountAllocCells();
  2018 				}
  2019 			else
  2020 				{
  2021 				ret=iHeap->Count();
  2022 				}	
  2023 			break;
  2024 		case EFbsMessSetHeapReset:
  2025 			if (aMessage.Int0()==RFbsSession::EHeapFailTypeServerMemory)
  2026 				{
  2027 				iOwnHeapFailNumber=-1;
  2028 				}
  2029 			else
  2030 				{
  2031 				iSharedHeapFailNumber=-1;
  2032 				}				
  2033 			break;
  2034 		case EFbsMessSetHeapCheck:
  2035 			if (aMessage.Int0()==RFbsSession::EHeapFailTypeServerMemory)
  2036 				{
  2037 				iOwnHeapCheckFlip=ETrue;
  2038 				}
  2039 			else
  2040 				{
  2041 				iHeapCheckFlip=ETrue;
  2042 				}
  2043 			break;
  2044 		case EFbsMessHeap:
  2045 			ret=(TInt)iHeap;
  2046 			break;
  2047 		default:
  2048 			ret = KErrUnknown;
  2049 		}
  2050 	aMessage.Complete(ret);
  2051 	iRet=ret;
  2052 	}
  2053 
  2054 /**
  2055 Processes messages associated with the Glyph Atlas.
  2056 @param aMessage The message used to perform IPC to the client.
  2057  */
  2058 void CFbClient::ProcAtlasMessage(const RMessage2 &aMessage)
  2059 	{
  2060 	TInt ret = KErrNone;
  2061 	CFbTop* fbtop = TopLevelStore();
  2062 	CGlyphAtlas* glyphAtlas = fbtop->GlyphAtlas();
  2063 	if (!glyphAtlas)
  2064 		{
  2065 		ret = KErrNotSupported;
  2066 		}
  2067 	else
  2068 		{
  2069 		switch(aMessage.Function())
  2070 			{
  2071 			case EFbsMessAtlasFontCount:
  2072 				ret = glyphAtlas->FontCount();
  2073 				break;
  2074 			case EFbsMessAtlasGlyphCount:
  2075 				{
  2076 				TInt fontHandle = aMessage.Int0();
  2077 				if (fontHandle != 0)
  2078 					{
  2079 					if (fbtop->ValidFontHandle(fontHandle))
  2080 						{
  2081 						CFontObject* fontptr = reinterpret_cast<CFontObject*>(fontHandle);
  2082 						ret = glyphAtlas->GlyphCount(static_cast<CBitmapFont&>(*(fontptr->iAddressPointer)));
  2083 						}
  2084 					else
  2085 						{
  2086 						ret = KErrNotFound;
  2087 						}
  2088 					}
  2089 				else
  2090 					{
  2091 					ret = glyphAtlas->GlyphCount();
  2092 					}
  2093 				}
  2094 				break;
  2095 			default:
  2096 				ret = KErrUnknown;
  2097 			}
  2098 		}
  2099 	aMessage.Complete(ret);
  2100 	iRet=ret;
  2101 	}
  2102 #endif