fontservices/fontstore/src/OPENFONT.CPP
changeset 0 1fb32624e06b
child 5 e96e8a131979
child 21 f2f7b3284356
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 2003-2009 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 
       
    30 const TInt KSessionCacheEntries = 512;
       
    31 const TInt KDefaultSlantFactor = 20480;
       
    32 const TInt KOneIn16Dot16FixedPointFormat = 65536;
       
    33 
       
    34 #ifdef FNTSTORE_SUPPORT_FMM
       
    35 class TPointerArrayBaseOffset
       
    36 	{
       
    37 public:
       
    38 	TInt iCount;
       
    39 	TAny** iEntries;
       
    40 	TInt iAllocated;
       
    41 	TInt iGranularity;
       
    42 	};
       
    43 
       
    44 /*RArrayGlyphEntries*/
       
    45 
       
    46 inline const COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex) const
       
    47 	{
       
    48 	return *Entry(anIndex);
       
    49 	}
       
    50 
       
    51 inline COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex)
       
    52 	{
       
    53 	return *const_cast<COpenFontGlyphTreeEntry*>(Entry(anIndex));
       
    54 	}
       
    55 
       
    56 inline const COpenFontGlyphTreeEntry* RArrayGlyphEntries::Entry(TInt anIndex) const
       
    57 	{
       
    58 	return reinterpret_cast<const COpenFontGlyphTreeEntry*>(PtrAdd(EntryMemberOffSet()[anIndex],reinterpret_cast<TInt>(this)));
       
    59 	}
       
    60 
       
    61 inline COpenFontGlyphTreeEntry** RArrayGlyphEntries::EntryMemberOffSet() const
       
    62 	{
       
    63 	return reinterpret_cast<COpenFontGlyphTreeEntry**>(iEntriesOffset+reinterpret_cast<TInt>(this));
       
    64 	}
       
    65 
       
    66 inline TAny** RArrayGlyphEntries::EntryMember() const
       
    67 	{
       
    68 	return reinterpret_cast<const TPointerArrayBaseOffset*>(this)->iEntries;
       
    69 	}
       
    70 
       
    71 TInt RArrayGlyphEntries::Append(COpenFontGlyphTreeEntry& anEntry)
       
    72 	{		
       
    73 	TInt err = RArray<TInt>::Append(reinterpret_cast<TInt>(&anEntry)-reinterpret_cast<TInt>(this));
       
    74 	if (err == KErrNone)
       
    75 		{
       
    76 		iEntriesOffset=reinterpret_cast<TInt>(EntryMember())-reinterpret_cast<TInt>(this);
       
    77 		}
       
    78 	return err;
       
    79 	}
       
    80 #endif // FNTSTORE_SUPPORT_FMM
       
    81 
       
    82 /*COpenFontGlyphCache*/
       
    83 
       
    84 TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams)
       
    85 	{
       
    86 	if (iShaperCacheSentinel == NULL)
       
    87 		return NULL;
       
    88 	COpenFontShaperCacheEntry* searchNode = iShaperCacheSentinel->iNext;
       
    89 	
       
    90 	TInt start = aParams->iStart;
       
    91 	TInt end = aParams->iEnd;
       
    92 	TInt script = aParams->iScript;
       
    93 	const TUint16* text = (TUint16*)aParams->iText->Ptr();
       
    94 	TUint16* cachedText;
       
    95 	const TUint16* copyOfText;
       
    96 	TInt noOfChars = end - start;
       
    97 	TInt textIsSame = 1;
       
    98 	while (searchNode != iShaperCacheSentinel)
       
    99 		{
       
   100 		//Future work: add Script check for further script support
       
   101 		//Future work: add Language check for further language support
       
   102 		if ((searchNode->iEnd == end) && (searchNode->iStart == start) && (searchNode->iScript == script))
       
   103 			{
       
   104 			// Check for the entire text (within the context) coming in.
       
   105 			TInt i = 0;
       
   106 			copyOfText = text + start;
       
   107 			cachedText = (TUint16*)searchNode->iText + searchNode->iStart;
       
   108 			textIsSame = 1;
       
   109 			while (i < noOfChars && textIsSame != 0)
       
   110 				{
       
   111 				if (*cachedText != *copyOfText)
       
   112 					textIsSame = 0;
       
   113 				i++;
       
   114 				copyOfText++;
       
   115 				cachedText++;
       
   116 				};
       
   117 
       
   118 			if (textIsSame)
       
   119 				{
       
   120 				if (searchNode == iShaperCacheSentinel->iNext)
       
   121 					{
       
   122 					// now we need to update the reference count here for that session
       
   123 					if (searchNode->IncRefCount(aSessionHandle) != KErrNone)
       
   124 						return NULL;
       
   125 					return iShaperCacheSentinel->iNext->iShapeHeader;
       
   126 					}
       
   127 				// We have found a node, now put that node to the top of the list as the most recently used node
       
   128 				searchNode->iPrevious->iNext = searchNode->iNext;
       
   129 				searchNode->iNext->iPrevious = searchNode->iPrevious;
       
   130 				
       
   131 				searchNode->iNext = iShaperCacheSentinel->iNext;
       
   132 				iShaperCacheSentinel->iNext->iPrevious = searchNode;
       
   133 				iShaperCacheSentinel->iNext = searchNode;
       
   134 				searchNode->iPrevious = iShaperCacheSentinel;
       
   135 				if (searchNode->IncRefCount(aSessionHandle)!= KErrNone)
       
   136 					return NULL;
       
   137 				return searchNode->iShapeHeader;
       
   138 				}
       
   139 			}
       
   140 			searchNode = searchNode->iNext;
       
   141 		}
       
   142 	return NULL;
       
   143 	}
       
   144 
       
   145 TShapeHeader* COpenFontGlyphCache::Insert(TInt aSessionHandle, RHeap* aHeap, CShaper::TInput aInput, TShapeHeader* aShapeHeader, TInt& aAddedBytes)
       
   146 	{
       
   147 	TInt heapSizeBefAloc = 0;
       
   148 	aHeap->AllocSize(heapSizeBefAloc);
       
   149 
       
   150 	COpenFontShaperCacheEntry* new_entry;
       
   151 	new_entry = COpenFontShaperCacheEntry::New(aHeap, aInput, aShapeHeader);
       
   152 	if (new_entry)
       
   153 		{
       
   154 		// increase the reference count for this
       
   155 		TInt ret=new_entry->IncRefCount(aSessionHandle);
       
   156 		if (ret != KErrNone)
       
   157 			{
       
   158 			//no memory here
       
   159 			COpenFontShaperCacheEntry::Delete(aHeap, new_entry);
       
   160 			return NULL;
       
   161 			}
       
   162 		new_entry->iNext = iShaperCacheSentinel->iNext;
       
   163 		iShaperCacheSentinel->iNext->iPrevious = new_entry;
       
   164 		iShaperCacheSentinel->iNext = new_entry;
       
   165 		new_entry->iPrevious = iShaperCacheSentinel;
       
   166 
       
   167 		iNumberOfShaperCacheEntries++;
       
   168 		TInt heapSizeOnAloc = 0;
       
   169 		aHeap->AllocSize(heapSizeOnAloc);
       
   170 		aAddedBytes = heapSizeOnAloc - heapSizeBefAloc;
       
   171 
       
   172 		// Update the amount of memory used in creation of a new entry
       
   173 		iShapingInfoCacheMemory += heapSizeOnAloc - heapSizeBefAloc;
       
   174 
       
   175 		return new_entry->iShapeHeader;
       
   176 		}
       
   177 	return NULL;
       
   178 	}
       
   179 
       
   180 /**
       
   181 Searches from the least recently used towards the most recently used
       
   182 and try to free entry that is no longer referenced
       
   183 */
       
   184 TInt COpenFontGlyphCache::DeleteLeastRecentlyUsedEntry(RHeap* aHeap)
       
   185 	{
       
   186 	// start from the least recently used
       
   187 	COpenFontShaperCacheEntry* deleteNode = iShaperCacheSentinel->iPrevious;
       
   188 
       
   189 	// if empty list there is nothing to delete
       
   190 	if (deleteNode == iShaperCacheSentinel)
       
   191 		return 0;
       
   192 	// else navigating starting from the LRU entry
       
   193 	while (deleteNode != iShaperCacheSentinel)
       
   194 		{
       
   195 		// cannot delete if the iHandleRefCount is greater than zero
       
   196 		if (deleteNode->iHandleRefCount>0)
       
   197 			{
       
   198 			deleteNode = deleteNode->iPrevious;
       
   199 			continue;
       
   200 			}
       
   201 
       
   202 		// otherwise we can delete the entry
       
   203 		deleteNode->iPrevious->iNext = deleteNode->iNext;
       
   204 		deleteNode->iNext->iPrevious = deleteNode->iPrevious;
       
   205 
       
   206 		TInt heapSizeBeforeDel = 0;
       
   207 		TInt heapSizeAfterDel = 0;
       
   208 		aHeap->AllocSize(heapSizeBeforeDel);
       
   209 		COpenFontShaperCacheEntry::Delete(aHeap, deleteNode);
       
   210 		aHeap->AllocSize(heapSizeAfterDel);
       
   211 		TInt deletedBytes = heapSizeBeforeDel - heapSizeAfterDel;
       
   212 
       
   213 		iNumberOfShaperCacheEntries--;
       
   214 		iShapingInfoCacheMemory -= deletedBytes;
       
   215 
       
   216 		return deletedBytes;
       
   217 		}
       
   218 	// we have navigated through the whole list and cannot delete anything
       
   219 	return 0;
       
   220 	}
       
   221 
       
   222 TInt COpenFont::DecrementCachedRefCount(TInt aSessionHandle, TShapeHeader* aShapeHeader, TBool aResetAll)
       
   223 	{
       
   224 #ifdef FNTSTORE_SUPPORT_FMM
       
   225 	COpenFontShaperCacheEntry* ptr=NULL;
       
   226 	COpenFontGlyphCache* glyphCache=GetGlyphCache();
       
   227 	if (glyphCache)
       
   228 		ptr=glyphCache->iShaperCacheSentinel;
       
   229 	if (!ptr)
       
   230 		return KErrNone;
       
   231 #else
       
   232 	if (!iGlyphCache || !(iGlyphCache->iShaperCacheSentinel))
       
   233 		return KErrNone;
       
   234 
       
   235 	COpenFontShaperCacheEntry* ptr=iGlyphCache->iShaperCacheSentinel;
       
   236 	COpenFontGlyphCache* glyphCache=iGlyphCache;
       
   237 #endif // FNTSTORE_SUPPORT_FMM
       
   238 
       
   239 	TInt ret = KErrNotFound;
       
   240 	CFontStore* thisFontStore = File()->GetFontStore();
       
   241 	TInt allocBefDec = 0;
       
   242 	TInt allocAfterDec = 0;
       
   243 	TInt deletedBytes = 0;
       
   244 
       
   245 	// loop through the cache entry to decrement the ref count for a particular session	
       
   246 	while (ptr->iNext)
       
   247 		{
       
   248 		if (aResetAll)
       
   249 			{
       
   250 			// we want to reset any cache that has a matching the session handle
       
   251 			// i.e. here we dont care about which TShapeHeader and hence we can
       
   252 			// ignore the error code here if not found
       
   253 
       
   254 			// Always update the memory usage of the cache as decreasing the ref count 
       
   255 			// releases memory
       
   256 			iHeap->AllocSize(allocBefDec);
       
   257 
       
   258 			ptr->DecRefCount(aSessionHandle, ETrue);
       
   259 
       
   260 			iHeap->AllocSize(allocAfterDec);
       
   261 			deletedBytes = allocBefDec - allocAfterDec;
       
   262 			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
       
   263 			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
       
   264 
       
   265 			ret=KErrNone;
       
   266 			}
       
   267 		else if (ptr->iShapeHeader && ptr->iShapeHeader==aShapeHeader)
       
   268 			{
       
   269 			// Always update the memory usage of the cache as decreasing the ref count 
       
   270 			// releases memory
       
   271 			iHeap->AllocSize(allocBefDec);
       
   272 
       
   273 			ptr->DecRefCount(aSessionHandle);
       
   274 
       
   275 			iHeap->AllocSize(allocAfterDec);
       
   276 			deletedBytes = allocBefDec - allocAfterDec;
       
   277 			glyphCache->iShapingInfoCacheMemory -= deletedBytes;
       
   278 			thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
       
   279 
       
   280 			return KErrNone;
       
   281 			}
       
   282 		ptr=ptr->iNext;
       
   283 		if (ptr == glyphCache->iShaperCacheSentinel)
       
   284 			{
       
   285 			break;
       
   286 			}
       
   287 		}
       
   288 	return ret;
       
   289 	}
       
   290 
       
   291 TInt COpenFont::FreeShaperCacheMemory(TInt aBytesNeeded)
       
   292 	{
       
   293 	TInt totalDeletedBytes = 0;
       
   294 	TInt tempDeletedBytes = 0;
       
   295 	CFontStore* thisFontStore = File()->GetFontStore();
       
   296 
       
   297 	if (aBytesNeeded <= KMaxShaperSesssionCacheMemory)
       
   298 		{
       
   299 		// delete LRU entries from all the caches except the one owned by this COpenFont
       
   300 		// The 'if' condition here is to avoid looping through every font in the system
       
   301 		// if only one of the them has a non-empty cache. In situations where only one
       
   302 		// cache is left and it is full, this strategy makes freeing the memory faster.
       
   303 		if (thisFontStore->GetNumShaperCaches() > 1)
       
   304 			{
       
   305 			CArrayPtrFlat<COpenFont>* fontList;
       
   306 			CArrayPtrFlat<COpenFontFile>* fontFileList = thisFontStore->GetOpenFontFileList();
       
   307 			TInt numberOfFontFiles = fontFileList->Count();
       
   308 			TInt i = 0; 
       
   309 			while ((totalDeletedBytes < aBytesNeeded) && (i < numberOfFontFiles))
       
   310 				{
       
   311 				fontList = (*fontFileList)[i]->GetOpenFontList();
       
   312 				TInt fontListCount=fontList->Count();
       
   313 				TInt j = 0;
       
   314 				while ((totalDeletedBytes < aBytesNeeded) && (j < fontListCount))
       
   315 					{
       
   316 					COpenFont* open_font = (*fontList)[j];
       
   317 					COpenFontGlyphCache* glyphCache = open_font->GetGlyphCache();
       
   318 					if ((open_font != this) && (glyphCache != NULL))
       
   319 						{
       
   320 						while ((totalDeletedBytes < aBytesNeeded) && (!glyphCache->ShaperCacheIsEmpty()))
       
   321 							{
       
   322 							totalDeletedBytes += glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
       
   323 							if (glyphCache->ShaperCacheIsEmpty())
       
   324 								{
       
   325 								thisFontStore->DecNumShaperCaches();
       
   326 								}
       
   327 								
       
   328 							// If totalDeletedBytes is zero mean we cannot delete from this font
       
   329 							if (totalDeletedBytes == 0)
       
   330 								{
       
   331 								break;
       
   332 								}
       
   333 							}
       
   334 						}
       
   335 					j++;
       
   336 					}
       
   337 				i++;
       
   338 				}
       
   339 			}
       
   340 			
       
   341 		// If deleted bytes are still less than the required one delete from this font
       
   342 #ifdef FNTSTORE_SUPPORT_FMM
       
   343 		COpenFontGlyphCache* glyphCache = GetGlyphCache();
       
   344 #else
       
   345 		COpenFontGlyphCache* glyphCache = iGlyphCache;
       
   346 #endif // FNTSTORE_SUPPORT_FMM
       
   347 		while (totalDeletedBytes < aBytesNeeded && !glyphCache->ShaperCacheIsEmpty())
       
   348 			{				
       
   349 			tempDeletedBytes = glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
       
   350 			if ( tempDeletedBytes == 0)
       
   351 				break;
       
   352 			totalDeletedBytes += tempDeletedBytes;
       
   353 			}
       
   354 		}
       
   355 		
       
   356 	// Update the global CFontStore cache memory count
       
   357 	if (totalDeletedBytes > 0)
       
   358 		{
       
   359 		thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - totalDeletedBytes);
       
   360 		}
       
   361 
       
   362 	return totalDeletedBytes;
       
   363 	}
       
   364 
       
   365 TShapeHeader* COpenFont::InsertShapedDataIntoCache(TInt aSessionHandle,TFontShapeFunctionParameters* aParams, TShapeHeader* aShapeHeader)
       
   366 	{
       
   367 	CShaper::TInput input;
       
   368 	input.iEnd = aParams->iEnd;
       
   369 	input.iStart = aParams->iStart;
       
   370 	input.iScript = aParams->iScript;
       
   371 	input.iLanguage = aParams->iLanguage;
       
   372 	input.iText = aParams->iText;
       
   373 	input.iMaximumAdvance = KMaxTInt;
       
   374 	input.iFlags = 0;
       
   375 	input.iSessionHandle = aSessionHandle;
       
   376 	input.iReserved1 = 0;
       
   377 
       
   378 	CFontStore* thisFontStore = File()->GetFontStore();
       
   379 
       
   380 	// Create the glyph cache if it doesnt already exist.
       
   381 	// This call can only come from FBSERV
       
   382 	if (iGlyphCache == NULL)
       
   383 		{
       
   384 		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
       
   385 		if (iGlyphCache == NULL) // no memory
       
   386 			{
       
   387 			return NULL;
       
   388 			}
       
   389 		new(iGlyphCache) COpenFontGlyphCache;
       
   390 		}
       
   391 	// If there is no sentinel present, i.e. new cache
       
   392 	if (iGlyphCache->iShaperCacheSentinel == NULL)
       
   393 		{
       
   394 		// Create a sentinel
       
   395 		iGlyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap);
       
   396 		if (!iGlyphCache->iShaperCacheSentinel)
       
   397 			{
       
   398 			// no memory
       
   399 			return NULL;
       
   400 			}
       
   401 		iGlyphCache->iShaperCacheSentinel->iNext = iGlyphCache->iShaperCacheSentinel;
       
   402 		iGlyphCache->iShaperCacheSentinel->iPrevious = iGlyphCache->iShaperCacheSentinel;
       
   403 		iGlyphCache->iNumberOfShaperCacheEntries = 1;
       
   404 		}
       
   405 
       
   406 	// Before inserting into this cache, check if it was empty.
       
   407 	// If empty, then increment the global cache count signifying one more cache is active
       
   408 	if (iGlyphCache->ShaperCacheIsEmpty())
       
   409 		{
       
   410 		thisFontStore->IncNumShaperCaches();
       
   411 		}
       
   412 
       
   413 	TInt addedBytes = 0;
       
   414 	TShapeHeader* cached_header = NULL;
       
   415 
       
   416 	// Insert a new entry and return the newly inserted TShapeHeader entry
       
   417 	cached_header = iGlyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes);
       
   418 	if (cached_header == NULL)
       
   419 		return NULL;
       
   420 
       
   421 	// If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then
       
   422 	// free some memory by releasing the same amount of memory that was just added
       
   423 	if (thisFontStore->GetShaperCacheMemUsage() + addedBytes > KMaxShaperSesssionCacheMemory)
       
   424 		{
       
   425 		FreeShaperCacheMemory(addedBytes);
       
   426 		}
       
   427 
       
   428 	// Now update the memory count with the added memory for the new entry
       
   429 	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
       
   430 	return cached_header;
       
   431 	}
       
   432 
       
   433 TShapeHeader* COpenFont::GetShapedData(TInt aSessionHandle, TFontShapeFunctionParameters* aParams)
       
   434 	{
       
   435 	if (iGlyphCache == NULL)
       
   436 		return NULL;
       
   437 
       
   438 	TShapeHeader* cachedHeader = NULL;
       
   439 	CFontStore* thisFontStore = File()->GetFontStore();
       
   440 
       
   441 	// Always update the memory usage of the cache as increasing the reference count of a found header uses up memory
       
   442 	TInt allocBefInc = 0;
       
   443 	TInt allocAfterInc = 0;
       
   444 	iHeap->AllocSize(allocBefInc);
       
   445 	
       
   446 #ifdef FNTSTORE_SUPPORT_FMM
       
   447 	COpenFontGlyphCache* glyphCache = GetGlyphCache();
       
   448 #else
       
   449 	COpenFontGlyphCache* glyphCache = iGlyphCache;
       
   450 #endif // FNTSTORE_SUPPORT_FMM
       
   451 	cachedHeader = glyphCache->SearchShaperCache(aSessionHandle,aParams);
       
   452 	
       
   453 	iHeap->AllocSize(allocAfterInc);
       
   454 	TInt addedBytes = allocAfterInc - allocBefInc;
       
   455 	glyphCache->iShapingInfoCacheMemory += addedBytes;
       
   456 	thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
       
   457 
       
   458 	return cachedHeader;
       
   459 	}
       
   460 
       
   461 TBool COpenFontGlyphCache::ShaperCacheIsEmpty()
       
   462 	{
       
   463 	if (iShaperCacheSentinel == NULL)
       
   464 		return ETrue;
       
   465 
       
   466 	if (iShaperCacheSentinel->iNext == iShaperCacheSentinel)
       
   467 		return ETrue;
       
   468 	else
       
   469 		return EFalse;
       
   470 	}
       
   471 
       
   472 /**
       
   473 C++ constructor taking shared heap, session cache list and font file as parameters.
       
   474 
       
   475 You must either use this, or the other constructor, when creating your derived 
       
   476 object. This constructor might be used, in preference to the other, if there 
       
   477 is only a single typeface in the font file.
       
   478 
       
   479 @param aHeap The shared heap. 
       
   480 @param aSessionCacheList The session cache list.
       
   481 @param aFile A pointer to the COpenFontFile object creating this COpenFont. 
       
   482 e.g. when creating a COpenFont the COpenFontFile derived object would pass 
       
   483 it this.
       
   484 */
       
   485 #ifdef FNTSTORE_SUPPORT_FMM
       
   486 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList,
       
   487 							  COpenFontFile* aFile):
       
   488 	iHeap(aHeap),
       
   489 	iShaper(NULL),
       
   490 	iFile(aFile),
       
   491 	iFaceIndex(0),
       
   492 	iSessionCacheList(aSessionCacheList)
       
   493 	{	
       
   494 	iStartingThis=reinterpret_cast<TInt>(this);
       
   495 	}
       
   496 #else
       
   497 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile)
       
   498  :	iHeap(aHeap),
       
   499 	iShaper(NULL),
       
   500 	iFile(aFile),
       
   501 	iFaceIndex(0),
       
   502 	iSessionCacheList(aSessionCacheList),
       
   503 	iReserved(NULL)
       
   504 	{
       
   505 
       
   506 	}
       
   507 #endif // FNTSTORE_SUPPORT_FMM
       
   508 
       
   509 /**
       
   510 C++ constructor taking shared heap, session cache list, font file and face 
       
   511 index as parameters.
       
   512 
       
   513 You must either use this, or the other constructor, when creating your derived 
       
   514 object. This constructor would be used if the font file contains more than 
       
   515 one typeface.
       
   516 
       
   517 @param aHeap The shared heap.
       
   518 @param aSessionCacheList The session cache list.
       
   519 @param aFile A pointer to the COpenFontFile object creating this COpenFont. 
       
   520 e.g. when creating a COpenFont the COpenFontFile derived object would pass 
       
   521 it this.
       
   522 @param aFaceIndex The index of the typeface within the font file aFile.
       
   523 */
       
   524 #ifdef FNTSTORE_SUPPORT_FMM
       
   525 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex) :
       
   526  	iHeap(aHeap),
       
   527 	iShaper(NULL),
       
   528 	iFile(aFile),
       
   529 	iFaceIndex(aFaceIndex),
       
   530 	iSessionCacheList(aSessionCacheList)
       
   531 	{
       
   532 	iStartingThis=reinterpret_cast<TInt>(this);
       
   533 	}
       
   534 #else
       
   535 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex)
       
   536  :	iHeap(aHeap),
       
   537 	iShaper(NULL),
       
   538 	iFile(aFile),
       
   539 	iFaceIndex(aFaceIndex),
       
   540 	iSessionCacheList(aSessionCacheList),
       
   541 	iReserved(NULL)
       
   542 	{
       
   543 
       
   544 	}
       
   545 #endif // FNTSTORE_SUPPORT_FMM
       
   546 
       
   547 /**
       
   548 Destructor
       
   549 
       
   550 This function frees all memory owned by the object, including the session 
       
   551 cache list and the glyph list, prior to its destruction.
       
   552 */
       
   553 EXPORT_C COpenFont::~COpenFont()
       
   554 	{
       
   555 	//Delete the shaper
       
   556 	delete iShaper;
       
   557 
       
   558 	File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
       
   559 	
       
   560 	if (iGlyphCache)
       
   561 		{
       
   562 		COpenFontGlyphTreeEntry* next = NULL;
       
   563 #ifdef FNTSTORE_SUPPORT_FMM
       
   564 		TInt ii;
       
   565 		RArrayGlyphEntries& glyphArray=iGlyphCache->iGlyphArray;
       
   566 		for (ii=glyphArray.Count()-1;ii>=0;--ii)
       
   567 			{
       
   568 			next=&glyphArray[ii];
       
   569 			COpenFontGlyph::Delete(iHeap,next);
       
   570 			}
       
   571 		iGlyphCache->iGlyphArray.Close();
       
   572 #else
       
   573 		for (COpenFontGlyphTreeEntry* g = iGlyphCache->iGlyphList; g; g = next)
       
   574 			{
       
   575 			next = g->iNext;
       
   576 			COpenFontGlyph::Delete(iHeap, g);
       
   577 			}
       
   578 #endif // FNTSTORE_SUPPORT_FMM
       
   579 
       
   580 		// Delete the shaper cache as well
       
   581 		if (iGlyphCache->iShaperCacheSentinel)
       
   582 			{
       
   583 			COpenFontShaperCacheEntry* previous  = NULL;
       
   584 			COpenFontShaperCacheEntry* si = iGlyphCache->iShaperCacheSentinel->iPrevious;
       
   585 			TInt heapBefore = 0;
       
   586 			TInt heapAfter = 0;
       
   587 			iHeap->AllocSize(heapBefore);
       
   588 			while (iGlyphCache->iNumberOfShaperCacheEntries > 0)
       
   589 				{
       
   590 				previous = si->iPrevious;
       
   591 				COpenFontShaperCacheEntry::Delete(iHeap, si);
       
   592 				si = previous;
       
   593 				iGlyphCache->iNumberOfShaperCacheEntries--;
       
   594 				}
       
   595 			iHeap->AllocSize(heapAfter);
       
   596 			File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter));
       
   597 			File()->GetFontStore()->DecNumShaperCaches();
       
   598 			}
       
   599 
       
   600 		iHeap->Free(iGlyphCache);
       
   601 		}
       
   602 	if (iSessionCacheList)	
       
   603 		iSessionCacheList->DeleteFontGlyphs(iHeap, this);
       
   604 	if (iFile)
       
   605 		iFile->RemoveFontFromList(this);
       
   606 	}
       
   607 
       
   608 COpenFontGlyph::~COpenFontGlyph()
       
   609 	{
       
   610 	}
       
   611 
       
   612 void COpenFontGlyph::Delete(RHeap* aHeap, COpenFontGlyph* aGlyph)
       
   613 	{
       
   614 	if (aGlyph)
       
   615 		{
       
   616 #ifdef FNTSTORE_SUPPORT_FMM
       
   617 		aHeap->Free(aGlyph->Bitmap());
       
   618 #else
       
   619 		aHeap->Free(aGlyph->iBitmap);
       
   620 #endif // FNTSTORE_SUPPORT_FMM
       
   621 		aHeap->Free(aGlyph);
       
   622 		}
       
   623 	}
       
   624 
       
   625 EXPORT_C void COpenFont::operator delete(TAny *aFont)
       
   626 	{
       
   627 	if(aFont)
       
   628 		{
       
   629 		COpenFont* f = (COpenFont*)aFont;
       
   630 		if (f->iHeap)
       
   631 			f->iHeap->Free(aFont);
       
   632 		}
       
   633 	}
       
   634 
       
   635 /**
       
   636 Rasterize a glyph
       
   637 
       
   638 This function may only be called via an FBSERV message.
       
   639 
       
   640 @param aSessionHandle Session handle of the calling session
       
   641 @param aCode Unicode value or glyph code if top bit is set
       
   642 @param aGlyphData
       
   643 	Output data. May be null, in which case output may be
       
   644 	obtained through a call to GetCharacterData.
       
   645 
       
   646 @return
       
   647 	ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap()
       
   648 	and aGlyphData->Metrics() are valid), EFalse otherwise.
       
   649 */
       
   650 #ifdef FNTSTORE_SUPPORT_FMM
       
   651 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
       
   652 	TOpenFontGlyphData* aGlyphData)
       
   653 	{
       
   654 	// create the cache if it doesn't exisit. As this call can only come from
       
   655 	// FBSERV if the chunk has to be resized then no panic will happen.
       
   656 	if (iGlyphCache == NULL)
       
   657 		{
       
   658 		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
       
   659 		if (iGlyphCache == NULL) // no memory
       
   660 			{
       
   661 			return EFalse;
       
   662 			}
       
   663 		new(iGlyphCache) COpenFontGlyphCache;
       
   664 		}
       
   665 
       
   666 	// Look in the Font Cache	
       
   667 	TInt* nodeInsertPtr = NULL;	
       
   668 	const COpenFontGlyph* g = FontCacheGlyph(aCode, nodeInsertPtr);		 	
       
   669 
       
   670 	// If it is not found there look in the session cache.
       
   671 	COpenFontSessionCache* cache = NULL;
       
   672 	TInt index = 0;
       
   673 	if (!g)
       
   674 		{
       
   675 		g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse);
       
   676 		}
       
   677 
       
   678 	// If it has already been rasterized return it.
       
   679 	if (g)
       
   680 		{
       
   681 		if (aGlyphData)
       
   682 			{
       
   683 			aGlyphData->SetMetricsPointer(&g->iMetrics);
       
   684 			aGlyphData->SetBitmapPointer(g->Bitmap());
       
   685 			}
       
   686 
       
   687 		return ETrue;
       
   688 		}
       
   689 
       
   690 	// Rasterize the glyph.
       
   691 	TOpenFontGlyphData* temp_glyph_data = NULL;
       
   692 	TInt error = KErrNone;
       
   693 	TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
       
   694 	if (error != KErrNone)
       
   695 		{
       
   696 		iHeap->Free(temp_glyph_data);
       
   697 		return EFalse;
       
   698 		}
       
   699 
       
   700 	TBool glyph_data_valid = ETrue;
       
   701 	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
       
   702 	const COpenFontGlyph* new_glyph = NULL;
       
   703 
       
   704 	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
       
   705 	TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded();	
       
   706 	if(iGlyphCache && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
       
   707 		{
       
   708 		COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
       
   709 		new_glyph=new_entry;
       
   710 		if(new_entry)
       
   711 			{
       
   712 			// Insert new entry into the delete list 
       
   713 			error = iGlyphCache->iGlyphArray.Append(*new_entry);
       
   714 			if (error == KErrNone)
       
   715 				{
       
   716 				if(!iGlyphCache->iGlyphTreeOffset)
       
   717 					{
       
   718 					// First entry in tree
       
   719 					iGlyphCache->iGlyphTreeOffset = PointerToThisOffset(new_entry);
       
   720 					}	
       
   721 				else if (nodeInsertPtr)
       
   722 					{
       
   723 					// Add the glyph to a leaf node using the nodeInsertPtr that was returned by FontCacheGlyph()
       
   724 					*nodeInsertPtr = PointerToThisOffset(new_entry);
       
   725 					}
       
   726 				else 
       
   727 					{
       
   728 					// Failed to add the glyph to the glyph tree, remove it from the delete array.
       
   729 					// (The glyph is deleted below).
       
   730 					iGlyphCache->iGlyphArray.Remove(iGlyphCache->iGlyphArray.Count()-1);					
       
   731 					error = KErrGeneral;
       
   732 					}
       
   733 				}
       
   734 			if (error != KErrNone)
       
   735 				{
       
   736 				COpenFontGlyph::Delete(iHeap,new_entry);
       
   737 				}
       
   738 			else
       
   739 				{
       
   740 				iGlyphCache->iGlyphCacheMemory += bytes;
       
   741 				}		
       
   742 			}
       
   743 		}
       
   744 	else
       
   745 		{
       
   746 		error = KErrGeneral;
       
   747 		}
       
   748 
       
   749 	// Otherwise put the glyph into the per-session cache.
       
   750 	if (error != KErrNone)
       
   751 		{
       
   752 		// If the session cache is not yet known find it or create one.
       
   753 		if (!cache)
       
   754 			{
       
   755 			SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE);
       
   756 			}
       
   757 		if (!cache)
       
   758 			{			
       
   759 			return EFalse;
       
   760 			}
       
   761 
       
   762 		COpenFontSessionCacheEntry* new_entry =
       
   763 			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
       
   764 		new_glyph = new_entry;
       
   765 		if (new_entry)
       
   766 			{
       
   767 			cache->Insert(iHeap, new_entry, index);
       
   768 			}
       
   769 		}
       
   770 
       
   771 	if (temp_glyph_data)
       
   772 		{
       
   773 		iHeap->Free(temp_glyph_data);
       
   774         }
       
   775         
       
   776     // Fix up the returned glyph data pointers to point to the actual data.
       
   777     if (!new_glyph)
       
   778         glyph_data_valid = FALSE;
       
   779     else if (aGlyphData)
       
   780         {
       
   781         aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
       
   782         aGlyphData->SetBitmapPointer(new_glyph->Bitmap());
       
   783         }
       
   784 
       
   785 	return glyph_data_valid;
       
   786 	}
       
   787 #else
       
   788 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
       
   789 	TOpenFontGlyphData* aGlyphData)
       
   790 	{
       
   791 	// First look in the font cache.
       
   792 	COpenFontGlyphTreeEntry** node_ptr = NULL;
       
   793 	// create the cache if it doesn't exisit. As this call can only come from
       
   794 	// FBSERV if the chunk has to be resized then no panic will happen.
       
   795 	if (iGlyphCache == NULL)
       
   796 		{
       
   797 		iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
       
   798 		if (iGlyphCache == NULL) // no memory
       
   799 			{
       
   800 			return FALSE;
       
   801 			}
       
   802 		new(iGlyphCache) COpenFontGlyphCache;
       
   803 		}
       
   804 	
       
   805 	// Look in the fontcache. Do not expect to find a glyph here. However, 
       
   806 	// it is called again so that a node pointer is found where the new glyph
       
   807 	// will be placed when added to the font cache.
       
   808 	const COpenFontGlyph* glyph = FontCacheGlyph(aCode, node_ptr);
       
   809 	if (glyph)
       
   810 		{
       
   811 		// Do not expect it to get here, since the font cache has already been searched client-side,
       
   812 		// prior to calling Rasterize(). However, just in case it does find a match, use it.
       
   813 		if (aGlyphData)
       
   814 			{
       
   815 			aGlyphData->SetMetricsPointer(&glyph->iMetrics);
       
   816 			aGlyphData->SetBitmapPointer(glyph->iBitmap);
       
   817 			}
       
   818 		return TRUE;
       
   819 		}
       
   820 		
       
   821 	// Rasterize the glyph.
       
   822 	TOpenFontGlyphData* temp_glyph_data = NULL;
       
   823 	TInt error = KErrNone;
       
   824 	TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
       
   825 	if (error)
       
   826 		{
       
   827 		iHeap->Free(temp_glyph_data);
       
   828 		return FALSE;
       
   829 		}
       
   830 
       
   831 	TBool glyph_data_valid = TRUE;
       
   832 	const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
       
   833 	const COpenFontGlyph* new_glyph = NULL;
       
   834 
       
   835 	// If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
       
   836 	TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded();
       
   837 	if (iGlyphCache && node_ptr && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
       
   838 		{
       
   839 		COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
       
   840 		new_glyph = new_entry;
       
   841 		if (new_entry)
       
   842 			{
       
   843 			*node_ptr = new_entry;	// update the cache atomically
       
   844 
       
   845 			// Insert new entry into the delete list 
       
   846 
       
   847 			COpenFontGlyphTreeEntry* start = iGlyphCache->iGlyphTree;
       
   848 			COpenFontGlyphTreeEntry* tree = start;
       
   849 
       
   850 			if (new_entry != iGlyphCache->iGlyphTree)
       
   851 				{
       
   852 				while (tree->iNext)
       
   853 					{
       
   854 					tree = tree->iNext;
       
   855 					}
       
   856 				tree->iNext = new_entry;
       
   857 				}
       
   858 			else
       
   859 				{
       
   860 				// First entry in tree, initialise iGlyphList
       
   861 				iGlyphCache->iGlyphList = new_entry;
       
   862 				}
       
   863 
       
   864 			iGlyphCache->iGlyphCacheMemory += bytes;
       
   865 			}
       
   866 		}
       
   867 
       
   868 	// Otherwise put the glyph into the per-session cache.
       
   869 	else
       
   870 		{
       
   871 		// If the session cache is not yet known find it or create one.
       
   872 		COpenFontSessionCache* cache = NULL;
       
   873 		TInt index = 0;
       
   874 		SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE);
       
   875 		if (!cache)
       
   876 			return FALSE;
       
   877 		COpenFontSessionCacheEntry* new_entry =
       
   878 			COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
       
   879 		new_glyph = new_entry;
       
   880 		if (new_entry)
       
   881 			cache->Insert(iHeap, new_entry, index);
       
   882 		}
       
   883 
       
   884 	if (temp_glyph_data)
       
   885 		{
       
   886             iHeap->Free(temp_glyph_data);
       
   887         }
       
   888         
       
   889     // Fix up the returned glyph data pointers to point to the actual data.
       
   890     if (!new_glyph)
       
   891         glyph_data_valid = FALSE;
       
   892     else if (aGlyphData)
       
   893         {
       
   894         aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
       
   895         aGlyphData->SetBitmapPointer(new_glyph->iBitmap);
       
   896         }
       
   897 
       
   898 	return glyph_data_valid;
       
   899 	}
       
   900 #endif // FNTSTORE_SUPPORT_FMM
       
   901 
       
   902 void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData)
       
   903 	{
       
   904 	aTempGlyphData = 0;
       
   905 	MOpenFontShapingExtension* extensionInterface = 0;
       
   906 
       
   907 	// if the MSB is set this is a request to rasterize a glyph code
       
   908 	// rather than a unicode value.  This can only be done if the rasterizer
       
   909 	// supports the extended API. 
       
   910 	if ( aCode & 0x80000000 )
       
   911 		{
       
   912 		aCode = GLYPH_CODE(aCode);
       
   913 		// get the extension API for RasterizeGlyphL() if available
       
   914 		TAny* ext = NULL;
       
   915 		ExtendedInterface(KUidOpenFontShapingExtension, ext);
       
   916 		extensionInterface = reinterpret_cast<MOpenFontShapingExtension*>(ext);
       
   917 
       
   918 		if (!extensionInterface)
       
   919 			// an attempt to rasterize a glyph when the rasterizer does not
       
   920 			// support it; best to do nothing
       
   921 			return;
       
   922 		}
       
   923 	TOpenFontGlyphData* currGlyphData = aGlyphData;
       
   924 
       
   925 	if (!currGlyphData)
       
   926 		{
       
   927 		aTempGlyphData = TOpenFontGlyphData::New(iHeap, 0);
       
   928 		if (!aTempGlyphData)
       
   929 			User::Leave(KErrNoMemory);
       
   930 		currGlyphData = aTempGlyphData;
       
   931 		}
       
   932 
       
   933 	if (extensionInterface)
       
   934 		extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
       
   935 	else
       
   936 		RasterizeL(aCode, currGlyphData);
       
   937 
       
   938 	// If the GlyphData object was not large enough, create a temporary one
       
   939 	// that can then be deleted by the caller.
       
   940 	if (currGlyphData->Overflow())
       
   941 		{
       
   942 		TInt bytesNeeded = currGlyphData->BytesNeeded();
       
   943 		if (aTempGlyphData)
       
   944 			iHeap->Free(aTempGlyphData);
       
   945 		aTempGlyphData = TOpenFontGlyphData::New(iHeap, bytesNeeded);
       
   946 		if (!aTempGlyphData)
       
   947 			User::Leave(KErrNoMemory);
       
   948 		
       
   949 		currGlyphData = aTempGlyphData;
       
   950 
       
   951 		// If the extension interface was used above, then use again here
       
   952 		if (extensionInterface)
       
   953 			extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
       
   954 		else
       
   955 			RasterizeL(aCode, currGlyphData);
       
   956 		}
       
   957 		
       
   958 	if (currGlyphData->Metrics() == NULL) 
       
   959 		{
       
   960 		User::Leave(KErrArgument);
       
   961 		}
       
   962 	}
       
   963 
       
   964 /** @internalComponent */
       
   965 void COpenFont::SetShaper(CShaper* aShaper)
       
   966 	{
       
   967 	iShaper = aShaper;
       
   968 	}
       
   969 	
       
   970 /** @internalComponent */
       
   971 CShaper* COpenFont::GetShaper()
       
   972 	{
       
   973 	return iShaper;
       
   974 	}
       
   975 
       
   976 /** @internalComponent */
       
   977 TBool COpenFont::HasShaper() const
       
   978 	{
       
   979 	return iShaper != NULL;
       
   980 	}
       
   981 
       
   982 void COpenFont::DeleteShaper() const
       
   983 	{
       
   984 	delete iShaper;
       
   985 	}
       
   986 
       
   987 TInt COpenFont::GetFontTable(TUint32 aTag, TAny*& aTableContent, TInt& aLength) 
       
   988     {
       
   989     // get the extension API for GetTrueTypeTable() if available
       
   990     TAny* ext = NULL;
       
   991     ExtendedInterface(KUidOpenFontTrueTypeExtension, ext);
       
   992     MOpenFontTrueTypeExtension* extensionInterface = 
       
   993         reinterpret_cast<MOpenFontTrueTypeExtension*>(ext);
       
   994 
       
   995     TInt ret = KErrNone;
       
   996     if (!extensionInterface)
       
   997         {
       
   998         ret = KErrNotSupported;
       
   999         }
       
  1000     else 
       
  1001         {
       
  1002         TUint32 tag = aTag;
       
  1003         TInt len = 0;
       
  1004         aTableContent = extensionInterface->GetTrueTypeTable(ret, tag, &len);
       
  1005         if (KErrNone == ret) 
       
  1006             {
       
  1007             aLength = len;
       
  1008             }
       
  1009         }
       
  1010     return ret;
       
  1011     }
       
  1012 
       
  1013 TInt COpenFont::GetGlyphOutline(TUint aCode, 
       
  1014         TBool aHinted, TAny*& aOutline, TInt &aLength) 
       
  1015     {
       
  1016     // get the extension API for GetTrueTypeTable() if available
       
  1017     TAny* ext = NULL;
       
  1018     ExtendedInterface(KUidOpenFontGlyphOutlineExtension, ext);
       
  1019     MOpenFontGlyphOutlineExtension *extensionInterface = 
       
  1020         reinterpret_cast<MOpenFontGlyphOutlineExtension*>(ext);
       
  1021 
       
  1022     TInt ret = KErrNone;
       
  1023     if (!extensionInterface)
       
  1024         {
       
  1025         ret = KErrNotSupported;
       
  1026         }
       
  1027     else 
       
  1028         {
       
  1029         ret = extensionInterface->GetGlyphOutline(aCode, ETrue, 
       
  1030                 aHinted, aOutline, aLength);
       
  1031         }
       
  1032     return ret;
       
  1033     }
       
  1034 #ifdef FNTSTORE_SUPPORT_FMM
       
  1035 /** Given the passed pointer aAny, return an offset from it to the "this" pointer
       
  1036 of this COpenFont object.
       
  1037 @param aAny A pointer to an object that exists on the shared heap, i.e. the same heap
       
  1038 that this CCOpenFont object was created on.
       
  1039 @return An offset relative to the "this" pointer for this object, this offset can
       
  1040 be converted back to a pointer using ThisOffsetToPointer().
       
  1041 @see ThisOffsetToPointer().
       
  1042 @internalComponent 
       
  1043  */
       
  1044 TInt COpenFont::PointerToThisOffset(const TAny* aAny)
       
  1045 	{
       
  1046 	if (aAny)
       
  1047 		{
       
  1048 		return ((TInt)aAny - (TInt)this);
       
  1049 		}
       
  1050 	return 0;
       
  1051 	}
       
  1052 
       
  1053 /** Given the passed passed offset aThisOffset, convert it to a pointer relative to
       
  1054 the "this" pointer for this object.
       
  1055 @param aThisOffset An offset that was generated using PointerToThisOffset().
       
  1056 @return A pointer that has been created by adding (this+aThisOffset).
       
  1057 @see PointerToThisOffset().
       
  1058 @internalComponent 
       
  1059  */
       
  1060 TAny* COpenFont::ThisOffsetToPointer(const TInt aThisOffset)
       
  1061 	{
       
  1062 	if (aThisOffset)
       
  1063 		{
       
  1064 		return (TAny*)((TInt)this + aThisOffset);
       
  1065 		}
       
  1066 	return NULL;
       
  1067 	}		
       
  1068 #endif // FNTSTORE_SUPPORT_FMM
       
  1069 
       
  1070 /**
       
  1071 A constructor initialised with a TCharacterMetrics object.
       
  1072 
       
  1073 This is the old-style character metrics object. As for other T classes, there 
       
  1074 is no need to explicitly cleanup TOpenFontCharMetrics objects.
       
  1075 
       
  1076 @param aMetrics The old-style metrics object.
       
  1077 */
       
  1078 EXPORT_C TOpenFontCharMetrics::TOpenFontCharMetrics(const TCharacterMetrics& aMetrics)
       
  1079 	{
       
  1080 	iWidth = (TInt16)(aMetrics.iMoveInPixels - aMetrics.iLeftAdjustInPixels - aMetrics.iRightAdjustInPixels);
       
  1081 	iHeight = aMetrics.iHeightInPixels;
       
  1082 	iHorizBearingX = aMetrics.iLeftAdjustInPixels;
       
  1083 	iHorizBearingY = aMetrics.iAscentInPixels;
       
  1084 	iHorizAdvance = aMetrics.iMoveInPixels;
       
  1085 	iVertBearingX = 0;
       
  1086 	iVertBearingY = 0;
       
  1087 	iVertAdvance = aMetrics.iHeightInPixels;
       
  1088 	iGlyphBitmapType = 0;
       
  1089 	}
       
  1090 
       
  1091 /**
       
  1092 Converts a TOpenFontCharacterMetrics object to a TCharacterMetrics.
       
  1093 
       
  1094 @param aMetrics On return, contains the character's old-style metrics. 
       
  1095 @return ETrue if it was possible to get the metrics, otherwise EFalse.
       
  1096 */
       
  1097 EXPORT_C TBool TOpenFontCharMetrics::GetTCharacterMetrics(TCharacterMetrics& aMetrics) const
       
  1098 	{
       
  1099 	aMetrics.iAscentInPixels = iHorizBearingY;
       
  1100 	aMetrics.iHeightInPixels = iHeight;
       
  1101 	aMetrics.iLeftAdjustInPixels = iHorizBearingX;
       
  1102 	aMetrics.iMoveInPixels = iHorizAdvance;
       
  1103 	aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth);
       
  1104 	return TRUE;
       
  1105 	}
       
  1106 
       
  1107 TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const
       
  1108 	{
       
  1109 	const COpenFontGlyph* g = Glyph(aSessionHandle, aCode);
       
  1110 	if (g)
       
  1111 		{
       
  1112 		aMetrics = &g->iMetrics;
       
  1113 #ifdef FNTSTORE_SUPPORT_FMM
       
  1114 		aBitmap = g->Bitmap();
       
  1115 #else
       
  1116 		aBitmap = g->iBitmap;
       
  1117 #endif // FNTSTORE_SUPPORT_FMM
       
  1118 		return TRUE;
       
  1119 		}
       
  1120 	else
       
  1121 		{
       
  1122 		aMetrics = NULL;
       
  1123 		aBitmap = NULL;
       
  1124 		return FALSE;
       
  1125 		}
       
  1126 	}
       
  1127 
       
  1128 
       
  1129 
       
  1130 void COpenFont::OnFileDeleted()
       
  1131 	{
       
  1132 	iFile = NULL;
       
  1133 	}
       
  1134 
       
  1135 COpenFontGlyphCache* COpenFont::GetGlyphCache()
       
  1136 	{
       
  1137 #ifdef FNTSTORE_SUPPORT_FMM
       
  1138 	if (iGlyphCache)
       
  1139 		return reinterpret_cast<COpenFontGlyphCache*>(reinterpret_cast<TInt>(iGlyphCache)+Offset());
       
  1140 #else
       
  1141 	if (iGlyphCache)
       
  1142 		return iGlyphCache;
       
  1143 #endif // FNTSTORE_SUPPORT_FMM
       
  1144 	else
       
  1145 		return NULL;
       
  1146 	}
       
  1147 
       
  1148 const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const
       
  1149 	{	
       
  1150 #ifdef FNTSTORE_SUPPORT_FMM
       
  1151 	const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode);
       
  1152 	if (!glyph)
       
  1153 		{			
       
  1154 		COpenFontSessionCache* cache;
       
  1155 		TInt index;
       
  1156 		glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE);
       
  1157 	}
       
  1158 
       
  1159 	return glyph;
       
  1160 #else
       
  1161 	const COpenFontGlyph* g = CONST_CAST(COpenFont*,this)->FontCacheGlyph(aCode);
       
  1162 	if (!g)
       
  1163 		{
       
  1164 		COpenFontSessionCache* cache;
       
  1165 		TInt index;
       
  1166 		g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE);
       
  1167 		}
       
  1168 	return g;
       
  1169 #endif // FNTSTORE_SUPPORT_FMM
       
  1170 	}
       
  1171 
       
  1172 /**
       
  1173 Is the specified character present in the font?
       
  1174 */
       
  1175 TBool COpenFont::HasCharacterL(TInt aCode) const
       
  1176 	{
       
  1177 	COpenFontFile* file = File();
       
  1178 	if (file)
       
  1179 		return file->HasUnicodeCharacterL(iFaceIndex, aCode);
       
  1180 	else
       
  1181 		return FALSE;
       
  1182 	}
       
  1183 
       
  1184 #ifdef FNTSTORE_SUPPORT_FMM
       
  1185 /**
       
  1186 Retrieve glyph data from the per-font glyph cache.
       
  1187 If it is not found return NULL. 
       
  1188 If the cache hasn't been created, then return NULL.
       
  1189 Previous versions of this function created the cache, but as this function can potentially
       
  1190 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
       
  1191 be resized - this is not allowed by the kernel.
       
  1192 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
       
  1193 @param aCode The code for the glpyh to look for in the cache
       
  1194 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
       
  1195 */
       
  1196 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
       
  1197 	{		
       
  1198 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
       
  1199 		{		
       
  1200 		COpenFontGlyphTreeEntry* node = NULL;		
       
  1201 		if (glyphCache->iGlyphTreeOffset)
       
  1202 			{			
       
  1203 			node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
       
  1204 			}
       
  1205 				
       
  1206 		while (node)
       
  1207 			{
       
  1208 			TInt code = node->iCode;
       
  1209 			if(code == aCode)
       
  1210 				{
       
  1211 				// Found the glyph
       
  1212 				return node;
       
  1213 				}		
       
  1214 			else if(code > aCode)
       
  1215 				{									
       
  1216 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
       
  1217 				}
       
  1218 			else
       
  1219 				{										
       
  1220 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
       
  1221 				}
       
  1222 			}		
       
  1223 		}
       
  1224 	// No glyph found
       
  1225 	return NULL;
       
  1226 	}
       
  1227 	
       
  1228 /**
       
  1229 Retrieve glyph data from the per-font glyph cache.
       
  1230 If it is not found return NULL and place the address of the node pointer
       
  1231 to receive a new glyph in aNodeInsertPtr. 
       
  1232 If the cache hasn't been created, then return NULL.
       
  1233 Previous versions of this function created the cache, but as this function can potentially
       
  1234 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
       
  1235 be resized - this is not allowed by the kernel.
       
  1236 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
       
  1237 @param aCode The code for the glpyh to look for in the cache
       
  1238 @param aNodeInsertPtr Returns a pointer to a final empty left or right leaf node
       
  1239 in the glpyh tree where the searched for glyph can be inserted if necessary.
       
  1240 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
       
  1241 */
       
  1242 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode, TInt*& aNodeInsertPtr)
       
  1243 	{		
       
  1244 	aNodeInsertPtr = NULL;	
       
  1245 
       
  1246 	if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
       
  1247 		{		
       
  1248 		COpenFontGlyphTreeEntry* node = NULL;		
       
  1249 		if (glyphCache->iGlyphTreeOffset)
       
  1250 			{			
       
  1251 			node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(glyphCache->iGlyphTreeOffset));
       
  1252 			}
       
  1253 				
       
  1254 		while (node)
       
  1255 			{
       
  1256 			TInt code = node->iCode;
       
  1257 			if(code == aCode)
       
  1258 				{
       
  1259 				// Found the glyph
       
  1260 				return node;
       
  1261 				}		
       
  1262 			else if(code > aCode)
       
  1263 				{					
       
  1264 				aNodeInsertPtr = &node->iLeftOffset;
       
  1265 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iLeftOffset));			
       
  1266 				}
       
  1267 			else
       
  1268 				{						
       
  1269 				aNodeInsertPtr = &node->iRightOffset;
       
  1270 				node = static_cast<COpenFontGlyphTreeEntry*>(ThisOffsetToPointer(node->iRightOffset));			
       
  1271 				}
       
  1272 			}		
       
  1273 		}
       
  1274 
       
  1275 	// No glyph found
       
  1276 	return NULL;
       
  1277 	}
       
  1278 #else
       
  1279 /**
       
  1280 Retrieve glyph data from the per-font glyph cache.
       
  1281 If it is not found return NULL. 
       
  1282 If the cache hasn't been created, then return null.
       
  1283 Previous versions of this function created the cache, but as this function can potentially
       
  1284 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
       
  1285 be resized - this is not allowed by the kernel.
       
  1286 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
       
  1287 */
       
  1288 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode)
       
  1289 	{
       
  1290 	if (iGlyphCache)
       
  1291 		{					
       
  1292 		COpenFontGlyphTreeEntry* node = iGlyphCache->iGlyphTree;
       
  1293 		while (node)
       
  1294 			{
       
  1295 			if (node->iCode == aCode)
       
  1296 				return node;
       
  1297 			if (node->iCode > aCode)
       
  1298 				node = node->iLeft;
       
  1299 			else
       
  1300 				node = node->iRight;
       
  1301 			}			
       
  1302 		}
       
  1303 	
       
  1304 	return NULL;
       
  1305 	}
       
  1306 
       
  1307 /**
       
  1308 Retrieve glyph data from the per-font glyph cache.
       
  1309 If it is not found return NULL and place the address of the node pointer
       
  1310 to receive a new glyph in aNode. 
       
  1311 If the cache hasn't been created, then return null.
       
  1312 Previous versions of this function created the cache, but as this function can potentially
       
  1313 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to 
       
  1314 be resized - this is not allowed by the kernel.
       
  1315 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
       
  1316 */
       
  1317 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode, COpenFontGlyphTreeEntry**& aNode)
       
  1318 	{
       
  1319 	if (!iGlyphCache)
       
  1320 		{
       
  1321 		aNode = NULL;
       
  1322 		return NULL;
       
  1323 		}
       
  1324 
       
  1325 	aNode = &iGlyphCache->iGlyphTree;
       
  1326 	while (*aNode)
       
  1327 		{
       
  1328 		if ((*aNode)->iCode == aCode)
       
  1329 			return *aNode;
       
  1330 		if ((*aNode)->iCode > aCode)
       
  1331 			aNode = &((*aNode)->iLeft);
       
  1332 		else
       
  1333 			aNode = &((*aNode)->iRight);
       
  1334 		}
       
  1335 	
       
  1336 	return NULL;
       
  1337 	}
       
  1338 #endif // FNTSTORE_SUPPORT_FMM
       
  1339 
       
  1340 /** Retrieve glyph data from the session cache. If the glyph is not in the
       
  1341 cache, return the cache and glyph index where the glyph data should be put. If
       
  1342 there is no session cache, optionally create it.
       
  1343 
       
  1344 @param aHeap
       
  1345 	The heap on which to create the new cache, if appropriate. Not used if
       
  1346 	either the appropriate session cache already exists, or if aCreate is
       
  1347 	passed as false
       
  1348 @param aSessionHandle The session handle
       
  1349 @param aCode
       
  1350 	The code of the glyph to look up (Unicode or glyph code if the top bit is
       
  1351 	set)
       
  1352 @param aCache
       
  1353 	Returns the appropriate session cache, or NULL if an attempt to create it 
       
  1354 	has failed.
       
  1355 @param aIndex
       
  1356 	Returns where the glyph is, or should be put
       
  1357 @param aCreate
       
  1358 	If False, creation of a new cache is inhibited
       
  1359 @return The glyph data, or null if the glyph is not in the cache
       
  1360 @internalComponent
       
  1361 */
       
  1362 #ifdef FNTSTORE_SUPPORT_FMM
       
  1363 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
       
  1364 	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
       
  1365 	TInt& aIndex, TBool aCreate) const
       
  1366 	{
       
  1367 	aIndex = 0;
       
  1368 	COpenFontSessionCacheListItem* prev = NULL;
       
  1369 
       
  1370 	COpenFontSessionCacheList* cachelist = const_cast<COpenFont*>(this)->SessionCacheList();
       
  1371 	RSemaphore sem;
       
  1372 	if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
       
  1373 	    {
       
  1374 	    RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore"));
       
  1375 	    return NULL;
       
  1376 	    }
       
  1377 	sem.Wait();
       
  1378 	COpenFontSessionCacheListItem* cacheListStart=cachelist->Start();
       
  1379 	if(cacheListStart)
       
  1380 		{
       
  1381 		for (COpenFontSessionCacheListItem* p = cacheListStart; p; p = p->Next())
       
  1382 			{
       
  1383 			COpenFontSessionCache* cache=p->Cache();
       
  1384 			if (cache->iSessionHandle == aSessionHandle)
       
  1385 				{
       
  1386 				aCache = cache;
       
  1387 				sem.Signal();
       
  1388 				sem.Close();
       
  1389 				return aCache->Glyph(this,aCode,aIndex);
       
  1390 				}
       
  1391 			prev = p;
       
  1392 			}
       
  1393 		}
       
  1394 	sem.Signal();
       
  1395 	sem.Close();
       
  1396 	
       
  1397 	if (aCreate)
       
  1398 		{
       
  1399 		COpenFontSessionCache* new_cache = NULL;
       
  1400 		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
       
  1401 		
       
  1402 		if ((!error) && new_cache)
       
  1403 			{
       
  1404 			COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem));
       
  1405 			if (!new_item)
       
  1406 				{
       
  1407 				new_cache->Delete(aHeap);	
       
  1408 				aHeap->Free(new_cache);
       
  1409 				return NULL;
       
  1410 				}
       
  1411 
       
  1412 			new(new_item) COpenFontSessionCacheListItem(new_cache);
       
  1413 
       
  1414 			if (prev)
       
  1415 				{
       
  1416 				prev->SetNext(new_item);
       
  1417 				}
       
  1418 			else
       
  1419 				{
       
  1420 				cachelist->SetStart(new_item);
       
  1421 				}
       
  1422 
       
  1423 			aCache = new_cache;
       
  1424 			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
       
  1425 			}
       
  1426 		}
       
  1427 	return NULL;
       
  1428 	}
       
  1429 #else
       
  1430 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
       
  1431 	TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
       
  1432 	TInt& aIndex, TBool aCreate) const
       
  1433 	{
       
  1434 	aCache = NULL;
       
  1435 	aIndex = 0;
       
  1436 	COpenFontSessionCacheListItem* prev = NULL;
       
  1437     RSemaphore sem;
       
  1438     if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
       
  1439         {
       
  1440         RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore"));
       
  1441         return NULL;
       
  1442         }
       
  1443     sem.Wait();
       
  1444 	for (COpenFontSessionCacheListItem* p = iSessionCacheList->iStart; p; p = p->iNext)
       
  1445 		{
       
  1446 		if (p->iCache->iSessionHandle == aSessionHandle)
       
  1447 			{
       
  1448 			aCache = p->iCache;
       
  1449 		    sem.Signal();
       
  1450 		    sem.Close();
       
  1451 			return aCache->Glyph(this, aCode, aIndex);
       
  1452 			}
       
  1453 		prev = p;
       
  1454 		}
       
  1455     sem.Signal();
       
  1456 	sem.Close();
       
  1457 	
       
  1458 	if (aCreate)
       
  1459 		{
       
  1460 		COpenFontSessionCache* new_cache = NULL;
       
  1461 		TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
       
  1462 		
       
  1463 		if ((!error) && new_cache)
       
  1464 			{
       
  1465 			COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem));
       
  1466 			if (!new_item)
       
  1467 				{
       
  1468 				new_cache->Delete(aHeap);	
       
  1469 				aHeap->Free(new_cache);
       
  1470 				return NULL;
       
  1471 				}
       
  1472 
       
  1473 			new(new_item) COpenFontSessionCacheListItem(new_cache);
       
  1474 
       
  1475 			if (prev)
       
  1476 				prev->iNext = new_item;
       
  1477 			else
       
  1478 				iSessionCacheList->iStart = new_item;
       
  1479 
       
  1480 			aCache = new_cache;
       
  1481 			aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
       
  1482 			}
       
  1483 		}
       
  1484 	return NULL;
       
  1485 	}
       
  1486 #endif // FNTSTORE_SUPPORT_FMM
       
  1487 
       
  1488 /**
       
  1489 Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
       
  1490 The data is copied; ownership remains with the caller.
       
  1491 */
       
  1492 COpenFontGlyph* COpenFontGlyph::NewL(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
       
  1493 	{
       
  1494 	COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->AllocL(sizeof(COpenFontGlyph));
       
  1495 	new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
       
  1496 	if (!glyph->SetBitmap(aHeap, aBitmap))
       
  1497 		{
       
  1498 		aHeap->Free(glyph);
       
  1499 		User::Leave(KErrNoMemory);
       
  1500 		}
       
  1501 	return glyph;
       
  1502 	}	
       
  1503 
       
  1504 COpenFontGlyphTreeEntry* COpenFontGlyphTreeEntry::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
       
  1505 	{
       
  1506 	COpenFontGlyphTreeEntry* entry = (COpenFontGlyphTreeEntry*)aHeap->Alloc(sizeof(COpenFontGlyphTreeEntry));
       
  1507 	if (!entry)
       
  1508 		return NULL;
       
  1509 	new(entry) COpenFontGlyphTreeEntry(aCode, aGlyphIndex, aMetrics);
       
  1510 	if (!entry->SetBitmap(aHeap, aBitmap))
       
  1511 		{
       
  1512 		aHeap->Free(entry);
       
  1513 		entry = NULL;
       
  1514 		}
       
  1515 	return entry;
       
  1516 	}
       
  1517 
       
  1518 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) 
       
  1519 	{
       
  1520 	COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry));
       
  1521 	if (!entry)
       
  1522 		return NULL;
       
  1523 	new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
       
  1524 	if (!entry->SetBitmap(aHeap, aBitmap))
       
  1525 		{
       
  1526 		aHeap->Free(entry);
       
  1527 		entry = NULL;
       
  1528 		}
       
  1529 	return entry;
       
  1530 	}
       
  1531 
       
  1532 #ifdef FNTSTORE_SUPPORT_FMM
       
  1533 
       
  1534 inline COpenFont* COpenFontSessionCacheEntry::Font()const
       
  1535 {
       
  1536 if(iFontOffset)
       
  1537     {
       
  1538     return reinterpret_cast<COpenFont*>(reinterpret_cast<TInt>(this) + iFontOffset);
       
  1539     }
       
  1540 else
       
  1541     return NULL;
       
  1542 }
       
  1543 
       
  1544 /**
       
  1545 @return A pointer to the run-length-encoded bitmap stored with this glyph, or NULL
       
  1546 if no bitmap has been stored with this glyph.
       
  1547  */
       
  1548 TUint8* COpenFontGlyph::Bitmap() const
       
  1549 	{
       
  1550 	if (iBitmapOffset)
       
  1551 		{
       
  1552 		return (TUint8*)((TInt)this + iBitmapOffset);
       
  1553 		}
       
  1554 	return NULL;
       
  1555 	}
       
  1556 #endif // FNTSTORE_SUPPORT_FMM
       
  1557 
       
  1558 TBool COpenFontGlyph::SetBitmap(RHeap* aHeap, const TDesC8& aBitmap)
       
  1559 	{
       
  1560 	TUint8* bitmap = (TUint8*)aHeap->Alloc(aBitmap.Length());
       
  1561 	if (!bitmap)
       
  1562 		return FALSE;
       
  1563 	Mem::Copy(bitmap, aBitmap.Ptr(), aBitmap.Length());	
       
  1564 #ifdef FNTSTORE_SUPPORT_FMM
       
  1565 	aHeap->Free(Bitmap());
       
  1566 	iBitmapOffset = (TInt)bitmap - (TInt)this;
       
  1567 #else
       
  1568 	if (iBitmap)
       
  1569 		aHeap->Free(iBitmap);
       
  1570 	iBitmap = bitmap;
       
  1571 #endif // FNTSTORE_SUPPORT_FMM
       
  1572 	return TRUE;
       
  1573 	}
       
  1574 #ifdef FNTSTORE_SUPPORT_FMM
       
  1575 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
       
  1576 	{
       
  1577 	COpenFontSessionCache* c = reinterpret_cast<COpenFontSessionCache*>(aHeap->AllocL(sizeof(COpenFontSessionCache)));
       
  1578 	new(c) COpenFontSessionCache(aSessionHandle,aEntries);
       
  1579 	TInt bytes = sizeof(TInt) * aEntries;
       
  1580 	TInt* entry= reinterpret_cast<TInt*>(aHeap->Alloc(bytes));
       
  1581 	Mem::FillZ(entry, bytes);
       
  1582 	if (!entry)
       
  1583 		{
       
  1584 		aHeap->Free(c);
       
  1585 		User::Leave(KErrNoMemory);
       
  1586 		}
       
  1587 	c->iEntryOffset = reinterpret_cast<TInt>(entry) - reinterpret_cast<TInt>(c);
       
  1588 	return c;
       
  1589 	}
       
  1590 #else
       
  1591 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
       
  1592     {
       
  1593     COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
       
  1594     new(c) COpenFontSessionCache(aSessionHandle,aEntries);
       
  1595     TInt bytes = sizeof(COpenFontSessionCacheEntry*) * aEntries;
       
  1596     c->iEntry = (COpenFontSessionCacheEntry**)aHeap->Alloc(bytes);
       
  1597     Mem::FillZ(c->iEntry, bytes);
       
  1598     if (!c->iEntry)
       
  1599         {
       
  1600         aHeap->Free(c);
       
  1601         User::Leave(KErrNoMemory);
       
  1602         }
       
  1603     return c;
       
  1604     }
       
  1605 #endif //FNTSTORE_SUPPORT_FMM
       
  1606 
       
  1607 #ifdef FNTSTORE_SUPPORT_FMM
       
  1608 void COpenFontSessionCache::Delete(RHeap* aHeap)
       
  1609     {
       
  1610     TInt* e =Entry();
       
  1611     if(e)
       
  1612         {
       
  1613         for (TInt i = 0; i < iEntries; i++, e++)
       
  1614             {
       
  1615             if (ToCOpenFontSessionCacheEntryPointer(*e))
       
  1616                 {
       
  1617                 COpenFont* font=const_cast<COpenFont*>((ToCOpenFontSessionCacheEntryPointer(*e))->Font());
       
  1618                 if (font)
       
  1619                     font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue);
       
  1620                 aHeap->Free((ToCOpenFontSessionCacheEntryPointer(*e))->Bitmap());
       
  1621                 aHeap->Free(ToCOpenFontSessionCacheEntryPointer(*e));
       
  1622                 }
       
  1623             }
       
  1624         aHeap->Free(Entry());
       
  1625         iEntryOffset = 0;
       
  1626         }
       
  1627     }
       
  1628 #else
       
  1629 void COpenFontSessionCache::Delete(RHeap* aHeap)
       
  1630 	{
       
  1631 	COpenFontSessionCacheEntry** e =iEntry;
       
  1632 	for (TInt i = 0; i < iEntries; i++, e++)
       
  1633 		{
       
  1634 		if (*e)
       
  1635 			{
       
  1636 			COpenFont* font=const_cast<COpenFont*>((*e)->iFont);
       
  1637 			if (font)
       
  1638 				font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue);
       
  1639 			aHeap->Free((*e)->iBitmap);
       
  1640 			aHeap->Free(*e);
       
  1641 			}
       
  1642 		}
       
  1643 	aHeap->Free(iEntry);
       
  1644 	}
       
  1645 #endif //FNTSTORE_SUPPORT_FMM
       
  1646 
       
  1647 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex)
       
  1648 	{
       
  1649 	aIndex = -1;
       
  1650 	TInt oldest = KMaxTInt;
       
  1651 	TInt oldest_index = 0;
       
  1652 	TInt index = GLYPH_CODE(aCode) % iEntries;	// simple hash function to shorten searches
       
  1653 	for (TInt i = 0; i < iEntries; i++, index++)
       
  1654 		{
       
  1655 		if (index >= iEntries)
       
  1656 			index = 0;		
       
  1657 #ifdef FNTSTORE_SUPPORT_FMM
       
  1658 		COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[index]);
       
  1659 #else
       
  1660 		COpenFontSessionCacheEntry* e = iEntry[index];
       
  1661 #endif		//FNTSTORE_SUPPORT_FMM		
       
  1662 		if (!e)
       
  1663 			{
       
  1664 			if (aIndex == -1)
       
  1665 				aIndex = index;
       
  1666 			}
       
  1667 		else
       
  1668 			{
       
  1669 #ifdef FNTSTORE_SUPPORT_FMM
       
  1670 			if (e->Font() == aFont && e->iCode == aCode)
       
  1671 #else
       
  1672 			if (e->iFont == aFont && e->iCode == aCode)    
       
  1673 #endif //FNTSTORE_SUPPORT_FMM			    
       
  1674 				{
       
  1675 				e->iLastAccess = iLastAccess++;
       
  1676 				return e;
       
  1677 				}
       
  1678 			if (e->iLastAccess < oldest)
       
  1679 				{
       
  1680 				oldest = e->iLastAccess;
       
  1681 				oldest_index = index;
       
  1682 				}
       
  1683 			}
       
  1684 		}
       
  1685 	if (aIndex == -1)
       
  1686 		aIndex = oldest_index;
       
  1687 	return NULL;
       
  1688 	}
       
  1689 
       
  1690 
       
  1691 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
       
  1692 	{
       
  1693 	if ((aIndex < 0) || (aIndex > iEntries))
       
  1694 		Panic(EFntSessionCacheIndexOutOfRange);
       
  1695 #ifdef 	FNTSTORE_SUPPORT_FMM
       
  1696 	COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[aIndex]);
       
  1697 	COpenFontGlyph::Delete(aHeap, e);
       
  1698 	Entry()[aIndex] = reinterpret_cast<TInt>(aEntry) - reinterpret_cast<TInt>(this);
       
  1699 #else
       
  1700 	COpenFontGlyph::Delete(aHeap, iEntry[aIndex]);
       
  1701 	iEntry[aIndex] = aEntry;
       
  1702 #endif  //FNTSTORE_SUPPORT_FMM	
       
  1703 	aEntry->iLastAccess = iLastAccess++;
       
  1704 	}
       
  1705 
       
  1706 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle, TInt aEntries)
       
  1707  :	iSessionHandle(aSessionHandle),  
       
  1708 	iEntries(aEntries),
       
  1709 	iLastAccess(0),
       
  1710 #ifdef  FNTSTORE_SUPPORT_FMM
       
  1711     iEntryOffset(0)
       
  1712 #else 
       
  1713     iEntry(NULL)
       
  1714 #endif  //FNTSTORE_SUPPORT_FMM  
       
  1715 	{
       
  1716 	}
       
  1717 
       
  1718 #ifdef FNTSTORE_SUPPORT_FMM
       
  1719 
       
  1720 inline TInt* COpenFontSessionCache::Entry() const
       
  1721     {
       
  1722     if (iEntryOffset)
       
  1723         {
       
  1724         return reinterpret_cast<TInt*>(reinterpret_cast<TInt>(this) + iEntryOffset);
       
  1725         }
       
  1726     return NULL;
       
  1727     }
       
  1728 
       
  1729 inline COpenFontSessionCacheEntry* COpenFontSessionCache::ToCOpenFontSessionCacheEntryPointer(TInt aOffset)const
       
  1730     {
       
  1731     if(aOffset)
       
  1732         {
       
  1733         return reinterpret_cast<COpenFontSessionCacheEntry*>(reinterpret_cast<TInt>(this) + aOffset);
       
  1734         }
       
  1735     return NULL;
       
  1736     }
       
  1737 
       
  1738 #endif // FNTSTORE_SUPPORT_FMM
       
  1739 
       
  1740 /*COpenFontSessionCacheListItem*/
       
  1741 #ifdef FNTSTORE_SUPPORT_FMM
       
  1742 COpenFontSessionCacheListItem::COpenFontSessionCacheListItem(COpenFontSessionCache* aCache):
       
  1743 	iNextOffset(NULL)
       
  1744 	{
       
  1745 	if(aCache)
       
  1746 		{
       
  1747 		iCacheOffset = (TInt)aCache - (TInt)this;
       
  1748 		}
       
  1749 	else
       
  1750 		{
       
  1751 		iCacheOffset = NULL;
       
  1752 		}
       
  1753 	}
       
  1754 
       
  1755 COpenFontSessionCacheListItem::~COpenFontSessionCacheListItem()
       
  1756 	{
       
  1757 	}
       
  1758 #endif // FNTSTORE_SUPPORT_FMM
       
  1759 
       
  1760 /** Delete a COpenFontSessionCacheListItem from the passed heap.
       
  1761 
       
  1762 @param aHeap The heap to delete the COpenFontSessionCacheListItem from.
       
  1763  */
       
  1764 void COpenFontSessionCacheListItem::Delete(RHeap* aHeap)
       
  1765 	{
       
  1766 #ifdef FNTSTORE_SUPPORT_FMM
       
  1767 	Cache()->Delete(aHeap);	
       
  1768 	aHeap->Free(Cache());
       
  1769 	iCacheOffset=NULL;
       
  1770 	iNextOffset=NULL;
       
  1771 #else
       
  1772 	iCache->Delete(aHeap);	
       
  1773 	aHeap->Free(iCache);
       
  1774 	iCache=NULL;
       
  1775 #endif // FNTSTORE_SUPPORT_FMM
       
  1776 	}	
       
  1777 
       
  1778 #ifdef FNTSTORE_SUPPORT_FMM
       
  1779 /** Get the next item to this cache list item.
       
  1780 
       
  1781 @return A pointer to the next item to this one in the session cache, or NULL
       
  1782 if there is no next item.
       
  1783  */
       
  1784 COpenFontSessionCacheListItem* COpenFontSessionCacheListItem::Next()
       
  1785 	{
       
  1786 	if(iNextOffset)
       
  1787 		{
       
  1788 		COpenFontSessionCacheListItem* next = (COpenFontSessionCacheListItem*)((TInt)this + (TInt)iNextOffset);
       
  1789 		return next;
       
  1790 		}
       
  1791 	else
       
  1792 		{
       
  1793 		return NULL;
       
  1794 		}
       
  1795 	}
       
  1796 
       
  1797 /** Sets the next item to this in the session cache.
       
  1798 
       
  1799 @param aNext Set this cache list item as the next item to this one in the session cache list.
       
  1800  */
       
  1801 void COpenFontSessionCacheListItem::SetNext(COpenFontSessionCacheListItem* aNext)
       
  1802 	{
       
  1803 	if(aNext)
       
  1804 		{
       
  1805 		iNextOffset = (TInt)aNext - (TInt)this;
       
  1806 		}
       
  1807 	else
       
  1808 		{
       
  1809 		iNextOffset = NULL;
       
  1810 		}
       
  1811 	}
       
  1812 
       
  1813 /** Get a pointer to the session cache that this cache list item is in.
       
  1814 
       
  1815 @return A pointer to the session cache that this cache list item is part of.
       
  1816  */
       
  1817 COpenFontSessionCache* COpenFontSessionCacheListItem::Cache()
       
  1818 	{
       
  1819 	if(iCacheOffset)
       
  1820 		{
       
  1821 		COpenFontSessionCache* cache = (COpenFontSessionCache*)((TInt)this + (TInt)iCacheOffset);
       
  1822 		return cache;
       
  1823 		}
       
  1824 	else
       
  1825 		{
       
  1826 		return NULL;
       
  1827 		}
       
  1828 	}
       
  1829 
       
  1830 /** Get a pointer to the first item in the session cache.
       
  1831 
       
  1832 @return A pointer to the first item in the session cache.
       
  1833  */
       
  1834 COpenFontSessionCacheListItem* COpenFontSessionCacheList::Start()
       
  1835 	{
       
  1836 	if(iStartOffset)
       
  1837 		{
       
  1838 		COpenFontSessionCacheListItem* start = (COpenFontSessionCacheListItem*)((TInt)this + (TInt)iStartOffset);
       
  1839 		return start;
       
  1840 		}
       
  1841 	else
       
  1842 		{
       
  1843 		return NULL;
       
  1844 		}
       
  1845 
       
  1846 	}
       
  1847 
       
  1848 /** Set the passed item as the first item in the session cache. 
       
  1849 
       
  1850 @param aItem An item to be added to the session cache
       
  1851  */
       
  1852 void COpenFontSessionCacheList::SetStart(COpenFontSessionCacheListItem* aItem)
       
  1853 	{
       
  1854 	if(aItem!=NULL)
       
  1855 		{
       
  1856 		iStartOffset = (TInt)aItem - (TInt)this;
       
  1857 		}
       
  1858 	else
       
  1859 		{
       
  1860 		iStartOffset = 0;
       
  1861 		}
       
  1862 	}
       
  1863 #endif // FNTSTORE_SUPPORT_FMM
       
  1864 
       
  1865 /** Delete all the items in the session cache if the current cache session handle
       
  1866 matches the passed session handle.
       
  1867 
       
  1868 @param aHeap The heap base of the current process.
       
  1869 @param aSessionHandle The session handle of the cache to be deleted.
       
  1870  */
       
  1871 void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
       
  1872 	{
       
  1873 	COpenFontSessionCacheListItem* prev = NULL;
       
  1874 	   RSemaphore sem;
       
  1875 	    if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
       
  1876 	        {
       
  1877 	        RDebug::Print(_L("COpenFontSessionCacheList::DeleteCache() can't open SessionCacheSemaphore"));
       
  1878 	        return;
       
  1879 	        }	    
       
  1880 #ifdef FNTSTORE_SUPPORT_FMM
       
  1881  	for (COpenFontSessionCacheListItem* curr = Start(); curr; prev = curr, curr = curr->Next())
       
  1882 		{
       
  1883  		if (curr->Cache()->iSessionHandle == aSessionHandle)
       
  1884    			{
       
  1885    			for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
       
  1886    			    {
       
  1887 				//coverity[lock]
       
  1888 				//coverity[double_lock]
       
  1889    			    sem.Wait();
       
  1890    			    }
       
  1891  			if (curr==Start())
       
  1892  				SetStart(curr->Next());
       
  1893  			else
       
  1894  				prev->SetNext(curr->Next());
       
  1895  				
       
  1896    			curr->Delete(aHeap);
       
  1897  			aHeap->Free(curr);
       
  1898  			sem.Signal(KSessionCacheSemaphoreCount);
       
  1899  			sem.Close();
       
  1900    			return;
       
  1901    			}
       
  1902 		}
       
  1903 #else
       
  1904 	for (COpenFontSessionCacheListItem* curr = iStart; curr; prev = curr, curr = curr->iNext)
       
  1905 		{
       
  1906 		if (curr->iCache->iSessionHandle == aSessionHandle)
       
  1907 			{
       
  1908             for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
       
  1909                {
       
  1910                sem.Wait();
       
  1911                }
       
  1912 			if (curr==iStart)
       
  1913 				iStart   = curr->iNext;
       
  1914 			else
       
  1915 				prev->iNext = curr->iNext;
       
  1916 
       
  1917 			curr->Delete(aHeap);
       
  1918 			aHeap->Free(curr);
       
  1919             sem.Signal(KSessionCacheSemaphoreCount);
       
  1920             sem.Close();
       
  1921 			return;
       
  1922 			}
       
  1923 		}
       
  1924 #endif // FNTSTORE_SUPPORT_FMM
       
  1925 	}
       
  1926 
       
  1927 /** Delete all the items in the current session cache.
       
  1928 
       
  1929 @param aHeap The heap base of the current process.
       
  1930  */
       
  1931 void COpenFontSessionCacheList::Delete(RHeap* aHeap)
       
  1932 	{
       
  1933     RSemaphore sem;
       
  1934     if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
       
  1935         {
       
  1936         RDebug::Print(_L("COpenFontSessionCacheList::Delete() can't open SessionCacheSemaphore"));
       
  1937         return;
       
  1938         }		
       
  1939 #ifdef FNTSTORE_SUPPORT_FMM
       
  1940 	COpenFontSessionCacheListItem* cur = Start();
       
  1941 #else
       
  1942 	COpenFontSessionCacheListItem* cur = iStart;
       
  1943 #endif // FNTSTORE_SUPPORT_FMM
       
  1944 	COpenFontSessionCacheListItem* next = NULL;
       
  1945 
       
  1946     for(TInt i=0; i<KSessionCacheSemaphoreCount; i++)
       
  1947      {
       
  1948 	//coverity[lock]
       
  1949 	//coverity[double_lock]
       
  1950      sem.Wait();     
       
  1951      }
       
  1952 	while (cur)
       
  1953 		{
       
  1954 #ifdef FNTSTORE_SUPPORT_FMM
       
  1955 		next = cur->Next();
       
  1956 #else
       
  1957 		next = cur->iNext;
       
  1958 #endif // FNTSTORE_SUPPORT_FMM
       
  1959 		cur->Delete(aHeap);
       
  1960 		aHeap->Free(cur);
       
  1961 		cur = next;
       
  1962 		}
       
  1963     sem.Signal(KSessionCacheSemaphoreCount);
       
  1964     sem.Close();
       
  1965 	}
       
  1966 
       
  1967 /**
       
  1968 Delete all glyphs belonging to a particular font.
       
  1969 */
       
  1970 void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
       
  1971 	{
       
  1972     RSemaphore sem;
       
  1973     if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName))
       
  1974         {
       
  1975         RDebug::Print(_L("COpenFontSessionCacheList::DeleteFontGlyphs can't global open SessionCacheSemaphore"));
       
  1976         return;
       
  1977         }
       
  1978     sem.Wait();     
       
  1979 #ifdef FNTSTORE_SUPPORT_FMM     
       
  1980 	for (COpenFontSessionCacheListItem* p = Start(); p; p = p->Next())
       
  1981 		{
       
  1982 		COpenFontSessionCache* cache=p->Cache();
       
  1983 		TInt* e = cache->Entry();
       
  1984 		TInt entries = cache->iEntries;
       
  1985 		for (TInt i = 0; i < entries; i++, e++)
       
  1986 			{
       
  1987 			if ((cache->ToCOpenFontSessionCacheEntryPointer(*e)) 
       
  1988 			        && ((cache->ToCOpenFontSessionCacheEntryPointer(*e))->Font() == aFont))
       
  1989 				{
       
  1990 				COpenFontSessionCacheEntry::Delete(aHeap, cache->ToCOpenFontSessionCacheEntryPointer(*e));
       
  1991 				*e = 0;
       
  1992 				}
       
  1993 			}
       
  1994 		}
       
  1995 #else
       
  1996 	for (COpenFontSessionCacheListItem* p = iStart; p; p = p->iNext)
       
  1997 		{
       
  1998 		COpenFontSessionCacheEntry** e = p->iCache->iEntry;
       
  1999 		TInt entries = p->iCache->iEntries;
       
  2000 		for (TInt i = 0; i < entries; i++, e++)
       
  2001 			{
       
  2002 			if ((*e) && ((*e)->iFont == aFont))
       
  2003 				{
       
  2004 				COpenFontSessionCacheEntry::Delete(aHeap, *e);
       
  2005 				*e = NULL;
       
  2006 				}
       
  2007 			}
       
  2008 		}
       
  2009 #endif // FNTSTORE_SUPPORT_FMM
       
  2010 	
       
  2011 	sem.Signal();
       
  2012 	sem.Close();
       
  2013 	}
       
  2014 
       
  2015 /**
       
  2016 C++ constructor with a CFont parameter.
       
  2017 
       
  2018 This creates a TOpenFontMetrics and initialises it with size, ascent, maximum 
       
  2019 height, descent, maximum depth and maximum character width information from 
       
  2020 the CFont that was passed as a parameter.
       
  2021 
       
  2022 @param aFont The font from which to initialise the metrics object.
       
  2023 */
       
  2024 EXPORT_C TOpenFontMetrics::TOpenFontMetrics(const CFont* aFont)
       
  2025 	{
       
  2026 	iDesignHeight = (TInt16) aFont->HeightInPixels();
       
  2027 	iAscent = iMaxHeight = (TInt16) aFont->AscentInPixels();
       
  2028 	iDescent = iMaxDepth = (TInt16)(iDesignHeight - iAscent);
       
  2029 	iMaxWidth = (TInt16)aFont->MaxCharWidthInPixels();
       
  2030 	iBaselineCorrection = 0;
       
  2031 	}
       
  2032 
       
  2033 /** 
       
  2034 @publishedPartner
       
  2035 @prototype
       
  2036 
       
  2037 @param aBaselineCorrection The baseline correction to be associated with this font
       
  2038 
       
  2039 Sets the baseline correction applied to this font; this value is used to offset
       
  2040 the underlinke and strikethrough positions and is used by linked fonts only.
       
  2041 */
       
  2042 const TUint16 KBitsForUnderline = 10;
       
  2043 const TUint16 KMaskUnderline = (1<<KBitsForUnderline)-1;  //bottom bits which are set 
       
  2044 const TUint16 KMaskBitmapType = ~KMaskUnderline;  //top bits which are set
       
  2045 const TUint16 KSignBit = 1<<(KBitsForUnderline-1); //sign bit for the lower number, which can be signed
       
  2046 const TUint32 KTop16Of32Bits = 0xffff0000; 
       
  2047 
       
  2048 EXPORT_C void TOpenFontMetrics::SetBaselineCorrection(TInt aBaselineCorrection)
       
  2049 	{
       
  2050 	__ASSERT_DEBUG(aBaselineCorrection<(1<<(KBitsForUnderline-1)), Panic(EFntOverFlow));
       
  2051 	__ASSERT_DEBUG(aBaselineCorrection>(0-(1<<(KBitsForUnderline-1))), Panic(EFntOverFlow));
       
  2052 	
       
  2053 	TUint16 value = iBaselineCorrection;
       
  2054 	value &=~KMaskUnderline; //zero all the underline position bits
       
  2055 	if (aBaselineCorrection<0)
       
  2056 		{
       
  2057 		//need to mask out extra sign bits for negative value
       
  2058 		iBaselineCorrection = value | (static_cast<TUint16>(aBaselineCorrection)&~KMaskBitmapType);
       
  2059 		}
       
  2060 	else
       
  2061 		{
       
  2062 		iBaselineCorrection = value | static_cast<TUint16>(aBaselineCorrection);
       
  2063 		}
       
  2064 	}
       
  2065 
       
  2066 /**
       
  2067 @publishedPartner
       
  2068 @prototype
       
  2069 
       
  2070 Gets the baseline correction applied to this font; this value is used to offset
       
  2071 the underlinke and strikethrough positions and is used by linked fonts only.
       
  2072 
       
  2073 @return The baseline correction associated with this font
       
  2074 */
       
  2075 
       
  2076 EXPORT_C TInt TOpenFontMetrics::BaselineCorrection()
       
  2077 	{
       
  2078 	TUint16 value = iBaselineCorrection;  //read once for improved multi threading
       
  2079 	if (!(value & KSignBit))
       
  2080 		{
       
  2081 		//value is positive, no need to sign extend
       
  2082 		return value & KMaskUnderline;
       
  2083 		}
       
  2084 	else
       
  2085 		{
       
  2086 		//value is negative, need to stuff ones into the high bits
       
  2087 		//could shift up and shift down
       
  2088 		return static_cast<TInt>(static_cast<TUint>(value) | KMaskBitmapType | KTop16Of32Bits);
       
  2089 		}
       
  2090 	}
       
  2091 
       
  2092 /**
       
  2093 C++ constructor with UID and filename.
       
  2094 
       
  2095 Call this constructor in the constructor for your derived object, passing 
       
  2096 it aUid and aFileName arguments.
       
  2097 
       
  2098 Non Symbian-platform-native font files are allocated IDs by the font store. 
       
  2099 These are passed in by the rasteriser class. UIDs are required by the 
       
  2100 font framework. However you should not use the ID to access the file, since 
       
  2101 a new UID will need to be allocated when the file is next loaded, e.g. after 
       
  2102 a device reboot. Instead use the font file name.
       
  2103 
       
  2104 @param aUid The UID of the font file.
       
  2105 @param aFileName The full filename, including the path, of the font file.
       
  2106 */
       
  2107 EXPORT_C COpenFontFile::COpenFontFile(TInt aUid, const TDesC& aFileName)
       
  2108  :	iFaceAttrib(1),
       
  2109 	iUid(TUid::Uid(aUid)),
       
  2110 	iFileName(aFileName),
       
  2111 	iFontList(8)
       
  2112 	{
       
  2113 	}
       
  2114 
       
  2115 /**
       
  2116 Destructor.
       
  2117 
       
  2118 It is not allowed that file is deleted before its fonts
       
  2119 and the logic is handled in CFontStore::RemoveFile().
       
  2120 */
       
  2121 EXPORT_C COpenFontFile::~COpenFontFile()
       
  2122 	{
       
  2123     CFontStore *fs = GetFontStore();
       
  2124     if (fs)
       
  2125         {
       
  2126         fs->CleanupCacheOnOpenFontFileRemoval(this);
       
  2127         }
       
  2128 	delete iData;
       
  2129 	}
       
  2130 
       
  2131 /**
       
  2132 Gets the nearest font in pixels.
       
  2133 
       
  2134 Implementations of this pure virtual function should create the COpenFont 
       
  2135 derived object that most closely matches aFontSpec, and place a pointer to 
       
  2136 it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
       
  2137 aFont should be set to NULL. 
       
  2138 	
       
  2139 The other two arguments, aHeap and aSessionCacheList, should be passed to 
       
  2140 the COpenFont constructor.
       
  2141 	
       
  2142 Implementations may use the utilitity function GetNearestFontHelper() to get 
       
  2143 the attributes of the closest matching font.
       
  2144 	
       
  2145 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
       
  2146 classes' constructor.
       
  2147 @param aSessionCacheList The session cache list. This value should be passed 
       
  2148 to the COpenFont derived classes' constructor.
       
  2149 @param aDesiredFontSpec The desired font specification.
       
  2150 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
       
  2151 the algorithmic slant of the typeface. 
       
  2152 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
       
  2153 the algorithmic slant of the typeface.
       
  2154 @param aFont On return, contains a pointer to the newly created COpenFont 
       
  2155 derived object, or NULL if no font matching aDesiredFontSpec exists.
       
  2156 @param aActualFontSpec The actual font specification of the font retrieved 
       
  2157 into aFont. 
       
  2158 @see GetNearestFontHelper()
       
  2159 @deprecated Use GetNearestFontToDesignHeightInPixels
       
  2160 */
       
  2161 TInt COpenFontFile::GetNearestFontInPixels(
       
  2162 	RHeap*						aHeap,
       
  2163 	COpenFontSessionCacheList*	aSessionCacheList,
       
  2164 	const TOpenFontSpec&		aDesiredFontSpec,
       
  2165 	TInt						aPixelWidth,
       
  2166 	TInt						aPixelHeight,
       
  2167 	COpenFont*&					aFont,
       
  2168 	TOpenFontSpec&				aActualFontSpec)
       
  2169 	{
       
  2170 	return GetNearestFontToDesignHeightInPixels(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec);
       
  2171 	}
       
  2172 
       
  2173 /**
       
  2174 Gets the nearest font in pixels.
       
  2175 
       
  2176 Implementations of this pure virtual function should create the COpenFont 
       
  2177 derived object that most closely matches aFontSpec, and place a pointer to 
       
  2178 it in aFont. If this cannot be done, e.g. if the font name doesn't match, 
       
  2179 aFont should be set to NULL. 
       
  2180 	
       
  2181 The other two arguments, aHeap and aSessionCacheList, should be passed to 
       
  2182 the COpenFont constructor.
       
  2183 	
       
  2184 Implementations may use the utilitity function GetNearestFontHelper() to get 
       
  2185 the attributes of the closest matching font.
       
  2186 	
       
  2187 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
       
  2188 classes' constructor.
       
  2189 @param aSessionCacheList The session cache list. This value should be passed 
       
  2190 to the COpenFont derived classes' constructor.
       
  2191 @param aDesiredFontSpec The desired font specification.
       
  2192 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
       
  2193 the algorithmic slant of the typeface. 
       
  2194 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
       
  2195 the algorithmic slant of the typeface.
       
  2196 @param aFont On return, contains a pointer to the newly created COpenFont 
       
  2197 derived object, or NULL if no font matching aDesiredFontSpec exists.
       
  2198 @param aActualFontSpec The actual font specification of the font retrieved 
       
  2199 into aFont. 
       
  2200 @see GetNearestFontHelper()
       
  2201 */
       
  2202 TInt COpenFontFile::GetNearestFontToDesignHeightInPixels(
       
  2203 	RHeap*						aHeap,
       
  2204 	COpenFontSessionCacheList*	aSessionCacheList,
       
  2205 	const TOpenFontSpec&		aDesiredFontSpec,
       
  2206 	TInt						aPixelWidth,
       
  2207 	TInt						aPixelHeight,
       
  2208 	COpenFont*&					aFont,
       
  2209 	TOpenFontSpec&				aActualFontSpec)
       
  2210 	{
       
  2211 	aFont = NULL;
       
  2212 	TRAPD(error, GetNearestFontToDesignHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec));
       
  2213 	return error;
       
  2214 	}
       
  2215 
       
  2216 
       
  2217 void COpenFontFile::GetNearestFontToDesignHeightInPixelsAndAddToListL(
       
  2218 	RHeap*						aHeap,
       
  2219 	COpenFontSessionCacheList*	aSessionCacheList,
       
  2220 	const TOpenFontSpec&		aDesiredFontSpec,
       
  2221 	TInt						aPixelWidth,
       
  2222 	TInt						aPixelHeight,
       
  2223 	COpenFont*&					aFont,
       
  2224 	TOpenFontSpec&				aActualFontSpec)
       
  2225 	{
       
  2226 	COpenFont* fontPtr = NULL;
       
  2227 	GetNearestFontToDesignHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec);
       
  2228 	if (fontPtr != NULL)
       
  2229 		{ // found a matching font
       
  2230 		CleanupStack::PushL(fontPtr);
       
  2231 		iFontList.AppendL(fontPtr);
       
  2232 		// transfer ownership
       
  2233 		aFont = fontPtr;
       
  2234 		CleanupStack::Pop(fontPtr);
       
  2235 		}
       
  2236 	}
       
  2237 
       
  2238 
       
  2239 /**
       
  2240 Gets the nearest font in pixels that fits inside specified max height.
       
  2241 
       
  2242 Implementations of this pure virtual function should create the COpenFont 
       
  2243 derived object that most closely matches aFontSpec, while fitting within
       
  2244 aMaxHeight, and place a pointer to it in aFont. If this cannot be done,
       
  2245 e.g. if the font name doesn't match, aFont should be set to NULL. 
       
  2246 
       
  2247 The other two arguments, aHeap and aSessionCacheList, should be passed to 
       
  2248 the COpenFont constructor.
       
  2249 
       
  2250 Implementations may use the utilitity function GetNearestFontHelper()
       
  2251 to get the attributes of the closest matching font.
       
  2252 
       
  2253 @param aHeap Shared heap. This value should be passed to the COpenFont derived 
       
  2254 classes' constructor.
       
  2255 @param aSessionCacheList The session cache list. This value should be passed 
       
  2256 to the COpenFont derived classes' constructor.
       
  2257 @param aDesiredFontSpec The desired font specification.
       
  2258 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
       
  2259 the algorithmic slant of the typeface. 
       
  2260 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
       
  2261 the algorithmic slant of the typeface.
       
  2262 @param aFont On return, contains a pointer to the newly created COpenFont 
       
  2263 derived object, or NULL if no font matching aDesiredFontSpec exists.
       
  2264 @param aActualFontSpec The actual font specification of the font retrieved 
       
  2265 into aFont. 
       
  2266 @param aMaxHeight The maximum height within which the font must fit.
       
  2267 @see GetNearestFontHelper()
       
  2268 */
       
  2269 TInt COpenFontFile::GetNearestFontToMaxHeightInPixels(
       
  2270 	RHeap*						aHeap,
       
  2271 	COpenFontSessionCacheList*	aSessionCacheList,
       
  2272 	const TOpenFontSpec&		aDesiredFontSpec,
       
  2273 	TInt						aPixelWidth,
       
  2274 	TInt						aPixelHeight,
       
  2275 	COpenFont*&					aFont,
       
  2276 	TOpenFontSpec&				aActualFontSpec,
       
  2277 	TInt						aMaxHeight)
       
  2278 	{
       
  2279 	aFont = NULL;
       
  2280 	TRAPD(error, GetNearestFontToMaxHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec, aMaxHeight));
       
  2281 	return error;
       
  2282 	}
       
  2283 
       
  2284 
       
  2285 void COpenFontFile::GetNearestFontToMaxHeightInPixelsAndAddToListL(
       
  2286 	RHeap*						aHeap,
       
  2287 	COpenFontSessionCacheList*	aSessionCacheList,
       
  2288 	const TOpenFontSpec&		aDesiredFontSpec,
       
  2289 	TInt						aPixelWidth,
       
  2290 	TInt						aPixelHeight,
       
  2291 	COpenFont*&					aFont,
       
  2292 	TOpenFontSpec&				aActualFontSpec,
       
  2293 	TInt						aMaxHeight)
       
  2294 	{
       
  2295 	COpenFont* fontPtr = NULL;
       
  2296 	GetNearestFontToMaxHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec, aMaxHeight);
       
  2297 	if (fontPtr != NULL)
       
  2298 		{  // found a matching font
       
  2299 		CleanupStack::PushL(fontPtr);
       
  2300 		iFontList.AppendL(fontPtr);
       
  2301 		// transfer ownership
       
  2302 		aFont = fontPtr;
       
  2303 		CleanupStack::Pop(fontPtr);
       
  2304 		}
       
  2305 	}
       
  2306 
       
  2307 
       
  2308 /**
       
  2309 Gets the nearest font helper function.
       
  2310 
       
  2311 This function may be used by derived classes in their GetNearestFontInPixelsL() 
       
  2312 implementations. It finds the nearest font in the typeface attribute array, 
       
  2313 if any, to the provided font specification. If there is a possible match it 
       
  2314 places the face index in aFaceIndex and the actual specification (including 
       
  2315 algorithmic effects) in aActualFontSpec.
       
  2316 
       
  2317 @param aDesiredFontSpec The desired font specification.
       
  2318 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating 
       
  2319 the algorithmic slant of the typeface.
       
  2320 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating 
       
  2321 the algorithmic slant of the typeface.
       
  2322 @param aFaceIndex The index of the typeface which contains the closest match 
       
  2323 to aDesiredFontSpec.
       
  2324 @param aActualFontSpec The actual font specification of the font with attributes 
       
  2325 closest to aDesiredFontSpec.
       
  2326 @return ETrue if there is a possible font match, otherwise EFalse.
       
  2327 */
       
  2328 EXPORT_C TBool COpenFontFile::GetNearestFontHelper(
       
  2329 	const TOpenFontSpec&	aDesiredFontSpec,
       
  2330 	TInt					aPixelWidth,
       
  2331 	TInt					aPixelHeight,
       
  2332 	TInt&					aFaceIndex,
       
  2333 	TOpenFontSpec&			aActualFontSpec) const
       
  2334 	{
       
  2335 	const TInt faces = FaceCount();
       
  2336 	TInt best_points = 0;
       
  2337 	TInt best_index = -1;
       
  2338 
       
  2339 	for (TInt i = 0; i < faces; i++)
       
  2340 		{
       
  2341 		TInt cur_points = 0;
       
  2342 
       
  2343 		if (0 < aDesiredFontSpec.Name().Length())
       
  2344 			{
       
  2345 			cur_points = ScoreByName(aDesiredFontSpec, iFaceAttrib[i]);
       
  2346 			}
       
  2347 		else
       
  2348 			{
       
  2349 			cur_points = ScoreByStyle(aDesiredFontSpec, iFaceAttrib[i]);
       
  2350 			}
       
  2351 
       
  2352 		if (cur_points)
       
  2353 			{
       
  2354 			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
       
  2355 				cur_points++;
       
  2356 			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
       
  2357 				cur_points++;
       
  2358 			}
       
  2359 
       
  2360 		if (cur_points > best_points)
       
  2361 			{
       
  2362 			best_points = cur_points;
       
  2363 			best_index = i;
       
  2364 			}
       
  2365 		}
       
  2366 
       
  2367 	if (best_index != -1)
       
  2368 		{
       
  2369 		aActualFontSpec = aDesiredFontSpec;
       
  2370 		// copy attributes & name
       
  2371 		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
       
  2372 		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
       
  2373 		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
       
  2374 		if ((aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[best_index].IsItalic()) && (0 == aDesiredFontSpec.SlantFactor()))
       
  2375 			{
       
  2376 			TInt factor = KDefaultSlantFactor;
       
  2377 			if (TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
       
  2378 				{
       
  2379 				TOpenFontSpec::ApplyRatio(factor, aPixelWidth, aPixelHeight);
       
  2380 				}
       
  2381 			aActualFontSpec.SetSlantFactor(factor);
       
  2382 			}
       
  2383 		}
       
  2384 
       
  2385 	aFaceIndex = best_index;
       
  2386 	return best_index != -1;
       
  2387 	}
       
  2388 
       
  2389 TInt COpenFontFile::ScoreByName(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
       
  2390 	{
       
  2391 	if (!aDesiredFontSpec.Name().CompareF(aAttrib.FullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFullName()))
       
  2392 		{
       
  2393 		return 4;
       
  2394 		}
       
  2395 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFullName()))
       
  2396 		{
       
  2397 		return 3;
       
  2398 		}
       
  2399 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.FamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFamilyName()))
       
  2400 		{
       
  2401 		return 2;
       
  2402 		}
       
  2403 	else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFamilyName()))
       
  2404 		{
       
  2405 		return 1;
       
  2406 		}
       
  2407 	return 0;
       
  2408 	}
       
  2409 
       
  2410 TInt COpenFontFile::ScoreByStyle(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
       
  2411 	{
       
  2412 	if (aDesiredFontSpec.IsSymbol() == aAttrib.IsSymbol())
       
  2413 		{
       
  2414 		return 4;
       
  2415 		}
       
  2416 	else if(aDesiredFontSpec.IsMonoWidth() == aAttrib.IsMonoWidth())
       
  2417 		{
       
  2418 		return 3;
       
  2419 		}
       
  2420 	else if(aDesiredFontSpec.IsSerif() == aAttrib.IsSerif())
       
  2421 		{
       
  2422 		return 2;
       
  2423 		}
       
  2424 
       
  2425 	return 0;
       
  2426 	}
       
  2427 
       
  2428 #ifdef _DEBUG
       
  2429 /**  @internalComponent */
       
  2430 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec& aDesiredFontSpec, TInt aPixelWidth,TInt aPixelHeight,TInt& aFaceIndex, TOpenFontSpec& aActualFontSpec) const
       
  2431 	{
       
  2432 	TInt faces = FaceCount();
       
  2433 	TInt best_points = 0;
       
  2434 	TInt best_index = -1;
       
  2435 	TBool slant = FALSE;
       
  2436 	for (TInt i = 0; i < faces; i++)
       
  2437 		{
       
  2438 		TPtrC family_name = iFaceAttrib[i].FamilyName();
       
  2439 		TPtrC full_name = iFaceAttrib[i].FullName();
       
  2440 		TPtrC local_family_name = iFaceAttrib[i].LocalFamilyName();
       
  2441 		TPtrC local_full_name = iFaceAttrib[i].LocalFullName();
       
  2442 		TPtrC desired_name = aDesiredFontSpec.Name();
       
  2443 
       
  2444 		TInt cur_points = 0;
       
  2445 		if (desired_name.Length() > 0)
       
  2446 			{
       
  2447 			if ((full_name.CompareF(desired_name) == 0) || (local_full_name.CompareF(desired_name) == 0))
       
  2448 				cur_points = 4;
       
  2449 			else if ((family_name.CompareF(desired_name) == 0) || (local_family_name.CompareF(desired_name) == 0))
       
  2450 				cur_points = 2;
       
  2451 			}
       
  2452 		else
       
  2453 			{
       
  2454 			if ((aDesiredFontSpec.IsSerif() == iFaceAttrib[i].IsSerif()) && (aDesiredFontSpec.IsMonoWidth() == iFaceAttrib[i].IsMonoWidth()) && (aDesiredFontSpec.IsSymbol() == iFaceAttrib[i].IsSymbol()))
       
  2455 				cur_points = 2;
       
  2456 			}
       
  2457 		if (cur_points)
       
  2458 			{
       
  2459 			if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
       
  2460 				cur_points++;
       
  2461 			if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
       
  2462 				cur_points++;
       
  2463 			if (cur_points > best_points)
       
  2464 				{
       
  2465 				best_points = cur_points;
       
  2466 				best_index = i;
       
  2467 				slant = (aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[i].IsItalic());
       
  2468 				}
       
  2469 			}
       
  2470 		}
       
  2471 
       
  2472 	if (best_index != -1)
       
  2473 		{
       
  2474 		TInt32 slant_factor = aDesiredFontSpec.SlantFactor();
       
  2475 
       
  2476 		// Set an algorithmic slant and adjust it for the pixel aspect ratio.
       
  2477 		if (slant && slant_factor == 0)
       
  2478 			{
       
  2479 			slant_factor = KDefaultSlantFactor;
       
  2480 			if (aPixelWidth>0 && aPixelHeight>0 && TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth,aPixelHeight))
       
  2481 				{
       
  2482 				TOpenFontSpec::ApplyRatio(slant_factor,aPixelWidth,aPixelHeight);
       
  2483 				}
       
  2484 			}
       
  2485 
       
  2486 		aActualFontSpec = aDesiredFontSpec;
       
  2487 		// copy attributes & name
       
  2488 		aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
       
  2489 		aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
       
  2490 		aActualFontSpec.SetSlantFactor(slant_factor);
       
  2491 		aActualFontSpec.SetEffects(0);
       
  2492 		}
       
  2493 
       
  2494 	aFaceIndex = best_index;
       
  2495 	return best_index != -1;
       
  2496 	}
       
  2497 #else //_DEBUG
       
  2498 /**
       
  2499 @internalComponent
       
  2500 */
       
  2501 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec&, TInt, TInt, TInt&, TOpenFontSpec&) const 
       
  2502 	{
       
  2503 	return EFalse;
       
  2504 	}
       
  2505 #endif //_DEBUG
       
  2506 
       
  2507 /** This function is called (via iFile) by a COpenFont when it is destroyed. */
       
  2508 void COpenFontFile::RemoveFontFromList(const COpenFont* aFont)
       
  2509 	{
       
  2510 	TInt fonts = iFontList.Count();
       
  2511 	for (TInt i = 0; i < fonts; i++)
       
  2512 		if (iFontList[i] == aFont)
       
  2513 			{
       
  2514 			iFontList.Delete(i);
       
  2515 			break;
       
  2516 			}
       
  2517 	}
       
  2518 
       
  2519 /**
       
  2520 Adds a typeface to this object's typeface array.
       
  2521 
       
  2522 This function should be called during construction to add the attributes for 
       
  2523 each typeface in the font file to the typeface attribute array. 
       
  2524 
       
  2525 Note:
       
  2526 
       
  2527 The typeface array is what is searched for the closest match to a specified 
       
  2528 font by GetNearestFontHelper().
       
  2529 
       
  2530 @param aAttrib The attributes for a typeface to be added to the typeface attribute 
       
  2531 array.
       
  2532 @see FaceAttrib()
       
  2533 @see FaceCount()
       
  2534 */
       
  2535 EXPORT_C void COpenFontFile::AddFaceL(const TOpenFontFaceAttrib& aAttrib)
       
  2536 	{
       
  2537 	TAttrib& a = iFaceAttrib.ExtendL();
       
  2538 	(TOpenFontFaceAttrib&)a = aAttrib;
       
  2539 	}
       
  2540 
       
  2541 void COpenFontFile::SetFontStoreL(CFontStore* aFontStore)
       
  2542 	{
       
  2543 	if (!iData)
       
  2544 		{
       
  2545 		iData = new (ELeave) TOpenFontFileData;
       
  2546 		}
       
  2547 	iData->iFontStore = aFontStore;
       
  2548 	}
       
  2549 
       
  2550 CFontStore* COpenFontFile::GetFontStore()
       
  2551 	{
       
  2552 	return iData ? iData->iFontStore : NULL;
       
  2553 	}
       
  2554 
       
  2555 CArrayPtrFlat<COpenFont>* COpenFontFile::GetOpenFontList()
       
  2556 	{
       
  2557 	return &iFontList;
       
  2558 	}
       
  2559 
       
  2560 
       
  2561 static const TInt KTOpenFontSpecBitsNumSymbol = 1;
       
  2562 static const TInt KTOpenFontSpecBitsNumScript = 4;
       
  2563 static const TInt KTOpenFontSpecMaskSymbol = (1 << KTOpenFontSpecBitsNumSymbol) - 1;
       
  2564 static const TInt KTOpenFontSpecMaskScript = ((1 << KTOpenFontSpecBitsNumScript) - 1) << KTOpenFontSpecBitsNumSymbol;
       
  2565 static const TInt KTOpenFontSpecSymbolFlag = 0x1;
       
  2566 
       
  2567 /**
       
  2568 Default C++ constructor setting
       
  2569 height to 16 pixels or twips,
       
  2570 width factor to 1 (65536 in 16.16 format),
       
  2571 slant factor to 0 (no slant),
       
  2572 effects to ENone,
       
  2573 symbol to 0 (assuming EScriptNone = 0),
       
  2574 print position to EPrintPosNormal.
       
  2575 */
       
  2576 EXPORT_C TOpenFontSpec::TOpenFontSpec()
       
  2577  :	iHeight(16),
       
  2578 	iWidthFactor(KOneIn16Dot16FixedPointFormat),
       
  2579 	iSlantFactor(0),
       
  2580 	iBitmapType(0),
       
  2581 	iEffects(FontEffect::ENone),
       
  2582 	iSymbol(0),
       
  2583 	iPrintPosition(EPrintPosNormal),
       
  2584 	iReserved2(0)
       
  2585 	{
       
  2586 	}
       
  2587 
       
  2588 /**
       
  2589 C++ constructor taking a reference to a TFontSpec.
       
  2590 
       
  2591 This object's members are initialised from the values of the aFontSpec parameter.
       
  2592 
       
  2593 @param aFontSpec The font specification used to initialise this font specification.
       
  2594 */
       
  2595 EXPORT_C TOpenFontSpec::TOpenFontSpec(const TFontSpec& aFontSpec)
       
  2596 	{
       
  2597 	*this = aFontSpec;
       
  2598 	}
       
  2599 
       
  2600 /**
       
  2601 Assignment operator.
       
  2602 
       
  2603 @param aFontSpec The old-style font specification to copy into this font specification.
       
  2604 */
       
  2605 EXPORT_C void TOpenFontSpec::operator=(const TFontSpec& aFontSpec)
       
  2606 	{
       
  2607 	iSlantFactor = 0;
       
  2608 	iWidthFactor = KOneIn16Dot16FixedPointFormat;
       
  2609 	iHeight			= aFontSpec.iHeight;	// in twips
       
  2610 	iBitmapType		= aFontSpec.iFontStyle.BitmapType();
       
  2611 	iEffects		= aFontSpec.iFontStyle.Effects();
       
  2612 	iPrintPosition	= aFontSpec.iFontStyle.PrintPosition();
       
  2613 	iName			= aFontSpec.iTypeface.iName;
       
  2614 	SetScriptTypeForMetrics(aFontSpec.iTypeface.ScriptTypeForMetrics());
       
  2615 	const TBool symbol = aFontSpec.iTypeface.IsSymbol();
       
  2616 	SetSymbol(symbol);
       
  2617 	if (symbol)
       
  2618 		SetCoverage(0);	// no appropriate coverage value for the symbol set
       
  2619 	else
       
  2620 		SetCoverage(3);	// Latin and Latin-1 supplement
       
  2621 	iStyle = 0;
       
  2622 	if (!aFontSpec.iTypeface.IsProportional())
       
  2623 		iStyle |= TOpenFontFaceAttrib::EMonoWidth;
       
  2624 	if (aFontSpec.iTypeface.IsSerif())
       
  2625 		iStyle |= TOpenFontFaceAttrib::ESerif;
       
  2626 	if (aFontSpec.iFontStyle.Posture() == EPostureItalic)
       
  2627 		iStyle |= TOpenFontFaceAttrib::EItalic;
       
  2628 	if (aFontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
       
  2629 		iStyle |= TOpenFontFaceAttrib::EBold;
       
  2630 	}
       
  2631 
       
  2632 
       
  2633 /**
       
  2634 Adjust the width factor and slant factor to suit a pixel aspect ratio.
       
  2635 @publishedAll
       
  2636 @released
       
  2637 @param aPixelWidth The pixel width, in the same units as aPixelHeight.
       
  2638 @param aPixelHeight The pixel height, in the same units as aPixelWidth.
       
  2639 */
       
  2640 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(TInt aPixelWidth, TInt aPixelHeight)
       
  2641 	{
       
  2642 	if (IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
       
  2643 		{
       
  2644 		ApplyRatio(iWidthFactor, aPixelHeight, aPixelWidth);
       
  2645 		ApplyRatio(iSlantFactor, aPixelWidth, aPixelHeight);
       
  2646 		}
       
  2647 	}
       
  2648 
       
  2649 /**
       
  2650 Adjust the width factor and slant factor to suit a pixel aspect ratio stored 
       
  2651 in a MGraphicsDeviceMap derived object.
       
  2652 @publishedAll
       
  2653 @released
       
  2654 @param aMap The MGraphicsDeviceMap defining the pixel aspect ratio.
       
  2655 */
       
  2656 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(const MGraphicsDeviceMap& aMap)
       
  2657 	{
       
  2658 	CompensateForAspectRatio(aMap.HorizontalPixelsToTwips(1000), aMap.VerticalPixelsToTwips(1000));
       
  2659 	}
       
  2660 
       
  2661 /**
       
  2662 The pixel width and height are used to derive a ratio, and so can be 
       
  2663 in any units. Aspect ratios differing by less than 1/1000 are treated as 1:1.
       
  2664 @internalTechnology
       
  2665 */
       
  2666 TBool TOpenFontSpec::IsCompensationForAspectRatioNeeded(TInt aPixelWidth,TInt aPixelHeight)
       
  2667 	{
       
  2668 	if ((aPixelWidth != aPixelHeight) && (0 < aPixelWidth) && (0 < aPixelHeight))
       
  2669 		{
       
  2670 		//If nearly square don't transform (0.999 < aPixelHeight/aPixelWidth < 1.001)
       
  2671 		TInt64 width = aPixelWidth;
       
  2672 		TInt64 height = aPixelHeight;
       
  2673 		width *= 999;	// Cannot do multiplication on declaration lines above as risk of TInt32 overflow
       
  2674 		height *= 1000;
       
  2675 		if (width <= height)	// 999 * aPixelWidth <= 1000 * aPixelHeight
       
  2676 			return ETrue;
       
  2677 		width += aPixelWidth;
       
  2678 		width += aPixelWidth;	// Cannot do with previous line as small risk of TInt32 overflow
       
  2679 		if (width >= height)	// 1001 * aPixelWidth >= 1000 * aPixelHeight
       
  2680 			return ETrue;
       
  2681 		}
       
  2682 	return EFalse;
       
  2683 	}
       
  2684 
       
  2685 /**
       
  2686 Multiplies aValue by aNumerator/aDenominator but using TInt64's to avoid any overflows.
       
  2687 Returns ETrue if the final result has an overflow.
       
  2688 @internalTechnology
       
  2689 */
       
  2690 TBool TOpenFontSpec::ApplyRatio(TInt& aValue, TInt aNumerator, TInt aDenominator)
       
  2691 	{
       
  2692 	TInt64 value(aValue);
       
  2693 	value = (value * aNumerator) / aDenominator;
       
  2694 	aValue = I64LOW(value);
       
  2695 	__ASSERT_DEBUG(I64HIGH(value) == 0, Panic(EFntOverFlow));
       
  2696 	return I64HIGH(value) != 0;
       
  2697 	}
       
  2698 
       
  2699 /**
       
  2700 Same as above function but this takes a TInt32 not a TInt
       
  2701 */
       
  2702 TBool TOpenFontSpec::ApplyRatio(TInt32& aValue, TInt aNumerator, TInt aDenominator)
       
  2703 	{
       
  2704 	TInt value = aValue;
       
  2705 	TBool ret = ApplyRatio(value, aNumerator, aDenominator);
       
  2706 	aValue = value;
       
  2707 	return ret;
       
  2708 	}
       
  2709 
       
  2710 EXPORT_C void TOpenFontSpec::SetAttrib(const TOpenFontFaceAttribBase& aAttrib)
       
  2711 /**
       
  2712 Sets the font attributes.
       
  2713 
       
  2714 @param aAttrib The font attributes.
       
  2715 */
       
  2716 	{
       
  2717 	TOpenFontFaceAttribBase* self = this;
       
  2718 	*self = aAttrib;
       
  2719 	}
       
  2720 
       
  2721 /**
       
  2722 Gets the TFontSpec corresponding to this Open Font System font specification.
       
  2723 @publishedAll
       
  2724 @released
       
  2725 @param aFontSpec On return, contains the TFontSpec corresponding to this font 
       
  2726 specification.
       
  2727 */
       
  2728 EXPORT_C void TOpenFontSpec::GetTFontSpec(TFontSpec& aFontSpec) const
       
  2729 	{
       
  2730 	aFontSpec = TFontSpec();
       
  2731 	TPtrC short_name(iName.Ptr(), Min(iName.Length(), KMaxTypefaceNameLength));
       
  2732 	aFontSpec.iTypeface.iName = short_name;
       
  2733 	aFontSpec.iTypeface.SetIsProportional(!IsMonoWidth());
       
  2734 	aFontSpec.iTypeface.SetIsSerif(IsSerif());
       
  2735 	aFontSpec.iTypeface.SetIsSymbol(Symbol());
       
  2736 	aFontSpec.iTypeface.SetScriptTypeForMetrics(ScriptTypeForMetrics());
       
  2737 	aFontSpec.iHeight = iHeight;	// as twips
       
  2738 	if (IsItalic() || (iSlantFactor > 0))
       
  2739 		aFontSpec.iFontStyle.SetPosture(EPostureItalic);
       
  2740 	if (IsBold() || IsEffectOn(FontEffect::EAlgorithmicBold))
       
  2741 		aFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
       
  2742 	aFontSpec.iFontStyle.SetPrintPosition(iPrintPosition);
       
  2743 	aFontSpec.iFontStyle.SetBitmapType(BitmapType());
       
  2744 	aFontSpec.iFontStyle.SetEffects(iEffects);
       
  2745 	}
       
  2746 
       
  2747 /**
       
  2748 Sets a font effect to the given state.
       
  2749 @publishedAll
       
  2750 @released
       
  2751 @param aEffect The font effect to be set.
       
  2752 @param aOn True represents on, otherwise off.
       
  2753 @see TOpenFontSpec::IsEffectOn()
       
  2754 */
       
  2755 EXPORT_C void TOpenFontSpec::SetEffects(FontEffect::TEffect aEffect, TBool aOn)
       
  2756 	{
       
  2757 	FontEffect::SetEffect(aEffect, aOn, iEffects);
       
  2758 	}
       
  2759 
       
  2760 /** Checks if a font effect is on.
       
  2761 @publishedAll
       
  2762 @released
       
  2763 @return True represents the specified font effect is on, otherwise off.
       
  2764 @param aEffect The font effect to be checked.
       
  2765 @see TOpenFontSpec::SetEffects()
       
  2766 */
       
  2767 EXPORT_C TBool TOpenFontSpec::IsEffectOn(FontEffect::TEffect aEffect) const
       
  2768 	{
       
  2769 	return FontEffect::IsEffectOn(aEffect, iEffects);
       
  2770 	}
       
  2771 
       
  2772 /**
       
  2773 @deprecated This needs to be maintained to just call the inline methods.
       
  2774 */
       
  2775 EXPORT_C void TOpenFontSpec::DoSetEffects(TUint32 aEffects)
       
  2776 	{
       
  2777 	SetEffects(aEffects);
       
  2778 	}
       
  2779 
       
  2780 /**
       
  2781 @deprecated This needs to be maintained to just call the inline methods.
       
  2782 */
       
  2783 EXPORT_C TUint32 TOpenFontSpec::DoEffects() const
       
  2784 	{
       
  2785 	return Effects();
       
  2786 	}
       
  2787 
       
  2788 /**
       
  2789 Specifies the script which font metrics calculation will be based on.
       
  2790 @publishedAll
       
  2791 @released
       
  2792 @param aLanguage The language used to derive the required script.
       
  2793 */
       
  2794 EXPORT_C void TOpenFontSpec::SetScriptTypeForMetrics(TLanguage aLanguage)
       
  2795 	{
       
  2796 	SetScriptTypeForMetrics(GlyphSample::TLanguage2TScript(aLanguage));
       
  2797 	}
       
  2798 
       
  2799 /**
       
  2800 @internalTechnology
       
  2801 */
       
  2802 void TOpenFontSpec::SetScriptTypeForMetrics(TInt aScript)
       
  2803 	{
       
  2804 	iSymbol &= ~KTOpenFontSpecMaskScript;
       
  2805 	iSymbol |= (KTOpenFontSpecMaskScript & (aScript << KTOpenFontSpecBitsNumSymbol));
       
  2806 	}
       
  2807 
       
  2808 /**
       
  2809 Gets the script which the font metrics calculation will be based on.
       
  2810 @internalTechnology
       
  2811 @return The script.
       
  2812 */
       
  2813 EXPORT_C TInt TOpenFontSpec::ScriptTypeForMetrics() const
       
  2814 	{
       
  2815 	return (KTOpenFontSpecMaskScript & iSymbol) >> KTOpenFontSpecBitsNumSymbol;
       
  2816 	}
       
  2817 
       
  2818 /**
       
  2819 @internalTechnology
       
  2820 */
       
  2821 void TOpenFontSpec::SetSymbol(TBool aSymbol)
       
  2822 	{
       
  2823 	iSymbol &= ~KTOpenFontSpecMaskSymbol;
       
  2824 	iSymbol |= (aSymbol ? KTOpenFontSpecSymbolFlag : 0);
       
  2825 	}
       
  2826 
       
  2827 /**
       
  2828 @internalTechnology
       
  2829 */
       
  2830 TBool TOpenFontSpec::Symbol() const
       
  2831 	{
       
  2832 	return (KTOpenFontSpecSymbolFlag & iSymbol) > 0;
       
  2833 	}
       
  2834 
       
  2835 /**
       
  2836 @deprecated This needs to be maintained to just call the inline methods.
       
  2837 */
       
  2838 EXPORT_C TBool TOpenFontSpec::OperatorEquality(const TOpenFontSpec& aOpenFontSpec) const
       
  2839 	{
       
  2840 	return this->operator == (aOpenFontSpec);
       
  2841 	}
       
  2842 
       
  2843 /**
       
  2844 @internalTechnology
       
  2845 */
       
  2846 TBool TOpenFontSpec::operator!=(const TOpenFontSpec& aOpenFontSpec) const
       
  2847 	{
       
  2848 	return !(this->operator == (aOpenFontSpec));
       
  2849 	}
       
  2850 
       
  2851 /**
       
  2852 Static constructor for a TOpenFontGlyphData.
       
  2853 
       
  2854 This constructor creates the object on a specified heap. It must be deleted 
       
  2855 using RHeap::Free().
       
  2856 
       
  2857 @param aHeap The shared heap on which the object is constructed.
       
  2858 @param aBufferSize The amount of memory allocated for the glyph data.
       
  2859 @return A pointer to the newly created object.
       
  2860 */
       
  2861 EXPORT_C TOpenFontGlyphData* TOpenFontGlyphData::New(RHeap* aHeap, TInt aBufferSize)
       
  2862 	{
       
  2863 	if (aBufferSize < 1)
       
  2864 		aBufferSize = 1;
       
  2865 	TInt bytes = sizeof(TOpenFontGlyphData) + aBufferSize - 1;
       
  2866 	TOpenFontGlyphData* g = (TOpenFontGlyphData*)aHeap->Alloc(bytes);
       
  2867 	if (g)
       
  2868 		{
       
  2869 		Mem::FillZ(g, bytes);
       
  2870 		g->iBitmapBufferSize = aBufferSize;
       
  2871 		}
       
  2872 	return g;
       
  2873 	}
       
  2874 
       
  2875 // Virtual functions reserved for future expansion.
       
  2876 /**
       
  2877 @publishedPartner
       
  2878 @prototype
       
  2879 */
       
  2880 EXPORT_C void COpenFontRasterizer::ExtendedInterface(TUid, TAny*&)
       
  2881 	{
       
  2882 	}
       
  2883 
       
  2884 /** @internalComponent */
       
  2885 EXPORT_C void COpenFontFile::ExtendedInterface(TUid, TAny*&)
       
  2886 	{
       
  2887 	}
       
  2888 
       
  2889 EXPORT_C void COpenFont::ExtendedInterface(TUid, TAny*&)
       
  2890 	{
       
  2891 	}
       
  2892 	
       
  2893 EXPORT_C CShaper::CShaper()
       
  2894 	{
       
  2895 	
       
  2896 	}
       
  2897 	
       
  2898 EXPORT_C CShaper::~CShaper()
       
  2899 	{
       
  2900 	
       
  2901 	}
       
  2902 /** @internalComponent */
       
  2903 EXPORT_C void* CShaper::ExtendedInterface(TUid)
       
  2904 	{
       
  2905 	return 0;
       
  2906 	}
       
  2907 
       
  2908 /**
       
  2909 Sets the glyph bitmap type.
       
  2910 
       
  2911 Normally the bitmap type belongs to the font, but for linked fonts this can 
       
  2912 be different between different font elements making up the linked font.
       
  2913 
       
  2914 Note: This is only of use in conjunction with rasterizer based linked fonts.
       
  2915 
       
  2916 @publishedPartner
       
  2917 @prototype
       
  2918 */
       
  2919 EXPORT_C void TOpenFontCharMetrics::SetGlyphType(TGlyphBitmapType aGlyphBitmapType)
       
  2920 	{
       
  2921 	iGlyphBitmapType = aGlyphBitmapType;
       
  2922 	}
       
  2923 
       
  2924 /**
       
  2925 Gets the glyph bitmap type.
       
  2926 
       
  2927 @publishedPartner
       
  2928 @prototype
       
  2929 */
       
  2930 EXPORT_C TGlyphBitmapType TOpenFontCharMetrics::GlyphType() const
       
  2931 	{
       
  2932 	if (iGlyphBitmapType == 0)
       
  2933 		return EGlyphBitmapTypeNotDefined;
       
  2934 	else
       
  2935 		return static_cast<TGlyphBitmapType>(iGlyphBitmapType);
       
  2936 	}