fontservices/fontstore/src/OPENFONT.CPP
changeset 0 1fb32624e06b
child 1 e96e8a131979
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/fontstore/src/OPENFONT.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,2936 @@
+/*
+* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <fntstore.h>
+#include <gdi.h>
+#include "FNTSTD.H"
+#include <graphics/shapeimpl.h>
+#include "ShaperCache.H"
+#include "openfontsprivate.h"
+#include <linkedfonts.h>
+#include "linkedfontsprivate.h"
+#include <graphics/openfontrasterizer.h>
+#include <graphics/gdi/glyphsample.h>
+
+const TInt KSessionCacheEntries = 512;
+const TInt KDefaultSlantFactor = 20480;
+const TInt KOneIn16Dot16FixedPointFormat = 65536;
+
+#ifdef FNTSTORE_SUPPORT_FMM
+class TPointerArrayBaseOffset
+	{
+public:
+	TInt iCount;
+	TAny** iEntries;
+	TInt iAllocated;
+	TInt iGranularity;
+	};
+
+/*RArrayGlyphEntries*/
+
+inline const COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex) const
+	{
+	return *Entry(anIndex);
+	}
+
+inline COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex)
+	{
+	return *const_cast<COpenFontGlyphTreeEntry*>(Entry(anIndex));
+	}
+
+inline const COpenFontGlyphTreeEntry* RArrayGlyphEntries::Entry(TInt anIndex) const
+	{
+	return reinterpret_cast<const COpenFontGlyphTreeEntry*>(PtrAdd(EntryMemberOffSet()[anIndex],reinterpret_cast<TInt>(this)));
+	}
+
+inline COpenFontGlyphTreeEntry** RArrayGlyphEntries::EntryMemberOffSet() const
+	{
+	return reinterpret_cast<COpenFontGlyphTreeEntry**>(iEntriesOffset+reinterpret_cast<TInt>(this));
+	}
+
+inline TAny** RArrayGlyphEntries::EntryMember() const
+	{
+	return reinterpret_cast<const TPointerArrayBaseOffset*>(this)->iEntries;
+	}
+
+TInt RArrayGlyphEntries::Append(COpenFontGlyphTreeEntry& anEntry)
+	{		
+	TInt err = RArray<TInt>::Append(reinterpret_cast<TInt>(&anEntry)-reinterpret_cast<TInt>(this));
+	if (err == KErrNone)
+		{
+		iEntriesOffset=reinterpret_cast<TInt>(EntryMember())-reinterpret_cast<TInt>(this);
+		}
+	return err;
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/*COpenFontGlyphCache*/
+
+TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams)
+	{
+	if (iShaperCacheSentinel == NULL)
+		return NULL;
+	COpenFontShaperCacheEntry* searchNode = iShaperCacheSentinel->iNext;
+	
+	TInt start = aParams->iStart;
+	TInt end = aParams->iEnd;
+	TInt script = aParams->iScript;
+	const TUint16* text = (TUint16*)aParams->iText->Ptr();
+	TUint16* cachedText;
+	const TUint16* copyOfText;
+	TInt noOfChars = end - start;
+	TInt textIsSame = 1;
+	while (searchNode != iShaperCacheSentinel)
+		{
+		//Future work: add Script check for further script support
+		//Future work: add Language check for further language support
+		if ((searchNode->iEnd == end) && (searchNode->iStart == start) && (searchNode->iScript == script))
+			{
+			// Check for the entire text (within the context) coming in.
+			TInt i = 0;
+			copyOfText = text + start;
+			cachedText = (TUint16*)searchNode->iText + searchNode->iStart;
+			textIsSame = 1;
+			while (i < noOfChars && textIsSame != 0)
+				{
+				if (*cachedText != *copyOfText)
+					textIsSame = 0;
+				i++;
+				copyOfText++;
+				cachedText++;
+				};
+
+			if (textIsSame)
+				{
+				if (searchNode == iShaperCacheSentinel->iNext)
+					{
+					// now we need to update the reference count here for that session
+					if (searchNode->IncRefCount(aSessionHandle) != KErrNone)
+						return NULL;
+					return iShaperCacheSentinel->iNext->iShapeHeader;
+					}
+				// We have found a node, now put that node to the top of the list as the most recently used node
+				searchNode->iPrevious->iNext = searchNode->iNext;
+				searchNode->iNext->iPrevious = searchNode->iPrevious;
+				
+				searchNode->iNext = iShaperCacheSentinel->iNext;
+				iShaperCacheSentinel->iNext->iPrevious = searchNode;
+				iShaperCacheSentinel->iNext = searchNode;
+				searchNode->iPrevious = iShaperCacheSentinel;
+				if (searchNode->IncRefCount(aSessionHandle)!= KErrNone)
+					return NULL;
+				return searchNode->iShapeHeader;
+				}
+			}
+			searchNode = searchNode->iNext;
+		}
+	return NULL;
+	}
+
+TShapeHeader* COpenFontGlyphCache::Insert(TInt aSessionHandle, RHeap* aHeap, CShaper::TInput aInput, TShapeHeader* aShapeHeader, TInt& aAddedBytes)
+	{
+	TInt heapSizeBefAloc = 0;
+	aHeap->AllocSize(heapSizeBefAloc);
+
+	COpenFontShaperCacheEntry* new_entry;
+	new_entry = COpenFontShaperCacheEntry::New(aHeap, aInput, aShapeHeader);
+	if (new_entry)
+		{
+		// increase the reference count for this
+		TInt ret=new_entry->IncRefCount(aSessionHandle);
+		if (ret != KErrNone)
+			{
+			//no memory here
+			COpenFontShaperCacheEntry::Delete(aHeap, new_entry);
+			return NULL;
+			}
+		new_entry->iNext = iShaperCacheSentinel->iNext;
+		iShaperCacheSentinel->iNext->iPrevious = new_entry;
+		iShaperCacheSentinel->iNext = new_entry;
+		new_entry->iPrevious = iShaperCacheSentinel;
+
+		iNumberOfShaperCacheEntries++;
+		TInt heapSizeOnAloc = 0;
+		aHeap->AllocSize(heapSizeOnAloc);
+		aAddedBytes = heapSizeOnAloc - heapSizeBefAloc;
+
+		// Update the amount of memory used in creation of a new entry
+		iShapingInfoCacheMemory += heapSizeOnAloc - heapSizeBefAloc;
+
+		return new_entry->iShapeHeader;
+		}
+	return NULL;
+	}
+
+/**
+Searches from the least recently used towards the most recently used
+and try to free entry that is no longer referenced
+*/
+TInt COpenFontGlyphCache::DeleteLeastRecentlyUsedEntry(RHeap* aHeap)
+	{
+	// start from the least recently used
+	COpenFontShaperCacheEntry* deleteNode = iShaperCacheSentinel->iPrevious;
+
+	// if empty list there is nothing to delete
+	if (deleteNode == iShaperCacheSentinel)
+		return 0;
+	// else navigating starting from the LRU entry
+	while (deleteNode != iShaperCacheSentinel)
+		{
+		// cannot delete if the iHandleRefCount is greater than zero
+		if (deleteNode->iHandleRefCount>0)
+			{
+			deleteNode = deleteNode->iPrevious;
+			continue;
+			}
+
+		// otherwise we can delete the entry
+		deleteNode->iPrevious->iNext = deleteNode->iNext;
+		deleteNode->iNext->iPrevious = deleteNode->iPrevious;
+
+		TInt heapSizeBeforeDel = 0;
+		TInt heapSizeAfterDel = 0;
+		aHeap->AllocSize(heapSizeBeforeDel);
+		COpenFontShaperCacheEntry::Delete(aHeap, deleteNode);
+		aHeap->AllocSize(heapSizeAfterDel);
+		TInt deletedBytes = heapSizeBeforeDel - heapSizeAfterDel;
+
+		iNumberOfShaperCacheEntries--;
+		iShapingInfoCacheMemory -= deletedBytes;
+
+		return deletedBytes;
+		}
+	// we have navigated through the whole list and cannot delete anything
+	return 0;
+	}
+
+TInt COpenFont::DecrementCachedRefCount(TInt aSessionHandle, TShapeHeader* aShapeHeader, TBool aResetAll)
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	COpenFontShaperCacheEntry* ptr=NULL;
+	COpenFontGlyphCache* glyphCache=GetGlyphCache();
+	if (glyphCache)
+		ptr=glyphCache->iShaperCacheSentinel;
+	if (!ptr)
+		return KErrNone;
+#else
+	if (!iGlyphCache || !(iGlyphCache->iShaperCacheSentinel))
+		return KErrNone;
+
+	COpenFontShaperCacheEntry* ptr=iGlyphCache->iShaperCacheSentinel;
+	COpenFontGlyphCache* glyphCache=iGlyphCache;
+#endif // FNTSTORE_SUPPORT_FMM
+
+	TInt ret = KErrNotFound;
+	CFontStore* thisFontStore = File()->GetFontStore();
+	TInt allocBefDec = 0;
+	TInt allocAfterDec = 0;
+	TInt deletedBytes = 0;
+
+	// loop through the cache entry to decrement the ref count for a particular session	
+	while (ptr->iNext)
+		{
+		if (aResetAll)
+			{
+			// we want to reset any cache that has a matching the session handle
+			// i.e. here we dont care about which TShapeHeader and hence we can
+			// ignore the error code here if not found
+
+			// Always update the memory usage of the cache as decreasing the ref count 
+			// releases memory
+			iHeap->AllocSize(allocBefDec);
+
+			ptr->DecRefCount(aSessionHandle, ETrue);
+
+			iHeap->AllocSize(allocAfterDec);
+			deletedBytes = allocBefDec - allocAfterDec;
+			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
+			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
+
+			ret=KErrNone;
+			}
+		else if (ptr->iShapeHeader && ptr->iShapeHeader==aShapeHeader)
+			{
+			// Always update the memory usage of the cache as decreasing the ref count 
+			// releases memory
+			iHeap->AllocSize(allocBefDec);
+
+			ptr->DecRefCount(aSessionHandle);
+
+			iHeap->AllocSize(allocAfterDec);
+			deletedBytes = allocBefDec - allocAfterDec;
+			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
+			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
+
+			return KErrNone;
+			}
+		ptr=ptr->iNext;
+		if (ptr == glyphCache->iShaperCacheSentinel)
+			{
+			break;
+			}
+		}
+	return ret;
+	}
+
+TInt COpenFont::FreeShaperCacheMemory(TInt aBytesNeeded)
+	{
+	TInt totalDeletedBytes = 0;
+	TInt tempDeletedBytes = 0;
+	CFontStore* thisFontStore = File()->GetFontStore();
+
+	if (aBytesNeeded <= KMaxShaperSesssionCacheMemory)
+		{
+		// delete LRU entries from all the caches except the one owned by this COpenFont
+		// The 'if' condition here is to avoid looping through every font in the system
+		// if only one of the them has a non-empty cache. In situations where only one
+		// cache is left and it is full, this strategy makes freeing the memory faster.
+		if (thisFontStore->GetNumShaperCaches() > 1)
+			{
+			CArrayPtrFlat<COpenFont>* fontList;
+			CArrayPtrFlat<COpenFontFile>* fontFileList = thisFontStore->GetOpenFontFileList();
+			TInt numberOfFontFiles = fontFileList->Count();
+			TInt i = 0; 
+			while ((totalDeletedBytes < aBytesNeeded) && (i < numberOfFontFiles))
+				{
+				fontList = (*fontFileList)[i]->GetOpenFontList();
+				TInt fontListCount=fontList->Count();
+				TInt j = 0;
+				while ((totalDeletedBytes < aBytesNeeded) && (j < fontListCount))
+					{
+					COpenFont* open_font = (*fontList)[j];
+					COpenFontGlyphCache* glyphCache = open_font->GetGlyphCache();
+					if ((open_font != this) && (glyphCache != NULL))
+						{
+						while ((totalDeletedBytes < aBytesNeeded) && (!glyphCache->ShaperCacheIsEmpty()))
+							{
+							totalDeletedBytes += glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
+							if (glyphCache->ShaperCacheIsEmpty())
+								{
+								thisFontStore->DecNumShaperCaches();
+								}
+								
+							// If totalDeletedBytes is zero mean we cannot delete from this font
+							if (totalDeletedBytes == 0)
+								{
+								break;
+								}
+							}
+						}
+					j++;
+					}
+				i++;
+				}
+			}
+			
+		// If deleted bytes are still less than the required one delete from this font
+#ifdef FNTSTORE_SUPPORT_FMM
+		COpenFontGlyphCache* glyphCache = GetGlyphCache();
+#else
+		COpenFontGlyphCache* glyphCache = iGlyphCache;
+#endif // FNTSTORE_SUPPORT_FMM
+		while (totalDeletedBytes < aBytesNeeded && !glyphCache->ShaperCacheIsEmpty())
+			{				
+			tempDeletedBytes = glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
+			if ( tempDeletedBytes == 0)
+				break;
+			totalDeletedBytes += tempDeletedBytes;
+			}
+		}
+		
+	// Update the global CFontStore cache memory count
+	if (totalDeletedBytes > 0)
+		{
+		thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - totalDeletedBytes);
+		}
+
+	return totalDeletedBytes;
+	}
+
+TShapeHeader* COpenFont::InsertShapedDataIntoCache(TInt aSessionHandle,TFontShapeFunctionParameters* aParams, TShapeHeader* aShapeHeader)
+	{
+	CShaper::TInput input;
+	input.iEnd = aParams->iEnd;
+	input.iStart = aParams->iStart;
+	input.iScript = aParams->iScript;
+	input.iLanguage = aParams->iLanguage;
+	input.iText = aParams->iText;
+	input.iMaximumAdvance = KMaxTInt;
+	input.iFlags = 0;
+	input.iSessionHandle = aSessionHandle;
+	input.iReserved1 = 0;
+
+	CFontStore* thisFontStore = File()->GetFontStore();
+
+	// Create the glyph cache if it doesnt already exist.
+	// This call can only come from FBSERV
+	if (iGlyphCache == NULL)
+		{
+		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
+		if (iGlyphCache == NULL) // no memory
+			{
+			return NULL;
+			}
+		new(iGlyphCache) COpenFontGlyphCache;
+		}
+	// If there is no sentinel present, i.e. new cache
+	if (iGlyphCache->iShaperCacheSentinel == NULL)
+		{
+		// Create a sentinel
+		iGlyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap);
+		if (!iGlyphCache->iShaperCacheSentinel)
+			{
+			// no memory
+			return NULL;
+			}
+		iGlyphCache->iShaperCacheSentinel->iNext = iGlyphCache->iShaperCacheSentinel;
+		iGlyphCache->iShaperCacheSentinel->iPrevious = iGlyphCache->iShaperCacheSentinel;
+		iGlyphCache->iNumberOfShaperCacheEntries = 1;
+		}
+
+	// Before inserting into this cache, check if it was empty.
+	// If empty, then increment the global cache count signifying one more cache is active
+	if (iGlyphCache->ShaperCacheIsEmpty())
+		{
+		thisFontStore->IncNumShaperCaches();
+		}
+
+	TInt addedBytes = 0;
+	TShapeHeader* cached_header = NULL;
+
+	// Insert a new entry and return the newly inserted TShapeHeader entry
+	cached_header = iGlyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes);
+	if (cached_header == NULL)
+		return NULL;
+
+	// If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then
+	// free some memory by releasing the same amount of memory that was just added
+	if (thisFontStore->GetShaperCacheMemUsage() + addedBytes > KMaxShaperSesssionCacheMemory)
+		{
+		FreeShaperCacheMemory(addedBytes);
+		}
+
+	// Now update the memory count with the added memory for the new entry
+	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
+	return cached_header;
+	}
+
+TShapeHeader* COpenFont::GetShapedData(TInt aSessionHandle, TFontShapeFunctionParameters* aParams)
+	{
+	if (iGlyphCache == NULL)
+		return NULL;
+
+	TShapeHeader* cachedHeader = NULL;
+	CFontStore* thisFontStore = File()->GetFontStore();
+
+	// Always update the memory usage of the cache as increasing the reference count of a found header uses up memory
+	TInt allocBefInc = 0;
+	TInt allocAfterInc = 0;
+	iHeap->AllocSize(allocBefInc);
+	
+#ifdef FNTSTORE_SUPPORT_FMM
+	COpenFontGlyphCache* glyphCache = GetGlyphCache();
+#else
+	COpenFontGlyphCache* glyphCache = iGlyphCache;
+#endif // FNTSTORE_SUPPORT_FMM
+	cachedHeader = glyphCache->SearchShaperCache(aSessionHandle,aParams);
+	
+	iHeap->AllocSize(allocAfterInc);
+	TInt addedBytes = allocAfterInc - allocBefInc;
+	glyphCache->iShapingInfoCacheMemory += addedBytes;
+	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
+
+	return cachedHeader;
+	}
+
+TBool COpenFontGlyphCache::ShaperCacheIsEmpty()
+	{
+	if (iShaperCacheSentinel == NULL)
+		return ETrue;
+
+	if (iShaperCacheSentinel->iNext == iShaperCacheSentinel)
+		return ETrue;
+	else
+		return EFalse;
+	}
+
+/**
+C++ constructor taking shared heap, session cache list and font file as parameters.
+
+You must either use this, or the other constructor, when creating your derived 
+object. This constructor might be used, in preference to the other, if there 
+is only a single typeface in the font file.
+
+@param aHeap The shared heap. 
+@param aSessionCacheList The session cache list.
+@param aFile A pointer to the COpenFontFile object creating this COpenFont. 
+e.g. when creating a COpenFont the COpenFontFile derived object would pass 
+it this.
+*/
+#ifdef FNTSTORE_SUPPORT_FMM
+EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList,
+							  COpenFontFile* aFile):
+	iHeap(aHeap),
+	iShaper(NULL),
+	iFile(aFile),
+	iFaceIndex(0),
+	iSessionCacheList(aSessionCacheList)
+	{	
+	iStartingThis=reinterpret_cast<TInt>(this);
+	}
+#else
+EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile)
+ :	iHeap(aHeap),
+	iShaper(NULL),
+	iFile(aFile),
+	iFaceIndex(0),
+	iSessionCacheList(aSessionCacheList),
+	iReserved(NULL)
+	{
+
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/**
+C++ constructor taking shared heap, session cache list, font file and face 
+index as parameters.
+
+You must either use this, or the other constructor, when creating your derived 
+object. This constructor would be used if the font file contains more than 
+one typeface.
+
+@param aHeap The shared heap.
+@param aSessionCacheList The session cache list.
+@param aFile A pointer to the COpenFontFile object creating this COpenFont. 
+e.g. when creating a COpenFont the COpenFontFile derived object would pass 
+it this.
+@param aFaceIndex The index of the typeface within the font file aFile.
+*/
+#ifdef FNTSTORE_SUPPORT_FMM
+EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex) :
+ 	iHeap(aHeap),
+	iShaper(NULL),
+	iFile(aFile),
+	iFaceIndex(aFaceIndex),
+	iSessionCacheList(aSessionCacheList)
+	{
+	iStartingThis=reinterpret_cast<TInt>(this);
+	}
+#else
+EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex)
+ :	iHeap(aHeap),
+	iShaper(NULL),
+	iFile(aFile),
+	iFaceIndex(aFaceIndex),
+	iSessionCacheList(aSessionCacheList),
+	iReserved(NULL)
+	{
+
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/**
+Destructor
+
+This function frees all memory owned by the object, including the session 
+cache list and the glyph list, prior to its destruction.
+*/
+EXPORT_C COpenFont::~COpenFont()
+	{
+	//Delete the shaper
+	delete iShaper;
+
+	File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
+	
+	if (iGlyphCache)
+		{
+		COpenFontGlyphTreeEntry* next = NULL;
+#ifdef FNTSTORE_SUPPORT_FMM
+		TInt ii;
+		RArrayGlyphEntries& glyphArray=iGlyphCache->iGlyphArray;
+		for (ii=glyphArray.Count()-1;ii>=0;--ii)
+			{
+			next=&glyphArray[ii];
+			COpenFontGlyph::Delete(iHeap,next);
+			}
+		iGlyphCache->iGlyphArray.Close();
+#else
+		for (COpenFontGlyphTreeEntry* g = iGlyphCache->iGlyphList; g; g = next)
+			{
+			next = g->iNext;
+			COpenFontGlyph::Delete(iHeap, g);
+			}
+#endif // FNTSTORE_SUPPORT_FMM
+
+		// Delete the shaper cache as well
+		if (iGlyphCache->iShaperCacheSentinel)
+			{
+			COpenFontShaperCacheEntry* previous  = NULL;
+			COpenFontShaperCacheEntry* si = iGlyphCache->iShaperCacheSentinel->iPrevious;
+			TInt heapBefore = 0;
+			TInt heapAfter = 0;
+			iHeap->AllocSize(heapBefore);
+			while (iGlyphCache->iNumberOfShaperCacheEntries > 0)
+				{
+				previous = si->iPrevious;
+				COpenFontShaperCacheEntry::Delete(iHeap, si);
+				si = previous;
+				iGlyphCache->iNumberOfShaperCacheEntries--;
+				}
+			iHeap->AllocSize(heapAfter);
+			File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter));
+			File()->GetFontStore()->DecNumShaperCaches();
+			}
+
+		iHeap->Free(iGlyphCache);
+		}
+	if (iSessionCacheList)	
+		iSessionCacheList->DeleteFontGlyphs(iHeap, this);
+	if (iFile)
+		iFile->RemoveFontFromList(this);
+	}
+
+COpenFontGlyph::~COpenFontGlyph()
+	{
+	}
+
+void COpenFontGlyph::Delete(RHeap* aHeap, COpenFontGlyph* aGlyph)
+	{
+	if (aGlyph)
+		{
+#ifdef FNTSTORE_SUPPORT_FMM
+		aHeap->Free(aGlyph->Bitmap());
+#else
+		aHeap->Free(aGlyph->iBitmap);
+#endif // FNTSTORE_SUPPORT_FMM
+		aHeap->Free(aGlyph);
+		}
+	}
+
+EXPORT_C void COpenFont::operator delete(TAny *aFont)
+	{
+	if(aFont)
+		{
+		COpenFont* f = (COpenFont*)aFont;
+		if (f->iHeap)
+			f->iHeap->Free(aFont);
+		}
+	}
+
+/**
+Rasterize a glyph
+
+This function may only be called via an FBSERV message.
+
+@param aSessionHandle Session handle of the calling session
+@param aCode Unicode value or glyph code if top bit is set
+@param aGlyphData
+	Output data. May be null, in which case output may be
+	obtained through a call to GetCharacterData.
+
+@return
+	ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap()
+	and aGlyphData->Metrics() are valid), EFalse otherwise.
+*/
+#ifdef FNTSTORE_SUPPORT_FMM
+TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
+	TOpenFontGlyphData* aGlyphData)
+	{
+	// create the cache if it doesn't exisit. As this call can only come from
+	// FBSERV if the chunk has to be resized then no panic will happen.
+	if (iGlyphCache == NULL)
+		{
+		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
+		if (iGlyphCache == NULL) // no memory
+			{
+			return EFalse;
+			}
+		new(iGlyphCache) COpenFontGlyphCache;
+		}
+
+	// Look in the Font Cache	
+	TInt* nodeInsertPtr = NULL;	
+	const COpenFontGlyph* g = FontCacheGlyph(aCode, nodeInsertPtr);		 	
+
+	// If it is not found there look in the session cache.
+	COpenFontSessionCache* cache = NULL;
+	TInt index = 0;
+	if (!g)
+		{
+		g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse);
+		}
+
+	// If it has already been rasterized return it.
+	if (g)
+		{
+		if (aGlyphData)
+			{
+			aGlyphData->SetMetricsPointer(&g->iMetrics);
+			aGlyphData->SetBitmapPointer(g->Bitmap());
+			}
+
+		return ETrue;
+		}
+
+	// Rasterize the glyph.
+	TOpenFontGlyphData* temp_glyph_data = NULL;
+	TInt error = KErrNone;
+	TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
+	if (error != KErrNone)
+		{
+		iHeap->Free(temp_glyph_data);
+		return EFalse;
+		}
+
+	TBool glyph_data_valid = ETrue;
+	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
+	const COpenFontGlyph* new_glyph = NULL;
+
+	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
+	TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded();	
+	if(iGlyphCache && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
+		{
+		COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
+		new_glyph=new_entry;
+		if(new_entry)
+			{
+			// Insert new entry into the delete list 
+			error = iGlyphCache->iGlyphArray.Append(*new_entry);
+			if (error == KErrNone)
+				{
+				if(!iGlyphCache->iGlyphTreeOffset)
+					{
+					// First entry in tree
+					iGlyphCache->iGlyphTreeOffset = PointerToThisOffset(new_entry);
+					}	
+				else if (nodeInsertPtr)
+					{
+					// Add the glyph to a leaf node using the nodeInsertPtr that was returned by FontCacheGlyph()
+					*nodeInsertPtr = PointerToThisOffset(new_entry);
+					}
+				else 
+					{
+					// Failed to add the glyph to the glyph tree, remove it from the delete array.
+					// (The glyph is deleted below).
+					iGlyphCache->iGlyphArray.Remove(iGlyphCache->iGlyphArray.Count()-1);					
+					error = KErrGeneral;
+					}
+				}
+			if (error != KErrNone)
+				{
+				COpenFontGlyph::Delete(iHeap,new_entry);
+				}
+			else
+				{
+				iGlyphCache->iGlyphCacheMemory += bytes;
+				}		
+			}
+		}
+	else
+		{
+		error = KErrGeneral;
+		}
+
+	// Otherwise put the glyph into the per-session cache.
+	if (error != KErrNone)
+		{
+		// If the session cache is not yet known find it or create one.
+		if (!cache)
+			{
+			SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE);
+			}
+		if (!cache)
+			{			
+			return EFalse;
+			}
+
+		COpenFontSessionCacheEntry* new_entry =
+			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
+		new_glyph = new_entry;
+		if (new_entry)
+			{
+			cache->Insert(iHeap, new_entry, index);
+			}
+		}
+
+	if (temp_glyph_data)
+		{
+		iHeap->Free(temp_glyph_data);
+        }
+        
+    // Fix up the returned glyph data pointers to point to the actual data.
+    if (!new_glyph)
+        glyph_data_valid = FALSE;
+    else if (aGlyphData)
+        {
+        aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
+        aGlyphData->SetBitmapPointer(new_glyph->Bitmap());
+        }
+
+	return glyph_data_valid;
+	}
+#else
+TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
+	TOpenFontGlyphData* aGlyphData)
+	{
+	// First look in the font cache.
+	COpenFontGlyphTreeEntry** node_ptr = NULL;
+	// create the cache if it doesn't exisit. As this call can only come from
+	// FBSERV if the chunk has to be resized then no panic will happen.
+	if (iGlyphCache == NULL)
+		{
+		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
+		if (iGlyphCache == NULL) // no memory
+			{
+			return FALSE;
+			}
+		new(iGlyphCache) COpenFontGlyphCache;
+		}
+	
+	// Look in the fontcache. Do not expect to find a glyph here. However, 
+	// it is called again so that a node pointer is found where the new glyph
+	// will be placed when added to the font cache.
+	const COpenFontGlyph* glyph = FontCacheGlyph(aCode, node_ptr);
+	if (glyph)
+		{
+		// Do not expect it to get here, since the font cache has already been searched client-side,
+		// prior to calling Rasterize(). However, just in case it does find a match, use it.
+		if (aGlyphData)
+			{
+			aGlyphData->SetMetricsPointer(&glyph->iMetrics);
+			aGlyphData->SetBitmapPointer(glyph->iBitmap);
+			}
+		return TRUE;
+		}
+		
+	// Rasterize the glyph.
+	TOpenFontGlyphData* temp_glyph_data = NULL;
+	TInt error = KErrNone;
+	TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
+	if (error)
+		{
+		iHeap->Free(temp_glyph_data);
+		return FALSE;
+		}
+
+	TBool glyph_data_valid = TRUE;
+	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
+	const COpenFontGlyph* new_glyph = NULL;
+
+	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
+	TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded();
+	if (iGlyphCache && node_ptr && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
+		{
+		COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
+		new_glyph = new_entry;
+		if (new_entry)
+			{
+			*node_ptr = new_entry;	// update the cache atomically
+
+			// Insert new entry into the delete list 
+
+			COpenFontGlyphTreeEntry* start = iGlyphCache->iGlyphTree;
+			COpenFontGlyphTreeEntry* tree = start;
+
+			if (new_entry != iGlyphCache->iGlyphTree)
+				{
+				while (tree->iNext)
+					{
+					tree = tree->iNext;
+					}
+				tree->iNext = new_entry;
+				}
+			else
+				{
+				// First entry in tree, initialise iGlyphList
+				iGlyphCache->iGlyphList = new_entry;
+				}
+
+			iGlyphCache->iGlyphCacheMemory += bytes;
+			}
+		}
+
+	// Otherwise put the glyph into the per-session cache.
+	else
+		{
+		// If the session cache is not yet known find it or create one.
+		COpenFontSessionCache* cache = NULL;
+		TInt index = 0;
+		SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE);
+		if (!cache)
+			return FALSE;
+		COpenFontSessionCacheEntry* new_entry =
+			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
+		new_glyph = new_entry;
+		if (new_entry)
+			cache->Insert(iHeap, new_entry, index);
+		}
+
+	if (temp_glyph_data)
+		{
+            iHeap->Free(temp_glyph_data);
+        }
+        
+    // Fix up the returned glyph data pointers to point to the actual data.
+    if (!new_glyph)
+        glyph_data_valid = FALSE;
+    else if (aGlyphData)
+        {
+        aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
+        aGlyphData->SetBitmapPointer(new_glyph->iBitmap);
+        }
+
+	return glyph_data_valid;
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData)
+	{
+	aTempGlyphData = 0;
+	MOpenFontShapingExtension* extensionInterface = 0;
+
+	// if the MSB is set this is a request to rasterize a glyph code
+	// rather than a unicode value.  This can only be done if the rasterizer
+	// supports the extended API. 
+	if ( aCode & 0x80000000 )
+		{
+		aCode = GLYPH_CODE(aCode);
+		// get the extension API for RasterizeGlyphL() if available
+		TAny* ext = NULL;
+		ExtendedInterface(KUidOpenFontShapingExtension, ext);
+		extensionInterface = reinterpret_cast<MOpenFontShapingExtension*>(ext);
+
+		if (!extensionInterface)
+			// an attempt to rasterize a glyph when the rasterizer does not
+			// support it; best to do nothing
+			return;
+		}
+	TOpenFontGlyphData* currGlyphData = aGlyphData;
+
+	if (!currGlyphData)
+		{
+		aTempGlyphData = TOpenFontGlyphData::New(iHeap, 0);
+		if (!aTempGlyphData)
+			User::Leave(KErrNoMemory);
+		currGlyphData = aTempGlyphData;
+		}
+
+	if (extensionInterface)
+		extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
+	else
+		RasterizeL(aCode, currGlyphData);
+
+	// If the GlyphData object was not large enough, create a temporary one
+	// that can then be deleted by the caller.
+	if (currGlyphData->Overflow())
+		{
+		TInt bytesNeeded = currGlyphData->BytesNeeded();
+		if (aTempGlyphData)
+			iHeap->Free(aTempGlyphData);
+		aTempGlyphData = TOpenFontGlyphData::New(iHeap, bytesNeeded);
+		if (!aTempGlyphData)
+			User::Leave(KErrNoMemory);
+		
+		currGlyphData = aTempGlyphData;
+
+		// If the extension interface was used above, then use again here
+		if (extensionInterface)
+			extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
+		else
+			RasterizeL(aCode, currGlyphData);
+		}
+		
+	if (currGlyphData->Metrics() == NULL) 
+		{
+		User::Leave(KErrArgument);
+		}
+	}
+
+/** @internalComponent */
+void COpenFont::SetShaper(CShaper* aShaper)
+	{
+	iShaper = aShaper;
+	}
+	
+/** @internalComponent */
+CShaper* COpenFont::GetShaper()
+	{
+	return iShaper;
+	}
+
+/** @internalComponent */
+TBool COpenFont::HasShaper() const
+	{
+	return iShaper != NULL;
+	}
+
+void COpenFont::DeleteShaper() const
+	{
+	delete iShaper;
+	}
+
+TInt COpenFont::GetFontTable(TUint32 aTag, TAny*& aTableContent, TInt& aLength) 
+    {
+    // get the extension API for GetTrueTypeTable() if available
+    TAny* ext = NULL;
+    ExtendedInterface(KUidOpenFontTrueTypeExtension, ext);
+    MOpenFontTrueTypeExtension* extensionInterface = 
+        reinterpret_cast<MOpenFontTrueTypeExtension*>(ext);
+
+    TInt ret = KErrNone;
+    if (!extensionInterface)
+        {
+        ret = KErrNotSupported;
+        }
+    else 
+        {
+        TUint32 tag = aTag;
+        TInt len = 0;
+        aTableContent = extensionInterface->GetTrueTypeTable(ret, tag, &len);
+        if (KErrNone == ret) 
+            {
+            aLength = len;
+            }
+        }
+    return ret;
+    }
+
+TInt COpenFont::GetGlyphOutline(TUint aCode, 
+        TBool aHinted, TAny*& aOutline, TInt &aLength) 
+    {
+    // get the extension API for GetTrueTypeTable() if available
+    TAny* ext = NULL;
+    ExtendedInterface(KUidOpenFontGlyphOutlineExtension, ext);
+    MOpenFontGlyphOutlineExtension *extensionInterface = 
+        reinterpret_cast<MOpenFontGlyphOutlineExtension*>(ext);
+
+    TInt ret = KErrNone;
+    if (!extensionInterface)
+        {
+        ret = KErrNotSupported;
+        }
+    else 
+        {
+        ret = extensionInterface->GetGlyphOutline(aCode, ETrue, 
+                aHinted, aOutline, aLength);
+        }
+    return ret;
+    }
+#ifdef FNTSTORE_SUPPORT_FMM
+/** Given the passed pointer aAny, return an offset from it to the "this" pointer
+of this COpenFont object.
+@param aAny A pointer to an object that exists on the shared heap, i.e. the same heap
+that this CCOpenFont object was created on.
+@return An offset relative to the "this" pointer for this object, this offset can
+be converted back to a pointer using ThisOffsetToPointer().
+@see ThisOffsetToPointer().
+@internalComponent 
+ */
+TInt COpenFont::PointerToThisOffset(const TAny* aAny)
+	{
+	if (aAny)
+		{
+		return ((TInt)aAny - (TInt)this);
+		}
+	return 0;
+	}
+
+/** Given the passed passed offset aThisOffset, convert it to a pointer relative to
+the "this" pointer for this object.
+@param aThisOffset An offset that was generated using PointerToThisOffset().
+@return A pointer that has been created by adding (this+aThisOffset).
+@see PointerToThisOffset().
+@internalComponent 
+ */
+TAny* COpenFont::ThisOffsetToPointer(const TInt aThisOffset)
+	{
+	if (aThisOffset)
+		{
+		return (TAny*)((TInt)this + aThisOffset);
+		}
+	return NULL;
+	}		
+#endif // FNTSTORE_SUPPORT_FMM
+
+/**
+A constructor initialised with a TCharacterMetrics object.
+
+This is the old-style character metrics object. As for other T classes, there 
+is no need to explicitly cleanup TOpenFontCharMetrics objects.
+
+@param aMetrics The old-style metrics object.
+*/
+EXPORT_C TOpenFontCharMetrics::TOpenFontCharMetrics(const TCharacterMetrics& aMetrics)
+	{
+	iWidth = (TInt16)(aMetrics.iMoveInPixels - aMetrics.iLeftAdjustInPixels - aMetrics.iRightAdjustInPixels);
+	iHeight = aMetrics.iHeightInPixels;
+	iHorizBearingX = aMetrics.iLeftAdjustInPixels;
+	iHorizBearingY = aMetrics.iAscentInPixels;
+	iHorizAdvance = aMetrics.iMoveInPixels;
+	iVertBearingX = 0;
+	iVertBearingY = 0;
+	iVertAdvance = aMetrics.iHeightInPixels;
+	iGlyphBitmapType = 0;
+	}
+
+/**
+Converts a TOpenFontCharacterMetrics object to a TCharacterMetrics.
+
+@param aMetrics On return, contains the character's old-style metrics. 
+@return ETrue if it was possible to get the metrics, otherwise EFalse.
+*/
+EXPORT_C TBool TOpenFontCharMetrics::GetTCharacterMetrics(TCharacterMetrics& aMetrics) const
+	{
+	aMetrics.iAscentInPixels = iHorizBearingY;
+	aMetrics.iHeightInPixels = iHeight;
+	aMetrics.iLeftAdjustInPixels = iHorizBearingX;
+	aMetrics.iMoveInPixels = iHorizAdvance;
+	aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth);
+	return TRUE;
+	}
+
+TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const
+	{
+	const COpenFontGlyph* g = Glyph(aSessionHandle, aCode);
+	if (g)
+		{
+		aMetrics = &g->iMetrics;
+#ifdef FNTSTORE_SUPPORT_FMM
+		aBitmap = g->Bitmap();
+#else
+		aBitmap = g->iBitmap;
+#endif // FNTSTORE_SUPPORT_FMM
+		return TRUE;
+		}
+	else
+		{
+		aMetrics = NULL;
+		aBitmap = NULL;
+		return FALSE;
+		}
+	}
+
+
+
+void COpenFont::OnFileDeleted()
+	{
+	iFile = NULL;
+	}
+
+COpenFontGlyphCache* COpenFont::GetGlyphCache()
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (iGlyphCache)
+		return reinterpret_cast<COpenFontGlyphCache*>(reinterpret_cast<TInt>(iGlyphCache)+Offset());
+#else
+	if (iGlyphCache)
+		return iGlyphCache;
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return NULL;
+	}
+
+const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const
+	{	
+#ifdef FNTSTORE_SUPPORT_FMM
+	const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode);
+	if (!glyph)
+		{			
+		COpenFontSessionCache* cache;
+		TInt index;
+		glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE);
+	}
+
+	return glyph;
+#else
+	const COpenFontGlyph* g = CONST_CAST(COpenFont*,this)->FontCacheGlyph(aCode);
+	if (!g)
+		{
+		COpenFontSessionCache* cache;
+		TInt index;
+		g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE);
+		}
+	return g;
+#endif // FNTSTORE_SUPPORT_FMM
+	}
+
+/**
+Is the specified character present in the font?
+*/
+TBool COpenFont::HasCharacterL(TInt aCode) const
+	{
+	COpenFontFile* file = File();
+	if (file)
+		return file->HasUnicodeCharacterL(iFaceIndex, aCode);
+	else
+		return FALSE;
+	}
+
+#ifdef FNTSTORE_SUPPORT_FMM
+/**
+Retrieve glyph data from the per-font glyph cache.
+If it is not found return NULL. 
+If the cache hasn't been created, then return NULL.
+Previous versions of this function created the cache, but as this function can potentially
+run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
+be resized - this is not allowed by the kernel.
+The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
+@param aCode The code for the glpyh to look for in the cache
+@return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
+*/
+const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
+	{		
+	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
+		{		
+		COpenFontGlyphTreeEntry* node = NULL;		
+		if (glyphCache->iGlyphTreeOffset)
+			{			
+			node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
+			}
+				
+		while (node)
+			{
+			TInt code = node->iCode;
+			if(code == aCode)
+				{
+				// Found the glyph
+				return node;
+				}		
+			else if(code > aCode)
+				{									
+				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
+				}
+			else
+				{										
+				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
+				}
+			}		
+		}
+	// No glyph found
+	return NULL;
+	}
+	
+/**
+Retrieve glyph data from the per-font glyph cache.
+If it is not found return NULL and place the address of the node pointer
+to receive a new glyph in aNodeInsertPtr. 
+If the cache hasn't been created, then return NULL.
+Previous versions of this function created the cache, but as this function can potentially
+run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
+be resized - this is not allowed by the kernel.
+The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
+@param aCode The code for the glpyh to look for in the cache
+@param aNodeInsertPtr Returns a pointer to a final empty left or right leaf node
+in the glpyh tree where the searched for glyph can be inserted if necessary.
+@return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
+*/
+const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode, TInt*& aNodeInsertPtr)
+	{		
+	aNodeInsertPtr = NULL;	
+
+	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
+		{		
+		COpenFontGlyphTreeEntry* node = NULL;		
+		if (glyphCache->iGlyphTreeOffset)
+			{			
+			node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
+			}
+				
+		while (node)
+			{
+			TInt code = node->iCode;
+			if(code == aCode)
+				{
+				// Found the glyph
+				return node;
+				}		
+			else if(code > aCode)
+				{					
+				aNodeInsertPtr = &node->iLeftOffset;
+				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
+				}
+			else
+				{						
+				aNodeInsertPtr = &node->iRightOffset;
+				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
+				}
+			}		
+		}
+
+	// No glyph found
+	return NULL;
+	}
+#else
+/**
+Retrieve glyph data from the per-font glyph cache.
+If it is not found return NULL. 
+If the cache hasn't been created, then return null.
+Previous versions of this function created the cache, but as this function can potentially
+run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
+be resized - this is not allowed by the kernel.
+The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
+*/
+const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
+	{
+	if (iGlyphCache)
+		{					
+		COpenFontGlyphTreeEntry* node = iGlyphCache->iGlyphTree;
+		while (node)
+			{
+			if (node->iCode == aCode)
+				return node;
+			if (node->iCode > aCode)
+				node = node->iLeft;
+			else
+				node = node->iRight;
+			}			
+		}
+	
+	return NULL;
+	}
+
+/**
+Retrieve glyph data from the per-font glyph cache.
+If it is not found return NULL and place the address of the node pointer
+to receive a new glyph in aNode. 
+If the cache hasn't been created, then return null.
+Previous versions of this function created the cache, but as this function can potentially
+run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
+be resized - this is not allowed by the kernel.
+The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
+*/
+const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode, COpenFontGlyphTreeEntry**& aNode)
+	{
+	if (!iGlyphCache)
+		{
+		aNode = NULL;
+		return NULL;
+		}
+
+	aNode = &iGlyphCache->iGlyphTree;
+	while (*aNode)
+		{
+		if ((*aNode)->iCode == aCode)
+			return *aNode;
+		if ((*aNode)->iCode > aCode)
+			aNode = &((*aNode)->iLeft);
+		else
+			aNode = &((*aNode)->iRight);
+		}
+	
+	return NULL;
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/** Retrieve glyph data from the session cache. If the glyph is not in the
+cache, return the cache and glyph index where the glyph data should be put. If
+there is no session cache, optionally create it.
+
+@param aHeap
+	The heap on which to create the new cache, if appropriate. Not used if
+	either the appropriate session cache already exists, or if aCreate is
+	passed as false
+@param aSessionHandle The session handle
+@param aCode
+	The code of the glyph to look up (Unicode or glyph code if the top bit is
+	set)
+@param aCache
+	Returns the appropriate session cache, or NULL if an attempt to create it 
+	has failed.
+@param aIndex
+	Returns where the glyph is, or should be put
+@param aCreate
+	If False, creation of a new cache is inhibited
+@return The glyph data, or null if the glyph is not in the cache
+@internalComponent
+*/
+#ifdef FNTSTORE_SUPPORT_FMM
+const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
+	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
+	TInt& aIndex, TBool aCreate) const
+	{
+	aIndex = 0;
+	COpenFontSessionCacheListItem* prev = NULL;
+
+	COpenFontSessionCacheList* cachelist = const_cast<COpenFont*>(this)->SessionCacheList();
+	RSemaphore sem;
+	if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
+	    {
+	    RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore"));
+	    return NULL;
+	    }
+	sem.Wait();
+	COpenFontSessionCacheListItem* cacheListStart=cachelist->Start();
+	if(cacheListStart)
+		{
+		for (COpenFontSessionCacheListItem* p = cacheListStart; p; p = p->Next())
+			{
+			COpenFontSessionCache* cache=p->Cache();
+			if (cache->iSessionHandle == aSessionHandle)
+				{
+				aCache = cache;
+				sem.Signal();
+				sem.Close();
+				return aCache->Glyph(this,aCode,aIndex);
+				}
+			prev = p;
+			}
+		}
+	sem.Signal();
+	sem.Close();
+	
+	if (aCreate)
+		{
+		COpenFontSessionCache* new_cache = NULL;
+		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
+		
+		if ((!error) && new_cache)
+			{
+			COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem));
+			if (!new_item)
+				{
+				new_cache->Delete(aHeap);	
+				aHeap->Free(new_cache);
+				return NULL;
+				}
+
+			new(new_item) COpenFontSessionCacheListItem(new_cache);
+
+			if (prev)
+				{
+				prev->SetNext(new_item);
+				}
+			else
+				{
+				cachelist->SetStart(new_item);
+				}
+
+			aCache = new_cache;
+			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
+			}
+		}
+	return NULL;
+	}
+#else
+const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
+	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
+	TInt& aIndex, TBool aCreate) const
+	{
+	aCache = NULL;
+	aIndex = 0;
+	COpenFontSessionCacheListItem* prev = NULL;
+    RSemaphore sem;
+    if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
+        {
+        RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore"));
+        return NULL;
+        }
+    sem.Wait();
+	for (COpenFontSessionCacheListItem* p = iSessionCacheList->iStart; p; p = p->iNext)
+		{
+		if (p->iCache->iSessionHandle == aSessionHandle)
+			{
+			aCache = p->iCache;
+		    sem.Signal();
+		    sem.Close();
+			return aCache->Glyph(this, aCode, aIndex);
+			}
+		prev = p;
+		}
+    sem.Signal();
+	sem.Close();
+	
+	if (aCreate)
+		{
+		COpenFontSessionCache* new_cache = NULL;
+		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
+		
+		if ((!error) && new_cache)
+			{
+			COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem));
+			if (!new_item)
+				{
+				new_cache->Delete(aHeap);	
+				aHeap->Free(new_cache);
+				return NULL;
+				}
+
+			new(new_item) COpenFontSessionCacheListItem(new_cache);
+
+			if (prev)
+				prev->iNext = new_item;
+			else
+				iSessionCacheList->iStart = new_item;
+
+			aCache = new_cache;
+			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
+			}
+		}
+	return NULL;
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/**
+Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
+The data is copied; ownership remains with the caller.
+*/
+COpenFontGlyph* COpenFontGlyph::NewL(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
+	{
+	COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->AllocL(sizeof(COpenFontGlyph));
+	new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
+	if (!glyph->SetBitmap(aHeap, aBitmap))
+		{
+		aHeap->Free(glyph);
+		User::Leave(KErrNoMemory);
+		}
+	return glyph;
+	}	
+
+COpenFontGlyphTreeEntry* COpenFontGlyphTreeEntry::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
+	{
+	COpenFontGlyphTreeEntry* entry = (COpenFontGlyphTreeEntry*)aHeap->Alloc(sizeof(COpenFontGlyphTreeEntry));
+	if (!entry)
+		return NULL;
+	new(entry) COpenFontGlyphTreeEntry(aCode, aGlyphIndex, aMetrics);
+	if (!entry->SetBitmap(aHeap, aBitmap))
+		{
+		aHeap->Free(entry);
+		entry = NULL;
+		}
+	return entry;
+	}
+
+COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) 
+	{
+	COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry));
+	if (!entry)
+		return NULL;
+	new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
+	if (!entry->SetBitmap(aHeap, aBitmap))
+		{
+		aHeap->Free(entry);
+		entry = NULL;
+		}
+	return entry;
+	}
+
+#ifdef FNTSTORE_SUPPORT_FMM
+
+inline COpenFont* COpenFontSessionCacheEntry::Font()const
+{
+if(iFontOffset)
+    {
+    return reinterpret_cast<COpenFont*>(reinterpret_cast<TInt>(this) + iFontOffset);
+    }
+else
+    return NULL;
+}
+
+/**
+@return A pointer to the run-length-encoded bitmap stored with this glyph, or NULL
+if no bitmap has been stored with this glyph.
+ */
+TUint8* COpenFontGlyph::Bitmap() const
+	{
+	if (iBitmapOffset)
+		{
+		return (TUint8*)((TInt)this + iBitmapOffset);
+		}
+	return NULL;
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+TBool COpenFontGlyph::SetBitmap(RHeap* aHeap, const TDesC8& aBitmap)
+	{
+	TUint8* bitmap = (TUint8*)aHeap->Alloc(aBitmap.Length());
+	if (!bitmap)
+		return FALSE;
+	Mem::Copy(bitmap, aBitmap.Ptr(), aBitmap.Length());	
+#ifdef FNTSTORE_SUPPORT_FMM
+	aHeap->Free(Bitmap());
+	iBitmapOffset = (TInt)bitmap - (TInt)this;
+#else
+	if (iBitmap)
+		aHeap->Free(iBitmap);
+	iBitmap = bitmap;
+#endif // FNTSTORE_SUPPORT_FMM
+	return TRUE;
+	}
+#ifdef FNTSTORE_SUPPORT_FMM
+COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
+	{
+	COpenFontSessionCache* c = reinterpret_cast<COpenFontSessionCache*>(aHeap->AllocL(sizeof(COpenFontSessionCache)));
+	new(c) COpenFontSessionCache(aSessionHandle,aEntries);
+	TInt bytes = sizeof(TInt) * aEntries;
+	TInt* entry= reinterpret_cast<TInt*>(aHeap->Alloc(bytes));
+	Mem::FillZ(entry, bytes);
+	if (!entry)
+		{
+		aHeap->Free(c);
+		User::Leave(KErrNoMemory);
+		}
+	c->iEntryOffset = reinterpret_cast<TInt>(entry) - reinterpret_cast<TInt>(c);
+	return c;
+	}
+#else
+COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
+    {
+    COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
+    new(c) COpenFontSessionCache(aSessionHandle,aEntries);
+    TInt bytes = sizeof(COpenFontSessionCacheEntry*) * aEntries;
+    c->iEntry = (COpenFontSessionCacheEntry**)aHeap->Alloc(bytes);
+    Mem::FillZ(c->iEntry, bytes);
+    if (!c->iEntry)
+        {
+        aHeap->Free(c);
+        User::Leave(KErrNoMemory);
+        }
+    return c;
+    }
+#endif //FNTSTORE_SUPPORT_FMM
+
+#ifdef FNTSTORE_SUPPORT_FMM
+void COpenFontSessionCache::Delete(RHeap* aHeap)
+    {
+    TInt* e =Entry();
+    if(e)
+        {
+        for (TInt i = 0; i < iEntries; i++, e++)
+            {
+            if (ToCOpenFontSessionCacheEntryPointer(*e))
+                {
+                COpenFont* font=const_cast<COpenFont*>((ToCOpenFontSessionCacheEntryPointer(*e))->Font());
+                if (font)
+                    font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue);
+                aHeap->Free((ToCOpenFontSessionCacheEntryPointer(*e))->Bitmap());
+                aHeap->Free(ToCOpenFontSessionCacheEntryPointer(*e));
+                }
+            }
+        aHeap->Free(Entry());
+        iEntryOffset = 0;
+        }
+    }
+#else
+void COpenFontSessionCache::Delete(RHeap* aHeap)
+	{
+	COpenFontSessionCacheEntry** e =iEntry;
+	for (TInt i = 0; i < iEntries; i++, e++)
+		{
+		if (*e)
+			{
+			COpenFont* font=const_cast<COpenFont*>((*e)->iFont);
+			if (font)
+				font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue);
+			aHeap->Free((*e)->iBitmap);
+			aHeap->Free(*e);
+			}
+		}
+	aHeap->Free(iEntry);
+	}
+#endif //FNTSTORE_SUPPORT_FMM
+
+const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex)
+	{
+	aIndex = -1;
+	TInt oldest = KMaxTInt;
+	TInt oldest_index = 0;
+	TInt index = GLYPH_CODE(aCode) % iEntries;	// simple hash function to shorten searches
+	for (TInt i = 0; i < iEntries; i++, index++)
+		{
+		if (index >= iEntries)
+			index = 0;		
+#ifdef FNTSTORE_SUPPORT_FMM
+		COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[index]);
+#else
+		COpenFontSessionCacheEntry* e = iEntry[index];
+#endif		//FNTSTORE_SUPPORT_FMM		
+		if (!e)
+			{
+			if (aIndex == -1)
+				aIndex = index;
+			}
+		else
+			{
+#ifdef FNTSTORE_SUPPORT_FMM
+			if (e->Font() == aFont && e->iCode == aCode)
+#else
+			if (e->iFont == aFont && e->iCode == aCode)    
+#endif //FNTSTORE_SUPPORT_FMM			    
+				{
+				e->iLastAccess = iLastAccess++;
+				return e;
+				}
+			if (e->iLastAccess < oldest)
+				{
+				oldest = e->iLastAccess;
+				oldest_index = index;
+				}
+			}
+		}
+	if (aIndex == -1)
+		aIndex = oldest_index;
+	return NULL;
+	}
+
+
+void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
+	{
+	if ((aIndex < 0) || (aIndex > iEntries))
+		Panic(EFntSessionCacheIndexOutOfRange);
+#ifdef 	FNTSTORE_SUPPORT_FMM
+	COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[aIndex]);
+	COpenFontGlyph::Delete(aHeap, e);
+	Entry()[aIndex] = reinterpret_cast<TInt>(aEntry) - reinterpret_cast<TInt>(this);
+#else
+	COpenFontGlyph::Delete(aHeap, iEntry[aIndex]);
+	iEntry[aIndex] = aEntry;
+#endif  //FNTSTORE_SUPPORT_FMM	
+	aEntry->iLastAccess = iLastAccess++;
+	}
+
+COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle, TInt aEntries)
+ :	iSessionHandle(aSessionHandle),  
+	iEntries(aEntries),
+	iLastAccess(0),
+#ifdef  FNTSTORE_SUPPORT_FMM
+    iEntryOffset(0)
+#else 
+    iEntry(NULL)
+#endif  //FNTSTORE_SUPPORT_FMM  
+	{
+	}
+
+#ifdef FNTSTORE_SUPPORT_FMM
+
+inline TInt* COpenFontSessionCache::Entry() const
+    {
+    if (iEntryOffset)
+        {
+        return reinterpret_cast<TInt*>(reinterpret_cast<TInt>(this) + iEntryOffset);
+        }
+    return NULL;
+    }
+
+inline COpenFontSessionCacheEntry* COpenFontSessionCache::ToCOpenFontSessionCacheEntryPointer(TInt aOffset)const
+    {
+    if(aOffset)
+        {
+        return reinterpret_cast<COpenFontSessionCacheEntry*>(reinterpret_cast<TInt>(this) + aOffset);
+        }
+    return NULL;
+    }
+
+#endif // FNTSTORE_SUPPORT_FMM
+
+/*COpenFontSessionCacheListItem*/
+#ifdef FNTSTORE_SUPPORT_FMM
+COpenFontSessionCacheListItem::COpenFontSessionCacheListItem(COpenFontSessionCache* aCache):
+	iNextOffset(NULL)
+	{
+	if(aCache)
+		{
+		iCacheOffset = (TInt)aCache - (TInt)this;
+		}
+	else
+		{
+		iCacheOffset = NULL;
+		}
+	}
+
+COpenFontSessionCacheListItem::~COpenFontSessionCacheListItem()
+	{
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/** Delete a COpenFontSessionCacheListItem from the passed heap.
+
+@param aHeap The heap to delete the COpenFontSessionCacheListItem from.
+ */
+void COpenFontSessionCacheListItem::Delete(RHeap* aHeap)
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	Cache()->Delete(aHeap);	
+	aHeap->Free(Cache());
+	iCacheOffset=NULL;
+	iNextOffset=NULL;
+#else
+	iCache->Delete(aHeap);	
+	aHeap->Free(iCache);
+	iCache=NULL;
+#endif // FNTSTORE_SUPPORT_FMM
+	}	
+
+#ifdef FNTSTORE_SUPPORT_FMM
+/** Get the next item to this cache list item.
+
+@return A pointer to the next item to this one in the session cache, or NULL
+if there is no next item.
+ */
+COpenFontSessionCacheListItem* COpenFontSessionCacheListItem::Next()
+	{
+	if(iNextOffset)
+		{
+		COpenFontSessionCacheListItem* next = (COpenFontSessionCacheListItem*)((TInt)this + (TInt)iNextOffset);
+		return next;
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+/** Sets the next item to this in the session cache.
+
+@param aNext Set this cache list item as the next item to this one in the session cache list.
+ */
+void COpenFontSessionCacheListItem::SetNext(COpenFontSessionCacheListItem* aNext)
+	{
+	if(aNext)
+		{
+		iNextOffset = (TInt)aNext - (TInt)this;
+		}
+	else
+		{
+		iNextOffset = NULL;
+		}
+	}
+
+/** Get a pointer to the session cache that this cache list item is in.
+
+@return A pointer to the session cache that this cache list item is part of.
+ */
+COpenFontSessionCache* COpenFontSessionCacheListItem::Cache()
+	{
+	if(iCacheOffset)
+		{
+		COpenFontSessionCache* cache = (COpenFontSessionCache*)((TInt)this + (TInt)iCacheOffset);
+		return cache;
+		}
+	else
+		{
+		return NULL;
+		}
+	}
+
+/** Get a pointer to the first item in the session cache.
+
+@return A pointer to the first item in the session cache.
+ */
+COpenFontSessionCacheListItem* COpenFontSessionCacheList::Start()
+	{
+	if(iStartOffset)
+		{
+		COpenFontSessionCacheListItem* start = (COpenFontSessionCacheListItem*)((TInt)this + (TInt)iStartOffset);
+		return start;
+		}
+	else
+		{
+		return NULL;
+		}
+
+	}
+
+/** Set the passed item as the first item in the session cache. 
+
+@param aItem An item to be added to the session cache
+ */
+void COpenFontSessionCacheList::SetStart(COpenFontSessionCacheListItem* aItem)
+	{
+	if(aItem!=NULL)
+		{
+		iStartOffset = (TInt)aItem - (TInt)this;
+		}
+	else
+		{
+		iStartOffset = 0;
+		}
+	}
+#endif // FNTSTORE_SUPPORT_FMM
+
+/** Delete all the items in the session cache if the current cache session handle
+matches the passed session handle.
+
+@param aHeap The heap base of the current process.
+@param aSessionHandle The session handle of the cache to be deleted.
+ */
+void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
+	{
+	COpenFontSessionCacheListItem* prev = NULL;
+	   RSemaphore sem;
+	    if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
+	        {
+	        RDebug::Print(_L("COpenFontSessionCacheList::DeleteCache() can't open SessionCacheSemaphore"));
+	        return;
+	        }	    
+#ifdef FNTSTORE_SUPPORT_FMM
+ 	for (COpenFontSessionCacheListItem* curr = Start(); curr; prev = curr, curr = curr->Next())
+		{
+ 		if (curr->Cache()->iSessionHandle == aSessionHandle)
+   			{
+   			for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
+   			    {
+				//coverity[lock]
+				//coverity[double_lock]
+   			    sem.Wait();
+   			    }
+ 			if (curr==Start())
+ 				SetStart(curr->Next());
+ 			else
+ 				prev->SetNext(curr->Next());
+ 				
+   			curr->Delete(aHeap);
+ 			aHeap->Free(curr);
+ 			sem.Signal(KSessionCacheSemaphoreCount);
+ 			sem.Close();
+   			return;
+   			}
+		}
+#else
+	for (COpenFontSessionCacheListItem* curr = iStart; curr; prev = curr, curr = curr->iNext)
+		{
+		if (curr->iCache->iSessionHandle == aSessionHandle)
+			{
+            for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
+               {
+               sem.Wait();
+               }
+			if (curr==iStart)
+				iStart   = curr->iNext;
+			else
+				prev->iNext = curr->iNext;
+
+			curr->Delete(aHeap);
+			aHeap->Free(curr);
+            sem.Signal(KSessionCacheSemaphoreCount);
+            sem.Close();
+			return;
+			}
+		}
+#endif // FNTSTORE_SUPPORT_FMM
+	}
+
+/** Delete all the items in the current session cache.
+
+@param aHeap The heap base of the current process.
+ */
+void COpenFontSessionCacheList::Delete(RHeap* aHeap)
+	{
+    RSemaphore sem;
+    if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
+        {
+        RDebug::Print(_L("COpenFontSessionCacheList::Delete() can't open SessionCacheSemaphore"));
+        return;
+        }		
+#ifdef FNTSTORE_SUPPORT_FMM
+	COpenFontSessionCacheListItem* cur = Start();
+#else
+	COpenFontSessionCacheListItem* cur = iStart;
+#endif // FNTSTORE_SUPPORT_FMM
+	COpenFontSessionCacheListItem* next = NULL;
+
+    for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
+     {
+	//coverity[lock]
+	//coverity[double_lock]
+     sem.Wait();     
+     }
+	while (cur)
+		{
+#ifdef FNTSTORE_SUPPORT_FMM
+		next = cur->Next();
+#else
+		next = cur->iNext;
+#endif // FNTSTORE_SUPPORT_FMM
+		cur->Delete(aHeap);
+		aHeap->Free(cur);
+		cur = next;
+		}
+    sem.Signal(KSessionCacheSemaphoreCount);
+    sem.Close();
+	}
+
+/**
+Delete all glyphs belonging to a particular font.
+*/
+void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
+	{
+    RSemaphore sem;
+    if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
+        {
+        RDebug::Print(_L("COpenFontSessionCacheList::DeleteFontGlyphs can't global open SessionCacheSemaphore"));
+        return;
+        }
+    sem.Wait();     
+#ifdef FNTSTORE_SUPPORT_FMM     
+	for (COpenFontSessionCacheListItem* p = Start(); p; p = p->Next())
+		{
+		COpenFontSessionCache* cache=p->Cache();
+		TInt* e = cache->Entry();
+		TInt entries = cache->iEntries;
+		for (TInt i = 0; i < entries; i++, e++)
+			{
+			if ((cache->ToCOpenFontSessionCacheEntryPointer(*e)) 
+			        && ((cache->ToCOpenFontSessionCacheEntryPointer(*e))->Font() == aFont))
+				{
+				COpenFontSessionCacheEntry::Delete(aHeap, cache->ToCOpenFontSessionCacheEntryPointer(*e));
+				*e = 0;
+				}
+			}
+		}
+#else
+	for (COpenFontSessionCacheListItem* p = iStart; p; p = p->iNext)
+		{
+		COpenFontSessionCacheEntry** e = p->iCache->iEntry;
+		TInt entries = p->iCache->iEntries;
+		for (TInt i = 0; i < entries; i++, e++)
+			{
+			if ((*e) && ((*e)->iFont == aFont))
+				{
+				COpenFontSessionCacheEntry::Delete(aHeap, *e);
+				*e = NULL;
+				}
+			}
+		}
+#endif // FNTSTORE_SUPPORT_FMM
+	
+	sem.Signal();
+	sem.Close();
+	}
+
+/**
+C++ constructor with a CFont parameter.
+
+This creates a TOpenFontMetrics and initialises it with size, ascent, maximum 
+height, descent, maximum depth and maximum character width information from 
+the CFont that was passed as a parameter.
+
+@param aFont The font from which to initialise the metrics object.
+*/
+EXPORT_C TOpenFontMetrics::TOpenFontMetrics(const CFont* aFont)
+	{
+	iDesignHeight = (TInt16) aFont->HeightInPixels();
+	iAscent = iMaxHeight = (TInt16) aFont->AscentInPixels();
+	iDescent = iMaxDepth = (TInt16)(iDesignHeight - iAscent);
+	iMaxWidth = (TInt16)aFont->MaxCharWidthInPixels();
+	iBaselineCorrection = 0;
+	}
+
+/** 
+@publishedPartner
+@prototype
+
+@param aBaselineCorrection The baseline correction to be associated with this font
+
+Sets the baseline correction applied to this font; this value is used to offset
+the underlinke and strikethrough positions and is used by linked fonts only.
+*/
+const TUint16 KBitsForUnderline = 10;
+const TUint16 KMaskUnderline = (1<<KBitsForUnderline)-1;  //bottom bits which are set 
+const TUint16 KMaskBitmapType = ~KMaskUnderline;  //top bits which are set
+const TUint16 KSignBit = 1<<(KBitsForUnderline-1); //sign bit for the lower number, which can be signed
+const TUint32 KTop16Of32Bits = 0xffff0000; 
+
+EXPORT_C void TOpenFontMetrics::SetBaselineCorrection(TInt aBaselineCorrection)
+	{
+	__ASSERT_DEBUG(aBaselineCorrection<(1<<(KBitsForUnderline-1)), Panic(EFntOverFlow));
+	__ASSERT_DEBUG(aBaselineCorrection>(0-(1<<(KBitsForUnderline-1))), Panic(EFntOverFlow));
+	
+	TUint16 value = iBaselineCorrection;
+	value &=~KMaskUnderline; //zero all the underline position bits
+	if (aBaselineCorrection<0)
+		{
+		//need to mask out extra sign bits for negative value
+		iBaselineCorrection = value | (static_cast<TUint16>(aBaselineCorrection)&~KMaskBitmapType);
+		}
+	else
+		{
+		iBaselineCorrection = value | static_cast<TUint16>(aBaselineCorrection);
+		}
+	}
+
+/**
+@publishedPartner
+@prototype
+
+Gets the baseline correction applied to this font; this value is used to offset
+the underlinke and strikethrough positions and is used by linked fonts only.
+
+@return The baseline correction associated with this font
+*/
+
+EXPORT_C TInt TOpenFontMetrics::BaselineCorrection()
+	{
+	TUint16 value = iBaselineCorrection;  //read once for improved multi threading
+	if (!(value & KSignBit))
+		{
+		//value is positive, no need to sign extend
+		return value & KMaskUnderline;
+		}
+	else
+		{
+		//value is negative, need to stuff ones into the high bits
+		//could shift up and shift down
+		return static_cast<TInt>(static_cast<TUint>(value) | KMaskBitmapType | KTop16Of32Bits);
+		}
+	}
+
+/**
+C++ constructor with UID and filename.
+
+Call this constructor in the constructor for your derived object, passing 
+it aUid and aFileName arguments.
+
+Non Symbian-platform-native font files are allocated IDs by the font store. 
+These are passed in by the rasteriser class. UIDs are required by the 
+font framework. However you should not use the ID to access the file, since 
+a new UID will need to be allocated when the file is next loaded, e.g. after 
+a device reboot. Instead use the font file name.
+
+@param aUid The UID of the font file.
+@param aFileName The full filename, including the path, of the font file.
+*/
+EXPORT_C COpenFontFile::COpenFontFile(TInt aUid, const TDesC& aFileName)
+ :	iFaceAttrib(1),
+	iUid(TUid::Uid(aUid)),
+	iFileName(aFileName),
+	iFontList(8)
+	{
+	}
+
+/**
+Destructor.
+
+It is not allowed that file is deleted before its fonts
+and the logic is handled in CFontStore::RemoveFile().
+*/
+EXPORT_C COpenFontFile::~COpenFontFile()
+	{
+    CFontStore *fs = GetFontStore();
+    if (fs)
+        {
+        fs->CleanupCacheOnOpenFontFileRemoval(this);
+        }
+	delete iData;
+	}
+
+/**
+Gets the nearest font in pixels.
+
+Implementations of this pure virtual function should create the COpenFont 
+derived object that most closely matches aFontSpec, and place a pointer to 
+it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
+aFont should be set to NULL. 
+	
+The other two arguments, aHeap and aSessionCacheList, should be passed to 
+the COpenFont constructor.
+	
+Implementations may use the utilitity function GetNearestFontHelper() to get 
+the attributes of the closest matching font.
+	
+@param aHeap Shared heap. This value should be passed to the COpenFont derived 
+classes' constructor.
+@param aSessionCacheList The session cache list. This value should be passed 
+to the COpenFont derived classes' constructor.
+@param aDesiredFontSpec The desired font specification.
+@param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
+the algorithmic slant of the typeface. 
+@param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
+the algorithmic slant of the typeface.
+@param aFont On return, contains a pointer to the newly created COpenFont 
+derived object, or NULL if no font matching aDesiredFontSpec exists.
+@param aActualFontSpec The actual font specification of the font retrieved 
+into aFont. 
+@see GetNearestFontHelper()
+@deprecated Use GetNearestFontToDesignHeightInPixels
+*/
+TInt COpenFontFile::GetNearestFontInPixels(
+	RHeap*						aHeap,
+	COpenFontSessionCacheList*	aSessionCacheList,
+	const TOpenFontSpec&		aDesiredFontSpec,
+	TInt						aPixelWidth,
+	TInt						aPixelHeight,
+	COpenFont*&					aFont,
+	TOpenFontSpec&				aActualFontSpec)
+	{
+	return GetNearestFontToDesignHeightInPixels(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec);
+	}
+
+/**
+Gets the nearest font in pixels.
+
+Implementations of this pure virtual function should create the COpenFont 
+derived object that most closely matches aFontSpec, and place a pointer to 
+it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
+aFont should be set to NULL. 
+	
+The other two arguments, aHeap and aSessionCacheList, should be passed to 
+the COpenFont constructor.
+	
+Implementations may use the utilitity function GetNearestFontHelper() to get 
+the attributes of the closest matching font.
+	
+@param aHeap Shared heap. This value should be passed to the COpenFont derived 
+classes' constructor.
+@param aSessionCacheList The session cache list. This value should be passed 
+to the COpenFont derived classes' constructor.
+@param aDesiredFontSpec The desired font specification.
+@param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
+the algorithmic slant of the typeface. 
+@param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
+the algorithmic slant of the typeface.
+@param aFont On return, contains a pointer to the newly created COpenFont 
+derived object, or NULL if no font matching aDesiredFontSpec exists.
+@param aActualFontSpec The actual font specification of the font retrieved 
+into aFont. 
+@see GetNearestFontHelper()
+*/
+TInt COpenFontFile::GetNearestFontToDesignHeightInPixels(
+	RHeap*						aHeap,
+	COpenFontSessionCacheList*	aSessionCacheList,
+	const TOpenFontSpec&		aDesiredFontSpec,
+	TInt						aPixelWidth,
+	TInt						aPixelHeight,
+	COpenFont*&					aFont,
+	TOpenFontSpec&				aActualFontSpec)
+	{
+	aFont = NULL;
+	TRAPD(error, GetNearestFontToDesignHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec));
+	return error;
+	}
+
+
+void COpenFontFile::GetNearestFontToDesignHeightInPixelsAndAddToListL(
+	RHeap*						aHeap,
+	COpenFontSessionCacheList*	aSessionCacheList,
+	const TOpenFontSpec&		aDesiredFontSpec,
+	TInt						aPixelWidth,
+	TInt						aPixelHeight,
+	COpenFont*&					aFont,
+	TOpenFontSpec&				aActualFontSpec)
+	{
+	COpenFont* fontPtr = NULL;
+	GetNearestFontToDesignHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec);
+	if (fontPtr != NULL)
+		{ // found a matching font
+		CleanupStack::PushL(fontPtr);
+		iFontList.AppendL(fontPtr);
+		// transfer ownership
+		aFont = fontPtr;
+		CleanupStack::Pop(fontPtr);
+		}
+	}
+
+
+/**
+Gets the nearest font in pixels that fits inside specified max height.
+
+Implementations of this pure virtual function should create the COpenFont 
+derived object that most closely matches aFontSpec, while fitting within
+aMaxHeight, and place a pointer to it in aFont. If this cannot be done,
+e.g. if the font name doesn't match, aFont should be set to NULL. 
+
+The other two arguments, aHeap and aSessionCacheList, should be passed to 
+the COpenFont constructor.
+
+Implementations may use the utilitity function GetNearestFontHelper()
+to get the attributes of the closest matching font.
+
+@param aHeap Shared heap. This value should be passed to the COpenFont derived 
+classes' constructor.
+@param aSessionCacheList The session cache list. This value should be passed 
+to the COpenFont derived classes' constructor.
+@param aDesiredFontSpec The desired font specification.
+@param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
+the algorithmic slant of the typeface. 
+@param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
+the algorithmic slant of the typeface.
+@param aFont On return, contains a pointer to the newly created COpenFont 
+derived object, or NULL if no font matching aDesiredFontSpec exists.
+@param aActualFontSpec The actual font specification of the font retrieved 
+into aFont. 
+@param aMaxHeight The maximum height within which the font must fit.
+@see GetNearestFontHelper()
+*/
+TInt COpenFontFile::GetNearestFontToMaxHeightInPixels(
+	RHeap*						aHeap,
+	COpenFontSessionCacheList*	aSessionCacheList,
+	const TOpenFontSpec&		aDesiredFontSpec,
+	TInt						aPixelWidth,
+	TInt						aPixelHeight,
+	COpenFont*&					aFont,
+	TOpenFontSpec&				aActualFontSpec,
+	TInt						aMaxHeight)
+	{
+	aFont = NULL;
+	TRAPD(error, GetNearestFontToMaxHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec, aMaxHeight));
+	return error;
+	}
+
+
+void COpenFontFile::GetNearestFontToMaxHeightInPixelsAndAddToListL(
+	RHeap*						aHeap,
+	COpenFontSessionCacheList*	aSessionCacheList,
+	const TOpenFontSpec&		aDesiredFontSpec,
+	TInt						aPixelWidth,
+	TInt						aPixelHeight,
+	COpenFont*&					aFont,
+	TOpenFontSpec&				aActualFontSpec,
+	TInt						aMaxHeight)
+	{
+	COpenFont* fontPtr = NULL;
+	GetNearestFontToMaxHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec, aMaxHeight);
+	if (fontPtr != NULL)
+		{  // found a matching font
+		CleanupStack::PushL(fontPtr);
+		iFontList.AppendL(fontPtr);
+		// transfer ownership
+		aFont = fontPtr;
+		CleanupStack::Pop(fontPtr);
+		}
+	}
+
+
+/**
+Gets the nearest font helper function.
+
+This function may be used by derived classes in their GetNearestFontInPixelsL() 
+implementations. It finds the nearest font in the typeface attribute array, 
+if any, to the provided font specification. If there is a possible match it 
+places the face index in aFaceIndex and the actual specification (including 
+algorithmic effects) in aActualFontSpec.
+
+@param aDesiredFontSpec The desired font specification.
+@param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
+the algorithmic slant of the typeface.
+@param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
+the algorithmic slant of the typeface.
+@param aFaceIndex The index of the typeface which contains the closest match 
+to aDesiredFontSpec.
+@param aActualFontSpec The actual font specification of the font with attributes 
+closest to aDesiredFontSpec.
+@return ETrue if there is a possible font match, otherwise EFalse.
+*/
+EXPORT_C TBool COpenFontFile::GetNearestFontHelper(
+	const TOpenFontSpec&	aDesiredFontSpec,
+	TInt					aPixelWidth,
+	TInt					aPixelHeight,
+	TInt&					aFaceIndex,
+	TOpenFontSpec&			aActualFontSpec) const
+	{
+	const TInt faces = FaceCount();
+	TInt best_points = 0;
+	TInt best_index = -1;
+
+	for (TInt i = 0; i < faces; i++)
+		{
+		TInt cur_points = 0;
+
+		if (0 < aDesiredFontSpec.Name().Length())
+			{
+			cur_points = ScoreByName(aDesiredFontSpec, iFaceAttrib[i]);
+			}
+		else
+			{
+			cur_points = ScoreByStyle(aDesiredFontSpec, iFaceAttrib[i]);
+			}
+
+		if (cur_points)
+			{
+			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
+				cur_points++;
+			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
+				cur_points++;
+			}
+
+		if (cur_points > best_points)
+			{
+			best_points = cur_points;
+			best_index = i;
+			}
+		}
+
+	if (best_index != -1)
+		{
+		aActualFontSpec = aDesiredFontSpec;
+		// copy attributes & name
+		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
+		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
+		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
+		if ((aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[best_index].IsItalic()) && (0 == aDesiredFontSpec.SlantFactor()))
+			{
+			TInt factor = KDefaultSlantFactor;
+			if (TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
+				{
+				TOpenFontSpec::ApplyRatio(factor, aPixelWidth, aPixelHeight);
+				}
+			aActualFontSpec.SetSlantFactor(factor);
+			}
+		}
+
+	aFaceIndex = best_index;
+	return best_index != -1;
+	}
+
+TInt COpenFontFile::ScoreByName(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
+	{
+	if (!aDesiredFontSpec.Name().CompareF(aAttrib.FullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFullName()))
+		{
+		return 4;
+		}
+	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFullName()))
+		{
+		return 3;
+		}
+	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.FamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFamilyName()))
+		{
+		return 2;
+		}
+	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFamilyName()))
+		{
+		return 1;
+		}
+	return 0;
+	}
+
+TInt COpenFontFile::ScoreByStyle(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
+	{
+	if (aDesiredFontSpec.IsSymbol() == aAttrib.IsSymbol())
+		{
+		return 4;
+		}
+	else if(aDesiredFontSpec.IsMonoWidth() == aAttrib.IsMonoWidth())
+		{
+		return 3;
+		}
+	else if(aDesiredFontSpec.IsSerif() == aAttrib.IsSerif())
+		{
+		return 2;
+		}
+
+	return 0;
+	}
+
+#ifdef _DEBUG
+/**  @internalComponent */
+EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec& aDesiredFontSpec, TInt aPixelWidth,TInt aPixelHeight,TInt& aFaceIndex, TOpenFontSpec& aActualFontSpec) const
+	{
+	TInt faces = FaceCount();
+	TInt best_points = 0;
+	TInt best_index = -1;
+	TBool slant = FALSE;
+	for (TInt i = 0; i < faces; i++)
+		{
+		TPtrC family_name = iFaceAttrib[i].FamilyName();
+		TPtrC full_name = iFaceAttrib[i].FullName();
+		TPtrC local_family_name = iFaceAttrib[i].LocalFamilyName();
+		TPtrC local_full_name = iFaceAttrib[i].LocalFullName();
+		TPtrC desired_name = aDesiredFontSpec.Name();
+
+		TInt cur_points = 0;
+		if (desired_name.Length() > 0)
+			{
+			if ((full_name.CompareF(desired_name) == 0) || (local_full_name.CompareF(desired_name) == 0))
+				cur_points = 4;
+			else if ((family_name.CompareF(desired_name) == 0) || (local_family_name.CompareF(desired_name) == 0))
+				cur_points = 2;
+			}
+		else
+			{
+			if ((aDesiredFontSpec.IsSerif() == iFaceAttrib[i].IsSerif()) && (aDesiredFontSpec.IsMonoWidth() == iFaceAttrib[i].IsMonoWidth()) && (aDesiredFontSpec.IsSymbol() == iFaceAttrib[i].IsSymbol()))
+				cur_points = 2;
+			}
+		if (cur_points)
+			{
+			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
+				cur_points++;
+			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
+				cur_points++;
+			if (cur_points > best_points)
+				{
+				best_points = cur_points;
+				best_index = i;
+				slant = (aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[i].IsItalic());
+				}
+			}
+		}
+
+	if (best_index != -1)
+		{
+		TInt32 slant_factor = aDesiredFontSpec.SlantFactor();
+
+		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
+		if (slant && slant_factor == 0)
+			{
+			slant_factor = KDefaultSlantFactor;
+			if (aPixelWidth>0 && aPixelHeight>0 && TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth,aPixelHeight))
+				{
+				TOpenFontSpec::ApplyRatio(slant_factor,aPixelWidth,aPixelHeight);
+				}
+			}
+
+		aActualFontSpec = aDesiredFontSpec;
+		// copy attributes & name
+		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
+		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
+		aActualFontSpec.SetSlantFactor(slant_factor);
+		aActualFontSpec.SetEffects(0);
+		}
+
+	aFaceIndex = best_index;
+	return best_index != -1;
+	}
+#else //_DEBUG
+/**
+@internalComponent
+*/
+EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec&, TInt, TInt, TInt&, TOpenFontSpec&) const 
+	{
+	return EFalse;
+	}
+#endif //_DEBUG
+
+/** This function is called (via iFile) by a COpenFont when it is destroyed. */
+void COpenFontFile::RemoveFontFromList(const COpenFont* aFont)
+	{
+	TInt fonts = iFontList.Count();
+	for (TInt i = 0; i < fonts; i++)
+		if (iFontList[i] == aFont)
+			{
+			iFontList.Delete(i);
+			break;
+			}
+	}
+
+/**
+Adds a typeface to this object's typeface array.
+
+This function should be called during construction to add the attributes for 
+each typeface in the font file to the typeface attribute array. 
+
+Note:
+
+The typeface array is what is searched for the closest match to a specified 
+font by GetNearestFontHelper().
+
+@param aAttrib The attributes for a typeface to be added to the typeface attribute 
+array.
+@see FaceAttrib()
+@see FaceCount()
+*/
+EXPORT_C void COpenFontFile::AddFaceL(const TOpenFontFaceAttrib& aAttrib)
+	{
+	TAttrib& a = iFaceAttrib.ExtendL();
+	(TOpenFontFaceAttrib&)a = aAttrib;
+	}
+
+void COpenFontFile::SetFontStoreL(CFontStore* aFontStore)
+	{
+	if (!iData)
+		{
+		iData = new (ELeave) TOpenFontFileData;
+		}
+	iData->iFontStore = aFontStore;
+	}
+
+CFontStore* COpenFontFile::GetFontStore()
+	{
+	return iData ? iData->iFontStore : NULL;
+	}
+
+CArrayPtrFlat<COpenFont>* COpenFontFile::GetOpenFontList()
+	{
+	return &iFontList;
+	}
+
+
+static const TInt KTOpenFontSpecBitsNumSymbol = 1;
+static const TInt KTOpenFontSpecBitsNumScript = 4;
+static const TInt KTOpenFontSpecMaskSymbol = (1 << KTOpenFontSpecBitsNumSymbol) - 1;
+static const TInt KTOpenFontSpecMaskScript = ((1 << KTOpenFontSpecBitsNumScript) - 1) << KTOpenFontSpecBitsNumSymbol;
+static const TInt KTOpenFontSpecSymbolFlag = 0x1;
+
+/**
+Default C++ constructor setting
+height to 16 pixels or twips,
+width factor to 1 (65536 in 16.16 format),
+slant factor to 0 (no slant),
+effects to ENone,
+symbol to 0 (assuming EScriptNone = 0),
+print position to EPrintPosNormal.
+*/
+EXPORT_C TOpenFontSpec::TOpenFontSpec()
+ :	iHeight(16),
+	iWidthFactor(KOneIn16Dot16FixedPointFormat),
+	iSlantFactor(0),
+	iBitmapType(0),
+	iEffects(FontEffect::ENone),
+	iSymbol(0),
+	iPrintPosition(EPrintPosNormal),
+	iReserved2(0)
+	{
+	}
+
+/**
+C++ constructor taking a reference to a TFontSpec.
+
+This object's members are initialised from the values of the aFontSpec parameter.
+
+@param aFontSpec The font specification used to initialise this font specification.
+*/
+EXPORT_C TOpenFontSpec::TOpenFontSpec(const TFontSpec& aFontSpec)
+	{
+	*this = aFontSpec;
+	}
+
+/**
+Assignment operator.
+
+@param aFontSpec The old-style font specification to copy into this font specification.
+*/
+EXPORT_C void TOpenFontSpec::operator=(const TFontSpec& aFontSpec)
+	{
+	iSlantFactor = 0;
+	iWidthFactor = KOneIn16Dot16FixedPointFormat;
+	iHeight			= aFontSpec.iHeight;	// in twips
+	iBitmapType		= aFontSpec.iFontStyle.BitmapType();
+	iEffects		= aFontSpec.iFontStyle.Effects();
+	iPrintPosition	= aFontSpec.iFontStyle.PrintPosition();
+	iName			= aFontSpec.iTypeface.iName;
+	SetScriptTypeForMetrics(aFontSpec.iTypeface.ScriptTypeForMetrics());
+	const TBool symbol = aFontSpec.iTypeface.IsSymbol();
+	SetSymbol(symbol);
+	if (symbol)
+		SetCoverage(0);	// no appropriate coverage value for the symbol set
+	else
+		SetCoverage(3);	// Latin and Latin-1 supplement
+	iStyle = 0;
+	if (!aFontSpec.iTypeface.IsProportional())
+		iStyle |= TOpenFontFaceAttrib::EMonoWidth;
+	if (aFontSpec.iTypeface.IsSerif())
+		iStyle |= TOpenFontFaceAttrib::ESerif;
+	if (aFontSpec.iFontStyle.Posture() == EPostureItalic)
+		iStyle |= TOpenFontFaceAttrib::EItalic;
+	if (aFontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
+		iStyle |= TOpenFontFaceAttrib::EBold;
+	}
+
+
+/**
+Adjust the width factor and slant factor to suit a pixel aspect ratio.
+@publishedAll
+@released
+@param aPixelWidth The pixel width, in the same units as aPixelHeight.
+@param aPixelHeight The pixel height, in the same units as aPixelWidth.
+*/
+EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(TInt aPixelWidth, TInt aPixelHeight)
+	{
+	if (IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
+		{
+		ApplyRatio(iWidthFactor, aPixelHeight, aPixelWidth);
+		ApplyRatio(iSlantFactor, aPixelWidth, aPixelHeight);
+		}
+	}
+
+/**
+Adjust the width factor and slant factor to suit a pixel aspect ratio stored 
+in a MGraphicsDeviceMap derived object.
+@publishedAll
+@released
+@param aMap The MGraphicsDeviceMap defining the pixel aspect ratio.
+*/
+EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(const MGraphicsDeviceMap& aMap)
+	{
+	CompensateForAspectRatio(aMap.HorizontalPixelsToTwips(1000), aMap.VerticalPixelsToTwips(1000));
+	}
+
+/**
+The pixel width and height are used to derive a ratio, and so can be 
+in any units. Aspect ratios differing by less than 1/1000 are treated as 1:1.
+@internalTechnology
+*/
+TBool TOpenFontSpec::IsCompensationForAspectRatioNeeded(TInt aPixelWidth,TInt aPixelHeight)
+	{
+	if ((aPixelWidth != aPixelHeight) && (0 < aPixelWidth) && (0 < aPixelHeight))
+		{
+		//If nearly square don't transform (0.999 < aPixelHeight/aPixelWidth < 1.001)
+		TInt64 width = aPixelWidth;
+		TInt64 height = aPixelHeight;
+		width *= 999;	// Cannot do multiplication on declaration lines above as risk of TInt32 overflow
+		height *= 1000;
+		if (width <= height)	// 999 * aPixelWidth <= 1000 * aPixelHeight
+			return ETrue;
+		width += aPixelWidth;
+		width += aPixelWidth;	// Cannot do with previous line as small risk of TInt32 overflow
+		if (width >= height)	// 1001 * aPixelWidth >= 1000 * aPixelHeight
+			return ETrue;
+		}
+	return EFalse;
+	}
+
+/**
+Multiplies aValue by aNumerator/aDenominator but using TInt64's to avoid any overflows.
+Returns ETrue if the final result has an overflow.
+@internalTechnology
+*/
+TBool TOpenFontSpec::ApplyRatio(TInt& aValue, TInt aNumerator, TInt aDenominator)
+	{
+	TInt64 value(aValue);
+	value = (value * aNumerator) / aDenominator;
+	aValue = I64LOW(value);
+	__ASSERT_DEBUG(I64HIGH(value) == 0, Panic(EFntOverFlow));
+	return I64HIGH(value) != 0;
+	}
+
+/**
+Same as above function but this takes a TInt32 not a TInt
+*/
+TBool TOpenFontSpec::ApplyRatio(TInt32& aValue, TInt aNumerator, TInt aDenominator)
+	{
+	TInt value = aValue;
+	TBool ret = ApplyRatio(value, aNumerator, aDenominator);
+	aValue = value;
+	return ret;
+	}
+
+EXPORT_C void TOpenFontSpec::SetAttrib(const TOpenFontFaceAttribBase& aAttrib)
+/**
+Sets the font attributes.
+
+@param aAttrib The font attributes.
+*/
+	{
+	TOpenFontFaceAttribBase* self = this;
+	*self = aAttrib;
+	}
+
+/**
+Gets the TFontSpec corresponding to this Open Font System font specification.
+@publishedAll
+@released
+@param aFontSpec On return, contains the TFontSpec corresponding to this font 
+specification.
+*/
+EXPORT_C void TOpenFontSpec::GetTFontSpec(TFontSpec& aFontSpec) const
+	{
+	aFontSpec = TFontSpec();
+	TPtrC short_name(iName.Ptr(), Min(iName.Length(), KMaxTypefaceNameLength));
+	aFontSpec.iTypeface.iName = short_name;
+	aFontSpec.iTypeface.SetIsProportional(!IsMonoWidth());
+	aFontSpec.iTypeface.SetIsSerif(IsSerif());
+	aFontSpec.iTypeface.SetIsSymbol(Symbol());
+	aFontSpec.iTypeface.SetScriptTypeForMetrics(ScriptTypeForMetrics());
+	aFontSpec.iHeight = iHeight;	// as twips
+	if (IsItalic() || (iSlantFactor > 0))
+		aFontSpec.iFontStyle.SetPosture(EPostureItalic);
+	if (IsBold() || IsEffectOn(FontEffect::EAlgorithmicBold))
+		aFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+	aFontSpec.iFontStyle.SetPrintPosition(iPrintPosition);
+	aFontSpec.iFontStyle.SetBitmapType(BitmapType());
+	aFontSpec.iFontStyle.SetEffects(iEffects);
+	}
+
+/**
+Sets a font effect to the given state.
+@publishedAll
+@released
+@param aEffect The font effect to be set.
+@param aOn True represents on, otherwise off.
+@see TOpenFontSpec::IsEffectOn()
+*/
+EXPORT_C void TOpenFontSpec::SetEffects(FontEffect::TEffect aEffect, TBool aOn)
+	{
+	FontEffect::SetEffect(aEffect, aOn, iEffects);
+	}
+
+/** Checks if a font effect is on.
+@publishedAll
+@released
+@return True represents the specified font effect is on, otherwise off.
+@param aEffect The font effect to be checked.
+@see TOpenFontSpec::SetEffects()
+*/
+EXPORT_C TBool TOpenFontSpec::IsEffectOn(FontEffect::TEffect aEffect) const
+	{
+	return FontEffect::IsEffectOn(aEffect, iEffects);
+	}
+
+/**
+@deprecated This needs to be maintained to just call the inline methods.
+*/
+EXPORT_C void TOpenFontSpec::DoSetEffects(TUint32 aEffects)
+	{
+	SetEffects(aEffects);
+	}
+
+/**
+@deprecated This needs to be maintained to just call the inline methods.
+*/
+EXPORT_C TUint32 TOpenFontSpec::DoEffects() const
+	{
+	return Effects();
+	}
+
+/**
+Specifies the script which font metrics calculation will be based on.
+@publishedAll
+@released
+@param aLanguage The language used to derive the required script.
+*/
+EXPORT_C void TOpenFontSpec::SetScriptTypeForMetrics(TLanguage aLanguage)
+	{
+	SetScriptTypeForMetrics(GlyphSample::TLanguage2TScript(aLanguage));
+	}
+
+/**
+@internalTechnology
+*/
+void TOpenFontSpec::SetScriptTypeForMetrics(TInt aScript)
+	{
+	iSymbol &= ~KTOpenFontSpecMaskScript;
+	iSymbol |= (KTOpenFontSpecMaskScript & (aScript << KTOpenFontSpecBitsNumSymbol));
+	}
+
+/**
+Gets the script which the font metrics calculation will be based on.
+@internalTechnology
+@return The script.
+*/
+EXPORT_C TInt TOpenFontSpec::ScriptTypeForMetrics() const
+	{
+	return (KTOpenFontSpecMaskScript & iSymbol) >> KTOpenFontSpecBitsNumSymbol;
+	}
+
+/**
+@internalTechnology
+*/
+void TOpenFontSpec::SetSymbol(TBool aSymbol)
+	{
+	iSymbol &= ~KTOpenFontSpecMaskSymbol;
+	iSymbol |= (aSymbol ? KTOpenFontSpecSymbolFlag : 0);
+	}
+
+/**
+@internalTechnology
+*/
+TBool TOpenFontSpec::Symbol() const
+	{
+	return (KTOpenFontSpecSymbolFlag & iSymbol) > 0;
+	}
+
+/**
+@deprecated This needs to be maintained to just call the inline methods.
+*/
+EXPORT_C TBool TOpenFontSpec::OperatorEquality(const TOpenFontSpec& aOpenFontSpec) const
+	{
+	return this->operator == (aOpenFontSpec);
+	}
+
+/**
+@internalTechnology
+*/
+TBool TOpenFontSpec::operator!=(const TOpenFontSpec& aOpenFontSpec) const
+	{
+	return !(this->operator == (aOpenFontSpec));
+	}
+
+/**
+Static constructor for a TOpenFontGlyphData.
+
+This constructor creates the object on a specified heap. It must be deleted 
+using RHeap::Free().
+
+@param aHeap The shared heap on which the object is constructed.
+@param aBufferSize The amount of memory allocated for the glyph data.
+@return A pointer to the newly created object.
+*/
+EXPORT_C TOpenFontGlyphData* TOpenFontGlyphData::New(RHeap* aHeap, TInt aBufferSize)
+	{
+	if (aBufferSize < 1)
+		aBufferSize = 1;
+	TInt bytes = sizeof(TOpenFontGlyphData) + aBufferSize - 1;
+	TOpenFontGlyphData* g = (TOpenFontGlyphData*)aHeap->Alloc(bytes);
+	if (g)
+		{
+		Mem::FillZ(g, bytes);
+		g->iBitmapBufferSize = aBufferSize;
+		}
+	return g;
+	}
+
+// Virtual functions reserved for future expansion.
+/**
+@publishedPartner
+@prototype
+*/
+EXPORT_C void COpenFontRasterizer::ExtendedInterface(TUid, TAny*&)
+	{
+	}
+
+/** @internalComponent */
+EXPORT_C void COpenFontFile::ExtendedInterface(TUid, TAny*&)
+	{
+	}
+
+EXPORT_C void COpenFont::ExtendedInterface(TUid, TAny*&)
+	{
+	}
+	
+EXPORT_C CShaper::CShaper()
+	{
+	
+	}
+	
+EXPORT_C CShaper::~CShaper()
+	{
+	
+	}
+/** @internalComponent */
+EXPORT_C void* CShaper::ExtendedInterface(TUid)
+	{
+	return 0;
+	}
+
+/**
+Sets the glyph bitmap type.
+
+Normally the bitmap type belongs to the font, but for linked fonts this can 
+be different between different font elements making up the linked font.
+
+Note: This is only of use in conjunction with rasterizer based linked fonts.
+
+@publishedPartner
+@prototype
+*/
+EXPORT_C void TOpenFontCharMetrics::SetGlyphType(TGlyphBitmapType aGlyphBitmapType)
+	{
+	iGlyphBitmapType = aGlyphBitmapType;
+	}
+
+/**
+Gets the glyph bitmap type.
+
+@publishedPartner
+@prototype
+*/
+EXPORT_C TGlyphBitmapType TOpenFontCharMetrics::GlyphType() const
+	{
+	if (iGlyphBitmapType == 0)
+		return EGlyphBitmapTypeNotDefined;
+	else
+		return static_cast<TGlyphBitmapType>(iGlyphBitmapType);
+	}