os/textandloc/fontservices/fontstore/src/FNTSTORE.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 1995-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include <e32hal.h>
    20 #include <hal.h>
    21 #include <s32file.h>
    22 #include <graphics/shapeimpl.h>
    23 #include <fntstore.h>
    24 #include "FNTBODY.H"
    25 #include "FNTSTD.H"
    26 #include <graphics/shaperparams.h>
    27 
    28 #define DO_LOADFONT_OPTIMIZATION 1
    29 #include <linkedfonts.h>
    30 #include "linkedfontsprivate.h"
    31 #include "openfontsprivate.h"
    32 #include <openfontlinkedtypefaceelementspec.h>
    33 #include <graphics/openfontlinkedtypefaceextension.h>
    34 #include <graphics/openfontlinkedtypefacespecification.h>
    35 #include <graphics/openfontrasterizer.h>
    36 #include <graphics/openfontconstants.h>
    37 
    38 #include "OstTraceDefinitions.h"
    39 #ifdef OST_TRACE_COMPILER_IN_USE
    40 #include "FNTSTORETraces.h"
    41 #endif
    42 
    43 
    44 static const TUint32 KOutlineGlyphIdHashMask = 0x0000ffff;
    45 static const TUint32 KOutlineFileUidHashMask = 0x00ff0000;
    46 static const TUint32 KOutlineFaceIndexHashMask = 0x0f000000;
    47 static const TUint32 KOutlineFontPtrHashMask = 0x0fff0000;
    48 
    49 // uncomment to enable some verbose debug prints
    50 //#define VERBOSE_DEBUG 1
    51 
    52 
    53 /**  These constants set the default pixel width and height, in Twips x1000.
    54  Hal Data information overrides this if it is available. EDisplayXPixels & EDisplayXTwips, 
    55  EDisplayYPixels & EDisplayYTwips values are required respectively.
    56 
    57  (11860 is approx equivalent to 120 pixels per inch.)
    58 @internalComponent
    59 */
    60 const TInt KDefaultPixelWidthInTwips = 11860;
    61 const TInt KDefaultPixelHeightInTwips = 11860;
    62 
    63 // default granularity for arrays
    64 const TInt KDefaultArrayGranularity = 8;
    65 
    66 /* Maximum height of a character bitmap. When font height in pixel is 1024, each 
    67 character bitmap is equal to (roughly) 1024 x 1024 x 8 bits/pixel = 1 MB.
    68 @internalComponent
    69 */
    70 const TInt KMaxFontHeightInPixels = 1024;
    71 
    72 /* Minimum height of font in pixels that can be displayed on the screen.
    73 @internalComponent
    74 */
    75 const TInt KMinFontHeightInPixels = 2;
    76 /**
    77 The arbitrary list of sizes, in points, returned for scaleable fonts.
    78 We can't return 2^32 - 1 sizes, or something that reflect the fact
    79 that any size is okay, because a UI will probably try to create a listbox containing all the sizes.
    80 
    81 Array stored in Twips as that is the only form of the value currently used.
    82 @internalComponent
    83 */
    84 #define POINTSIZE_IN_TWIPS(p)	((p) * 20)
    85 const TInt gOpenFontSizeInTwipsArray[] =
    86 	{
    87 	// 4pt-18pt in steps of 1pt (15 sizes)
    88 	POINTSIZE_IN_TWIPS(4), POINTSIZE_IN_TWIPS(5), POINTSIZE_IN_TWIPS(6),
    89 	POINTSIZE_IN_TWIPS(7), POINTSIZE_IN_TWIPS(8), POINTSIZE_IN_TWIPS(9),
    90 	POINTSIZE_IN_TWIPS(10), POINTSIZE_IN_TWIPS(11), POINTSIZE_IN_TWIPS(12),
    91 	POINTSIZE_IN_TWIPS(13), POINTSIZE_IN_TWIPS(14), POINTSIZE_IN_TWIPS(15),
    92 	POINTSIZE_IN_TWIPS(16), POINTSIZE_IN_TWIPS(17), POINTSIZE_IN_TWIPS(18),
    93 	// 20pt-36pt in steps of 2pt (9 sizes)
    94 	POINTSIZE_IN_TWIPS(20), POINTSIZE_IN_TWIPS(22), POINTSIZE_IN_TWIPS(24),
    95 	POINTSIZE_IN_TWIPS(26), POINTSIZE_IN_TWIPS(28), POINTSIZE_IN_TWIPS(30),
    96 	POINTSIZE_IN_TWIPS(32), POINTSIZE_IN_TWIPS(34), POINTSIZE_IN_TWIPS(36),
    97 	// 40pt-72pt in steps of 4pt (9 sizes)
    98 	POINTSIZE_IN_TWIPS(40), POINTSIZE_IN_TWIPS(44), POINTSIZE_IN_TWIPS(48),
    99 	POINTSIZE_IN_TWIPS(52), POINTSIZE_IN_TWIPS(56), POINTSIZE_IN_TWIPS(60),
   100 	POINTSIZE_IN_TWIPS(64), POINTSIZE_IN_TWIPS(68), POINTSIZE_IN_TWIPS(72),
   101 	// 80pt-144pt in steps of 8pt (9 sizes)
   102 	POINTSIZE_IN_TWIPS(80), POINTSIZE_IN_TWIPS(88), POINTSIZE_IN_TWIPS(96),
   103 	POINTSIZE_IN_TWIPS(104), POINTSIZE_IN_TWIPS(112), POINTSIZE_IN_TWIPS(120),
   104 	POINTSIZE_IN_TWIPS(128), POINTSIZE_IN_TWIPS(136), POINTSIZE_IN_TWIPS(144)
   105 	};
   106 
   107 const TInt KOpenFontSizeArrayCount = sizeof(gOpenFontSizeInTwipsArray) / sizeof(gOpenFontSizeInTwipsArray[0]);
   108 
   109 /**
   110 @internalTechnology
   111  The folder used to store linked fonts; the character represents the system drive
   112  location and the descriptor contains the private path of fbserv.
   113  */
   114 _LIT(KLinkedFontFileFolder, "%c:%Slfonts\\");
   115 
   116 /**
   117 @internalTechnology
   118  The folder used to store updated linked fonts; the descriptor should be formatted
   119  with the formatted version of KLinkedFontFileFolder. Files will be moved from this
   120  folder to KLinkedFontFileFolder at boot time before the font loading procedure.
   121  */
   122 _LIT(KLinkedFontFileTempFolder, "update\\");
   123 
   124 /**
   125 The font search string. The Y: directory prefix forces the search to 
   126 start with drive Y:. The drives will be searched in the order Y: to A: then Z:
   127 */
   128 _LIT(KFBSERVFontDirSecure, "y:\\resource\\fonts\\");
   129 
   130 /**The maximum length of the linked font folder path*/
   131 const TInt KMaxLinkedFontPathLength = 36;
   132 
   133 /**The maximum length of a private path*/
   134 const TInt KMaxPrivatePathLength = 19;
   135 
   136 /** Container for TTypefaceSupport that describes an Open Font family.
   137 
   138 There is an implicit assumption that all fonts in the family will have the same attributes
   139 as the first instance found.  E.g. that the range of font heights is the same. 
   140 
   141 An array of pointers to the COpenFontFile file objects that hold fonts in this family
   142 also provides reference counting for the object.
   143 
   144 @internalComponent
   145 */
   146 NONSHARABLE_CLASS(CTypefaceSupportInfo) : public CBase
   147 	{
   148 public:
   149 	CTypefaceSupportInfo();
   150 	inline TInt AddFontFilePtr(COpenFontFile* aOpenFontFile);
   151 	inline TInt AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib);
   152 	inline TInt FindFontFilePtr(COpenFontFile* aOpenFontFile);
   153 	inline TBool RemoveFontFilePtr(TInt aIndex);
   154 	void SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips);
   155 	inline const TTypefaceSupport* TypefaceSupport() const;
   156 	inline TInt NearestPointSizeIndex() const;
   157 	static TInt CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2);
   158 	~CTypefaceSupportInfo();
   159 
   160 public:
   161 	TTypefaceSupport iSupport;
   162 	// pointers back to the COpenFontFile object which has one or more typefaces in this family
   163 	RPointerArray<COpenFontFile> iOpenFontFilePtrArray;
   164 	// nearest standard point size index;
   165 	TInt iNearestPointSizeIndex;
   166 	};
   167 
   168 
   169 /** helper class used with the cleanup stack
   170 @internalComponent
   171 */
   172 class TCleanupRemoveFontFile
   173 	{
   174 public:
   175 	inline TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid);
   176 public:
   177 	CFontStore* iFontStore;
   178 	TUid iFontUid;
   179 	};
   180 
   181 
   182 // declare static functions
   183 static TInt MatchFontSpecsInPixels(const TOpenFontSpec& aCandidateFontSpec,
   184 	const TOpenFontSpec& aIdealFontSpec, TInt aCandidateMaxHeight = 0, TInt aIdealMaxHeight = 0);
   185 static void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength);
   186 static TUint TtfTableTagFromBufferL(TDes8& aDes);
   187 
   188 #ifdef _DEBUG
   189 static TUint32 StartTiming(void);
   190 static TUint32 FinishTimingL(TUint32 startTime);
   191 #endif
   192 
   193 static TBool FileIsOnZ(TParse& aFileName);
   194 static TBool FileIsInList(TParse& aFileName, RArray<TParse>& aList);
   195 
   196 
   197 /** Helper function for converting a pointer to an offset from the passed
   198 heap base. Use OffsetToPointer() to convert the returned offset back to a
   199 useable pointer.
   200 @param aAny A pointer to be converted to an offset.
   201 @param aHeapBase The heap base of the current process.
   202 @return An offset representing the passed pointer that can be converted
   203 back to a pointer using the function OffsetToPointer(). 
   204 @see OffsetToPointer()
   205  */
   206 LOCAL_C TInt PointerToOffset(const TAny* aAny, TUint8* aHeapBase)
   207     {
   208     if (aAny && aHeapBase)
   209         {
   210         return reinterpret_cast<TInt>(aAny) - reinterpret_cast<TInt>(aHeapBase);
   211         }
   212     return 0;
   213     }
   214 
   215 /** Helper function for converting an offset (that was calculated using
   216 PointerToOffset()) back to a pointer relative to the passed heap base.
   217 @param aOffset The offset to be converted to a pointer.
   218 @param aHeapBase The heap base of the current process.
   219 @return A pointer relative to the passed heap base.
   220 @see PointerToOffset()
   221  */
   222 LOCAL_C TAny* OffsetToPointer(TInt aOffset, TUint8* aHeapBase)
   223     {
   224     if (aOffset && aHeapBase)
   225         {
   226         return reinterpret_cast<TAny*>(aOffset + reinterpret_cast<TInt>(aHeapBase));
   227         }
   228     return NULL;
   229     }
   230 
   231 
   232 // CTypefaceSupportInfo
   233 CTypefaceSupportInfo::CTypefaceSupportInfo()
   234 	{
   235 	}
   236 
   237 
   238 CTypefaceSupportInfo::~CTypefaceSupportInfo()
   239 	{ // no ownership of font files, so just Close the array
   240 	iOpenFontFilePtrArray.Close();
   241 	}
   242 
   243 
   244 /** Add a back pointer to an Open Font file, in sorted order.
   245 @param aOpenFontFile font file that has a typeface in this family.
   246 @return KErrNone if added, KErrAlreadyExists if file is already referenced, or KErrNoMemory.
   247 @internalComponent
   248 */
   249 TInt CTypefaceSupportInfo::AddFontFilePtr(COpenFontFile* aOpenFontFile)
   250 	{
   251 	return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile);
   252 	}
   253 
   254 /** Add a back pointer to an Open Font file, in sorted order, but only if the font details are unique.
   255 @param aOpenFontFile font file that has a typeface in this family.
   256 @return KErrNone if added, KErrInUse if another file already defines this, KErrAlreadyExists if file is already referenced, or KErrNoMemory.
   257 @internalComponent
   258 */
   259 TInt CTypefaceSupportInfo::AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib)
   260 	{
   261 #ifdef _DEBUG	
   262 	_LIT(KLoadedFont, "TypefaceSupport: already loaded font: %S\n");
   263 #endif
   264 	
   265 	TPtrC findName=aFaceAttrib.FullName();
   266 	for (TInt i=0,maxi=iOpenFontFilePtrArray.Count();i<maxi;i++)
   267 		{	//Do any of the fonts already registered with this family already provide this specific font?
   268 		COpenFontFile* cmpFont=iOpenFontFilePtrArray[i];
   269 		if (cmpFont==aOpenFontFile)
   270 			{   //Another specific font in this font file has already been added to this family
   271 				//InsertInAddressOrder would detect this.
   272 #ifdef _DEBUG
   273 				RDebug::Print(KLoadedFont, &findName);
   274 #endif
   275 				return KErrAlreadyExists;	
   276 			}
   277 		else
   278 			{
   279 			for (TInt j=0,maxj=cmpFont->FaceCount();j<maxj;j++)
   280 				{	//The expectation is that open fonts will only have 1 face per file, so this loop is 1-pass generally.
   281 				const TOpenFontFaceAttrib& cmpFace=cmpFont->FaceAttrib(j);
   282 				TPtrC cmpName=cmpFace.FullName();
   283 				if (cmpName==findName)
   284 					{
   285 #ifdef _DEBUG
   286 					RDebug::Print(KLoadedFont, &findName);
   287 #endif
   288 					return KErrInUse;
   289 					}
   290 				}
   291 			}
   292 		}
   293 	return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile);
   294 	}
   295 
   296 /** Check font family for back pointer to an Open Font file.
   297 @param aOpenFontFile font file that may have a typeface in this family.
   298 @return KErrNotFound or the index of pointer
   299 @internalComponent
   300 */
   301 TInt CTypefaceSupportInfo::FindFontFilePtr(COpenFontFile* aOpenFontFile)
   302 	{
   303 	return iOpenFontFilePtrArray.FindInAddressOrder(aOpenFontFile);
   304 	}
   305 
   306 
   307 /** Remove a font file back pointer.
   308 @param aIndex the index of pointer, from FindFontFilePtr()
   309 @return ETrue if there are no more implementations of the font family
   310 @internalComponent
   311 */
   312 TBool CTypefaceSupportInfo::RemoveFontFilePtr(TInt aIndex)
   313 	{
   314 	iOpenFontFilePtrArray.Remove(aIndex);
   315 	return iOpenFontFilePtrArray.Count() == 0;
   316 	}
   317 
   318 
   319 /** Set the details of the typeface family.
   320 @param aFaceAttrib typeface to parameterise.
   321 @internalComponent
   322 */
   323 void CTypefaceSupportInfo::SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips)
   324 	{
   325 	iSupport.iTypeface.iName = aFaceAttrib.ShortFamilyName();
   326 	iSupport.iTypeface.SetIsProportional(!aFaceAttrib.IsMonoWidth());
   327 	iSupport.iTypeface.SetIsSerif(aFaceAttrib.IsSerif());
   328 	iSupport.iTypeface.SetIsSymbol(aFaceAttrib.IsSymbol());
   329 
   330 	// Find minimum size in twips then find the next higher standard size.
   331 	iSupport.iMinHeightInTwips = aMinHeightInTwips;
   332 	TInt fontSizeIndex = 0;
   333 	for (; fontSizeIndex < KOpenFontSizeArrayCount; ++fontSizeIndex)
   334 		{
   335 		const TInt KMinHeightInTwips = gOpenFontSizeInTwipsArray[fontSizeIndex];
   336 		if (aMinHeightInTwips <= KMinHeightInTwips)
   337 			{
   338 			aMinHeightInTwips = KMinHeightInTwips;
   339 			break;
   340 			}
   341 		}
   342 	iNearestPointSizeIndex = fontSizeIndex;
   343 	iSupport.iMaxHeightInTwips = Max(gOpenFontSizeInTwipsArray[KOpenFontSizeArrayCount - 1], iSupport.iMinHeightInTwips);
   344 	iSupport.iNumHeights = Max(1,KOpenFontSizeArrayCount - iNearestPointSizeIndex);
   345 	iSupport.iIsScalable = TRUE;
   346 	}
   347 
   348 
   349 /** Get the details of the typeface family.
   350 @internalComponent
   351 */
   352 const TTypefaceSupport* CTypefaceSupportInfo::TypefaceSupport() const
   353 	{
   354 	return &iSupport;
   355 	}
   356 	
   357 /** Get the Nearest Standard Point Size Index.
   358 @internalComponent
   359 */
   360 TInt CTypefaceSupportInfo::NearestPointSizeIndex() const
   361 	{
   362 	return iNearestPointSizeIndex;
   363 	}
   364 
   365 // for InsertInOrder
   366 TInt CTypefaceSupportInfo::CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2)
   367 	{
   368 	return aTypeface1.iSupport.iTypeface.iName.CompareF(aTypeface2.iSupport.iTypeface.iName);
   369 	}
   370 
   371 
   372 // TCleanupRemoveFontFile
   373 TCleanupRemoveFontFile::TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid) :
   374 	iFontStore(aFontStore), iFontUid(aFontUid)
   375 	{
   376 	}
   377 
   378 
   379 TBitmapFontCharacterOffset::TBitmapFontCharacterOffset()
   380  :	iBitmapOffset(0)
   381 	{}
   382 
   383 void TBitmapFontCharacterOffset::InternalizeL(RReadStream& aStream)
   384 	{
   385 	iBitmapOffset = aStream.ReadUint16L();
   386 	};
   387 
   388 EXPORT_C TCharacterMetrics::TCharacterMetrics()
   389  :	iAscentInPixels(0),
   390 	iHeightInPixels(0),
   391 	iLeftAdjustInPixels(0),
   392 	iMoveInPixels(0),
   393 	iRightAdjustInPixels(0)
   394 	{
   395 	}
   396 
   397 TBitmapFontCharacterMetrics::TBitmapFontCharacterMetrics()
   398  :	iAscentInPixels(0),
   399 	iHeightInPixels(0),
   400 	iLeftAdjustInPixels(0),
   401 	iMoveInPixels(0),
   402 	iRightAdjustInPixels(0)
   403 	{
   404 	}
   405 
   406 void TBitmapFontCharacterMetrics::InternalizeL(RReadStream& aStream)
   407 	{
   408 	iAscentInPixels = aStream.ReadInt8L();
   409 	iHeightInPixels = aStream.ReadInt8L();
   410 	iLeftAdjustInPixels = aStream.ReadInt8L();
   411 	iMoveInPixels = aStream.ReadInt8L();
   412 	iRightAdjustInPixels = aStream.ReadInt8L();
   413 	}
   414 
   415 /** Constructor. */
   416 EXPORT_C TAlgStyle::TAlgStyle()
   417  :	iBaselineOffsetInPixels(0),
   418 	iFlags(0),
   419 	iWidthFactor(1),
   420 	iHeightFactor(1)
   421 	{
   422 	}
   423 
   424 /** Sets whether the font is bold.
   425 
   426 @param aIsBold ETrue if the font is bold; otherwise EFalse. */
   427 EXPORT_C void TAlgStyle::SetIsBold(TBool aIsBold)
   428 	{
   429 	if (aIsBold)
   430 		iFlags |= EBold;
   431 	else
   432 		iFlags &= ~EBold;
   433 	}
   434 
   435 /** Sets whether the font is italic.
   436 
   437 @param aIsItalic ETrue if the font is italic; otherwise EFalse. */
   438 EXPORT_C void TAlgStyle::SetIsItalic(TBool aIsItalic)
   439 	{
   440 	if (aIsItalic)
   441 		iFlags |= EItalic;
   442 	else
   443 		iFlags &= ~EItalic;
   444 	}
   445 
   446 /** Sets whether the font is mono width - i.e. all characters have the same width.
   447 
   448 @param aIsMono ETrue if the font is mono width; otherwise EFalse. */
   449 EXPORT_C void TAlgStyle::SetIsMono(TBool aIsMono)
   450 	{
   451 	if (aIsMono)
   452 		iFlags|=EMono;
   453 	else
   454 		iFlags&=~EMono;
   455 	}
   456 
   457 /** Sets the width factor.
   458 
   459 @param aWidthFactor A width factor. */
   460 EXPORT_C void TAlgStyle::SetWidthFactor(TInt aWidthFactor)
   461 	{
   462 	iWidthFactor=(TInt8) aWidthFactor;
   463 	}
   464 
   465 /** Sets the height factor.
   466 
   467 @param aHeightFactor A height factor. */
   468 EXPORT_C void TAlgStyle::SetHeightFactor(TInt aHeightFactor)
   469 	{
   470 	iHeightFactor=(TInt8) aHeightFactor;
   471 	}
   472 
   473 /** Returns whether the font is bold.
   474 
   475 @return ETrue if the font is bold; otherwise EFalse. */
   476 EXPORT_C TBool TAlgStyle::IsBold() const
   477 	{
   478 	return iFlags&EBold;
   479 	}
   480 
   481 /** Returns whether the font is italic.
   482 
   483 @return ETrue if the font is italic; otherwise EFalse. */
   484 EXPORT_C TBool TAlgStyle::IsItalic() const
   485 	{
   486 	return iFlags&EItalic;
   487 	}
   488 
   489 /** Returns whether the font is mono - i.e. all characters have the same width.
   490 
   491 @return ETrue if the font is mono; otherwise EFalse. */
   492 EXPORT_C TBool TAlgStyle::IsMono() const
   493 	{
   494 	return iFlags&EMono;
   495 	}
   496 
   497 /** Returns the width factor.
   498 
   499 @return A width factor. */
   500 EXPORT_C TInt TAlgStyle::WidthFactor() const
   501 	{
   502 	return iWidthFactor;
   503 	}
   504 
   505 /** Returns the height factor.
   506 
   507 @return A height factor. */
   508 EXPORT_C TInt TAlgStyle::HeightFactor() const
   509 	{
   510 	return iHeightFactor;
   511 	}
   512 
   513 EXPORT_C TBool TAlgStyle::operator==(const TAlgStyle& aAlgStyle) const
   514 	{
   515 	return (iFlags==aAlgStyle.iFlags) && 
   516 	       (iWidthFactor==aAlgStyle.iWidthFactor) &&
   517 	       (iHeightFactor==aAlgStyle.iHeightFactor) &&
   518 	       (iBaselineOffsetInPixels==aAlgStyle.iBaselineOffsetInPixels);
   519 	}
   520 
   521 /**
   522 @internalTechnology
   523 */
   524 TBool TAlgStyle::operator!=(const TAlgStyle& aAlgStyle) const
   525 	{
   526 	return !this->operator==(aAlgStyle);
   527 	}
   528 
   529 CBitmapFont::CBitmapFont(
   530 	RHeap*				aHeap,
   531 	const TFontSpec&	aFontSpecInTwips,
   532 	const TAlgStyle&	aAlgStyle,
   533 	CFontBitmap*		aFontBitmap):
   534 	iFontSpecInTwips(aFontSpecInTwips),
   535 	iAlgStyle(aAlgStyle),
   536 	iHeap(aHeap)
   537 	{
   538 	iFontBitmapOffset = (TInt) ((TUint)(aFontBitmap) - (TUint)(this));
   539 	}
   540 
   541 CBitmapFont::CBitmapFont(
   542 	RHeap*				aHeap,
   543 	const TFontSpec&	aFontSpecInTwips,
   544 	const TAlgStyle&	aAlgStyle,
   545 	COpenFont*			aOpenFont):
   546 	iFontSpecInTwips(aFontSpecInTwips),
   547 	iAlgStyle(aAlgStyle),
   548 	iHeap(aHeap)
   549 	{
   550     // Set iOpenFont to be the offset of aOpenFont from the address of CBitmapFont.
   551     // In order to be able to identify iOpenFont as an offset instead of a pointer,
   552     // bitwise or the offset with 1.  Pointers will always be word aligned (and therefore even).
   553     if (aOpenFont)
   554         {
   555         __ASSERT_DEBUG(!(reinterpret_cast<TInt>(aOpenFont) & 1), Panic(EFntPointerNotByteAligned));
   556         iOpenFont = reinterpret_cast<COpenFont*>((reinterpret_cast<TInt>(aOpenFont) - reinterpret_cast<TInt>(this)) | 1);
   557         }
   558     else
   559         {
   560         iOpenFont = NULL;
   561         }
   562 	}
   563 
   564 /** This member is private and not intended for use. */
   565 void CBitmapFont::ConstructL()
   566 	{
   567 	if (!IsOpenFont())
   568 		FontBitmap()->UseL();
   569 	}
   570 
   571 /** This member is private and not intended for use. */
   572 CBitmapFont::~CBitmapFont()
   573 	{	
   574 	if (!IsOpenFont() && iFontBitmapOffset)
   575 		FontBitmap()->Release();
   576 	else if (IsOpenFont())
   577 		delete OpenFont();
   578 	}	
   579 
   580 CBitmapFont* CBitmapFont::NewL(
   581 	RHeap*				aHeap,
   582 	const TFontSpec&	aFontSpecInTwips,
   583 	const TAlgStyle&	aAlgStyle,
   584 	CFontBitmap*		aFontBitmap)
   585 	{
   586 	// font is placed in shared heap
   587 	CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont));
   588 	new(f) CBitmapFont(aHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap);
   589 	CleanupStack::PushL(f);
   590 	f->ConstructL();
   591 	CleanupStack::Pop(f);
   592 	return f;
   593 	}
   594 
   595 CBitmapFont* CBitmapFont::NewL(
   596 	RHeap*				aHeap,
   597 	const TFontSpec&	aFontSpecInTwips,
   598 	const TAlgStyle&	aAlgStyle,
   599 	COpenFont*			aOpenFont)
   600 	{
   601 	// font is placed in shared heap
   602 	CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont));
   603 	new(f) CBitmapFont(aHeap,aFontSpecInTwips,aAlgStyle,aOpenFont);
   604 	return f;
   605 	}
   606 	
   607 /** Returns the font type identifier:KCBitmapFontUidVal.
   608 
   609 @return The font type identifier. */
   610 EXPORT_C TUid CBitmapFont::DoTypeUid() const
   611 	{
   612 	return TUid::Uid(KCBitmapFontUidVal);
   613 	}
   614 
   615 /** Returns a font identifier.
   616 
   617 If it uses an open font the UID returned has a value of zero. Otherwise it 
   618 has the UID value of the CFontBitmap it uses.
   619 
   620 @return A font identifier. */
   621 TUid CBitmapFont::Uid() const
   622 	{
   623 	if (IsOpenFont())
   624 		return TUid::Uid(0);	
   625 	else
   626 		return FontBitmap()->iUid;
   627 	}
   628 
   629 /** Returns the font height in pixels.
   630 For an open font this will be the design height (notional rather than exact).
   631 
   632 @return Font height in pixels.
   633 @see FontMaxHeight()
   634 */
   635 EXPORT_C TInt CBitmapFont::DoHeightInPixels() const
   636 	{
   637 	if (IsOpenFont())
   638 		return Height(OpenFont()->Metrics().Size());	
   639 	else
   640 		return Height(FontBitmap()->iCellHeightInPixels);
   641 	}
   642 
   643 /** Returns the font ascent in pixels.
   644 
   645 The ascent is usually the height of a Latin capital letter above the baseline.
   646 For an open font, the returned value is likely to be inaccurate.
   647 Don't rely on it to get exact metrics at the pixel level.
   648 
   649 @return Font ascent in pixels.
   650 @see FontCapitalAscent()
   651 @see FontMaxAscent()
   652 */
   653 EXPORT_C TInt CBitmapFont::DoAscentInPixels() const
   654 	{
   655 	if (IsOpenFont())
   656 		return Height(OpenFont()->Metrics().Ascent());	
   657 	else
   658 		return Height(FontBitmap()->iAscentInPixels);
   659 	}
   660 
   661 /** Returns the width, in pixels, of the given character.
   662 
   663 If all characters have the same width (i.e. the font is mono - an attribute 
   664 stored in iAlgStyle) then this is the maximum normal width, returned using 
   665 MaxNormalCharWidthInPixels().
   666 
   667 Note: For OpenType fonts this function returns the horizontal advance of
   668 the character, which may be different from the actual width.
   669 
   670 @param aChar A character.
   671 @return The character width in pixels. */
   672 EXPORT_C TInt CBitmapFont::DoCharWidthInPixels(TChar aChar) const
   673 	{
   674 	const TUint8* bytes;
   675 	if (iAlgStyle.IsMono())
   676 		return MaxNormalCharWidthInPixels();
   677 	else
   678 		return Width(CharacterMetrics(aChar,bytes).iMoveInPixels);
   679 	}
   680 
   681 /** Returns the width, in pixels, of the given text.
   682 
   683 @param aText Text string.
   684 @return Width of the text in pixels. */
   685 EXPORT_C TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText) const
   686 	{
   687 	TMeasureTextInput* dummy = NULL;
   688 	return DoTextWidthInPixels(aText, dummy);
   689 	}
   690 
   691 /** Returns the width, in pixels, of the given text.
   692 
   693 @param aText Text string.
   694 @return Width of the text in pixels. */
   695 TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText, const TMeasureTextInput* aParam) const
   696 	{
   697 	TMeasureTextOutput output;
   698 	TInt advance_width = MeasureText(aText,aParam,&output);
   699 	return Max(advance_width,output.iBounds.Width());
   700 	}
   701 
   702 
   703 /** Returns the baseline offset in pixels, as stored in iAlgStyle.
   704 
   705 @return The baseline offset in pixels. */
   706 EXPORT_C TInt CBitmapFont::DoBaselineOffsetInPixels() const
   707 	{
   708 	return iAlgStyle.iBaselineOffsetInPixels;
   709 	}
   710 
   711 /** Returns the number of whole characters of aText, starting from the beginning, 
   712 that fit into the given pixel width.
   713 
   714 @param aText A text string.
   715 @param aWidthInPixels A width in pixels.
   716 @return The number of whole characters of aText that fit into aWidthInPixels.
   717 */
   718 EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels) const
   719 	{
   720 	TInt count = 0;
   721 	const TInt length = aText.Length();
   722 	TInt width = 0;
   723 	// accumulate text width character by character, until target is reached or exceeded
   724 	TInt widthDiff = aWidthInPixels - width;
   725 	while ( (widthDiff > 0) && (length > count) )
   726 		{ 
   727 		width += TextWidthInPixels(aText.Mid(count,1));
   728 		widthDiff = aWidthInPixels - width;
   729 		if (widthDiff >= 0)
   730 			{ // width <= aWidthInPixels
   731 			++count;
   732 			}
   733 		}
   734 	return count;
   735 	}
   736 
   737 /** Returns the number of whole characters of aText, starting from the beginning, 
   738 that fit into the given pixel width, and gets the excess width.
   739 
   740 @param aText A text descriptor.
   741 @param aWidthInPixels A width in pixels.
   742 @param aExcessWidthInPixels On return, the width left over of aWidthInPixels 
   743 after the maximum possible whole number of characters of aText have been fit 
   744 into it.
   745 @return The number of whole characters of aText that fit into aWidthInPixels. */
   746 EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels,TInt &aExcessWidthInPixels) const
   747 	{
   748 	TInt count = TextCount(aText,aWidthInPixels);
   749 	aExcessWidthInPixels = aWidthInPixels - TextWidthInPixels(aText.Left(count));
   750 	return count;
   751 	}
   752 
   753 /** Returns the font's maximum character width in pixels.
   754 
   755 @return The maximum character width in pixels. */
   756 EXPORT_C TInt CBitmapFont::DoMaxCharWidthInPixels() const
   757 	{
   758 	if (IsOpenFont())
   759 		return Width(OpenFont()->Metrics().MaxWidth());	
   760 	else
   761 		return Width(FontBitmap()->iMaxCharWidthInPixels);
   762 	}
   763 
   764 /** Returns the font's normal maximum character width in pixels.
   765 
   766 Note that when a CFontBitmap is used this value is the same as the maximum 
   767 character width in pixels returned by MaxCharWidthInPixels(), but when a COpenFont 
   768 is used the value may be different.
   769 
   770 @return The normal maximum character width in pixels. */
   771 EXPORT_C TInt CBitmapFont::DoMaxNormalCharWidthInPixels() const
   772 	{
   773 	if (IsOpenFont())
   774 		return Width(OpenFont()->Metrics().MaxWidth());
   775 	else
   776 		return Width(FontBitmap()->iMaxNormalCharWidthInPixels);
   777 	}
   778 
   779 /** Returns the device-independent font specification for the font.
   780 
   781 Note that this is set when the bitmap font object is constructed.
   782 
   783 @return A font specification. */
   784 EXPORT_C TFontSpec CBitmapFont::DoFontSpecInTwips() const
   785 	{
   786 	return iFontSpecInTwips;
   787 	}
   788 
   789 
   790 /** Attempts to rasterize a character (aCode) into a data area (aGlyphData) in 
   791 shared memory.
   792 
   793 This works only for open fonts: where the bitmap font object is using a COpenFont.
   794 
   795 Bitmap fonts are deemed to be fully rasterized after they have been loaded 
   796 from file. 
   797 
   798 Returns ETrue if the character was successfully rasterized or was already 
   799 in the cache. This function can be called only by the server; rasterization 
   800 uses memory and other resources (e.g., file handles) owned by the server. 
   801 
   802 @param aSessionHandle A session handle for the open font system.
   803 @param aCode A character code.
   804 @param aGlyphData A data area in shared memory.
   805 @return ETrue if the character was successfully rasterized or was already in 
   806 the cache; otherwise EFalse. */
   807 EXPORT_C TBool CBitmapFont::Rasterize(TInt aSessionHandle, TInt aCode, TOpenFontGlyphData* aGlyphData) const
   808 	{
   809 	if (IsOpenFont())
   810 		return OpenFont()->Rasterize(aSessionHandle, aCode, aGlyphData);
   811 	else
   812 		return EFalse;
   813 	}
   814 
   815 /** Gets a pointer to a bitmap and the metrics for a specified character, but only 
   816 if a CFontBitmap is being used by the bitmap font object.
   817 
   818 This function does not work when a COpenFont is being used, but GetCharacterData() 
   819 can be used instead.
   820 
   821 If the specified character does not exist in the font then the bitmap pointer 
   822 and character metrics are gotten for a replacement character, KReplacementCharacter.
   823 
   824 @param aCode A character code.
   825 @param aBytes On return, a pointer to the bitmap for the specified character.
   826 @return Metrics for the specified character. */
   827 EXPORT_C TCharacterMetrics CBitmapFont::CharacterMetrics(TInt aCode,const TUint8*& aBytes) const
   828 	{
   829 	/*
   830 	This function does not work for Open Fonts because the character data need not be
   831 	shared between sessions and a session handle is needed; GetCharacterData should be used instead.
   832 	*/
   833 	if (IsOpenFont())
   834 		{
   835 		aBytes = NULL;
   836 		return TCharacterMetrics();
   837 		}
   838 
   839 	TBitmapFontCharacterMetrics bitmap_font_metrics = FontBitmap()->CharacterMetrics(aCode,aBytes);
   840 
   841 	// Substitute the replacement character if this character doesn't exist in the font.
   842 	if (aBytes == NULL)
   843 		bitmap_font_metrics = FontBitmap()->CharacterMetrics(KReplacementCharacter,aBytes);
   844 
   845 	TCharacterMetrics metrics;
   846 	metrics.iAscentInPixels = bitmap_font_metrics.iAscentInPixels;
   847 	metrics.iHeightInPixels = bitmap_font_metrics.iHeightInPixels;
   848 	metrics.iLeftAdjustInPixels = bitmap_font_metrics.iLeftAdjustInPixels;
   849 	metrics.iMoveInPixels = bitmap_font_metrics.iMoveInPixels;
   850 	metrics.iRightAdjustInPixels = bitmap_font_metrics.iRightAdjustInPixels;
   851 	
   852 	if (iAlgStyle.IsMono())
   853 		{
   854 		TInt width = metrics.iMoveInPixels - metrics.iLeftAdjustInPixels - metrics.iRightAdjustInPixels;
   855 		metrics.iMoveInPixels = FontBitmap()->iMaxNormalCharWidthInPixels;
   856 		metrics.iLeftAdjustInPixels = (TInt16)((metrics.iMoveInPixels - width) / 2);
   857 		metrics.iRightAdjustInPixels = (TInt16)(metrics.iMoveInPixels - width - metrics.iLeftAdjustInPixels);
   858 		}
   859 
   860 	return metrics;	 // N.B. Not doubled for double height and double width.
   861 	}
   862 
   863  
   864 /** Gets a pointer to a bitmap and the metrics for a specified character.
   865 
   866 Note that this function calls CharacterMetrics() if a CFontBitmap is being 
   867 used by the bitmap font object, and maps the TCharacterMetrics values returned 
   868 by that function to aMetrics.
   869 
   870 If the function fails to get the bitmap and metric values (because the character 
   871 is in an open font and has not yet been rasterized) returns EFalse.
   872 
   873 @param aSessionHandle A session handle for the open font system.
   874 @param aCode A character code.
   875 @param aMetrics On return, metrics for the specified character.
   876 @param aBitmap On return, a pointer to the bitmap for the specified character.
   877 @return ETrue if successful, otherwise EFalse. */
   878 EXPORT_C TBool CBitmapFont::GetCharacterData(TInt aSessionHandle,TInt aCode,
   879 											 TOpenFontCharMetrics& aMetrics,const TUint8*& aBitmap) const
   880 	{
   881 	if (IsOpenFont())
   882 		{
   883 		const TOpenFontCharMetrics* nm;
   884 		if (OpenFont()->GetCharacterData(aSessionHandle,aCode,nm,aBitmap))
   885 			{
   886 			aMetrics = *nm;
   887 			return ETrue;
   888 			}
   889 		else
   890 			return EFalse;
   891 		}
   892 	else
   893 		{
   894 		TCharacterMetrics m = CharacterMetrics(aCode,aBitmap);
   895 		aMetrics = TOpenFontCharMetrics(m);
   896 		return ETrue;
   897 		}
   898 	}
   899 
   900 /** Gets the open font metrics. 
   901 
   902 These metrics distinguish between maximum character height and depth and typographic 
   903 ascent and descent, so that the clipping rectangle for text can be distinguished 
   904 from the distance to neighbouring baselines. 
   905 
   906 @param aMetrics Open font metrics. */
   907  
   908 EXPORT_C void CBitmapFont::GetFontMetrics(TOpenFontMetrics& aMetrics) const
   909 	{
   910 	if (IsOpenFont())
   911 		aMetrics = OpenFont()->Metrics();
   912 	else
   913 		{
   914 		new(&aMetrics) TOpenFontMetrics;
   915 		aMetrics.SetSize(CBitmapFont::DoHeightInPixels());
   916 		aMetrics.SetAscent(CBitmapFont::DoAscentInPixels());
   917 		aMetrics.SetDescent(aMetrics.Size() - aMetrics.Ascent());
   918 		aMetrics.SetMaxHeight(aMetrics.Ascent());
   919 		aMetrics.SetMaxDepth(aMetrics.Descent());
   920 		aMetrics.SetMaxWidth(CBitmapFont::DoMaxCharWidthInPixels());
   921 		}
   922 	}
   923 
   924  
   925 /** Gets the open font typeface attributes if possible. 
   926 
   927 At present no attempt is made to sythesize these attributes for bitmap fonts 
   928 (CFontBitmaps). 
   929 
   930 @param aAttrib On return, the open font typeface attributes.
   931 @return ETrue if successful; EFalse if not possible to get the open font typeface 
   932 attributes. */
   933 EXPORT_C TBool CBitmapFont::GetFaceAttrib(TOpenFontFaceAttrib& aAttrib) const
   934 	{
   935 	if (IsOpenFont())
   936 		{
   937 		const TOpenFontFaceAttrib* a = OpenFont()->FaceAttrib();
   938 		if (a)
   939 			{
   940 			aAttrib = *a;
   941 			return ETrue;
   942 			}
   943 		}
   944 	return EFalse;
   945 	}
   946 
   947 /** Gets encoding if a bitmap font (a CFontBitmap) is used.
   948 
   949 @return Bitmap encoding value. */
   950 EXPORT_C TInt CBitmapFont::BitmapEncoding() const
   951 	{
   952 	if (IsOpenFont())
   953 		return 0;
   954 	else
   955 		return FontBitmap()->iBitmapEncoding;
   956 	}
   957 
   958 /** Gets whether the open or bitmap font has the specified character.
   959 
   960 @param aCode A character code.
   961 @return ETrue if the font has the specified character; otherwise EFalse. */
   962 EXPORT_C TBool CBitmapFont::HasCharacterL(TInt aCode) const
   963 	{
   964 	if (IsOpenFont())
   965 		return OpenFont()->HasCharacterL(aCode);
   966 	else
   967 		{
   968 		const TUint8* bytes;
   969 		FontBitmap()->CharacterMetrics(aCode,bytes);
   970 		return (bytes != NULL);
   971 		}
   972 	}
   973 
   974 /** Gets whether the specified character needs to be rasterised.
   975 
   976 False is returned if it is a bitmap font (a CFontBitmap) being used by the 
   977 bitmap font object (so no rasterization is required) or if is an open font 
   978 (a COpenFont) and the character has been rasterized.
   979 
   980 @param aSessionHandle A session handle for the open font system.
   981 @param aCode A character code.
   982 @return ETrue if the character needs to be rasterized; otherwise EFalse. */
   983 EXPORT_C TBool CBitmapFont::CharacterNeedsToBeRasterized(TInt aSessionHandle,TInt aCode) const
   984 	{
   985 	if (IsOpenFont())
   986 		return OpenFont()->CharacterNeedsToBeRasterized(aSessionHandle,aCode);
   987 	else
   988 		return FALSE;	// characters in bitmap fonts do not need to be rasterized	
   989 	}
   990 
   991 /** Turns text into glyph codes and positions.
   992 @param aText The Unicode text to shape plus context
   993 @return The output shape header from the per-font cache, or 0 on failure.
   994 @internalTechnology
   995 */
   996 EXPORT_C TShapeHeader* CBitmapFont::ShapeTextL(const TDesC16& aText,
   997 	TInt aSessionHandle, const TShapeMessageParameters& aParams)
   998 	{
   999 	TShapeHeader* shape = 0;
  1000 
  1001 	if(IsOpenFont())
  1002 		{
  1003 		// get the data in a CShaper::TInput for the shaper
  1004 		CShaper::TInput input;
  1005 		input.iText = &aText;
  1006 		input.iStart = aParams.iStart;
  1007 		input.iEnd = aParams.iEnd;
  1008 		input.iScript= aParams.iScript;
  1009 		input.iLanguage = aParams.iLanguage;
  1010 		input.iMaximumAdvance = KMaxTInt;
  1011 		input.iFlags = 0;
  1012 		input.iSessionHandle = aSessionHandle;
  1013 		input.iReserved1 = 0;
  1014 
  1015 		TFontShapeFunctionParameters params;
  1016 		params.iEnd = input.iEnd;
  1017 		params.iLanguage = input.iLanguage;
  1018 		params.iScript = input.iScript;
  1019 		params.iStart = input.iStart;
  1020 		params.iText = input.iText;
  1021 		
  1022 		COpenFont* openFont = OpenFont();
  1023 		
  1024 		//if already exist just increase the reference count for that session
  1025 		shape = openFont->GetShapedData(aSessionHandle,&params);
  1026 		
  1027 		if (shape == NULL)
  1028 			{
  1029 			if (!openFont->HasShaper()
  1030  				|| (openFont->HasShaper() && ( 
  1031  				(TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetScript)) != input.iScript
  1032  				|| (TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetLang)) != input.iLanguage)))
  1033 				{ // Install the shaper
  1034 				openFont->DeleteShaper();
  1035 				InstallOpenFontShaper(openFont, input);
  1036 				}
  1037 
  1038 			if (openFont->HasShaper())
  1039 				{
  1040 				TInt error = openFont->GetShaper()->ShapeText(shape, input, iHeap);
  1041 				if (error != KErrNone)
  1042 					User::Leave(error);
  1043 				
  1044 				// Put this into the session cache
  1045 				TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(aSessionHandle,&params, shape);
  1046 				if (!cached_header)
  1047 					User::LeaveNoMemory();
  1048 				iHeap->Free(shape);
  1049 				shape = cached_header;
  1050 				}
  1051 			}
  1052 		}
  1053 	return shape;
  1054 	}
  1055 
  1056 
  1057 void CBitmapFont::InstallOpenFontShaper(COpenFont* aOpenFont, CShaper::TInput& aShaperInput)
  1058 	{
  1059 	CShaper* shaper = NULL;
  1060 	const CArrayPtrFlat<CShaperFactory>* shaperFactoryList = aOpenFont->File()->GetFontStore()->ShaperFactoryList();
  1061 
  1062 	TInt factoryCount = shaperFactoryList->Count();
  1063 	for (TInt index = 0; index < factoryCount; index++)
  1064 		{
  1065 		TRAPD(err, shaper = (*shaperFactoryList)[index]->NewShaperL(this,
  1066 				aShaperInput.iScript, aShaperInput.iLanguage,  iHeap));
  1067 		if (err == KErrNone)
  1068 			{
  1069 			aOpenFont->SetShaper(shaper);
  1070 			OstTrace0( TRACE_IMPORTANT, CBITMAPFONT_INSTALLOPENFONTSHAPER, "A shaper is installed" );
  1071 			break;
  1072 			}
  1073 		}
  1074 	}
  1075 
  1076 
  1077 /** Frees the memory taken up as a result of shaping
  1078 @internalTechnology */
  1079 EXPORT_C void CBitmapFont::DeleteShape(TInt aSessionHandle,TShapeHeader* aHeader)
  1080 	{
  1081 	//safe to assume aHeader is never NULL?
  1082 	if (IsOpenFont())
  1083 		{
  1084 		//we just need to decrease the reference count, no deletion here
  1085 		//as the entry in cache can still be reused by other client
  1086 		//only in the case where the memory is full, the freeing will
  1087 		//delete any cache entry that is not referenced at all
  1088 		TInt ret=OpenFont()->DecrementCachedRefCount(aSessionHandle,aHeader);
  1089 		//panic in debug mode if trying to delete something that is not there.
  1090 		if ((ret != KErrNone) && (ret != KErrNotFound))
  1091 		    {
  1092 		    OstTrace1( TRACE_FATAL, CBITMAPFONT_DELETESHAPE, "OpenFont()->DecrementCachedRefCount() return %d, Invariant", ret);
  1093 		    __ASSERT_DEBUG(0, User::Invariant());
  1094 		    }
  1095 		}
  1096 	}
  1097 
  1098 EXPORT_C void CBitmapFont::operator delete(TAny *aThis)
  1099 	{
  1100 	if (((CBitmapFont *)aThis)->iHeap)
  1101 		((CBitmapFont *)aThis)->iHeap->Free(aThis);
  1102 	}
  1103 
  1104 TInt CBitmapFont::Width(TInt aNum) const
  1105 	{
  1106 	TInt widthfactor=iAlgStyle.WidthFactor();
  1107 	return ((widthfactor==1)? aNum: aNum*widthfactor);
  1108 	}
  1109 
  1110 TInt CBitmapFont::Height(TInt aNum) const
  1111 	{
  1112 	TInt heightfactor=iAlgStyle.HeightFactor();
  1113 	return ((heightfactor==1)? aNum: aNum*heightfactor);
  1114 	}
  1115 
  1116 CFontBitmap* CBitmapFont::FontBitmap() const
  1117 /** This member is private and not intended for use. */
  1118 	{
  1119 	if (IsOpenFont())
  1120 	    {
  1121 	    OstTrace0( TRACE_FATAL, CBITMAPFONT_FONTBITMAP, "Panic(EFntTypefaceHasNoFontBitmaps)" );
  1122 	    __ASSERT_ALWAYS(0, Panic(EFntTypefaceHasNoFontBitmaps));
  1123 	    }
  1124     if(iFontBitmapOffset)
  1125         return reinterpret_cast<CFontBitmap*>(reinterpret_cast<TInt>(this)+iFontBitmapOffset);
  1126     else
  1127         return NULL;
  1128 	}
  1129 
  1130 /** Gets a font table.
  1131 @param aTag: Input. The name of the font table.
  1132 @param aTableContent: Output. To return the address of the table content.
  1133 @param aLength: Output. To return the length (in bytes) of the table.
  1134 @param aSessionHandle: Input. A handle to the session requesting this table.
  1135 @return KErrNone on success, specific error code on failure.
  1136 @internalTechnology
  1137 */
  1138 EXPORT_C TInt CBitmapFont::GetFontTable(TUint32 aTag, TAny *&aTableContent, 
  1139         TInt &aLength, TInt aSessionHandle) 
  1140     {
  1141     COpenFont *fontPtr = NULL;
  1142     if (IsOpenFont())
  1143         fontPtr = OpenFont();
  1144     else
  1145         return KErrNotSupported;
  1146     
  1147     // try to find it in cache.
  1148     CFontStore *fntStore = fontPtr->File()->GetFontStore();
  1149     TUid fileUid = fontPtr->File()->Uid();
  1150     TInt ret = fntStore->FindFontTableInCache(fileUid, aTag, aTableContent, aLength);
  1151     if (KErrNone == ret)
  1152         {
  1153         ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
  1154         return ret;
  1155         }
  1156     
  1157     // font table not found in cache.
  1158     ret = fontPtr->GetFontTable(aTag, aTableContent, aLength);
  1159     if (KErrNone == ret)
  1160         {
  1161         ret = fntStore->CacheFontTable(fileUid, aTag, aTableContent, aLength);
  1162         if (KErrNone == ret)
  1163             {
  1164             ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle);
  1165             }
  1166         else 
  1167             {
  1168             aTableContent = NULL;
  1169             }
  1170         }
  1171     
  1172     return ret;
  1173     }
  1174 
  1175 /** Release a font table. Decrement its reference count. Remove from cache if 
  1176  * reference decreases to zero.
  1177 @param aTag: Input. The name of the font table to be released.
  1178 @param aSessionHandle: Input. Handle to the session releasing this table.
  1179 @return KErrNone on success, specific error code on failure.
  1180 @internalTechnology
  1181 */
  1182 EXPORT_C void CBitmapFont::ReleaseFontTable(TUint32 aTag, 
  1183         TInt aSessionHandle)
  1184     {
  1185     COpenFont *fontPtr = NULL;
  1186     if (IsOpenFont())
  1187         fontPtr = OpenFont();
  1188     else
  1189         return;
  1190     
  1191     CFontStore *fntStore = fontPtr->File()->GetFontStore();
  1192     TUid fileUid = fontPtr->File()->Uid();
  1193     fntStore->ReleaseFontTable(fileUid, aTag, aSessionHandle);
  1194     }
  1195 
  1196 
  1197 /** Release a number of glyph outlines. Decrement their reference count.
  1198  * Remove it from cache if reference count decreases to zero.
  1199 @param aCount: Input. Number of outlines to be released.
  1200 @param aCodes: Input. An array of codes. Its interpretation depends on the parameter
  1201     'aIsGlyphId' (see below).
  1202 @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCodes' is an array of glyph ID's.
  1203     When aIsGlyphId==EFalse, 'aCodes' is an array of Unicode values.
  1204 @param aHinted: Input. To indicate if the outlines are hinted or unhinted.
  1205 @param aSessionHandle: Input. Handle to the session releasing the outlines.
  1206 @return KErrNone on success, specific error code on failure.
  1207 @internalTechnology
  1208 */
  1209 EXPORT_C void CBitmapFont::ReleaseGlyphOutlines(TInt aCount, const TUint *aCodes, 
  1210         TBool aHinted, TInt aSessionHandle)
  1211     {
  1212     COpenFont *fontPtr = NULL;
  1213         if (IsOpenFont())
  1214             fontPtr = OpenFont();
  1215         else
  1216             return;
  1217     
  1218     CFontStore *fontStore = fontPtr->File()->GetFontStore();
  1219     
  1220     for (TInt i = 0; i < aCount; ++i)
  1221         {
  1222         if (aHinted)
  1223             {
  1224             THintedOutlineId outlineId(fontPtr, aCodes[i]);
  1225             fontStore->ReleaseHintedOutline(outlineId, aSessionHandle);
  1226             }
  1227         else
  1228             {
  1229             TInt faceId = fontPtr->FaceIndex();
  1230             TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCodes[i]);
  1231             fontStore->ReleaseUnhintedOutline(outlineId, aSessionHandle);
  1232             }
  1233         }
  1234     }
  1235 
  1236 /** Gets a font table.
  1237 @param aCode: Input. An glyph code. Its interpretation depends on the parameter
  1238     'aIsGlyphId' (see below).
  1239 @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCode' is a glyph ID.
  1240     When aIsGlyphId==EFalse, 'aCode' is a Unicode values.
  1241 @param aHinted: Input. To indicate if hinted or unhinted outline is needed.
  1242 @param aOutline: Output. A 'void*' pointer, pointing to the outline in memory.
  1243 @param aLength: Output. A TInt, recording the lenght (in bytes) of the outline.
  1244 @param aSessionHandle: Input. Handle to the session requesting this outline.
  1245 @return KErrNone on success, specific error code on failure.
  1246 @internalTechnology
  1247 */
  1248 EXPORT_C TInt CBitmapFont::GetGlyphOutline(TUint aCode, 
  1249         TBool aHinted, TAny *&aOutline, TInt &aLength, TInt aSessionHandle)
  1250     {
  1251     COpenFont *fontPtr = NULL;
  1252         if (IsOpenFont())
  1253             fontPtr = OpenFont();
  1254         else
  1255             return KErrNotSupported;
  1256     
  1257     CFontStore *fontStore = fontPtr->File()->GetFontStore();
  1258     TAny *outlineData = NULL; 
  1259     TInt len = KErrGeneral;
  1260     TInt ret = KErrNone;
  1261     if (!aHinted)
  1262         {
  1263         TInt faceId = fontPtr->FaceIndex();
  1264         TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCode);
  1265         ret = fontStore->FindUnhintedOutlineInCache(outlineId, outlineData, len);
  1266         if (KErrNotFound == ret)
  1267             {
  1268             TAny* tmpOutline = 0; 
  1269             TInt tmpLen = 0;
  1270             ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
  1271             if (KErrNone == ret)
  1272                 {
  1273                 fontStore->CacheUnhintedOutline(outlineId,
  1274                         tmpOutline, (TInt)tmpLen, outlineData, len);
  1275                 }
  1276             User::Free(tmpOutline);
  1277             }
  1278         if (KErrNone == ret)
  1279             {
  1280             fontStore->IncreaseUnhintedOutlineRefCount(outlineId, aSessionHandle);
  1281             }
  1282         }
  1283     else 
  1284         {
  1285         THintedOutlineId outlineId(fontPtr, aCode);
  1286         ret = fontStore->FindHintedOutlineInCache(outlineId, outlineData, len);
  1287         if (KErrNotFound == ret)
  1288             {
  1289             TAny* tmpOutline = 0; 
  1290             TInt tmpLen = 0;
  1291             ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen);
  1292             if (KErrNone == ret)
  1293                 {
  1294                 fontStore->CacheHintedOutline(outlineId,
  1295                         tmpOutline, (TInt)tmpLen, outlineData, len);
  1296                 }
  1297             User::Free(tmpOutline);
  1298             }
  1299         if (KErrNone == ret)
  1300             {
  1301             fontStore->IncreaseHintedOutlineRefCount(outlineId, aSessionHandle);
  1302             }
  1303         }
  1304     
  1305     aOutline = outlineData;
  1306     aLength = len;    
  1307     return KErrNone;
  1308     }
  1309 
  1310 EXPORT_C TUint32 CBitmapFont::UniqueFontId()
  1311 	{
  1312 	return iUniqueFontId;
  1313 	}
  1314 
  1315 void CBitmapFont::SetUniqueFontId(TUint32 aUniqueFontId)
  1316 	{
  1317 	iUniqueFontId = aUniqueFontId;	
  1318 	}
  1319 
  1320 /** API extension system that enables the caller to access a particular API
  1321 extension function. As an overload of this function in a derived class
  1322 it calls its immediate parent implementation for any extension function Uid
  1323 that it does not recognize and handle.
  1324 @param aInterfaceId UID of the required extension function
  1325 @param aParam Pointer to an arbitrary parameter block that can be used to
  1326 provide and/or return information to/from the particular extension function,
  1327 defaults to NULL.
  1328 @return Integer return value from extension function
  1329 @internalTechnology
  1330 @released
  1331 */
  1332 EXPORT_C TInt CBitmapFont::DoExtendedFunction(TUid aFunctionId, TAny* aParam) const
  1333 	{
  1334 	if (KFontCapitalAscent == aFunctionId)
  1335 		{
  1336 		return Height(IsOpenFont() ? OpenFont()->FontCapitalAscent() : FontBitmap()->FontCapitalAscent());
  1337 		}
  1338 	else if (KFontMaxAscent == aFunctionId)
  1339 		{
  1340 		return Height(IsOpenFont() ? OpenFont()->FontMaxAscent() : FontBitmap()->FontMaxAscent());
  1341 		}
  1342 	else if (KFontStandardDescent == aFunctionId)
  1343 		{
  1344 		return Height(IsOpenFont() ? OpenFont()->FontStandardDescent() : FontBitmap()->FontStandardDescent());
  1345 		}
  1346 	else if (KFontMaxDescent == aFunctionId)
  1347 		{
  1348 		return Height(IsOpenFont() ? OpenFont()->FontMaxDescent() : FontBitmap()->FontMaxDescent());
  1349 		}
  1350 	else if (KFontLineGap == aFunctionId)
  1351 		{
  1352 		return Height(IsOpenFont() ? OpenFont()->FontLineGap() : FontBitmap()->FontLineGap());
  1353 		}
  1354 	
  1355 	return CFont::DoExtendedFunction(aFunctionId, aParam);
  1356 	}
  1357 
  1358 
  1359 CFontTableCacheItem::CFontTableCacheItem(TUid &aFileUid, const TUint32 aTag, 
  1360         TInt aOffset, TInt aLength): iFileUid(aFileUid), iTag(aTag),
  1361         iOffset(aOffset), iLength(aLength)
  1362     {
  1363     // a null constructor
  1364     }
  1365 
  1366 CFontTableCacheItem::~CFontTableCacheItem()
  1367     {
  1368     iUsers.ResetAndDestroy();
  1369     iUsers.Close();
  1370     }
  1371     
  1372 TBool CFontTableCacheItem::HasOutstandingRefCount()
  1373     {
  1374     TInt count = iUsers.Count();
  1375     for (TInt j = 0; j < count; ++j)
  1376         {
  1377         if (iUsers[j]->iRefCount > 0) 
  1378             {
  1379             return ETrue;
  1380             }
  1381         }
  1382     return EFalse;
  1383     }
  1384 
  1385 
  1386 TInt CFontTableCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
  1387     {
  1388     TInt len = iUsers.Count();
  1389     for (TInt i = 0; i < len; ++i)
  1390         {
  1391         if (aSessionHandle == iUsers[i]->iSessionHandle)
  1392             {
  1393             *id = i;
  1394             return KErrNone;
  1395             }
  1396         }
  1397     return KErrNotFound;
  1398     }
  1399 
  1400 TInt CFontTableCacheItem::DecRefCount(TInt aSessionHandle)
  1401     {
  1402     TInt id = 0; 
  1403     TInt ret = FindUser(aSessionHandle, &id);
  1404     if (KErrNone == ret)
  1405         {
  1406         iUsers[id]->iRefCount--;
  1407         if (0 == iUsers[id]->iRefCount) 
  1408             {
  1409             delete iUsers[id];
  1410             iUsers.Remove(id);
  1411             }
  1412         return iUsers.Count();
  1413         }
  1414     return KErrNotFound;
  1415     }
  1416 
  1417 TInt CFontTableCacheItem::IncRefCount(TInt aSessionHandle)
  1418     {
  1419     TInt id = 0; 
  1420     TInt ret = FindUser(aSessionHandle, &id);
  1421     if (KErrNone == ret)
  1422         {
  1423         iUsers[id]->iRefCount++;
  1424         }
  1425     else
  1426         {
  1427         TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
  1428         if (NULL != newUser)
  1429             {
  1430             TRAP(ret, iUsers.AppendL(newUser));
  1431             }
  1432         else 
  1433             {
  1434             ret = KErrNoMemory;
  1435             }
  1436         //coverity[leaked_storage]
  1437         // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount(). 
  1438         }
  1439     return ret;
  1440     }
  1441 
  1442 TInt CFontTableCache::Append(TUid aFileUid, TUint32 aTag, 
  1443         TAny *&aContent, TInt aLength) 
  1444     {
  1445     TInt ret = 0;
  1446     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
  1447         {
  1448         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
  1449         return KErrNoMemory;
  1450         }
  1451     // make a copy of the table content on the shared heap.
  1452     TAny *sharedCopy = iHeap->Alloc(aLength);
  1453     if (NULL == sharedCopy) 
  1454         {
  1455         return KErrNoMemory;
  1456         }
  1457     
  1458     Mem::Copy(sharedCopy, aContent, aLength);
  1459 
  1460     CFontTableCacheItem *newItem = NULL;
  1461     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
  1462     TRAP(ret, newItem = new(ELeave) CFontTableCacheItem(aFileUid, aTag, offset, aLength));
  1463     if (KErrNone != ret)
  1464         {
  1465         iHeap->Free(sharedCopy);
  1466         return ret;
  1467         }
  1468     
  1469     TRAP(ret, iCacheItems.AppendL(newItem));
  1470     if (KErrNone == ret)
  1471         {
  1472         // do not free 'aContent', because the mem is managed by
  1473         // rasterizer cache.
  1474         aContent = sharedCopy;
  1475         iCacheMemMon.Inc(aLength);
  1476         }
  1477     else 
  1478         {
  1479         iHeap->Free(sharedCopy);
  1480         }
  1481 #ifdef _DEBUG
  1482     GetCacheState(__func__);
  1483 #endif
  1484     return ret;
  1485     }
  1486 
  1487 TInt CFontTableCache::Find(TUid aFileUid, TUint32 aTag, TAny *&aContent, 
  1488         TInt &aLength, TInt *id)
  1489     {
  1490     *id = KErrNotFound;
  1491     TInt len = iCacheItems.Count();
  1492     
  1493     TInt ret = KErrNotFound;
  1494     for (TInt i = 0; i < len; ++i)
  1495         {
  1496         CFontTableCacheItem *item = iCacheItems[i]; 
  1497         if (item->iFileUid == aFileUid && item->iTag == aTag) 
  1498             {
  1499             aContent = OffsetToPointer(item->iOffset, iHeap->Base());
  1500             aLength = item->iLength;
  1501             *id = i;
  1502             ret = KErrNone;
  1503             break;
  1504             }
  1505         }
  1506     
  1507 #ifdef _DEBUG
  1508     GetCacheState(__func__);
  1509 #endif
  1510     return ret;
  1511     }
  1512 
  1513 CFontTableCache::CFontTableCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): 
  1514     iCacheMemMon(aMon), iHeap(aHeap) 
  1515     {
  1516     // null constructor
  1517     }
  1518 
  1519 CFontTableCache::~CFontTableCache()
  1520     {
  1521     for (TInt i = 0; i < iCacheItems.Count(); ++i)
  1522         {
  1523         iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
  1524         }
  1525     iCacheItems.ResetAndDestroy();
  1526     iCacheItems.Close();
  1527     }
  1528 
  1529 TInt CFontTableCache::IncRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
  1530     {
  1531     TAny *outline = NULL;
  1532     TInt len = 0;
  1533     TInt id = 0;
  1534     
  1535     TInt ret = Find(aFileUid, aTag, outline, len, &id);
  1536     if (KErrNone == ret)
  1537         {
  1538         ret = iCacheItems[id]->IncRefCount(aSessionHandle);
  1539         }
  1540     
  1541 #ifdef _DEBUG
  1542     GetCacheState(__func__);
  1543 #endif
  1544     return ret;
  1545     }
  1546 
  1547 TInt CFontTableCache::DecRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle)
  1548     {
  1549     TAny *outline = NULL;
  1550     TInt len = 0;
  1551     TInt id = 0;
  1552     
  1553     TInt ret = Find(aFileUid, aTag, outline, len, &id);
  1554     if (KErrNone == ret) 
  1555         {
  1556         TInt numUsers = iCacheItems[id]->DecRefCount(aSessionHandle);
  1557         if (0 == numUsers) 
  1558             {
  1559             // There is no outstanding reference to the cache item.
  1560             iHeap->Free(outline);
  1561             iCacheMemMon.Dec(len);
  1562             delete (iCacheItems[id]);
  1563             iCacheItems.Remove(id);
  1564             }
  1565         }
  1566     
  1567 #ifdef _DEBUG
  1568     GetCacheState(__func__);
  1569 #endif
  1570     return ret;
  1571     }
  1572 
  1573 TBool CFontTableCache::HasOutstandingRefCount() 
  1574     {
  1575     TInt len = iCacheItems.Count();
  1576    
  1577     for (TInt i = 0; i < len; ++i)
  1578         {
  1579         if (iCacheItems[i]->HasOutstandingRefCount())
  1580             {
  1581             return ETrue;
  1582             }
  1583         }
  1584     return EFalse;
  1585     }
  1586 
  1587 TBool CFontTableCache::HasOutstandingRefCountWithUid(TUid aFileUid)
  1588     {
  1589     TInt len = iCacheItems.Count();
  1590    
  1591     for (TInt i = 0; i < len; ++i)
  1592         {
  1593         if (iCacheItems[i]->iFileUid == aFileUid) 
  1594             {
  1595             if (iCacheItems[i]->HasOutstandingRefCount())
  1596                 {
  1597                 return ETrue;
  1598                 }
  1599             }
  1600         }
  1601     return EFalse;
  1602     }
  1603 
  1604 void CFontTableCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *)
  1605     {
  1606     // In CFontStore::RemoveFile(), a font file is not allowed to be removed if
  1607     // there are outstanding ref counts on any table in it. If that check passed 
  1608     // and this function is called, there shall be no cache item for that file.
  1609     
  1610     // Currently a cache item having a refcount of 0 is removed immediately.
  1611     // If this strategy is changed in the future, we may need to do some
  1612     // cleanup here.
  1613     }
  1614 
  1615 void CFontTableCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
  1616     {
  1617     TInt len = iCacheItems.Count();
  1618    
  1619     for (TInt i = 0; i < len; ++i)
  1620         {
  1621         TInt id = -1;
  1622         if (KErrNone == iCacheItems[i]->FindUser(aSessionHandle, &id))
  1623             {
  1624             iCacheItems[i]->iUsers.Remove(id);
  1625             if (iCacheItems[i]->iUsers.Count() == 0)
  1626                 {
  1627                 iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base()));
  1628                 iCacheMemMon.Dec(iCacheItems[i]->iLength);
  1629                 delete iCacheItems[i];
  1630                 iCacheItems.Remove(i);
  1631                 }
  1632             }
  1633         }
  1634     }
  1635 
  1636 
  1637 #ifdef _DEBUG
  1638 TInt CFontTableCache::GetCacheState(const char *func) 
  1639     {
  1640     RDebug::Printf("%s called from %s: ", __func__, func);
  1641     TBuf<256> buf;
  1642     
  1643     int len = iCacheItems.Count();
  1644     int numTables = 0, numSessions = 0, totalRef = 0;
  1645     buf.Append(_L("Table cache: "));
  1646     for (int i = 0; i < len; ++i)
  1647         {
  1648         ++numTables;
  1649         TInt abc = iCacheItems[i]->iUsers.Count();
  1650         numSessions += abc;
  1651         for (int j = 0; j < abc; ++j)
  1652             {
  1653             totalRef += iCacheItems[i]->iUsers[j]->iRefCount;
  1654             }
  1655         }
  1656     if (0 == iCacheItems.Count())
  1657         {
  1658         buf.Append(_L("cache empty. "));
  1659         }
  1660     else 
  1661         {
  1662         buf.AppendFormat(_L("%d tables referenced by %d sessions, total ref count %d"),
  1663                 numTables, numSessions, totalRef);
  1664         }
  1665     RDebug::RawPrint(buf);
  1666     return 0;
  1667     }
  1668 #endif
  1669 
  1670 
  1671 
  1672 TInt COutlineCacheItem::FindUser(TInt aSessionHandle, TInt *id) 
  1673     {
  1674     TInt len = iUsers.Count();
  1675     for (TInt i = 0; i < len; ++i)
  1676         {
  1677         if (aSessionHandle == iUsers[i]->iSessionHandle)
  1678             {
  1679             *id = i;
  1680             return KErrNone;
  1681             }
  1682         }
  1683     return KErrNotFound;
  1684     }
  1685 
  1686 COutlineCacheItem::~COutlineCacheItem() 
  1687     { 
  1688     iUsers.ResetAndDestroy(); 
  1689     }
  1690 
  1691 COutlineCacheItem::COutlineCacheItem(TInt aOffset, TInt aLength):
  1692     iOffset(aOffset), iLength(aLength)
  1693     {
  1694     // a null constructor.
  1695     }
  1696 
  1697 TInt COutlineCacheItem::DecRefCount(TInt aSessionHandle)
  1698     {
  1699     TInt id = 0; 
  1700     TInt ret = FindUser(aSessionHandle, &id);
  1701     if (KErrNone == ret)
  1702         {
  1703         iUsers[id]->iRefCount--;
  1704         if (0 == iUsers[id]->iRefCount) 
  1705             {
  1706             delete iUsers[id];
  1707             iUsers.Remove(id);
  1708             }
  1709         return iUsers.Count();
  1710         }
  1711     return KErrNotFound;
  1712     }
  1713 
  1714 TInt COutlineCacheItem::IncRefCount(TInt aSessionHandle)
  1715     {
  1716     TInt id = 0; 
  1717     TInt ret = FindUser(aSessionHandle, &id);
  1718     if (KErrNone == ret)
  1719         {
  1720         iUsers[id]->iRefCount++;
  1721         }
  1722     else
  1723         {
  1724         TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1);
  1725         if (NULL != newUser)
  1726             {
  1727             TRAP(ret, iUsers.AppendL(newUser));
  1728             }
  1729         else 
  1730             {
  1731             ret = KErrNoMemory;
  1732             }
  1733         //coverity[leaked_storage]
  1734         // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount().
  1735         }
  1736     return ret;
  1737     }
  1738 
  1739 #ifdef _DEBUG
  1740 TInt CUnhintedOutlineCache::GetCacheState(const char *func)
  1741     {
  1742     RDebug::Printf("%s called from %s: ", __func__, func);
  1743     int numSessions = 0, totalRef = 0;
  1744     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  1745     it.NextValue();
  1746     while (it.CurrentValue())
  1747         {
  1748         COutlineCacheItem **data = it.CurrentValue();
  1749         int len = (*data)->iUsers.Count();
  1750         numSessions += len;
  1751         for (int j = 0; j < len; ++j)
  1752             {
  1753             totalRef += (*data)->iUsers[j]->iRefCount;
  1754             }
  1755         it.NextValue();
  1756         }
  1757     
  1758     TBuf<256> buf;
  1759     buf.Append(_L("Unhinted outline cache: "));
  1760     TInt numItems = iItemIdMap.Count();
  1761     if (0 == numItems)
  1762         {
  1763         buf.Append(_L("empty. "));
  1764         }
  1765     else 
  1766         {
  1767         buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
  1768                 numItems, numSessions, totalRef);
  1769         }
  1770         
  1771     RDebug::RawPrint(buf);
  1772             
  1773     return 0;
  1774     }
  1775 #endif
  1776 
  1777 CUnhintedOutlineCache::CUnhintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
  1778     iCacheMemMon(aMon), iHeap(aHeap), 
  1779     iItemIdMap(THashFunction32<TUnhintedOutlineId>(CUnhintedOutlineCache::IdHash),
  1780         TIdentityRelation<TUnhintedOutlineId>(CUnhintedOutlineCache::IdIdentity))
  1781     { 
  1782     
  1783     }
  1784 
  1785 CUnhintedOutlineCache::~CUnhintedOutlineCache()
  1786     {
  1787     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  1788     it.NextValue();
  1789     while (it.CurrentValue())
  1790         {
  1791         const TUnhintedOutlineId *outlineId = it.CurrentKey();
  1792         COutlineCacheItem **data = it.CurrentValue();
  1793         
  1794         // loop body here!
  1795         iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  1796         delete (*data);
  1797         iItemIdMap.Remove(*outlineId);
  1798         // end loop body
  1799         
  1800         it.NextValue();
  1801         }
  1802     return;
  1803     }
  1804 
  1805 
  1806 TInt CUnhintedOutlineCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile)
  1807     {
  1808     TUid fileUid = aFontFile->Uid();
  1809     
  1810     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  1811     it.NextValue();
  1812     while (it.CurrentValue())
  1813         {
  1814         const TUnhintedOutlineId *outlineId = it.CurrentKey();
  1815         COutlineCacheItem **data = it.CurrentValue();
  1816         
  1817         // loop body here!
  1818         if (outlineId->iFileUid == fileUid)
  1819             {
  1820             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  1821             iCacheMemMon.Dec((*data)->iLength);
  1822             delete (*data);
  1823             iItemIdMap.Remove(*outlineId);
  1824             }
  1825         // end loop body
  1826         
  1827         it.NextValue();
  1828         }
  1829     return KErrNone;
  1830     }
  1831 
  1832 TInt CUnhintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
  1833     {
  1834     THashMapIter<TUnhintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  1835     it.NextValue();
  1836     while (it.CurrentValue())
  1837         {
  1838         const TUnhintedOutlineId *outlineId = it.CurrentKey();
  1839         COutlineCacheItem **data = it.CurrentValue();
  1840         
  1841         // loop body here!
  1842         TInt id = 0;
  1843         TInt ret = (*data)->FindUser(aSessionHandle, &id);
  1844         if (KErrNone == ret)
  1845             {
  1846             delete (*data)->iUsers[id];
  1847             (*data)->iUsers.Remove(id);
  1848             if (0 == (*data)->iUsers.Count())
  1849                 {
  1850                 iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  1851                 iCacheMemMon.Dec((*data)->iLength);
  1852                 delete (*data);
  1853                 iItemIdMap.Remove(*outlineId);
  1854                 }
  1855             }
  1856         // end loop body
  1857         
  1858         it.NextValue();
  1859         }
  1860     return KErrNone;
  1861     }
  1862 
  1863 
  1864 TInt CUnhintedOutlineCache::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
  1865         TAny* const aData, const TInt aLength, TAny *&aOutline, TInt &aLen)
  1866     {
  1867 #ifdef _DEBUG
  1868     GetCacheState(__func__);
  1869 #endif
  1870     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
  1871         {
  1872         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
  1873         return KErrNoMemory;
  1874         }
  1875     
  1876     aLen = KErrGeneral;
  1877     TInt ret1= KErrNone;
  1878 
  1879     // make a copy of the outline data on the shared heap.
  1880     TAny *sharedCopy = iHeap->Alloc(aLength);
  1881     if (NULL == sharedCopy) 
  1882         {
  1883         return KErrNoMemory;
  1884         }
  1885     
  1886     Mem::Copy(sharedCopy, aData, aLength);
  1887 
  1888     COutlineCacheItem *newItem = NULL;
  1889     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
  1890     TRAP(ret1, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
  1891     if (KErrNone != ret1)
  1892         {
  1893         iHeap->Free(sharedCopy);
  1894         sharedCopy = NULL;
  1895         }
  1896     else 
  1897         {
  1898         TRAP(ret1, iItemIdMap.InsertL(aOutlineId, newItem));
  1899         if (KErrNone != ret1)
  1900             {
  1901             delete newItem;
  1902             iHeap->Free(sharedCopy);
  1903             sharedCopy = NULL;
  1904             }
  1905         else
  1906             {
  1907             iCacheMemMon.Inc(aLength);
  1908             aLen = aLength;
  1909             }
  1910         }
  1911     aOutline = sharedCopy;
  1912     return ret1;  
  1913     }
  1914 
  1915 TInt CUnhintedOutlineCache::IncRefCount(const TUnhintedOutlineId &aOutlineId,
  1916         TInt aSessionHandle)
  1917     {
  1918 #ifdef _DEBUG
  1919     GetCacheState(__func__);
  1920 #endif
  1921     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
  1922     if (NULL != ret)
  1923         {
  1924         (*ret)->IncRefCount(aSessionHandle);
  1925         }
  1926     return (NULL==ret?KErrNotFound:KErrNone);
  1927     }
  1928 
  1929 TInt CUnhintedOutlineCache::DecRefCount(const TUnhintedOutlineId &aOutlineId,
  1930         TInt aSessionHandle)
  1931     {
  1932 #ifdef _DEBUG
  1933     GetCacheState(__func__);
  1934 #endif
  1935     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); 
  1936     if (NULL != ret) 
  1937         {
  1938         TInt numUsers = (*ret)->DecRefCount(aSessionHandle);
  1939         if (0 == numUsers) 
  1940             {
  1941             // There is no outstanding reference to the cache item.
  1942             iHeap->Free(OffsetToPointer((*ret)->iOffset, iHeap->Base()));
  1943             iCacheMemMon.Dec((*ret)->iLength);
  1944             delete (*ret);
  1945             iItemIdMap.Remove(aOutlineId);
  1946             }
  1947         }
  1948     return (NULL==ret?KErrNotFound:KErrNone);
  1949     }
  1950 
  1951 TInt CUnhintedOutlineCache::Find(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
  1952         TInt &aLength)
  1953     {
  1954     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
  1955     TInt ret2 = KErrNone;
  1956     if (NULL != ret)
  1957         {
  1958         aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
  1959         aLength = (*ret)->iLength;
  1960         }
  1961     else
  1962         {
  1963         ret2 = KErrNotFound;
  1964         }
  1965     return ret2;
  1966     }
  1967     
  1968   
  1969 TUint32 CUnhintedOutlineCache::IdHash(const TUnhintedOutlineId &outlineId)
  1970     {
  1971     // The hash value: 
  1972     // bits 0-15: glyph id; 
  1973     // bits 16-23: lower 8 bit of font file uid
  1974     // bits 24-27: lower 4 bit of the face index
  1975     // bit 28: 'isGlyphId'
  1976     TUint32 ret = 0;
  1977     ret |= (outlineId.iId & KOutlineGlyphIdHashMask);
  1978     ret |= (KOutlineFileUidHashMask & (outlineId.iFileUid.iUid << 16));
  1979     ret |= (KOutlineFaceIndexHashMask & (outlineId.iFaceIndex << 24));
  1980     ret = (ret % 701);
  1981     return ret;
  1982     }
  1983 
  1984 TBool CUnhintedOutlineCache::IdIdentity(const TUnhintedOutlineId &id1, const TUnhintedOutlineId &id2)
  1985     {
  1986     return id1.iId == id2.iId && id1.iFaceIndex == id2.iFaceIndex &&
  1987             id1.iFileUid == id2.iFileUid;
  1988     }
  1989 
  1990 // hinted outline cache
  1991 #ifdef _DEBUG
  1992 TInt CHintedOutlineCache::GetCacheState(const char *func)
  1993     {
  1994     RDebug::Printf("%s called from %s: ", __func__, func);
  1995     int numSessions = 0, totalRef = 0;
  1996     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  1997     it.NextValue();
  1998     while (it.CurrentValue())
  1999         {
  2000         COutlineCacheItem **data = it.CurrentValue();
  2001         int len = (*data)->iUsers.Count();
  2002         numSessions += len;
  2003         for (int j = 0; j < len; ++j)
  2004             {
  2005             totalRef += (*data)->iUsers[j]->iRefCount;
  2006             }
  2007         it.NextValue();
  2008         }
  2009     
  2010     TBuf<256> buf;
  2011     buf.Append(_L("Hinted outline cache: "));
  2012     TInt numItems = iItemIdMap.Count();
  2013     if (0 == numItems)
  2014         {
  2015         buf.Append(_L("empty. "));
  2016         }
  2017     else 
  2018         {
  2019         buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"),
  2020                 numItems, numSessions, totalRef);
  2021         }
  2022         
  2023     RDebug::RawPrint(buf);
  2024             
  2025     return 0;
  2026     }
  2027 #endif
  2028 
  2029 TInt CHintedOutlineCache::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
  2030     {
  2031     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  2032     it.NextValue();
  2033     while (it.CurrentValue())
  2034         {
  2035         const THintedOutlineId *outlineId = it.CurrentKey();
  2036         COutlineCacheItem **data = it.CurrentValue();
  2037         
  2038         // loop body here!
  2039         if (outlineId->iFont == aFont)
  2040             {
  2041             iCacheMemMon.Dec((*data)->iLength);
  2042             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  2043             delete (*data);
  2044             iItemIdMap.Remove(*outlineId);
  2045             }
  2046         // end loop body
  2047         
  2048         it.NextValue();
  2049         }
  2050     return KErrNone;
  2051     }
  2052 
  2053 TInt CHintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
  2054     {
  2055     THashMapIter<THintedOutlineId, COutlineCacheItem*> it(iItemIdMap);
  2056     it.NextValue();
  2057     while (it.CurrentValue())
  2058         {
  2059         const THintedOutlineId *outlineId = it.CurrentKey();
  2060         COutlineCacheItem **data = it.CurrentValue();
  2061         
  2062         // loop body here!
  2063         TInt id = 0; 
  2064         TInt ret = (*data)->FindUser(aSessionHandle, &id);
  2065         if (KErrNone == ret)
  2066             {
  2067             delete (*data)->iUsers[id];
  2068             (*data)->iUsers.Remove(id);
  2069             if (0 == (*data)->iUsers.Count())
  2070                 {
  2071                 iCacheMemMon.Dec((*data)->iLength);
  2072                 iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  2073                 delete (*data);
  2074                 iItemIdMap.Remove(*outlineId);
  2075                 }
  2076             }
  2077         // end loop body
  2078         
  2079         it.NextValue();
  2080         }
  2081 
  2082     return KErrNone;
  2083     }
  2084 
  2085 
  2086 CHintedOutlineCache::CHintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon):
  2087     iCacheMemMon(aMon), iHeap(aHeap), 
  2088     iItemIdMap(THashFunction32<THintedOutlineId>(CHintedOutlineCache::IdHash),
  2089         TIdentityRelation<THintedOutlineId>(CHintedOutlineCache::IdIdentity)) 
  2090     { 
  2091     // a null constructor
  2092     }
  2093 
  2094 TInt CHintedOutlineCache::CacheHintedOutline(const THintedOutlineId &aOutlineId,
  2095         TAny* aData, TInt aLength, TAny *&aOutline, TInt &aLen)
  2096     {
  2097 #ifdef _DEBUG
  2098     GetCacheState(__func__);
  2099 #endif
  2100     if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem)
  2101         {
  2102         RDebug::Printf("Table/Glyph cache full. Unable to add new item.");
  2103         return KErrNoMemory;
  2104         }
  2105     
  2106     aLen = KErrGeneral;
  2107     TInt ret = KErrNone;
  2108     // make a copy of the outline data on the shared heap.
  2109     TAny *sharedCopy = iHeap->Alloc(aLength);
  2110     if (NULL == sharedCopy) 
  2111         {
  2112         return KErrNoMemory;
  2113         }
  2114     
  2115     Mem::Copy(sharedCopy, aData, aLength);
  2116 
  2117     COutlineCacheItem *newItem = NULL;
  2118     TInt offset = PointerToOffset(sharedCopy, iHeap->Base());
  2119     TRAP(ret, newItem = new(ELeave) COutlineCacheItem(offset, aLength));
  2120     if (KErrNone != ret)
  2121         {
  2122         iHeap->Free(sharedCopy);
  2123         sharedCopy = NULL;
  2124         }
  2125     else 
  2126         {
  2127         TRAP(ret, iItemIdMap.InsertL(aOutlineId, newItem));
  2128         if (KErrNone != ret)
  2129             {
  2130             delete newItem;
  2131             iHeap->Free(sharedCopy);
  2132             sharedCopy = NULL;
  2133             }
  2134         else
  2135             {
  2136             iCacheMemMon.Inc(aLength);
  2137             aLen = aLength;
  2138             }
  2139         }
  2140     aOutline = sharedCopy;
  2141     return ret;
  2142     }
  2143 
  2144 TInt CHintedOutlineCache::IncRefCount(const THintedOutlineId &aOutlineId, 
  2145         TInt aSessionHandle)
  2146     {
  2147 #ifdef _DEBUG
  2148     GetCacheState(__func__);
  2149 #endif
  2150     COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
  2151     if (NULL != data)
  2152         {
  2153         (*data)->IncRefCount(aSessionHandle);
  2154         }
  2155     return (NULL==data?KErrNotFound:KErrNone);
  2156     }
  2157 
  2158 TInt CHintedOutlineCache::DecRefCount(const THintedOutlineId &aOutlineId,
  2159         TInt aSessionHandle)
  2160     {
  2161 #ifdef _DEBUG
  2162     GetCacheState(__func__);
  2163 #endif
  2164     COutlineCacheItem **data = iItemIdMap.Find(aOutlineId);
  2165     if (NULL != data) 
  2166         {
  2167         TInt numUsers = (*data)->DecRefCount(aSessionHandle);
  2168         if (0 == numUsers) 
  2169             {
  2170             // There is no outstanding reference to the cache item.
  2171             iCacheMemMon.Dec((*data)->iLength);
  2172             iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base()));
  2173             delete (*data);
  2174             iItemIdMap.Remove(aOutlineId);
  2175             }
  2176         }
  2177     return (NULL==data?KErrNotFound:KErrNone);
  2178     }
  2179 
  2180 TInt CHintedOutlineCache::Find(const THintedOutlineId &aOutlineId, 
  2181         TAny *&aData, TInt &aLength)
  2182     {
  2183     COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId);
  2184     TInt ret2 = KErrNone;
  2185     if (NULL != ret)
  2186         {
  2187         aData = OffsetToPointer((*ret)->iOffset, iHeap->Base());
  2188         aLength = (*ret)->iLength;
  2189         }
  2190     else
  2191         {
  2192         ret2 = KErrNotFound;
  2193         }
  2194     return ret2;
  2195     }
  2196 
  2197 
  2198 TUint32 CHintedOutlineCache::IdHash(const THintedOutlineId &outlineId)
  2199     {
  2200     // The hash value:
  2201     // bits 0-15: the outline id
  2202     // bits 16-27: the lower 12 bits of the font pointer
  2203     // bit 28: 'isGlyphId'
  2204     
  2205     TUint32 ret = 0;
  2206     ret |= (KOutlineGlyphIdHashMask & outlineId.iId);
  2207     ret |= (KOutlineFontPtrHashMask & (((TUint32)outlineId.iFont) << 16));
  2208     ret = ret % 701;
  2209     return ret;
  2210     }
  2211 
  2212 TBool CHintedOutlineCache::IdIdentity(const THintedOutlineId &id1, const THintedOutlineId &id2)
  2213     {
  2214     return id1.iId == id2.iId && id1.iFont == id2.iFont;
  2215     }
  2216 // hinted cache
  2217 
  2218 
  2219 CFontStore::CFontStore(RHeap* aHeap):
  2220 	iKPixelWidthInTwips(KDefaultPixelWidthInTwips),
  2221 	iKPixelHeightInTwips(KDefaultPixelHeightInTwips),
  2222 	iFs(),
  2223 	iHeap(aHeap),
  2224 	iFontStoreFileList(KDefaultArrayGranularity),			// list of EPOC Bitmap font files loaded
  2225 	iTypefaceList(KDefaultArrayGranularity),
  2226 	iFontBitmapList(KDefaultArrayGranularity),
  2227 	iTypefaceFontBitmapList(KDefaultArrayGranularity),
  2228 	iOpenFontFileList(KDefaultArrayGranularity),			// list of 'Open Font' files loaded
  2229 	iOpenFontRasterizerList(KDefaultArrayGranularity),		// open rasterizers, in load order
  2230 	iOpenFontUid(1),
  2231 	iDefaultBitmapType(EMonochromeGlyphBitmap),
  2232 	iShaperFactoryList(KDefaultArrayGranularity),
  2233 	iOpenFontShaperCacheMemUsage(0),
  2234 	iNumberOfShaperCaches(0),
  2235 	iOpenFontTypefaceSupportList(KDefaultArrayGranularity),	// list of Open Font typefaces available
  2236 	iUniqueFontIdCount(0)									// used to give every font a unique id
  2237 	{
  2238 	}
  2239 
  2240 void CFontStore::ConstructL()
  2241 	{
  2242 	// Cache is placed in the shared heap
  2243 	iOpenFontSessionCacheList = (COpenFontSessionCacheList*)iHeap->AllocL(sizeof(COpenFontSessionCacheList));
  2244 	new(iOpenFontSessionCacheList) COpenFontSessionCacheList;
  2245 
  2246 	CTypefaceStore::ConstructL();
  2247 	User::LeaveIfError(iFs.Connect());
  2248 
  2249 	TMachineInfoV1Buf machineInfoBuffer;
  2250 	User::LeaveIfError(UserHal::MachineInfo(machineInfoBuffer));
  2251 
  2252 	const TSize twipSize = machineInfoBuffer().iPhysicalScreenSize;
  2253 	const TSize pixelSize = machineInfoBuffer().iDisplaySizeInPixels;
  2254 
  2255 	if (twipSize.iWidth > 0 && pixelSize.iWidth > 0)
  2256 		iKPixelWidthInTwips = twipSize.iWidth * 1000 / pixelSize.iWidth;
  2257 
  2258 	if (twipSize.iHeight > 0 && pixelSize.iHeight > 0)
  2259 		iKPixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight;
  2260 	
  2261 	iCacheMemMon = new(ELeave) TFontTableGlyphOutlineCacheMemMonitor;
  2262 	iUnhintedOutlineCache = new(ELeave) CUnhintedOutlineCache(iHeap, *iCacheMemMon);
  2263 	iHintedOutlineCache = new(ELeave) CHintedOutlineCache(iHeap, *iCacheMemMon);
  2264 	iFontTableCache = new(ELeave) CFontTableCache(iHeap, *iCacheMemMon);
  2265 	
  2266 	}
  2267 
  2268 /** Creates a new CFontStore object.
  2269 
  2270 Sets iKPixelWidthInTwips and iKPixelHeightInTwips.
  2271 
  2272 Sets the default bitmap type, used when getting bitmap fonts, to EMonochromeGlyphBitmap.
  2273 
  2274 Also initialises other private member variable values .
  2275 
  2276 @param aHeap A pointer to the heap class used for memory allocation.
  2277 @leave KErrNoMemory Insufficient memory available on the heap. */
  2278 EXPORT_C CFontStore *CFontStore::NewL(RHeap* aHeap)
  2279 	{
  2280 	User::LeaveIfNull(aHeap);
  2281 	CFontStore *fontstore = new(ELeave) CFontStore(aHeap);
  2282 	CleanupStack::PushL(fontstore);
  2283 	fontstore->ConstructL();
  2284 	CleanupStack::Pop(fontstore);
  2285 	return fontstore;
  2286 	}
  2287 
  2288 /** Destructor. */
  2289 EXPORT_C CFontStore::~CFontStore()
  2290 	{
  2291 	// Remove All font files, and Reset associated arrays
  2292 	RemoveFile(KNullUid);
  2293 	iOpenFontRasterizerList.ResetAndDestroy();
  2294 	iShaperFactoryList.ResetAndDestroy();
  2295 	if (iOpenFontSessionCacheList)
  2296 		{
  2297 		iOpenFontSessionCacheList->Delete(iHeap);
  2298 		iHeap->Free(iOpenFontSessionCacheList);
  2299 		}
  2300 	iFs.Close();
  2301 	
  2302     delete iFontTableCache;
  2303     delete iUnhintedOutlineCache;
  2304     delete iHintedOutlineCache;
  2305     delete iCacheMemMon;
  2306 	}
  2307 
  2308 
  2309 // local utility functions
  2310 // reads bytes from file, if the requested number of bytes are not available it leaves
  2311 void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength)
  2312 	{
  2313 	User::LeaveIfError(aFile.Read(aDes, aLength));
  2314 	if (aDes.Length() != aLength)
  2315 		{
  2316 		OstTrace0( TRACE_DUMP, _READFROMFILEL, "EOF reading structure from font file, Leave(KErrCorrupt)" );
  2317 		User::Leave(KErrCorrupt);
  2318 		}
  2319 	}
  2320 
  2321 // local function(s) to read values from buffer & validate them
  2322 TUint TtfTableTagFromBufferL(TDes8& aDes)
  2323 	{
  2324 	TUint value = 0;
  2325 	for (TUint index = 0; index < 4;)
  2326 		{
  2327 		TUint temp = static_cast<TUint>(aDes[index++]);
  2328 		// must be ASCII character between 32 & 126 inclusive (per Apple's TTF specification document)
  2329 		if ( (temp < 32) || (temp > 126) )
  2330 			{
  2331 			OstTrace1( TRACE_DUMP, _TTFTABLETAGFROMBUFFERL, "invalid ASCII character (0x%x) in ttf table tag, Leave(KErrCorrupt)", temp);
  2332 			User::Leave(KErrCorrupt);
  2333 			}
  2334 		value = (value << 8) | temp;
  2335 		}
  2336 	return value;
  2337 	}
  2338 
  2339 /* Sanity check for TrueType Font, checks that the font tables are sensible.
  2340 */
  2341 void CFontStore::SanityCheckForTtfL(RFile& aFontFile, TUint aFontFileSize, TBool aStrictChecking)
  2342 	{
  2343 	OstTraceExt2( TRACE_DUMP, CFONTSTORE_SANITYCHECKFORTTFL, "TTF File Size is %u (0x%x) bytes", aFontFileSize, aFontFileSize );
  2344 	// check the Offset Table at the start of the file
  2345 	TBuf8<16>	fileBuffer;
  2346 
  2347 	ReadFromFileL(aFontFile, fileBuffer, 12);
  2348 	TUint numTables = (fileBuffer[4] << 8) | (fileBuffer[5]);
  2349 	TUint searchRange = (fileBuffer[6] << 8) | (fileBuffer[7]);
  2350 	TUint entrySelector = (fileBuffer[8] << 8) | (fileBuffer[9]);
  2351 	TUint rangeShift = (fileBuffer[10] << 8) | (fileBuffer[11]);
  2352 
  2353 	const TInt tableStart = 12 + (numTables << 4);	// lowest possible address for actual table data
  2354 
  2355 	if ( (numTables == 0) || (numTables & 0xF0000000) || (tableStart > aFontFileSize) )
  2356 		{
  2357 		OstTrace1( TRACE_DUMP, DUP1_CFONTSTORE_SANITYCHECKFORTTFL, "# of tables (%d) in ttf is invalid, Leave(KErrCorrupt)", numTables );
  2358 		User::Leave(KErrCorrupt);
  2359 		}
  2360 
  2361 #if defined(_DEBUG) && defined(VERBOSE_DEBUG)
  2362 	// scalar type is 0x00010000 for Windows fonts, other possible values include 0x74727565 and 0x74797031: not checked
  2363 	TUint scalarType = (fileBuffer[0] << 24) | (fileBuffer[1] << 16) | (fileBuffer[2] << 8) | (fileBuffer[3]);
  2364 	RDebug::Print(_L("ttf scalarType is 0x%x, # of tables is %u\n"), scalarType, numTables);
  2365 	RDebug::Print(_L("searchRange is 0x%x, entrySelector is 0x%x, rangeShift is 0x%x\n"), 
  2366 		searchRange, entrySelector, rangeShift);
  2367 #endif
  2368 
  2369 	// check searchRange, entrySelector & rangeShift values
  2370 	// (some not quite TTF files fail the rangeShift check)
  2371 	if ( (searchRange < 16) || (entrySelector > 24)
  2372 		|| (aStrictChecking && (rangeShift != ( (numTables << 4) - searchRange )) ) )
  2373 		{
  2374 		OstTraceExt4( TRACE_DUMP, DUP2_CFONTSTORE_SANITYCHECKFORTTFL, "searchRange (0x%x), entrySelector (0x%x) or rangeShift (0x%x) invalid for numTables (%d), Leave(KErrCorrupt)", 
  2375 		        searchRange, entrySelector, rangeShift, numTables );
  2376 		User::Leave(KErrCorrupt);
  2377 		}
  2378 
  2379 	// entrySelector is defined as Log2(Maximum power of 2 <= nmumTables)
  2380 	TUint exp = 1 << entrySelector;		// log to exponent
  2381 	if ( (numTables < exp) || (numTables > (exp << 1)) )
  2382 		{
  2383 		OstTraceExt2( TRACE_DUMP, DUP3_CFONTSTORE_SANITYCHECKFORTTFL, "entrySelector (0x%x) wrong for numTables(%d), Leave(KErrCorrupt)", 
  2384 		        entrySelector, numTables );
  2385 		User::Leave(KErrCorrupt);
  2386 		}
  2387 
  2388 	// easy checks on the table directory
  2389 	TInt totalFontSize = tableStart;				// accumulated total directories plus table sizes
  2390 	TInt highestTableEnd = 0;						// highest value found for table start plus table length
  2391 	TUint lastTableTag = 0;							// to check that tags are in order
  2392 	TInt tableNum = 0;
  2393 
  2394 	do 
  2395 		{ // each entry is 16 bytes, (though we don't check the checksum)
  2396 		ReadFromFileL(aFontFile, fileBuffer, 16);
  2397 		TUint tableTag = TtfTableTagFromBufferL(fileBuffer);
  2398 		TUint offset = (fileBuffer[8] << 24) | (fileBuffer[9] << 16) | (fileBuffer[10] << 8) | (fileBuffer[11]);
  2399 		TUint length = (fileBuffer[12] << 24) | (fileBuffer[13] << 16) | (fileBuffer[14] << 8) | (fileBuffer[15]);
  2400 
  2401 #if defined(_DEBUG) && defined(VERBOSE_DEBUG)
  2402 		RDebug::Print(_L("ttf table tag ('%c%c%c%c'): offset is 0x%x, length is 0x%x\n"), 
  2403 			tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F, 
  2404 			offset, length);
  2405 #endif
  2406 		length = (length + 3) & ~3;	// round up, all tables must be a multiple of 4 bytes for checksumming
  2407 
  2408 		// table Tags must be unique & in order
  2409 		if (tableTag <= lastTableTag)
  2410 			{
  2411 			OstTraceExt4( TRACE_DUMP, DUP4_CFONTSTORE_SANITYCHECKFORTTFL, "ttf table tag ('%c%c%c%c') is out of order, Leave(KErrCorrupt)",
  2412 			        tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F);
  2413 			User::Leave(KErrCorrupt);
  2414 			}
  2415 
  2416 
  2417 		// the offset must be 4-byte aligned, and after the table directory
  2418 		// offset + length must be bigger than the start offset (!)
  2419 		TInt end = length + offset;
  2420 		if ( (offset & 3) || (offset < tableStart) || (length == 0) || (end < offset) || (end > aFontFileSize))
  2421 			{
  2422 			OstTraceExt2( TRACE_DUMP, DUP5_CFONTSTORE_SANITYCHECKFORTTFL, "offset (0x%x) or length (0x%x) are bad, Leave(KErrCorrupt)",
  2423 			        offset, length );
  2424 			User::Leave(KErrCorrupt);
  2425 			}
  2426 
  2427 		lastTableTag = tableTag;
  2428 		totalFontSize += length;
  2429 		if (end > highestTableEnd)
  2430 			{
  2431 			highestTableEnd = end;
  2432 			}
  2433 		}
  2434 		while (++tableNum < numTables);
  2435 
  2436 #if defined(_DEBUG) && defined(VERBOSE_DEBUG)
  2437 	RDebug::Print(_L("last address used by any table is 0x%x, Minimum font file size to hold all tables is 0x%x\n"), 
  2438 			highestTableEnd, totalFontSize);
  2439 #endif
  2440 
  2441 	// for single font files highestTableEnd & totalFontSize should be the same
  2442 	if (highestTableEnd != totalFontSize)
  2443 		{
  2444 		OstTraceExt2( TRACE_DUMP, DUP6_CFONTSTORE_SANITYCHECKFORTTFL, "Total Font Size (0x%x) is different from end of the last table (0x%x), Leave(KErrCorrupt)",
  2445 		        highestTableEnd, totalFontSize);
  2446 		User::Leave(KErrCorrupt);
  2447 		}
  2448 	}
  2449 
  2450 /* Sanity checks on font files, currently only knows about TrueType Font files: .ttf and .otf
  2451 Protects FBserv / the client and the rasterizer plug-in from grossly corrupt data.
  2452 @leave KErrCorrupt if the font tables are daft
  2453 */
  2454 void CFontStore::SanityCheckFontFileL(TParse& aParse)
  2455 	{
  2456 
  2457 	// try to open the file and getting the file size
  2458 	RFile fontFile;
  2459 	const TInt openError = fontFile.Open(iFs, aParse.FullName(), EFileRead | EFileShareReadersOnly);
  2460 #ifdef _DEBUG
  2461 	if (KErrNone != openError)
  2462 		{
  2463 		const TDesC& fileName = aParse.FullName();
  2464 		RDebug::Print(_L("Sanity checking font file \"%S\", file open gave error %d\n"), &fileName, openError);
  2465 		}
  2466 #endif
  2467 	User::LeaveIfError(openError);
  2468 	CleanupClosePushL(fontFile);
  2469 	TInt fontFileSize = 0;
  2470 	User::LeaveIfError(fontFile.Size(fontFileSize));
  2471 
  2472 	if (fontFileSize == 0)
  2473 		{ // no font can be zero length!
  2474 #ifdef _DEBUG
  2475 		RDebug::Print(_L("font file size (%i) is zero\n"), fontFileSize);
  2476 #endif
  2477 		User::Leave(KErrCorrupt);
  2478 		}
  2479 	else
  2480 		{
  2481 		const TDesC& fileExt = aParse.Ext();
  2482 		// TrueType fonts
  2483 		_LIT(KFntStoreTrueTypeExtension,".ttf");
  2484 		// OpenType fonts
  2485 		_LIT(KFntStoreOpenTypeExtension,".otf");
  2486 		// other font files that follow TTF format
  2487 		_LIT(KFntStoreCccFontFileExtension,".ccc");
  2488 
  2489 		if ( (0 == fileExt.CompareF(KFntStoreTrueTypeExtension)) || (0 == fileExt.CompareF(KFntStoreOpenTypeExtension)) )
  2490 			{ // uses TrueType file format, perform strict format check
  2491 			SanityCheckForTtfL(fontFile, fontFileSize, ETrue);
  2492 			}
  2493 		else if (0 == fileExt.CompareF(KFntStoreCccFontFileExtension))
  2494 			{ // uses nearly TrueType file format, perform slightly less strict format check
  2495 			SanityCheckForTtfL(fontFile, fontFileSize, EFalse);
  2496 			}
  2497 
  2498 		// extendible if required for other font file types ...
  2499 		}
  2500 
  2501 	CleanupStack::PopAndDestroy(&fontFile);
  2502 	}
  2503 
  2504 
  2505 /** Finds or creates a font file object to support a font file. The specified font
  2506 file must be accessible to any process, i.e. not located inside an
  2507 application's private directory.
  2508 
  2509 If an appropriate font file object exists then no new open font file is created. 
  2510 In this case the reference count of the font file object is incremented.
  2511 
  2512 Notes:
  2513 
  2514 If aName is recognised as an open font file, creates a COpenFontFile, which 
  2515 will manage the font file specified by aName, and adds it to the file store's 
  2516 list of open font files.
  2517 
  2518 The list of open font files is used when getting the nearest font for a font 
  2519 specification (i.e. by the GetNearestFont...() functions of this class) if 
  2520 the font is generated via a rasterizer.
  2521 
  2522 The appropriate rasterizer, which supports the font format of the font file, 
  2523 is used to generate the open font file using COpenFontRasterizer::NewFontFileL().
  2524 
  2525 If aName is not recognised as an open font file then CFontStoreFile tries to open
  2526 the file as a Symbian Bitmap font.
  2527 
  2528 @param aName The full path and filename of the font file to be supported.
  2529 @return The UID of the font file object supporting aName.
  2530 @leave KErrNotSupported if the file is not recognised at all
  2531 @leave KErrCorrupt if the font file data does not make sense
  2532 @leave or another system-wide error
  2533 */
  2534 EXPORT_C TUid CFontStore::AddFileL(const TDesC& aName)
  2535 	{
  2536 	TParse fontFilename;
  2537 	User::LeaveIfError(iFs.Parse(aName, fontFilename));
  2538 
  2539 	// increment reference count if font file is already loaded
  2540 	TUid fontUid = KNullUid;
  2541 
  2542 	if (IncRefCountOfLoadedFont(fontFilename, fontUid))
  2543 		{
  2544 		return fontUid;
  2545 		}
  2546 
  2547 	// Do not validate fonts on Z: (assumed to be ROM created with valid fonts)
  2548 	if (!FileIsOnZ(fontFilename))
  2549 		{
  2550 		// file is not open - check that the file exists and has a plausible content
  2551 		SanityCheckFontFileL(fontFilename);
  2552 		}
  2553 	
  2554 	AddSanityCheckedFontL(fontFilename, fontUid);
  2555 	
  2556 	return fontUid;
  2557 	}
  2558 
  2559 /**
  2560 Finds or creates a font file object to support a font file.
  2561 @param aFileName The filename to check
  2562 @param aUid The list to check
  2563 @see CFontStore::AddFileL
  2564 */
  2565 void CFontStore::AddSanityCheckedFontL(const TParse& aFileName, TUid& aUid)
  2566 	{
  2567 	// Try loading the file as an Open Font
  2568 	if (!LoadFileAsOpenFontL(aFileName, aUid))
  2569 		{
  2570 		// It could not be recognised as an Open Font file so load it as an EPOC bitmap font file.
  2571 		// (This always succeeds or Leaves.)
  2572 		aUid = LoadFileAsBitmapFontL(aFileName);
  2573 		}
  2574 	}
  2575 
  2576 
  2577 // Remove a Font File - called via the Cleanup Stack if a leave occurs during font install
  2578 void CFontStore::CleanupRemoveFontFile(TAny* aCleanupInfo)
  2579 	{
  2580 	TCleanupRemoveFontFile* cleanupInfo = (TCleanupRemoveFontFile *) aCleanupInfo;
  2581 	cleanupInfo->iFontStore->RemoveFile(cleanupInfo->iFontUid);
  2582 	}
  2583 
  2584 
  2585 /** Search through the rasterizers for one that will open the font filename.
  2586 
  2587 Can leave if the rasterizer encounters an error, such as unexpected end of file, nonsense data, no memory.
  2588 
  2589 @param aName full filename to open
  2590 @param aFontUid set to the font file UID if it is already loaded
  2591 @return ETrue if the font file is loaded, otherwise EFalse
  2592 @internalComponent
  2593 */
  2594 TBool CFontStore::LoadFileAsOpenFontL(const TParse& aFileName, TUid& aFontUid)
  2595 	{
  2596 	const TDesC& fullName = aFileName.FullName();
  2597 	
  2598 	// ask each of the rasterizers in turn to create a COpenFontFile object.
  2599 	const TInt rasterizerCount = iOpenFontRasterizerList.Count();
  2600 	for (TInt index = 0; index < rasterizerCount; index++)
  2601 		{
  2602 		COpenFontFile* openFontFile = iOpenFontRasterizerList[index]->NewFontFileL(iOpenFontUid, fullName, iFs);
  2603 		if (NULL != openFontFile)
  2604 			{
  2605 			/* Uids for Open Fonts are allocated in order; the
  2606 			one for the COpenFontFile just created won't match any existing one.
  2607 			(When a file is removed, the fake Uid will match, because the one that was returned here is used.)
  2608 			*/
  2609 			CleanupStack::PushL(openFontFile);
  2610 			openFontFile->SetFontStoreL(this);
  2611 			iOpenFontFileList.AppendL(openFontFile);
  2612 			openFontFile->IncRefCount();
  2613 			CleanupStack::Pop(openFontFile);
  2614 
  2615 			TInt typefaceAddError = AddTypefacesToSupportList(openFontFile);
  2616 			if (typefaceAddError)
  2617 				{
  2618 				// cleanup
  2619 				RemoveFile(openFontFile->Uid());
  2620 				// throw the error
  2621 				User::Leave(typefaceAddError);
  2622 				}
  2623 
  2624 			/*
  2625 			iOpenFontUid is the fake Uid used for new font files. It is made modulo a 'zillion' (2^28)
  2626 			so that it cannot conflict with real Uids, which are >= 2^28. It starts at 1 so that
  2627 			it does not conflict with the value 0 (KNullUid) which is used as a sentinel in
  2628 			CFontStore::RemoveFileL.
  2629 			*/
  2630 			++iOpenFontUid;
  2631 			iOpenFontUid = iOpenFontUid % 0x1000000;
  2632 
  2633 			aFontUid = openFontFile->Uid();
  2634 			return ETrue;
  2635 			}
  2636 		}
  2637 	return EFalse;
  2638 	}
  2639 
  2640 
  2641 /** Search loaded fonts for filename, and increment the reference count
  2642 @param aParse full filename to search for
  2643 @return the font file UID
  2644 @leave KErrNotSupported or another system wide error code
  2645 @internalComponent
  2646 */
  2647 TUid CFontStore::LoadFileAsBitmapFontL(const TParse& aParse)
  2648 	{
  2649 	// open the file, presuming it is a bitmap font
  2650 	CFontStoreFile* fontStoreFile = CFontStoreFile::NewL(aParse, iFs);
  2651 
  2652 	// See if a font with this UID is already open
  2653 	TInt match = FindBitmapFontFileIndexByUid(fontStoreFile->iCollectionUid);
  2654 	if (match != KErrNotFound) // The file is open.
  2655 		{ // close the new duplicate, inc the reference count
  2656 		delete fontStoreFile;
  2657 		fontStoreFile = iFontStoreFileList[match];
  2658 		fontStoreFile->iUsageCount++;
  2659 		}
  2660 	else
  2661 		{
  2662 		CleanupStack::PushL(fontStoreFile);
  2663 		iFontStoreFileList.AppendL(fontStoreFile);
  2664 		CleanupStack::Pop(fontStoreFile);
  2665 
  2666 		// special object to removes the font file if a leave occurs during font install
  2667 		TCleanupRemoveFontFile cleanupHelper(this, fontStoreFile->iCollectionUid);
  2668 		CleanupStack::PushL(TCleanupItem(CleanupRemoveFontFile, &cleanupHelper));
  2669 		// install the new font
  2670 		InternalizeFontStoreFileL(fontStoreFile, fontStoreFile->iFontVersion);
  2671 		CleanupStack::Pop(&cleanupHelper); // CleanupRemoveFontFile
  2672 		}
  2673 	return fontStoreFile->iCollectionUid;
  2674 	}
  2675 
  2676 
  2677 /** Search open Bitmap font files for matching UID
  2678 @param aUid UID to search for
  2679 @return The index of the matching item in iFontStoreFileList[] array, or KErrNotFound
  2680 @internalComponent
  2681 */
  2682 TInt CFontStore::FindBitmapFontFileIndexByUid(TUid aUid)
  2683 	{
  2684 	const TInt fontFileCount = iFontStoreFileList.Count();
  2685 	for (TInt index = 0; index < fontFileCount; index++)
  2686 		{
  2687 		if (iFontStoreFileList[index]->iCollectionUid == aUid)
  2688 			{
  2689 			return index;
  2690 			}
  2691 		}
  2692 	return KErrNotFound;
  2693 	}
  2694 
  2695 
  2696 /** Search loaded fonts for filename, and increment the reference count
  2697 @param aName full filename to search for
  2698 @param aFontUid set to the font file UID if it is already loaded
  2699 @return ETrue if the font file is already loaded, otherwise EFalse
  2700 @internalComponent
  2701 */
  2702 TBool CFontStore::IncRefCountOfLoadedFont(const TParse& aFileName, TUid& aFontUid)
  2703 	{
  2704 	const TDesC& fullName = aFileName.FullName();
  2705 	
  2706 	// Is it already in the Open Font list? Compare by full filename, not (fake) Uid;
  2707 	const TInt openFontCount = iOpenFontFileList.Count();
  2708 	TInt i = 0;
  2709 	for (i = 0; i < openFontCount; ++i)
  2710 		{
  2711 		COpenFontFile* openFontFile = iOpenFontFileList[i];
  2712 		if (fullName.CompareF(openFontFile->FileName()) == 0)
  2713 			{
  2714 			// Open Font file already loaded
  2715 			openFontFile->IncRefCount();
  2716 			aFontUid = openFontFile->Uid();
  2717 			return ETrue;
  2718 			}
  2719 		}
  2720 
  2721 	// already open as an EPOC bitmap font file?
  2722 	const TInt fontFileCount = iFontStoreFileList.Count();
  2723 	for (i = 0; i < fontFileCount; i++)
  2724 		{
  2725 		CFontStoreFile* fontStoreFile = iFontStoreFileList[i];
  2726 		if (fullName.CompareF(fontStoreFile->FullName()) == 0)
  2727 			{
  2728 			// font file already loaded
  2729 			++(fontStoreFile->iUsageCount);
  2730 			aFontUid = fontStoreFile->iCollectionUid;
  2731 			return ETrue;
  2732 			}
  2733 		}
  2734 	return EFalse;
  2735 	}
  2736 
  2737 
  2738 /** Releases a hold on one or all font file objects (COpenFontFiles or CFontStoreFiles).
  2739 
  2740 If aFileUid identifies a font file object, then the reference count for this 
  2741 object is decremented. If this brings the reference count down to zero then 
  2742 the font file object and typefaces associated with this file are removed from
  2743 the font store, provided no fonts associated with this file are being accessed. 
  2744 If one or more fonts are being accessed then the file removal request will be ignored.
  2745 
  2746 If, on the other hand, aFileUid's value is NULL, then all font file objects 
  2747 are removed, along with all fonts and typefaces in the font store, provided
  2748 that no fonts in the font store are being accessed (i.e. iFontAccess is empty),
  2749 otherwise it has no effect.
  2750 
  2751 (If aFileUid is invalid, then no objects are removed.)
  2752 
  2753 @param aFileUid UID of a hold on a font file object to be released, or KNullUid
  2754 if all font file objects are to be removed.
  2755 */
  2756 EXPORT_C void CFontStore::RemoveFile(TUid aFileUid)
  2757 	{
  2758 	TInt i, count;
  2759 	if (aFileUid == KNullUid)	// this means 'delete all files'
  2760 		{
  2761 		if(iFontAccess)
  2762 			{
  2763 			TInt count = iFontAccess->Count();		
  2764 			for (TInt i = 0; i < count; i++)
  2765 				if((*iFontAccess)[i].iAccessCount)
  2766 					return;
  2767 			}
  2768 		if (iFontTableCache && iFontTableCache->HasOutstandingRefCount())
  2769 		    {
  2770 		    // disallow font file removal if any font tables are still cached
  2771 		    return;
  2772 		    }
  2773 		
  2774 		iTypefaceList.ResetAndDestroy();
  2775 		count = iFontBitmapList.Count();
  2776 		for (TInt i = 0; i < count; i++)
  2777 			iFontBitmapList[i]->Release();
  2778 		iFontBitmapList.Reset();
  2779 		iTypefaceFontBitmapList.Reset();
  2780 		iFontStoreFileList.ResetAndDestroy();
  2781 		iOpenFontFileList.ResetAndDestroy();
  2782 		iOpenFontTypefaceSupportList.ResetAndDestroy();
  2783 		}
  2784 	else
  2785 		{
  2786 		// See if it's an Open Font file.
  2787 		count = iOpenFontFileList.Count();
  2788 		for (i = 0; i < count; i++)
  2789 			{
  2790 			TInt fontAccessCount;
  2791 			if (iOpenFontFileList[i]->Uid() == aFileUid)
  2792 				{ // found the file
  2793 				if (iFontAccess)
  2794 					{ // Check to see if there are any references before we consider deleting
  2795 					fontAccessCount = iFontAccess->Count();
  2796 					for (TInt kk = 0; kk < fontAccessCount; ++kk)
  2797 						{
  2798 		  	  	  		CBitmapFont* bitmapFont = reinterpret_cast<CBitmapFont*>((*iFontAccess)[kk].iFont);
  2799 		  	  	  		COpenFont* openFont = bitmapFont->OpenFont();
  2800 		  	  	  		if (openFont && openFont->File()->Uid() == aFileUid )
  2801 		  	  	  			{
  2802 		  	  	  			if ((*iFontAccess)[kk].iAccessCount > 0) 
  2803 		  	  	  				return; // Outstanding reference found, so ignoring file removal request
  2804 		  	  	  			}
  2805 						}
  2806 					} // Safe to proceed with removing file
  2807 				// also check if there are outstanding references to any 
  2808 				// table in that file.
  2809 				if (iFontTableCache && iFontTableCache->HasOutstandingRefCountWithUid(aFileUid))
  2810 				    {
  2811 				    return; // outstanding reference to font table found.
  2812 				    }
  2813 				
  2814 				// Safe to proceed with removing file
  2815 				if (iOpenFontFileList[i]->DecRefCount())
  2816 					{ // unload the font file
  2817 					RemoveTypefacesFromSupportList(iOpenFontFileList[i]);
  2818 					//linked fonts deleted from this destructor
  2819 					delete iOpenFontFileList[i];
  2820 					iOpenFontFileList.Delete(i);
  2821 					}
  2822 				return;
  2823 				}
  2824 			}
  2825 
  2826 		// Finds first fontstorefile with correct id
  2827 		TInt index = FindBitmapFontFileIndexByUid(aFileUid);
  2828 		if (index != KErrNotFound)  //  Checks fontstore file has been found
  2829 			{
  2830 			iFontStoreFileList[index]->iUsageCount--;
  2831 			if (!iFontStoreFileList[index]->iUsageCount)
  2832 				{
  2833 				TInt tfcount = iTypefaceFontBitmapList.Count();
  2834 				for (i=tfcount-1; i>=0; i--)
  2835 					if (aFileUid == iTypefaceFontBitmapList[i].iFontBitmap->FontStoreFile()->iCollectionUid)
  2836 						iTypefaceFontBitmapList.Delete(i);
  2837 				count = iFontBitmapList.Count();
  2838 				for (i=count-1; i>=0; i--)
  2839 					{
  2840 					
  2841 					if (aFileUid==iFontBitmapList[i]->FontStoreFile()->iCollectionUid)
  2842 						{
  2843 						iFontBitmapList[i]->Release();
  2844 						iFontBitmapList.Delete(i);
  2845 						}  
  2846 					}
  2847 				count = iTypefaceList.Count();
  2848 				for (i=count-1; i>=0; i--)	
  2849 					{
  2850 					TBool inlist=EFalse;  
  2851 					tfcount = iTypefaceFontBitmapList.Count();
  2852 					for (TInt j=0; j<tfcount; j++)
  2853 						if (iTypefaceList[i] == iTypefaceFontBitmapList[j].iTypeface)
  2854 							inlist = ETrue;
  2855 					if (!inlist)
  2856 						{
  2857 						delete iTypefaceList[i];
  2858 						iTypefaceList.Delete(i);
  2859 						}
  2860 					}
  2861 				delete iFontStoreFileList[index];
  2862 				iFontStoreFileList.Delete(index);
  2863 				}
  2864 			}
  2865 		}
  2866 	}
  2867 
  2868 /**
  2869 @publishedAll
  2870 */
  2871 EXPORT_C TInt CFontStore::GetNearestFontInTwips(CFont*& aFont, const TFontSpec& aFontSpec)
  2872 	{
  2873 	return GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
  2874 	}
  2875 
  2876 /**
  2877 Gets the font which is the nearest to the given font specification.
  2878 
  2879 Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInTwips() 
  2880 yielding (virtually) the same result. However clients are strongly encouraged to use the new
  2881 @c GetNearestFontToMaxHeightInTwips() function instead. This will guarantee that every 
  2882 character within any given text string will fit within the given amount of twips, whereas the design 
  2883 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  2884 may result in cropped characters.
  2885 
  2886 @param aFont On return, contains a pointer to the nearest font.
  2887 @param aFontSpec The specification of the font to be matched.
  2888 @return KErrNone if successful; a system-wide error code otherwise.
  2889 @publishedAll
  2890 @deprecated Use GetNearestFontToDesignHeightInTwips
  2891 */
  2892 EXPORT_C TInt CFontStore::GetNearestFontInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec)
  2893 	{
  2894 	return GetNearestFontToDesignHeightInTwips(aFont, aFontSpec);
  2895 	}
  2896 
  2897 /**
  2898 @publishedAll
  2899 */
  2900 EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInTwips(CFont*& aFont, const TFontSpec& aFontSpec)
  2901 	{
  2902 	TOpenFontSpec spec(aFontSpec);
  2903 	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
  2904 	return GetNearestFontToDesignHeightInPixels(aFont, spec);
  2905 	}
  2906 
  2907 /**
  2908 Gets the font which is the nearest to the given font specification.
  2909 
  2910 This new function replaces the deprecated @c GetNearestFontInTwips() yielding (virtually) the 
  2911 same result. However clients are strongly encouraged to use the new
  2912 @c GetNearestFontToMaxHeightInTwips() function instead. This will guarantee that every 
  2913 character within any given text string will fit within the given amount of twips, whereas the design 
  2914 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  2915 may result in cropped characters.
  2916 
  2917 @param aFont On return, contains a pointer to the nearest font.
  2918 @param aFontSpec The specification of the font to be matched.
  2919 @return KErrNone if successful; a system-wide error code otherwise.
  2920 @publishedAll
  2921 @released
  2922 */
  2923 EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec)
  2924 	{
  2925 	TOpenFontSpec spec = aFontSpec;
  2926 	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
  2927 	return GetNearestFontToDesignHeightInPixels(aFont, spec);
  2928 	}
  2929 
  2930 /**
  2931 @publishedAll
  2932 */
  2933 EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInTwips(CFont*& aFont, const TFontSpec& aFontSpec, TInt aMaxHeight)
  2934 	{
  2935 	TOpenFontSpec spec(aFontSpec);
  2936 	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
  2937 	return GetNearestFontToMaxHeightInPixels(aFont, spec, VerticalTwipsToPixels(aMaxHeight));
  2938 	}
  2939 
  2940 /**
  2941 Gets the font which is the nearest to the given font specification.
  2942 
  2943 The font and bitmap server returns a pointer to the nearest matching font 
  2944 from those available. Matches to max height of font - this does its best 
  2945 to return a font that will fit within the maximum height specified (but 
  2946 note that variations due to hinting algorithms may rarely result in this 
  2947 height being exceeded by up to one pixel). Problems can also be 
  2948 encountered with bitmap fonts where the typeface exists but doesn't have 
  2949 a font small enough.
  2950 
  2951 @param aFont On return, contains a pointer to the nearest font.
  2952 @param aFontSpec The specification of the font to be matched.
  2953 @param aMaxHeight The maximum height within which the font must fit. If maximum height
  2954 is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
  2955 if equals to 1 pixel. This overrides the height specified in aFontSpec.
  2956 @return KErrNone if successful; a system-wide error code otherwise.
  2957 @publishedAll
  2958 @released
  2959 */
  2960 EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInTwips(CFont*& aFont, const TOpenFontSpec& aFontSpec, TInt aMaxHeight)
  2961 	{
  2962 	TOpenFontSpec spec = aFontSpec;
  2963 	spec.SetHeight(VerticalTwipsToPixels(spec.Height()));
  2964 	return GetNearestFontToMaxHeightInPixels(aFont, spec, VerticalTwipsToPixels(aMaxHeight));
  2965 	}
  2966 
  2967 
  2968 /** Local utility method to compare two font specs; the higher the return value, the better the match.
  2969 It is not clear how to reliably test for symbol fonts or language coverage because some
  2970 TOpenFontSpecs are created from bitmap TFontSpecs that do not have this info
  2971 */
  2972 TInt MatchFontSpecsInPixels(
  2973 	const TOpenFontSpec&	aCandidateFontSpec,
  2974 	const TOpenFontSpec&	aIdealFontSpec,
  2975 	TInt					aCandidateMaxHeight,
  2976 	TInt					aIdealMaxHeight)
  2977 	{
  2978 	// scores for matching (or similar) font attributes:
  2979 	const TInt KFontMatchScoreForName = 10;
  2980 	// favour fonts with heights closer together 
  2981 	const TInt KFontMaxScoreForHeight = 10;
  2982 	// A match on both italic-ness and presence of forward slant factor is worth 2 points.
  2983 	const TInt KFontMatchScoreForExactItalicAndSlant = 2;
  2984 	// A match between italic-ness in one font and presence of forward slant factor in the other is worth 1 point.
  2985 	const TInt KFontSimilarScoreForItalicAndSlant = 1;
  2986 	const TInt KFontMatchScoreForBold = 2;
  2987 	const TInt KFontMatchScoreForBitmapType = 2;
  2988 	// A match between outline or shadow effect in one font with other is worth 2 points. Its same as matching for bitmaptype.
  2989 	const TInt KFontMatchScoreForOutlineOrShadow = 2;
  2990 	// The monospaced/proportional status is rated higher at 3 because it has a major effect on the look and layout
  2991 	const TInt KFontMatchScoreForMonoSpace = 3;
  2992 	// Whether the font is serifed or not has a smaller effect on the look and layout so it is only rated at 1
  2993 	const TInt KFontMatchScoreForSerif = 1;
  2994 
  2995 	TInt score = 0;
  2996 
  2997 	// Favour perfect name and height matches.	
  2998 	if (0 == aCandidateFontSpec.Name().CompareF(aIdealFontSpec.Name()))
  2999 		{
  3000 		score += KFontMatchScoreForName;
  3001 		}
  3002 
  3003 	// Check for max height if given, otherwise height in font spec
  3004 	TInt height_diff = 0;
  3005 	if (aCandidateMaxHeight && aIdealMaxHeight)
  3006 		{
  3007 		if (aIdealMaxHeight < aCandidateMaxHeight)
  3008 			return 0;
  3009 		height_diff = aIdealMaxHeight - aCandidateMaxHeight;
  3010 		}
  3011 	else
  3012  		{
  3013 		height_diff = aIdealFontSpec.Height() - aCandidateFontSpec.Height();
  3014 		if (0 > height_diff)
  3015 			height_diff = -height_diff;
  3016 		}
  3017 	score += KFontMaxScoreForHeight - height_diff;
  3018 
  3019 	if (aCandidateFontSpec.IsItalic() == aIdealFontSpec.IsItalic() &&
  3020 		(0 < aCandidateFontSpec.SlantFactor()) == (0 < aIdealFontSpec.SlantFactor()))
  3021 		{
  3022 		score += KFontMatchScoreForExactItalicAndSlant;
  3023 		}
  3024 	else if ((aCandidateFontSpec.IsItalic() && 0 < aIdealFontSpec.SlantFactor()) ||
  3025 			 (aIdealFontSpec.IsItalic() && 0 < aCandidateFontSpec.SlantFactor()))
  3026 		{
  3027 		score += KFontSimilarScoreForItalicAndSlant;
  3028 		}
  3029 
  3030 	if (aCandidateFontSpec.IsBold() == aIdealFontSpec.IsBold())
  3031 		{
  3032 		score += KFontMatchScoreForBold;
  3033 		}
  3034 	
  3035 	TUint effectsFlag = aIdealFontSpec.Effects() & aCandidateFontSpec.Effects();
  3036 	TBool isShadowOutlineEffects = EFalse;
  3037 
  3038 	if(effectsFlag & FontEffect::EOutline)
  3039 		{
  3040 		score += KFontMatchScoreForOutlineOrShadow;
  3041 		isShadowOutlineEffects = ETrue;
  3042 		}
  3043 	if(effectsFlag & FontEffect::EDropShadow)
  3044 		{
  3045 		score += KFontMatchScoreForOutlineOrShadow;
  3046 		isShadowOutlineEffects = ETrue;
  3047 		}
  3048 		
  3049 	//Match for bitmap glyph type only when effects are off.
  3050 	//BitmapType in aIdealFontSpec will be set to EFourColourBlendGlyphBitmap by rasterizer only
  3051 	//when any of the effects (outline/shadow) are on and if it supports outline and shadow fonts.
  3052 	if(!isShadowOutlineEffects && (aCandidateFontSpec.BitmapType() == aIdealFontSpec.BitmapType()))
  3053 		{
  3054 		score += KFontMatchScoreForBitmapType;
  3055 		}
  3056 	if (aCandidateFontSpec.IsMonoWidth() == aIdealFontSpec.IsMonoWidth())
  3057 		{
  3058 		score += KFontMatchScoreForMonoSpace;
  3059 		}
  3060 	if (aCandidateFontSpec.IsSerif() == aIdealFontSpec.IsSerif())
  3061 		{
  3062 		score += KFontMatchScoreForSerif;
  3063 		}
  3064 
  3065 	return score;
  3066 	}
  3067 
  3068 
  3069 /**
  3070 Find and load the nearest Open Font by
  3071 1. using aDesiredFontSpec to check if its already loaded,
  3072 2. using aActualFontSpec to partially match	and create a new font.
  3073 Partial match means typeface name must match, other attributes need not match.
  3074 Font must fit vertically within the specified max height if given.
  3075 
  3076 @param aFont Output, is the returned font.
  3077 @param aActualFontSpec Output, is used to represent the returned font and changed to twips. 
  3078 @param aDesiredFontSpec Input, the desired font specification
  3079 @param aMaxHeight Input, the maximum height in Pixels, or 0
  3080 @post if any Open Fonts are available this will always return something
  3081 */
  3082 void CFontStore::GetNearestOpenFontInPixelsL(
  3083 	CFont*&					aFont,
  3084 	TOpenFontSpec&			aActualFontSpec,
  3085 	const TOpenFontSpec&	aDesiredFontSpec,
  3086 	TInt					aMaxHeight)
  3087 	{
  3088 	// Set the baseline offset appropriately for superscript or subscript.
  3089 	TAlgStyle algstyle;
  3090 	algstyle.iBaselineOffsetInPixels = BaselineOffset(aActualFontSpec.Height(), aActualFontSpec.PrintPosition());
  3091 
  3092 	// Determine if an open font with a perfect match is already loaded.
  3093 	if (IsFontLoaded(aFont, algstyle, aDesiredFontSpec, aMaxHeight))
  3094 		{
  3095 		aActualFontSpec = aDesiredFontSpec;
  3096 		}
  3097 	else
  3098 		{ // If not, find the nearest match for aActualFontSpec.
  3099 		COpenFont* nearestFont = NULL;
  3100 
  3101 		// fast search, if DO_LOADFONT_OPTIMIZATION is defined, search loaded font names for match
  3102 		TInt errorName=GetNearestOpenFontInPixelsByFontName(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight);
  3103 		TInt errorSimilar=KErrNone;
  3104 
  3105 		if (!nearestFont)
  3106 			{
  3107 			errorSimilar=GetNearestOpenFontInPixelsBySimilarity(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight);
  3108 			}
  3109 
  3110 		// If an imperfect match was found, is it already loaded? If not, create a new CBitmapFont.
  3111 		if (nearestFont)
  3112 			{
  3113 			//
  3114 			// Results of everything above are stored in nearestFont, and aActualFontSpec
  3115 			// First check if the not-exactly-matched font is already loaded
  3116 			// aMaxHeight is 0 to prevent duplicate CBitmapFontObjects being created
  3117 			//
  3118 			if (IsFontLoaded(aFont, algstyle, aActualFontSpec, 0))
  3119 				{
  3120 				delete nearestFont;
  3121 				}
  3122 			else
  3123 				{
  3124 				// Set the specification of the nearest match in twips.
  3125 				TOpenFontSpec openFontSpec(aActualFontSpec);
  3126 				openFontSpec.SetHeight(VerticalPixelsToTwips(openFontSpec.Height()));
  3127 				CleanupStack::PushL(nearestFont);
  3128 				aFont = NewFontL(openFontSpec, algstyle, nearestFont);
  3129 				CleanupStack::Pop(nearestFont);
  3130 				}
  3131 			}
  3132 		else
  3133 			{
  3134 			User::LeaveIfError(errorSimilar);
  3135 			User::LeaveIfError(errorName);
  3136 			}
  3137 		}
  3138 	}
  3139 
  3140 
  3141 /** Using the Desired Font Name try to find a matching font.
  3142 
  3143 @param aNearestOpenFont Output, nearest matching open font
  3144 @param aActualFontSpec Output, is used to represent the returned font 
  3145 @param aDesiredFontSpec Input, the desired font specification
  3146 @param aMaxHeight Input, the maximum height in Pixels, or 0
  3147 */
  3148 #if(DO_LOADFONT_OPTIMIZATION)
  3149 TInt CFontStore::GetNearestOpenFontInPixelsByFontName(
  3150 	COpenFont*&				aOpenFont,
  3151 	TOpenFontSpec&			aActualFontSpec,
  3152 	const TOpenFontSpec&	aDesiredFontSpec,
  3153 	TInt					aMaxHeight)
  3154 	{
  3155 	TOpenFontSpec actualFontSpec;
  3156 	COpenFont* nearestFont = NULL;
  3157 
  3158 	if (aMaxHeight == 0 && aDesiredFontSpec.Name().Length() > 0)	// check if it is a request for OpenFont
  3159 		{
  3160 		TPtrC requestedName = aDesiredFontSpec.Name();
  3161 		// Typeface files may contain all those typefaces in a family, or may contain only some.
  3162 		// The optimization first tries the ShortFullName of the typeface in case the typefaces are
  3163 		// put into separate files.
  3164 		
  3165 		// First check FullName. The following assumes that there are never two COpenFontFiles in the 
  3166 		// list with the same ShortFullName. So italic and bold flags are not checked.
  3167 
  3168 		const TInt openFontFileCount = iOpenFontFileList.Count();
  3169 		TInt index;
  3170 		TInt typicalError = KErrNone;
  3171 		for (index = 0; index < openFontFileCount; index++)
  3172 			{
  3173 			COpenFontFile *pFile = iOpenFontFileList[index]; 
  3174 			const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0);
  3175 			
  3176 			// Use short names. They are truncated to the same length as the request in TTypeface
  3177 			if ((faceAttrib.ShortFullName().CompareF(requestedName)==0) &&
  3178 				(faceAttrib.IsBold() == aActualFontSpec.IsBold()) &&
  3179 				(faceAttrib.IsItalic() == aActualFontSpec.IsItalic()) )			
  3180 				{
  3181 				TInt error=pFile->GetNearestFontToDesignHeightInPixels(
  3182 					iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
  3183 					iKPixelHeightInTwips, nearestFont, actualFontSpec);				
  3184 
  3185 				// search has finished if a match was found
  3186 				if (nearestFont)
  3187 					{
  3188 					// need to copy the actual to the value that is going to be used down below
  3189 					// to make a new font
  3190 					aOpenFont = nearestFont;
  3191 					aActualFontSpec = actualFontSpec;
  3192 					return KErrNone;
  3193 					}
  3194 				else
  3195 					{
  3196 					if (error)
  3197 						{
  3198 						typicalError=error;
  3199 						}
  3200 					}
  3201 				}
  3202 			}
  3203 
  3204 		// If the FullName match above has failed, then the request is being made by
  3205 		// something other than a full name (assuming typeface is present).
  3206 		// Although there may be more than one typeface in a file,
  3207 		// It is not possible to conclude that ALL typefaces of the family are in one file.
  3208 		// So to be safe, checks are made on italic and bold, possibly downgrading the optimization.
  3209 		// Use short names. They are truncated to the same length as the request in TTypeface
  3210 		for (index = 0; index < openFontFileCount; index++)
  3211 			{
  3212 			COpenFontFile *pFile = iOpenFontFileList[index]; 
  3213 			const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0);
  3214 
  3215 			if(	(faceAttrib.ShortFamilyName().CompareF(requestedName) == 0) &&
  3216 				(faceAttrib.IsItalic() == aDesiredFontSpec.IsItalic()) &&
  3217 				(faceAttrib.IsBold() == aDesiredFontSpec.IsBold()) )	
  3218 				{
  3219 				TInt error=pFile->GetNearestFontToDesignHeightInPixels(
  3220 					iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
  3221 					iKPixelHeightInTwips, nearestFont, actualFontSpec);
  3222 
  3223 				// search has finished if a match was found
  3224 				if (nearestFont)
  3225 					{
  3226 					// need to copy the actual to the value that is going to be used down below
  3227 					// to make a new font
  3228 					aOpenFont = nearestFont;
  3229 					aActualFontSpec = actualFontSpec;
  3230 					return KErrNone;
  3231 					}
  3232 				else
  3233 					{
  3234 					if (error)
  3235 						{
  3236 						typicalError=error;
  3237 						}
  3238 					}
  3239 				}
  3240 			}
  3241 		// no match
  3242 		return typicalError;
  3243 		}
  3244 	// not open request
  3245 	return KErrNone;
  3246 	}
  3247 #else
  3248 TInt CFontStore::GetNearestOpenFontInPixelsByFontName(
  3249 	COpenFont*&				/* aOpenFont */,
  3250 	TOpenFontSpec&			/* aActualFontSpec */,
  3251 	const TOpenFontSpec&	/* aDesiredFontSpec */,
  3252 	TInt					/* aMaxHeight*/)
  3253 	{ // no match
  3254 	return KErrNone;
  3255 	}
  3256 #endif
  3257 
  3258 
  3259 /** Using the Desired Font Name try to find a matching font.
  3260 
  3261 @param aNearestOpenFont Output, nearest matching open font
  3262 @param aActualFontSpec Output, is used to represent the returned font 
  3263 @param aDesiredFontSpec Input, the desired font specification
  3264 @param aMaxHeight Input, the maximum height in Pixels, or 0
  3265 */
  3266 TInt CFontStore::GetNearestOpenFontInPixelsBySimilarity(
  3267 	COpenFont*&				aNearestOpenFont,
  3268 	TOpenFontSpec&			aActualFontSpec,
  3269 	const TOpenFontSpec&	aDesiredFontSpec,
  3270 	TInt					aMaxHeight)
  3271 	{
  3272 	const TInt openFontFileCount = iOpenFontFileList.Count();
  3273 	TOpenFontSpec nearestFontSpec;
  3274 	COpenFont* nearestFont = NULL;
  3275 	TInt nearestMatch = 0;
  3276     TInt typicalError=KErrNone;
  3277 	for (TInt index = 0; index < openFontFileCount; index++)
  3278 		{
  3279 		// ask font file for its best match, if any
  3280 		COpenFont* candidateFont = NULL;
  3281 		TOpenFontSpec actualFontSpec;
  3282 		TInt lastError=KErrNone;
  3283 		if (aMaxHeight)
  3284 			{
  3285 			lastError=iOpenFontFileList[index]->GetNearestFontToMaxHeightInPixels(
  3286 				iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
  3287 				iKPixelHeightInTwips, candidateFont, actualFontSpec, aMaxHeight);
  3288 			}
  3289 		else
  3290 			{
  3291 			lastError=iOpenFontFileList[index]->GetNearestFontToDesignHeightInPixels(
  3292 				iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips,
  3293 				iKPixelHeightInTwips, candidateFont, actualFontSpec);
  3294 			}
  3295 
  3296 		// hold on to the best overall match
  3297 		if (candidateFont)
  3298 			{
  3299 			const TInt candidateMatch = MatchFontSpecsInPixels(
  3300 				actualFontSpec, aDesiredFontSpec, candidateFont->FontMaxHeight(), aMaxHeight);
  3301 
  3302 			if (NULL == nearestFont || candidateMatch > nearestMatch)
  3303 				{
  3304 				if (nearestFont)
  3305 					{
  3306 					delete nearestFont;
  3307 					}
  3308 				nearestFont = candidateFont;
  3309 				nearestMatch = candidateMatch;
  3310 				nearestFontSpec	= actualFontSpec;
  3311 				}
  3312 			else
  3313 				{
  3314 				// Font match is no better than the current nearestFont
  3315 				//
  3316 				// Note this object is newed in GetNearestFontInPixels each time 
  3317 				// a matching font is found.
  3318 				delete candidateFont;
  3319 				}
  3320 			}
  3321 		else
  3322 			{
  3323 			if (lastError)
  3324 				{
  3325 				typicalError=lastError;
  3326 				}
  3327 			}
  3328 		}
  3329 
  3330 	if (nearestFont != NULL)
  3331 		{ // result
  3332 		aNearestOpenFont = nearestFont;
  3333 		aActualFontSpec = nearestFontSpec;
  3334 		return KErrNone;
  3335 		}
  3336 	else
  3337 		{
  3338 		return typicalError;
  3339 		}
  3340 	}
  3341 
  3342 
  3343 /**
  3344 Get the nearest bitmap font to aFontSpec and place it in aFont. Font must 
  3345 fit vertically inside specified maximum height if given. GetNearestTypeface is
  3346 called which insists that there is at least one typeface. This function will always 
  3347 succeed unless there is an out-of-memory error or other abnormal error. 
  3348 Change aFontSpec to represent the returned font and change it to twips.
  3349 */
  3350 void CFontStore::GetNearestBitmapFontInPixelsL(
  3351 	CFont*&		aFont,
  3352 	TFontSpec&	aFontSpec,
  3353 	TInt		aMaxHeight)
  3354 	{
  3355 	aFontSpec.iTypeface = *GetNearestTypeface(aFontSpec.iTypeface);
  3356 	TTypefaceFontBitmap tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight);
  3357 	const TInt height = tffb.HeightInPixels();
  3358 	if (aFontSpec.iFontStyle.PrintPosition() != EPrintPosNormal)
  3359 		{
  3360 		aFontSpec.iHeight = SuperSubHeight(height, aFontSpec.iFontStyle.PrintPosition());
  3361 		tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight);
  3362 		}
  3363 	aFontSpec.iHeight = height;
  3364 	TAlgStyle algstyle;
  3365 	algstyle.SetIsBold(
  3366 		EStrokeWeightBold == aFontSpec.iFontStyle.StrokeWeight() &&
  3367 		EStrokeWeightNormal == tffb.iFontBitmap->StrokeWeight());
  3368 	algstyle.SetIsItalic(
  3369 		EPostureItalic == aFontSpec.iFontStyle.Posture() &&
  3370 		EPostureUpright == tffb.iFontBitmap->Posture());
  3371 	algstyle.SetIsMono(!aFontSpec.iTypeface.IsProportional() && tffb.iFontBitmap->IsProportional());
  3372 	TInt widthfactor =
  3373 		((tffb.iWidthFactor * tffb.iFontBitmap->FontStoreFile()->iKPixelAspectRatio * iKPixelWidthInTwips) + (500 * iKPixelHeightInTwips)) / (1000 * iKPixelHeightInTwips);
  3374 	if (!widthfactor)
  3375 		widthfactor = 1;
  3376 	algstyle.SetWidthFactor(widthfactor);
  3377 	algstyle.SetHeightFactor( tffb.iHeightFactor );
  3378 	algstyle.iBaselineOffsetInPixels = BaselineOffset(height, aFontSpec.iFontStyle.PrintPosition());
  3379 	if (IsFontLoaded(aFont, algstyle, aFontSpec, tffb.iFontBitmap->iUid))
  3380 		return;
  3381 	TFontSpec spec(aFontSpec);
  3382 	spec.iHeight = VerticalPixelsToTwips(height);
  3383 	spec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap);
  3384 	aFont = NewFontL(spec, algstyle, tffb.iFontBitmap);
  3385 	}
  3386 
  3387 /**
  3388 Gets the font which is the nearest to the given font specification.
  3389 
  3390 Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() 
  3391 yielding (virtually) the same result. However clients are strongly encouraged to use the new
  3392 @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
  3393 character within any given text string will fit within the given amount of pixels, whereas the design 
  3394 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  3395 may result in cropped characters.
  3396 
  3397 @param aFont On return, contains a pointer to the nearest font.
  3398 @param aFontSpec The specification of the font to be matched.
  3399 @return KErrNone if successful; a system-wide error code otherwise.
  3400 @publishedAll
  3401 @deprecated Use GetNearestFontToDesignHeightInPixels
  3402 */
  3403 EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TFontSpec& aFontSpec)
  3404 	{
  3405 	return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec);
  3406 	}
  3407 
  3408 /**
  3409 Gets the font which is the nearest to the given font specification.
  3410 
  3411 Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() 
  3412 yielding (virtually) the same result. However clients are strongly encouraged to use the new
  3413 @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
  3414 character within any given text string will fit within the given amount of pixels, whereas the design 
  3415 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  3416 may result in cropped characters.
  3417 
  3418 @param aFont On return, contains a pointer to the nearest font.
  3419 @param aFontSpec The specification of the font to be matched.
  3420 @return KErrNone if successful; a system-wide error code otherwise.
  3421 @publishedAll
  3422 @deprecated Use GetNearestFontToDesignHeightInPixels
  3423 */
  3424 EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec)
  3425 	{
  3426 	return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec);
  3427 	}
  3428 
  3429 /**
  3430 Gets the font which is the nearest to the given font specification.
  3431 
  3432 This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the 
  3433 same result. However clients are strongly encouraged to use the new
  3434 @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
  3435 character within any given text string will fit within the given amount of pixels, whereas the design 
  3436 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  3437 may result in cropped characters.
  3438 
  3439 @param aFont On return, contains a pointer to the nearest font.
  3440 @param aFontSpec The specification of the font to be matched.
  3441 @return KErrNone if successful; a system-wide error code otherwise.
  3442 @publishedAll
  3443 @released
  3444 */
  3445 EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec)
  3446 	{
  3447 	TOpenFontSpec spec(aFontSpec);
  3448 	return GetNearestFontToDesignHeightInPixels(aFont, spec);
  3449 	}
  3450 
  3451 /**
  3452 Gets the font which is the nearest to the given font specification.
  3453 
  3454 This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the 
  3455 same result. However clients are strongly encouraged to use the new
  3456 @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every 
  3457 character within any given text string will fit within the given amount of pixels, whereas the design 
  3458 height is an aesthetic unit decided by the font designer without strict physical meaning, which 
  3459 may result in cropped characters.
  3460 
  3461 @param aFont On return, contains a pointer to the nearest font.
  3462 @param aFontSpec The specification of the font to be matched.
  3463 @return KErrNone if successful; a system-wide error code otherwise.
  3464 @publishedAll
  3465 @released
  3466 */
  3467 EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec)
  3468 	{
  3469 	return GetNearestFontInPixels(aFont, aFontSpec, 0);
  3470 	}
  3471 
  3472 /**
  3473 Gets the font which is the nearest to the given font specification.
  3474 
  3475 The font and bitmap server returns a pointer to the nearest matching font 
  3476 from those available. Matches to max height of font - this does its best 
  3477 to return a font that will fit within the maximum height specified (but 
  3478 note that variations due to hinting algorithms may rarely result in this 
  3479 height being exceeded by up to one pixel). Problems can also be 
  3480 encountered with bitmap fonts where the typeface exists but doesn't have 
  3481 a font small enough.
  3482 
  3483 @param aFont On return, contains a pointer to the nearest font.
  3484 @param aFontSpec The specification of the font to be matched.
  3485 @param aMaxHeight The maximum height within which the font must fit. If maximum height
  3486 is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
  3487 if equals to 1 pixel. This overrides the height specified in aFontSpec.
  3488 @return KErrNone if successful; a system-wide error code otherwise.
  3489 @publishedAll
  3490 @released
  3491 */
  3492 EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec, TInt aMaxHeight)
  3493 	{
  3494 	TOpenFontSpec spec(aFontSpec);
  3495 	return GetNearestFontToMaxHeightInPixels(aFont, spec, aMaxHeight);
  3496 	}
  3497 
  3498 /**
  3499 Gets the font which is the nearest to the given font specification.
  3500 
  3501 The font and bitmap server returns a pointer to the nearest matching font 
  3502 from those available. Matches to max height of font - this does its best 
  3503 to return a font that will fit within the maximum height specified (but 
  3504 note that variations due to hinting algorithms may rarely result in this 
  3505 height being exceeded by up to one pixel). Problems can also be 
  3506 encountered with bitmap fonts where the typeface exists but doesn't have 
  3507 a font small enough.
  3508 
  3509 @param aFont On return, contains a pointer to the nearest font.
  3510 @param aFontSpec The specification of the font to be matched.
  3511 @param aMaxHeight The maximum height within which the font must fit. If maximum height
  3512 is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument
  3513 if equals to 1 pixel. This overrides the height specified in aFontSpec.
  3514 @return KErrNone if successful; a system-wide error code otherwise.
  3515 @publishedAll
  3516 @released
  3517 */
  3518 EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec, TInt aMaxHeight)
  3519 	{
  3520 	if (KMaxFontHeightInPixels < aMaxHeight)
  3521 		{
  3522 		return KErrTooBig;
  3523 		}
  3524 	if (aMaxHeight > 0 && aMaxHeight < KMinFontHeightInPixels)
  3525 		{
  3526 		return KErrArgument;
  3527 		}
  3528 	return GetNearestFontInPixels(aFont, aFontSpec, aMaxHeight);
  3529 	}
  3530 
  3531 TInt CFontStore::GetNearestFontInPixels(
  3532 	CFont*&					aFont,
  3533 	const TOpenFontSpec&	aDesiredFontSpec,
  3534 	TInt					aMaxHeight)
  3535 	{
  3536 	aFont = NULL;
  3537 
  3538 	// Determine the ideal version of the font spec.
  3539 	TOpenFontSpec originalFontSpec = aDesiredFontSpec;
  3540 	originalFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips);
  3541 	TOpenFontSpec desiredFontSpec = originalFontSpec;
  3542 	if (EDefaultGlyphBitmap == desiredFontSpec.BitmapType())
  3543 		{
  3544 		desiredFontSpec.SetBitmapType(iDefaultBitmapType);
  3545 		}
  3546 	if (EPrintPosNormal != desiredFontSpec.PrintPosition())
  3547 		{
  3548 		desiredFontSpec.SetHeight(SuperSubHeight(desiredFontSpec.Height(), desiredFontSpec.PrintPosition()));
  3549 		}
  3550 	TOpenFontSpec actualOpenFontSpec = desiredFontSpec;
  3551 
  3552 	// Try to get an open font.
  3553 	CFont* openFont = NULL;
  3554 	TRAPD(error, GetNearestOpenFontInPixelsL(
  3555 		openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
  3556 
  3557 	// Try to get a bitmap font - if getting open font failed or the match was not perfect.
  3558 	CFont* bitmapFont = NULL;
  3559 	TInt errorBitmap=KErrNone;
  3560 	TOpenFontSpec actualBitmapFontSpec;
  3561 	if (error || !openFont || actualOpenFontSpec != desiredFontSpec)
  3562 		{
  3563 		TFontSpec f;
  3564 		originalFontSpec.GetTFontSpec(f);
  3565 		if (iTypefaceList.Count() > 0)
  3566 			{
  3567 			TRAP(errorBitmap, GetNearestBitmapFontInPixelsL(bitmapFont, f, aMaxHeight));
  3568 			}
  3569 		actualBitmapFontSpec = f;
  3570 		actualBitmapFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips);
  3571 		}
  3572 
  3573 	//If both attempts fail then there is nothing more we can do...
  3574 	if (!openFont && !bitmapFont)
  3575 		{
  3576 		//If an error caused no fonts to be returned then forward the error
  3577 		if (error)
  3578 			return error;
  3579 		if (errorBitmap)
  3580 			return errorBitmap;
  3581 		}
  3582 	// Choose the best candidate
  3583 	if (NULL == openFont && NULL == bitmapFont)
  3584 		{
  3585 		// Try to get an open font again - unnamed font.
  3586 		// See COpenFontFile::GetNearestFontHelper - how it works with unnamed fonts.
  3587 		actualOpenFontSpec.SetName(KNullDesC);
  3588 		TRAP(error, GetNearestOpenFontInPixelsL(
  3589 			openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
  3590 		if (KErrNone == error && openFont)
  3591 			{
  3592 			aFont = openFont;
  3593 			return KErrNone;
  3594 			}
  3595 		else
  3596 			{
  3597 			OstTraceExt2( TRACE_FATAL, CFONTSTORE_GETNEARESTFONTINPIXELS, "GetNearestOpenFontInPixelsL() return %d, openFont is 0x%x, Panic(EFntNoFontFound)",
  3598 			        error, (unsigned int)openFont);
  3599 			__ASSERT_DEBUG(0, Panic(EFntNoFontFound));
  3600 			return KErrGeneral;
  3601 			}
  3602 		}
  3603 	else if (NULL == openFont)
  3604 		{
  3605 		if (actualBitmapFontSpec.Name().CompareF(desiredFontSpec.Name()) != 0)
  3606 			{
  3607 			// Try to get the nearest open font - because no exact bitmap font match for typeface name
  3608 			actualOpenFontSpec.SetName(KNullDesC);
  3609 			desiredFontSpec.SetName(KNullDesC);
  3610 			TRAPD(errorOpen, GetNearestOpenFontInPixelsL(
  3611 				openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight));
  3612 			if (KErrNone == errorOpen && openFont)
  3613 				{
  3614 				aFont = openFont;
  3615 				ReleaseFont(bitmapFont);
  3616 				}
  3617 			}
  3618 		if (aFont == NULL)
  3619 			{
  3620 			aFont = bitmapFont;
  3621 			}
  3622 		}
  3623 	else if (NULL == bitmapFont)
  3624 		{
  3625 		aFont = openFont;
  3626 		}
  3627 
  3628 	if (aFont == NULL)
  3629 		{
  3630 		// Pick the closest match; for backward compatibility prefer a bitmap font if there is a dead heat.
  3631 		const TInt open_match = MatchFontSpecsInPixels(
  3632 			actualOpenFontSpec, desiredFontSpec, openFont->FontMaxHeight(), aMaxHeight);
  3633 		const TInt bitmap_match = MatchFontSpecsInPixels(
  3634 			actualBitmapFontSpec, desiredFontSpec, bitmapFont->FontMaxHeight(), aMaxHeight);
  3635 		if (open_match > bitmap_match)
  3636 			{
  3637 			aFont = openFont;
  3638 			ReleaseFont(bitmapFont);
  3639 			}
  3640 		else
  3641 			{
  3642 			aFont = bitmapFont;
  3643 			ReleaseFont(openFont);
  3644 			}
  3645 		}
  3646 	return KErrNone;
  3647 	}
  3648 
  3649 /** Gets a bitmap font using the given font UID and algorithmic style.
  3650 
  3651 Tries to find a bitmap font in the font store with the given UID. If successful, 
  3652 the given algorithmic style is applied to the font and this font (which may 
  3653 be a suitable one already existing in the store, or may be a newly generated 
  3654 font) is stored in aFont. If unsuccessful then no font is stored in aFont.
  3655 
  3656 @param aFont On return, a device-dependent font.
  3657 @param aUid A bitmap font UID.
  3658 @param aAlgStyle An algorithmic style to apply to the font.
  3659 @return KErrNone if the font is found, KErrNotFound if the font is not found, 
  3660 or another system-wide error code. */
  3661 EXPORT_C TInt CFontStore::GetFontById(
  3662 	CFont*&				aFont,
  3663 	TUid				aUid,
  3664 	const TAlgStyle&	aAlgStyle)
  3665 	{
  3666 	aFont = NULL;
  3667 	CFontBitmap* fontbitmap = GetFontBitmapById(aUid);
  3668 	if (!fontbitmap)
  3669 		{
  3670 		return KErrNotFound;
  3671 		}
  3672 
  3673 	const TInt height = fontbitmap->iCellHeightInPixels * aAlgStyle.HeightFactor();
  3674 	TFontSpec fontspec;
  3675 	fontspec.iHeight=height;	//Otherwise IsFontLoaded() compares with zero height!!!
  3676 	fontspec.iTypeface.SetIsProportional(!aAlgStyle.IsMono() && fontbitmap->IsProportional());
  3677 	if (aAlgStyle.IsBold() || EStrokeWeightBold == fontbitmap->StrokeWeight())
  3678 		{
  3679 		fontspec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
  3680 		}
  3681 	if (aAlgStyle.IsItalic() || EPostureItalic == fontbitmap->Posture())
  3682 		{
  3683 		fontspec.iFontStyle.SetPosture(EPostureItalic);
  3684 		}
  3685 	if (IsFontLoaded(aFont, aAlgStyle, fontspec, fontbitmap->iUid))
  3686 		{
  3687 		return KErrNone;
  3688 		}
  3689 
  3690 	// Fill in the typeface by finding a typeface with the same font bitmap.
  3691 	fontspec.iHeight = VerticalPixelsToTwips(height);
  3692 	const TInt n = iTypefaceFontBitmapList.Count();
  3693 	for (TInt i = 0; i < n; i++)
  3694 		{
  3695 		if (iTypefaceFontBitmapList[i].iFontBitmap == fontbitmap)
  3696 			{
  3697 			fontspec.iTypeface = *iTypefaceFontBitmapList[i].iTypeface;
  3698 			break;
  3699 			}
  3700 		}
  3701 	TRAPD(ret, aFont = NewFontL(fontspec, aAlgStyle, fontbitmap));
  3702 	return ret;
  3703 	}
  3704 
  3705 /** Gets the number of typefaces held in the font store.
  3706 
  3707 Note that this includes both open font typefaces and non-scalable typefaces.
  3708 
  3709 @return The number of supported typefaces. */
  3710 EXPORT_C TInt CFontStore::NumTypefaces() const
  3711 	{
  3712 	return iTypefaceList.Count() + iOpenFontTypefaceSupportList.Count();
  3713 	}
  3714 
  3715 /** Gets a typeface support object for the typeface in the font store represented 
  3716 by the given index.
  3717 
  3718 Returns benignly with an empty TTypefaceSupport if the index is too high; 
  3719 this can happen if another process removes a typeface after the first process 
  3720 has already got the number of typefaces. However, if the aTypefaceIndex<0 
  3721 the function panics with EFntTypefaceIndexOutOfRange.
  3722 
  3723 @param aTypefaceSupport On return, a typeface support object.
  3724 @param aTypefaceIndex An index number representing a typeface, which is valid 
  3725 if in the range 0 to (NumTypefaces() - 1). */
  3726 EXPORT_C void CFontStore::TypefaceSupport(TTypefaceSupport &aTypefaceSupport,TInt aTypefaceIndex) const
  3727 	{
  3728 	if (aTypefaceIndex < 0)
  3729 		Panic(EFntTypefaceIndexOutOfRange);
  3730 
  3731 	/*
  3732 	Return benignly with an empty TTypefaceSupport if the index is too high; this can happen if another
  3733 	process removes a font after the first process has already got the number of typefaces.
  3734 	*/
  3735 	int typefaces = NumTypefaces();
  3736 	if (aTypefaceIndex >= typefaces)
  3737 		{
  3738 		aTypefaceSupport = TTypefaceSupport();
  3739 		return;
  3740 		}
  3741 
  3742 	//now return Typeface Support for Open Fonts
  3743 	if (aTypefaceIndex >= iTypefaceList.Count())
  3744 		{
  3745 		// copy Open Font typeface details
  3746 		aTypefaceSupport = *iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()]->TypefaceSupport();
  3747 		return;
  3748 		}
  3749 	
  3750 	if (!((aTypefaceIndex >= 0) && (aTypefaceIndex < iTypefaceList.Count())))
  3751 	    {
  3752 	    OstTraceExt2( TRACE_FATAL, CFONTSTORE_TYPEFACESUPPORT, "aTypefaceIndex=%d, iTypefaceList.Count()=%d Panic(EFntTypefaceIndexOutOfRange)",
  3753 	            aTypefaceIndex, iTypefaceList.Count());
  3754 	    __ASSERT_DEBUG(0,Panic(EFntTypefaceIndexOutOfRange));
  3755 	    }
  3756 	TTypeface* typeface = iTypefaceList[aTypefaceIndex];
  3757 	aTypefaceSupport.iTypeface = *typeface;
  3758 	TInt count = iTypefaceFontBitmapList.Count();
  3759 	TInt i;
  3760 	for(i = 0; i < count && iTypefaceFontBitmapList[i].iTypeface != typeface; i++)
  3761 		{  // Finds first fontbitmap with correct typeface
  3762 		}
  3763 	aTypefaceSupport.iMinHeightInTwips = VerticalPixelsToTwips(iTypefaceFontBitmapList[i].HeightInPixels()); 
  3764 	aTypefaceSupport.iNumHeights=0;
  3765 	TInt height=0;
  3766 	for(; (i<count) && (typeface == iTypefaceFontBitmapList[i].iTypeface); i++)
  3767 		if (height != iTypefaceFontBitmapList[i].HeightInPixels())
  3768 			{
  3769 			height = iTypefaceFontBitmapList[i].HeightInPixels();
  3770 			aTypefaceSupport.iNumHeights++;
  3771 			}
  3772 	aTypefaceSupport.iMaxHeightInTwips=VerticalPixelsToTwips(height);
  3773 	aTypefaceSupport.iIsScalable = EFalse;
  3774 	}
  3775 
  3776 /** Returns a font height, in twips, for a certain typeface and height index.
  3777 
  3778 The font height is a height allowed for the typeface represented by aTypefaceIndex. 
  3779 The height returned increases with aHeightIndex.
  3780 
  3781 If aTypefaceIndex<0 the function panics with EFntTypefaceIndexOutOfRange. 
  3782 If aTypefaceIndex is greater than the number of typefaces or aHeightIndex<0 
  3783 then the function returns 0. If aHeightIndex is greater than the number of 
  3784 heights then the function returns the biggest height. 
  3785 
  3786 @param aTypefaceIndex An index number representing a typeface, which is valid 
  3787 in the range 0 to (NumTypefaces() - 1).
  3788 @param aHeightIndex A font height index number, which is valid in the range 
  3789 0 to (TTypefaceSupport::iNumHeights - 1). Note that the typeface support object 
  3790 for the typeface can be got using TypefaceSupport(). 
  3791 @return The height of a font, in twips.
  3792 @see TypefaceSupport()
  3793 */
  3794 EXPORT_C TInt CFontStore::FontHeightInTwips(TInt aTypefaceIndex,TInt aHeightIndex) const
  3795 	{
  3796 	if (aTypefaceIndex >= iTypefaceList.Count())
  3797 		{
  3798 		// it's an Open Font managed by a COpenFontFile
  3799 		if (aTypefaceIndex >= NumTypefaces() || aHeightIndex < 0)
  3800 			return 0;
  3801 		
  3802 		const CTypefaceSupportInfo* supportInfo = iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()];
  3803 		TInt i = Min( supportInfo->NearestPointSizeIndex() + aHeightIndex, 
  3804 					  KOpenFontSizeArrayCount - 1);
  3805 
  3806 		return gOpenFontSizeInTwipsArray[i];
  3807 		}
  3808 	else
  3809 		{
  3810 		return VerticalPixelsToTwips(FontHeightInPixels(aTypefaceIndex,aHeightIndex));
  3811 		}
  3812 	}
  3813 
  3814 /** Returns a font height, in pixels, for a certain typeface and height index.
  3815 
  3816 The font height is a height allowed for the typeface represented by aTypefaceIndex. 
  3817 The height returned increases with aHeightIndex.
  3818 
  3819 If aTypefaceIndex<0 the function panics with EFntTypefaceIndexOutOfRange. 
  3820 If aTypefaceIndex is greater than the number of typefaces or aHeightIndex<0 
  3821 then the function returns 0. If aHeightIndex is greater than the number of 
  3822 heights then the function returns the biggest height. 
  3823 
  3824 @param aTypefaceIndex An index number representing a typeface, which is valid 
  3825 in the range 0 to (NumTypefaces() - 1).
  3826 @param aHeightIndex A font height index number, which is valid in the range 
  3827 0 to (TTypefaceSupport::iNumHeights - 1). Note that the typeface support object 
  3828 for the typeface can be got using TypefaceSupport(). 
  3829 @return The height of a font, in pixels.
  3830 @see TypefaceSupport()
  3831 */
  3832 EXPORT_C TInt CFontStore::FontHeightInPixels(TInt aTypefaceIndex,TInt aHeightIndex) const
  3833 	{
  3834 
  3835 	if (aTypefaceIndex >= iTypefaceList.Count())	// it's an Open Font managed by a COpenFontFile
  3836 		return VerticalTwipsToPixels(FontHeightInTwips(aTypefaceIndex,aHeightIndex));
  3837 	else
  3838 		{
  3839 		if (aTypefaceIndex < 0)
  3840 			Panic(EFntTypefaceIndexOutOfRange);
  3841 		TTypeface* typeface = iTypefaceList[aTypefaceIndex];
  3842 		TInt count = iTypefaceFontBitmapList.Count();
  3843 		TInt i;
  3844 		for(i=0; (i < count) && (iTypefaceFontBitmapList[i].iTypeface != typeface); i++)
  3845 			{  // Finds first fontbitmap with correct typeface
  3846 			}
  3847 		TInt height=0,h=0;
  3848 		for(; (i<count) && (iTypefaceFontBitmapList[i].iTypeface==typeface)
  3849 						&& (h<=aHeightIndex); i++)
  3850 			if (height != iTypefaceFontBitmapList[i].HeightInPixels())
  3851 				{
  3852 				height = iTypefaceFontBitmapList[i].HeightInPixels();
  3853 				h++;
  3854 				}
  3855 		return height;
  3856 		}
  3857 	}
  3858 
  3859 void CFontStore::InternalizeFontStoreFileL(CFontStoreFile* aFontStoreFile, TInt aFontVersion)
  3860 	{
  3861 	RStoreReadStream stream;
  3862 	stream.OpenLC(*aFontStoreFile->iFileStore,aFontStoreFile->iDataStreamId);
  3863 	TInt i, size = stream.ReadInt32L();
  3864 	TInt opsPerformed=0;
  3865 	for (i=0; i<size; i++)
  3866 		{
  3867 		// font is placed in shared heap
  3868 		CFontBitmap* fontbitmap=(CFontBitmap*)iHeap->AllocL(sizeof(CFontBitmap));
  3869 		new(fontbitmap) CFontBitmap(iHeap,aFontStoreFile);
  3870 		CleanupReleasePushL(*fontbitmap);
  3871 		fontbitmap->InternalizeL(stream, aFontVersion);
  3872 		if (GetFontBitmapById(fontbitmap->iUid))
  3873 			{
  3874 			fontbitmap->Release();
  3875 			}
  3876 		else
  3877 			{
  3878 			iFontBitmapList.AppendL(fontbitmap);
  3879 			opsPerformed++;
  3880 			}
  3881 		// safely internalized & owned
  3882 		CleanupStack::Pop(fontbitmap);
  3883 		}
  3884 	size = stream.ReadInt32L();
  3885 	for (i=0; i<size; i++)
  3886 		{
  3887 		TTypeface* typeface=new(ELeave) TTypeface;
  3888 		CleanupStack::PushL(typeface);
  3889 		typeface->InternalizeL(stream);
  3890 		TInt index,count=iTypefaceList.Count(); 		
  3891 		for (index=0; (index<count) && typeface->iName.CompareF(iTypefaceList[index]->iName); index++)
  3892 			{  // Looks to see if typeface is already in list
  3893 			}
  3894 		if (index == count) // If typeface not in list
  3895 			{
  3896 			iTypefaceList.AppendL(typeface);
  3897 			index = iTypefaceList.Count()-1;
  3898 			opsPerformed++;
  3899 			CleanupStack::Pop();  // typeface
  3900 			}
  3901 		else
  3902 			{
  3903 			CleanupStack::Pop();  // typeface
  3904 			delete typeface;
  3905 			typeface=iTypefaceList[index];
  3906 			}
  3907 		TInt num = stream.ReadInt32L();
  3908 		for (TInt j=0; j<num; j++)
  3909 			{
  3910 			TUid uid;
  3911 			stream >> uid;
  3912  			CFontBitmap* fontbitmap = GetFontBitmapById(uid);
  3913  			if (!fontbitmap)
  3914  			    {
  3915  			    OstTrace0( TRACE_FATAL, CFONTSTORE_INTERNALIZEFONTSTOREFILEL, "Panic(EFntFontBitmapNotLoaded)" );
  3916  			   __ASSERT_DEBUG(0,Panic(EFntFontBitmapNotLoaded));
  3917  			    }
  3918 #ifndef _DEBUG
  3919 			User::LeaveIfNull(fontbitmap);
  3920 #endif			
  3921 			TTypefaceFontBitmap typefacefontbitmap(iTypefaceList[index],fontbitmap);
  3922 			typefacefontbitmap.iWidthFactor=stream.ReadInt8L();
  3923 			typefacefontbitmap.iHeightFactor=stream.ReadInt8L();
  3924 			count=iTypefaceFontBitmapList.Count();
  3925 			TInt pos;
  3926 			if (index == count)
  3927 				{
  3928 				pos=count;
  3929 				}
  3930 			else
  3931 				{
  3932 				
  3933 				for (pos=0; (pos<count) && (iTypefaceFontBitmapList[pos].iTypeface != typeface); pos++)
  3934 					{  // Finds position of first fontbitmap with same typeface
  3935 					}
  3936 				for (; (pos<count) && (iTypefaceFontBitmapList[pos].iTypeface == typeface)
  3937 				                   && (iTypefaceFontBitmapList[pos].HeightInPixels()<typefacefontbitmap.HeightInPixels()); pos++)
  3938 					{
  3939 					}
  3940 				for (; (pos<count) &&  (iTypefaceFontBitmapList[pos].iTypeface == typeface)
  3941 				                   &&  (iTypefaceFontBitmapList[pos].HeightInPixels()==typefacefontbitmap.HeightInPixels())
  3942 				                   &&  (iTypefaceFontBitmapList[pos].iFontBitmap->Posture()<fontbitmap->Posture()); pos++)
  3943 	       			{  // Finds position after fontbitmap with same height
  3944 					}
  3945 				for (; (pos<count) &&  (iTypefaceFontBitmapList[pos].iTypeface == typeface)
  3946 				                   &&  (iTypefaceFontBitmapList[pos].HeightInPixels()==typefacefontbitmap.HeightInPixels())
  3947 				                   &&  (iTypefaceFontBitmapList[pos].iFontBitmap->StrokeWeight()<fontbitmap->StrokeWeight()); pos++)
  3948 	       			{  // Finds position after fontbitmap with same height
  3949 					}
  3950 				}
  3951 			TTypefaceFontBitmap* tfbAtPos=(pos==count)
  3952 											?	NULL
  3953 											:	&iTypefaceFontBitmapList[pos];
  3954 			if (	!tfbAtPos	
  3955 				||	tfbAtPos->iTypeface!=typeface
  3956 				||	tfbAtPos->HeightInPixels()!=typefacefontbitmap.HeightInPixels()
  3957 				||	tfbAtPos->iFontBitmap->Posture()!=fontbitmap->Posture()
  3958 				||	tfbAtPos->iFontBitmap->StrokeWeight()!=fontbitmap->StrokeWeight()
  3959 				||	tfbAtPos->iWidthFactor!=typefacefontbitmap.iWidthFactor	
  3960 				||	tfbAtPos->iHeightFactor!=typefacefontbitmap.iHeightFactor	
  3961 				)
  3962 				{
  3963 				iTypefaceFontBitmapList.InsertL(pos,typefacefontbitmap);
  3964 				opsPerformed++;
  3965 				}
  3966 			}
  3967 		}
  3968 		CleanupStack::PopAndDestroy(); // stream
  3969 		if (!opsPerformed)
  3970 			User::Leave(KErrAlreadyExists);
  3971 	}
  3972 
  3973 TTypeface* CFontStore::GetNearestTypeface(const TTypeface& aTypeface) const
  3974 	{
  3975 	TInt index,count = iTypefaceList.Count();
  3976 	if (count <= 0)
  3977 	    {
  3978 	    OstTrace1( TRACE_FATAL, CFONTSTORE_GETNEARESTTYPEFACE, "count=%d, Panic(EFntNoTypefaces)", count );
  3979 	    __ASSERT_DEBUG(0,Panic(EFntNoTypefaces));
  3980 	    }
  3981 	for (index=0; (index<count) && aTypeface.iName.CompareF(iTypefaceList[index]->iName); index++)	  
  3982 		{ // tries matching	typeface name
  3983 		}
  3984 	if (index==count)
  3985 		{
  3986 		if (!aTypeface.IsSymbol())
  3987 			{
  3988 			for (index=0; (index<count) && ((iTypefaceList[index]->IsSymbol()) ||
  3989 			                                (aTypeface.IsProportional() != iTypefaceList[index]->IsProportional()) || 
  3990 			                                (aTypeface.IsSerif() != iTypefaceList[index]->IsSerif())); index++)	  
  3991 				{ // tries matching	typeface flags
  3992 				}
  3993 			if (index==count)
  3994 				for (index=0; (index<count) && ((iTypefaceList[index]->IsSymbol()) ||
  3995 				                                (aTypeface.IsProportional()!=iTypefaceList[index]->IsProportional())); index++)	  
  3996 					{ // tries matching	typeface flags
  3997 					}
  3998 			if (index==count)
  3999 				for (index=0; (index<count) && iTypefaceList[index]->IsSymbol(); index++)	  
  4000 					{ // finds first non-symbol typeface
  4001 					}
  4002 			}
  4003 		else
  4004 			{
  4005 			for (index=0; (index<count) && (!iTypefaceList[index]->IsSymbol()); index++)	  
  4006 				{ // finds first symbol typeface
  4007 				}
  4008 			}
  4009 		}
  4010 
  4011 	if (index==count)
  4012 		index=0;
  4013 	return iTypefaceList[index];
  4014 	}
  4015 
  4016 TTypefaceFontBitmap CFontStore::GetNearestTypefaceFontBitmap(const TFontSpec& aFontSpecInPixels, TInt aMaxHeight)
  4017 	{
  4018 	TTypefaceFontBitmap typefacefontbitmap;
  4019 	TInt count = iTypefaceFontBitmapList.Count();
  4020 	if (count <= 0)
  4021 	    {
  4022 	    OstTrace1( TRACE_FATAL, CFONTSTORE_GETNEARESTTYPEFACEFONTBITMAP, "count=%d, Panic(EFntNoTypefaceFontBitmaps)", count );
  4023 	    __ASSERT_DEBUG(0, Panic(EFntNoTypefaceFontBitmaps));
  4024 	    }
  4025 	TInt i;
  4026 	TInt j;
  4027 	// Assumes there is at least one fontbitmap per typeface
  4028 	for (i = 0; (i < count) && !(aFontSpecInPixels.iTypeface == *iTypefaceFontBitmapList[i].iTypeface); i++)
  4029 		{  // Finds first fontbitmap with correct typeface
  4030 		}
  4031 	if (i >= count)
  4032 	    {
  4033 	    OstTraceExt2( TRACE_FATAL, DUP1_CFONTSTORE_GETNEARESTTYPEFACEFONTBITMAP, "i=%d, count=%d, Panic(EFntTypefaceHasNoFontBitmaps)", i, count );
  4034 	    __ASSERT_DEBUG(i < count, Panic(EFntTypefaceHasNoFontBitmaps));
  4035 	    }
  4036 	TTypeface* typeface = iTypefaceFontBitmapList[i].iTypeface;
  4037 	TInt height = 0;
  4038 	if (aMaxHeight > 0)
  4039 		{ // need to check against max height
  4040 		for (j = i; (j < count) && (iTypefaceFontBitmapList[ j ].iTypeface == typeface) 
  4041 								&& (iTypefaceFontBitmapList[j].iFontBitmap->FontMaxHeight() <= aMaxHeight); j++)
  4042 			{
  4043 			if (iTypefaceFontBitmapList[j].HeightInPixels() != height)
  4044 				{
  4045 				height = iTypefaceFontBitmapList[j].HeightInPixels();
  4046 				i = j;
  4047 				}
  4048 			}
  4049 		}
  4050 	else
  4051 		{ // just check against height
  4052 		for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface)
  4053 								&& (iTypefaceFontBitmapList[j].HeightInPixels() <= aFontSpecInPixels.iHeight); j++)
  4054 			{
  4055 			if (iTypefaceFontBitmapList[j].HeightInPixels() != height)
  4056 				{
  4057 				height = iTypefaceFontBitmapList[j].HeightInPixels();
  4058 				i = j;
  4059 				}
  4060 			}
  4061 		}
  4062 	for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface)
  4063 							&& (iTypefaceFontBitmapList[j].HeightInPixels() == height); j++) 
  4064 		{  // Finds position after fontbitmap correct posture
  4065 		if ((iTypefaceFontBitmapList[j].iFontBitmap->Posture() <= aFontSpecInPixels.iFontStyle.Posture()) &&
  4066 			(iTypefaceFontBitmapList[j].iFontBitmap->StrokeWeight() <= aFontSpecInPixels.iFontStyle.StrokeWeight()))
  4067 			i = j;
  4068 		}
  4069 	typefacefontbitmap = iTypefaceFontBitmapList[i];		
  4070 	return typefacefontbitmap;
  4071 	}
  4072 
  4073 CFontBitmap* CFontStore::GetFontBitmapById(TUid aUid)
  4074 	{
  4075 	CFontBitmap* fontbitmap = NULL;
  4076 	TInt i, count = iFontBitmapList.Count();
  4077 	for (i = 0; (i < count) && (aUid != iFontBitmapList[i]->iUid); i++)
  4078 		{ // finds matching font bitmap
  4079 		}
  4080 	if (i<count) // bitmap found
  4081 		fontbitmap = iFontBitmapList[i];
  4082 	return fontbitmap;				
  4083 	}
  4084 
  4085 /** The method uses the fontspec and algorithmic style only.
  4086 The Uid is not used for Open Fonts. They all have a Uid of 0.
  4087 */
  4088 TBool CFontStore::IsFontLoaded(
  4089 	CFont*&					aFont,
  4090 	const TAlgStyle&		aAlgStyle,
  4091 	const TOpenFontSpec&	aFontSpecInPixels,
  4092 	TInt					aMaxHeight) const
  4093 	{
  4094 	TFontSpec fontSpec;
  4095 	aFontSpecInPixels.GetTFontSpec(fontSpec);
  4096 	return IsFontLoaded(aFont, aAlgStyle, fontSpec, TUid::Uid(0), aMaxHeight);
  4097 	}
  4098 
  4099 //stub functions to help optimise IsFontLoaded.
  4100 //These shims are more efficient than a pointer-to-member.
  4101 static TInt GetHeightShimMaxHeight(CFont* aFont)	{	return	aFont->FontMaxHeight();		}
  4102 static TInt GetHeightShimHeightPixels(CFont* aFont)	{	return	aFont->HeightInPixels();	}
  4103 
  4104 /**
  4105 Font spec comparison is based on
  4106 1. Max height if its given, otherwise design height
  4107 2. All other attributes in TFontSpec
  4108 
  4109 @see CFbsTypefaceStore::IsFontLoaded
  4110 @see CPdrTypefaceStore::IsFontLoaded
  4111 */
  4112 TBool CFontStore::IsFontLoaded(
  4113 	CFont*&				aFont,
  4114 	const TAlgStyle&	aAlgStyle,
  4115 	const TFontSpec&	aFontSpecInPixels,
  4116 	TUid				aUid,
  4117 	TInt				aMaxHeight) const
  4118 	{	//It is not worth copying iFontAccess to frame as it doesn't get register optimised.
  4119 	const TInt count = iFontAccess->Count();
  4120 	const TInt reqHeight =  aMaxHeight ? aMaxHeight : aFontSpecInPixels.iHeight;
  4121 	TInt (*heightFn)(CFont*) = aMaxHeight ? GetHeightShimMaxHeight : GetHeightShimHeightPixels;
  4122 	for (TInt i = 0; i < count; i++)
  4123 		{
  4124 		CBitmapFont* bitmapFont = reinterpret_cast<CBitmapFont*>((*iFontAccess)[i].iFont);
  4125 		if (bitmapFont->Uid() != aUid ||
  4126 			bitmapFont->iAlgStyle != aAlgStyle	||
  4127 			heightFn(bitmapFont) != reqHeight
  4128 			)
  4129 			{
  4130 			continue;
  4131 			}
  4132 		TFontSpec fontSpec = bitmapFont->FontSpecInTwips();
  4133 		if (	fontSpec.iFontStyle == aFontSpecInPixels.iFontStyle &&
  4134 				fontSpec.iTypeface.iName == aFontSpecInPixels.iTypeface.iName
  4135 			) 
  4136 			{
  4137 			(*iFontAccess)[i].iAccessCount++;
  4138 			aFont = static_cast<CFont*>(bitmapFont);
  4139 			return ETrue;
  4140 			}
  4141 		}
  4142 	return EFalse;
  4143 	}
  4144 
  4145 CBitmapFont* CFontStore::NewFontL(
  4146 	const TFontSpec&	aFontSpecInTwips,
  4147 	const TAlgStyle&	aAlgStyle,
  4148 	CFontBitmap*		aFontBitmap)
  4149 	{
  4150 	CBitmapFont* f = CBitmapFont::NewL(iHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap);
  4151 	CleanupStack::PushL(f);
  4152 	AddFontL(f);
  4153 	CleanupStack::Pop();
  4154 	f->SetUniqueFontId(++iUniqueFontIdCount);
  4155 	return f;
  4156 	}
  4157 
  4158 CBitmapFont* CFontStore::NewFontL(
  4159 	const TOpenFontSpec&	aFontSpecInTwips,
  4160 	const TAlgStyle&		aAlgStyle,
  4161 	COpenFont*				aOpenFont)
  4162 	{
  4163 	TFontSpec spec;
  4164 	aFontSpecInTwips.GetTFontSpec(spec);
  4165 	CBitmapFont* f = CBitmapFont::NewL(iHeap, spec, aAlgStyle, aOpenFont);
  4166 	CleanupStack::PushL(f);
  4167 	AddFontL(f);
  4168 	CleanupStack::Pop();
  4169 	f->SetUniqueFontId(++iUniqueFontIdCount);
  4170 	return f;
  4171 	}
  4172 
  4173 // This function is biased towards rounding up
  4174 // The cutoff is effectively at one-third of a pixel
  4175 // This is to match VerticalTwipsToPixels(...)
  4176 TInt CFontStore::VerticalPixelsToTwips(TInt aPixelHeight) const
  4177 	{
  4178 	return ((aPixelHeight * iKPixelHeightInTwips) + 667) / 1000; // Rounds up above one-third of a pixel
  4179 	}
  4180 
  4181 // This function is biased towards rounding down
  4182 // The cutoff is effectively at two-thirds of a twip
  4183 // This is to support the legacy system of rounding down
  4184 // but with a sanity-check cutoff to round up past two-thirds
  4185 TInt CFontStore::VerticalTwipsToPixels(TInt aTwipsHeight) const
  4186 	{
  4187 	if (!iKPixelHeightInTwips)
  4188 	    {
  4189 	    OstTrace0( TRACE_FATAL, CFONTSTORE_VERTICALTWIPSTOPIXELS, "Panic(EFntKPixelHeightInTwipsZero)" );
  4190 	    __ASSERT_DEBUG(0, Panic(EFntKPixelHeightInTwipsZero));
  4191 	    }
  4192 	return ((aTwipsHeight * 1000) + (iKPixelHeightInTwips / 3)) / iKPixelHeightInTwips;  // Rounds down below two-thirds of a twip
  4193 	}
  4194 
  4195 /** Installs and takes ownership of an Open Font rasterizer.
  4196 
  4197 @param aRasterizer A pointer to an Open Font rasterizer. */
  4198 EXPORT_C void CFontStore::InstallRasterizerL(COpenFontRasterizer* aRasterizer)
  4199 	{
  4200 	iOpenFontRasterizerList.AppendL(aRasterizer);
  4201 	}
  4202 	
  4203 /** Install and takes ownership of the shaper
  4204 
  4205 @param aShaperFactory A pointer to a shaper factory. */
  4206 EXPORT_C void CFontStore::InstallShaperFactoryL(CShaperFactory* aShaperFactory)
  4207 	{
  4208 	iShaperFactoryList.AppendL(aShaperFactory);
  4209 	}
  4210 
  4211 /** Deletes the glyph cache belonging to a particular client. 
  4212 
  4213 Called by ~CFbClient().
  4214 
  4215 @param aSessionHandle A session handle. */
  4216 EXPORT_C void CFontStore::DeleteSessionCache(TInt aSessionHandle)
  4217 	{
  4218 	iOpenFontSessionCacheList->DeleteCache(iHeap,aSessionHandle);
  4219 	}
  4220 
  4221 const CArrayPtrFlat<CShaperFactory>* CFontStore::ShaperFactoryList() const
  4222 	{
  4223 	return &iShaperFactoryList;
  4224 	}
  4225 
  4226 /** Returns the list of session caches owned by the COpenFonts
  4227 @internalComponent */
  4228 COpenFontSessionCacheList* CFontStore::GetSessionCacheList()
  4229 	{
  4230 	return iOpenFontSessionCacheList;
  4231 	}
  4232 	
  4233 /** Returns the total cache memory used by all the COpenFonts in the system 
  4234  	@return Total cache memory usage
  4235 	@internalComponent 
  4236 */	
  4237 TInt CFontStore::GetShaperCacheMemUsage()
  4238 	{
  4239 	return iOpenFontShaperCacheMemUsage;
  4240 	}
  4241 	
  4242 /** Updates the total cache memory used by all the COpenFonts in the system
  4243  	@param aUsage New value of total cache memory usage
  4244 	@internalComponent
  4245 */	
  4246 void CFontStore::SetShaperCacheMemUsage(TInt aUsage)
  4247 	{
  4248 	iOpenFontShaperCacheMemUsage = aUsage;
  4249 	}
  4250 	
  4251 /** Returns the list of COpenFontFiles owned by the CFontStore object
  4252 	@internalComponent
  4253 */	
  4254 CArrayPtrFlat<COpenFontFile>* CFontStore::GetOpenFontFileList()
  4255 	{
  4256 	return &iOpenFontFileList;
  4257 	}
  4258 
  4259 void CFontStore::IncNumShaperCaches()
  4260 	{
  4261 	iNumberOfShaperCaches++;
  4262 	}
  4263 	
  4264 void CFontStore::DecNumShaperCaches()
  4265 	{
  4266 	iNumberOfShaperCaches--;
  4267 	}
  4268 
  4269 TInt CFontStore::GetNumShaperCaches()
  4270 	{
  4271 	return iNumberOfShaperCaches;
  4272 	}
  4273 
  4274 
  4275 /** Adds the typeface( of the currently added openfont file from the store) to Open Font System typefaces Supported List
  4276 ignoring duplicate family names.
  4277 1. Prior to adding the entry into the typefaceList, it is searched whether already exists or not
  4278 2. If it is found only its reference count is incremented.
  4279 3. If it is not found then its reference count is set to 1 and added that entry into the typefacelist.
  4280 4. If 0 typefaces are added then KErrAlreadyExists is returned causing the new font to be unloaded.
  4281 @return KErrNone is successful, otherwise a system wide error code
  4282 @internalComponent
  4283 */
  4284 TInt CFontStore::AddTypefacesToSupportList(COpenFontFile* aOpenFontFile)
  4285 	{
  4286 	TInt faceCount = aOpenFontFile->FaceCount();
  4287 	CTypefaceSupportInfo* typefaceFamily = NULL;
  4288 	TInt error = KErrNone;
  4289 	TBool facesAdded=0;
  4290 	// go through all fonts, stop early if an error
  4291 	for (TInt faceIndex = 0; (faceIndex < faceCount) && (error == KErrNone); ++faceIndex)
  4292 		{
  4293 		//Preparing the Supported Typeface Entry
  4294 		if (typefaceFamily == NULL)
  4295 			{ // need a new typeface object
  4296 			typefaceFamily = new CTypefaceSupportInfo();
  4297 			if (typefaceFamily == NULL)
  4298 				{ // failed
  4299 				error = KErrNoMemory;
  4300 				break;
  4301 				}
  4302 			}
  4303 
  4304 		// initialise for next type face
  4305 		const TOpenFontFaceAttrib& faceAttrib = aOpenFontFile->FaceAttrib(faceIndex);
  4306 		typefaceFamily->SetTypefaceInfo(faceAttrib, VerticalPixelsToTwips(faceAttrib.MinSizeInPixels()));
  4307 
  4308 		TInt fontPos = -1;	// an invalid index
  4309 		TInt findError = iOpenFontTypefaceSupportList.FindInOrder(typefaceFamily, fontPos, CTypefaceSupportInfo::CompareFontNames);
  4310  
  4311 		// new font family?
  4312 		if (findError == KErrNotFound)
  4313 			{
  4314 			// back reference to the font file
  4315 			error = typefaceFamily->AddFontFilePtr(aOpenFontFile);
  4316 			if (error == KErrNone)
  4317 				{ // transfer ownership
  4318 				error = iOpenFontTypefaceSupportList.Insert(typefaceFamily, fontPos);
  4319 				if (error == KErrNone)
  4320 					{
  4321 					typefaceFamily = NULL;
  4322 					facesAdded++;					
  4323 					}
  4324 				}
  4325 			}
  4326 		else
  4327 			{
  4328 			// back reference to the new font file (allowed to fail with KErrAlreadyExists)
  4329 			TInt addError = iOpenFontTypefaceSupportList[fontPos]->AddUniqueFontFilePtr(aOpenFontFile,faceAttrib);
  4330 			if (addError==KErrNone)
  4331 				{
  4332 				facesAdded++;
  4333 				}
  4334 			else if (addError == KErrInUse )
  4335 				{
  4336 				//remove typeface from loaded font file????
  4337 				}
  4338 			else if (addError != KErrAlreadyExists )
  4339 				{
  4340 				error = addError;
  4341 				}
  4342 			//else KErrAlreadyExists because loaded by a lower-indexed face in this font file, so faces won't be zero.
  4343 			}
  4344 		}
  4345 
  4346 	if (typefaceFamily != NULL)
  4347 		{
  4348 		delete typefaceFamily;
  4349 		}
  4350 	if (facesAdded==0 && error==KErrNone)
  4351 		{
  4352 			error= KErrAlreadyExists;
  4353 		}
  4354 #ifdef _DEBUG
  4355 	// check that array is in order
  4356 	const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count();
  4357 	for (TInt fontPos = 0; fontPos < countTypefaceFamilies - 1; ++fontPos)
  4358 		{
  4359 		TInt cmp = CTypefaceSupportInfo::CompareFontNames(*iOpenFontTypefaceSupportList[fontPos], *iOpenFontTypefaceSupportList[fontPos+1]);
  4360 		ASSERT(cmp < 0);
  4361 		}
  4362 #endif
  4363 
  4364 	return error;
  4365 	}
  4366 
  4367 
  4368 /** Removes the typefaces from the Support List corresponding to the fontfile removed from
  4369 	the fontstore
  4370 This is done by 
  4371 1. Searching in the typefacesupportList for pointer references to the font file.
  4372 2. If the file is referenced by the typeface family remove the reference.
  4373 3. If typeface family no has any implementations remove the family
  4374 @internalComponent
  4375 */
  4376 void CFontStore::RemoveTypefacesFromSupportList(COpenFontFile* aOpenFontFile)
  4377 	{
  4378 	const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count();
  4379 
  4380 	// search typeface families
  4381 	for (TInt fontPos = countTypefaceFamilies - 1; fontPos >= 0; --fontPos)
  4382 		{
  4383 		CTypefaceSupportInfo* fontInfo = iOpenFontTypefaceSupportList[fontPos];
  4384 
  4385 		// look for back pointer to this Font File
  4386 		TInt fontFileIndex = fontInfo->FindFontFilePtr(aOpenFontFile);
  4387 
  4388 		if (fontFileIndex > KErrNotFound)
  4389 			{ // remove pointer
  4390 			if (fontInfo->RemoveFontFilePtr(fontFileIndex))
  4391 				{ // last implementation of the family, so delete it
  4392 				delete fontInfo;
  4393 				iOpenFontTypefaceSupportList.Remove(fontPos);
  4394 				}
  4395 			}
  4396 		}
  4397 	}
  4398 
  4399 /**
  4400 This function checks the supplied typeface name against the existing bitmap and open 
  4401 typefaces, to see if it present.
  4402 
  4403 @param aName The name of the typeface family name to be checked. 
  4404 @return ETrue if the typeface is present, EFalse otherwise.
  4405 
  4406 @released
  4407 @internalTechnology 
  4408 */
  4409 EXPORT_C TBool CFontStore::HaveTypefaceFamilyName(const TDesC& aName)
  4410 	{
  4411 	//there are two lists for typefaces
  4412 	//not supporting linked fonts here
  4413 	
  4414 	//first list is open fonts
  4415 	TInt count = iOpenFontTypefaceSupportList.Count();
  4416 	for (TInt index=count-1;index>=0;index--)
  4417 		{
  4418 		if (aName.CompareF(iOpenFontTypefaceSupportList[index]->iSupport.iTypeface.iName)==0)
  4419 			return ETrue;
  4420 		}
  4421 
  4422 	//now look through bitmap fonts
  4423 	count = iTypefaceList.Count();
  4424 	for (TInt index=count-1;index>=0;index--)
  4425 		{
  4426 		if (aName.CompareF(iTypefaceList[index]->iName)==0)
  4427 			return ETrue;
  4428 		}
  4429 
  4430 	return EFalse;
  4431 	}
  4432 
  4433 /**
  4434 @internalTechnology
  4435 @released
  4436 */
  4437 EXPORT_C TInt CFontStore::CreateLinkedTypeface(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt aSession, TInt& aId)
  4438 	{
  4439 	TInt err;
  4440 	TInt retErr=0;
  4441 	TRAP(err,retErr = CreateLinkedTypefaceL(aLinkedTypefaceSpec,aSession,aId));
  4442 	if (err!=KErrNone)
  4443 		{	
  4444 		return err;
  4445 		}
  4446 	else
  4447 		{
  4448 		return retErr;	
  4449 		}
  4450 	}
  4451 
  4452 /* this function is used to create the linked typeface, the linked typeface is created on
  4453  * the font and bitmap server heap, not the shared heap.
  4454  */	
  4455 TInt CFontStore::CreateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt /*aSession*/, TInt& /*aId*/)	
  4456 	//reconstuct a CLinkedTypefaceSpecification - could store as T type, but then the
  4457 	// maximum size would be used for every linked typeface
  4458 	//
  4459 	{
  4460 	const TAny* extensionPtr = FontLinkingInterface();
  4461 	
  4462 	if (extensionPtr == NULL)
  4463 		return KErrNotSupported;
  4464 	
  4465 	//Convert the TLinkedTypefaceSpecification args into the
  4466 	//COpenFontLinkedTypefaceSpecification recognised by the rasteriser 
  4467 	COpenFontLinkedTypefaceSpecification* spec = 
  4468 		COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec);
  4469 	
  4470 	TInt err = ValidateLinkedFontSpecificationL(*spec, EFalse);
  4471 	
  4472 	if (err == KErrNone)
  4473     {
  4474 		GenerateLinkedFontFileL(*spec, extensionPtr, EFalse);
  4475     }
  4476 
  4477 	CleanupStack::PopAndDestroy(spec);
  4478 	return err;
  4479 	}
  4480 
  4481 /*
  4482 @internalTechnology
  4483 Retrieve the specification from a linked typeface; the name of the typeface should be specified in the parameter.
  4484 
  4485 @param aLinkedTypefaceSpec An empty linked typeface spec containing the name of the typeface to be retrieved.
  4486 
  4487 @leave One of the system wide error codes.
  4488 */
  4489 EXPORT_C void CFontStore::GetLinkedTypefaceL(TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec)
  4490 	{
  4491 	const TAny* extensionPtr = FontLinkingInterface();
  4492 	
  4493 	if (extensionPtr == NULL)
  4494 		User::Leave(KErrNotSupported);
  4495 
  4496 	MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)extensionPtr;
  4497 	
  4498 	//Check whether the font is loaded
  4499 	CTypefaceSupportInfo* supinfo;
  4500 	TTypefaceSupport support;
  4501 	COpenFontFile* fetchFont=NULL;
  4502 	for (TInt count=0;count<(iOpenFontTypefaceSupportList.Count());count++)
  4503 		{
  4504 		supinfo = iOpenFontTypefaceSupportList[count];
  4505 		support = supinfo->iSupport;			
  4506 		
  4507 		if (aLinkedTypefaceSpec.iName==support.iTypeface.iName)
  4508 			{
  4509 			fetchFont = supinfo->iOpenFontFilePtrArray[0];
  4510 			
  4511 			break;	
  4512 			}
  4513 		}
  4514 	if (fetchFont==NULL)
  4515 		{
  4516 		User::Leave(KErrNotFound);	
  4517 		}
  4518 
  4519 	COpenFontLinkedTypefaceSpecification* typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec.iName);
  4520 	TFileName fetchFile = fetchFont->FileName();
  4521 	linkedExt->GetLinkedTypefaceSpecificationL(fetchFile, *typefaceSpec);
  4522 	aLinkedTypefaceSpec = *typefaceSpec;
  4523 	CleanupStack::PopAndDestroy(typefaceSpec);
  4524 	}
  4525 
  4526 /*
  4527 @internalTechnology
  4528 Updates an existing linked typeface to a new specification.
  4529 
  4530 @param aLinkedTypefaceSpec The new specification for the typeface
  4531 
  4532 @leave KErrNotSupported Font linking is not supported by any of the installed rasterizers
  4533 @leave One of the system wide error codes.
  4534 */
  4535 EXPORT_C void CFontStore::UpdateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs& aLinkedTypefaceSpec)
  4536 	{
  4537 	const TAny* extensionPtr = FontLinkingInterface();
  4538 	
  4539 	if (extensionPtr == NULL)
  4540 		User::Leave(KErrNotSupported);
  4541 	
  4542 	//Convert the TLinkedTypefaceSpecification args into the
  4543 	//COpenFontLinkedTypefaceSpecification recognised by the rasteriser 
  4544 	COpenFontLinkedTypefaceSpecification* spec = 
  4545 		COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec);
  4546 	
  4547 	TInt err = ValidateLinkedFontSpecificationL(*spec, ETrue);
  4548 	User::LeaveIfError(err);
  4549 	
  4550 	GenerateLinkedFontFileL(*spec, extensionPtr, ETrue);
  4551 
  4552 	CleanupStack::PopAndDestroy(spec);
  4553 	}
  4554 
  4555 /**
  4556 @internalTechnology
  4557 Performs the loading of font files at boot time. This is a three stage procedure.
  4558 
  4559 1. Copies linked fonts to be updated from their temporary directory into the linked fonts folder
  4560 2. Loads all the linked fonts from the linked fonts folder.
  4561 3. Loads all remaining font files from *:\resource\fonts
  4562  */
  4563 EXPORT_C void CFontStore::LoadFontsAtStartupL()
  4564 	{
  4565 	//First copy any updated linked fonts from their temporary dir to the linked font dir
  4566 	CFileMan* fm = CFileMan::NewL(iFs);
  4567 	CleanupStack::PushL(fm);
  4568 	
  4569 	//Get the fbserv private folder
  4570 	TBuf<KMaxPrivatePathLength> privPath;
  4571 	iFs.PrivatePath(privPath);
  4572 	
  4573 	//Construct the linked font dir path
  4574 	TBuf<KMaxLinkedFontPathLength> linkedFontDir;
  4575 	linkedFontDir.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath);
  4576 	
  4577 	//Construct the linked font temp dir path
  4578 	TBuf<KMaxLinkedFontPathLength> linkedFontTempDir;
  4579 	linkedFontTempDir.Append(linkedFontDir);
  4580 	linkedFontTempDir.Append(KLinkedFontFileTempFolder);
  4581 	
  4582 	//Copy the temp folder into the main folder
  4583 	TInt err = fm->Copy(linkedFontTempDir, linkedFontDir, CFileMan::EOverWrite);
  4584 
  4585 	if (err == KErrNone)
  4586 		{
  4587 		//If sucessful copying remove the temp folder
  4588 		//A leave is not thrown as the empty directory remaining is not a significant enough
  4589 		//to prevent fbserv from starting
  4590 		fm->RmDir(linkedFontTempDir);
  4591 		}
  4592 	 
  4593 	CleanupStack::PopAndDestroy(fm);
  4594 	
  4595 	//Load Linked Fonts
  4596 	LoadFontsL(linkedFontDir);
  4597 	
  4598 	//Load the remaining fonts
  4599 	LoadFontsL(KFBSERVFontDirSecure);
  4600 	}
  4601 /**
  4602 @internalTechnology
  4603 Returns the pointer to the first rasterizer supporting font linking (KUidLinkedTypefaceRasterizerExtension).
  4604 */
  4605 const TAny* CFontStore::FontLinkingInterface() const
  4606 	{
  4607 	TInt rastcount = iOpenFontRasterizerList.Count();
  4608 	COpenFontRasterizer* rast;
  4609 	TAny* extensionPtr = NULL;
  4610 	
  4611 	//Check each rasterizer in turn to check it supports the extended interface.
  4612 	//In reality there should only be one but multiple rasterizers are supported.
  4613 	for (TInt i = 0 ; i != rastcount ; i++)
  4614 		{
  4615 		rast = iOpenFontRasterizerList[i];
  4616 		rast->ExtendedInterface(KUidLinkedTypefaceRasterizerExtension, extensionPtr);
  4617 		
  4618 		if (extensionPtr != NULL)
  4619 			break;
  4620 		}
  4621 	
  4622 	return extensionPtr;
  4623 	}
  4624 
  4625 /**
  4626 Validates the linked font specification passed as a parameter.
  4627 
  4628 @param aSpec The specification to be validated
  4629 @param aOverwrite ETrue if this is an update operation, EFalse otherwise
  4630 */
  4631 TInt CFontStore::ValidateLinkedFontSpecificationL(COpenFontLinkedTypefaceSpecification& aSpec, TBool aOverwrite) const
  4632 	{
  4633 	//see if the typeface is an existing regular typeface.
  4634 	if (!aOverwrite)
  4635 		{
  4636 		TInt numberTypefaces = iTypefaceList.Count();
  4637 		TInt c;
  4638 		
  4639 		for (c=0;c<numberTypefaces;c++)
  4640 			{
  4641 			TTypeface* ptr=(iTypefaceList)[c];
  4642 			
  4643 			/* only comparing on the name */
  4644 			if (0== ptr->iName.CompareF(aSpec.Name()))
  4645 				{
  4646 				//A typeface with this name is already loaded
  4647 				return KErrAlreadyExists;
  4648 				}
  4649 			}
  4650 			
  4651 		TInt numberOpenFontFiles = iOpenFontFileList.Count();
  4652 		for (c=0;c<numberOpenFontFiles;c++)
  4653 			{
  4654 			COpenFontFile* ptr=(iOpenFontFileList)[c];
  4655 			
  4656 			numberTypefaces= ptr->FaceCount();
  4657 			TInt c2;
  4658 			for (c2=0;c2<numberTypefaces;c2++)
  4659 				{
  4660 				const TOpenFontFaceAttrib& attrib = ptr->FaceAttrib(c2);
  4661 
  4662 				/* only comparing on the name */
  4663 				if (0== attrib.ShortFullName().CompareF(aSpec.Name()))
  4664 					{
  4665 					//have a matching name, return error
  4666 					return KErrAlreadyExists;
  4667 					}
  4668 				if (0== attrib.ShortFamilyName().CompareF(aSpec.Name()))
  4669 					{
  4670 					//have a matching name, return error
  4671 					return KErrAlreadyExists;
  4672 					}	
  4673 				}
  4674 			}
  4675 		}
  4676 		//For each element, check whether the typeface exists and add the correct filename to the spec if it does
  4677 		TInt numTypefaces = aSpec.TypefaceCount();
  4678 		TFileName fileName;
  4679 		COpenFontLinkedTypefaceElementSpec* element;
  4680 		
  4681 		for (TInt counter=0;counter<numTypefaces;counter++)
  4682 			{
  4683 			element = aSpec.Typeface(counter);
  4684 			
  4685 			if (GetFontFilePath(element->ElementName(), fileName))
  4686 				{
  4687 				element->SetFileNameL(fileName);
  4688 				}
  4689 			else
  4690 				{
  4691 				return KErrNotFound;
  4692 				}
  4693 			}
  4694 		return KErrNone;
  4695 	}
  4696 
  4697 
  4698 /**
  4699 Sends the specification to the font rasterizer to be created/updated.
  4700 
  4701 @param aSpec The linked font specification
  4702 @param aExtension The extension interface of the chosen rasterizer
  4703 @param aUpdate ETrue if the file is being updated, EFalse if it should be created
  4704 
  4705 @leave KErrNotFound Attempting to update a file which does not exist
  4706  */
  4707 void CFontStore::GenerateLinkedFontFileL(COpenFontLinkedTypefaceSpecification& aSpec, const TAny* aExtension, TBool aUpdate)
  4708 	{
  4709 	MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)aExtension;
  4710 
  4711 	//Generate the filename for the linked font file (excluding the extension
  4712 	//and the .) which are appended by the rasterizer.
  4713 	TFileName privPath;
  4714 	User::LeaveIfError(iFs.PrivatePath(privPath));
  4715 	TFileName fn;
  4716 	fn.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath);
  4717 	
  4718 	//Choose the correct path to write the file to
  4719 	if (aUpdate)
  4720 		{
  4721 		fn.Append(KLinkedFontFileTempFolder);
  4722 		}
  4723 	
  4724 	// Create the directory if it does not exist
  4725 	TInt result = iFs.MkDirAll(fn);
  4726 	if (result != KErrAlreadyExists)
  4727 		{
  4728 		User::LeaveIfError(result);
  4729 		}
  4730 	
  4731 	//Append the linked font filename to the path for the rasterizer.
  4732 	fn.Append(aSpec.Name());
  4733 	
  4734 	// If we are updating, check that the file is a linked typeface before attempting the update.
  4735 	if (aUpdate)
  4736 		{
  4737 		TFileName fn;
  4738 		TBool exists = GetFontFilePath(aSpec.Name(), fn);
  4739 		
  4740 		if (exists)
  4741 			{
  4742 			COpenFontLinkedTypefaceSpecification* tempSpec = COpenFontLinkedTypefaceSpecification::NewLC(aSpec.Name());
  4743 			TRAPD(ret, linkedExt->GetLinkedTypefaceSpecificationL(fn, *tempSpec));
  4744 			User::LeaveIfError(ret);
  4745 			CleanupStack::PopAndDestroy(tempSpec);
  4746 			}
  4747 		else
  4748 			{
  4749 			User::Leave(KErrNotFound);
  4750 			}
  4751 		}
  4752 	
  4753 	//Use the rasterizer extension to create the linked typeface
  4754 	linkedExt->CreateLinkedTypefaceL(aSpec, fn);
  4755 	
  4756 	// Load the new linked typeface
  4757 	if (!aUpdate)
  4758 		{
  4759 		AddFileL(fn);
  4760 		}
  4761 	}
  4762 
  4763 /**
  4764 Function called at system startup to find and load all fonts in the specified 
  4765 folder. The value of the folder will be the secure Data-caged private folder 
  4766 named "\resource\fonts". 
  4767 
  4768 The first font of a given name overrides subsequent ones. 
  4769 
  4770 The search order is: Y:, X:, W:, ..., C:, B:, A:, Z:
  4771 
  4772 @see TFindFile 
  4773 @param aFontsDir The directory search pattern 
  4774  */
  4775 void CFontStore::LoadFontsL(const TDesC& aFontsDir)
  4776 	{
  4777 #ifdef _DEBUG
  4778 	_LIT(KLoadStarted, "CFontStore::LoadFontsL Started.\r\n");
  4779 	RDebug::Print(KLoadStarted);
  4780 	TUint32	loadStartTime = StartTiming();
  4781 #endif
  4782 	
  4783 	RArray<TParse> fontsToLoad;
  4784 	CleanupClosePushL(fontsToLoad);
  4785 	TFindFile fileFinder(iFs);
  4786 	CDir* foundFileList = NULL;
  4787 
  4788 	_LIT(KFBSERVFontFilePattern, "*");
  4789 	TInt findFileComplete = fileFinder.FindWildByDir(KFBSERVFontFilePattern, aFontsDir, foundFileList);
  4790 
  4791 	while (!findFileComplete)
  4792 		{
  4793 		CleanupStack::PushL(foundFileList);
  4794 		const TInt foundFileCount = foundFileList->Count();
  4795 		const TDesC& pathInfo = fileFinder.File();
  4796 		
  4797 		// Build a list of fonts to be loaded eliminating duplicate filenames. 
  4798 		for (TInt ii = 0; ii < foundFileCount; ii++)
  4799 			{
  4800 			TParse fullFontFileName;
  4801 			if (fullFontFileName.Set((*foundFileList)[ii].iName, &pathInfo, NULL) == KErrNone)
  4802 				{
  4803 				// If the font has not already been loaded, validate it then add it to the list.
  4804 				if (!FileIsInList(fullFontFileName, fontsToLoad))
  4805 					{
  4806 					// Do not validate fonts on Z: (assumed to be ROM created with valid fonts)
  4807 					if (FileIsOnZ(fullFontFileName))
  4808 						{
  4809 						fontsToLoad.AppendL(fullFontFileName);
  4810 						}
  4811 					else
  4812 						{
  4813 						// Test font before loading
  4814 						TRAPD(err, SanityCheckFontFileL(fullFontFileName))
  4815 						if (KErrNone == err)
  4816 							{
  4817 							// Add file 
  4818 							fontsToLoad.AppendL(fullFontFileName);
  4819 							}
  4820 						else
  4821 							{
  4822 							_LIT(KCorruptFont, "CFontStore::LoadFontsL %S could not be loaded.\r\n");
  4823 							RDebug::Print(KCorruptFont, &fullFontFileName.FullName());
  4824 							}
  4825 						}
  4826 					}
  4827 				}
  4828 			}
  4829 
  4830 		CleanupStack::PopAndDestroy(foundFileList);
  4831 		findFileComplete = fileFinder.FindWild(foundFileList);
  4832 		}
  4833 	
  4834 	// Load the fonts in reverse order (i.e. Z:, A: to Y:) this causes
  4835 	// fonts on Z: to take priority over fonts on A: to Y: when the internal 
  4836 	// font names are identical.
  4837 	TInt kk = fontsToLoad.Count();
  4838 	while(kk--)
  4839 		{
  4840 		TUid fontUid = KNullUid;
  4841 		
  4842 		// Load this font as a new font, and add it to the list of loaded fonts
  4843 		TRAPD(addFileError, AddSanityCheckedFontL(fontsToLoad[kk], fontUid));
  4844 		if (addFileError)
  4845 			{
  4846 			_LIT(KLoadedFont, "CFontStore::LoadFontsL failed with error %i to load font, filename: %S\r\n");
  4847 			RDebug::Print(KLoadedFont, addFileError, &(fontsToLoad[kk].FullName()));
  4848 			}
  4849 #ifdef _DEBUG
  4850 		else
  4851 			{
  4852 			// NOTE: This is to make testing of confirming what fonts are loaded a little easier as there is no 
  4853 			//		 easy way to get this information from outside the server.
  4854 			_LIT(KLoadedFont, "CFontStore::LoadFontsL loaded font filename: %S\r\n");
  4855 			RDebug::Print(KLoadedFont, &(fontsToLoad[kk].FullName()));
  4856 			}
  4857 #endif
  4858 		}
  4859 	
  4860 #ifdef _DEBUG
  4861 	TUint32 loadTime = FinishTimingL(loadStartTime);
  4862 	_LIT(KLoadEnded, "CFontStore::LoadFontsL Finished. Took: %dus\r\n");
  4863 	RDebug::Print(KLoadEnded, loadTime);
  4864 #endif
  4865 	CleanupStack::PopAndDestroy(&fontsToLoad);
  4866 	}
  4867 /**
  4868 Retrieves the full path and filename of the font with the specified name. This function
  4869 searches through all open font files currently loaded by font store.
  4870 
  4871 @param aFontName The full name of the font to search for
  4872 @param aFilePath An empty descriptor to have the file name filled in
  4873 
  4874 @return ETrue if the font is found; EFalse if not
  4875 */
  4876 EXPORT_C TBool CFontStore::GetFontFilePath(const TDesC& aFontName, TFileName& aFilePath) const
  4877 	{
  4878 	TInt numTypefaces = iOpenFontFileList.Count();
  4879 	COpenFontFile* thisFile;
  4880 	TOpenFontFaceAttrib faceAttrib;
  4881 	
  4882 	//For every (Truetype) font file
  4883 	for (TInt i = 0 ; i != numTypefaces ; i++)
  4884 		{
  4885 		thisFile = iOpenFontFileList[i];
  4886 		
  4887 		//For every face within this file
  4888 		for (TInt face = 0 ; face != thisFile->FaceCount() ; face++)
  4889 			{
  4890 			faceAttrib = thisFile->FaceAttrib(face);
  4891 			if (faceAttrib.FullName().CompareF(aFontName) == 0)
  4892 				{
  4893 				aFilePath = thisFile->FileName();
  4894 				return ETrue;
  4895 				}
  4896 			}
  4897 		}
  4898 	return EFalse;	
  4899 	}
  4900 
  4901 TInt CFontStore::CacheFontTable(TUid aFileUid, TUint32 aTag, 
  4902         TAny *&aContent, TInt aLength)
  4903     {
  4904     return iFontTableCache->Append(aFileUid, aTag, aContent, aLength);
  4905     }
  4906 
  4907 TInt CFontStore::FindFontTableInCache(TUid aFileUid, TUint32 aTag, 
  4908         TAny *&aContent, TInt &aLength)
  4909     {
  4910     TInt id;
  4911     return iFontTableCache->Find(aFileUid, aTag, aContent, aLength, &id);
  4912     }
  4913 
  4914 TInt CFontStore::IncreaseUnhintedOutlineRefCount(const TUnhintedOutlineId &aOutlineId, 
  4915         TInt aSessionHandle)
  4916     {
  4917     return iUnhintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
  4918     }
  4919 
  4920 TInt CFontStore::IncreaseHintedOutlineRefCount(const THintedOutlineId &aOutlineId,
  4921         TInt aSessionHandle)
  4922     {
  4923     return iHintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle);
  4924     }
  4925 
  4926 TInt CFontStore::IncFontTableRefCount(TUid aFileUid, TUint32 aTag, 
  4927         TInt aSessionHandle)
  4928     {
  4929     return iFontTableCache->IncRefCount(aFileUid, aTag, aSessionHandle);
  4930     }
  4931 
  4932 TInt CFontStore::DecFontTableRefCount(TUid aFileUid, TUint32 aTag, 
  4933         TInt aSessionHandle)
  4934     {
  4935     return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
  4936     }
  4937 
  4938 TInt CFontStore::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, TAny * aData, 
  4939         TInt aLength, TAny *&aOutline, TInt &aLen)
  4940     {
  4941     return iUnhintedOutlineCache->CacheUnhintedOutline(aOutlineId, aData, aLength, 
  4942             aOutline, aLen);
  4943     }
  4944 
  4945 TInt CFontStore::CacheHintedOutline(const THintedOutlineId &aOutlineId,
  4946         TAny * aData, TInt aLength, TAny *&aOutline, TInt &aLen)
  4947     {
  4948     return iHintedOutlineCache->CacheHintedOutline(aOutlineId, aData, aLength,
  4949             aOutline, aLen);
  4950     }
  4951 
  4952 TInt CFontStore::ReleaseUnhintedOutline(const TUnhintedOutlineId &aOutlineId, 
  4953         TInt aSessionHandle)
  4954     {
  4955     return iUnhintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
  4956     }
  4957 
  4958 TInt CFontStore::ReleaseHintedOutline(const THintedOutlineId &aOutlineId,
  4959         TInt aSessionHandle)
  4960     {
  4961     return iHintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle);    
  4962     }
  4963 
  4964 TInt CFontStore::ReleaseFontTable(TUid aFileUid, TUint32 aTag, 
  4965         TInt aSessionHandle)
  4966     {
  4967     return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle);
  4968     }
  4969 
  4970 TInt CFontStore::FindUnhintedOutlineInCache(const TUnhintedOutlineId &aOutlineId, TAny *&aData, 
  4971         TInt &aLength)
  4972     {
  4973     return iUnhintedOutlineCache->Find(aOutlineId, aData, aLength);
  4974     }
  4975 
  4976 TInt CFontStore::FindHintedOutlineInCache(const THintedOutlineId &aOutlineId, 
  4977         TAny *&aData, TInt &aLength)
  4978     {
  4979     return iHintedOutlineCache->Find(aOutlineId, aData, aLength);
  4980     }
  4981 
  4982 void CFontStore::CleanupCacheOnOpenFontRemoval(COpenFont *aFont)
  4983     {
  4984     iHintedOutlineCache->CleanupCacheOnOpenFontRemoval(aFont);
  4985     //iUnhintedOutlineCache.OnOpenFontRemoval(aFont);
  4986     }
  4987 
  4988 void CFontStore::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile) 
  4989     {
  4990     iUnhintedOutlineCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
  4991     iFontTableCache->CleanupCacheOnOpenFontFileRemoval(aFontFile);
  4992     }
  4993 
  4994 /** Clean up font table and glyph outline caches when an FBS session is terminated.
  4995  * All the reference counts related to that session are cleared.
  4996 @param aSession: Input. A pointer to the terminating session.
  4997 @return always returns KErrNone.
  4998 @internalTechnology
  4999 */
  5000 EXPORT_C
  5001 void CFontStore::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle)
  5002     {
  5003     iHintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
  5004     iUnhintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
  5005     iFontTableCache->CleanupCacheOnFbsSessionTermination(aSessionHandle);
  5006     }
  5007 
  5008 
  5009 void TFontTableGlyphOutlineCacheMemMonitor::Inc(TInt aBytes)
  5010     {
  5011     iBytes += aBytes;
  5012     }
  5013 
  5014 void TFontTableGlyphOutlineCacheMemMonitor::Dec(TInt aBytes)
  5015     {
  5016     iBytes -= aBytes;
  5017     }
  5018 
  5019 TInt TFontTableGlyphOutlineCacheMemMonitor::GetMemUsage()
  5020     {
  5021     return iBytes;
  5022     }
  5023 
  5024 TFontTableGlyphOutlineCacheMemMonitor::TFontTableGlyphOutlineCacheMemMonitor(): 
  5025     iBytes(0) 
  5026     {
  5027     // null constructor
  5028     }
  5029 
  5030 TUnhintedOutlineId::TUnhintedOutlineId(TUid aFileUid, TInt aFaceIndex, TUint aId):
  5031 iFileUid(aFileUid), iFaceIndex(aFaceIndex), iId(aId)
  5032     {
  5033     // a null constructor;
  5034     }
  5035 
  5036 THintedOutlineId::THintedOutlineId(COpenFont *aFont, TUint aId):
  5037 iFont(aFont), iId(aId)
  5038     {
  5039     // a null constructor;
  5040     }
  5041 
  5042 #ifdef _DEBUG
  5043 /**
  5044 Returns a timestamp for use by FinishTimingL().
  5045 @return The timestamp.
  5046 @see FinishTimingL
  5047 */
  5048 TUint32 StartTiming(void)
  5049 	{
  5050 	return User::FastCounter();
  5051 	}
  5052 
  5053 /**
  5054 Returns the time difference between a given time and now in microseconds.
  5055 @param aStartTime The start time returned by calling StartTiming()
  5056 @return The time difference in microseconds.
  5057 @see StartTiming()
  5058 */
  5059 TUint32 FinishTimingL(TUint32 aStartTime)
  5060 	{
  5061 	TInt freq = 0;
  5062 	TUint32 endtime = User::FastCounter();
  5063 	User::LeaveIfError(HAL::Get(HALData::EFastCounterFrequency, freq));
  5064 	TUint32 diff = endtime - aStartTime;
  5065 	TInt64 diffTime = (1000000 * TInt64(diff)) / (TInt64)freq;
  5066 	return TUint32(diffTime);
  5067 	}
  5068 #endif
  5069 
  5070 /**
  5071 Returns true if the filename passed in is on the Z: drive
  5072 @param aFileName The filename to check
  5073 @return ETrue if the file is on Z:
  5074 */
  5075 TBool FileIsOnZ(TParse& aFileName)
  5076 	{
  5077 	TBool onZ = EFalse;
  5078 	
  5079 	const TDesC& fileDrive = aFileName.Drive();
  5080 	_LIT(KZDrive,"z:");
  5081 	if (0 == fileDrive.CompareF(KZDrive))
  5082 		{
  5083 		onZ = ETrue;
  5084 		}
  5085 	
  5086 	return onZ;
  5087 	}
  5088 
  5089 
  5090 /**
  5091 Returns true if the filename passed in is in the supplied list
  5092 @param aFileName The filename to check
  5093 @param aList The list to check
  5094 @return ETrue if the file is in the list
  5095 */
  5096 TBool FileIsInList(TParse& aFileName, RArray<TParse>& aList)
  5097 	{
  5098 	TBool inList = EFalse;
  5099 	
  5100 	TInt jj = aList.Count();
  5101 	while(jj--)
  5102 		{
  5103 		TPtrC shortFilename = aFileName.NameAndExt();
  5104 		if (shortFilename.CompareF( aList[jj].NameAndExt() ) == 0)
  5105 			{
  5106 #ifdef _DEBUG
  5107 			_LIT(KEclipsesFont, "CFontStore::FileIsInList %S eclipses %S\r\n");
  5108 			RDebug::Print(KEclipsesFont, &aList[jj].FullName(), &aFileName.FullName());
  5109 #endif
  5110 			inList = ETrue;
  5111 			break;
  5112 			}
  5113 		}
  5114 	
  5115 	return inList;
  5116 	}