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