fontservices/fontstore/src/FNTSTORE.CPP
changeset 0 1fb32624e06b
child 5 e96e8a131979
child 21 f2f7b3284356
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fontservices/fontstore/src/FNTSTORE.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,5219 @@
+/*
+* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <e32hal.h>
+#include <hal.h>
+#include <s32file.h>
+#include <graphics/shapeimpl.h>
+#include <fntstore.h>
+#include "FNTBODY.H"
+#include "FNTSTD.H"
+#include <graphics/shaperparams.h>
+
+#define DO_LOADFONT_OPTIMIZATION 1
+#include <linkedfonts.h>
+#include "linkedfontsprivate.h"
+#include "openfontsprivate.h"
+#include <openfontlinkedtypefaceelementspec.h>
+#include <graphics/openfontlinkedtypefaceextension.h>
+#include <graphics/openfontlinkedtypefacespecification.h>
+#include <graphics/openfontrasterizer.h>
+#include <graphics/openfontconstants.h>
+
+static const TUint32 KOutlineGlyphIdHashMask = 0x0000ffff;
+static const TUint32 KOutlineFileUidHashMask = 0x00ff0000;
+static const TUint32 KOutlineFaceIndexHashMask = 0x0f000000;
+static const TUint32 KOutlineFontPtrHashMask = 0x0fff0000;
+
+// uncomment to enable some verbose debug prints
+//#define VERBOSE_DEBUG 1
+
+
+/**  These constants set the default pixel width and height, in Twips x1000.
+ Hal Data information overrides this if it is available. EDisplayXPixels & EDisplayXTwips, 
+ EDisplayYPixels & EDisplayYTwips values are required respectively.
+
+ (11860 is approx equivalent to 120 pixels per inch.)
+@internalComponent
+*/
+const TInt KDefaultPixelWidthInTwips = 11860;
+const TInt KDefaultPixelHeightInTwips = 11860;
+
+// default granularity for arrays
+const TInt KDefaultArrayGranularity = 8;
+
+/* Maximum height of a character bitmap. When font height in pixel is 1024, each 
+character bitmap is equal to (roughly) 1024 x 1024 x 8 bits/pixel = 1 MB.
+@internalComponent
+*/
+const TInt KMaxFontHeightInPixels = 1024;
+
+/* Minimum height of font in pixels that can be displayed on the screen.
+@internalComponent
+*/
+const TInt KMinFontHeightInPixels = 2;
+/**
+The arbitrary list of sizes, in points, returned for scaleable fonts.
+We can't return 2^32 - 1 sizes, or something that reflect the fact
+that any size is okay, because a UI will probably try to create a listbox containing all the sizes.
+
+Array stored in Twips as that is the only form of the value currently used.
+@internalComponent
+*/
+#define POINTSIZE_IN_TWIPS(p)	((p) * 20)
+const TInt gOpenFontSizeInTwipsArray[] =
+	{
+	// 4pt-18pt in steps of 1pt (15 sizes)
+	POINTSIZE_IN_TWIPS(4), POINTSIZE_IN_TWIPS(5), POINTSIZE_IN_TWIPS(6),
+	POINTSIZE_IN_TWIPS(7), POINTSIZE_IN_TWIPS(8), POINTSIZE_IN_TWIPS(9),
+	POINTSIZE_IN_TWIPS(10), POINTSIZE_IN_TWIPS(11), POINTSIZE_IN_TWIPS(12),
+	POINTSIZE_IN_TWIPS(13), POINTSIZE_IN_TWIPS(14), POINTSIZE_IN_TWIPS(15),
+	POINTSIZE_IN_TWIPS(16), POINTSIZE_IN_TWIPS(17), POINTSIZE_IN_TWIPS(18),
+	// 20pt-36pt in steps of 2pt (9 sizes)
+	POINTSIZE_IN_TWIPS(20), POINTSIZE_IN_TWIPS(22), POINTSIZE_IN_TWIPS(24),
+	POINTSIZE_IN_TWIPS(26), POINTSIZE_IN_TWIPS(28), POINTSIZE_IN_TWIPS(30),
+	POINTSIZE_IN_TWIPS(32), POINTSIZE_IN_TWIPS(34), POINTSIZE_IN_TWIPS(36),
+	// 40pt-72pt in steps of 4pt (9 sizes)
+	POINTSIZE_IN_TWIPS(40), POINTSIZE_IN_TWIPS(44), POINTSIZE_IN_TWIPS(48),
+	POINTSIZE_IN_TWIPS(52), POINTSIZE_IN_TWIPS(56), POINTSIZE_IN_TWIPS(60),
+	POINTSIZE_IN_TWIPS(64), POINTSIZE_IN_TWIPS(68), POINTSIZE_IN_TWIPS(72),
+	// 80pt-144pt in steps of 8pt (9 sizes)
+	POINTSIZE_IN_TWIPS(80), POINTSIZE_IN_TWIPS(88), POINTSIZE_IN_TWIPS(96),
+	POINTSIZE_IN_TWIPS(104), POINTSIZE_IN_TWIPS(112), POINTSIZE_IN_TWIPS(120),
+	POINTSIZE_IN_TWIPS(128), POINTSIZE_IN_TWIPS(136), POINTSIZE_IN_TWIPS(144)
+	};
+
+const TInt KOpenFontSizeArrayCount = sizeof(gOpenFontSizeInTwipsArray) / sizeof(gOpenFontSizeInTwipsArray[0]);
+
+/**
+@internalTechnology
+ The folder used to store linked fonts; the character represents the system drive
+ location and the descriptor contains the private path of fbserv.
+ */
+_LIT(KLinkedFontFileFolder, "%c:%Slfonts\\");
+
+/**
+@internalTechnology
+ The folder used to store updated linked fonts; the descriptor should be formatted
+ with the formatted version of KLinkedFontFileFolder. Files will be moved from this
+ folder to KLinkedFontFileFolder at boot time before the font loading procedure.
+ */
+_LIT(KLinkedFontFileTempFolder, "update\\");
+
+/**
+The font search string. The Y: directory prefix forces the search to 
+start with drive Y:. The drives will be searched in the order Y: to A: then Z:
+*/
+_LIT(KFBSERVFontDirSecure, "y:\\resource\\fonts\\");
+
+/**The maximum length of the linked font folder path*/
+const TInt KMaxLinkedFontPathLength = 36;
+
+/**The maximum length of a private path*/
+const TInt KMaxPrivatePathLength = 19;
+
+/** Container for TTypefaceSupport that describes an Open Font family.
+
+There is an implicit assumption that all fonts in the family will have the same attributes
+as the first instance found.  E.g. that the range of font heights is the same. 
+
+An array of pointers to the COpenFontFile file objects that hold fonts in this family
+also provides reference counting for the object.
+
+@internalComponent
+*/
+NONSHARABLE_CLASS(CTypefaceSupportInfo) : public CBase
+	{
+public:
+	CTypefaceSupportInfo();
+	inline TInt AddFontFilePtr(COpenFontFile* aOpenFontFile);
+	inline TInt AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib);
+	inline TInt FindFontFilePtr(COpenFontFile* aOpenFontFile);
+	inline TBool RemoveFontFilePtr(TInt aIndex);
+	void SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips);
+	inline const TTypefaceSupport* TypefaceSupport() const;
+	inline TInt NearestPointSizeIndex() const;
+	static TInt CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2);
+	~CTypefaceSupportInfo();
+
+public:
+	TTypefaceSupport iSupport;
+	// pointers back to the COpenFontFile object which has one or more typefaces in this family
+	RPointerArray<COpenFontFile> iOpenFontFilePtrArray;
+	// nearest standard point size index;
+	TInt iNearestPointSizeIndex;
+	};
+
+
+/** helper class used with the cleanup stack
+@internalComponent
+*/
+class TCleanupRemoveFontFile
+	{
+public:
+	inline TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid);
+public:
+	CFontStore* iFontStore;
+	TUid iFontUid;
+	};
+
+
+// declare static functions
+static TInt MatchFontSpecsInPixels(const TOpenFontSpec& aCandidateFontSpec,
+	const TOpenFontSpec& aIdealFontSpec, TInt aCandidateMaxHeight = 0, TInt aIdealMaxHeight = 0);
+static void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength);
+static TUint TtfTableTagFromBufferL(TDes8& aDes);
+
+#ifdef _DEBUG
+static TUint32 StartTiming(void);
+static TUint32 FinishTimingL(TUint32 startTime);
+#endif
+
+static TBool FileIsOnZ(TParse& aFileName);
+static TBool FileIsInList(TParse& aFileName, RArray<TParse>& aList);
+
+
+/** Helper function for converting a pointer to an offset from the passed
+heap base. Use OffsetToPointer() to convert the returned offset back to a
+useable pointer.
+@param aAny A pointer to be converted to an offset.
+@param aHeapBase The heap base of the current process.
+@return An offset representing the passed pointer that can be converted
+back to a pointer using the function OffsetToPointer(). 
+@see OffsetToPointer()
+ */
+LOCAL_C TInt PointerToOffset(const TAny* aAny, TUint8* aHeapBase)
+    {
+    if (aAny && aHeapBase)
+        {
+        return (TInt)aAny - (TInt)aHeapBase;
+        }
+    return 0;
+    }
+
+/** Helper function for converting an offset (that was calculated using
+PointerToOffset()) back to a pointer relative to the passed heap base.
+@param aOffset The offset to be converted to a pointer.
+@param aHeapBase The heap base of the current process.
+@return A pointer relative to the passed heap base.
+@see PointerToOffset()
+ */
+LOCAL_C TAny* OffsetToPointer(const TInt aOffset, TUint8* aHeapBase)
+    {
+    if (aOffset && aHeapBase)
+        {
+        return (TAny*)(aOffset + (TInt)aHeapBase);
+        }
+    return NULL;
+    }
+
+// CTypefaceSupportInfo
+CTypefaceSupportInfo::CTypefaceSupportInfo()
+	{
+	}
+
+
+CTypefaceSupportInfo::~CTypefaceSupportInfo()
+	{ // no ownership of font files, so just Close the array
+	iOpenFontFilePtrArray.Close();
+	}
+
+
+/** Add a back pointer to an Open Font file, in sorted order.
+@param aOpenFontFile font file that has a typeface in this family.
+@return KErrNone if added, KErrAlreadyExists if file is already referenced, or KErrNoMemory.
+@internalComponent
+*/
+TInt CTypefaceSupportInfo::AddFontFilePtr(COpenFontFile* aOpenFontFile)
+	{
+	return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile);
+	}
+
+/** Add a back pointer to an Open Font file, in sorted order, but only if the font details are unique.
+@param aOpenFontFile font file that has a typeface in this family.
+@return KErrNone if added, KErrInUse if another file already defines this, KErrAlreadyExists if file is already referenced, or KErrNoMemory.
+@internalComponent
+*/
+TInt CTypefaceSupportInfo::AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib)
+	{
+#ifdef _DEBUG	
+	_LIT(KLoadedFont, "TypefaceSupport: already loaded font: %S\n");
+#endif
+	
+	TPtrC findName=aFaceAttrib.FullName();
+	for (TInt i=0,maxi=iOpenFontFilePtrArray.Count();i<maxi;i++)
+		{	//Do any of the fonts already registered with this family already provide this specific font?
+		COpenFontFile* cmpFont=iOpenFontFilePtrArray[i];
+		if (cmpFont==aOpenFontFile)
+			{   //Another specific font in this font file has already been added to this family
+				//InsertInAddressOrder would detect this.
+#ifdef _DEBUG
+				RDebug::Print(KLoadedFont, &findName);
+#endif
+				return KErrAlreadyExists;	
+			}
+		else
+			{
+			for (TInt j=0,maxj=cmpFont->FaceCount();j<maxj;j++)
+				{	//The expectation is that open fonts will only have 1 face per file, so this loop is 1-pass generally.
+				const TOpenFontFaceAttrib& cmpFace=cmpFont->FaceAttrib(j);
+				TPtrC cmpName=cmpFace.FullName();
+				if (cmpName==findName)
+					{
+#ifdef _DEBUG
+					RDebug::Print(KLoadedFont, &findName);
+#endif
+					return KErrInUse;
+					}
+				}
+			}
+		}
+	return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile);
+	}
+
+/** Check font family for back pointer to an Open Font file.
+@param aOpenFontFile font file that may have a typeface in this family.
+@return KErrNotFound or the index of pointer
+@internalComponent
+*/
+TInt CTypefaceSupportInfo::FindFontFilePtr(COpenFontFile* aOpenFontFile)
+	{
+	return iOpenFontFilePtrArray.FindInAddressOrder(aOpenFontFile);
+	}
+
+
+/** Remove a font file back pointer.
+@param aIndex the index of pointer, from FindFontFilePtr()
+@return ETrue if there are no more implementations of the font family
+@internalComponent
+*/
+TBool CTypefaceSupportInfo::RemoveFontFilePtr(TInt aIndex)
+	{
+	iOpenFontFilePtrArray.Remove(aIndex);
+	return iOpenFontFilePtrArray.Count() == 0;
+	}
+
+
+/** Set the details of the typeface family.
+@param aFaceAttrib typeface to parameterise.
+@internalComponent
+*/
+void CTypefaceSupportInfo::SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips)
+	{
+	iSupport.iTypeface.iName = aFaceAttrib.ShortFamilyName();
+	iSupport.iTypeface.SetIsProportional(!aFaceAttrib.IsMonoWidth());
+	iSupport.iTypeface.SetIsSerif(aFaceAttrib.IsSerif());
+	iSupport.iTypeface.SetIsSymbol(aFaceAttrib.IsSymbol());
+
+	// Find minimum size in twips then find the next higher standard size.
+	iSupport.iMinHeightInTwips = aMinHeightInTwips;
+	TInt fontSizeIndex = 0;
+	for (; fontSizeIndex < KOpenFontSizeArrayCount; ++fontSizeIndex)
+		{
+		const TInt KMinHeightInTwips = gOpenFontSizeInTwipsArray[fontSizeIndex];
+		if (aMinHeightInTwips <= KMinHeightInTwips)
+			{
+			aMinHeightInTwips = KMinHeightInTwips;
+			break;
+			}
+		}
+	iNearestPointSizeIndex = fontSizeIndex;
+	iSupport.iMaxHeightInTwips = Max(gOpenFontSizeInTwipsArray[KOpenFontSizeArrayCount - 1], iSupport.iMinHeightInTwips);
+	iSupport.iNumHeights = Max(1,KOpenFontSizeArrayCount - iNearestPointSizeIndex);
+	iSupport.iIsScalable = TRUE;
+	}
+
+
+/** Get the details of the typeface family.
+@internalComponent
+*/
+const TTypefaceSupport* CTypefaceSupportInfo::TypefaceSupport() const
+	{
+	return &iSupport;
+	}
+	
+/** Get the Nearest Standard Point Size Index.
+@internalComponent
+*/
+TInt CTypefaceSupportInfo::NearestPointSizeIndex() const
+	{
+	return iNearestPointSizeIndex;
+	}
+
+// for InsertInOrder
+TInt CTypefaceSupportInfo::CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2)
+	{
+	return aTypeface1.iSupport.iTypeface.iName.CompareF(aTypeface2.iSupport.iTypeface.iName);
+	}
+
+
+// TCleanupRemoveFontFile
+TCleanupRemoveFontFile::TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid) :
+	iFontStore(aFontStore), iFontUid(aFontUid)
+	{
+	}
+
+
+TBitmapFontCharacterOffset::TBitmapFontCharacterOffset()
+ :	iBitmapOffset(0)
+	{}
+
+void TBitmapFontCharacterOffset::InternalizeL(RReadStream& aStream)
+	{
+	iBitmapOffset = aStream.ReadUint16L();
+	};
+
+EXPORT_C TCharacterMetrics::TCharacterMetrics()
+ :	iAscentInPixels(0),
+	iHeightInPixels(0),
+	iLeftAdjustInPixels(0),
+	iMoveInPixels(0),
+	iRightAdjustInPixels(0)
+	{
+	}
+
+TBitmapFontCharacterMetrics::TBitmapFontCharacterMetrics()
+ :	iAscentInPixels(0),
+	iHeightInPixels(0),
+	iLeftAdjustInPixels(0),
+	iMoveInPixels(0),
+	iRightAdjustInPixels(0)
+	{
+	}
+
+void TBitmapFontCharacterMetrics::InternalizeL(RReadStream& aStream)
+	{
+	iAscentInPixels = aStream.ReadInt8L();
+	iHeightInPixels = aStream.ReadInt8L();
+	iLeftAdjustInPixels = aStream.ReadInt8L();
+	iMoveInPixels = aStream.ReadInt8L();
+	iRightAdjustInPixels = aStream.ReadInt8L();
+	}
+
+/** Constructor. */
+EXPORT_C TAlgStyle::TAlgStyle()
+ :	iBaselineOffsetInPixels(0),
+	iFlags(0),
+	iWidthFactor(1),
+	iHeightFactor(1)
+	{
+	}
+
+/** Sets whether the font is bold.
+
+@param aIsBold ETrue if the font is bold; otherwise EFalse. */
+EXPORT_C void TAlgStyle::SetIsBold(TBool aIsBold)
+	{
+	if (aIsBold)
+		iFlags |= EBold;
+	else
+		iFlags &= ~EBold;
+	}
+
+/** Sets whether the font is italic.
+
+@param aIsItalic ETrue if the font is italic; otherwise EFalse. */
+EXPORT_C void TAlgStyle::SetIsItalic(TBool aIsItalic)
+	{
+	if (aIsItalic)
+		iFlags |= EItalic;
+	else
+		iFlags &= ~EItalic;
+	}
+
+/** Sets whether the font is mono width - i.e. all characters have the same width.
+
+@param aIsMono ETrue if the font is mono width; otherwise EFalse. */
+EXPORT_C void TAlgStyle::SetIsMono(TBool aIsMono)
+	{
+	if (aIsMono)
+		iFlags|=EMono;
+	else
+		iFlags&=~EMono;
+	}
+
+/** Sets the width factor.
+
+@param aWidthFactor A width factor. */
+EXPORT_C void TAlgStyle::SetWidthFactor(TInt aWidthFactor)
+	{
+	iWidthFactor=(TInt8) aWidthFactor;
+	}
+
+/** Sets the height factor.
+
+@param aHeightFactor A height factor. */
+EXPORT_C void TAlgStyle::SetHeightFactor(TInt aHeightFactor)
+	{
+	iHeightFactor=(TInt8) aHeightFactor;
+	}
+
+/** Returns whether the font is bold.
+
+@return ETrue if the font is bold; otherwise EFalse. */
+EXPORT_C TBool TAlgStyle::IsBold() const
+	{
+	return iFlags&EBold;
+	}
+
+/** Returns whether the font is italic.
+
+@return ETrue if the font is italic; otherwise EFalse. */
+EXPORT_C TBool TAlgStyle::IsItalic() const
+	{
+	return iFlags&EItalic;
+	}
+
+/** Returns whether the font is mono - i.e. all characters have the same width.
+
+@return ETrue if the font is mono; otherwise EFalse. */
+EXPORT_C TBool TAlgStyle::IsMono() const
+	{
+	return iFlags&EMono;
+	}
+
+/** Returns the width factor.
+
+@return A width factor. */
+EXPORT_C TInt TAlgStyle::WidthFactor() const
+	{
+	return iWidthFactor;
+	}
+
+/** Returns the height factor.
+
+@return A height factor. */
+EXPORT_C TInt TAlgStyle::HeightFactor() const
+	{
+	return iHeightFactor;
+	}
+
+EXPORT_C TBool TAlgStyle::operator==(const TAlgStyle& aAlgStyle) const
+	{
+	return (iFlags==aAlgStyle.iFlags) && 
+	       (iWidthFactor==aAlgStyle.iWidthFactor) &&
+	       (iHeightFactor==aAlgStyle.iHeightFactor) &&
+	       (iBaselineOffsetInPixels==aAlgStyle.iBaselineOffsetInPixels);
+	}
+
+/**
+@internalTechnology
+*/
+TBool TAlgStyle::operator!=(const TAlgStyle& aAlgStyle) const
+	{
+	return !this->operator==(aAlgStyle);
+	}
+
+CBitmapFont::CBitmapFont(
+	RHeap*				aHeap,
+	const TFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&	aAlgStyle,
+	CFontBitmap*		aFontBitmap):
+	iFontSpecInTwips(aFontSpecInTwips),
+	iAlgStyle(aAlgStyle),
+	iHeap(aHeap)
+	{
+	iFontBitmapOffset = (TInt) ((TUint)(aFontBitmap) - (TUint)(this));
+	}
+
+CBitmapFont::CBitmapFont(
+	RHeap*				aHeap,
+	const TFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&	aAlgStyle,
+	COpenFont*			aOpenFont):
+	iFontSpecInTwips(aFontSpecInTwips),
+	iAlgStyle(aAlgStyle),
+	iHeap(aHeap),
+	iOpenFont(aOpenFont)
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	iOpenFontOffset=reinterpret_cast<TInt>(aOpenFont)-reinterpret_cast<TInt>(this);
+#endif // FNTSTORE_SUPPORT_FMM
+	}
+
+/** This member is private and not intended for use. */
+void CBitmapFont::ConstructL()
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (!IsOpenFont())
+		FontBitmap()->UseL();
+#else
+	if (!iOpenFont)
+		FontBitmap()->UseL();	
+#endif // FNTSTORE_SUPPORT_FMM
+	}
+
+/** This member is private and not intended for use. */
+CBitmapFont::~CBitmapFont()
+	{	
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (!IsOpenFont() && iFontBitmapOffset)
+		FontBitmap()->Release();
+	else if (IsOpenFont())
+		delete OpenFont();
+#else
+	if (!iOpenFont)
+		FontBitmap()->Release();
+	delete iOpenFont;
+#endif // FNTSTORE_SUPPORT_FMM
+	}	
+
+CBitmapFont* CBitmapFont::NewL(
+	RHeap*				aHeap,
+	const TFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&	aAlgStyle,
+	CFontBitmap*		aFontBitmap)
+	{
+	// font is placed in shared heap
+	CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont));
+	new(f) CBitmapFont(aHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap);
+	CleanupStack::PushL(f);
+	f->ConstructL();
+	CleanupStack::Pop(f);
+	return f;
+	}
+
+CBitmapFont* CBitmapFont::NewL(
+	RHeap*				aHeap,
+	const TFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&	aAlgStyle,
+	COpenFont*			aOpenFont)
+	{
+	// font is placed in shared heap
+	CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont));
+	new(f) CBitmapFont(aHeap,aFontSpecInTwips,aAlgStyle,aOpenFont);
+	return f;
+	}
+	
+/** Returns the font type identifier:KCBitmapFontUidVal.
+
+@return The font type identifier. */
+EXPORT_C TUid CBitmapFont::DoTypeUid() const
+	{
+	return TUid::Uid(KCBitmapFontUidVal);
+	}
+
+/** Returns a font identifier.
+
+If it uses an open font the UID returned has a value of zero. Otherwise it 
+has the UID value of the CFontBitmap it uses.
+
+@return A font identifier. */
+TUid CBitmapFont::Uid() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return TUid::Uid(0);	
+#else
+	if (iOpenFont)
+		return TUid::Uid(0);	
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return FontBitmap()->iUid;
+	}
+
+/** Returns the font height in pixels.
+For an open font this will be the design height (notional rather than exact).
+
+@return Font height in pixels.
+@see FontMaxHeight()
+*/
+EXPORT_C TInt CBitmapFont::DoHeightInPixels() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return Height(OpenFont()->Metrics().Size());	
+#else
+	if (iOpenFont)
+		return Height(iOpenFont->Metrics().Size());	
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return Height(FontBitmap()->iCellHeightInPixels);
+	}
+
+/** Returns the font ascent in pixels.
+
+The ascent is usually the height of a Latin capital letter above the baseline.
+For an open font, the returned value is likely to be inaccurate.
+Don't rely on it to get exact metrics at the pixel level.
+
+@return Font ascent in pixels.
+@see FontCapitalAscent()
+@see FontMaxAscent()
+*/
+EXPORT_C TInt CBitmapFont::DoAscentInPixels() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return Height(OpenFont()->Metrics().Ascent());	
+#else
+	if (iOpenFont)
+		return Height(iOpenFont->Metrics().Ascent());	
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return Height(FontBitmap()->iAscentInPixels);
+	}
+
+/** Returns the width, in pixels, of the given character.
+
+If all characters have the same width (i.e. the font is mono - an attribute 
+stored in iAlgStyle) then this is the maximum normal width, returned using 
+MaxNormalCharWidthInPixels().
+
+Note: For OpenType fonts this function returns the horizontal advance of
+the character, which may be different from the actual width.
+
+@param aChar A character.
+@return The character width in pixels. */
+EXPORT_C TInt CBitmapFont::DoCharWidthInPixels(TChar aChar) const
+	{
+	const TUint8* bytes;
+	if (iAlgStyle.IsMono())
+		return MaxNormalCharWidthInPixels();
+	else
+		return Width(CharacterMetrics(aChar,bytes).iMoveInPixels);
+	}
+
+/** Returns the width, in pixels, of the given text.
+
+@param aText Text string.
+@return Width of the text in pixels. */
+EXPORT_C TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText) const
+	{
+	TMeasureTextInput* dummy = NULL;
+	return DoTextWidthInPixels(aText, dummy);
+	}
+
+/** Returns the width, in pixels, of the given text.
+
+@param aText Text string.
+@return Width of the text in pixels. */
+TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText, const TMeasureTextInput* aParam) const
+	{
+	TMeasureTextOutput output;
+	TInt advance_width = MeasureText(aText,aParam,&output);
+	return Max(advance_width,output.iBounds.Width());
+	}
+
+
+/** Returns the baseline offset in pixels, as stored in iAlgStyle.
+
+@return The baseline offset in pixels. */
+EXPORT_C TInt CBitmapFont::DoBaselineOffsetInPixels() const
+	{
+	return iAlgStyle.iBaselineOffsetInPixels;
+	}
+
+/** Returns the number of whole characters of aText, starting from the beginning, 
+that fit into the given pixel width.
+
+@param aText A text string.
+@param aWidthInPixels A width in pixels.
+@return The number of whole characters of aText that fit into aWidthInPixels.
+*/
+EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels) const
+	{
+	TInt count = 0;
+	const TInt length = aText.Length();
+	TInt width = 0;
+	// accumulate text width character by character, until target is reached or exceeded
+	TInt widthDiff = aWidthInPixels - width;
+	while ( (widthDiff > 0) && (length > count) )
+		{ 
+		width += TextWidthInPixels(aText.Mid(count,1));
+		widthDiff = aWidthInPixels - width;
+		if (widthDiff >= 0)
+			{ // width <= aWidthInPixels
+			++count;
+			}
+		}
+	return count;
+	}
+
+/** Returns the number of whole characters of aText, starting from the beginning, 
+that fit into the given pixel width, and gets the excess width.
+
+@param aText A text descriptor.
+@param aWidthInPixels A width in pixels.
+@param aExcessWidthInPixels On return, the width left over of aWidthInPixels 
+after the maximum possible whole number of characters of aText have been fit 
+into it.
+@return The number of whole characters of aText that fit into aWidthInPixels. */
+EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels,TInt &aExcessWidthInPixels) const
+	{
+	TInt count = TextCount(aText,aWidthInPixels);
+	aExcessWidthInPixels = aWidthInPixels - TextWidthInPixels(aText.Left(count));
+	return count;
+	}
+
+/** Returns the font's maximum character width in pixels.
+
+@return The maximum character width in pixels. */
+EXPORT_C TInt CBitmapFont::DoMaxCharWidthInPixels() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return Width(OpenFont()->Metrics().MaxWidth());	
+#else
+	if (iOpenFont)
+		return Width(iOpenFont->Metrics().MaxWidth());	
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return Width(FontBitmap()->iMaxCharWidthInPixels);
+	}
+
+/** Returns the font's normal maximum character width in pixels.
+
+Note that when a CFontBitmap is used this value is the same as the maximum 
+character width in pixels returned by MaxCharWidthInPixels(), but when a COpenFont 
+is used the value may be different.
+
+@return The normal maximum character width in pixels. */
+EXPORT_C TInt CBitmapFont::DoMaxNormalCharWidthInPixels() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return Width(OpenFont()->Metrics().MaxWidth());
+#else
+	if (iOpenFont)
+		return Width(iOpenFont->Metrics().MaxWidth());
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return Width(FontBitmap()->iMaxNormalCharWidthInPixels);
+	}
+
+/** Returns the device-independent font specification for the font.
+
+Note that this is set when the bitmap font object is constructed.
+
+@return A font specification. */
+EXPORT_C TFontSpec CBitmapFont::DoFontSpecInTwips() const
+	{
+	return iFontSpecInTwips;
+	}
+
+
+/** Attempts to rasterize a character (aCode) into a data area (aGlyphData) in 
+shared memory.
+
+This works only for open fonts: where the bitmap font object is using a COpenFont.
+
+Bitmap fonts are deemed to be fully rasterized after they have been loaded 
+from file. 
+
+Returns ETrue if the character was successfully rasterized or was already 
+in the cache. This function can be called only by the server; rasterization 
+uses memory and other resources (e.g., file handles) owned by the server. 
+
+@param aSessionHandle A session handle for the open font system.
+@param aCode A character code.
+@param aGlyphData A data area in shared memory.
+@return ETrue if the character was successfully rasterized or was already in 
+the cache; otherwise EFalse. */
+EXPORT_C TBool CBitmapFont::Rasterize(TInt aSessionHandle, TInt aCode, TOpenFontGlyphData* aGlyphData) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return OpenFont()->Rasterize(aSessionHandle, aCode, aGlyphData);
+#else
+	if (iOpenFont)
+		return iOpenFont->Rasterize(aSessionHandle, aCode, aGlyphData);
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return EFalse;
+	}
+
+/** Gets a pointer to a bitmap and the metrics for a specified character, but only 
+if a CFontBitmap is being used by the bitmap font object.
+
+This function does not work when a COpenFont is being used, but GetCharacterData() 
+can be used instead.
+
+If the specified character does not exist in the font then the bitmap pointer 
+and character metrics are gotten for a replacement character, KReplacementCharacter.
+
+@param aCode A character code.
+@param aBytes On return, a pointer to the bitmap for the specified character.
+@return Metrics for the specified character. */
+EXPORT_C TCharacterMetrics CBitmapFont::CharacterMetrics(TInt aCode,const TUint8*& aBytes) const
+	{
+	/*
+	This function does not work for Open Fonts because the character data need not be
+	shared between sessions and a session handle is needed; GetCharacterData should be used instead.
+	*/
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+#else
+	if (iOpenFont)
+#endif // FNTSTORE_SUPPORT_FMM
+		{
+		aBytes = NULL;
+		return TCharacterMetrics();
+		}
+
+	TBitmapFontCharacterMetrics bitmap_font_metrics = FontBitmap()->CharacterMetrics(aCode,aBytes);
+
+	// Substitute the replacement character if this character doesn't exist in the font.
+	if (aBytes == NULL)
+		bitmap_font_metrics = FontBitmap()->CharacterMetrics(KReplacementCharacter,aBytes);
+
+	TCharacterMetrics metrics;
+	metrics.iAscentInPixels = bitmap_font_metrics.iAscentInPixels;
+	metrics.iHeightInPixels = bitmap_font_metrics.iHeightInPixels;
+	metrics.iLeftAdjustInPixels = bitmap_font_metrics.iLeftAdjustInPixels;
+	metrics.iMoveInPixels = bitmap_font_metrics.iMoveInPixels;
+	metrics.iRightAdjustInPixels = bitmap_font_metrics.iRightAdjustInPixels;
+	
+	if (iAlgStyle.IsMono())
+		{
+		TInt width = metrics.iMoveInPixels - metrics.iLeftAdjustInPixels - metrics.iRightAdjustInPixels;
+		metrics.iMoveInPixels = FontBitmap()->iMaxNormalCharWidthInPixels;
+		metrics.iLeftAdjustInPixels = (TInt16)((metrics.iMoveInPixels - width) / 2);
+		metrics.iRightAdjustInPixels = (TInt16)(metrics.iMoveInPixels - width - metrics.iLeftAdjustInPixels);
+		}
+
+	return metrics;	 // N.B. Not doubled for double height and double width.
+	}
+
+ 
+/** Gets a pointer to a bitmap and the metrics for a specified character.
+
+Note that this function calls CharacterMetrics() if a CFontBitmap is being 
+used by the bitmap font object, and maps the TCharacterMetrics values returned 
+by that function to aMetrics.
+
+If the function fails to get the bitmap and metric values (because the character 
+is in an open font and has not yet been rasterized) returns EFalse.
+
+@param aSessionHandle A session handle for the open font system.
+@param aCode A character code.
+@param aMetrics On return, metrics for the specified character.
+@param aBitmap On return, a pointer to the bitmap for the specified character.
+@return ETrue if successful, otherwise EFalse. */
+EXPORT_C TBool CBitmapFont::GetCharacterData(TInt aSessionHandle,TInt aCode,
+											 TOpenFontCharMetrics& aMetrics,const TUint8*& aBitmap) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+#else
+	if (iOpenFont)
+#endif // FNTSTORE_SUPPORT_FMM
+		{
+		const TOpenFontCharMetrics* nm;
+#ifdef FNTSTORE_SUPPORT_FMM
+		if (OpenFont()->GetCharacterData(aSessionHandle,aCode,nm,aBitmap))
+#else
+		if (iOpenFont->GetCharacterData(aSessionHandle,aCode,nm,aBitmap))
+#endif // FNTSTORE_SUPPORT_FMM
+			{
+			aMetrics = *nm;
+			return ETrue;
+			}
+		else
+			return EFalse;
+		}
+	else
+		{
+		TCharacterMetrics m = CharacterMetrics(aCode,aBitmap);
+		aMetrics = TOpenFontCharMetrics(m);
+		return ETrue;
+		}
+	}
+
+/** Gets the open font metrics. 
+
+These metrics distinguish between maximum character height and depth and typographic 
+ascent and descent, so that the clipping rectangle for text can be distinguished 
+from the distance to neighbouring baselines. 
+
+@param aMetrics Open font metrics. */
+ 
+EXPORT_C void CBitmapFont::GetFontMetrics(TOpenFontMetrics& aMetrics) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		aMetrics = OpenFont()->Metrics();
+#else
+	if (iOpenFont)
+		aMetrics = iOpenFont->Metrics();
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		{
+		new(&aMetrics) TOpenFontMetrics;
+		aMetrics.SetSize(CBitmapFont::DoHeightInPixels());
+		aMetrics.SetAscent(CBitmapFont::DoAscentInPixels());
+		aMetrics.SetDescent(aMetrics.Size() - aMetrics.Ascent());
+		aMetrics.SetMaxHeight(aMetrics.Ascent());
+		aMetrics.SetMaxDepth(aMetrics.Descent());
+		aMetrics.SetMaxWidth(CBitmapFont::DoMaxCharWidthInPixels());
+		}
+	}
+
+ 
+/** Gets the open font typeface attributes if possible. 
+
+At present no attempt is made to sythesize these attributes for bitmap fonts 
+(CFontBitmaps). 
+
+@param aAttrib On return, the open font typeface attributes.
+@return ETrue if successful; EFalse if not possible to get the open font typeface 
+attributes. */
+EXPORT_C TBool CBitmapFont::GetFaceAttrib(TOpenFontFaceAttrib& aAttrib) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+#else
+	if (iOpenFont)
+#endif // FNTSTORE_SUPPORT_FMM
+		{
+#ifdef FNTSTORE_SUPPORT_FMM
+		const TOpenFontFaceAttrib* a = OpenFont()->FaceAttrib();
+#else
+		const TOpenFontFaceAttrib* a = iOpenFont->FaceAttrib();
+#endif // FNTSTORE_SUPPORT_FMM
+		if (a)
+			{
+			aAttrib = *a;
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+/** Gets encoding if a bitmap font (a CFontBitmap) is used.
+
+@return Bitmap encoding value. */
+EXPORT_C TInt CBitmapFont::BitmapEncoding() const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return 0;
+#else
+	if (iOpenFont)
+		return 0;
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return FontBitmap()->iBitmapEncoding;
+	}
+
+/** Gets whether the open or bitmap font has the specified character.
+
+@param aCode A character code.
+@return ETrue if the font has the specified character; otherwise EFalse. */
+EXPORT_C TBool CBitmapFont::HasCharacterL(TInt aCode) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return OpenFont()->HasCharacterL(aCode);
+#else
+	if (iOpenFont)
+		return iOpenFont->HasCharacterL(aCode);
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		{
+		const TUint8* bytes;
+		FontBitmap()->CharacterMetrics(aCode,bytes);
+		return (bytes != NULL);
+		}
+	}
+
+/** Gets whether the specified character needs to be rasterised.
+
+False is returned if it is a bitmap font (a CFontBitmap) being used by the 
+bitmap font object (so no rasterization is required) or if is an open font 
+(a COpenFont) and the character has been rasterized.
+
+@param aSessionHandle A session handle for the open font system.
+@param aCode A character code.
+@return ETrue if the character needs to be rasterized; otherwise EFalse. */
+EXPORT_C TBool CBitmapFont::CharacterNeedsToBeRasterized(TInt aSessionHandle,TInt aCode) const
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	if (IsOpenFont())
+		return OpenFont()->CharacterNeedsToBeRasterized(aSessionHandle,aCode);
+#else
+	if (iOpenFont)
+		return iOpenFont->CharacterNeedsToBeRasterized(aSessionHandle,aCode);
+#endif // FNTSTORE_SUPPORT_FMM
+	else
+		return FALSE;	// characters in bitmap fonts do not need to be rasterized	
+	}
+
+/** Turns text into glyph codes and positions.
+@param aText The Unicode text to shape plus context
+@return The output shape header from the per-font cache, or 0 on failure.
+@internalTechnology
+*/
+EXPORT_C TShapeHeader* CBitmapFont::ShapeTextL(const TDesC16& aText,
+	TInt aSessionHandle, const TShapeMessageParameters& aParams)
+	{
+	TShapeHeader* shape = 0;
+
+	if(IsOpenFont())
+		{
+		// get the data in a CShaper::TInput for the shaper
+		CShaper::TInput input;
+		input.iText = &aText;
+		input.iStart = aParams.iStart;
+		input.iEnd = aParams.iEnd;
+		input.iScript= aParams.iScript;
+		input.iLanguage = aParams.iLanguage;
+		input.iMaximumAdvance = KMaxTInt;
+		input.iFlags = 0;
+		input.iSessionHandle = aSessionHandle;
+		input.iReserved1 = 0;
+
+		TFontShapeFunctionParameters params;
+		params.iEnd = input.iEnd;
+		params.iLanguage = input.iLanguage;
+		params.iScript = input.iScript;
+		params.iStart = input.iStart;
+		params.iText = input.iText;
+		
+		COpenFont* openFont = OpenFont();
+		
+		//if already exist just increase the reference count for that session
+		shape = openFont->GetShapedData(aSessionHandle,&params);
+		
+		if (shape == NULL)
+			{
+			if (!openFont->HasShaper()
+ 				|| (openFont->HasShaper() && ( 
+ 				(TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetScript)) != input.iScript
+ 				|| (TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetLang)) != input.iLanguage)))
+				{ // Install the shaper
+				openFont->DeleteShaper();
+				InstallOpenFontShaper(openFont, input);
+				}
+
+			if (openFont->HasShaper())
+				{
+				TInt error = openFont->GetShaper()->ShapeText(shape, input, iHeap);
+				if (error != KErrNone)
+					User::Leave(error);
+				
+				// Put this into the session cache
+				TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(aSessionHandle,&params, shape);
+				if (!cached_header)
+					User::LeaveNoMemory();
+				iHeap->Free(shape);
+				shape = cached_header;
+				}
+			}
+		}
+	return shape;
+	}
+
+
+void CBitmapFont::InstallOpenFontShaper(COpenFont* aOpenFont, CShaper::TInput& aShaperInput)
+	{
+	CShaper* shaper = NULL;
+	const CArrayPtrFlat<CShaperFactory>* shaperFactoryList = aOpenFont->File()->GetFontStore()->ShaperFactoryList();
+
+	TInt factoryCount = shaperFactoryList->Count();
+	for (TInt index = 0; index < factoryCount; index++)
+		{
+		TRAPD(err, shaper = (*shaperFactoryList)[index]->NewShaperL(this,
+				aShaperInput.iScript, aShaperInput.iLanguage,  iHeap));
+		if (err == KErrNone)
+			{
+			aOpenFont->SetShaper(shaper);
+			break;
+			}
+		}
+	}
+
+
+/** Frees the memory taken up as a result of shaping
+@internalTechnology */
+EXPORT_C void CBitmapFont::DeleteShape(TInt aSessionHandle,TShapeHeader* aHeader)
+	{
+	//safe to assume aHeader is never NULL?
+	if (IsOpenFont())
+		{
+		//we just need to decrease the reference count, no deletion here
+		//as the entry in cache can still be reused by other client
+		//only in the case where the memory is full, the freeing will
+		//delete any cache entry that is not referenced at all
+		TInt ret=OpenFont()->DecrementCachedRefCount(aSessionHandle,aHeader);
+		//panic in debug mode if trying to delete something that is not there.
+		__ASSERT_DEBUG(ret==KErrNone || ret==KErrNotFound, User::Invariant());
+		}
+	}
+
+EXPORT_C void CBitmapFont::operator delete(TAny *aThis)
+	{
+	if (((CBitmapFont *)aThis)->iHeap)
+		((CBitmapFont *)aThis)->iHeap->Free(aThis);
+	}
+
+TInt CBitmapFont::Width(TInt aNum) const
+	{
+	TInt widthfactor=iAlgStyle.WidthFactor();
+	return ((widthfactor==1)? aNum: aNum*widthfactor);
+	}
+
+TInt CBitmapFont::Height(TInt aNum) const
+	{
+	TInt heightfactor=iAlgStyle.HeightFactor();
+	return ((heightfactor==1)? aNum: aNum*heightfactor);
+	}
+
+CFontBitmap* CBitmapFont::FontBitmap() const
+/** This member is private and not intended for use. */
+	{
+#ifdef FNTSTORE_SUPPORT_FMM
+	__ASSERT_ALWAYS(!IsOpenFont(),Panic(EFntTypefaceHasNoFontBitmaps));
+	if(iFontBitmapOffset)
+		return reinterpret_cast<CFontBitmap*>(reinterpret_cast<TInt>(this)+iFontBitmapOffset);
+	else
+		return NULL;
+#else
+	__ASSERT_ALWAYS(!iOpenFont,Panic(EFntTypefaceHasNoFontBitmaps));
+	TInt fontbitmap=TInt(this)+iFontBitmapOffset;
+	return((CFontBitmap*)fontbitmap);
+#endif // FNTSTORE_SUPPORT_FMM
+	}
+
+/** Gets a font table.
+@param aTag: Input. The name of the font table.
+@param aTableContent: Output. To return the address of the table content.
+@param aLength: Output. To return the length (in bytes) of the table.
+@param aSessionHandle: Input. A handle to the session requesting this table.
+@return KErrNone on success, specific error code on failure.
+@internalTechnology
+*/
+EXPORT_C
+TInt CBitmapFont::GetFontTable(TUint32 aTag, TAny *&aTableContent, 
+        TInt &aLength, TInt aSessionHandle) 
+    {
+    COpenFont *fontPtr = NULL;
+#ifdef FNTSTORE_SUPPORT_FMM
+    if (IsOpenFont())
+        fontPtr = OpenFont();
+#else
+    if (iOpenFont)
+        fontPtr = iOpenFont;
+#endif // FNTSTORE_SUPPORT_FMM
+    else
+        return KErrNotSupported;
+    
+    // try to find it in cache.
+    CFontStore *fntStore = fontPtr->File()->GetFontStore();
+    TUid fileUid = fontPtr->File()->Uid();
+    TInt ret = fntStore->FindFontTableInCache(fileUid, aTag, aTableContent, aLength);
+    if (KErrNone == ret)
+        {
+        ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
+        return ret;
+        }
+    
+    // font table not found in cache.
+    ret = fontPtr->GetFontTable(aTag, aTableContent, aLength);
+    if (KErrNone == ret)
+        {
+        ret = fntStore->CacheFontTable(fileUid, aTag, aTableContent, aLength);
+        if (KErrNone == ret)
+            {
+            ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
+            }
+        else 
+            {
+            aTableContent = NULL;
+            }
+        }
+    
+    return ret;
+    }
+
+/** Release a font table. Decrement its reference count. Remove from cache if 
+ * reference decreases to zero.
+@param aTag: Input. The name of the font table to be released.
+@param aSessionHandle: Input. Handle to the session releasing this table.
+@return KErrNone on success, specific error code on failure.
+@internalTechnology
+*/
+EXPORT_C void CBitmapFont::ReleaseFontTable(TUint32 aTag, 
+        TInt aSessionHandle)
+    {
+    COpenFont *fontPtr = NULL;
+#ifdef FNTSTORE_SUPPORT_FMM
+    if (IsOpenFont())
+        fontPtr = OpenFont();
+#else
+    if (iOpenFont)
+        fontPtr = iOpenFont;
+#endif // FNTSTORE_SUPPORT_FMM
+    else
+        return;
+    
+    CFontStore *fntStore = fontPtr->File()->GetFontStore();
+    TUid fileUid = fontPtr->File()->Uid();
+    fntStore->ReleaseFontTable(fileUid, aTag, aSessionHandle);
+    }
+
+
+/** Release a number of glyph outlines. Decrement their reference count.
+ * Remove it from cache if reference count decreases to zero.
+@param aCount: Input. Number of outlines to be released.
+@param aCodes: Input. An array of codes. Its interpretation depends on the parameter
+    'aIsGlyphId' (see below).
+@param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCodes' is an array of glyph ID's.
+    When aIsGlyphId==EFalse, 'aCodes' is an array of Unicode values.
+@param aHinted: Input. To indicate if the outlines are hinted or unhinted.
+@param aSessionHandle: Input. Handle to the session releasing the outlines.
+@return KErrNone on success, specific error code on failure.
+@internalTechnology
+*/
+EXPORT_C void CBitmapFont::ReleaseGlyphOutlines(TInt aCount, const TUint *aCodes, 
+        TBool aHinted, TInt aSessionHandle)
+    {
+    COpenFont *fontPtr = NULL;
+    #ifdef FNTSTORE_SUPPORT_FMM
+        if (IsOpenFont())
+            fontPtr = OpenFont();
+    #else
+        if (iOpenFont)
+            fontPtr = iOpenFont;
+    #endif // FNTSTORE_SUPPORT_FMM
+        else
+            return;
+    
+    CFontStore *fontStore = fontPtr->File()->GetFontStore();
+    
+    for (TInt i = 0; i < aCount; ++i)
+        {
+        if (aHinted)
+            {
+            THintedOutlineId outlineId(fontPtr, aCodes[i]);
+            fontStore->ReleaseHintedOutline(outlineId, aSessionHandle);
+            }
+        else
+            {
+            TInt faceId = fontPtr->FaceIndex();
+            TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCodes[i]);
+            fontStore->ReleaseUnhintedOutline(outlineId, aSessionHandle);
+            }
+        }
+    }
+
+/** Gets a font table.
+@param aCode: Input. An glyph code. Its interpretation depends on the parameter
+    'aIsGlyphId' (see below).
+@param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCode' is a glyph ID.
+    When aIsGlyphId==EFalse, 'aCode' is a Unicode values.
+@param aHinted: Input. To indicate if hinted or unhinted outline is needed.
+@param aOutline: Output. A 'void*' pointer, pointing to the outline in memory.
+@param aLength: Output. A TInt, recording the lenght (in bytes) of the outline.
+@param aSessionHandle: Input. Handle to the session requesting this outline.
+@return KErrNone on success, specific error code on failure.
+@internalTechnology
+*/
+EXPORT_C TInt CBitmapFont::GetGlyphOutline(TUint aCode, 
+        TBool aHinted, TAny *&aOutline, TInt &aLength, TInt aSessionHandle)
+    {
+    COpenFont *fontPtr = NULL;
+    #ifdef FNTSTORE_SUPPORT_FMM
+        if (IsOpenFont())
+            fontPtr = OpenFont();
+    #else
+        if (iOpenFont)
+            fontPtr = iOpenFont;
+    #endif // FNTSTORE_SUPPORT_FMM
+        else
+            return KErrNotSupported;
+    
+    CFontStore *fontStore = fontPtr->File()->GetFontStore();
+    TAny *outlineData = NULL; 
+    TInt len = KErrGeneral;
+    TInt ret = KErrNone;
+    if (!aHinted)
+        {
+        TInt faceId = fontPtr->FaceIndex();
+        TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCode);
+        ret = fontStore->FindUnhintedOutlineInCache(outlineId, outlineData, len);
+        if (KErrNotFound == ret)
+            {
+            TAny* tmpOutline = 0; 
+            TInt tmpLen = 0;
+            ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
+            if (KErrNone == ret)
+                {
+                fontStore->CacheUnhintedOutline(outlineId,
+                        tmpOutline, (TInt)tmpLen, outlineData, len);
+                }
+            User::Free(tmpOutline);
+            }
+        if (KErrNone == ret)
+            {
+            fontStore->IncreaseUnhintedOutlineRefCount(outlineId, aSessionHandle);
+            }
+        }
+    else 
+        {
+        THintedOutlineId outlineId(fontPtr, aCode);
+        ret = fontStore->FindHintedOutlineInCache(outlineId, outlineData, len);
+        if (KErrNotFound == ret)
+            {
+            TAny* tmpOutline = 0; 
+            TInt tmpLen = 0;
+            ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
+            if (KErrNone == ret)
+                {
+                fontStore->CacheHintedOutline(outlineId,
+                        tmpOutline, (TInt)tmpLen, outlineData, len);
+                }
+            User::Free(tmpOutline);
+            }
+        if (KErrNone == ret)
+            {
+            fontStore->IncreaseHintedOutlineRefCount(outlineId, aSessionHandle);
+            }
+        }
+    
+    aOutline = outlineData;
+    aLength = len;    
+    return KErrNone;
+    }
+
+EXPORT_C TUint32 CBitmapFont::UniqueFontId()
+	{
+	return iUniqueFontId;
+	}
+
+void CBitmapFont::SetUniqueFontId(TUint32 aUniqueFontId)
+	{
+	iUniqueFontId = aUniqueFontId;	
+	}
+
+/** API extension system that enables the caller to access a particular API
+extension function. As an overload of this function in a derived class
+it calls its immediate parent implementation for any extension function Uid
+that it does not recognize and handle.
+@param aInterfaceId UID of the required extension function
+@param aParam Pointer to an arbitrary parameter block that can be used to
+provide and/or return information to/from the particular extension function,
+defaults to NULL.
+@return Integer return value from extension function
+@internalTechnology
+@released
+*/
+EXPORT_C TInt CBitmapFont::DoExtendedFunction(TUid aFunctionId, TAny* aParam) const
+	{
+	if (KFontCapitalAscent == aFunctionId)
+		{
+		return Height(IsOpenFont() ? OpenFont()->FontCapitalAscent() : FontBitmap()->FontCapitalAscent());
+		}
+	else if (KFontMaxAscent == aFunctionId)
+		{
+		return Height(IsOpenFont() ? OpenFont()->FontMaxAscent() : FontBitmap()->FontMaxAscent());
+		}
+	else if (KFontStandardDescent == aFunctionId)
+		{
+		return Height(IsOpenFont() ? OpenFont()->FontStandardDescent() : FontBitmap()->FontStandardDescent());
+		}
+	else if (KFontMaxDescent == aFunctionId)
+		{
+		return Height(IsOpenFont() ? OpenFont()->FontMaxDescent() : FontBitmap()->FontMaxDescent());
+		}
+	else if (KFontLineGap == aFunctionId)
+		{
+		return Height(IsOpenFont() ? OpenFont()->FontLineGap() : FontBitmap()->FontLineGap());
+		}
+	
+	return CFont::DoExtendedFunction(aFunctionId, aParam);
+	}
+
+
+CFontTableCacheItem::CFontTableCacheItem(TUid &aFileUid, const TUint32 aTag, 
+        TInt aOffset, TInt aLength): iFileUid(aFileUid), iTag(aTag),
+        iOffset(aOffset), iLength(aLength)
+    {
+    // a null constructor
+    }
+
+CFontTableCacheItem::~CFontTableCacheItem()
+    {
+    iUsers.ResetAndDestroy();
+    iUsers.Close();
+    }
+    
+TBool CFontTableCacheItem::HasOutstandingRefCount()
+    {
+    TInt count = iUsers.Count();
+    for (TInt j = 0; j < count; ++j)
+        {
+        if (iUsers[j]->iRefCount > 0) 
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+
+TInt CFontTableCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
+    {
+    TInt len = iUsers.Count();
+    for (TInt i = 0; i < len; ++i)
+        {
+        if (aSessionHandle == iUsers[i]->iSessionHandle)
+            {
+            *id = i;
+            return KErrNone;
+            }
+        }
+    return KErrNotFound;
+    }
+
+TInt CFontTableCacheItem::DecRefCount(TInt aSessionHandle)
+    {
+    TInt id = 0; 
+    TInt ret = FindUser(aSessionHandle, &id);
+    if (KErrNone == ret)
+        {
+        iUsers[id]->iRefCount--;
+        if (0 == iUsers[id]->iRefCount) 
+            {
+            delete iUsers[id];
+            iUsers.Remove(id);
+            }
+        return iUsers.Count();
+        }
+    return KErrNotFound;
+    }
+
+TInt CFontTableCacheItem::IncRefCount(TInt aSessionHandle)
+    {
+    TInt id = 0; 
+    TInt ret = FindUser(aSessionHandle, &id);
+    if (KErrNone == ret)
+        {
+        iUsers[id]->iRefCount++;
+        }
+    else
+        {
+        TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
+        if (NULL != newUser)
+            {
+            TRAP(ret, iUsers.AppendL(newUser));
+            }
+        else 
+            {
+            ret = KErrNoMemory;
+            }
+        //coverity[leaked_storage]
+        // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount(). 
+        }
+    return ret;
+    }
+
+TInt CFontTableCache::Append(TUid aFileUid, TUint32 aTag, 
+        TAny *&aContent, TInt aLength) 
+    {
+    TInt ret = 0;
+    if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
+        {
+        RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
+        return KErrNoMemory;
+        }
+    // make a copy of the table content on the shared heap.
+    TAny *sharedCopy = iHeap->Alloc(aLength);
+    if (NULL == sharedCopy) 
+        {
+        return KErrNoMemory;
+        }
+    
+    Mem::Copy(sharedCopy, aContent, aLength);
+
+    CFontTableCacheItem *newItem = NULL;
+    TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
+    TRAP(ret, newItem = new(ELeave) CFontTableCacheItem(aFileUid, aTag, offset, aLength));
+    if (KErrNone != ret)
+        {
+        iHeap->Free(sharedCopy);
+        return ret;
+        }
+    
+    TRAP(ret, iCacheItems.AppendL(newItem));
+    if (KErrNone == ret)
+        {
+        // do not free 'aContent', because the mem is managed by
+        // rasterizer cache.
+        aContent = sharedCopy;
+        iCacheMemMon.Inc(aLength);
+        }
+    else 
+        {
+        iHeap->Free(sharedCopy);
+        }
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    return ret;
+    }
+
+TInt CFontTableCache::Find(TUid aFileUid, TUint32 aTag, TAny *&aContent, 
+        TInt &aLength, TInt *id)
+    {
+    *id = KErrNotFound;
+    TInt len = iCacheItems.Count();
+    
+    TInt ret = KErrNotFound;
+    for (TInt i = 0; i < len; ++i)
+        {
+        CFontTableCacheItem *item = iCacheItems[i]; 
+        if (item->iFileUid == aFileUid && item->iTag == aTag) 
+            {
+            aContent = OffsetToPointer(item->iOffset, iHeap->Base());
+            aLength = item->iLength;
+            *id = i;
+            ret = KErrNone;
+            break;
+            }
+        }
+    
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    return ret;
+    }
+
+CFontTableCache::CFontTableCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): 
+    iCacheMemMon(aMon), iHeap(aHeap) 
+    {
+    // null constructor
+    }
+
+CFontTableCache::~CFontTableCache()
+    {
+    for (TInt i = 0; i < iCacheItems.Count(); ++i)
+        {
+        iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
+        }
+    iCacheItems.ResetAndDestroy();
+    iCacheItems.Close();
+    }
+
+TInt CFontTableCache::IncRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
+    {
+    TAny *outline = NULL;
+    TInt len = 0;
+    TInt id = 0;
+    
+    TInt ret = Find(aFileUid, aTag, outline, len, &id);
+    if (KErrNone == ret)
+        {
+        ret = iCacheItems[id]->IncRefCount(aSessionHandle);
+        }
+    
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    return ret;
+    }
+
+TInt CFontTableCache::DecRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
+    {
+    TAny *outline = NULL;
+    TInt len = 0;
+    TInt id = 0;
+    
+    TInt ret = Find(aFileUid, aTag, outline, len, &id);
+    if (KErrNone == ret) 
+        {
+        TInt numUsers = iCacheItems[id]->DecRefCount(aSessionHandle);
+        if (0 == numUsers) 
+            {
+            // There is no outstanding reference to the cache item.
+            iHeap->Free(outline);
+            iCacheMemMon.Dec(len);
+            delete (iCacheItems[id]);
+            iCacheItems.Remove(id);
+            }
+        }
+    
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    return ret;
+    }
+
+TBool CFontTableCache::HasOutstandingRefCount() 
+    {
+    TInt len = iCacheItems.Count();
+   
+    for (TInt i = 0; i < len; ++i)
+        {
+        if (iCacheItems[i]->HasOutstandingRefCount())
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+TBool CFontTableCache::HasOutstandingRefCountWithUid(TUid aFileUid)
+    {
+    TInt len = iCacheItems.Count();
+   
+    for (TInt i = 0; i < len; ++i)
+        {
+        if (iCacheItems[i]->iFileUid == aFileUid) 
+            {
+            if (iCacheItems[i]->HasOutstandingRefCount())
+                {
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;
+    }
+
+void CFontTableCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *)
+    {
+    // In CFontStore::RemoveFile(), a font file is not allowed to be removed if
+    // there are outstanding ref counts on any table in it. If that check passed 
+    // and this function is called, there shall be no cache item for that file.
+    
+    // Currently a cache item having a refcount of 0 is removed immediately.
+    // If this strategy is changed in the future, we may need to do some
+    // cleanup here.
+    }
+
+void CFontTableCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
+    {
+    TInt len = iCacheItems.Count();
+   
+    for (TInt i = 0; i < len; ++i)
+        {
+        TInt id = -1;
+        if (KErrNone == iCacheItems[i]->FindUser(aSessionHandle, &id))
+            {
+            iCacheItems[i]->iUsers.Remove(id);
+            if (iCacheItems[i]->iUsers.Count() == 0)
+                {
+                iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
+                iCacheMemMon.Dec(iCacheItems[i]->iLength);
+                delete iCacheItems[i];
+                iCacheItems.Remove(i);
+                }
+            }
+        }
+    }
+
+
+#ifdef _DEBUG
+TInt CFontTableCache::GetCacheState(const char *func) 
+    {
+    RDebug::Printf("%s called from %s: ", __func__, func);
+    TBuf<256> buf;
+    
+    int len = iCacheItems.Count();
+    int numTables = 0, numSessions = 0, totalRef = 0;
+    buf.Append(_L("Table cache: "));
+    for (int i = 0; i < len; ++i)
+        {
+        ++numTables;
+        TInt abc = iCacheItems[i]->iUsers.Count();
+        numSessions += abc;
+        for (int j = 0; j < abc; ++j)
+            {
+            totalRef += iCacheItems[i]->iUsers[j]->iRefCount;
+            }
+        }
+    if (0 == iCacheItems.Count())
+        {
+        buf.Append(_L("cache empty. "));
+        }
+    else 
+        {
+        buf.AppendFormat(_L("%d tables referenced by %d sessions, total ref count %d"),
+                numTables, numSessions, totalRef);
+        }
+    RDebug::RawPrint(buf);
+    return 0;
+    }
+#endif
+
+
+
+TInt COutlineCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
+    {
+    TInt len = iUsers.Count();
+    for (TInt i = 0; i < len; ++i)
+        {
+        if (aSessionHandle == iUsers[i]->iSessionHandle)
+            {
+            *id = i;
+            return KErrNone;
+            }
+        }
+    return KErrNotFound;
+    }
+
+COutlineCacheItem::~COutlineCacheItem() 
+    { 
+    iUsers.ResetAndDestroy(); 
+    }
+
+COutlineCacheItem::COutlineCacheItem(TInt aOffset, TInt aLength):
+    iOffset(aOffset), iLength(aLength)
+    {
+    // a null constructor.
+    }
+
+TInt COutlineCacheItem::DecRefCount(TInt aSessionHandle)
+    {
+    TInt id = 0; 
+    TInt ret = FindUser(aSessionHandle, &id);
+    if (KErrNone == ret)
+        {
+        iUsers[id]->iRefCount--;
+        if (0 == iUsers[id]->iRefCount) 
+            {
+            delete iUsers[id];
+            iUsers.Remove(id);
+            }
+        return iUsers.Count();
+        }
+    return KErrNotFound;
+    }
+
+TInt COutlineCacheItem::IncRefCount(TInt aSessionHandle)
+    {
+    TInt id = 0; 
+    TInt ret = FindUser(aSessionHandle, &id);
+    if (KErrNone == ret)
+        {
+        iUsers[id]->iRefCount++;
+        }
+    else
+        {
+        TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
+        if (NULL != newUser)
+            {
+            TRAP(ret, iUsers.AppendL(newUser));
+            }
+        else 
+            {
+            ret = KErrNoMemory;
+            }
+        //coverity[leaked_storage]
+        // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount().
+        }
+    return ret;
+    }
+
+#ifdef _DEBUG
+TInt CUnhintedOutlineCache::GetCacheState(const char *func)
+    {
+    RDebug::Printf("%s called from %s: ", __func__, func);
+    int numSessions = 0, totalRef = 0;
+    THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        COutlineCacheItem **data = it.CurrentValue();
+        int len = (*data)->iUsers.Count();
+        numSessions += len;
+        for (int j = 0; j < len; ++j)
+            {
+            totalRef += (*data)->iUsers[j]->iRefCount;
+            }
+        it.NextValue();
+        }
+    
+    TBuf<256> buf;
+    buf.Append(_L("Unhinted outline cache: "));
+    TInt numItems = iItemIdMap.Count();
+    if (0 == numItems)
+        {
+        buf.Append(_L("empty. "));
+        }
+    else 
+        {
+        buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
+                numItems, numSessions, totalRef);
+        }
+        
+    RDebug::RawPrint(buf);
+            
+    return 0;
+    }
+#endif
+
+CUnhintedOutlineCache::CUnhintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
+    iCacheMemMon(aMon), iHeap(aHeap), 
+    iItemIdMap(THashFunction32<TUnhintedOutlineId>(CUnhintedOutlineCache::IdHash),
+        TIdentityRelation<TUnhintedOutlineId>(CUnhintedOutlineCache::IdIdentity))
+    { 
+    
+    }
+
+CUnhintedOutlineCache::~CUnhintedOutlineCache()
+    {
+    THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        const TUnhintedOutlineId *outlineId = it.CurrentKey();
+        COutlineCacheItem **data = it.CurrentValue();
+        
+        // loop body here!
+        iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+        delete (*data);
+        iItemIdMap.Remove(*outlineId);
+        // end loop body
+        
+        it.NextValue();
+        }
+    return;
+    }
+
+
+TInt CUnhintedOutlineCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile)
+    {
+    TUid fileUid = aFontFile->Uid();
+    
+    THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        const TUnhintedOutlineId *outlineId = it.CurrentKey();
+        COutlineCacheItem **data = it.CurrentValue();
+        
+        // loop body here!
+        if (outlineId->iFileUid == fileUid)
+            {
+            iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+            iCacheMemMon.Dec((*data)->iLength);
+            delete (*data);
+            iItemIdMap.Remove(*outlineId);
+            }
+        // end loop body
+        
+        it.NextValue();
+        }
+    return KErrNone;
+    }
+
+TInt CUnhintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
+    {
+    THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        const TUnhintedOutlineId *outlineId = it.CurrentKey();
+        COutlineCacheItem **data = it.CurrentValue();
+        
+        // loop body here!
+        TInt id = 0;
+        TInt ret = (*data)->FindUser(aSessionHandle, &id);
+        if (KErrNone == ret)
+            {
+            delete (*data)->iUsers[id];
+            (*data)->iUsers.Remove(id);
+            if (0 == (*data)->iUsers.Count())
+                {
+                iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+                iCacheMemMon.Dec((*data)->iLength);
+                delete (*data);
+                iItemIdMap.Remove(*outlineId);
+                }
+            }
+        // end loop body
+        
+        it.NextValue();
+        }
+    return KErrNone;
+    }
+
+
+TInt CUnhintedOutlineCache::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
+        TAny* const aData, const TInt aLength, TAny *&aOutline, TInt &aLen)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
+        {
+        RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
+        return KErrNoMemory;
+        }
+    
+    aLen = KErrGeneral;
+    TInt ret1= KErrNone;
+
+    // make a copy of the outline data on the shared heap.
+    TAny *sharedCopy = iHeap->Alloc(aLength);
+    if (NULL == sharedCopy) 
+        {
+        return KErrNoMemory;
+        }
+    
+    Mem::Copy(sharedCopy, aData, aLength);
+
+    COutlineCacheItem *newItem = NULL;
+    TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
+    TRAP(ret1, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
+    if (KErrNone != ret1)
+        {
+        iHeap->Free(sharedCopy);
+        sharedCopy = NULL;
+        }
+    else 
+        {
+        TRAP(ret1, iItemIdMap.InsertL(aOutlineId, newItem));
+        if (KErrNone != ret1)
+            {
+            delete newItem;
+            iHeap->Free(sharedCopy);
+            sharedCopy = NULL;
+            }
+        else
+            {
+            iCacheMemMon.Inc(aLength);
+            aLen = aLength;
+            }
+        }
+    aOutline = sharedCopy;
+    return ret1;  
+    }
+
+TInt CUnhintedOutlineCache::IncRefCount(const TUnhintedOutlineId &aOutlineId,
+        TInt aSessionHandle)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
+    if (NULL != ret)
+        {
+        (*ret)->IncRefCount(aSessionHandle);
+        }
+    return (NULL==ret?KErrNotFound:KErrNone);
+    }
+
+TInt CUnhintedOutlineCache::DecRefCount(const TUnhintedOutlineId &aOutlineId,
+        TInt aSessionHandle)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); 
+    if (NULL != ret) 
+        {
+        TInt numUsers = (*ret)->DecRefCount(aSessionHandle);
+        if (0 == numUsers) 
+            {
+            // There is no outstanding reference to the cache item.
+            iHeap->Free(OffsetToPointer((*ret)->iOffset, iHeap->Base()));
+            iCacheMemMon.Dec((*ret)->iLength);
+            delete (*ret);
+            iItemIdMap.Remove(aOutlineId);
+            }
+        }
+    return (NULL==ret?KErrNotFound:KErrNone);
+    }
+
+TInt CUnhintedOutlineCache::Find(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
+        TInt &aLength)
+    {
+    COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
+    TInt ret2 = KErrNone;
+    if (NULL != ret)
+        {
+        aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
+        aLength = (*ret)->iLength;
+        }
+    else
+        {
+        ret2 = KErrNotFound;
+        }
+    return ret2;
+    }
+    
+  
+TUint32 CUnhintedOutlineCache::IdHash(const TUnhintedOutlineId &outlineId)
+    {
+    // The hash value: 
+    // bits 0-15: glyph id; 
+    // bits 16-23: lower 8 bit of font file uid
+    // bits 24-27: lower 4 bit of the face index
+    // bit 28: 'isGlyphId'
+    TUint32 ret = 0;
+    ret |= (outlineId.iId & KOutlineGlyphIdHashMask);
+    ret |= (KOutlineFileUidHashMask & (outlineId.iFileUid.iUid << 16));
+    ret |= (KOutlineFaceIndexHashMask & (outlineId.iFaceIndex << 24));
+    ret = (ret % 701);
+    return ret;
+    }
+
+TBool CUnhintedOutlineCache::IdIdentity(const TUnhintedOutlineId &id1, const TUnhintedOutlineId &id2)
+    {
+    return id1.iId == id2.iId && id1.iFaceIndex == id2.iFaceIndex &&
+            id1.iFileUid == id2.iFileUid;
+    }
+
+// hinted outline cache
+#ifdef _DEBUG
+TInt CHintedOutlineCache::GetCacheState(const char *func)
+    {
+    RDebug::Printf("%s called from %s: ", __func__, func);
+    int numSessions = 0, totalRef = 0;
+    THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        COutlineCacheItem **data = it.CurrentValue();
+        int len = (*data)->iUsers.Count();
+        numSessions += len;
+        for (int j = 0; j < len; ++j)
+            {
+            totalRef += (*data)->iUsers[j]->iRefCount;
+            }
+        it.NextValue();
+        }
+    
+    TBuf<256> buf;
+    buf.Append(_L("Hinted outline cache: "));
+    TInt numItems = iItemIdMap.Count();
+    if (0 == numItems)
+        {
+        buf.Append(_L("empty. "));
+        }
+    else 
+        {
+        buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
+                numItems, numSessions, totalRef);
+        }
+        
+    RDebug::RawPrint(buf);
+            
+    return 0;
+    }
+#endif
+
+TInt CHintedOutlineCache::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
+    {
+    THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        const THintedOutlineId *outlineId = it.CurrentKey();
+        COutlineCacheItem **data = it.CurrentValue();
+        
+        // loop body here!
+        if (outlineId->iFont == aFont)
+            {
+            iCacheMemMon.Dec((*data)->iLength);
+            iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+            delete (*data);
+            iItemIdMap.Remove(*outlineId);
+            }
+        // end loop body
+        
+        it.NextValue();
+        }
+    return KErrNone;
+    }
+
+TInt CHintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
+    {
+    THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
+    it.NextValue();
+    while (it.CurrentValue())
+        {
+        const THintedOutlineId *outlineId = it.CurrentKey();
+        COutlineCacheItem **data = it.CurrentValue();
+        
+        // loop body here!
+        TInt id = 0; 
+        TInt ret = (*data)->FindUser(aSessionHandle, &id);
+        if (KErrNone == ret)
+            {
+            delete (*data)->iUsers[id];
+            (*data)->iUsers.Remove(id);
+            if (0 == (*data)->iUsers.Count())
+                {
+                iCacheMemMon.Dec((*data)->iLength);
+                iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+                delete (*data);
+                iItemIdMap.Remove(*outlineId);
+                }
+            }
+        // end loop body
+        
+        it.NextValue();
+        }
+
+    return KErrNone;
+    }
+
+
+CHintedOutlineCache::CHintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
+    iCacheMemMon(aMon), iHeap(aHeap), 
+    iItemIdMap(THashFunction32<THintedOutlineId>(CHintedOutlineCache::IdHash),
+        TIdentityRelation<THintedOutlineId>(CHintedOutlineCache::IdIdentity)) 
+    { 
+    // a null constructor
+    }
+
+TInt CHintedOutlineCache::CacheHintedOutline(const THintedOutlineId &aOutlineId,
+        TAny* aData, TInt aLength, TAny *&aOutline, TInt &aLen)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
+        {
+        RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
+        return KErrNoMemory;
+        }
+    
+    aLen = KErrGeneral;
+    TInt ret = KErrNone;
+    // make a copy of the outline data on the shared heap.
+    TAny *sharedCopy = iHeap->Alloc(aLength);
+    if (NULL == sharedCopy) 
+        {
+        return KErrNoMemory;
+        }
+    
+    Mem::Copy(sharedCopy, aData, aLength);
+
+    COutlineCacheItem *newItem = NULL;
+    TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
+    TRAP(ret, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
+    if (KErrNone != ret)
+        {
+        iHeap->Free(sharedCopy);
+        sharedCopy = NULL;
+        }
+    else 
+        {
+        TRAP(ret, iItemIdMap.InsertL(aOutlineId, newItem));
+        if (KErrNone != ret)
+            {
+            delete newItem;
+            iHeap->Free(sharedCopy);
+            sharedCopy = NULL;
+            }
+        else
+            {
+            iCacheMemMon.Inc(aLength);
+            aLen = aLength;
+            }
+        }
+    aOutline = sharedCopy;
+    return ret;
+    }
+
+TInt CHintedOutlineCache::IncRefCount(const THintedOutlineId &aOutlineId, 
+        TInt aSessionHandle)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
+    if (NULL != data)
+        {
+        (*data)->IncRefCount(aSessionHandle);
+        }
+    return (NULL==data?KErrNotFound:KErrNone);
+    }
+
+TInt CHintedOutlineCache::DecRefCount(const THintedOutlineId &aOutlineId,
+        TInt aSessionHandle)
+    {
+#ifdef _DEBUG
+    GetCacheState(__func__);
+#endif
+    COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
+    if (NULL != data) 
+        {
+        TInt numUsers = (*data)->DecRefCount(aSessionHandle);
+        if (0 == numUsers) 
+            {
+            // There is no outstanding reference to the cache item.
+            iCacheMemMon.Dec((*data)->iLength);
+            iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
+            delete (*data);
+            iItemIdMap.Remove(aOutlineId);
+            }
+        }
+    return (NULL==data?KErrNotFound:KErrNone);
+    }
+
+TInt CHintedOutlineCache::Find(const THintedOutlineId &aOutlineId, 
+        TAny *&aData, TInt &aLength)
+    {
+    COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
+    TInt ret2 = KErrNone;
+    if (NULL != ret)
+        {
+        aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
+        aLength = (*ret)->iLength;
+        }
+    else
+        {
+        ret2 = KErrNotFound;
+        }
+    return ret2;
+    }
+
+
+TUint32 CHintedOutlineCache::IdHash(const THintedOutlineId &outlineId)
+    {
+    // The hash value:
+    // bits 0-15: the outline id
+    // bits 16-27: the lower 12 bits of the font pointer
+    // bit 28: 'isGlyphId'
+    
+    TUint32 ret = 0;
+    ret |= (KOutlineGlyphIdHashMask & outlineId.iId);
+    ret |= (KOutlineFontPtrHashMask & (((TUint32)outlineId.iFont) << 16));
+    ret = ret % 701;
+    return ret;
+    }
+
+TBool CHintedOutlineCache::IdIdentity(const THintedOutlineId &id1, const THintedOutlineId &id2)
+    {
+    return id1.iId == id2.iId && id1.iFont == id2.iFont;
+    }
+// hinted cache
+
+
+CFontStore::CFontStore(RHeap* aHeap):
+	iKPixelWidthInTwips(KDefaultPixelWidthInTwips),
+	iKPixelHeightInTwips(KDefaultPixelHeightInTwips),
+	iFs(),
+	iHeap(aHeap),
+	iFontStoreFileList(KDefaultArrayGranularity),			// list of EPOC Bitmap font files loaded
+	iTypefaceList(KDefaultArrayGranularity),
+	iFontBitmapList(KDefaultArrayGranularity),
+	iTypefaceFontBitmapList(KDefaultArrayGranularity),
+	iOpenFontFileList(KDefaultArrayGranularity),			// list of 'Open Font' files loaded
+	iOpenFontRasterizerList(KDefaultArrayGranularity),		// open rasterizers, in load order
+	iOpenFontUid(1),
+	iDefaultBitmapType(EMonochromeGlyphBitmap),
+	iShaperFactoryList(KDefaultArrayGranularity),
+	iOpenFontShaperCacheMemUsage(0),
+	iNumberOfShaperCaches(0),
+	iOpenFontTypefaceSupportList(KDefaultArrayGranularity),	// list of Open Font typefaces available
+	iUniqueFontIdCount(0)									// used to give every font a unique id
+	{
+	}
+
+void CFontStore::ConstructL()
+	{
+	// Cache is placed in the shared heap
+	iOpenFontSessionCacheList = (COpenFontSessionCacheList*)iHeap->AllocL(sizeof(COpenFontSessionCacheList));
+	new(iOpenFontSessionCacheList) COpenFontSessionCacheList;
+
+	CTypefaceStore::ConstructL();
+	User::LeaveIfError(iFs.Connect());
+
+	TMachineInfoV1Buf machineInfoBuffer;
+	User::LeaveIfError(UserHal::MachineInfo(machineInfoBuffer));
+	
+	//Create Handles which may be used by Fntstore
+	iHandleArray = new(ELeave) RArray<RHandleBase>();
+
+	RSemaphore SessionCacheSem;
+	TInt ret = SessionCacheSem.CreateGlobal(KSessionCacheSemaphoreName,KSessionCacheSemaphoreCount);
+	if(ret == KErrAlreadyExists)
+	    {
+	    User::LeaveIfError(SessionCacheSem.OpenGlobal(KSessionCacheSemaphoreName));
+	    }
+	else if (ret != KErrNone)
+	    {
+	    User::LeaveIfError(ret);	    
+	    }
+	ret = iHandleArray->Append(SessionCacheSem);
+	if(ret != KErrNone)
+	    {
+	    SessionCacheSem.Close();
+	    User::Leave(ret);
+	    }
+
+	const TSize twipSize = machineInfoBuffer().iPhysicalScreenSize;
+	const TSize pixelSize = machineInfoBuffer().iDisplaySizeInPixels;
+
+	if (twipSize.iWidth > 0 && pixelSize.iWidth > 0)
+		iKPixelWidthInTwips = twipSize.iWidth * 1000 / pixelSize.iWidth;
+
+	if (twipSize.iHeight > 0 && pixelSize.iHeight > 0)
+		iKPixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight;
+	
+	iCacheMemMon = new(ELeave) TFontTableGlyphOutlineCacheMemMonitor;
+	iUnhintedOutlineCache = new(ELeave) CUnhintedOutlineCache(iHeap, *iCacheMemMon);
+	iHintedOutlineCache = new(ELeave) CHintedOutlineCache(iHeap, *iCacheMemMon);
+	iFontTableCache = new(ELeave) CFontTableCache(iHeap, *iCacheMemMon);
+	
+	}
+
+/** Creates a new CFontStore object.
+
+Sets iKPixelWidthInTwips and iKPixelHeightInTwips.
+
+Sets the default bitmap type, used when getting bitmap fonts, to EMonochromeGlyphBitmap.
+
+Also initialises other private member variable values .
+
+@param aHeap A pointer to the heap class used for memory allocation.
+@leave KErrNoMemory Insufficient memory available on the heap. */
+EXPORT_C CFontStore *CFontStore::NewL(RHeap* aHeap)
+	{
+	User::LeaveIfNull(aHeap);
+	CFontStore *fontstore = new(ELeave) CFontStore(aHeap);
+	CleanupStack::PushL(fontstore);
+	fontstore->ConstructL();
+	CleanupStack::Pop(fontstore);
+	return fontstore;
+	}
+
+/** Destructor. */
+EXPORT_C CFontStore::~CFontStore()
+	{
+	// Remove All font files, and Reset associated arrays
+	RemoveFile(KNullUid);
+	iOpenFontRasterizerList.ResetAndDestroy();
+	iShaperFactoryList.ResetAndDestroy();
+	if (iOpenFontSessionCacheList)
+		{
+		iOpenFontSessionCacheList->Delete(iHeap);
+		iHeap->Free(iOpenFontSessionCacheList);
+		}
+    if (iHandleArray)
+        {
+        for (TInt i = 0; i < iHandleArray->Count(); i++)
+            {
+            (*iHandleArray)[i].Close();
+            }
+        iHandleArray->Close();
+        delete iHandleArray;
+        }
+	iFs.Close();
+	
+    delete iFontTableCache;
+    delete iUnhintedOutlineCache;
+    delete iHintedOutlineCache;
+    delete iCacheMemMon;
+	}
+
+
+// local utility functions
+// reads bytes from file, if the requested number of bytes are not available it leaves
+void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength)
+	{
+	User::LeaveIfError(aFile.Read(aDes, aLength));
+	if (aDes.Length() != aLength)
+		{
+#ifdef _DEBUG
+		RDebug::Print(_L("EOF reading structure from font file\n"));
+#endif
+		User::Leave(KErrCorrupt);
+		}
+	}
+
+// local function(s) to read values from buffer & validate them
+TUint TtfTableTagFromBufferL(TDes8& aDes)
+	{
+	TUint value = 0;
+	for (TUint index = 0; index < 4;)
+		{
+		TUint temp = static_cast<TUint>(aDes[index++]);
+		// must be ASCII character between 32 & 126 inclusive (per Apple's TTF specification document)
+		if ( (temp < 32) || (temp > 126) )
+			{
+			User::Leave(KErrCorrupt);
+#ifdef _DEBUG
+			RDebug::Print(_L("invalid ASCII character (0x%x) in ttf table tag\n"), temp);
+#endif
+			}
+		value = (value << 8) | temp;
+		}
+	return value;
+	}
+
+/* Sanity check for TrueType Font, checks that the font tables are sensible.
+*/
+void CFontStore::SanityCheckForTtfL(RFile& aFontFile, TUint aFontFileSize, TBool aStrictChecking)
+	{
+#if defined(_DEBUG)
+	RDebug::Print(_L("TTF File Size is %u (0x%x) bytes\n"), aFontFileSize, aFontFileSize);
+#endif
+
+	// check the Offset Table at the start of the file
+	TBuf8<16>	fileBuffer;
+
+	ReadFromFileL(aFontFile, fileBuffer, 12);
+	TUint numTables = (fileBuffer[4] << 8) | (fileBuffer[5]);
+	TUint searchRange = (fileBuffer[6] << 8) | (fileBuffer[7]);
+	TUint entrySelector = (fileBuffer[8] << 8) | (fileBuffer[9]);
+	TUint rangeShift = (fileBuffer[10] << 8) | (fileBuffer[11]);
+
+	const TInt tableStart = 12 + (numTables << 4);	// lowest possible address for actual table data
+
+	if ( (numTables == 0) || (numTables & 0xF0000000) || (tableStart > aFontFileSize) )
+		{
+#ifdef _DEBUG
+		RDebug::Print(_L("# of tables (%i) in ttf is invalid\n"), numTables);
+#endif
+		User::Leave(KErrCorrupt);
+		}
+
+#if defined(_DEBUG) && defined(VERBOSE_DEBUG)
+	// scalar type is 0x00010000 for Windows fonts, other possible values include 0x74727565 and 0x74797031: not checked
+	TUint scalarType = (fileBuffer[0] << 24) | (fileBuffer[1] << 16) | (fileBuffer[2] << 8) | (fileBuffer[3]);
+	RDebug::Print(_L("ttf scalarType is 0x%x, # of tables is %u\n"), scalarType, numTables);
+	RDebug::Print(_L("searchRange is 0x%x, entrySelector is 0x%x, rangeShift is 0x%x\n"), 
+		searchRange, entrySelector, rangeShift);
+#endif
+
+	// check searchRange, entrySelector & rangeShift values
+	// (some not quite TTF files fail the rangeShift check)
+	if ( (searchRange < 16) || (entrySelector > 24)
+		|| (aStrictChecking && (rangeShift != ( (numTables << 4) - searchRange )) ) )
+		{
+#ifdef _DEBUG
+		RDebug::Print(_L("searchRange (0x%x), entrySelector (0x%x) or rangeShift (0x%x) invalid for numTables (%i)\n"), 
+			searchRange, entrySelector, rangeShift, numTables);
+#endif
+		User::Leave(KErrCorrupt);
+		}
+
+	// entrySelector is defined as Log2(Maximum power of 2 <= nmumTables)
+	TUint exp = 1 << entrySelector;		// log to exponent
+	if ( (numTables < exp) || (numTables > (exp << 1)) )
+		{
+#ifdef _DEBUG
+		RDebug::Print(_L("entrySelector (0x%x) wrong for numTables(%i)\n"), entrySelector, numTables);
+#endif
+		User::Leave(KErrCorrupt);
+		}
+
+	// easy checks on the table directory
+	TInt totalFontSize = tableStart;				// accumulated total directories plus table sizes
+	TInt highestTableEnd = 0;						// highest value found for table start plus table length
+	TUint lastTableTag = 0;							// to check that tags are in order
+	TInt tableNum = 0;
+
+	do 
+		{ // each entry is 16 bytes, (though we don't check the checksum)
+		ReadFromFileL(aFontFile, fileBuffer, 16);
+		TUint tableTag = TtfTableTagFromBufferL(fileBuffer);
+		TUint offset = (fileBuffer[8] << 24) | (fileBuffer[9] << 16) | (fileBuffer[10] << 8) | (fileBuffer[11]);
+		TUint length = (fileBuffer[12] << 24) | (fileBuffer[13] << 16) | (fileBuffer[14] << 8) | (fileBuffer[15]);
+
+#if defined(_DEBUG) && defined(VERBOSE_DEBUG)
+		RDebug::Print(_L("ttf table tag ('%c%c%c%c'): offset is 0x%x, length is 0x%x\n"), 
+			tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F, 
+			offset, length);
+#endif
+		length = (length + 3) & ~3;	// round up, all tables must be a multiple of 4 bytes for checksumming
+
+		// table Tags must be unique & in order
+		if (tableTag <= lastTableTag)
+			{
+#ifdef _DEBUG
+			RDebug::Print(_L("ttf table tag ('%c%c%c%c') is out of order\n"), 
+				tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F);
+#endif
+			User::Leave(KErrCorrupt);
+			}
+
+
+		// the offset must be 4-byte aligned, and after the table directory
+		// offset + length must be bigger than the start offset (!)
+		TInt end = length + offset;
+		if ( (offset & 3) || (offset < tableStart) || (length == 0) || (end < offset) || (end > aFontFileSize))
+			{
+#ifdef _DEBUG
+			RDebug::Print(_L("offset (0x%x) or length (0x%x) are bad\n"), offset, length);
+#endif		
+			User::Leave(KErrCorrupt);
+			}
+
+		lastTableTag = tableTag;
+		totalFontSize += length;
+		if (end > highestTableEnd)
+			{
+			highestTableEnd = end;
+			}
+		}
+		while (++tableNum < numTables);
+
+#if defined(_DEBUG) && defined(VERBOSE_DEBUG)
+	RDebug::Print(_L("last address used by any table is 0x%x, Minimum font file size to hold all tables is 0x%x\n"), 
+			highestTableEnd, totalFontSize);
+#endif
+
+	// for single font files highestTableEnd & totalFontSize should be the same
+	if (highestTableEnd != totalFontSize)
+		{
+#ifdef _DEBUG
+		RDebug::Print(_L("Total Font Size (0x%x) is different from end of the last table (0x%x)\n"), 
+				highestTableEnd, totalFontSize);
+#endif
+		User::Leave(KErrCorrupt);
+		}
+	}
+
+/* Sanity checks on font files, currently only knows about TrueType Font files: .ttf and .otf
+Protects FBserv / the client and the rasterizer plug-in from grossly corrupt data.
+@leave KErrCorrupt if the font tables are daft
+*/
+void CFontStore::SanityCheckFontFileL(TParse& aParse)
+	{
+
+	// try to open the file and getting the file size
+	RFile fontFile;
+	const TInt openError = fontFile.Open(iFs, aParse.FullName(), EFileRead | EFileShareReadersOnly);
+#ifdef _DEBUG
+	if (KErrNone != openError)
+		{
+		const TDesC& fileName = aParse.FullName();
+		RDebug::Print(_L("Sanity checking font file \"%S\", file open gave error %d\n"), &fileName, openError);
+		}
+#endif
+	User::LeaveIfError(openError);
+	CleanupClosePushL(fontFile);
+	TInt fontFileSize = 0;
+	User::LeaveIfError(fontFile.Size(fontFileSize));
+
+	if (fontFileSize == 0)
+		{ // no font can be zero length!
+#ifdef _DEBUG
+		RDebug::Print(_L("font file size (%i) is zero\n"), fontFileSize);
+#endif
+		User::Leave(KErrCorrupt);
+		}
+	else
+		{
+		const TDesC& fileExt = aParse.Ext();
+		// TrueType fonts
+		_LIT(KFntStoreTrueTypeExtension,".ttf");
+		// OpenType fonts
+		_LIT(KFntStoreOpenTypeExtension,".otf");
+		// other font files that follow TTF format
+		_LIT(KFntStoreCccFontFileExtension,".ccc");
+
+		if ( (0 == fileExt.CompareF(KFntStoreTrueTypeExtension)) || (0 == fileExt.CompareF(KFntStoreOpenTypeExtension)) )
+			{ // uses TrueType file format, perform strict format check
+			SanityCheckForTtfL(fontFile, fontFileSize, ETrue);
+			}
+		else if (0 == fileExt.CompareF(KFntStoreCccFontFileExtension))
+			{ // uses nearly TrueType file format, perform slightly less strict format check
+			SanityCheckForTtfL(fontFile, fontFileSize, EFalse);
+			}
+
+		// extendible if required for other font file types ...
+		}
+
+	CleanupStack::PopAndDestroy(&fontFile);
+	}
+
+
+/** Finds or creates a font file object to support a font file. The specified font
+file must be accessible to any process, i.e. not located inside an
+application's private directory.
+
+If an appropriate font file object exists then no new open font file is created. 
+In this case the reference count of the font file object is incremented.
+
+Notes:
+
+If aName is recognised as an open font file, creates a COpenFontFile, which 
+will manage the font file specified by aName, and adds it to the file store's 
+list of open font files.
+
+The list of open font files is used when getting the nearest font for a font 
+specification (i.e. by the GetNearestFont...() functions of this class) if 
+the font is generated via a rasterizer.
+
+The appropriate rasterizer, which supports the font format of the font file, 
+is used to generate the open font file using COpenFontRasterizer::NewFontFileL().
+
+If aName is not recognised as an open font file then CFontStoreFile tries to open
+the file as a Symbian Bitmap font.
+
+@param aName The full path and filename of the font file to be supported.
+@return The UID of the font file object supporting aName.
+@leave KErrNotSupported if the file is not recognised at all
+@leave KErrCorrupt if the font file data does not make sense
+@leave or another system-wide error
+*/
+EXPORT_C TUid CFontStore::AddFileL(const TDesC& aName)
+	{
+	TParse fontFilename;
+	User::LeaveIfError(iFs.Parse(aName, fontFilename));
+
+	// increment reference count if font file is already loaded
+	TUid fontUid = KNullUid;
+
+	if (IncRefCountOfLoadedFont(fontFilename, fontUid))
+		{
+		return fontUid;
+		}
+
+	// Do not validate fonts on Z: (assumed to be ROM created with valid fonts)
+	if (!FileIsOnZ(fontFilename))
+		{
+		// file is not open - check that the file exists and has a plausible content
+		SanityCheckFontFileL(fontFilename);
+		}
+	
+	AddSanityCheckedFontL(fontFilename, fontUid);
+	
+	return fontUid;
+	}
+
+/**
+Finds or creates a font file object to support a font file.
+@param aFileName The filename to check
+@param aUid The list to check
+@see CFontStore::AddFileL
+*/
+void CFontStore::AddSanityCheckedFontL(const TParse& aFileName, TUid& aUid)
+	{
+	// Try loading the file as an Open Font
+	if (!LoadFileAsOpenFontL(aFileName, aUid))
+		{
+		// It could not be recognised as an Open Font file so load it as an EPOC bitmap font file.
+		// (This always succeeds or Leaves.)
+		aUid = LoadFileAsBitmapFontL(aFileName);
+		}
+	}
+
+
+// Remove a Font File - called via the Cleanup Stack if a leave occurs during font install
+void CFontStore::CleanupRemoveFontFile(TAny* aCleanupInfo)
+	{
+	TCleanupRemoveFontFile* cleanupInfo = (TCleanupRemoveFontFile *) aCleanupInfo;
+	cleanupInfo->iFontStore->RemoveFile(cleanupInfo->iFontUid);
+	}
+
+
+/** Search through the rasterizers for one that will open the font filename.
+
+Can leave if the rasterizer encounters an error, such as unexpected end of file, nonsense data, no memory.
+
+@param aName full filename to open
+@param aFontUid set to the font file UID if it is already loaded
+@return ETrue if the font file is loaded, otherwise EFalse
+@internalComponent
+*/
+TBool CFontStore::LoadFileAsOpenFontL(const TParse& aFileName, TUid& aFontUid)
+	{
+	const TDesC& fullName = aFileName.FullName();
+	
+	// ask each of the rasterizers in turn to create a COpenFontFile object.
+	const TInt rasterizerCount = iOpenFontRasterizerList.Count();
+	for (TInt index = 0; index < rasterizerCount; index++)
+		{
+		COpenFontFile* openFontFile = iOpenFontRasterizerList[index]->NewFontFileL(iOpenFontUid, fullName, iFs);
+		if (NULL != openFontFile)
+			{
+			/* Uids for Open Fonts are allocated in order; the
+			one for the COpenFontFile just created won't match any existing one.
+			(When a file is removed, the fake Uid will match, because the one that was returned here is used.)
+			*/
+			CleanupStack::PushL(openFontFile);
+			openFontFile->SetFontStoreL(this);
+			iOpenFontFileList.AppendL(openFontFile);
+			openFontFile->IncRefCount();
+			CleanupStack::Pop(openFontFile);
+
+			TInt typefaceAddError = AddTypefacesToSupportList(openFontFile);
+			if (typefaceAddError)
+				{
+				// cleanup
+				RemoveFile(openFontFile->Uid());
+				// throw the error
+				User::Leave(typefaceAddError);
+				}
+
+			/*
+			iOpenFontUid is the fake Uid used for new font files. It is made modulo a 'zillion' (2^28)
+			so that it cannot conflict with real Uids, which are >= 2^28. It starts at 1 so that
+			it does not conflict with the value 0 (KNullUid) which is used as a sentinel in
+			CFontStore::RemoveFileL.
+			*/
+			++iOpenFontUid;
+			iOpenFontUid = iOpenFontUid % 0x1000000;
+
+			aFontUid = openFontFile->Uid();
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+
+/** Search loaded fonts for filename, and increment the reference count
+@param aParse full filename to search for
+@return the font file UID
+@leave KErrNotSupported or another system wide error code
+@internalComponent
+*/
+TUid CFontStore::LoadFileAsBitmapFontL(const TParse& aParse)
+	{
+	// open the file, presuming it is a bitmap font
+	CFontStoreFile* fontStoreFile = CFontStoreFile::NewL(aParse, iFs);
+
+	// See if a font with this UID is already open
+	TInt match = FindBitmapFontFileIndexByUid(fontStoreFile->iCollectionUid);
+	if (match != KErrNotFound) // The file is open.
+		{ // close the new duplicate, inc the reference count
+		delete fontStoreFile;
+		fontStoreFile = iFontStoreFileList[match];
+		fontStoreFile->iUsageCount++;
+		}
+	else
+		{
+		CleanupStack::PushL(fontStoreFile);
+		iFontStoreFileList.AppendL(fontStoreFile);
+		CleanupStack::Pop(fontStoreFile);
+
+		// special object to removes the font file if a leave occurs during font install
+		TCleanupRemoveFontFile cleanupHelper(this, fontStoreFile->iCollectionUid);
+		CleanupStack::PushL(TCleanupItem(CleanupRemoveFontFile, &cleanupHelper));
+		// install the new font
+		InternalizeFontStoreFileL(fontStoreFile, fontStoreFile->iFontVersion);
+		CleanupStack::Pop(&cleanupHelper); // CleanupRemoveFontFile
+		}
+	return fontStoreFile->iCollectionUid;
+	}
+
+
+/** Search open Bitmap font files for matching UID
+@param aUid UID to search for
+@return The index of the matching item in iFontStoreFileList[] array, or KErrNotFound
+@internalComponent
+*/
+TInt CFontStore::FindBitmapFontFileIndexByUid(TUid aUid)
+	{
+	const TInt fontFileCount = iFontStoreFileList.Count();
+	for (TInt index = 0; index < fontFileCount; index++)
+		{
+		if (iFontStoreFileList[index]->iCollectionUid == aUid)
+			{
+			return index;
+			}
+		}
+	return KErrNotFound;
+	}
+
+
+/** Search loaded fonts for filename, and increment the reference count
+@param aName full filename to search for
+@param aFontUid set to the font file UID if it is already loaded
+@return ETrue if the font file is already loaded, otherwise EFalse
+@internalComponent
+*/
+TBool CFontStore::IncRefCountOfLoadedFont(const TParse& aFileName, TUid& aFontUid)
+	{
+	const TDesC& fullName = aFileName.FullName();
+	
+	// Is it already in the Open Font list? Compare by full filename, not (fake) Uid;
+	const TInt openFontCount = iOpenFontFileList.Count();
+	TInt i = 0;
+	for (i = 0; i < openFontCount; ++i)
+		{
+		COpenFontFile* openFontFile = iOpenFontFileList[i];
+		if (fullName.CompareF(openFontFile->FileName()) == 0)
+			{
+			// Open Font file already loaded
+			openFontFile->IncRefCount();
+			aFontUid = openFontFile->Uid();
+			return ETrue;
+			}
+		}
+
+	// already open as an EPOC bitmap font file?
+	const TInt fontFileCount = iFontStoreFileList.Count();
+	for (i = 0; i < fontFileCount; i++)
+		{
+		CFontStoreFile* fontStoreFile = iFontStoreFileList[i];
+		if (fullName.CompareF(fontStoreFile->FullName()) == 0)
+			{
+			// font file already loaded
+			++(fontStoreFile->iUsageCount);
+			aFontUid = fontStoreFile->iCollectionUid;
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+
+/** Releases a hold on one or all font file objects (COpenFontFiles or CFontStoreFiles).
+
+If aFileUid identifies a font file object, then the reference count for this 
+object is decremented. If this brings the reference count down to zero then 
+the font file object and typefaces associated with this file are removed from
+the font store, provided no fonts associated with this file are being accessed. 
+If one or more fonts are being accessed then the file removal request will be ignored.
+
+If, on the other hand, aFileUid's value is NULL, then all font file objects 
+are removed, along with all fonts and typefaces in the font store, provided
+that no fonts in the font store are being accessed (i.e. iFontAccess is empty),
+otherwise it has no effect.
+
+(If aFileUid is invalid, then no objects are removed.)
+
+@param aFileUid UID of a hold on a font file object to be released, or KNullUid
+if all font file objects are to be removed.
+*/
+EXPORT_C void CFontStore::RemoveFile(TUid aFileUid)
+	{
+	TInt i, count;
+	if (aFileUid == KNullUid)	// this means 'delete all files'
+		{
+		if(iFontAccess)
+			{
+			TInt count = iFontAccess->Count();		
+			for (TInt i = 0; i < count; i++)
+				if((*iFontAccess)[i].iAccessCount)
+					return;
+			}
+		if (iFontTableCache && iFontTableCache->HasOutstandingRefCount())
+		    {
+		    // disallow font file removal if any font tables are still cached
+		    return;
+		    }
+		
+		iTypefaceList.ResetAndDestroy();
+		count = iFontBitmapList.Count();
+		for (TInt i = 0; i < count; i++)
+			iFontBitmapList[i]->Release();
+		iFontBitmapList.Reset();
+		iTypefaceFontBitmapList.Reset();
+		iFontStoreFileList.ResetAndDestroy();
+		iOpenFontFileList.ResetAndDestroy();
+		iOpenFontTypefaceSupportList.ResetAndDestroy();
+		}
+	else
+		{
+		// See if it's an Open Font file.
+		count = iOpenFontFileList.Count();
+		for (i = 0; i < count; i++)
+			{
+			TInt fontAccessCount;
+			if (iOpenFontFileList[i]->Uid() == aFileUid)
+				{ // found the file
+				if (iFontAccess)
+					{ // Check to see if there are any references before we consider deleting
+					fontAccessCount = iFontAccess->Count();
+					for (TInt kk = 0; kk < fontAccessCount; ++kk)
+						{
+		  	  	  		CBitmapFont* bitmapFont = reinterpret_cast<CBitmapFont*>((*iFontAccess)[kk].iFont);
+		  	  	  		COpenFont* openFont = bitmapFont->OpenFont();
+		  	  	  		if (openFont && openFont->File()->Uid() == aFileUid )
+		  	  	  			{
+		  	  	  			if ((*iFontAccess)[kk].iAccessCount > 0) 
+		  	  	  				return; // Outstanding reference found, so ignoring file removal request
+		  	  	  			}
+						}
+					} // Safe to proceed with removing file
+				// also check if there are outstanding references to any 
+				// table in that file.
+				if (iFontTableCache && iFontTableCache->HasOutstandingRefCountWithUid(aFileUid))
+				    {
+				    return; // outstanding reference to font table found.
+				    }
+				
+				// Safe to proceed with removing file
+				if (iOpenFontFileList[i]->DecRefCount())
+					{ // unload the font file
+					RemoveTypefacesFromSupportList(iOpenFontFileList[i]);
+					//linked fonts deleted from this destructor
+					delete iOpenFontFileList[i];
+					iOpenFontFileList.Delete(i);
+					}
+				return;
+				}
+			}
+
+		// Finds first fontstorefile with correct id
+		TInt index = FindBitmapFontFileIndexByUid(aFileUid);
+		if (index != KErrNotFound)  //  Checks fontstore file has been found
+			{
+			iFontStoreFileList[index]->iUsageCount--;
+			if (!iFontStoreFileList[index]->iUsageCount)
+				{
+				TInt tfcount = iTypefaceFontBitmapList.Count();
+				for (i=tfcount-1; i>=0; i--)
+					if (aFileUid == iTypefaceFontBitmapList[i].iFontBitmap->FontStoreFile()->iCollectionUid)
+						iTypefaceFontBitmapList.Delete(i);
+				count = iFontBitmapList.Count();
+				for (i=count-1; i>=0; i--)
+					{
+					
+					if (aFileUid==iFontBitmapList[i]->FontStoreFile()->iCollectionUid)
+						{
+						iFontBitmapList[i]->Release();
+						iFontBitmapList.Delete(i);
+						}  
+					}
+				count = iTypefaceList.Count();
+				for (i=count-1; i>=0; i--)	
+					{
+					TBool inlist=EFalse;  
+					tfcount = iTypefaceFontBitmapList.Count();
+					for (TInt j=0; j<tfcount; j++)
+						if (iTypefaceList[i] == iTypefaceFontBitmapList[j].iTypeface)
+							inlist = ETrue;
+					if (!inlist)
+						{
+						delete iTypefaceList[i];
+						iTypefaceList.Delete(i);
+						}
+					}
+				delete iFontStoreFileList[index];
+				iFontStoreFileList.Delete(index);
+				}
+			}
+		}
+	}
+
+/**
+@publishedAll
+*/
+EXPORT_C TInt CFontStore::GetNearestFontInTwips(CFont*& aFont, const TFontSpec& aFontSpec)
+	{
+	return GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInTwips() 
+yielding (virtually) the same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInTwips() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of twips, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@deprecated Use GetNearestFontToDesignHeightInTwips
+*/
+EXPORT_C TInt CFontStore::GetNearestFontInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec)
+	{
+	return GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
+	}
+
+/**
+@publishedAll
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInTwips(CFont*& aFont, const TFontSpec& aFontSpec)
+	{
+	TOpenFontSpec spec(aFontSpec);
+	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
+	return GetNearestFontToDesignHeightInPixels(aFont, spec);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+This new function replaces the deprecated @c GetNearestFontInTwips() yielding (virtually) the 
+same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInTwips() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of twips, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec)
+	{
+	TOpenFontSpec spec = aFontSpec;
+	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
+	return GetNearestFontToDesignHeightInPixels(aFont, spec);
+	}
+
+/**
+@publishedAll
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInTwips(CFont*& aFont, const TFontSpec& aFontSpec, TInt aMaxHeight)
+	{
+	TOpenFontSpec spec(aFontSpec);
+	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
+	return GetNearestFontToMaxHeightInPixels(aFont, spec, VerticalTwipsToPixels(aMaxHeight));
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+The font and bitmap server returns a pointer to the nearest matching font 
+from those available. Matches to max height of font - this does its best 
+to return a font that will fit within the maximum height specified (but 
+note that variations due to hinting algorithms may rarely result in this 
+height being exceeded by up to one pixel). Problems can also be 
+encountered with bitmap fonts where the typeface exists but doesn't have 
+a font small enough.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@param aMaxHeight The maximum height within which the font must fit. If maximum height
+is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
+if equals to 1 pixel. This overrides the height specified in aFontSpec.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec, TInt aMaxHeight)
+	{
+	TOpenFontSpec spec = aFontSpec;
+	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
+	return GetNearestFontToMaxHeightInPixels(aFont, spec, VerticalTwipsToPixels(aMaxHeight));
+	}
+
+
+/** Local utility method to compare two font specs; the higher the return value, the better the match.
+It is not clear how to reliably test for symbol fonts or language coverage because some
+TOpenFontSpecs are created from bitmap TFontSpecs that do not have this info
+*/
+TInt MatchFontSpecsInPixels(
+	const TOpenFontSpec&	aCandidateFontSpec,
+	const TOpenFontSpec&	aIdealFontSpec,
+	TInt					aCandidateMaxHeight,
+	TInt					aIdealMaxHeight)
+	{
+	// scores for matching (or similar) font attributes:
+	const TInt KFontMatchScoreForName = 10;
+	// favour fonts with heights closer together 
+	const TInt KFontMaxScoreForHeight = 10;
+	// A match on both italic-ness and presence of forward slant factor is worth 2 points.
+	const TInt KFontMatchScoreForExactItalicAndSlant = 2;
+	// A match between italic-ness in one font and presence of forward slant factor in the other is worth 1 point.
+	const TInt KFontSimilarScoreForItalicAndSlant = 1;
+	const TInt KFontMatchScoreForBold = 2;
+	const TInt KFontMatchScoreForBitmapType = 2;
+	// A match between outline or shadow effect in one font with other is worth 2 points. Its same as matching for bitmaptype.
+	const TInt KFontMatchScoreForOutlineOrShadow = 2;
+	// The monospaced/proportional status is rated higher at 3 because it has a major effect on the look and layout
+	const TInt KFontMatchScoreForMonoSpace = 3;
+	// Whether the font is serifed or not has a smaller effect on the look and layout so it is only rated at 1
+	const TInt KFontMatchScoreForSerif = 1;
+
+	TInt score = 0;
+
+	// Favour perfect name and height matches.	
+	if (0 == aCandidateFontSpec.Name().CompareF(aIdealFontSpec.Name()))
+		{
+		score += KFontMatchScoreForName;
+		}
+
+	// Check for max height if given, otherwise height in font spec
+	TInt height_diff = 0;
+	if (aCandidateMaxHeight && aIdealMaxHeight)
+		{
+		if (aIdealMaxHeight < aCandidateMaxHeight)
+			return 0;
+		height_diff = aIdealMaxHeight - aCandidateMaxHeight;
+		}
+	else
+ 		{
+		height_diff = aIdealFontSpec.Height() - aCandidateFontSpec.Height();
+		if (0 > height_diff)
+			height_diff = -height_diff;
+		}
+	score += KFontMaxScoreForHeight - height_diff;
+
+	if (aCandidateFontSpec.IsItalic() == aIdealFontSpec.IsItalic() &&
+		(0 < aCandidateFontSpec.SlantFactor()) == (0 < aIdealFontSpec.SlantFactor()))
+		{
+		score += KFontMatchScoreForExactItalicAndSlant;
+		}
+	else if ((aCandidateFontSpec.IsItalic() && 0 < aIdealFontSpec.SlantFactor()) ||
+			 (aIdealFontSpec.IsItalic() && 0 < aCandidateFontSpec.SlantFactor()))
+		{
+		score += KFontSimilarScoreForItalicAndSlant;
+		}
+
+	if (aCandidateFontSpec.IsBold() == aIdealFontSpec.IsBold())
+		{
+		score += KFontMatchScoreForBold;
+		}
+	
+	TUint effectsFlag = aIdealFontSpec.Effects() & aCandidateFontSpec.Effects();
+	TBool isShadowOutlineEffects = EFalse;
+
+	if(effectsFlag & FontEffect::EOutline)
+		{
+		score += KFontMatchScoreForOutlineOrShadow;
+		isShadowOutlineEffects = ETrue;
+		}
+	if(effectsFlag & FontEffect::EDropShadow)
+		{
+		score += KFontMatchScoreForOutlineOrShadow;
+		isShadowOutlineEffects = ETrue;
+		}
+		
+	//Match for bitmap glyph type only when effects are off.
+	//BitmapType in aIdealFontSpec will be set to EFourColourBlendGlyphBitmap by rasterizer only
+	//when any of the effects (outline/shadow) are on and if it supports outline and shadow fonts.
+	if(!isShadowOutlineEffects && (aCandidateFontSpec.BitmapType() == aIdealFontSpec.BitmapType()))
+		{
+		score += KFontMatchScoreForBitmapType;
+		}
+	if (aCandidateFontSpec.IsMonoWidth() == aIdealFontSpec.IsMonoWidth())
+		{
+		score += KFontMatchScoreForMonoSpace;
+		}
+	if (aCandidateFontSpec.IsSerif() == aIdealFontSpec.IsSerif())
+		{
+		score += KFontMatchScoreForSerif;
+		}
+
+	return score;
+	}
+
+
+/**
+Find and load the nearest Open Font by
+1. using aDesiredFontSpec to check if its already loaded,
+2. using aActualFontSpec to partially match	and create a new font.
+Partial match means typeface name must match, other attributes need not match.
+Font must fit vertically within the specified max height if given.
+
+@param aFont Output, is the returned font.
+@param aActualFontSpec Output, is used to represent the returned font and changed to twips. 
+@param aDesiredFontSpec Input, the desired font specification
+@param aMaxHeight Input, the maximum height in Pixels, or 0
+@post if any Open Fonts are available this will always return something
+*/
+void CFontStore::GetNearestOpenFontInPixelsL(
+	CFont*&					aFont,
+	TOpenFontSpec&			aActualFontSpec,
+	const TOpenFontSpec&	aDesiredFontSpec,
+	TInt					aMaxHeight)
+	{
+	// Set the baseline offset appropriately for superscript or subscript.
+	TAlgStyle algstyle;
+	algstyle.iBaselineOffsetInPixels = BaselineOffset(aActualFontSpec.Height(), aActualFontSpec.PrintPosition());
+
+	// Determine if an open font with a perfect match is already loaded.
+	if (IsFontLoaded(aFont, algstyle, aDesiredFontSpec, aMaxHeight))
+		{
+		aActualFontSpec = aDesiredFontSpec;
+		}
+	else
+		{ // If not, find the nearest match for aActualFontSpec.
+		COpenFont* nearestFont = NULL;
+
+		// fast search, if DO_LOADFONT_OPTIMIZATION is defined, search loaded font names for match
+		TInt errorName=GetNearestOpenFontInPixelsByFontName(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight);
+		TInt errorSimilar=KErrNone;
+
+		if (!nearestFont)
+			{
+			errorSimilar=GetNearestOpenFontInPixelsBySimilarity(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight);
+			}
+
+		// If an imperfect match was found, is it already loaded? If not, create a new CBitmapFont.
+		if (nearestFont)
+			{
+			//
+			// Results of everything above are stored in nearestFont, and aActualFontSpec
+			// First check if the not-exactly-matched font is already loaded
+			// aMaxHeight is 0 to prevent duplicate CBitmapFontObjects being created
+			//
+			if (IsFontLoaded(aFont, algstyle, aActualFontSpec, 0))
+				{
+				delete nearestFont;
+				}
+			else
+				{
+				// Set the specification of the nearest match in twips.
+				TOpenFontSpec openFontSpec(aActualFontSpec);
+				openFontSpec.SetHeight(VerticalPixelsToTwips(openFontSpec.Height()));
+				CleanupStack::PushL(nearestFont);
+				aFont = NewFontL(openFontSpec, algstyle, nearestFont);
+				CleanupStack::Pop(nearestFont);
+				}
+			}
+		else
+			{
+			User::LeaveIfError(errorSimilar);
+			User::LeaveIfError(errorName);
+			}
+		}
+	}
+
+
+/** Using the Desired Font Name try to find a matching font.
+
+@param aNearestOpenFont Output, nearest matching open font
+@param aActualFontSpec Output, is used to represent the returned font 
+@param aDesiredFontSpec Input, the desired font specification
+@param aMaxHeight Input, the maximum height in Pixels, or 0
+*/
+#if(DO_LOADFONT_OPTIMIZATION)
+TInt CFontStore::GetNearestOpenFontInPixelsByFontName(
+	COpenFont*&				aOpenFont,
+	TOpenFontSpec&			aActualFontSpec,
+	const TOpenFontSpec&	aDesiredFontSpec,
+	TInt					aMaxHeight)
+	{
+	TOpenFontSpec actualFontSpec;
+	COpenFont* nearestFont = NULL;
+
+	if (aMaxHeight == 0 && aDesiredFontSpec.Name().Length() > 0)	// check if it is a request for OpenFont
+		{
+		TPtrC requestedName = aDesiredFontSpec.Name();
+		// Typeface files may contain all those typefaces in a family, or may contain only some.
+		// The optimization first tries the ShortFullName of the typeface in case the typefaces are
+		// put into separate files.
+		
+		// First check FullName. The following assumes that there are never two COpenFontFiles in the 
+		// list with the same ShortFullName. So italic and bold flags are not checked.
+
+		const TInt openFontFileCount = iOpenFontFileList.Count();
+		TInt index;
+		TInt typicalError = KErrNone;
+		for (index = 0; index < openFontFileCount; index++)
+			{
+			COpenFontFile *pFile = iOpenFontFileList[index]; 
+			const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0);
+			
+			// Use short names. They are truncated to the same length as the request in TTypeface
+			if ((faceAttrib.ShortFullName().CompareF(requestedName)==0) &&
+				(faceAttrib.IsBold() == aActualFontSpec.IsBold()) &&
+				(faceAttrib.IsItalic() == aActualFontSpec.IsItalic()) )			
+				{
+				TInt error=pFile->GetNearestFontToDesignHeightInPixels(
+					iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
+					iKPixelHeightInTwips, nearestFont, actualFontSpec);				
+
+				// search has finished if a match was found
+				if (nearestFont)
+					{
+					// need to copy the actual to the value that is going to be used down below
+					// to make a new font
+					aOpenFont = nearestFont;
+					aActualFontSpec = actualFontSpec;
+					return KErrNone;
+					}
+				else
+					{
+					if (error)
+						{
+						typicalError=error;
+						}
+					}
+				}
+			}
+
+		// If the FullName match above has failed, then the request is being made by
+		// something other than a full name (assuming typeface is present).
+		// Although there may be more than one typeface in a file,
+		// It is not possible to conclude that ALL typefaces of the family are in one file.
+		// So to be safe, checks are made on italic and bold, possibly downgrading the optimization.
+		// Use short names. They are truncated to the same length as the request in TTypeface
+		for (index = 0; index < openFontFileCount; index++)
+			{
+			COpenFontFile *pFile = iOpenFontFileList[index]; 
+			const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0);
+
+			if(	(faceAttrib.ShortFamilyName().CompareF(requestedName) == 0) &&
+				(faceAttrib.IsItalic() == aDesiredFontSpec.IsItalic()) &&
+				(faceAttrib.IsBold() == aDesiredFontSpec.IsBold()) )	
+				{
+				TInt error=pFile->GetNearestFontToDesignHeightInPixels(
+					iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
+					iKPixelHeightInTwips, nearestFont, actualFontSpec);
+
+				// search has finished if a match was found
+				if (nearestFont)
+					{
+					// need to copy the actual to the value that is going to be used down below
+					// to make a new font
+					aOpenFont = nearestFont;
+					aActualFontSpec = actualFontSpec;
+					return KErrNone;
+					}
+				else
+					{
+					if (error)
+						{
+						typicalError=error;
+						}
+					}
+				}
+			}
+		// no match
+		return typicalError;
+		}
+	// not open request
+	return KErrNone;
+	}
+#else
+TInt CFontStore::GetNearestOpenFontInPixelsByFontName(
+	COpenFont*&				/* aOpenFont */,
+	TOpenFontSpec&			/* aActualFontSpec */,
+	const TOpenFontSpec&	/* aDesiredFontSpec */,
+	TInt					/* aMaxHeight*/)
+	{ // no match
+	return KErrNone;
+	}
+#endif
+
+
+/** Using the Desired Font Name try to find a matching font.
+
+@param aNearestOpenFont Output, nearest matching open font
+@param aActualFontSpec Output, is used to represent the returned font 
+@param aDesiredFontSpec Input, the desired font specification
+@param aMaxHeight Input, the maximum height in Pixels, or 0
+*/
+TInt CFontStore::GetNearestOpenFontInPixelsBySimilarity(
+	COpenFont*&				aNearestOpenFont,
+	TOpenFontSpec&			aActualFontSpec,
+	const TOpenFontSpec&	aDesiredFontSpec,
+	TInt					aMaxHeight)
+	{
+	const TInt openFontFileCount = iOpenFontFileList.Count();
+	TOpenFontSpec nearestFontSpec;
+	COpenFont* nearestFont = NULL;
+	TInt nearestMatch = 0;
+    TInt typicalError=KErrNone;
+	for (TInt index = 0; index < openFontFileCount; index++)
+		{
+		// ask font file for its best match, if any
+		COpenFont* candidateFont = NULL;
+		TOpenFontSpec actualFontSpec;
+		TInt lastError=KErrNone;
+		if (aMaxHeight)
+			{
+			lastError=iOpenFontFileList[index]->GetNearestFontToMaxHeightInPixels(
+				iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
+				iKPixelHeightInTwips, candidateFont, actualFontSpec, aMaxHeight);
+			}
+		else
+			{
+			lastError=iOpenFontFileList[index]->GetNearestFontToDesignHeightInPixels(
+				iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
+				iKPixelHeightInTwips, candidateFont, actualFontSpec);
+			}
+
+		// hold on to the best overall match
+		if (candidateFont)
+			{
+			const TInt candidateMatch = MatchFontSpecsInPixels(
+				actualFontSpec, aDesiredFontSpec, candidateFont->FontMaxHeight(), aMaxHeight);
+
+			if (NULL == nearestFont || candidateMatch > nearestMatch)
+				{
+				if (nearestFont)
+					{
+					delete nearestFont;
+					}
+				nearestFont = candidateFont;
+				nearestMatch = candidateMatch;
+				nearestFontSpec	= actualFontSpec;
+				}
+			else
+				{
+				// Font match is no better than the current nearestFont
+				//
+				// Note this object is newed in GetNearestFontInPixels each time 
+				// a matching font is found.
+				delete candidateFont;
+				}
+			}
+		else
+			{
+			if (lastError)
+				{
+				typicalError=lastError;
+				}
+			}
+		}
+
+	if (nearestFont != NULL)
+		{ // result
+		aNearestOpenFont = nearestFont;
+		aActualFontSpec = nearestFontSpec;
+		return KErrNone;
+		}
+	else
+		{
+		return typicalError;
+		}
+	}
+
+
+/**
+Get the nearest bitmap font to aFontSpec and place it in aFont. Font must 
+fit vertically inside specified maximum height if given. GetNearestTypeface is
+called which insists that there is at least one typeface. This function will always 
+succeed unless there is an out-of-memory error or other abnormal error. 
+Change aFontSpec to represent the returned font and change it to twips.
+*/
+void CFontStore::GetNearestBitmapFontInPixelsL(
+	CFont*&		aFont,
+	TFontSpec&	aFontSpec,
+	TInt		aMaxHeight)
+	{
+	aFontSpec.iTypeface = *GetNearestTypeface(aFontSpec.iTypeface);
+	TTypefaceFontBitmap tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight);
+	const TInt height = tffb.HeightInPixels();
+	if (aFontSpec.iFontStyle.PrintPosition() != EPrintPosNormal)
+		{
+		aFontSpec.iHeight = SuperSubHeight(height, aFontSpec.iFontStyle.PrintPosition());
+		tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight);
+		}
+	aFontSpec.iHeight = height;
+	TAlgStyle algstyle;
+	algstyle.SetIsBold(
+		EStrokeWeightBold == aFontSpec.iFontStyle.StrokeWeight() &&
+		EStrokeWeightNormal == tffb.iFontBitmap->StrokeWeight());
+	algstyle.SetIsItalic(
+		EPostureItalic == aFontSpec.iFontStyle.Posture() &&
+		EPostureUpright == tffb.iFontBitmap->Posture());
+	algstyle.SetIsMono(!aFontSpec.iTypeface.IsProportional() && tffb.iFontBitmap->IsProportional());
+	TInt widthfactor =
+		((tffb.iWidthFactor * tffb.iFontBitmap->FontStoreFile()->iKPixelAspectRatio * iKPixelWidthInTwips) + (500 * iKPixelHeightInTwips)) / (1000 * iKPixelHeightInTwips);
+	if (!widthfactor)
+		widthfactor = 1;
+	algstyle.SetWidthFactor(widthfactor);
+	algstyle.SetHeightFactor( tffb.iHeightFactor );
+	algstyle.iBaselineOffsetInPixels = BaselineOffset(height, aFontSpec.iFontStyle.PrintPosition());
+	if (IsFontLoaded(aFont, algstyle, aFontSpec, tffb.iFontBitmap->iUid))
+		return;
+	TFontSpec spec(aFontSpec);
+	spec.iHeight = VerticalPixelsToTwips(height);
+	spec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap);
+	aFont = NewFontL(spec, algstyle, tffb.iFontBitmap);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() 
+yielding (virtually) the same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of pixels, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@deprecated Use GetNearestFontToDesignHeightInPixels
+*/
+EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TFontSpec& aFontSpec)
+	{
+	return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() 
+yielding (virtually) the same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of pixels, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@deprecated Use GetNearestFontToDesignHeightInPixels
+*/
+EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec)
+	{
+	return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the 
+same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of pixels, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec)
+	{
+	TOpenFontSpec spec(aFontSpec);
+	return GetNearestFontToDesignHeightInPixels(aFont, spec);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the 
+same result. However clients are strongly encouraged to use the new
+@c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
+character within any given text string will fit within the given amount of pixels, whereas the design 
+height is an aesthetic unit decided by the font designer without strict physical meaning, which 
+may result in cropped characters.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec)
+	{
+	return GetNearestFontInPixels(aFont, aFontSpec, 0);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+The font and bitmap server returns a pointer to the nearest matching font 
+from those available. Matches to max height of font - this does its best 
+to return a font that will fit within the maximum height specified (but 
+note that variations due to hinting algorithms may rarely result in this 
+height being exceeded by up to one pixel). Problems can also be 
+encountered with bitmap fonts where the typeface exists but doesn't have 
+a font small enough.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@param aMaxHeight The maximum height within which the font must fit. If maximum height
+is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
+if equals to 1 pixel. This overrides the height specified in aFontSpec.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec, TInt aMaxHeight)
+	{
+	TOpenFontSpec spec(aFontSpec);
+	return GetNearestFontToMaxHeightInPixels(aFont, spec, aMaxHeight);
+	}
+
+/**
+Gets the font which is the nearest to the given font specification.
+
+The font and bitmap server returns a pointer to the nearest matching font 
+from those available. Matches to max height of font - this does its best 
+to return a font that will fit within the maximum height specified (but 
+note that variations due to hinting algorithms may rarely result in this 
+height being exceeded by up to one pixel). Problems can also be 
+encountered with bitmap fonts where the typeface exists but doesn't have 
+a font small enough.
+
+@param aFont On return, contains a pointer to the nearest font.
+@param aFontSpec The specification of the font to be matched.
+@param aMaxHeight The maximum height within which the font must fit. If maximum height
+is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
+if equals to 1 pixel. This overrides the height specified in aFontSpec.
+@return KErrNone if successful; a system-wide error code otherwise.
+@publishedAll
+@released
+*/
+EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec, TInt aMaxHeight)
+	{
+	if (KMaxFontHeightInPixels < aMaxHeight)
+		{
+		return KErrTooBig;
+		}
+	if (aMaxHeight > 0 && aMaxHeight < KMinFontHeightInPixels)
+		{
+		return KErrArgument;
+		}
+	return GetNearestFontInPixels(aFont, aFontSpec, aMaxHeight);
+	}
+
+TInt CFontStore::GetNearestFontInPixels(
+	CFont*&					aFont,
+	const TOpenFontSpec&	aDesiredFontSpec,
+	TInt					aMaxHeight)
+	{
+	aFont = NULL;
+
+	// Determine the ideal version of the font spec.
+	TOpenFontSpec originalFontSpec = aDesiredFontSpec;
+	originalFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips);
+	TOpenFontSpec desiredFontSpec = originalFontSpec;
+	if (EDefaultGlyphBitmap == desiredFontSpec.BitmapType())
+		{
+		desiredFontSpec.SetBitmapType(iDefaultBitmapType);
+		}
+	if (EPrintPosNormal != desiredFontSpec.PrintPosition())
+		{
+		desiredFontSpec.SetHeight(SuperSubHeight(desiredFontSpec.Height(), desiredFontSpec.PrintPosition()));
+		}
+	TOpenFontSpec actualOpenFontSpec = desiredFontSpec;
+
+	// Try to get an open font.
+	CFont* openFont = NULL;
+	TRAPD(error, GetNearestOpenFontInPixelsL(
+		openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
+
+	// Try to get a bitmap font - if getting open font failed or the match was not perfect.
+	CFont* bitmapFont = NULL;
+	TInt errorBitmap=KErrNone;
+	TOpenFontSpec actualBitmapFontSpec;
+	if (error || !openFont || actualOpenFontSpec != desiredFontSpec)
+		{
+		TFontSpec f;
+		originalFontSpec.GetTFontSpec(f);
+		if (iTypefaceList.Count() > 0)
+			{
+			TRAP(errorBitmap, GetNearestBitmapFontInPixelsL(bitmapFont, f, aMaxHeight));
+			}
+		actualBitmapFontSpec = f;
+		actualBitmapFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips);
+		}
+
+	//If both attempts fail then there is nothing more we can do...
+	if (!openFont && !bitmapFont)
+		{
+		//If an error caused no fonts to be returned then forward the error
+		if (error)
+			return error;
+		if (errorBitmap)
+			return errorBitmap;
+		}
+	// Choose the best candidate
+	if (NULL == openFont && NULL == bitmapFont)
+		{
+		// Try to get an open font again - unnamed font.
+		// See COpenFontFile::GetNearestFontHelper - how it works with unnamed fonts.
+		actualOpenFontSpec.SetName(KNullDesC);
+		TRAP(error, GetNearestOpenFontInPixelsL(
+			openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
+		if (KErrNone == error && openFont)
+			{
+			aFont = openFont;
+			return KErrNone;
+			}
+		else
+			{
+			__ASSERT_DEBUG(false, Panic(EFntNoFontFound));
+			return KErrGeneral;
+			}
+		}
+	else if (NULL == openFont)
+		{
+		if (actualBitmapFontSpec.Name().CompareF(desiredFontSpec.Name()) != 0)
+			{
+			// Try to get the nearest open font - because no exact bitmap font match for typeface name
+			actualOpenFontSpec.SetName(KNullDesC);
+			desiredFontSpec.SetName(KNullDesC);
+			TRAPD(errorOpen, GetNearestOpenFontInPixelsL(
+				openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
+			if (KErrNone == errorOpen && openFont)
+				{
+				aFont = openFont;
+				ReleaseFont(bitmapFont);
+				}
+			}
+		if (aFont == NULL)
+			{
+			aFont = bitmapFont;
+			}
+		}
+	else if (NULL == bitmapFont)
+		{
+		aFont = openFont;
+		}
+
+	if (aFont == NULL)
+		{
+		// Pick the closest match; for backward compatibility prefer a bitmap font if there is a dead heat.
+		const TInt open_match = MatchFontSpecsInPixels(
+			actualOpenFontSpec, desiredFontSpec, openFont->FontMaxHeight(), aMaxHeight);
+		const TInt bitmap_match = MatchFontSpecsInPixels(
+			actualBitmapFontSpec, desiredFontSpec, bitmapFont->FontMaxHeight(), aMaxHeight);
+		if (open_match > bitmap_match)
+			{
+			aFont = openFont;
+			ReleaseFont(bitmapFont);
+			}
+		else
+			{
+			aFont = bitmapFont;
+			ReleaseFont(openFont);
+			}
+		}
+	return KErrNone;
+	}
+
+/** Gets a bitmap font using the given font UID and algorithmic style.
+
+Tries to find a bitmap font in the font store with the given UID. If successful, 
+the given algorithmic style is applied to the font and this font (which may 
+be a suitable one already existing in the store, or may be a newly generated 
+font) is stored in aFont. If unsuccessful then no font is stored in aFont.
+
+@param aFont On return, a device-dependent font.
+@param aUid A bitmap font UID.
+@param aAlgStyle An algorithmic style to apply to the font.
+@return KErrNone if the font is found, KErrNotFound if the font is not found, 
+or another system-wide error code. */
+EXPORT_C TInt CFontStore::GetFontById(
+	CFont*&				aFont,
+	TUid				aUid,
+	const TAlgStyle&	aAlgStyle)
+	{
+	aFont = NULL;
+	CFontBitmap* fontbitmap = GetFontBitmapById(aUid);
+	if (!fontbitmap)
+		{
+		return KErrNotFound;
+		}
+
+	const TInt height = fontbitmap->iCellHeightInPixels * aAlgStyle.HeightFactor();
+	TFontSpec fontspec;
+	fontspec.iHeight=height;	//Otherwise IsFontLoaded() compares with zero height!!!
+	fontspec.iTypeface.SetIsProportional(!aAlgStyle.IsMono() && fontbitmap->IsProportional());
+	if (aAlgStyle.IsBold() || EStrokeWeightBold == fontbitmap->StrokeWeight())
+		{
+		fontspec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+		}
+	if (aAlgStyle.IsItalic() || EPostureItalic == fontbitmap->Posture())
+		{
+		fontspec.iFontStyle.SetPosture(EPostureItalic);
+		}
+	if (IsFontLoaded(aFont, aAlgStyle, fontspec, fontbitmap->iUid))
+		{
+		return KErrNone;
+		}
+
+	// Fill in the typeface by finding a typeface with the same font bitmap.
+	fontspec.iHeight = VerticalPixelsToTwips(height);
+	const TInt n = iTypefaceFontBitmapList.Count();
+	for (TInt i = 0; i < n; i++)
+		{
+		if (iTypefaceFontBitmapList[i].iFontBitmap == fontbitmap)
+			{
+			fontspec.iTypeface = *iTypefaceFontBitmapList[i].iTypeface;
+			break;
+			}
+		}
+	TRAPD(ret, aFont = NewFontL(fontspec, aAlgStyle, fontbitmap));
+	return ret;
+	}
+
+/** Gets the number of typefaces held in the font store.
+
+Note that this includes both open font typefaces and non-scalable typefaces.
+
+@return The number of supported typefaces. */
+EXPORT_C TInt CFontStore::NumTypefaces() const
+	{
+	return iTypefaceList.Count() + iOpenFontTypefaceSupportList.Count();
+	}
+
+/** Gets a typeface support object for the typeface in the font store represented 
+by the given index.
+
+Returns benignly with an empty TTypefaceSupport if the index is too high; 
+this can happen if another process removes a typeface after the first process 
+has already got the number of typefaces. However, if the aTypefaceIndex<0 
+the function panics with EFntTypefaceIndexOutOfRange.
+
+@param aTypefaceSupport On return, a typeface support object.
+@param aTypefaceIndex An index number representing a typeface, which is valid 
+if in the range 0 to (NumTypefaces() - 1). */
+EXPORT_C void CFontStore::TypefaceSupport(TTypefaceSupport &aTypefaceSupport,TInt aTypefaceIndex) const
+	{
+	if (aTypefaceIndex < 0)
+		Panic(EFntTypefaceIndexOutOfRange);
+
+	/*
+	Return benignly with an empty TTypefaceSupport if the index is too high; this can happen if another
+	process removes a font after the first process has already got the number of typefaces.
+	*/
+	int typefaces = NumTypefaces();
+	if (aTypefaceIndex >= typefaces)
+		{
+		aTypefaceSupport = TTypefaceSupport();
+		return;
+		}
+
+	//now return Typeface Support for Open Fonts
+	if (aTypefaceIndex >= iTypefaceList.Count())
+		{
+		// copy Open Font typeface details
+		aTypefaceSupport = *iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()]->TypefaceSupport();
+		return;
+		}
+
+	__ASSERT_DEBUG((aTypefaceIndex >= 0) && (aTypefaceIndex < iTypefaceList.Count()),Panic(EFntTypefaceIndexOutOfRange));
+	TTypeface* typeface = iTypefaceList[aTypefaceIndex];
+	aTypefaceSupport.iTypeface = *typeface;
+	TInt count = iTypefaceFontBitmapList.Count();
+	TInt i;
+	for(i = 0; i < count && iTypefaceFontBitmapList[i].iTypeface != typeface; i++)
+		{  // Finds first fontbitmap with correct typeface
+		}
+	aTypefaceSupport.iMinHeightInTwips = VerticalPixelsToTwips(iTypefaceFontBitmapList[i].HeightInPixels()); 
+	aTypefaceSupport.iNumHeights=0;
+	TInt height=0;
+	for(; (i<count) && (typeface == iTypefaceFontBitmapList[i].iTypeface); i++)
+		if (height != iTypefaceFontBitmapList[i].HeightInPixels())
+			{
+			height = iTypefaceFontBitmapList[i].HeightInPixels();
+			aTypefaceSupport.iNumHeights++;
+			}
+	aTypefaceSupport.iMaxHeightInTwips=VerticalPixelsToTwips(height);
+	aTypefaceSupport.iIsScalable = EFalse;
+	}
+
+/** Returns a font height, in twips, for a certain typeface and height index.
+
+The font height is a height allowed for the typeface represented by aTypefaceIndex. 
+The height returned increases with aHeightIndex.
+
+If aTypefaceIndex<0 the function panics with EFntTypefaceIndexOutOfRange. 
+If aTypefaceIndex is greater than the number of typefaces or aHeightIndex<0 
+then the function returns 0. If aHeightIndex is greater than the number of 
+heights then the function returns the biggest height. 
+
+@param aTypefaceIndex An index number representing a typeface, which is valid 
+in the range 0 to (NumTypefaces() - 1).
+@param aHeightIndex A font height index number, which is valid in the range 
+0 to (TTypefaceSupport::iNumHeights - 1). Note that the typeface support object 
+for the typeface can be got using TypefaceSupport(). 
+@return The height of a font, in twips.
+@see TypefaceSupport()
+*/
+EXPORT_C TInt CFontStore::FontHeightInTwips(TInt aTypefaceIndex,TInt aHeightIndex) const
+	{
+	if (aTypefaceIndex >= iTypefaceList.Count())
+		{
+		// it's an Open Font managed by a COpenFontFile
+		if (aTypefaceIndex >= NumTypefaces() || aHeightIndex < 0)
+			return 0;
+		
+		const CTypefaceSupportInfo* supportInfo = iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()];
+		TInt i = Min( supportInfo->NearestPointSizeIndex() + aHeightIndex, 
+					  KOpenFontSizeArrayCount - 1);
+
+		return gOpenFontSizeInTwipsArray[i];
+		}
+	else
+		{
+		return VerticalPixelsToTwips(FontHeightInPixels(aTypefaceIndex,aHeightIndex));
+		}
+	}
+
+/** Returns a font height, in pixels, for a certain typeface and height index.
+
+The font height is a height allowed for the typeface represented by aTypefaceIndex. 
+The height returned increases with aHeightIndex.
+
+If aTypefaceIndex<0 the function panics with EFntTypefaceIndexOutOfRange. 
+If aTypefaceIndex is greater than the number of typefaces or aHeightIndex<0 
+then the function returns 0. If aHeightIndex is greater than the number of 
+heights then the function returns the biggest height. 
+
+@param aTypefaceIndex An index number representing a typeface, which is valid 
+in the range 0 to (NumTypefaces() - 1).
+@param aHeightIndex A font height index number, which is valid in the range 
+0 to (TTypefaceSupport::iNumHeights - 1). Note that the typeface support object 
+for the typeface can be got using TypefaceSupport(). 
+@return The height of a font, in pixels.
+@see TypefaceSupport()
+*/
+EXPORT_C TInt CFontStore::FontHeightInPixels(TInt aTypefaceIndex,TInt aHeightIndex) const
+	{
+
+	if (aTypefaceIndex >= iTypefaceList.Count())	// it's an Open Font managed by a COpenFontFile
+		return VerticalTwipsToPixels(FontHeightInTwips(aTypefaceIndex,aHeightIndex));
+	else
+		{
+		if (aTypefaceIndex < 0)
+			Panic(EFntTypefaceIndexOutOfRange);
+		TTypeface* typeface = iTypefaceList[aTypefaceIndex];
+		TInt count = iTypefaceFontBitmapList.Count();
+		TInt i;
+		for(i=0; (i < count) && (iTypefaceFontBitmapList[i].iTypeface != typeface); i++)
+			{  // Finds first fontbitmap with correct typeface
+			}
+		TInt height=0,h=0;
+		for(; (i<count) && (iTypefaceFontBitmapList[i].iTypeface==typeface)
+						&& (h<=aHeightIndex); i++)
+			if (height != iTypefaceFontBitmapList[i].HeightInPixels())
+				{
+				height = iTypefaceFontBitmapList[i].HeightInPixels();
+				h++;
+				}
+		return height;
+		}
+	}
+
+void CFontStore::InternalizeFontStoreFileL(CFontStoreFile* aFontStoreFile, TInt aFontVersion)
+	{
+	RStoreReadStream stream;
+	stream.OpenLC(*aFontStoreFile->iFileStore,aFontStoreFile->iDataStreamId);
+	TInt i, size = stream.ReadInt32L();
+	TInt opsPerformed=0;
+	for (i=0; i<size; i++)
+		{
+		// font is placed in shared heap
+		CFontBitmap* fontbitmap=(CFontBitmap*)iHeap->AllocL(sizeof(CFontBitmap));
+		new(fontbitmap) CFontBitmap(iHeap,aFontStoreFile);
+		CleanupReleasePushL(*fontbitmap);
+		fontbitmap->InternalizeL(stream, aFontVersion);
+		if (GetFontBitmapById(fontbitmap->iUid))
+			{
+			fontbitmap->Release();
+			}
+		else
+			{
+			iFontBitmapList.AppendL(fontbitmap);
+			opsPerformed++;
+			}
+		// safely internalized & owned
+		CleanupStack::Pop(fontbitmap);
+		}
+	size = stream.ReadInt32L();
+	for (i=0; i<size; i++)
+		{
+		TTypeface* typeface=new(ELeave) TTypeface;
+		CleanupStack::PushL(typeface);
+		typeface->InternalizeL(stream);
+		TInt index,count=iTypefaceList.Count(); 		
+		for (index=0; (index<count) && typeface->iName.CompareF(iTypefaceList[index]->iName); index++)
+			{  // Looks to see if typeface is already in list
+			}
+		if (index == count) // If typeface not in list
+			{
+			iTypefaceList.AppendL(typeface);
+			index = iTypefaceList.Count()-1;
+			opsPerformed++;
+			CleanupStack::Pop();  // typeface
+			}
+		else
+			{
+			CleanupStack::Pop();  // typeface
+			delete typeface;
+			typeface=iTypefaceList[index];
+			}
+		TInt num = stream.ReadInt32L();
+		for (TInt j=0; j<num; j++)
+			{
+			TUid uid;
+			stream >> uid;
+ 			CFontBitmap* fontbitmap = GetFontBitmapById(uid);
+			__ASSERT_DEBUG(fontbitmap,Panic(EFntFontBitmapNotLoaded));
+#ifndef _DEBUG
+			User::LeaveIfNull(fontbitmap);
+#endif			
+			TTypefaceFontBitmap typefacefontbitmap(iTypefaceList[index],fontbitmap);
+			typefacefontbitmap.iWidthFactor=stream.ReadInt8L();
+			typefacefontbitmap.iHeightFactor=stream.ReadInt8L();
+			count=iTypefaceFontBitmapList.Count();
+			TInt pos;
+			if (index == count)
+				{
+				pos=count;
+				}
+			else
+				{
+				
+				for (pos=0; (pos<count) && (iTypefaceFontBitmapList[pos].iTypeface != typeface); pos++)
+					{  // Finds position of first fontbitmap with same typeface
+					}
+				for (; (pos<count) && (iTypefaceFontBitmapList[pos].iTypeface == typeface)
+				                   && (iTypefaceFontBitmapList[pos].HeightInPixels()<typefacefontbitmap.HeightInPixels()); pos++)
+					{
+					}
+				for (; (pos<count) &&  (iTypefaceFontBitmapList[pos].iTypeface == typeface)
+				                   &&  (iTypefaceFontBitmapList[pos].HeightInPixels()==typefacefontbitmap.HeightInPixels())
+				                   &&  (iTypefaceFontBitmapList[pos].iFontBitmap->Posture()<fontbitmap->Posture()); pos++)
+	       			{  // Finds position after fontbitmap with same height
+					}
+				for (; (pos<count) &&  (iTypefaceFontBitmapList[pos].iTypeface == typeface)
+				                   &&  (iTypefaceFontBitmapList[pos].HeightInPixels()==typefacefontbitmap.HeightInPixels())
+				                   &&  (iTypefaceFontBitmapList[pos].iFontBitmap->StrokeWeight()<fontbitmap->StrokeWeight()); pos++)
+	       			{  // Finds position after fontbitmap with same height
+					}
+				}
+			TTypefaceFontBitmap* tfbAtPos=(pos==count)
+											?	NULL
+											:	&iTypefaceFontBitmapList[pos];
+			if (	!tfbAtPos	
+				||	tfbAtPos->iTypeface!=typeface
+				||	tfbAtPos->HeightInPixels()!=typefacefontbitmap.HeightInPixels()
+				||	tfbAtPos->iFontBitmap->Posture()!=fontbitmap->Posture()
+				||	tfbAtPos->iFontBitmap->StrokeWeight()!=fontbitmap->StrokeWeight()
+				||	tfbAtPos->iWidthFactor!=typefacefontbitmap.iWidthFactor	
+				||	tfbAtPos->iHeightFactor!=typefacefontbitmap.iHeightFactor	
+				)
+				{
+				iTypefaceFontBitmapList.InsertL(pos,typefacefontbitmap);
+				opsPerformed++;
+				}
+			}
+		}
+		CleanupStack::PopAndDestroy(); // stream
+		if (!opsPerformed)
+			User::Leave(KErrAlreadyExists);
+	}
+
+TTypeface* CFontStore::GetNearestTypeface(const TTypeface& aTypeface) const
+	{
+	TInt index,count = iTypefaceList.Count();
+	__ASSERT_DEBUG(count>0,Panic(EFntNoTypefaces));
+	for (index=0; (index<count) && aTypeface.iName.CompareF(iTypefaceList[index]->iName); index++)	  
+		{ // tries matching	typeface name
+		}
+	if (index==count)
+		{
+		if (!aTypeface.IsSymbol())
+			{
+			for (index=0; (index<count) && ((iTypefaceList[index]->IsSymbol()) ||
+			                                (aTypeface.IsProportional() != iTypefaceList[index]->IsProportional()) || 
+			                                (aTypeface.IsSerif() != iTypefaceList[index]->IsSerif())); index++)	  
+				{ // tries matching	typeface flags
+				}
+			if (index==count)
+				for (index=0; (index<count) && ((iTypefaceList[index]->IsSymbol()) ||
+				                                (aTypeface.IsProportional()!=iTypefaceList[index]->IsProportional())); index++)	  
+					{ // tries matching	typeface flags
+					}
+			if (index==count)
+				for (index=0; (index<count) && iTypefaceList[index]->IsSymbol(); index++)	  
+					{ // finds first non-symbol typeface
+					}
+			}
+		else
+			{
+			for (index=0; (index<count) && (!iTypefaceList[index]->IsSymbol()); index++)	  
+				{ // finds first symbol typeface
+				}
+			}
+		}
+
+	if (index==count)
+		index=0;
+	return iTypefaceList[index];
+	}
+
+TTypefaceFontBitmap CFontStore::GetNearestTypefaceFontBitmap(const TFontSpec& aFontSpecInPixels, TInt aMaxHeight)
+	{
+	TTypefaceFontBitmap typefacefontbitmap;
+	TInt count = iTypefaceFontBitmapList.Count();
+	__ASSERT_DEBUG(count > 0, Panic(EFntNoTypefaceFontBitmaps));
+	TInt i;
+	TInt j;
+	// Assumes there is at least one fontbitmap per typeface
+	for (i = 0; (i < count) && !(aFontSpecInPixels.iTypeface == *iTypefaceFontBitmapList[i].iTypeface); i++)
+		{  // Finds first fontbitmap with correct typeface
+		}
+	__ASSERT_DEBUG(i < count, Panic(EFntTypefaceHasNoFontBitmaps));
+	TTypeface* typeface = iTypefaceFontBitmapList[i].iTypeface;
+	TInt height = 0;
+	if (aMaxHeight > 0)
+		{ // need to check against max height
+		for (j = i; (j < count) && (iTypefaceFontBitmapList[ j ].iTypeface == typeface) 
+								&& (iTypefaceFontBitmapList[j].iFontBitmap->FontMaxHeight() <= aMaxHeight); j++)
+			{
+			if (iTypefaceFontBitmapList[j].HeightInPixels() != height)
+				{
+				height = iTypefaceFontBitmapList[j].HeightInPixels();
+				i = j;
+				}
+			}
+		}
+	else
+		{ // just check against height
+		for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface)
+								&& (iTypefaceFontBitmapList[j].HeightInPixels() <= aFontSpecInPixels.iHeight); j++)
+			{
+			if (iTypefaceFontBitmapList[j].HeightInPixels() != height)
+				{
+				height = iTypefaceFontBitmapList[j].HeightInPixels();
+				i = j;
+				}
+			}
+		}
+	for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface)
+							&& (iTypefaceFontBitmapList[j].HeightInPixels() == height); j++) 
+		{  // Finds position after fontbitmap correct posture
+		if ((iTypefaceFontBitmapList[j].iFontBitmap->Posture() <= aFontSpecInPixels.iFontStyle.Posture()) &&
+			(iTypefaceFontBitmapList[j].iFontBitmap->StrokeWeight() <= aFontSpecInPixels.iFontStyle.StrokeWeight()))
+			i = j;
+		}
+	typefacefontbitmap = iTypefaceFontBitmapList[i];		
+	return typefacefontbitmap;
+	}
+
+CFontBitmap* CFontStore::GetFontBitmapById(TUid aUid)
+	{
+	CFontBitmap* fontbitmap = NULL;
+	TInt i, count = iFontBitmapList.Count();
+	for (i = 0; (i < count) && (aUid != iFontBitmapList[i]->iUid); i++)
+		{ // finds matching font bitmap
+		}
+	if (i<count) // bitmap found
+		fontbitmap = iFontBitmapList[i];
+	return fontbitmap;				
+	}
+
+/** The method uses the fontspec and algorithmic style only.
+The Uid is not used for Open Fonts. They all have a Uid of 0.
+*/
+TBool CFontStore::IsFontLoaded(
+	CFont*&					aFont,
+	const TAlgStyle&		aAlgStyle,
+	const TOpenFontSpec&	aFontSpecInPixels,
+	TInt					aMaxHeight) const
+	{
+	TFontSpec fontSpec;
+	aFontSpecInPixels.GetTFontSpec(fontSpec);
+	return IsFontLoaded(aFont, aAlgStyle, fontSpec, TUid::Uid(0), aMaxHeight);
+	}
+
+//stub functions to help optimise IsFontLoaded.
+//These shims are more efficient than a pointer-to-member.
+static TInt GetHeightShimMaxHeight(CFont* aFont)	{	return	aFont->FontMaxHeight();		}
+static TInt GetHeightShimHeightPixels(CFont* aFont)	{	return	aFont->HeightInPixels();	}
+
+/**
+Font spec comparison is based on
+1. Max height if its given, otherwise design height
+2. All other attributes in TFontSpec
+
+@see CFbsTypefaceStore::IsFontLoaded
+@see CPdrTypefaceStore::IsFontLoaded
+*/
+TBool CFontStore::IsFontLoaded(
+	CFont*&				aFont,
+	const TAlgStyle&	aAlgStyle,
+	const TFontSpec&	aFontSpecInPixels,
+	TUid				aUid,
+	TInt				aMaxHeight) const
+	{	//It is not worth copying iFontAccess to frame as it doesn't get register optimised.
+	const TInt count = iFontAccess->Count();
+	const TInt reqHeight =  aMaxHeight ? aMaxHeight : aFontSpecInPixels.iHeight;
+	TInt (*heightFn)(CFont*) = aMaxHeight ? GetHeightShimMaxHeight : GetHeightShimHeightPixels;
+	for (TInt i = 0; i < count; i++)
+		{
+		CBitmapFont* bitmapFont = reinterpret_cast<CBitmapFont*>((*iFontAccess)[i].iFont);
+		if (bitmapFont->Uid() != aUid ||
+			bitmapFont->iAlgStyle != aAlgStyle	||
+			heightFn(bitmapFont) != reqHeight
+			)
+			{
+			continue;
+			}
+		TFontSpec fontSpec = bitmapFont->FontSpecInTwips();
+		if (	fontSpec.iFontStyle == aFontSpecInPixels.iFontStyle &&
+				fontSpec.iTypeface.iName == aFontSpecInPixels.iTypeface.iName
+			) 
+			{
+			(*iFontAccess)[i].iAccessCount++;
+			aFont = static_cast<CFont*>(bitmapFont);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+CBitmapFont* CFontStore::NewFontL(
+	const TFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&	aAlgStyle,
+	CFontBitmap*		aFontBitmap)
+	{
+	CBitmapFont* f = CBitmapFont::NewL(iHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap);
+	CleanupStack::PushL(f);
+	AddFontL(f);
+	CleanupStack::Pop();
+	f->SetUniqueFontId(++iUniqueFontIdCount);
+	return f;
+	}
+
+CBitmapFont* CFontStore::NewFontL(
+	const TOpenFontSpec&	aFontSpecInTwips,
+	const TAlgStyle&		aAlgStyle,
+	COpenFont*				aOpenFont)
+	{
+	TFontSpec spec;
+	aFontSpecInTwips.GetTFontSpec(spec);
+	CBitmapFont* f = CBitmapFont::NewL(iHeap, spec, aAlgStyle, aOpenFont);
+	CleanupStack::PushL(f);
+	AddFontL(f);
+	CleanupStack::Pop();
+	f->SetUniqueFontId(++iUniqueFontIdCount);
+	return f;
+	}
+
+// This function is biased towards rounding up
+// The cutoff is effectively at one-third of a pixel
+// This is to match VerticalTwipsToPixels(...)
+TInt CFontStore::VerticalPixelsToTwips(TInt aPixelHeight) const
+	{
+	return ((aPixelHeight * iKPixelHeightInTwips) + 667) / 1000; // Rounds up above one-third of a pixel
+	}
+
+// This function is biased towards rounding down
+// The cutoff is effectively at two-thirds of a twip
+// This is to support the legacy system of rounding down
+// but with a sanity-check cutoff to round up past two-thirds
+TInt CFontStore::VerticalTwipsToPixels(TInt aTwipsHeight) const
+	{
+	__ASSERT_DEBUG(iKPixelHeightInTwips,Panic(EFntKPixelHeightInTwipsZero));
+	return ((aTwipsHeight * 1000) + (iKPixelHeightInTwips / 3)) / iKPixelHeightInTwips;  // Rounds down below two-thirds of a twip
+	}
+
+/** Installs and takes ownership of an Open Font rasterizer.
+
+@param aRasterizer A pointer to an Open Font rasterizer. */
+EXPORT_C void CFontStore::InstallRasterizerL(COpenFontRasterizer* aRasterizer)
+	{
+	iOpenFontRasterizerList.AppendL(aRasterizer);
+	}
+	
+/** Install and takes ownership of the shaper
+
+@param aShaperFactory A pointer to a shaper factory. */
+EXPORT_C void CFontStore::InstallShaperFactoryL(CShaperFactory* aShaperFactory)
+	{
+	iShaperFactoryList.AppendL(aShaperFactory);
+	}
+
+/** Deletes the glyph cache belonging to a particular client. 
+
+Called by ~CFbClient().
+
+@param aSessionHandle A session handle. */
+EXPORT_C void CFontStore::DeleteSessionCache(TInt aSessionHandle)
+	{
+	iOpenFontSessionCacheList->DeleteCache(iHeap,aSessionHandle);
+	}
+
+const CArrayPtrFlat<CShaperFactory>* CFontStore::ShaperFactoryList() const
+	{
+	return &iShaperFactoryList;
+	}
+
+/** Returns the list of session caches owned by the COpenFonts
+@internalComponent */
+COpenFontSessionCacheList* CFontStore::GetSessionCacheList()
+	{
+	return iOpenFontSessionCacheList;
+	}
+	
+/** Returns the total cache memory used by all the COpenFonts in the system 
+ 	@return Total cache memory usage
+	@internalComponent 
+*/	
+TInt CFontStore::GetShaperCacheMemUsage()
+	{
+	return iOpenFontShaperCacheMemUsage;
+	}
+	
+/** Updates the total cache memory used by all the COpenFonts in the system
+ 	@param aUsage New value of total cache memory usage
+	@internalComponent
+*/	
+void CFontStore::SetShaperCacheMemUsage(TInt aUsage)
+	{
+	iOpenFontShaperCacheMemUsage = aUsage;
+	}
+	
+/** Returns the list of COpenFontFiles owned by the CFontStore object
+	@internalComponent
+*/	
+CArrayPtrFlat<COpenFontFile>* CFontStore::GetOpenFontFileList()
+	{
+	return &iOpenFontFileList;
+	}
+
+void CFontStore::IncNumShaperCaches()
+	{
+	iNumberOfShaperCaches++;
+	}
+	
+void CFontStore::DecNumShaperCaches()
+	{
+	iNumberOfShaperCaches--;
+	}
+
+TInt CFontStore::GetNumShaperCaches()
+	{
+	return iNumberOfShaperCaches;
+	}
+
+
+/** Adds the typeface( of the currently added openfont file from the store) to Open Font System typefaces Supported List
+ignoring duplicate family names.
+1. Prior to adding the entry into the typefaceList, it is searched whether already exists or not
+2. If it is found only its reference count is incremented.
+3. If it is not found then its reference count is set to 1 and added that entry into the typefacelist.
+4. If 0 typefaces are added then KErrAlreadyExists is returned causing the new font to be unloaded.
+@return KErrNone is successful, otherwise a system wide error code
+@internalComponent
+*/
+TInt CFontStore::AddTypefacesToSupportList(COpenFontFile* aOpenFontFile)
+	{
+	TInt faceCount = aOpenFontFile->FaceCount();
+	CTypefaceSupportInfo* typefaceFamily = NULL;
+	TInt error = KErrNone;
+	TBool facesAdded=0;
+	// go through all fonts, stop early if an error
+	for (TInt faceIndex = 0; (faceIndex < faceCount) && (error == KErrNone); ++faceIndex)
+		{
+		//Preparing the Supported Typeface Entry
+		if (typefaceFamily == NULL)
+			{ // need a new typeface object
+			typefaceFamily = new CTypefaceSupportInfo();
+			if (typefaceFamily == NULL)
+				{ // failed
+				error = KErrNoMemory;
+				break;
+				}
+			}
+
+		// initialise for next type face
+		const TOpenFontFaceAttrib& faceAttrib = aOpenFontFile->FaceAttrib(faceIndex);
+		typefaceFamily->SetTypefaceInfo(faceAttrib, VerticalPixelsToTwips(faceAttrib.MinSizeInPixels()));
+
+		TInt fontPos = -1;	// an invalid index
+		TInt findError = iOpenFontTypefaceSupportList.FindInOrder(typefaceFamily, fontPos, CTypefaceSupportInfo::CompareFontNames);
+ 
+		// new font family?
+		if (findError == KErrNotFound)
+			{
+			// back reference to the font file
+			error = typefaceFamily->AddFontFilePtr(aOpenFontFile);
+			if (error == KErrNone)
+				{ // transfer ownership
+				error = iOpenFontTypefaceSupportList.Insert(typefaceFamily, fontPos);
+				if (error == KErrNone)
+					{
+					typefaceFamily = NULL;
+					facesAdded++;					
+					}
+				}
+			}
+		else
+			{
+			// back reference to the new font file (allowed to fail with KErrAlreadyExists)
+			TInt addError = iOpenFontTypefaceSupportList[fontPos]->AddUniqueFontFilePtr(aOpenFontFile,faceAttrib);
+			if (addError==KErrNone)
+				{
+				facesAdded++;
+				}
+			else if (addError == KErrInUse )
+				{
+				//remove typeface from loaded font file????
+				}
+			else if (addError != KErrAlreadyExists )
+				{
+				error = addError;
+				}
+			//else KErrAlreadyExists because loaded by a lower-indexed face in this font file, so faces won't be zero.
+			}
+		}
+
+	if (typefaceFamily != NULL)
+		{
+		delete typefaceFamily;
+		}
+	if (facesAdded==0 && error==KErrNone)
+		{
+			error= KErrAlreadyExists;
+		}
+#ifdef _DEBUG
+	// check that array is in order
+	const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count();
+	for (TInt fontPos = 0; fontPos < countTypefaceFamilies - 1; ++fontPos)
+		{
+		TInt cmp = CTypefaceSupportInfo::CompareFontNames(*iOpenFontTypefaceSupportList[fontPos], *iOpenFontTypefaceSupportList[fontPos+1]);
+		ASSERT(cmp < 0);
+		}
+#endif
+
+	return error;
+	}
+
+
+/** Removes the typefaces from the Support List corresponding to the fontfile removed from
+	the fontstore
+This is done by 
+1. Searching in the typefacesupportList for pointer references to the font file.
+2. If the file is referenced by the typeface family remove the reference.
+3. If typeface family no has any implementations remove the family
+@internalComponent
+*/
+void CFontStore::RemoveTypefacesFromSupportList(COpenFontFile* aOpenFontFile)
+	{
+	const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count();
+
+	// search typeface families
+	for (TInt fontPos = countTypefaceFamilies - 1; fontPos >= 0; --fontPos)
+		{
+		CTypefaceSupportInfo* fontInfo = iOpenFontTypefaceSupportList[fontPos];
+
+		// look for back pointer to this Font File
+		TInt fontFileIndex = fontInfo->FindFontFilePtr(aOpenFontFile);
+
+		if (fontFileIndex > KErrNotFound)
+			{ // remove pointer
+			if (fontInfo->RemoveFontFilePtr(fontFileIndex))
+				{ // last implementation of the family, so delete it
+				delete fontInfo;
+				iOpenFontTypefaceSupportList.Remove(fontPos);
+				}
+			}
+		}
+	}
+
+/**
+This function checks the supplied typeface name against the existing bitmap and open 
+typefaces, to see if it present.
+
+@param aName The name of the typeface family name to be checked. 
+@return ETrue if the typeface is present, EFalse otherwise.
+
+@released
+@internalTechnology 
+*/
+EXPORT_C TBool CFontStore::HaveTypefaceFamilyName(const TDesC& aName)
+	{
+	//there are two lists for typefaces
+	//not supporting linked fonts here
+	
+	//first list is open fonts
+	TInt count = iOpenFontTypefaceSupportList.Count();
+	for (TInt index=count-1;index>=0;index--)
+		{
+		if (aName.CompareF(iOpenFontTypefaceSupportList[index]->iSupport.iTypeface.iName)==0)
+			return ETrue;
+		}
+
+	//now look through bitmap fonts
+	count = iTypefaceList.Count();
+	for (TInt index=count-1;index>=0;index--)
+		{
+		if (aName.CompareF(iTypefaceList[index]->iName)==0)
+			return ETrue;
+		}
+
+	return EFalse;
+	}
+
+/**
+@internalTechnology
+@released
+*/
+EXPORT_C TInt CFontStore::CreateLinkedTypeface(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt aSession, TInt& aId)
+	{
+	TInt err;
+	TInt retErr=0;
+	TRAP(err,retErr = CreateLinkedTypefaceL(aLinkedTypefaceSpec,aSession,aId));
+	if (err!=KErrNone)
+		{	
+		return err;
+		}
+	else
+		{
+		return retErr;	
+		}
+	}
+
+/* this function is used to create the linked typeface, the linked typeface is created on
+ * the font and bitmap server heap, not the shared heap.
+ */	
+TInt CFontStore::CreateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt /*aSession*/, TInt& /*aId*/)	
+	//reconstuct a CLinkedTypefaceSpecification - could store as T type, but then the
+	// maximum size would be used for every linked typeface
+	//
+	{
+	const TAny* extensionPtr = FontLinkingInterface();
+	
+	if (extensionPtr == NULL)
+		return KErrNotSupported;
+	
+	//Convert the TLinkedTypefaceSpecification args into the
+	//COpenFontLinkedTypefaceSpecification recognised by the rasteriser 
+	COpenFontLinkedTypefaceSpecification* spec = 
+		COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec);
+	
+	TInt err = ValidateLinkedFontSpecificationL(*spec, EFalse);
+	
+	if (err == KErrNone)
+    {
+		GenerateLinkedFontFileL(*spec, extensionPtr, EFalse);
+    }
+
+	CleanupStack::PopAndDestroy(spec);
+	return err;
+	}
+
+/*
+@internalTechnology
+Retrieve the specification from a linked typeface; the name of the typeface should be specified in the parameter.
+
+@param aLinkedTypefaceSpec An empty linked typeface spec containing the name of the typeface to be retrieved.
+
+@leave One of the system wide error codes.
+*/
+EXPORT_C void CFontStore::GetLinkedTypefaceL(TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec)
+	{
+	const TAny* extensionPtr = FontLinkingInterface();
+	
+	if (extensionPtr == NULL)
+		User::Leave(KErrNotSupported);
+
+	MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)extensionPtr;
+	
+	//Check whether the font is loaded
+	CTypefaceSupportInfo* supinfo;
+	TTypefaceSupport support;
+	COpenFontFile* fetchFont=NULL;
+	for (TInt count=0;count<(iOpenFontTypefaceSupportList.Count());count++)
+		{
+		supinfo = iOpenFontTypefaceSupportList[count];
+		support = supinfo->iSupport;			
+		
+		if (aLinkedTypefaceSpec.iName==support.iTypeface.iName)
+			{
+			fetchFont = supinfo->iOpenFontFilePtrArray[0];
+			
+			break;	
+			}
+		}
+	if (fetchFont==NULL)
+		{
+		User::Leave(KErrNotFound);	
+		}
+
+	COpenFontLinkedTypefaceSpecification* typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec.iName);
+	TFileName fetchFile = fetchFont->FileName();
+	linkedExt->GetLinkedTypefaceSpecificationL(fetchFile, *typefaceSpec);
+	aLinkedTypefaceSpec = *typefaceSpec;
+	CleanupStack::PopAndDestroy(typefaceSpec);
+	}
+
+/*
+@internalTechnology
+Updates an existing linked typeface to a new specification.
+
+@param aLinkedTypefaceSpec The new specification for the typeface
+
+@leave KErrNotSupported Font linking is not supported by any of the installed rasterizers
+@leave One of the system wide error codes.
+*/
+EXPORT_C void CFontStore::UpdateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs& aLinkedTypefaceSpec)
+	{
+	const TAny* extensionPtr = FontLinkingInterface();
+	
+	if (extensionPtr == NULL)
+		User::Leave(KErrNotSupported);
+	
+	//Convert the TLinkedTypefaceSpecification args into the
+	//COpenFontLinkedTypefaceSpecification recognised by the rasteriser 
+	COpenFontLinkedTypefaceSpecification* spec = 
+		COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec);
+	
+	TInt err = ValidateLinkedFontSpecificationL(*spec, ETrue);
+	User::LeaveIfError(err);
+	
+	GenerateLinkedFontFileL(*spec, extensionPtr, ETrue);
+
+	CleanupStack::PopAndDestroy(spec);
+	}
+
+/**
+@internalTechnology
+Performs the loading of font files at boot time. This is a three stage procedure.
+
+1. Copies linked fonts to be updated from their temporary directory into the linked fonts folder
+2. Loads all the linked fonts from the linked fonts folder.
+3. Loads all remaining font files from *:\resource\fonts
+ */
+EXPORT_C void CFontStore::LoadFontsAtStartupL()
+	{
+	//First copy any updated linked fonts from their temporary dir to the linked font dir
+	CFileMan* fm = CFileMan::NewL(iFs);
+	CleanupStack::PushL(fm);
+	
+	//Get the fbserv private folder
+	TBuf<KMaxPrivatePathLength> privPath;
+	iFs.PrivatePath(privPath);
+	
+	//Construct the linked font dir path
+	TBuf<KMaxLinkedFontPathLength> linkedFontDir;
+	linkedFontDir.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath);
+	
+	//Construct the linked font temp dir path
+	TBuf<KMaxLinkedFontPathLength> linkedFontTempDir;
+	linkedFontTempDir.Append(linkedFontDir);
+	linkedFontTempDir.Append(KLinkedFontFileTempFolder);
+	
+	//Copy the temp folder into the main folder
+	TInt err = fm->Copy(linkedFontTempDir, linkedFontDir, CFileMan::EOverWrite);
+
+	if (err == KErrNone)
+		{
+		//If sucessful copying remove the temp folder
+		//A leave is not thrown as the empty directory remaining is not a significant enough
+		//to prevent fbserv from starting
+		fm->RmDir(linkedFontTempDir);
+		}
+	 
+	CleanupStack::PopAndDestroy(fm);
+	
+	//Load Linked Fonts
+	LoadFontsL(linkedFontDir);
+	
+	//Load the remaining fonts
+	LoadFontsL(KFBSERVFontDirSecure);
+	}
+/**
+@internalTechnology
+Returns the pointer to the first rasterizer supporting font linking (KUidLinkedTypefaceRasterizerExtension).
+*/
+const TAny* CFontStore::FontLinkingInterface() const
+	{
+	TInt rastcount = iOpenFontRasterizerList.Count();
+	COpenFontRasterizer* rast;
+	TAny* extensionPtr = NULL;
+	
+	//Check each rasterizer in turn to check it supports the extended interface.
+	//In reality there should only be one but multiple rasterizers are supported.
+	for (TInt i = 0 ; i != rastcount ; i++)
+		{
+		rast = iOpenFontRasterizerList[i];
+		rast->ExtendedInterface(KUidLinkedTypefaceRasterizerExtension, extensionPtr);
+		
+		if (extensionPtr != NULL)
+			break;
+		}
+	
+	return extensionPtr;
+	}
+
+/**
+Validates the linked font specification passed as a parameter.
+
+@param aSpec The specification to be validated
+@param aOverwrite ETrue if this is an update operation, EFalse otherwise
+*/
+TInt CFontStore::ValidateLinkedFontSpecificationL(COpenFontLinkedTypefaceSpecification& aSpec, TBool aOverwrite) const
+	{
+	//see if the typeface is an existing regular typeface.
+	if (!aOverwrite)
+		{
+		TInt numberTypefaces = iTypefaceList.Count();
+		TInt c;
+		
+		for (c=0;c<numberTypefaces;c++)
+			{
+			TTypeface* ptr=(iTypefaceList)[c];
+			
+			/* only comparing on the name */
+			if (0== ptr->iName.CompareF(aSpec.Name()))
+				{
+				//A typeface with this name is already loaded
+				return KErrAlreadyExists;
+				}
+			}
+			
+		TInt numberOpenFontFiles = iOpenFontFileList.Count();
+		for (c=0;c<numberOpenFontFiles;c++)
+			{
+			COpenFontFile* ptr=(iOpenFontFileList)[c];
+			
+			numberTypefaces= ptr->FaceCount();
+			TInt c2;
+			for (c2=0;c2<numberTypefaces;c2++)
+				{
+				const TOpenFontFaceAttrib& attrib = ptr->FaceAttrib(c2);
+
+				/* only comparing on the name */
+				if (0== attrib.ShortFullName().CompareF(aSpec.Name()))
+					{
+					//have a matching name, return error
+					return KErrAlreadyExists;
+					}
+				if (0== attrib.ShortFamilyName().CompareF(aSpec.Name()))
+					{
+					//have a matching name, return error
+					return KErrAlreadyExists;
+					}	
+				}
+			}
+		}
+		//For each element, check whether the typeface exists and add the correct filename to the spec if it does
+		TInt numTypefaces = aSpec.TypefaceCount();
+		TFileName fileName;
+		COpenFontLinkedTypefaceElementSpec* element;
+		
+		for (TInt counter=0;counter<numTypefaces;counter++)
+			{
+			element = aSpec.Typeface(counter);
+			
+			if (GetFontFilePath(element->ElementName(), fileName))
+				{
+				element->SetFileNameL(fileName);
+				}
+			else
+				{
+				return KErrNotFound;
+				}
+			}
+		return KErrNone;
+	}
+
+
+/**
+Sends the specification to the font rasterizer to be created/updated.
+
+@param aSpec The linked font specification
+@param aExtension The extension interface of the chosen rasterizer
+@param aUpdate ETrue if the file is being updated, EFalse if it should be created
+
+@leave KErrNotFound Attempting to update a file which does not exist
+ */
+void CFontStore::GenerateLinkedFontFileL(COpenFontLinkedTypefaceSpecification& aSpec, const TAny* aExtension, TBool aUpdate)
+	{
+	MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)aExtension;
+
+	//Generate the filename for the linked font file (excluding the extension
+	//and the .) which are appended by the rasterizer.
+	TFileName privPath;
+	User::LeaveIfError(iFs.PrivatePath(privPath));
+	TFileName fn;
+	fn.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath);
+	
+	//Choose the correct path to write the file to
+	if (aUpdate)
+		{
+		fn.Append(KLinkedFontFileTempFolder);
+		}
+	
+	// Create the directory if it does not exist
+	TInt result = iFs.MkDirAll(fn);
+	if (result != KErrAlreadyExists)
+		{
+		User::LeaveIfError(result);
+		}
+	
+	//Append the linked font filename to the path for the rasterizer.
+	fn.Append(aSpec.Name());
+	
+	// If we are updating, check that the file is a linked typeface before attempting the update.
+	if (aUpdate)
+		{
+		TFileName fn;
+		TBool exists = GetFontFilePath(aSpec.Name(), fn);
+		
+		if (exists)
+			{
+			COpenFontLinkedTypefaceSpecification* tempSpec = COpenFontLinkedTypefaceSpecification::NewLC(aSpec.Name());
+			TRAPD(ret, linkedExt->GetLinkedTypefaceSpecificationL(fn, *tempSpec));
+			User::LeaveIfError(ret);
+			CleanupStack::PopAndDestroy(tempSpec);
+			}
+		else
+			{
+			User::Leave(KErrNotFound);
+			}
+		}
+	
+	//Use the rasterizer extension to create the linked typeface
+	linkedExt->CreateLinkedTypefaceL(aSpec, fn);
+	
+	// Load the new linked typeface
+	if (!aUpdate)
+		{
+		AddFileL(fn);
+		}
+	}
+
+/**
+Function called at system startup to find and load all fonts in the specified 
+folder. The value of the folder will be the secure Data-caged private folder 
+named "\resource\fonts". 
+
+The first font of a given name overrides subsequent ones. 
+
+The search order is: Y:, X:, W:, ..., C:, B:, A:, Z:
+
+@see TFindFile 
+@param aFontsDir The directory search pattern 
+ */
+void CFontStore::LoadFontsL(const TDesC& aFontsDir)
+	{
+#ifdef _DEBUG
+	_LIT(KLoadStarted, "CFontStore::LoadFontsL Started.\r\n");
+	RDebug::Print(KLoadStarted);
+	TUint32	loadStartTime = StartTiming();
+#endif
+	
+	RArray<TParse> fontsToLoad;
+	CleanupClosePushL(fontsToLoad);
+	TFindFile fileFinder(iFs);
+	CDir* foundFileList = NULL;
+
+	_LIT(KFBSERVFontFilePattern, "*");
+	TInt findFileComplete = fileFinder.FindWildByDir(KFBSERVFontFilePattern, aFontsDir, foundFileList);
+
+	while (!findFileComplete)
+		{
+		CleanupStack::PushL(foundFileList);
+		const TInt foundFileCount = foundFileList->Count();
+		const TDesC& pathInfo = fileFinder.File();
+		
+		// Build a list of fonts to be loaded eliminating duplicate filenames. 
+		for (TInt ii = 0; ii < foundFileCount; ii++)
+			{
+			TParse fullFontFileName;
+			if (fullFontFileName.Set((*foundFileList)[ii].iName, &pathInfo, NULL) == KErrNone)
+				{
+				// If the font has not already been loaded, validate it then add it to the list.
+				if (!FileIsInList(fullFontFileName, fontsToLoad))
+					{
+					// Do not validate fonts on Z: (assumed to be ROM created with valid fonts)
+					if (FileIsOnZ(fullFontFileName))
+						{
+						fontsToLoad.AppendL(fullFontFileName);
+						}
+					else
+						{
+						// Test font before loading
+						TRAPD(err, SanityCheckFontFileL(fullFontFileName))
+						if (KErrNone == err)
+							{
+							// Add file 
+							fontsToLoad.AppendL(fullFontFileName);
+							}
+						else
+							{
+							_LIT(KCorruptFont, "CFontStore::LoadFontsL %S could not be loaded.\r\n");
+							RDebug::Print(KCorruptFont, &fullFontFileName.FullName());
+							}
+						}
+					}
+				}
+			}
+
+		CleanupStack::PopAndDestroy(foundFileList);
+		findFileComplete = fileFinder.FindWild(foundFileList);
+		}
+	
+	// Load the fonts in reverse order (i.e. Z:, A: to Y:) this causes
+	// fonts on Z: to take priority over fonts on A: to Y: when the internal 
+	// font names are identical.
+	TInt kk = fontsToLoad.Count();
+	while(kk--)
+		{
+		TUid fontUid = KNullUid;
+		
+		// Load this font as a new font, and add it to the list of loaded fonts
+		TRAPD(addFileError, AddSanityCheckedFontL(fontsToLoad[kk], fontUid));
+		if (addFileError)
+			{
+			_LIT(KLoadedFont, "CFontStore::LoadFontsL failed with error %i to load font, filename: %S\r\n");
+			RDebug::Print(KLoadedFont, addFileError, &(fontsToLoad[kk].FullName()));
+			}
+#ifdef _DEBUG
+		else
+			{
+			// NOTE: This is to make testing of confirming what fonts are loaded a little easier as there is no 
+			//		 easy way to get this information from outside the server.
+			_LIT(KLoadedFont, "CFontStore::LoadFontsL loaded font filename: %S\r\n");
+			RDebug::Print(KLoadedFont, &(fontsToLoad[kk].FullName()));
+			}
+#endif
+		}
+	
+#ifdef _DEBUG
+	TUint32 loadTime = FinishTimingL(loadStartTime);
+	_LIT(KLoadEnded, "CFontStore::LoadFontsL Finished. Took: %dus\r\n");
+	RDebug::Print(KLoadEnded, loadTime);
+#endif
+	CleanupStack::PopAndDestroy(&fontsToLoad);
+	}
+/**
+Retrieves the full path and filename of the font with the specified name. This function
+searches through all open font files currently loaded by font store.
+
+@param aFontName The full name of the font to search for
+@param aFilePath An empty descriptor to have the file name filled in
+
+@return ETrue if the font is found; EFalse if not
+*/
+EXPORT_C TBool CFontStore::GetFontFilePath(const TDesC& aFontName, TFileName& aFilePath) const
+	{
+	TInt numTypefaces = iOpenFontFileList.Count();
+	COpenFontFile* thisFile;
+	TOpenFontFaceAttrib faceAttrib;
+	
+	//For every (Truetype) font file
+	for (TInt i = 0 ; i != numTypefaces ; i++)
+		{
+		thisFile = iOpenFontFileList[i];
+		
+		//For every face within this file
+		for (TInt face = 0 ; face != thisFile->FaceCount() ; face++)
+			{
+			faceAttrib = thisFile->FaceAttrib(face);
+			if (faceAttrib.FullName().CompareF(aFontName) == 0)
+				{
+				aFilePath = thisFile->FileName();
+				return ETrue;
+				}
+			}
+		}
+	return EFalse;	
+	}
+
+TInt CFontStore::CacheFontTable(TUid aFileUid, TUint32 aTag, 
+        TAny *&aContent, TInt aLength)
+    {
+    return iFontTableCache->Append(aFileUid, aTag, aContent, aLength);
+    }
+
+TInt CFontStore::FindFontTableInCache(TUid aFileUid, TUint32 aTag, 
+        TAny *&aContent, TInt &aLength)
+    {
+    TInt id;
+    return iFontTableCache->Find(aFileUid, aTag, aContent, aLength, &id);
+    }
+
+TInt CFontStore::IncreaseUnhintedOutlineRefCount(const TUnhintedOutlineId &aOutlineId, 
+        TInt aSessionHandle)
+    {
+    return iUnhintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
+    }
+
+TInt CFontStore::IncreaseHintedOutlineRefCount(const THintedOutlineId &aOutlineId,
+        TInt aSessionHandle)
+    {
+    return iHintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
+    }
+
+TInt CFontStore::IncFontTableRefCount(TUid aFileUid, TUint32 aTag, 
+        TInt aSessionHandle)
+    {
+    return iFontTableCache->IncRefCount(aFileUid, aTag, aSessionHandle);
+    }
+
+TInt CFontStore::DecFontTableRefCount(TUid aFileUid, TUint32 aTag, 
+        TInt aSessionHandle)
+    {
+    return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
+    }
+
+TInt CFontStore::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, TAny * aData, 
+        TInt aLength, TAny *&aOutline, TInt &aLen)
+    {
+    return iUnhintedOutlineCache->CacheUnhintedOutline(aOutlineId, aData, aLength, 
+            aOutline, aLen);
+    }
+
+TInt CFontStore::CacheHintedOutline(const THintedOutlineId &aOutlineId,
+        TAny * aData, TInt aLength, TAny *&aOutline, TInt &aLen)
+    {
+    return iHintedOutlineCache->CacheHintedOutline(aOutlineId, aData, aLength,
+            aOutline, aLen);
+    }
+
+TInt CFontStore::ReleaseUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
+        TInt aSessionHandle)
+    {
+    return iUnhintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
+    }
+
+TInt CFontStore::ReleaseHintedOutline(const THintedOutlineId &aOutlineId,
+        TInt aSessionHandle)
+    {
+    return iHintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
+    }
+
+TInt CFontStore::ReleaseFontTable(TUid aFileUid, TUint32 aTag, 
+        TInt aSessionHandle)
+    {
+    return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
+    }
+
+TInt CFontStore::FindUnhintedOutlineInCache(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
+        TInt &aLength)
+    {
+    return iUnhintedOutlineCache->Find(aOutlineId, aData, aLength);
+    }
+
+TInt CFontStore::FindHintedOutlineInCache(const THintedOutlineId &aOutlineId, 
+        TAny *&aData, TInt &aLength)
+    {
+    return iHintedOutlineCache->Find(aOutlineId, aData, aLength);
+    }
+
+void CFontStore::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
+    {
+    iHintedOutlineCache->CleanupCacheOnOpenFontRemoval(aFont);
+    //iUnhintedOutlineCache.OnOpenFontRemoval(aFont);
+    }
+
+void CFontStore::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile) 
+    {
+    iUnhintedOutlineCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
+    iFontTableCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
+    }
+
+/** Clean up font table and glyph outline caches when an FBS session is terminated.
+ * All the reference counts related to that session are cleared.
+@param aSession: Input. A pointer to the terminating session.
+@return always returns KErrNone.
+@internalTechnology
+*/
+EXPORT_C
+void CFontStore::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
+    {
+    iHintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
+    iUnhintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
+    iFontTableCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
+    }
+
+
+void TFontTableGlyphOutlineCacheMemMonitor::Inc(TInt aBytes)
+    {
+    iBytes += aBytes;
+    }
+
+void TFontTableGlyphOutlineCacheMemMonitor::Dec(TInt aBytes)
+    {
+    iBytes -= aBytes;
+    }
+
+TInt TFontTableGlyphOutlineCacheMemMonitor::GetMemUsage()
+    {
+    return iBytes;
+    }
+
+TFontTableGlyphOutlineCacheMemMonitor::TFontTableGlyphOutlineCacheMemMonitor(): 
+    iBytes(0) 
+    {
+    // null constructor
+    }
+
+TUnhintedOutlineId::TUnhintedOutlineId(TUid aFileUid, TInt aFaceIndex, TUint aId):
+iFileUid(aFileUid), iFaceIndex(aFaceIndex), iId(aId)
+    {
+    // a null constructor;
+    }
+
+THintedOutlineId::THintedOutlineId(COpenFont *aFont, TUint aId):
+iFont(aFont), iId(aId)
+    {
+    // a null constructor;
+    }
+
+#ifdef _DEBUG
+/**
+Returns a timestamp for use by FinishTimingL().
+@return The timestamp.
+@see FinishTimingL
+*/
+TUint32 StartTiming(void)
+	{
+	return User::FastCounter();
+	}
+
+/**
+Returns the time difference between a given time and now in microseconds.
+@param aStartTime The start time returned by calling StartTiming()
+@return The time difference in microseconds.
+@see StartTiming()
+*/
+TUint32 FinishTimingL(TUint32 aStartTime)
+	{
+	TInt freq = 0;
+	TUint32 endtime = User::FastCounter();
+	User::LeaveIfError(HAL::Get(HALData::EFastCounterFrequency, freq));
+	TUint32 diff = endtime - aStartTime;
+	TInt64 diffTime = (1000000 * TInt64(diff)) / (TInt64)freq;
+	return TUint32(diffTime);
+	}
+#endif
+
+/**
+Returns true if the filename passed in is on the Z: drive
+@param aFileName The filename to check
+@return ETrue if the file is on Z:
+*/
+TBool FileIsOnZ(TParse& aFileName)
+	{
+	TBool onZ = EFalse;
+	
+	const TDesC& fileDrive = aFileName.Drive();
+	_LIT(KZDrive,"z:");
+	if (0 == fileDrive.CompareF(KZDrive))
+		{
+		onZ = ETrue;
+		}
+	
+	return onZ;
+	}
+
+
+/**
+Returns true if the filename passed in is in the supplied list
+@param aFileName The filename to check
+@param aList The list to check
+@return ETrue if the file is in the list
+*/
+TBool FileIsInList(TParse& aFileName, RArray<TParse>& aList)
+	{
+	TBool inList = EFalse;
+	
+	TInt jj = aList.Count();
+	while(jj--)
+		{
+		TPtrC shortFilename = aFileName.NameAndExt();
+		if (shortFilename.CompareF( aList[jj].NameAndExt() ) == 0)
+			{
+#ifdef _DEBUG
+			_LIT(KEclipsesFont, "CFontStore::FileIsInList %S eclipses %S\r\n");
+			RDebug::Print(KEclipsesFont, &aList[jj].FullName(), &aFileName.FullName());
+#endif
+			inList = ETrue;
+			break;
+			}
+		}
+	
+	return inList;
+	}