os/textandloc/fontservices/fontstore/src/OPENFONT.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2003-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 <fntstore.h>
    20 #include <gdi.h>
    21 #include "FNTSTD.H"
    22 #include <graphics/shapeimpl.h>
    23 #include "ShaperCache.H"
    24 #include "openfontsprivate.h"
    25 #include <linkedfonts.h>
    26 #include "linkedfontsprivate.h"
    27 #include <graphics/openfontrasterizer.h>
    28 #include <graphics/gdi/glyphsample.h>
    29 #include <e32math.h>
    30 
    31 #include "OstTraceDefinitions.h"
    32 #ifdef OST_TRACE_COMPILER_IN_USE
    33 #include "OPENFONTTraces.h"
    34 #endif
    35 
    36 
    37 const TInt KSessionCacheEntries = 512;
    38 const TInt KDefaultSlantFactor = 20480;
    39 const TInt KOneIn16Dot16FixedPointFormat = 65536;
    40 
    41 template<class T>
    42 ROffsetArray<T>::ROffsetArray()
    43     : iOffset(0), iCount(0)
    44     {}
    45 
    46 template<class T>
    47 TInt ROffsetArray<T>::Create(RHeap* aHeap, TInt aCount)
    48     {
    49     if (iOffset != 0)
    50         {
    51         return KErrAlreadyExists;
    52         }
    53     TAny* p = aHeap->AllocZ(aCount * sizeof(TInt));
    54     if (p == NULL)
    55         {
    56         return KErrNoMemory;
    57         }
    58     iOffset = (TInt)p - (TInt)this;
    59     iCount = aCount;
    60     return KErrNone;
    61     }
    62 
    63 template<class T>
    64 void ROffsetArray<T>::Close(RHeap* aHeap)
    65     {
    66     if (iOffset != 0)
    67         {
    68         aHeap->Free(PtrAdd(this, iOffset));
    69         }
    70     iOffset = 0;
    71     iCount = 0;
    72     }
    73 
    74 template<class T>
    75 TInt ROffsetArray<T>::Count() const
    76     {
    77     return iCount;
    78     }
    79 
    80 template<class T>
    81 T* ROffsetArray<T>::operator[](TInt aIndex) const
    82     {
    83     TInt e = ((TInt*)PtrAdd(this, iOffset))[aIndex];
    84     return e != 0 ? (T*)PtrAdd(this, e) : NULL;
    85     }
    86 
    87 template<class T>
    88 void ROffsetArray<T>::SetAt(TInt aIndex, T* aEntry)
    89     {
    90     ((TInt*)PtrAdd(this, iOffset))[aIndex] = aEntry ? (TInt)aEntry - (TInt)this : 0;
    91     }
    92 
    93 
    94 /*COpenFontGlyphCache*/
    95 
    96 TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams)
    97 	{
    98 	if (iShaperCacheSentinel == NULL)
    99 		return NULL;
   100 	COpenFontShaperCacheEntry* searchNode = iShaperCacheSentinel->iNext;
   101 	
   102 	TInt start = aParams->iStart;
   103 	TInt end = aParams->iEnd;
   104 	TInt script = aParams->iScript;
   105 	const TUint16* text = (TUint16*)aParams->iText->Ptr();
   106 	TUint16* cachedText;
   107 	const TUint16* copyOfText;
   108 	TInt noOfChars = end - start;
   109 	TInt textIsSame = 1;
   110 	while (searchNode != iShaperCacheSentinel)
   111 		{
   112 		//Future work: add Script check for further script support
   113 		//Future work: add Language check for further language support
   114 		if ((searchNode->iEnd == end) && (searchNode->iStart == start) && (searchNode->iScript == script))
   115 			{
   116 			// Check for the entire text (within the context) coming in.
   117 			TInt i = 0;
   118 			copyOfText = text + start;
   119 			cachedText = (TUint16*)searchNode->iText + searchNode->iStart;
   120 			textIsSame = 1;
   121 			while (i < noOfChars && textIsSame != 0)
   122 				{
   123 				if (*cachedText != *copyOfText)
   124 					textIsSame = 0;
   125 				i++;
   126 				copyOfText++;
   127 				cachedText++;
   128 				};
   129 
   130 			if (textIsSame)
   131 				{
   132 				if (searchNode == iShaperCacheSentinel->iNext)
   133 					{
   134 					// now we need to update the reference count here for that session
   135 					if (searchNode->IncRefCount(aSessionHandle) != KErrNone)
   136 						return NULL;
   137 					return iShaperCacheSentinel->iNext->iShapeHeader;
   138 					}
   139 				// We have found a node, now put that node to the top of the list as the most recently used node
   140 				searchNode->iPrevious->iNext = searchNode->iNext;
   141 				searchNode->iNext->iPrevious = searchNode->iPrevious;
   142 				
   143 				searchNode->iNext = iShaperCacheSentinel->iNext;
   144 				iShaperCacheSentinel->iNext->iPrevious = searchNode;
   145 				iShaperCacheSentinel->iNext = searchNode;
   146 				searchNode->iPrevious = iShaperCacheSentinel;
   147 				if (searchNode->IncRefCount(aSessionHandle)!= KErrNone)
   148 					return NULL;
   149 				return searchNode->iShapeHeader;
   150 				}
   151 			}
   152 			searchNode = searchNode->iNext;
   153 		}
   154 	return NULL;
   155 	}
   156 
   157 TShapeHeader* COpenFontGlyphCache::Insert(TInt aSessionHandle, RHeap* aHeap, CShaper::TInput aInput, TShapeHeader* aShapeHeader, TInt& aAddedBytes)
   158 	{
   159 	TInt heapSizeBefAloc = 0;
   160 	aHeap->AllocSize(heapSizeBefAloc);
   161 
   162 	COpenFontShaperCacheEntry* new_entry;
   163 	new_entry = COpenFontShaperCacheEntry::New(aHeap, aInput, aShapeHeader);
   164 	if (new_entry != NULL)
   165 		{
   166 		// increase the reference count for this
   167 		TInt ret=new_entry->IncRefCount(aSessionHandle);
   168 		if (ret != KErrNone)
   169 			{
   170 			//no memory here
   171 			COpenFontShaperCacheEntry::Delete(aHeap, new_entry);
   172 			return NULL;
   173 			}
   174 		new_entry->iNext = iShaperCacheSentinel->iNext;
   175 		iShaperCacheSentinel->iNext->iPrevious = new_entry;
   176 		iShaperCacheSentinel->iNext = new_entry;
   177 		new_entry->iPrevious = iShaperCacheSentinel;
   178 
   179 		iNumberOfShaperCacheEntries++;
   180 		TInt heapSizeOnAloc = 0;
   181 		aHeap->AllocSize(heapSizeOnAloc);
   182 		aAddedBytes = heapSizeOnAloc - heapSizeBefAloc;
   183 
   184 		// Update the amount of memory used in creation of a new entry
   185 		iShapingInfoCacheMemory += heapSizeOnAloc - heapSizeBefAloc;
   186 
   187 		return new_entry->iShapeHeader;
   188 		}
   189 	return NULL;
   190 	}
   191 
   192 /**
   193 Searches from the least recently used towards the most recently used
   194 and try to free entry that is no longer referenced
   195 */
   196 TInt COpenFontGlyphCache::DeleteLeastRecentlyUsedEntry(RHeap* aHeap)
   197 	{
   198 	// start from the least recently used
   199 	COpenFontShaperCacheEntry* deleteNode = iShaperCacheSentinel->iPrevious;
   200 
   201 	// if empty list there is nothing to delete
   202 	if (deleteNode == iShaperCacheSentinel)
   203 		return 0;
   204 	// else navigating starting from the LRU entry
   205 	while (deleteNode != iShaperCacheSentinel)
   206 		{
   207 		// cannot delete if the iHandleRefCount is greater than zero
   208 		if (deleteNode->iHandleRefCount>0)
   209 			{
   210 			deleteNode = deleteNode->iPrevious;
   211 			continue;
   212 			}
   213 
   214 		// otherwise we can delete the entry
   215 		deleteNode->iPrevious->iNext = deleteNode->iNext;
   216 		deleteNode->iNext->iPrevious = deleteNode->iPrevious;
   217 
   218 		TInt heapSizeBeforeDel = 0;
   219 		TInt heapSizeAfterDel = 0;
   220 		aHeap->AllocSize(heapSizeBeforeDel);
   221 		COpenFontShaperCacheEntry::Delete(aHeap, deleteNode);
   222 		aHeap->AllocSize(heapSizeAfterDel);
   223 		TInt deletedBytes = heapSizeBeforeDel - heapSizeAfterDel;
   224 
   225 		iNumberOfShaperCacheEntries--;
   226 		iShapingInfoCacheMemory -= deletedBytes;
   227 
   228 		return deletedBytes;
   229 		}
   230 	// we have navigated through the whole list and cannot delete anything
   231 	return 0;
   232 	}
   233 
   234 TInt COpenFont::DecrementCachedRefCount(TInt aSessionHandle, TShapeHeader* aShapeHeader, TBool aResetAll)
   235 	{
   236 	COpenFontShaperCacheEntry* ptr=NULL;
   237 	COpenFontGlyphCache* glyphCache=GetGlyphCache();
   238 	if (glyphCache != NULL)
   239 		ptr=glyphCache->iShaperCacheSentinel;
   240 	if (ptr == NULL)
   241 		return KErrNone;
   242 
   243 	TInt ret = KErrNotFound;
   244 	CFontStore* thisFontStore = File()->GetFontStore();
   245 	TInt allocBefDec = 0;
   246 	TInt allocAfterDec = 0;
   247 	TInt deletedBytes = 0;
   248 
   249 	// loop through the cache entry to decrement the ref count for a particular session	
   250 	while (ptr->iNext != NULL)
   251 		{
   252 		if (aResetAll)
   253 			{
   254 			// we want to reset any cache that has a matching the session handle
   255 			// i.e. here we dont care about which TShapeHeader and hence we can
   256 			// ignore the error code here if not found
   257 
   258 			// Always update the memory usage of the cache as decreasing the ref count 
   259 			// releases memory
   260 			iHeap->AllocSize(allocBefDec);
   261 
   262 			ptr->DecRefCount(aSessionHandle, ETrue);
   263 
   264 			iHeap->AllocSize(allocAfterDec);
   265 			deletedBytes = allocBefDec - allocAfterDec;
   266 			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
   267 			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
   268 
   269 			ret=KErrNone;
   270 			}
   271 		else if (ptr->iShapeHeader != NULL && ptr->iShapeHeader==aShapeHeader)
   272 			{
   273 			// Always update the memory usage of the cache as decreasing the ref count 
   274 			// releases memory
   275 			iHeap->AllocSize(allocBefDec);
   276 
   277 			ptr->DecRefCount(aSessionHandle);
   278 
   279 			iHeap->AllocSize(allocAfterDec);
   280 			deletedBytes = allocBefDec - allocAfterDec;
   281 			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
   282 			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
   283 
   284 			return KErrNone;
   285 			}
   286 		ptr=ptr->iNext;
   287 		if (ptr == glyphCache->iShaperCacheSentinel)
   288 			{
   289 			break;
   290 			}
   291 		}
   292 	return ret;
   293 	}
   294 
   295 TInt COpenFont::FreeShaperCacheMemory(TInt aBytesNeeded)
   296 	{
   297 	TInt totalDeletedBytes = 0;
   298 	TInt tempDeletedBytes = 0;
   299 	CFontStore* thisFontStore = File()->GetFontStore();
   300 
   301 	if (aBytesNeeded <= KMaxShaperSesssionCacheMemory)
   302 		{
   303 		// delete LRU entries from all the caches except the one owned by this COpenFont
   304 		// The 'if' condition here is to avoid looping through every font in the system
   305 		// if only one of the them has a non-empty cache. In situations where only one
   306 		// cache is left and it is full, this strategy makes freeing the memory faster.
   307 		if (thisFontStore->GetNumShaperCaches() > 1)
   308 			{
   309 			CArrayPtrFlat<COpenFont>* fontList;
   310 			CArrayPtrFlat<COpenFontFile>* fontFileList = thisFontStore->GetOpenFontFileList();
   311 			TInt numberOfFontFiles = fontFileList->Count();
   312 			TInt i = 0; 
   313 			while ((totalDeletedBytes < aBytesNeeded) && (i < numberOfFontFiles))
   314 				{
   315 				fontList = (*fontFileList)[i]->GetOpenFontList();
   316 				TInt fontListCount=fontList->Count();
   317 				TInt j = 0;
   318 				while ((totalDeletedBytes < aBytesNeeded) && (j < fontListCount))
   319 					{
   320 					COpenFont* open_font = (*fontList)[j];
   321 					COpenFontGlyphCache* glyphCache = open_font->GetGlyphCache();
   322 					if ((open_font != this) && (glyphCache != NULL))
   323 						{
   324 						while ((totalDeletedBytes < aBytesNeeded) && (!glyphCache->ShaperCacheIsEmpty()))
   325 							{
   326 							totalDeletedBytes += glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
   327 							if (glyphCache->ShaperCacheIsEmpty())
   328 								{
   329 								thisFontStore->DecNumShaperCaches();
   330 								}
   331 								
   332 							// If totalDeletedBytes is zero mean we cannot delete from this font
   333 							if (totalDeletedBytes == 0)
   334 								{
   335 								break;
   336 								}
   337 							}
   338 						}
   339 					j++;
   340 					}
   341 				i++;
   342                 }
   343             }
   344 
   345         // If deleted bytes are still less than the required one delete from this font
   346         COpenFontGlyphCache* glyphCache = GetGlyphCache();
   347         if (glyphCache != NULL)
   348             {
   349             while (totalDeletedBytes < aBytesNeeded && !glyphCache->ShaperCacheIsEmpty())
   350                 {
   351                 tempDeletedBytes = glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
   352                 if (tempDeletedBytes == 0)
   353                     break;
   354                 totalDeletedBytes += tempDeletedBytes;
   355                 }
   356             }   //if(glyphCache)
   357         }   //if(aBytesNeeded <= KMaxShaperSesssionCacheMemory)
   358 		
   359 	// Update the global CFontStore cache memory count
   360 	if (totalDeletedBytes > 0)
   361 		{
   362 		thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - totalDeletedBytes);
   363 		}
   364 
   365 	return totalDeletedBytes;
   366 	}
   367 
   368 TShapeHeader* COpenFont::InsertShapedDataIntoCache(TInt aSessionHandle,TFontShapeFunctionParameters* aParams, TShapeHeader* aShapeHeader)
   369 	{
   370 	CShaper::TInput input;
   371 	input.iEnd = aParams->iEnd;
   372 	input.iStart = aParams->iStart;
   373 	input.iScript = aParams->iScript;
   374 	input.iLanguage = aParams->iLanguage;
   375 	input.iText = aParams->iText;
   376 	input.iMaximumAdvance = KMaxTInt;
   377 	input.iFlags = 0;
   378 	input.iSessionHandle = aSessionHandle;
   379 	input.iReserved1 = 0;
   380 
   381 	CFontStore* thisFontStore = File()->GetFontStore();
   382 	
   383 	// Create the glyph cache if it doesn't already exist.
   384     // This call can only come from FBSERV
   385     COpenFontGlyphCache* glyphCache = GetGlyphCache();
   386     if (glyphCache == NULL)
   387         {
   388         glyphCache = (COpenFontGlyphCache*) iHeap->Alloc(sizeof(COpenFontGlyphCache));
   389         if (glyphCache == NULL) // no memory
   390             {
   391             return NULL;
   392             }
   393         new (glyphCache) COpenFontGlyphCache(iHeap);
   394         SetGlyphCache(glyphCache);
   395         }
   396     // If there is no sentinel present, i.e. new cache
   397     if (glyphCache->iShaperCacheSentinel == NULL)
   398         {
   399         // Create a sentinel
   400         glyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap);
   401         if (glyphCache->iShaperCacheSentinel == NULL)
   402             {
   403             // no memory
   404             return NULL;
   405             }
   406         glyphCache->iShaperCacheSentinel->iNext = glyphCache->iShaperCacheSentinel;
   407         glyphCache->iShaperCacheSentinel->iPrevious = glyphCache->iShaperCacheSentinel;
   408         glyphCache->iNumberOfShaperCacheEntries = 1;
   409         }
   410 
   411     // Before inserting into this cache, check if it was empty.
   412     // If empty, then increment the global cache count signifying one more cache is active
   413     if (glyphCache->ShaperCacheIsEmpty())
   414         {
   415         thisFontStore->IncNumShaperCaches();
   416         }
   417 
   418 	TInt addedBytes = 0;
   419 	TShapeHeader* cached_header = NULL;
   420 
   421 	// Insert a new entry and return the newly inserted TShapeHeader entry
   422 	cached_header = glyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes);
   423 	if (cached_header == NULL)
   424 		return NULL;
   425 
   426 	// If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then
   427 	// free some memory by releasing the same amount of memory that was just added
   428 	if (thisFontStore->GetShaperCacheMemUsage() + addedBytes > KMaxShaperSesssionCacheMemory)
   429 		{
   430 		FreeShaperCacheMemory(addedBytes);
   431 		}
   432 
   433 	// Now update the memory count with the added memory for the new entry
   434 	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
   435 	return cached_header;
   436 	}
   437 
   438 TShapeHeader* COpenFont::GetShapedData(TInt aSessionHandle, TFontShapeFunctionParameters* aParams)
   439 	{
   440     COpenFontGlyphCache* glyphCache = GetGlyphCache();
   441 	if (glyphCache == NULL)
   442 		return NULL;
   443 
   444 	TShapeHeader* cachedHeader = NULL;
   445 	CFontStore* thisFontStore = File()->GetFontStore();
   446 
   447 	// Always update the memory usage of the cache as increasing the reference count of a found header uses up memory
   448 	TInt allocBefInc = 0;
   449 	TInt allocAfterInc = 0;
   450 	iHeap->AllocSize(allocBefInc);
   451 
   452 	cachedHeader = glyphCache->SearchShaperCache(aSessionHandle,aParams);
   453 	
   454 	iHeap->AllocSize(allocAfterInc);
   455 	TInt addedBytes = allocAfterInc - allocBefInc;
   456 	glyphCache->iShapingInfoCacheMemory += addedBytes;
   457 	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
   458 
   459 	return cachedHeader;
   460 	}
   461 
   462 TBool COpenFontGlyphCache::ShaperCacheIsEmpty()
   463 	{
   464 	if (iShaperCacheSentinel == NULL)
   465 		return ETrue;
   466 
   467 	if (iShaperCacheSentinel->iNext == iShaperCacheSentinel)
   468 		return ETrue;
   469 	else
   470 		return EFalse;
   471 	}
   472 
   473 /**
   474 C++ constructor taking shared heap, session cache list and font file as parameters.
   475 
   476 You must either use this, or the other constructor, when creating your derived 
   477 object. This constructor might be used, in preference to the other, if there 
   478 is only a single typeface in the font file.
   479 
   480 @param aHeap The shared heap. 
   481 @param aSessionCacheList The session cache list.
   482 @param aFile A pointer to the COpenFontFile object creating this COpenFont. 
   483 e.g. when creating a COpenFont the COpenFontFile derived object would pass 
   484 it this.
   485 */
   486 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList,
   487 							  COpenFontFile* aFile):
   488 	iHeap(aHeap),
   489 	iShaper(NULL),
   490 	iFaceIndex(0)
   491 	{	
   492     SetFile(aFile);
   493     SetSessionCacheList(aSessionCacheList);
   494 	}
   495 
   496 /**
   497 C++ constructor taking shared heap, session cache list, font file and face 
   498 index as parameters.
   499 
   500 You must either use this, or the other constructor, when creating your derived 
   501 object. This constructor would be used if the font file contains more than 
   502 one typeface.
   503 
   504 @param aHeap The shared heap.
   505 @param aSessionCacheList The session cache list.
   506 @param aFile A pointer to the COpenFontFile object creating this COpenFont. 
   507 e.g. when creating a COpenFont the COpenFontFile derived object would pass 
   508 it this.
   509 @param aFaceIndex The index of the typeface within the font file aFile.
   510 */
   511 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex) :
   512  	iHeap(aHeap),
   513 	iShaper(NULL),
   514 	iFaceIndex(aFaceIndex)
   515 	{
   516     SetFile(aFile);
   517     SetSessionCacheList(aSessionCacheList);
   518 	}
   519 
   520 /**
   521 Destructor
   522 
   523 This function frees all memory owned by the object, including the session 
   524 cache list and the glyph list, prior to its destruction.
   525 */
   526 EXPORT_C COpenFont::~COpenFont()
   527 	{
   528 	//Delete the shaper
   529 	delete iShaper;
   530 
   531 	File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
   532 	
   533 	COpenFontGlyphCache* glyphCache = GetGlyphCache();
   534 	if (glyphCache != NULL)
   535 		{
   536 		glyphCache->iGlyphTreeById.ResetAndDestroy();
   537 		glyphCache->iGlyphTreeByUnicode.ResetAndDestroy();
   538 
   539 		// Delete the shaper cache as well
   540 		if (glyphCache->iShaperCacheSentinel)
   541 			{
   542 			COpenFontShaperCacheEntry* previous  = NULL;
   543 			COpenFontShaperCacheEntry* si = glyphCache->iShaperCacheSentinel->iPrevious;
   544 			TInt heapBefore = 0;
   545 			TInt heapAfter = 0;
   546 			iHeap->AllocSize(heapBefore);
   547 			while (glyphCache->iNumberOfShaperCacheEntries > 0)
   548 				{
   549 				previous = si->iPrevious;
   550 				COpenFontShaperCacheEntry::Delete(iHeap, si);
   551 				si = previous;
   552 				glyphCache->iNumberOfShaperCacheEntries--;
   553 				}
   554 			iHeap->AllocSize(heapAfter);
   555 			File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter));
   556 			File()->GetFontStore()->DecNumShaperCaches();
   557 			}
   558 
   559 		iHeap->Free(glyphCache);
   560 		}
   561 	COpenFontSessionCacheList* sessionCacheList = SessionCacheList();
   562     if (sessionCacheList != NULL)
   563         {
   564         sessionCacheList->DeleteFontGlyphs(iHeap, this);
   565         }
   566     COpenFontFile* file = File();
   567     if (file != NULL)
   568         {
   569         file->RemoveFontFromList(this);
   570         }
   571 	}
   572 
   573 EXPORT_C void COpenFont::operator delete(TAny *aFont)
   574 	{
   575 	if(aFont != NULL)
   576 		{
   577 		COpenFont* f = (COpenFont*)aFont;
   578 		if (f->iHeap)
   579 			f->iHeap->Free(aFont);
   580 		}
   581 	}
   582 
   583 /**
   584 Rasterize a glyph
   585 
   586 This function may only be called via an FBSERV message.
   587 
   588 @param aSessionHandle Session handle of the calling session
   589 @param aCode Unicode value or glyph code if top bit is set
   590 @param aGlyphData
   591 	Output data. May be null, in which case output may be
   592 	obtained through a call to GetCharacterData.
   593 
   594 @return
   595 	ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap()
   596 	and aGlyphData->Metrics() are valid), EFalse otherwise.
   597 */
   598 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
   599 	TOpenFontGlyphData* aGlyphData)
   600 	{
   601 	// create the cache if it doesn't exisit. As this call can only come from
   602 	// FBSERV if the chunk has to be resized then no panic will happen.
   603     COpenFontGlyphCache* glyphCache = GetGlyphCache();
   604 	if (glyphCache == NULL)
   605 		{
   606         glyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
   607 		if (glyphCache == NULL) // no memory
   608 			{
   609 			return EFalse;
   610 			}
   611 		new(glyphCache) COpenFontGlyphCache(iHeap);
   612 		SetGlyphCache(glyphCache);
   613 		}
   614 
   615 	// Look in the Font Cache	
   616 	const COpenFontGlyph* g = FontCacheGlyph(aCode);		 	
   617 
   618 	// If it has already been rasterized return it.
   619 	if (g != NULL)
   620 		{
   621 		if (aGlyphData != NULL)
   622 			{
   623 			aGlyphData->SetMetricsPointer(&g->iMetrics);
   624 			aGlyphData->SetBitmapPointer(g->Bitmap());
   625 			}
   626 
   627 		return ETrue;
   628 		}
   629 
   630 	// Rasterize the glyph.
   631 	TOpenFontGlyphData* temp_glyph_data = NULL;
   632 	TInt error = KErrNone;
   633 	TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
   634 	if (error != KErrNone)
   635 		{
   636 		iHeap->Free(temp_glyph_data);
   637 		return EFalse;
   638 		}
   639 
   640 	TBool glyph_data_valid = ETrue;
   641 	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
   642 	COpenFontGlyph* new_glyph = NULL;
   643 
   644 	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
   645 	TInt bytes = sizeof(COpenFontGlyph) + cur_glyph_data->BytesNeeded();	
   646 	if(glyphCache != NULL && bytes + glyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
   647 		{
   648 		new_glyph = COpenFontGlyph::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   649 		if (new_glyph != NULL)
   650             {
   651 			if ((aCode & 0x80000000) != 0)
   652 				{
   653 				error = glyphCache->iGlyphTreeById.SetAt(aCode & 0x7FFFFFFF, new_glyph);
   654 				}
   655 			else
   656 				{
   657 				error = glyphCache->iGlyphTreeByUnicode.SetAt(aCode, new_glyph);
   658 				}
   659 			if (error == KErrNone)
   660 			    {
   661                 glyphCache->iGlyphCacheMemory += bytes;
   662 			    }
   663 			else
   664 			    {
   665                 iHeap->Free(new_glyph);
   666                 new_glyph = NULL;
   667 			    }
   668             }
   669 		}
   670 	// Otherwise put the glyph into the per-session cache.
   671 	else
   672 		{
   673 		// Look in the session cache. Do not expect to find the glyph here
   674 		// since the session cache has already been searched client-side.
   675 		// However, SessionCacheGlyph() is called so that the session cache is
   676 		// created if needed and an index is found where the new glyph will be
   677 		// placed when added to the session cache.
   678 		COpenFontSessionCache* cache = NULL;
   679 		TInt index = 0;
   680 		(void)SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, ETrue);
   681 		if (cache == NULL)
   682 			{			
   683 			iHeap->Free(temp_glyph_data);
   684 			return EFalse;
   685 			}
   686 
   687 		COpenFontSessionCacheEntry* new_entry =
   688 			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
   689 		new_glyph = new_entry;
   690 		if (new_entry != NULL)
   691 			{
   692 			cache->Insert(iHeap, new_entry, index);
   693 			}
   694 		}
   695 
   696 	if (temp_glyph_data != NULL)
   697 		{
   698 		iHeap->Free(temp_glyph_data);
   699         }
   700         
   701     // Fix up the returned glyph data pointers to point to the actual data.
   702     if (new_glyph == NULL)
   703         glyph_data_valid = EFalse;
   704     else if (aGlyphData != NULL)
   705         {
   706         aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
   707         aGlyphData->SetBitmapPointer(new_glyph->Bitmap());
   708         }
   709 
   710 	return glyph_data_valid;
   711 	}
   712 
   713 void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData)
   714 	{
   715 	aTempGlyphData = 0;
   716 	MOpenFontShapingExtension* extensionInterface = 0;
   717 
   718 	// if the MSB is set this is a request to rasterize a glyph code
   719 	// rather than a unicode value.  This can only be done if the rasterizer
   720 	// supports the extended API. 
   721 	if ( aCode & 0x80000000 )
   722 		{
   723 		aCode = GLYPH_CODE(aCode);
   724 		// get the extension API for RasterizeGlyphL() if available
   725 		TAny* ext = NULL;
   726 		ExtendedInterface(KUidOpenFontShapingExtension, ext);
   727 		extensionInterface = reinterpret_cast<MOpenFontShapingExtension*>(ext);
   728 
   729 		if (extensionInterface == NULL)
   730 			// an attempt to rasterize a glyph when the rasterizer does not
   731 			// support it; best to do nothing
   732 			return;
   733 		}
   734 	TOpenFontGlyphData* currGlyphData = aGlyphData;
   735 
   736 	if (currGlyphData == NULL)
   737 		{
   738 		aTempGlyphData = TOpenFontGlyphData::New(iHeap, 0);
   739 		if (!aTempGlyphData)
   740 			User::Leave(KErrNoMemory);
   741 		currGlyphData = aTempGlyphData;
   742 		}
   743 
   744 	if (extensionInterface != NULL)
   745 		extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
   746 	else
   747 		RasterizeL(aCode, currGlyphData);
   748 
   749 	// If the GlyphData object was not large enough, create a temporary one
   750 	// that can then be deleted by the caller.
   751 	if (currGlyphData->Overflow())
   752 		{
   753 		TInt bytesNeeded = currGlyphData->BytesNeeded();
   754 		if (aTempGlyphData)
   755 			iHeap->Free(aTempGlyphData);
   756 		aTempGlyphData = TOpenFontGlyphData::New(iHeap, bytesNeeded);
   757 		if (aTempGlyphData == NULL)
   758 			User::Leave(KErrNoMemory);
   759 		
   760 		currGlyphData = aTempGlyphData;
   761 
   762 		// If the extension interface was used above, then use again here
   763 		if (extensionInterface != NULL)
   764 			extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
   765 		else
   766 			RasterizeL(aCode, currGlyphData);
   767 		}
   768 		
   769 	if (currGlyphData->Metrics() == NULL) 
   770 		{
   771 		User::Leave(KErrArgument);
   772 		}
   773 	}
   774 
   775 /** @internalComponent */
   776 void COpenFont::SetShaper(CShaper* aShaper)
   777 	{
   778 	iShaper = aShaper;
   779 	}
   780 	
   781 /** @internalComponent */
   782 CShaper* COpenFont::GetShaper()
   783 	{
   784 	return iShaper;
   785 	}
   786 
   787 /** @internalComponent */
   788 TBool COpenFont::HasShaper() const
   789 	{
   790 	return iShaper != NULL;
   791 	}
   792 
   793 void COpenFont::DeleteShaper() const
   794 	{
   795 	delete iShaper;
   796 	}
   797 
   798 TInt COpenFont::GetFontTable(TUint32 aTag, TAny*& aTableContent, TInt& aLength) 
   799     {
   800     // get the extension API for GetTrueTypeTable() if available
   801     TAny* ext = NULL;
   802     ExtendedInterface(KUidOpenFontTrueTypeExtension, ext);
   803     MOpenFontTrueTypeExtension* extensionInterface = 
   804         reinterpret_cast<MOpenFontTrueTypeExtension*>(ext);
   805 
   806     TInt ret = KErrNone;
   807     if (extensionInterface == NULL)
   808         {
   809         ret = KErrNotSupported;
   810         }
   811     else 
   812         {
   813         TUint32 tag = aTag;
   814         TInt len = 0;
   815         aTableContent = extensionInterface->GetTrueTypeTable(ret, tag, &len);
   816         if (KErrNone == ret) 
   817             {
   818             aLength = len;
   819             }
   820         }
   821     return ret;
   822     }
   823 
   824 TInt COpenFont::GetGlyphOutline(TUint aCode, 
   825         TBool aHinted, TAny*& aOutline, TInt &aLength) 
   826     {
   827     // get the extension API for GetTrueTypeTable() if available
   828     TAny* ext = NULL;
   829     ExtendedInterface(KUidOpenFontGlyphOutlineExtension, ext);
   830     MOpenFontGlyphOutlineExtension *extensionInterface = 
   831         reinterpret_cast<MOpenFontGlyphOutlineExtension*>(ext);
   832 
   833     TInt ret = KErrNone;
   834     if (extensionInterface == NULL)
   835         {
   836         ret = KErrNotSupported;
   837         }
   838     else 
   839         {
   840         ret = extensionInterface->GetGlyphOutline(aCode, ETrue, 
   841                 aHinted, aOutline, aLength);
   842         }
   843     return ret;
   844     }
   845 
   846 
   847 /**
   848 A constructor initialised with a TCharacterMetrics object.
   849 
   850 This is the old-style character metrics object. As for other T classes, there 
   851 is no need to explicitly cleanup TOpenFontCharMetrics objects.
   852 
   853 @param aMetrics The old-style metrics object.
   854 */
   855 EXPORT_C TOpenFontCharMetrics::TOpenFontCharMetrics(const TCharacterMetrics& aMetrics)
   856 	{
   857 	iWidth = (TInt16)(aMetrics.iMoveInPixels - aMetrics.iLeftAdjustInPixels - aMetrics.iRightAdjustInPixels);
   858 	iHeight = aMetrics.iHeightInPixels;
   859 	iHorizBearingX = aMetrics.iLeftAdjustInPixels;
   860 	iHorizBearingY = aMetrics.iAscentInPixels;
   861 	iHorizAdvance = aMetrics.iMoveInPixels;
   862 	iVertBearingX = 0;
   863 	iVertBearingY = 0;
   864 	iVertAdvance = aMetrics.iHeightInPixels;
   865 	iGlyphBitmapType = 0;
   866 	}
   867 
   868 /**
   869 Converts a TOpenFontCharacterMetrics object to a TCharacterMetrics.
   870 
   871 @param aMetrics On return, contains the character's old-style metrics. 
   872 @return ETrue if it was possible to get the metrics, otherwise EFalse.
   873 */
   874 EXPORT_C TBool TOpenFontCharMetrics::GetTCharacterMetrics(TCharacterMetrics& aMetrics) const
   875 	{
   876 	aMetrics.iAscentInPixels = iHorizBearingY;
   877 	aMetrics.iHeightInPixels = iHeight;
   878 	aMetrics.iLeftAdjustInPixels = iHorizBearingX;
   879 	aMetrics.iMoveInPixels = iHorizAdvance;
   880 	aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth);
   881 	return ETrue;
   882 	}
   883 
   884 TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const
   885 	{
   886 	const COpenFontGlyph* g = Glyph(aSessionHandle, aCode);
   887 	if (g != NULL)
   888 		{
   889 		aMetrics = &g->iMetrics;
   890 		aBitmap = g->Bitmap();
   891 		return ETrue;
   892 		}
   893 	else
   894 		{
   895 		aMetrics = NULL;
   896 		aBitmap = NULL;
   897 		return EFalse;
   898 		}
   899 	}
   900 
   901 
   902 
   903 void COpenFont::OnFileDeleted()
   904 	{
   905     iFileOffset = 0;
   906 	}
   907 
   908 COpenFontGlyphCache* COpenFont::GetGlyphCache() const
   909 	{
   910     if (iGlyphCacheOffset == 0)
   911         {
   912         return NULL;
   913         }
   914     return reinterpret_cast<COpenFontGlyphCache*>(PtrAdd(const_cast<COpenFont*>(this), iGlyphCacheOffset));
   915 	}
   916 
   917 const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const
   918 	{	
   919 	const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode);
   920 	if (glyph == NULL)
   921 		{			
   922 		COpenFontSessionCache* cache;
   923 		TInt index;
   924 		glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse);
   925 	}
   926 
   927 	return glyph;
   928 	}
   929 
   930 /**
   931 Is the specified character present in the font?
   932 */
   933 TBool COpenFont::HasCharacterL(TInt aCode) const
   934 	{
   935 	COpenFontFile* file = File();
   936 	if (file != NULL)
   937 		return file->HasUnicodeCharacterL(iFaceIndex, aCode);
   938 	else
   939 		return EFalse;
   940 	}
   941 
   942 /**
   943 Retrieve glyph data from the per-font glyph cache.
   944 If it is not found return NULL. 
   945 If the cache hasn't been created, then return NULL.
   946 Previous versions of this function created the cache, but as this function can potentially
   947 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
   948 be resized - this is not allowed by the kernel.
   949 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
   950 @param aCode The code for the glpyh to look for in the cache
   951 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
   952 */
   953 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode) const
   954 	{
   955 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
   956 		{
   957 		if ((aCode & 0x80000000) != 0)
   958 			{
   959 			return glyphCache->iGlyphTreeById.At(aCode & 0x7FFFFFFF);
   960 			}
   961 		else
   962 			{
   963 			return glyphCache->iGlyphTreeByUnicode.At(aCode);
   964 			}
   965 		}
   966 
   967 	// No glyph found
   968 	return NULL;
   969 	}
   970 
   971 /** Retrieve glyph data from the session cache. If the glyph is not in the
   972 cache, return the cache and glyph index where the glyph data should be put. If
   973 there is no session cache, optionally create it.
   974 
   975 @param aHeap
   976 	The heap on which to create the new cache, if appropriate. Not used if
   977 	either the appropriate session cache already exists, or if aCreate is
   978 	passed as false
   979 @param aSessionHandle The session handle
   980 @param aCode
   981 	The code of the glyph to look up (Unicode or glyph code if the top bit is
   982 	set)
   983 @param aCache
   984 	Returns the appropriate session cache, or NULL if an attempt to create it 
   985 	has failed.
   986 @param aIndex
   987 	Returns where the glyph is, or should be put
   988 @param aCreate
   989 	If False, creation of a new cache is inhibited
   990 @return The glyph data, or null if the glyph is not in the cache
   991 @internalComponent
   992 */
   993 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
   994 	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
   995 	TInt& aIndex, TBool aCreate) const
   996 	{
   997 	aIndex = 0;
   998 	COpenFontSessionCacheList* cacheList = SessionCacheList();
   999 	aCache = cacheList->FindCache(aSessionHandle);
  1000 	if (aCache != NULL)
  1001 		{
  1002 		return aCache->Glyph(this, aCode, aIndex);
  1003 		}
  1004 	
  1005 	if (aCreate)
  1006 		{
  1007 		COpenFontSessionCache* new_cache = NULL;
  1008 		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
  1009 		
  1010 		if ((!error) && new_cache != NULL)
  1011 			{
  1012 			if (cacheList->AddCache(new_cache) != KErrNone)
  1013 				{
  1014 				new_cache->Delete(aHeap);	
  1015 				aHeap->Free(new_cache);
  1016 				return NULL;
  1017 				}
  1018 
  1019 			aCache = new_cache;
  1020 			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
  1021 			}
  1022 		}
  1023 	return NULL;
  1024 	}
  1025 
  1026 COpenFontSessionCacheList* COpenFont::SessionCacheList()const
  1027     {
  1028     if (iSessionCacheListOffset == 0)
  1029         {
  1030         return NULL;
  1031         }
  1032     return reinterpret_cast<COpenFontSessionCacheList*>(reinterpret_cast<TInt>(this) + iSessionCacheListOffset);
  1033     }
  1034 
  1035 void COpenFont::SetSessionCacheList(COpenFontSessionCacheList* aSessionCacheList)
  1036     {
  1037     iSessionCacheListOffset = aSessionCacheList ? reinterpret_cast<TInt>(aSessionCacheList) - reinterpret_cast<TInt>(this) : NULL;
  1038     }
  1039 
  1040 void COpenFont::SetFile(COpenFontFile* aFile)
  1041     {
  1042     iFileOffset = aFile ? reinterpret_cast<TInt>(aFile) - reinterpret_cast<TInt>(this) : NULL;
  1043     }
  1044 
  1045 void COpenFont::SetGlyphCache(COpenFontGlyphCache* aGlyphCache)
  1046     {
  1047     iGlyphCacheOffset = aGlyphCache ? reinterpret_cast<TInt>(aGlyphCache) - reinterpret_cast<TInt>(this) : NULL;
  1048     }
  1049 
  1050 
  1051 /**
  1052 Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
  1053 The data is copied; ownership remains with the caller.
  1054 */
  1055 COpenFontGlyph* COpenFontGlyph::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
  1056 	{
  1057 	COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->Alloc(sizeof(COpenFontGlyph) + aBitmap.Size());
  1058     if (glyph == NULL)
  1059         {
  1060         return NULL;
  1061         }
  1062     new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
  1063 	glyph->SetBitmap(glyph + 1);
  1064 	Mem::Copy(glyph + 1, aBitmap.Ptr(), aBitmap.Size());
  1065 	return glyph;
  1066 	}
  1067 
  1068 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) 
  1069 	{
  1070 	COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry) + aBitmap.Size());
  1071 	if (entry == NULL)
  1072 		{
  1073 		return NULL;
  1074 		}
  1075 	new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
  1076 	entry->SetBitmap(entry + 1);
  1077 	Mem::Copy(entry + 1, aBitmap.Ptr(), aBitmap.Size());
  1078 	return entry;
  1079 	}
  1080 
  1081 void COpenFontGlyph::SetBitmap(const TAny* aBitmap)
  1082 	{
  1083 	iBitmapOffset = reinterpret_cast<TInt>(aBitmap) - reinterpret_cast<TInt>(this);
  1084 	}
  1085 
  1086 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
  1087 	{
  1088     COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
  1089     new(c) COpenFontSessionCache(aSessionHandle);
  1090     if (c->iEntryArray.Create(aHeap, aEntries) != KErrNone)
  1091         {
  1092         aHeap->Free(c);
  1093         User::Leave(KErrNoMemory);
  1094         }
  1095     return c;
  1096 	}
  1097 
  1098 
  1099 void COpenFontSessionCache::Delete(RHeap* aHeap)
  1100     {
  1101     TInt numEntries = iEntryArray.Count();
  1102     for (TInt i = 0; i < numEntries; ++i)
  1103         {
  1104         COpenFontSessionCacheEntry* entry = iEntryArray[i];
  1105         if (entry != NULL)
  1106             {
  1107             COpenFont* font=const_cast<COpenFont*>(entry->Font());
  1108             if (font != NULL)
  1109                 font->DecrementCachedRefCount(iSessionHandle,NULL,ETrue);
  1110             COpenFontSessionCacheEntry::Delete(aHeap, entry);
  1111             }
  1112         }
  1113     iEntryArray.Close(aHeap);
  1114     }
  1115 
  1116 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex) const
  1117 	{
  1118     aIndex = -1;
  1119     TInt numEntries = iEntryArray.Count();
  1120     TInt index = GLYPH_CODE(aCode) % numEntries;   // simple hash function to shorten searches
  1121     for (TInt i = 0; i < numEntries; ++i, ++index)
  1122         {
  1123         if (index >= numEntries)
  1124             {
  1125             index = 0;
  1126             }
  1127         const COpenFontSessionCacheEntry* entry = iEntryArray[index];
  1128         if (entry == NULL)
  1129             {
  1130             if (aIndex < 0)
  1131                 {
  1132                 aIndex = index;
  1133                 }
  1134             }
  1135         else if (entry->Font() == aFont && entry->iCode == aCode)
  1136             {
  1137             return entry;
  1138             }
  1139         }
  1140     return NULL;
  1141 	}
  1142 
  1143 
  1144 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
  1145 	{
  1146     if (aIndex >= iEntryArray.Count())
  1147         {
  1148         Panic(EFntSessionCacheIndexOutOfRange);
  1149         }
  1150     if (aIndex < 0)
  1151         {
  1152         aIndex = Math::Rand(iRandomSeed) % iEntryArray.Count();
  1153         }
  1154     COpenFontSessionCacheEntry::Delete(aHeap, iEntryArray[aIndex]);
  1155     iEntryArray.SetAt(aIndex, aEntry);
  1156 	}
  1157 
  1158 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle):
  1159     iSessionHandle(aSessionHandle),
  1160     iRandomSeed(0)
  1161     {
  1162     }
  1163 
  1164 TInt COpenFontSessionCacheList::AddCache(COpenFontSessionCache* aCache)
  1165 	{
  1166 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1167 		{
  1168 		if (iSessionHandleArray[index] == 0)
  1169 			{
  1170 			iSessionHandleArray[index] = aCache->SessionHandle();
  1171 			iCacheOffsetArray[index] = reinterpret_cast<TInt>(aCache) - reinterpret_cast<TInt>(this);
  1172 			return KErrNone;
  1173 			}
  1174 		}
  1175 	return KErrNoMemory;
  1176 	}
  1177 
  1178 COpenFontSessionCache* COpenFontSessionCacheList::FindCache(TInt aSessionHandle) const
  1179 	{
  1180 	if (aSessionHandle == 0)
  1181 		{
  1182 		return NULL;
  1183 		}
  1184 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1185 		{
  1186 		if (iSessionHandleArray[index] == aSessionHandle)
  1187 			{
  1188 			return reinterpret_cast<COpenFontSessionCache*>(reinterpret_cast<TInt>(this) + iCacheOffsetArray[index]);
  1189 			}
  1190 		}
  1191 	return NULL;
  1192 	}
  1193 
  1194 /** Delete all the items in the session cache if the current cache session handle
  1195 matches the passed session handle.
  1196 
  1197 @param aHeap The heap base of the current process.
  1198 @param aSessionHandle The session handle of the cache to be deleted.
  1199  */
  1200 void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
  1201 	{
  1202 	if (aSessionHandle == 0)
  1203 		{
  1204 		return;
  1205 		}
  1206 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1207 		{
  1208 		if (iSessionHandleArray[index] == aSessionHandle)
  1209 			{
  1210 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1211 			cache->Delete(aHeap);
  1212 			aHeap->Free(cache);
  1213 			iSessionHandleArray[index] = 0;
  1214 			iCacheOffsetArray[index] = 0;
  1215 			return;
  1216 			}
  1217         }
  1218 	}
  1219 
  1220 /** Delete all the items in the current session cache.
  1221 
  1222 @param aHeap The heap base of the current process.
  1223  */
  1224 void COpenFontSessionCacheList::Delete(RHeap* aHeap)
  1225 	{
  1226 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1227 		{
  1228 		if (iCacheOffsetArray[index] != 0)
  1229 			{
  1230 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1231 			cache->Delete(aHeap);
  1232 			aHeap->Free(cache);
  1233 			}
  1234 		}
  1235 	Mem::FillZ(this, sizeof(COpenFontSessionCacheList));
  1236 	}
  1237 
  1238 /**
  1239 Delete all glyphs belonging to a particular font.
  1240 */
  1241 void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
  1242 	{
  1243 	for (TInt index = 0; index < EMaxNumCaches; ++index)
  1244 		{
  1245 		if (iCacheOffsetArray[index] != 0)
  1246 			{
  1247 			COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
  1248 			TInt numEntries = cache->iEntryArray.Count();
  1249 			for (TInt i = 0; i < numEntries; ++i)
  1250 				{
  1251 				COpenFontSessionCacheEntry* entry = cache->iEntryArray[i];
  1252 				if (entry != NULL && entry->Font() == aFont)
  1253 					{
  1254 					COpenFontSessionCacheEntry::Delete(aHeap, entry);
  1255 					cache->iEntryArray.SetAt(i, NULL);
  1256 					}
  1257 				}
  1258 			}
  1259         }
  1260 	}
  1261 
  1262 /**
  1263 C++ constructor with a CFont parameter.
  1264 
  1265 This creates a TOpenFontMetrics and initialises it with size, ascent, maximum 
  1266 height, descent, maximum depth and maximum character width information from 
  1267 the CFont that was passed as a parameter.
  1268 
  1269 @param aFont The font from which to initialise the metrics object.
  1270 */
  1271 EXPORT_C TOpenFontMetrics::TOpenFontMetrics(const CFont* aFont)
  1272 	{
  1273 	iDesignHeight = (TInt16) aFont->HeightInPixels();
  1274 	iAscent = iMaxHeight = (TInt16) aFont->AscentInPixels();
  1275 	iDescent = iMaxDepth = (TInt16)(iDesignHeight - iAscent);
  1276 	iMaxWidth = (TInt16)aFont->MaxCharWidthInPixels();
  1277 	iBaselineCorrection = 0;
  1278 	}
  1279 
  1280 /** 
  1281 @publishedPartner
  1282 @prototype
  1283 
  1284 @param aBaselineCorrection The baseline correction to be associated with this font
  1285 
  1286 Sets the baseline correction applied to this font; this value is used to offset
  1287 the underlinke and strikethrough positions and is used by linked fonts only.
  1288 */
  1289 const TUint16 KBitsForUnderline = 10;
  1290 const TUint16 KMaskUnderline = (1<<KBitsForUnderline)-1;  //bottom bits which are set 
  1291 const TUint16 KMaskBitmapType = ~KMaskUnderline;  //top bits which are set
  1292 const TUint16 KSignBit = 1<<(KBitsForUnderline-1); //sign bit for the lower number, which can be signed
  1293 const TUint32 KTop16Of32Bits = 0xffff0000; 
  1294 
  1295 EXPORT_C void TOpenFontMetrics::SetBaselineCorrection(TInt aBaselineCorrection)
  1296 	{
  1297 	if (aBaselineCorrection >= (1<<(KBitsForUnderline-1)))
  1298 	    {
  1299 	    OstTrace1( TRACE_FATAL, TOPENFONTMETRICS_SETBASELINECORRECTION, "aBaselineCorrection=%d, Panic(EFntOverFlow)", aBaselineCorrection );
  1300 	    __ASSERT_DEBUG(0, Panic(EFntOverFlow));
  1301 	    }
  1302 	if (aBaselineCorrection <= (0-(1<<(KBitsForUnderline-1))))
  1303 	    {
  1304 	    OstTrace1( TRACE_FATAL, DUP1_TOPENFONTMETRICS_SETBASELINECORRECTION, "aBaselineCorrection=%d, Panic(EFntOverFlow)", aBaselineCorrection );
  1305 	    __ASSERT_DEBUG(0, Panic(EFntOverFlow));
  1306 	    }
  1307 	
  1308 	TUint16 value = iBaselineCorrection;
  1309 	value &=~KMaskUnderline; //zero all the underline position bits
  1310 	if (aBaselineCorrection<0)
  1311 		{
  1312 		//need to mask out extra sign bits for negative value
  1313 		iBaselineCorrection = value | (static_cast<TUint16>(aBaselineCorrection)&~KMaskBitmapType);
  1314 		}
  1315 	else
  1316 		{
  1317 		iBaselineCorrection = value | static_cast<TUint16>(aBaselineCorrection);
  1318 		}
  1319 	}
  1320 
  1321 /**
  1322 @publishedPartner
  1323 @prototype
  1324 
  1325 Gets the baseline correction applied to this font; this value is used to offset
  1326 the underlinke and strikethrough positions and is used by linked fonts only.
  1327 
  1328 @return The baseline correction associated with this font
  1329 */
  1330 
  1331 EXPORT_C TInt TOpenFontMetrics::BaselineCorrection()
  1332 	{
  1333 	TUint16 value = iBaselineCorrection;  //read once for improved multi threading
  1334 	if (!(value & KSignBit))
  1335 		{
  1336 		//value is positive, no need to sign extend
  1337 		return value & KMaskUnderline;
  1338 		}
  1339 	else
  1340 		{
  1341 		//value is negative, need to stuff ones into the high bits
  1342 		//could shift up and shift down
  1343 		return static_cast<TInt>(static_cast<TUint>(value) | KMaskBitmapType | KTop16Of32Bits);
  1344 		}
  1345 	}
  1346 
  1347 /**
  1348 C++ constructor with UID and filename.
  1349 
  1350 Call this constructor in the constructor for your derived object, passing 
  1351 it aUid and aFileName arguments.
  1352 
  1353 Non Symbian-platform-native font files are allocated IDs by the font store. 
  1354 These are passed in by the rasteriser class. UIDs are required by the 
  1355 font framework. However you should not use the ID to access the file, since 
  1356 a new UID will need to be allocated when the file is next loaded, e.g. after 
  1357 a device reboot. Instead use the font file name.
  1358 
  1359 @param aUid The UID of the font file.
  1360 @param aFileName The full filename, including the path, of the font file.
  1361 */
  1362 EXPORT_C COpenFontFile::COpenFontFile(TInt aUid, const TDesC& aFileName)
  1363  :	iFaceAttrib(1),
  1364 	iUid(TUid::Uid(aUid)),
  1365 	iFileName(aFileName),
  1366 	iFontList(8)
  1367 	{
  1368 	}
  1369 
  1370 /**
  1371 Destructor.
  1372 
  1373 It is not allowed that file is deleted before its fonts
  1374 and the logic is handled in CFontStore::RemoveFile().
  1375 */
  1376 EXPORT_C COpenFontFile::~COpenFontFile()
  1377 	{
  1378     CFontStore *fs = GetFontStore();
  1379     if (fs != NULL)
  1380         {
  1381         fs->CleanupCacheOnOpenFontFileRemoval(this);
  1382         }
  1383 	delete iData;
  1384 	}
  1385 
  1386 /**
  1387 Gets the nearest font in pixels.
  1388 
  1389 Implementations of this pure virtual function should create the COpenFont 
  1390 derived object that most closely matches aFontSpec, and place a pointer to 
  1391 it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
  1392 aFont should be set to NULL. 
  1393 	
  1394 The other two arguments, aHeap and aSessionCacheList, should be passed to 
  1395 the COpenFont constructor.
  1396 	
  1397 Implementations may use the utilitity function GetNearestFontHelper() to get 
  1398 the attributes of the closest matching font.
  1399 	
  1400 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
  1401 classes' constructor.
  1402 @param aSessionCacheList The session cache list. This value should be passed 
  1403 to the COpenFont derived classes' constructor.
  1404 @param aDesiredFontSpec The desired font specification.
  1405 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
  1406 the algorithmic slant of the typeface. 
  1407 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
  1408 the algorithmic slant of the typeface.
  1409 @param aFont On return, contains a pointer to the newly created COpenFont 
  1410 derived object, or NULL if no font matching aDesiredFontSpec exists.
  1411 @param aActualFontSpec The actual font specification of the font retrieved 
  1412 into aFont. 
  1413 @see GetNearestFontHelper()
  1414 @deprecated Use GetNearestFontToDesignHeightInPixels
  1415 */
  1416 TInt COpenFontFile::GetNearestFontInPixels(
  1417 	RHeap*						aHeap,
  1418 	COpenFontSessionCacheList*	aSessionCacheList,
  1419 	const TOpenFontSpec&		aDesiredFontSpec,
  1420 	TInt						aPixelWidth,
  1421 	TInt						aPixelHeight,
  1422 	COpenFont*&					aFont,
  1423 	TOpenFontSpec&				aActualFontSpec)
  1424 	{
  1425 	return GetNearestFontToDesignHeightInPixels(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec);
  1426 	}
  1427 
  1428 /**
  1429 Gets the nearest font in pixels.
  1430 
  1431 Implementations of this pure virtual function should create the COpenFont 
  1432 derived object that most closely matches aFontSpec, and place a pointer to 
  1433 it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
  1434 aFont should be set to NULL. 
  1435 	
  1436 The other two arguments, aHeap and aSessionCacheList, should be passed to 
  1437 the COpenFont constructor.
  1438 	
  1439 Implementations may use the utilitity function GetNearestFontHelper() to get 
  1440 the attributes of the closest matching font.
  1441 	
  1442 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
  1443 classes' constructor.
  1444 @param aSessionCacheList The session cache list. This value should be passed 
  1445 to the COpenFont derived classes' constructor.
  1446 @param aDesiredFontSpec The desired font specification.
  1447 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
  1448 the algorithmic slant of the typeface. 
  1449 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
  1450 the algorithmic slant of the typeface.
  1451 @param aFont On return, contains a pointer to the newly created COpenFont 
  1452 derived object, or NULL if no font matching aDesiredFontSpec exists.
  1453 @param aActualFontSpec The actual font specification of the font retrieved 
  1454 into aFont. 
  1455 @see GetNearestFontHelper()
  1456 */
  1457 TInt COpenFontFile::GetNearestFontToDesignHeightInPixels(
  1458 	RHeap*						aHeap,
  1459 	COpenFontSessionCacheList*	aSessionCacheList,
  1460 	const TOpenFontSpec&		aDesiredFontSpec,
  1461 	TInt						aPixelWidth,
  1462 	TInt						aPixelHeight,
  1463 	COpenFont*&					aFont,
  1464 	TOpenFontSpec&				aActualFontSpec)
  1465 	{
  1466 	aFont = NULL;
  1467 	TRAPD(error, GetNearestFontToDesignHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec));
  1468 	return error;
  1469 	}
  1470 
  1471 
  1472 void COpenFontFile::GetNearestFontToDesignHeightInPixelsAndAddToListL(
  1473 	RHeap*						aHeap,
  1474 	COpenFontSessionCacheList*	aSessionCacheList,
  1475 	const TOpenFontSpec&		aDesiredFontSpec,
  1476 	TInt						aPixelWidth,
  1477 	TInt						aPixelHeight,
  1478 	COpenFont*&					aFont,
  1479 	TOpenFontSpec&				aActualFontSpec)
  1480 	{
  1481 	COpenFont* fontPtr = NULL;
  1482 	GetNearestFontToDesignHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec);
  1483 	if (fontPtr != NULL)
  1484 		{ // found a matching font
  1485 		CleanupStack::PushL(fontPtr);
  1486 		iFontList.AppendL(fontPtr);
  1487 		// transfer ownership
  1488 		aFont = fontPtr;
  1489 		CleanupStack::Pop(fontPtr);
  1490 		}
  1491 	}
  1492 
  1493 
  1494 /**
  1495 Gets the nearest font in pixels that fits inside specified max height.
  1496 
  1497 Implementations of this pure virtual function should create the COpenFont 
  1498 derived object that most closely matches aFontSpec, while fitting within
  1499 aMaxHeight, and place a pointer to it in aFont. If this cannot be done,
  1500 e.g. if the font name doesn't match, aFont should be set to NULL. 
  1501 
  1502 The other two arguments, aHeap and aSessionCacheList, should be passed to 
  1503 the COpenFont constructor.
  1504 
  1505 Implementations may use the utilitity function GetNearestFontHelper()
  1506 to get the attributes of the closest matching font.
  1507 
  1508 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
  1509 classes' constructor.
  1510 @param aSessionCacheList The session cache list. This value should be passed 
  1511 to the COpenFont derived classes' constructor.
  1512 @param aDesiredFontSpec The desired font specification.
  1513 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
  1514 the algorithmic slant of the typeface. 
  1515 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
  1516 the algorithmic slant of the typeface.
  1517 @param aFont On return, contains a pointer to the newly created COpenFont 
  1518 derived object, or NULL if no font matching aDesiredFontSpec exists.
  1519 @param aActualFontSpec The actual font specification of the font retrieved 
  1520 into aFont. 
  1521 @param aMaxHeight The maximum height within which the font must fit.
  1522 @see GetNearestFontHelper()
  1523 */
  1524 TInt COpenFontFile::GetNearestFontToMaxHeightInPixels(
  1525 	RHeap*						aHeap,
  1526 	COpenFontSessionCacheList*	aSessionCacheList,
  1527 	const TOpenFontSpec&		aDesiredFontSpec,
  1528 	TInt						aPixelWidth,
  1529 	TInt						aPixelHeight,
  1530 	COpenFont*&					aFont,
  1531 	TOpenFontSpec&				aActualFontSpec,
  1532 	TInt						aMaxHeight)
  1533 	{
  1534 	aFont = NULL;
  1535 	TRAPD(error, GetNearestFontToMaxHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec, aMaxHeight));
  1536 	return error;
  1537 	}
  1538 
  1539 
  1540 void COpenFontFile::GetNearestFontToMaxHeightInPixelsAndAddToListL(
  1541 	RHeap*						aHeap,
  1542 	COpenFontSessionCacheList*	aSessionCacheList,
  1543 	const TOpenFontSpec&		aDesiredFontSpec,
  1544 	TInt						aPixelWidth,
  1545 	TInt						aPixelHeight,
  1546 	COpenFont*&					aFont,
  1547 	TOpenFontSpec&				aActualFontSpec,
  1548 	TInt						aMaxHeight)
  1549 	{
  1550 	COpenFont* fontPtr = NULL;
  1551 	GetNearestFontToMaxHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec, aMaxHeight);
  1552 	if (fontPtr != NULL)
  1553 		{  // found a matching font
  1554 		CleanupStack::PushL(fontPtr);
  1555 		iFontList.AppendL(fontPtr);
  1556 		// transfer ownership
  1557 		aFont = fontPtr;
  1558 		CleanupStack::Pop(fontPtr);
  1559 		}
  1560 	}
  1561 
  1562 
  1563 /**
  1564 Gets the nearest font helper function.
  1565 
  1566 This function may be used by derived classes in their GetNearestFontInPixelsL() 
  1567 implementations. It finds the nearest font in the typeface attribute array, 
  1568 if any, to the provided font specification. If there is a possible match it 
  1569 places the face index in aFaceIndex and the actual specification (including 
  1570 algorithmic effects) in aActualFontSpec.
  1571 
  1572 @param aDesiredFontSpec The desired font specification.
  1573 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
  1574 the algorithmic slant of the typeface.
  1575 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
  1576 the algorithmic slant of the typeface.
  1577 @param aFaceIndex The index of the typeface which contains the closest match 
  1578 to aDesiredFontSpec.
  1579 @param aActualFontSpec The actual font specification of the font with attributes 
  1580 closest to aDesiredFontSpec.
  1581 @return ETrue if there is a possible font match, otherwise EFalse.
  1582 */
  1583 EXPORT_C TBool COpenFontFile::GetNearestFontHelper(
  1584 	const TOpenFontSpec&	aDesiredFontSpec,
  1585 	TInt					aPixelWidth,
  1586 	TInt					aPixelHeight,
  1587 	TInt&					aFaceIndex,
  1588 	TOpenFontSpec&			aActualFontSpec) const
  1589 	{
  1590 	const TInt faces = FaceCount();
  1591 	TInt best_points = 0;
  1592 	TInt best_index = -1;
  1593 
  1594 	for (TInt i = 0; i < faces; i++)
  1595 		{
  1596 		TInt cur_points = 0;
  1597 
  1598 		if (0 < aDesiredFontSpec.Name().Length())
  1599 			{
  1600 			cur_points = ScoreByName(aDesiredFontSpec, iFaceAttrib[i]);
  1601 			}
  1602 		else
  1603 			{
  1604 			cur_points = ScoreByStyle(aDesiredFontSpec, iFaceAttrib[i]);
  1605 			}
  1606 
  1607 		if (cur_points)
  1608 			{
  1609 			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
  1610 				cur_points++;
  1611 			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
  1612 				cur_points++;
  1613 			}
  1614 
  1615 		if (cur_points > best_points)
  1616 			{
  1617 			best_points = cur_points;
  1618 			best_index = i;
  1619 			}
  1620 		}
  1621 
  1622 	if (best_index != -1)
  1623 		{
  1624 		aActualFontSpec = aDesiredFontSpec;
  1625 		// copy attributes & name
  1626 		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
  1627 		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
  1628 		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
  1629 		if ((aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[best_index].IsItalic()) && (0 == aDesiredFontSpec.SlantFactor()))
  1630 			{
  1631 			TInt factor = KDefaultSlantFactor;
  1632 			if (TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
  1633 				{
  1634 				TOpenFontSpec::ApplyRatio(factor, aPixelWidth, aPixelHeight);
  1635 				}
  1636 			aActualFontSpec.SetSlantFactor(factor);
  1637 			}
  1638 		}
  1639 
  1640 	aFaceIndex = best_index;
  1641 	return best_index != -1;
  1642 	}
  1643 
  1644 TInt COpenFontFile::ScoreByName(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
  1645 	{
  1646 	if (!aDesiredFontSpec.Name().CompareF(aAttrib.FullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFullName()))
  1647 		{
  1648 		return 4;
  1649 		}
  1650 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFullName()))
  1651 		{
  1652 		return 3;
  1653 		}
  1654 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.FamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFamilyName()))
  1655 		{
  1656 		return 2;
  1657 		}
  1658 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFamilyName()))
  1659 		{
  1660 		return 1;
  1661 		}
  1662 	return 0;
  1663 	}
  1664 
  1665 TInt COpenFontFile::ScoreByStyle(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
  1666 	{
  1667 	if (aDesiredFontSpec.IsSymbol() == aAttrib.IsSymbol())
  1668 		{
  1669 		return 4;
  1670 		}
  1671 	else if(aDesiredFontSpec.IsMonoWidth() == aAttrib.IsMonoWidth())
  1672 		{
  1673 		return 3;
  1674 		}
  1675 	else if(aDesiredFontSpec.IsSerif() == aAttrib.IsSerif())
  1676 		{
  1677 		return 2;
  1678 		}
  1679 
  1680 	return 0;
  1681 	}
  1682 
  1683 #ifdef _DEBUG
  1684 /**  @internalComponent */
  1685 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec& aDesiredFontSpec, TInt aPixelWidth,TInt aPixelHeight,TInt& aFaceIndex, TOpenFontSpec& aActualFontSpec) const
  1686 	{
  1687 	TInt faces = FaceCount();
  1688 	TInt best_points = 0;
  1689 	TInt best_index = -1;
  1690 	TBool slant = FALSE;
  1691 	for (TInt i = 0; i < faces; i++)
  1692 		{
  1693 		TPtrC family_name = iFaceAttrib[i].FamilyName();
  1694 		TPtrC full_name = iFaceAttrib[i].FullName();
  1695 		TPtrC local_family_name = iFaceAttrib[i].LocalFamilyName();
  1696 		TPtrC local_full_name = iFaceAttrib[i].LocalFullName();
  1697 		TPtrC desired_name = aDesiredFontSpec.Name();
  1698 
  1699 		TInt cur_points = 0;
  1700 		if (desired_name.Length() > 0)
  1701 			{
  1702 			if ((full_name.CompareF(desired_name) == 0) || (local_full_name.CompareF(desired_name) == 0))
  1703 				cur_points = 4;
  1704 			else if ((family_name.CompareF(desired_name) == 0) || (local_family_name.CompareF(desired_name) == 0))
  1705 				cur_points = 2;
  1706 			}
  1707 		else
  1708 			{
  1709 			if ((aDesiredFontSpec.IsSerif() == iFaceAttrib[i].IsSerif()) && (aDesiredFontSpec.IsMonoWidth() == iFaceAttrib[i].IsMonoWidth()) && (aDesiredFontSpec.IsSymbol() == iFaceAttrib[i].IsSymbol()))
  1710 				cur_points = 2;
  1711 			}
  1712 		if (cur_points)
  1713 			{
  1714 			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
  1715 				cur_points++;
  1716 			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
  1717 				cur_points++;
  1718 			if (cur_points > best_points)
  1719 				{
  1720 				best_points = cur_points;
  1721 				best_index = i;
  1722 				slant = (aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[i].IsItalic());
  1723 				}
  1724 			}
  1725 		}
  1726 
  1727 	if (best_index != -1)
  1728 		{
  1729 		TInt32 slant_factor = aDesiredFontSpec.SlantFactor();
  1730 
  1731 		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
  1732 		if (slant && slant_factor == 0)
  1733 			{
  1734 			slant_factor = KDefaultSlantFactor;
  1735 			if (aPixelWidth>0 && aPixelHeight>0 && TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth,aPixelHeight))
  1736 				{
  1737 				TOpenFontSpec::ApplyRatio(slant_factor,aPixelWidth,aPixelHeight);
  1738 				}
  1739 			}
  1740 
  1741 		aActualFontSpec = aDesiredFontSpec;
  1742 		// copy attributes & name
  1743 		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
  1744 		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
  1745 		aActualFontSpec.SetSlantFactor(slant_factor);
  1746 		aActualFontSpec.SetEffects(0);
  1747 		}
  1748 
  1749 	aFaceIndex = best_index;
  1750 	return best_index != -1;
  1751 	}
  1752 #else //_DEBUG
  1753 /**
  1754 @internalComponent
  1755 */
  1756 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec&, TInt, TInt, TInt&, TOpenFontSpec&) const 
  1757 	{
  1758 	return EFalse;
  1759 	}
  1760 #endif //_DEBUG
  1761 
  1762 /** This function is called (via iFile) by a COpenFont when it is destroyed. */
  1763 void COpenFontFile::RemoveFontFromList(const COpenFont* aFont)
  1764 	{
  1765 	TInt fonts = iFontList.Count();
  1766 	for (TInt i = 0; i < fonts; i++)
  1767 		if (iFontList[i] == aFont)
  1768 			{
  1769 			iFontList.Delete(i);
  1770 			break;
  1771 			}
  1772 	}
  1773 
  1774 /**
  1775 Adds a typeface to this object's typeface array.
  1776 
  1777 This function should be called during construction to add the attributes for 
  1778 each typeface in the font file to the typeface attribute array. 
  1779 
  1780 Note:
  1781 
  1782 The typeface array is what is searched for the closest match to a specified 
  1783 font by GetNearestFontHelper().
  1784 
  1785 @param aAttrib The attributes for a typeface to be added to the typeface attribute 
  1786 array.
  1787 @see FaceAttrib()
  1788 @see FaceCount()
  1789 */
  1790 EXPORT_C void COpenFontFile::AddFaceL(const TOpenFontFaceAttrib& aAttrib)
  1791 	{
  1792 	TAttrib& a = iFaceAttrib.ExtendL();
  1793 	(TOpenFontFaceAttrib&)a = aAttrib;
  1794 	}
  1795 
  1796 void COpenFontFile::SetFontStoreL(CFontStore* aFontStore)
  1797 	{
  1798 	if (iData == NULL)
  1799 		{
  1800 		iData = new (ELeave) TOpenFontFileData;
  1801 		}
  1802 	iData->iFontStore = aFontStore;
  1803 	}
  1804 
  1805 CFontStore* COpenFontFile::GetFontStore()
  1806 	{
  1807 	return iData ? iData->iFontStore : NULL;
  1808 	}
  1809 
  1810 CArrayPtrFlat<COpenFont>* COpenFontFile::GetOpenFontList()
  1811 	{
  1812 	return &iFontList;
  1813 	}
  1814 
  1815 
  1816 static const TInt KTOpenFontSpecBitsNumSymbol = 1;
  1817 static const TInt KTOpenFontSpecBitsNumScript = 4;
  1818 static const TInt KTOpenFontSpecMaskSymbol = (1 << KTOpenFontSpecBitsNumSymbol) - 1;
  1819 static const TInt KTOpenFontSpecMaskScript = ((1 << KTOpenFontSpecBitsNumScript) - 1) << KTOpenFontSpecBitsNumSymbol;
  1820 static const TInt KTOpenFontSpecSymbolFlag = 0x1;
  1821 
  1822 /**
  1823 Default C++ constructor setting
  1824 height to 16 pixels or twips,
  1825 width factor to 1 (65536 in 16.16 format),
  1826 slant factor to 0 (no slant),
  1827 effects to ENone,
  1828 symbol to 0 (assuming EScriptNone = 0),
  1829 print position to EPrintPosNormal.
  1830 */
  1831 EXPORT_C TOpenFontSpec::TOpenFontSpec()
  1832  :	iHeight(16),
  1833 	iWidthFactor(KOneIn16Dot16FixedPointFormat),
  1834 	iSlantFactor(0),
  1835 	iBitmapType(0),
  1836 	iEffects(FontEffect::ENone),
  1837 	iSymbol(0),
  1838 	iPrintPosition(EPrintPosNormal),
  1839 	iReserved2(0)
  1840 	{
  1841 	}
  1842 
  1843 /**
  1844 C++ constructor taking a reference to a TFontSpec.
  1845 
  1846 This object's members are initialised from the values of the aFontSpec parameter.
  1847 
  1848 @param aFontSpec The font specification used to initialise this font specification.
  1849 */
  1850 EXPORT_C TOpenFontSpec::TOpenFontSpec(const TFontSpec& aFontSpec)
  1851 	{
  1852 	*this = aFontSpec;
  1853 	}
  1854 
  1855 /**
  1856 Assignment operator.
  1857 
  1858 @param aFontSpec The old-style font specification to copy into this font specification.
  1859 */
  1860 EXPORT_C void TOpenFontSpec::operator=(const TFontSpec& aFontSpec)
  1861 	{
  1862 	iSlantFactor = 0;
  1863 	iWidthFactor = KOneIn16Dot16FixedPointFormat;
  1864 	iHeight			= aFontSpec.iHeight;	// in twips
  1865 	iBitmapType		= aFontSpec.iFontStyle.BitmapType();
  1866 	iEffects		= aFontSpec.iFontStyle.Effects();
  1867 	iPrintPosition	= aFontSpec.iFontStyle.PrintPosition();
  1868 	iName			= aFontSpec.iTypeface.iName;
  1869 	SetScriptTypeForMetrics(aFontSpec.iTypeface.ScriptTypeForMetrics());
  1870 	const TBool symbol = aFontSpec.iTypeface.IsSymbol();
  1871 	SetSymbol(symbol);
  1872 	if (symbol)
  1873 		SetCoverage(0);	// no appropriate coverage value for the symbol set
  1874 	else
  1875 		SetCoverage(3);	// Latin and Latin-1 supplement
  1876 	iStyle = 0;
  1877 	if (!aFontSpec.iTypeface.IsProportional())
  1878 		iStyle |= TOpenFontFaceAttrib::EMonoWidth;
  1879 	if (aFontSpec.iTypeface.IsSerif())
  1880 		iStyle |= TOpenFontFaceAttrib::ESerif;
  1881 	if (aFontSpec.iFontStyle.Posture() == EPostureItalic)
  1882 		iStyle |= TOpenFontFaceAttrib::EItalic;
  1883 	if (aFontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
  1884 		iStyle |= TOpenFontFaceAttrib::EBold;
  1885 	}
  1886 
  1887 
  1888 /**
  1889 Adjust the width factor and slant factor to suit a pixel aspect ratio.
  1890 @publishedAll
  1891 @released
  1892 @param aPixelWidth The pixel width, in the same units as aPixelHeight.
  1893 @param aPixelHeight The pixel height, in the same units as aPixelWidth.
  1894 */
  1895 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(TInt aPixelWidth, TInt aPixelHeight)
  1896 	{
  1897 	if (IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
  1898 		{
  1899 		ApplyRatio(iWidthFactor, aPixelHeight, aPixelWidth);
  1900 		ApplyRatio(iSlantFactor, aPixelWidth, aPixelHeight);
  1901 		}
  1902 	}
  1903 
  1904 /**
  1905 Adjust the width factor and slant factor to suit a pixel aspect ratio stored 
  1906 in a MGraphicsDeviceMap derived object.
  1907 @publishedAll
  1908 @released
  1909 @param aMap The MGraphicsDeviceMap defining the pixel aspect ratio.
  1910 */
  1911 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(const MGraphicsDeviceMap& aMap)
  1912 	{
  1913 	CompensateForAspectRatio(aMap.HorizontalPixelsToTwips(1000), aMap.VerticalPixelsToTwips(1000));
  1914 	}
  1915 
  1916 /**
  1917 The pixel width and height are used to derive a ratio, and so can be 
  1918 in any units. Aspect ratios differing by less than 1/1000 are treated as 1:1.
  1919 @internalTechnology
  1920 */
  1921 TBool TOpenFontSpec::IsCompensationForAspectRatioNeeded(TInt aPixelWidth,TInt aPixelHeight)
  1922 	{
  1923 	if ((aPixelWidth != aPixelHeight) && (0 < aPixelWidth) && (0 < aPixelHeight))
  1924 		{
  1925 		//If nearly square don't transform (0.999 < aPixelHeight/aPixelWidth < 1.001)
  1926 		TInt64 width = aPixelWidth;
  1927 		TInt64 height = aPixelHeight;
  1928 		width *= 999;	// Cannot do multiplication on declaration lines above as risk of TInt32 overflow
  1929 		height *= 1000;
  1930 		if (width <= height)	// 999 * aPixelWidth <= 1000 * aPixelHeight
  1931 			return ETrue;
  1932 		width += aPixelWidth;
  1933 		width += aPixelWidth;	// Cannot do with previous line as small risk of TInt32 overflow
  1934 		if (width >= height)	// 1001 * aPixelWidth >= 1000 * aPixelHeight
  1935 			return ETrue;
  1936 		}
  1937 	return EFalse;
  1938 	}
  1939 
  1940 /**
  1941 Multiplies aValue by aNumerator/aDenominator but using TInt64's to avoid any overflows.
  1942 Returns ETrue if the final result has an overflow.
  1943 @internalTechnology
  1944 */
  1945 TBool TOpenFontSpec::ApplyRatio(TInt& aValue, TInt aNumerator, TInt aDenominator)
  1946 	{
  1947 	TInt64 value(aValue);
  1948 	value = (value * aNumerator) / aDenominator;
  1949 	aValue = I64LOW(value);
  1950 	if (I64HIGH(value) != 0)
  1951 	    {
  1952 	    OstTrace1( TRACE_FATAL, TOPENFONTSPEC_APPLYRATIO, "value=%ld, Panic(EFntOverFlow)", value );
  1953 	    __ASSERT_DEBUG(0, Panic(EFntOverFlow));
  1954 	    }
  1955 	return I64HIGH(value) != 0;
  1956 	}
  1957 
  1958 /**
  1959 Same as above function but this takes a TInt32 not a TInt
  1960 */
  1961 TBool TOpenFontSpec::ApplyRatio(TInt32& aValue, TInt aNumerator, TInt aDenominator)
  1962 	{
  1963 	TInt value = aValue;
  1964 	TBool ret = ApplyRatio(value, aNumerator, aDenominator);
  1965 	aValue = value;
  1966 	return ret;
  1967 	}
  1968 
  1969 EXPORT_C void TOpenFontSpec::SetAttrib(const TOpenFontFaceAttribBase& aAttrib)
  1970 /**
  1971 Sets the font attributes.
  1972 
  1973 @param aAttrib The font attributes.
  1974 */
  1975 	{
  1976 	TOpenFontFaceAttribBase* self = this;
  1977 	*self = aAttrib;
  1978 	}
  1979 
  1980 /**
  1981 Gets the TFontSpec corresponding to this Open Font System font specification.
  1982 @publishedAll
  1983 @released
  1984 @param aFontSpec On return, contains the TFontSpec corresponding to this font 
  1985 specification.
  1986 */
  1987 EXPORT_C void TOpenFontSpec::GetTFontSpec(TFontSpec& aFontSpec) const
  1988 	{
  1989 	aFontSpec = TFontSpec();
  1990 	TPtrC short_name(iName.Ptr(), Min(iName.Length(), KMaxTypefaceNameLength));
  1991 	aFontSpec.iTypeface.iName = short_name;
  1992 	aFontSpec.iTypeface.SetIsProportional(!IsMonoWidth());
  1993 	aFontSpec.iTypeface.SetIsSerif(IsSerif());
  1994 	aFontSpec.iTypeface.SetIsSymbol(Symbol());
  1995 	aFontSpec.iTypeface.SetScriptTypeForMetrics(ScriptTypeForMetrics());
  1996 	aFontSpec.iHeight = iHeight;	// as twips
  1997 	if (IsItalic() || (iSlantFactor > 0))
  1998 		aFontSpec.iFontStyle.SetPosture(EPostureItalic);
  1999 	if (IsBold() || IsEffectOn(FontEffect::EAlgorithmicBold))
  2000 		aFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
  2001 	aFontSpec.iFontStyle.SetPrintPosition(iPrintPosition);
  2002 	aFontSpec.iFontStyle.SetBitmapType(BitmapType());
  2003 	aFontSpec.iFontStyle.SetEffects(iEffects);
  2004 	}
  2005 
  2006 /**
  2007 Sets a font effect to the given state.
  2008 @publishedAll
  2009 @released
  2010 @param aEffect The font effect to be set.
  2011 @param aOn True represents on, otherwise off.
  2012 @see TOpenFontSpec::IsEffectOn()
  2013 */
  2014 EXPORT_C void TOpenFontSpec::SetEffects(FontEffect::TEffect aEffect, TBool aOn)
  2015 	{
  2016 	FontEffect::SetEffect(aEffect, aOn, iEffects);
  2017 	}
  2018 
  2019 /** Checks if a font effect is on.
  2020 @publishedAll
  2021 @released
  2022 @return True represents the specified font effect is on, otherwise off.
  2023 @param aEffect The font effect to be checked.
  2024 @see TOpenFontSpec::SetEffects()
  2025 */
  2026 EXPORT_C TBool TOpenFontSpec::IsEffectOn(FontEffect::TEffect aEffect) const
  2027 	{
  2028 	return FontEffect::IsEffectOn(aEffect, iEffects);
  2029 	}
  2030 
  2031 /**
  2032 @deprecated This needs to be maintained to just call the inline methods.
  2033 */
  2034 EXPORT_C void TOpenFontSpec::DoSetEffects(TUint32 aEffects)
  2035 	{
  2036 	SetEffects(aEffects);
  2037 	}
  2038 
  2039 /**
  2040 @deprecated This needs to be maintained to just call the inline methods.
  2041 */
  2042 EXPORT_C TUint32 TOpenFontSpec::DoEffects() const
  2043 	{
  2044 	return Effects();
  2045 	}
  2046 
  2047 /**
  2048 Specifies the script which font metrics calculation will be based on.
  2049 @publishedAll
  2050 @released
  2051 @param aLanguage The language used to derive the required script.
  2052 */
  2053 EXPORT_C void TOpenFontSpec::SetScriptTypeForMetrics(TLanguage aLanguage)
  2054 	{
  2055 	SetScriptTypeForMetrics(GlyphSample::TLanguage2TScript(aLanguage));
  2056 	}
  2057 
  2058 /**
  2059 @internalTechnology
  2060 */
  2061 void TOpenFontSpec::SetScriptTypeForMetrics(TInt aScript)
  2062 	{
  2063 	iSymbol &= ~KTOpenFontSpecMaskScript;
  2064 	iSymbol |= (KTOpenFontSpecMaskScript & (aScript << KTOpenFontSpecBitsNumSymbol));
  2065 	}
  2066 
  2067 /**
  2068 Gets the script which the font metrics calculation will be based on.
  2069 @internalTechnology
  2070 @return The script.
  2071 */
  2072 EXPORT_C TInt TOpenFontSpec::ScriptTypeForMetrics() const
  2073 	{
  2074 	return (KTOpenFontSpecMaskScript & iSymbol) >> KTOpenFontSpecBitsNumSymbol;
  2075 	}
  2076 
  2077 /**
  2078 @internalTechnology
  2079 */
  2080 void TOpenFontSpec::SetSymbol(TBool aSymbol)
  2081 	{
  2082 	iSymbol &= ~KTOpenFontSpecMaskSymbol;
  2083 	iSymbol |= (aSymbol ? KTOpenFontSpecSymbolFlag : 0);
  2084 	}
  2085 
  2086 /**
  2087 @internalTechnology
  2088 */
  2089 TBool TOpenFontSpec::Symbol() const
  2090 	{
  2091 	return (KTOpenFontSpecSymbolFlag & iSymbol) > 0;
  2092 	}
  2093 
  2094 /**
  2095 @deprecated This needs to be maintained to just call the inline methods.
  2096 */
  2097 EXPORT_C TBool TOpenFontSpec::OperatorEquality(const TOpenFontSpec& aOpenFontSpec) const
  2098 	{
  2099 	return this->operator == (aOpenFontSpec);
  2100 	}
  2101 
  2102 /**
  2103 @internalTechnology
  2104 */
  2105 TBool TOpenFontSpec::operator!=(const TOpenFontSpec& aOpenFontSpec) const
  2106 	{
  2107 	return !(this->operator == (aOpenFontSpec));
  2108 	}
  2109 
  2110 /**
  2111 Static constructor for a TOpenFontGlyphData.
  2112 
  2113 This constructor creates the object on a specified heap. It must be deleted 
  2114 using RHeap::Free().
  2115 
  2116 @param aHeap The shared heap on which the object is constructed.
  2117 @param aBufferSize The amount of memory allocated for the glyph data.
  2118 @return A pointer to the newly created object.
  2119 */
  2120 EXPORT_C TOpenFontGlyphData* TOpenFontGlyphData::New(RHeap* aHeap, TInt aBufferSize)
  2121 	{
  2122 	if (aBufferSize < 1)
  2123 		aBufferSize = 1;
  2124 	TInt bytes = sizeof(TOpenFontGlyphData) + aBufferSize - 1;
  2125 	TOpenFontGlyphData* g = (TOpenFontGlyphData*)aHeap->Alloc(bytes);
  2126 	if (g != NULL)
  2127 		{
  2128 		Mem::FillZ(g, bytes);
  2129 		g->iBitmapBufferSize = aBufferSize;
  2130 		}
  2131 	return g;
  2132 	}
  2133 
  2134 // Virtual functions reserved for future expansion.
  2135 /**
  2136 @publishedPartner
  2137 @prototype
  2138 */
  2139 EXPORT_C void COpenFontRasterizer::ExtendedInterface(TUid, TAny*&)
  2140 	{
  2141 	}
  2142 
  2143 /** @internalComponent */
  2144 EXPORT_C void COpenFontFile::ExtendedInterface(TUid, TAny*&)
  2145 	{
  2146 	}
  2147 
  2148 EXPORT_C void COpenFont::ExtendedInterface(TUid, TAny*&)
  2149 	{
  2150 	}
  2151 	
  2152 EXPORT_C CShaper::CShaper()
  2153 	{
  2154 	
  2155 	}
  2156 	
  2157 EXPORT_C CShaper::~CShaper()
  2158 	{
  2159 	
  2160 	}
  2161 /** @internalComponent */
  2162 EXPORT_C void* CShaper::ExtendedInterface(TUid)
  2163 	{
  2164 	return 0;
  2165 	}
  2166 
  2167 /**
  2168 Sets the glyph bitmap type.
  2169 
  2170 Normally the bitmap type belongs to the font, but for linked fonts this can 
  2171 be different between different font elements making up the linked font.
  2172 
  2173 Note: This is only of use in conjunction with rasterizer based linked fonts.
  2174 
  2175 @publishedPartner
  2176 @prototype
  2177 */
  2178 EXPORT_C void TOpenFontCharMetrics::SetGlyphType(TGlyphBitmapType aGlyphBitmapType)
  2179 	{
  2180 	iGlyphBitmapType = aGlyphBitmapType;
  2181 	}
  2182 
  2183 /**
  2184 Gets the glyph bitmap type.
  2185 
  2186 @publishedPartner
  2187 @prototype
  2188 */
  2189 EXPORT_C TGlyphBitmapType TOpenFontCharMetrics::GlyphType() const
  2190 	{
  2191 	if (iGlyphBitmapType == 0)
  2192 		return EGlyphBitmapTypeNotDefined;
  2193 	else
  2194 		return static_cast<TGlyphBitmapType>(iGlyphBitmapType);
  2195 	}