Update contrib.
2 * Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
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>
31 #include "OstTraceDefinitions.h"
32 #ifdef OST_TRACE_COMPILER_IN_USE
33 #include "OPENFONTTraces.h"
37 const TInt KSessionCacheEntries = 512;
38 const TInt KDefaultSlantFactor = 20480;
39 const TInt KOneIn16Dot16FixedPointFormat = 65536;
42 ROffsetArray<T>::ROffsetArray()
43 : iOffset(0), iCount(0)
47 TInt ROffsetArray<T>::Create(RHeap* aHeap, TInt aCount)
51 return KErrAlreadyExists;
53 TAny* p = aHeap->AllocZ(aCount * sizeof(TInt));
58 iOffset = (TInt)p - (TInt)this;
64 void ROffsetArray<T>::Close(RHeap* aHeap)
68 aHeap->Free(PtrAdd(this, iOffset));
75 TInt ROffsetArray<T>::Count() const
81 T* ROffsetArray<T>::operator[](TInt aIndex) const
83 TInt e = ((TInt*)PtrAdd(this, iOffset))[aIndex];
84 return e != 0 ? (T*)PtrAdd(this, e) : NULL;
88 void ROffsetArray<T>::SetAt(TInt aIndex, T* aEntry)
90 ((TInt*)PtrAdd(this, iOffset))[aIndex] = aEntry ? (TInt)aEntry - (TInt)this : 0;
94 /*COpenFontGlyphCache*/
96 TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams)
98 if (iShaperCacheSentinel == NULL)
100 COpenFontShaperCacheEntry* searchNode = iShaperCacheSentinel->iNext;
102 TInt start = aParams->iStart;
103 TInt end = aParams->iEnd;
104 TInt script = aParams->iScript;
105 const TUint16* text = (TUint16*)aParams->iText->Ptr();
107 const TUint16* copyOfText;
108 TInt noOfChars = end - start;
110 while (searchNode != iShaperCacheSentinel)
112 //Future work: add Script check for further script support
113 //Future work: add Language check for further language support
114 if ((searchNode->iEnd == end) && (searchNode->iStart == start) && (searchNode->iScript == script))
116 // Check for the entire text (within the context) coming in.
118 copyOfText = text + start;
119 cachedText = (TUint16*)searchNode->iText + searchNode->iStart;
121 while (i < noOfChars && textIsSame != 0)
123 if (*cachedText != *copyOfText)
132 if (searchNode == iShaperCacheSentinel->iNext)
134 // now we need to update the reference count here for that session
135 if (searchNode->IncRefCount(aSessionHandle) != KErrNone)
137 return iShaperCacheSentinel->iNext->iShapeHeader;
139 // We have found a node, now put that node to the top of the list as the most recently used node
140 searchNode->iPrevious->iNext = searchNode->iNext;
141 searchNode->iNext->iPrevious = searchNode->iPrevious;
143 searchNode->iNext = iShaperCacheSentinel->iNext;
144 iShaperCacheSentinel->iNext->iPrevious = searchNode;
145 iShaperCacheSentinel->iNext = searchNode;
146 searchNode->iPrevious = iShaperCacheSentinel;
147 if (searchNode->IncRefCount(aSessionHandle)!= KErrNone)
149 return searchNode->iShapeHeader;
152 searchNode = searchNode->iNext;
157 TShapeHeader* COpenFontGlyphCache::Insert(TInt aSessionHandle, RHeap* aHeap, CShaper::TInput aInput, TShapeHeader* aShapeHeader, TInt& aAddedBytes)
159 TInt heapSizeBefAloc = 0;
160 aHeap->AllocSize(heapSizeBefAloc);
162 COpenFontShaperCacheEntry* new_entry;
163 new_entry = COpenFontShaperCacheEntry::New(aHeap, aInput, aShapeHeader);
164 if (new_entry != NULL)
166 // increase the reference count for this
167 TInt ret=new_entry->IncRefCount(aSessionHandle);
171 COpenFontShaperCacheEntry::Delete(aHeap, new_entry);
174 new_entry->iNext = iShaperCacheSentinel->iNext;
175 iShaperCacheSentinel->iNext->iPrevious = new_entry;
176 iShaperCacheSentinel->iNext = new_entry;
177 new_entry->iPrevious = iShaperCacheSentinel;
179 iNumberOfShaperCacheEntries++;
180 TInt heapSizeOnAloc = 0;
181 aHeap->AllocSize(heapSizeOnAloc);
182 aAddedBytes = heapSizeOnAloc - heapSizeBefAloc;
184 // Update the amount of memory used in creation of a new entry
185 iShapingInfoCacheMemory += heapSizeOnAloc - heapSizeBefAloc;
187 return new_entry->iShapeHeader;
193 Searches from the least recently used towards the most recently used
194 and try to free entry that is no longer referenced
196 TInt COpenFontGlyphCache::DeleteLeastRecentlyUsedEntry(RHeap* aHeap)
198 // start from the least recently used
199 COpenFontShaperCacheEntry* deleteNode = iShaperCacheSentinel->iPrevious;
201 // if empty list there is nothing to delete
202 if (deleteNode == iShaperCacheSentinel)
204 // else navigating starting from the LRU entry
205 while (deleteNode != iShaperCacheSentinel)
207 // cannot delete if the iHandleRefCount is greater than zero
208 if (deleteNode->iHandleRefCount>0)
210 deleteNode = deleteNode->iPrevious;
214 // otherwise we can delete the entry
215 deleteNode->iPrevious->iNext = deleteNode->iNext;
216 deleteNode->iNext->iPrevious = deleteNode->iPrevious;
218 TInt heapSizeBeforeDel = 0;
219 TInt heapSizeAfterDel = 0;
220 aHeap->AllocSize(heapSizeBeforeDel);
221 COpenFontShaperCacheEntry::Delete(aHeap, deleteNode);
222 aHeap->AllocSize(heapSizeAfterDel);
223 TInt deletedBytes = heapSizeBeforeDel - heapSizeAfterDel;
225 iNumberOfShaperCacheEntries--;
226 iShapingInfoCacheMemory -= deletedBytes;
230 // we have navigated through the whole list and cannot delete anything
234 TInt COpenFont::DecrementCachedRefCount(TInt aSessionHandle, TShapeHeader* aShapeHeader, TBool aResetAll)
236 COpenFontShaperCacheEntry* ptr=NULL;
237 COpenFontGlyphCache* glyphCache=GetGlyphCache();
238 if (glyphCache != NULL)
239 ptr=glyphCache->iShaperCacheSentinel;
243 TInt ret = KErrNotFound;
244 CFontStore* thisFontStore = File()->GetFontStore();
245 TInt allocBefDec = 0;
246 TInt allocAfterDec = 0;
247 TInt deletedBytes = 0;
249 // loop through the cache entry to decrement the ref count for a particular session
250 while (ptr->iNext != NULL)
254 // we want to reset any cache that has a matching the session handle
255 // i.e. here we dont care about which TShapeHeader and hence we can
256 // ignore the error code here if not found
258 // Always update the memory usage of the cache as decreasing the ref count
260 iHeap->AllocSize(allocBefDec);
262 ptr->DecRefCount(aSessionHandle, ETrue);
264 iHeap->AllocSize(allocAfterDec);
265 deletedBytes = allocBefDec - allocAfterDec;
266 glyphCache->iShapingInfoCacheMemory -= deletedBytes;
267 thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
271 else if (ptr->iShapeHeader != NULL && ptr->iShapeHeader==aShapeHeader)
273 // Always update the memory usage of the cache as decreasing the ref count
275 iHeap->AllocSize(allocBefDec);
277 ptr->DecRefCount(aSessionHandle);
279 iHeap->AllocSize(allocAfterDec);
280 deletedBytes = allocBefDec - allocAfterDec;
281 glyphCache->iShapingInfoCacheMemory -= deletedBytes;
282 thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - deletedBytes);
287 if (ptr == glyphCache->iShaperCacheSentinel)
295 TInt COpenFont::FreeShaperCacheMemory(TInt aBytesNeeded)
297 TInt totalDeletedBytes = 0;
298 TInt tempDeletedBytes = 0;
299 CFontStore* thisFontStore = File()->GetFontStore();
301 if (aBytesNeeded <= KMaxShaperSesssionCacheMemory)
303 // delete LRU entries from all the caches except the one owned by this COpenFont
304 // The 'if' condition here is to avoid looping through every font in the system
305 // if only one of the them has a non-empty cache. In situations where only one
306 // cache is left and it is full, this strategy makes freeing the memory faster.
307 if (thisFontStore->GetNumShaperCaches() > 1)
309 CArrayPtrFlat<COpenFont>* fontList;
310 CArrayPtrFlat<COpenFontFile>* fontFileList = thisFontStore->GetOpenFontFileList();
311 TInt numberOfFontFiles = fontFileList->Count();
313 while ((totalDeletedBytes < aBytesNeeded) && (i < numberOfFontFiles))
315 fontList = (*fontFileList)[i]->GetOpenFontList();
316 TInt fontListCount=fontList->Count();
318 while ((totalDeletedBytes < aBytesNeeded) && (j < fontListCount))
320 COpenFont* open_font = (*fontList)[j];
321 COpenFontGlyphCache* glyphCache = open_font->GetGlyphCache();
322 if ((open_font != this) && (glyphCache != NULL))
324 while ((totalDeletedBytes < aBytesNeeded) && (!glyphCache->ShaperCacheIsEmpty()))
326 totalDeletedBytes += glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
327 if (glyphCache->ShaperCacheIsEmpty())
329 thisFontStore->DecNumShaperCaches();
332 // If totalDeletedBytes is zero mean we cannot delete from this font
333 if (totalDeletedBytes == 0)
345 // If deleted bytes are still less than the required one delete from this font
346 COpenFontGlyphCache* glyphCache = GetGlyphCache();
347 if (glyphCache != NULL)
349 while (totalDeletedBytes < aBytesNeeded && !glyphCache->ShaperCacheIsEmpty())
351 tempDeletedBytes = glyphCache->DeleteLeastRecentlyUsedEntry(iHeap);
352 if (tempDeletedBytes == 0)
354 totalDeletedBytes += tempDeletedBytes;
357 } //if(aBytesNeeded <= KMaxShaperSesssionCacheMemory)
359 // Update the global CFontStore cache memory count
360 if (totalDeletedBytes > 0)
362 thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() - totalDeletedBytes);
365 return totalDeletedBytes;
368 TShapeHeader* COpenFont::InsertShapedDataIntoCache(TInt aSessionHandle,TFontShapeFunctionParameters* aParams, TShapeHeader* aShapeHeader)
370 CShaper::TInput input;
371 input.iEnd = aParams->iEnd;
372 input.iStart = aParams->iStart;
373 input.iScript = aParams->iScript;
374 input.iLanguage = aParams->iLanguage;
375 input.iText = aParams->iText;
376 input.iMaximumAdvance = KMaxTInt;
378 input.iSessionHandle = aSessionHandle;
379 input.iReserved1 = 0;
381 CFontStore* thisFontStore = File()->GetFontStore();
383 // Create the glyph cache if it doesn't already exist.
384 // This call can only come from FBSERV
385 COpenFontGlyphCache* glyphCache = GetGlyphCache();
386 if (glyphCache == NULL)
388 glyphCache = (COpenFontGlyphCache*) iHeap->Alloc(sizeof(COpenFontGlyphCache));
389 if (glyphCache == NULL) // no memory
393 new (glyphCache) COpenFontGlyphCache(iHeap);
394 SetGlyphCache(glyphCache);
396 // If there is no sentinel present, i.e. new cache
397 if (glyphCache->iShaperCacheSentinel == NULL)
400 glyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap);
401 if (glyphCache->iShaperCacheSentinel == NULL)
406 glyphCache->iShaperCacheSentinel->iNext = glyphCache->iShaperCacheSentinel;
407 glyphCache->iShaperCacheSentinel->iPrevious = glyphCache->iShaperCacheSentinel;
408 glyphCache->iNumberOfShaperCacheEntries = 1;
411 // Before inserting into this cache, check if it was empty.
412 // If empty, then increment the global cache count signifying one more cache is active
413 if (glyphCache->ShaperCacheIsEmpty())
415 thisFontStore->IncNumShaperCaches();
419 TShapeHeader* cached_header = NULL;
421 // Insert a new entry and return the newly inserted TShapeHeader entry
422 cached_header = glyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes);
423 if (cached_header == NULL)
426 // If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then
427 // free some memory by releasing the same amount of memory that was just added
428 if (thisFontStore->GetShaperCacheMemUsage() + addedBytes > KMaxShaperSesssionCacheMemory)
430 FreeShaperCacheMemory(addedBytes);
433 // Now update the memory count with the added memory for the new entry
434 thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
435 return cached_header;
438 TShapeHeader* COpenFont::GetShapedData(TInt aSessionHandle, TFontShapeFunctionParameters* aParams)
440 COpenFontGlyphCache* glyphCache = GetGlyphCache();
441 if (glyphCache == NULL)
444 TShapeHeader* cachedHeader = NULL;
445 CFontStore* thisFontStore = File()->GetFontStore();
447 // Always update the memory usage of the cache as increasing the reference count of a found header uses up memory
448 TInt allocBefInc = 0;
449 TInt allocAfterInc = 0;
450 iHeap->AllocSize(allocBefInc);
452 cachedHeader = glyphCache->SearchShaperCache(aSessionHandle,aParams);
454 iHeap->AllocSize(allocAfterInc);
455 TInt addedBytes = allocAfterInc - allocBefInc;
456 glyphCache->iShapingInfoCacheMemory += addedBytes;
457 thisFontStore->SetShaperCacheMemUsage(thisFontStore->GetShaperCacheMemUsage() + addedBytes);
462 TBool COpenFontGlyphCache::ShaperCacheIsEmpty()
464 if (iShaperCacheSentinel == NULL)
467 if (iShaperCacheSentinel->iNext == iShaperCacheSentinel)
474 C++ constructor taking shared heap, session cache list and font file as parameters.
476 You must either use this, or the other constructor, when creating your derived
477 object. This constructor might be used, in preference to the other, if there
478 is only a single typeface in the font file.
480 @param aHeap The shared heap.
481 @param aSessionCacheList The session cache list.
482 @param aFile A pointer to the COpenFontFile object creating this COpenFont.
483 e.g. when creating a COpenFont the COpenFontFile derived object would pass
486 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList,
487 COpenFontFile* aFile):
493 SetSessionCacheList(aSessionCacheList);
497 C++ constructor taking shared heap, session cache list, font file and face
500 You must either use this, or the other constructor, when creating your derived
501 object. This constructor would be used if the font file contains more than
504 @param aHeap The shared heap.
505 @param aSessionCacheList The session cache list.
506 @param aFile A pointer to the COpenFontFile object creating this COpenFont.
507 e.g. when creating a COpenFont the COpenFontFile derived object would pass
509 @param aFaceIndex The index of the typeface within the font file aFile.
511 EXPORT_C COpenFont::COpenFont(RHeap* aHeap,COpenFontSessionCacheList* aSessionCacheList, COpenFontFile* aFile,TInt aFaceIndex) :
514 iFaceIndex(aFaceIndex)
517 SetSessionCacheList(aSessionCacheList);
523 This function frees all memory owned by the object, including the session
524 cache list and the glyph list, prior to its destruction.
526 EXPORT_C COpenFont::~COpenFont()
531 File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this);
533 COpenFontGlyphCache* glyphCache = GetGlyphCache();
534 if (glyphCache != NULL)
536 glyphCache->iGlyphTreeById.ResetAndDestroy();
537 glyphCache->iGlyphTreeByUnicode.ResetAndDestroy();
539 // Delete the shaper cache as well
540 if (glyphCache->iShaperCacheSentinel)
542 COpenFontShaperCacheEntry* previous = NULL;
543 COpenFontShaperCacheEntry* si = glyphCache->iShaperCacheSentinel->iPrevious;
546 iHeap->AllocSize(heapBefore);
547 while (glyphCache->iNumberOfShaperCacheEntries > 0)
549 previous = si->iPrevious;
550 COpenFontShaperCacheEntry::Delete(iHeap, si);
552 glyphCache->iNumberOfShaperCacheEntries--;
554 iHeap->AllocSize(heapAfter);
555 File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter));
556 File()->GetFontStore()->DecNumShaperCaches();
559 iHeap->Free(glyphCache);
561 COpenFontSessionCacheList* sessionCacheList = SessionCacheList();
562 if (sessionCacheList != NULL)
564 sessionCacheList->DeleteFontGlyphs(iHeap, this);
566 COpenFontFile* file = File();
569 file->RemoveFontFromList(this);
573 EXPORT_C void COpenFont::operator delete(TAny *aFont)
577 COpenFont* f = (COpenFont*)aFont;
579 f->iHeap->Free(aFont);
586 This function may only be called via an FBSERV message.
588 @param aSessionHandle Session handle of the calling session
589 @param aCode Unicode value or glyph code if top bit is set
591 Output data. May be null, in which case output may be
592 obtained through a call to GetCharacterData.
595 ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap()
596 and aGlyphData->Metrics() are valid), EFalse otherwise.
598 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode,
599 TOpenFontGlyphData* aGlyphData)
601 // create the cache if it doesn't exisit. As this call can only come from
602 // FBSERV if the chunk has to be resized then no panic will happen.
603 COpenFontGlyphCache* glyphCache = GetGlyphCache();
604 if (glyphCache == NULL)
606 glyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache));
607 if (glyphCache == NULL) // no memory
611 new(glyphCache) COpenFontGlyphCache(iHeap);
612 SetGlyphCache(glyphCache);
615 // Look in the Font Cache
616 const COpenFontGlyph* g = FontCacheGlyph(aCode);
618 // If it has already been rasterized return it.
621 if (aGlyphData != NULL)
623 aGlyphData->SetMetricsPointer(&g->iMetrics);
624 aGlyphData->SetBitmapPointer(g->Bitmap());
630 // Rasterize the glyph.
631 TOpenFontGlyphData* temp_glyph_data = NULL;
632 TInt error = KErrNone;
633 TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data));
634 if (error != KErrNone)
636 iHeap->Free(temp_glyph_data);
640 TBool glyph_data_valid = ETrue;
641 const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData;
642 COpenFontGlyph* new_glyph = NULL;
644 // If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache.
645 TInt bytes = sizeof(COpenFontGlyph) + cur_glyph_data->BytesNeeded();
646 if(glyphCache != NULL && bytes + glyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory)
648 new_glyph = COpenFontGlyph::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
649 if (new_glyph != NULL)
651 if ((aCode & 0x80000000) != 0)
653 error = glyphCache->iGlyphTreeById.SetAt(aCode & 0x7FFFFFFF, new_glyph);
657 error = glyphCache->iGlyphTreeByUnicode.SetAt(aCode, new_glyph);
659 if (error == KErrNone)
661 glyphCache->iGlyphCacheMemory += bytes;
665 iHeap->Free(new_glyph);
670 // Otherwise put the glyph into the per-session cache.
673 // Look in the session cache. Do not expect to find the glyph here
674 // since the session cache has already been searched client-side.
675 // However, SessionCacheGlyph() is called so that the session cache is
676 // created if needed and an index is found where the new glyph will be
677 // placed when added to the session cache.
678 COpenFontSessionCache* cache = NULL;
680 (void)SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, ETrue);
683 iHeap->Free(temp_glyph_data);
687 COpenFontSessionCacheEntry* new_entry =
688 COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap());
689 new_glyph = new_entry;
690 if (new_entry != NULL)
692 cache->Insert(iHeap, new_entry, index);
696 if (temp_glyph_data != NULL)
698 iHeap->Free(temp_glyph_data);
701 // Fix up the returned glyph data pointers to point to the actual data.
702 if (new_glyph == NULL)
703 glyph_data_valid = EFalse;
704 else if (aGlyphData != NULL)
706 aGlyphData->SetMetricsPointer(&new_glyph->iMetrics);
707 aGlyphData->SetBitmapPointer(new_glyph->Bitmap());
710 return glyph_data_valid;
713 void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData)
716 MOpenFontShapingExtension* extensionInterface = 0;
718 // if the MSB is set this is a request to rasterize a glyph code
719 // rather than a unicode value. This can only be done if the rasterizer
720 // supports the extended API.
721 if ( aCode & 0x80000000 )
723 aCode = GLYPH_CODE(aCode);
724 // get the extension API for RasterizeGlyphL() if available
726 ExtendedInterface(KUidOpenFontShapingExtension, ext);
727 extensionInterface = reinterpret_cast<MOpenFontShapingExtension*>(ext);
729 if (extensionInterface == NULL)
730 // an attempt to rasterize a glyph when the rasterizer does not
731 // support it; best to do nothing
734 TOpenFontGlyphData* currGlyphData = aGlyphData;
736 if (currGlyphData == NULL)
738 aTempGlyphData = TOpenFontGlyphData::New(iHeap, 0);
740 User::Leave(KErrNoMemory);
741 currGlyphData = aTempGlyphData;
744 if (extensionInterface != NULL)
745 extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
747 RasterizeL(aCode, currGlyphData);
749 // If the GlyphData object was not large enough, create a temporary one
750 // that can then be deleted by the caller.
751 if (currGlyphData->Overflow())
753 TInt bytesNeeded = currGlyphData->BytesNeeded();
755 iHeap->Free(aTempGlyphData);
756 aTempGlyphData = TOpenFontGlyphData::New(iHeap, bytesNeeded);
757 if (aTempGlyphData == NULL)
758 User::Leave(KErrNoMemory);
760 currGlyphData = aTempGlyphData;
762 // If the extension interface was used above, then use again here
763 if (extensionInterface != NULL)
764 extensionInterface->RasterizeGlyphL(aCode, currGlyphData);
766 RasterizeL(aCode, currGlyphData);
769 if (currGlyphData->Metrics() == NULL)
771 User::Leave(KErrArgument);
775 /** @internalComponent */
776 void COpenFont::SetShaper(CShaper* aShaper)
781 /** @internalComponent */
782 CShaper* COpenFont::GetShaper()
787 /** @internalComponent */
788 TBool COpenFont::HasShaper() const
790 return iShaper != NULL;
793 void COpenFont::DeleteShaper() const
798 TInt COpenFont::GetFontTable(TUint32 aTag, TAny*& aTableContent, TInt& aLength)
800 // get the extension API for GetTrueTypeTable() if available
802 ExtendedInterface(KUidOpenFontTrueTypeExtension, ext);
803 MOpenFontTrueTypeExtension* extensionInterface =
804 reinterpret_cast<MOpenFontTrueTypeExtension*>(ext);
807 if (extensionInterface == NULL)
809 ret = KErrNotSupported;
815 aTableContent = extensionInterface->GetTrueTypeTable(ret, tag, &len);
824 TInt COpenFont::GetGlyphOutline(TUint aCode,
825 TBool aHinted, TAny*& aOutline, TInt &aLength)
827 // get the extension API for GetTrueTypeTable() if available
829 ExtendedInterface(KUidOpenFontGlyphOutlineExtension, ext);
830 MOpenFontGlyphOutlineExtension *extensionInterface =
831 reinterpret_cast<MOpenFontGlyphOutlineExtension*>(ext);
834 if (extensionInterface == NULL)
836 ret = KErrNotSupported;
840 ret = extensionInterface->GetGlyphOutline(aCode, ETrue,
841 aHinted, aOutline, aLength);
848 A constructor initialised with a TCharacterMetrics object.
850 This is the old-style character metrics object. As for other T classes, there
851 is no need to explicitly cleanup TOpenFontCharMetrics objects.
853 @param aMetrics The old-style metrics object.
855 EXPORT_C TOpenFontCharMetrics::TOpenFontCharMetrics(const TCharacterMetrics& aMetrics)
857 iWidth = (TInt16)(aMetrics.iMoveInPixels - aMetrics.iLeftAdjustInPixels - aMetrics.iRightAdjustInPixels);
858 iHeight = aMetrics.iHeightInPixels;
859 iHorizBearingX = aMetrics.iLeftAdjustInPixels;
860 iHorizBearingY = aMetrics.iAscentInPixels;
861 iHorizAdvance = aMetrics.iMoveInPixels;
864 iVertAdvance = aMetrics.iHeightInPixels;
865 iGlyphBitmapType = 0;
869 Converts a TOpenFontCharacterMetrics object to a TCharacterMetrics.
871 @param aMetrics On return, contains the character's old-style metrics.
872 @return ETrue if it was possible to get the metrics, otherwise EFalse.
874 EXPORT_C TBool TOpenFontCharMetrics::GetTCharacterMetrics(TCharacterMetrics& aMetrics) const
876 aMetrics.iAscentInPixels = iHorizBearingY;
877 aMetrics.iHeightInPixels = iHeight;
878 aMetrics.iLeftAdjustInPixels = iHorizBearingX;
879 aMetrics.iMoveInPixels = iHorizAdvance;
880 aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth);
884 TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const
886 const COpenFontGlyph* g = Glyph(aSessionHandle, aCode);
889 aMetrics = &g->iMetrics;
890 aBitmap = g->Bitmap();
903 void COpenFont::OnFileDeleted()
908 COpenFontGlyphCache* COpenFont::GetGlyphCache() const
910 if (iGlyphCacheOffset == 0)
914 return reinterpret_cast<COpenFontGlyphCache*>(PtrAdd(const_cast<COpenFont*>(this), iGlyphCacheOffset));
917 const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const
919 const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode);
922 COpenFontSessionCache* cache;
924 glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse);
931 Is the specified character present in the font?
933 TBool COpenFont::HasCharacterL(TInt aCode) const
935 COpenFontFile* file = File();
937 return file->HasUnicodeCharacterL(iFaceIndex, aCode);
943 Retrieve glyph data from the per-font glyph cache.
944 If it is not found return NULL.
945 If the cache hasn't been created, then return NULL.
946 Previous versions of this function created the cache, but as this function can potentially
947 run in the context of threads other than FBSERV the alloc could panic if iHeap's chunk had to
948 be resized - this is not allowed by the kernel.
949 The cache is now created in COpenFont::Rasterize which can only be called within the context of FBSERV
950 @param aCode The code for the glpyh to look for in the cache
951 @return A pointer to the requested glyph if it was found in the glyph cache, NULL if it was not found.
953 const COpenFontGlyph* COpenFont::FontCacheGlyph(TInt aCode) const
955 if (COpenFontGlyphCache* glyphCache = GetGlyphCache())
957 if ((aCode & 0x80000000) != 0)
959 return glyphCache->iGlyphTreeById.At(aCode & 0x7FFFFFFF);
963 return glyphCache->iGlyphTreeByUnicode.At(aCode);
971 /** Retrieve glyph data from the session cache. If the glyph is not in the
972 cache, return the cache and glyph index where the glyph data should be put. If
973 there is no session cache, optionally create it.
976 The heap on which to create the new cache, if appropriate. Not used if
977 either the appropriate session cache already exists, or if aCreate is
979 @param aSessionHandle The session handle
981 The code of the glyph to look up (Unicode or glyph code if the top bit is
984 Returns the appropriate session cache, or NULL if an attempt to create it
987 Returns where the glyph is, or should be put
989 If False, creation of a new cache is inhibited
990 @return The glyph data, or null if the glyph is not in the cache
993 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap,
994 TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache,
995 TInt& aIndex, TBool aCreate) const
998 COpenFontSessionCacheList* cacheList = SessionCacheList();
999 aCache = cacheList->FindCache(aSessionHandle);
1002 return aCache->Glyph(this, aCode, aIndex);
1007 COpenFontSessionCache* new_cache = NULL;
1008 TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries));
1010 if ((!error) && new_cache != NULL)
1012 if (cacheList->AddCache(new_cache) != KErrNone)
1014 new_cache->Delete(aHeap);
1015 aHeap->Free(new_cache);
1020 aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries;
1026 COpenFontSessionCacheList* COpenFont::SessionCacheList()const
1028 if (iSessionCacheListOffset == 0)
1032 return reinterpret_cast<COpenFontSessionCacheList*>(reinterpret_cast<TInt>(this) + iSessionCacheListOffset);
1035 void COpenFont::SetSessionCacheList(COpenFontSessionCacheList* aSessionCacheList)
1037 iSessionCacheListOffset = aSessionCacheList ? reinterpret_cast<TInt>(aSessionCacheList) - reinterpret_cast<TInt>(this) : NULL;
1040 void COpenFont::SetFile(COpenFontFile* aFile)
1042 iFileOffset = aFile ? reinterpret_cast<TInt>(aFile) - reinterpret_cast<TInt>(this) : NULL;
1045 void COpenFont::SetGlyphCache(COpenFontGlyphCache* aGlyphCache)
1047 iGlyphCacheOffset = aGlyphCache ? reinterpret_cast<TInt>(aGlyphCache) - reinterpret_cast<TInt>(this) : NULL;
1052 Create a glyph data object on the shared heap, given the code, metrics and the data bytes.
1053 The data is copied; ownership remains with the caller.
1055 COpenFontGlyph* COpenFontGlyph::New(RHeap* aHeap, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
1057 COpenFontGlyph* glyph = (COpenFontGlyph*)aHeap->Alloc(sizeof(COpenFontGlyph) + aBitmap.Size());
1062 new(glyph) COpenFontGlyph(aCode, aGlyphIndex, aMetrics);
1063 glyph->SetBitmap(glyph + 1);
1064 Mem::Copy(glyph + 1, aBitmap.Ptr(), aBitmap.Size());
1068 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap)
1070 COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry) + aBitmap.Size());
1075 new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics);
1076 entry->SetBitmap(entry + 1);
1077 Mem::Copy(entry + 1, aBitmap.Ptr(), aBitmap.Size());
1081 void COpenFontGlyph::SetBitmap(const TAny* aBitmap)
1083 iBitmapOffset = reinterpret_cast<TInt>(aBitmap) - reinterpret_cast<TInt>(this);
1086 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries)
1088 COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache));
1089 new(c) COpenFontSessionCache(aSessionHandle);
1090 if (c->iEntryArray.Create(aHeap, aEntries) != KErrNone)
1093 User::Leave(KErrNoMemory);
1099 void COpenFontSessionCache::Delete(RHeap* aHeap)
1101 TInt numEntries = iEntryArray.Count();
1102 for (TInt i = 0; i < numEntries; ++i)
1104 COpenFontSessionCacheEntry* entry = iEntryArray[i];
1107 COpenFont* font=const_cast<COpenFont*>(entry->Font());
1109 font->DecrementCachedRefCount(iSessionHandle,NULL,ETrue);
1110 COpenFontSessionCacheEntry::Delete(aHeap, entry);
1113 iEntryArray.Close(aHeap);
1116 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex) const
1119 TInt numEntries = iEntryArray.Count();
1120 TInt index = GLYPH_CODE(aCode) % numEntries; // simple hash function to shorten searches
1121 for (TInt i = 0; i < numEntries; ++i, ++index)
1123 if (index >= numEntries)
1127 const COpenFontSessionCacheEntry* entry = iEntryArray[index];
1135 else if (entry->Font() == aFont && entry->iCode == aCode)
1144 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex)
1146 if (aIndex >= iEntryArray.Count())
1148 Panic(EFntSessionCacheIndexOutOfRange);
1152 aIndex = Math::Rand(iRandomSeed) % iEntryArray.Count();
1154 COpenFontSessionCacheEntry::Delete(aHeap, iEntryArray[aIndex]);
1155 iEntryArray.SetAt(aIndex, aEntry);
1158 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle):
1159 iSessionHandle(aSessionHandle),
1164 TInt COpenFontSessionCacheList::AddCache(COpenFontSessionCache* aCache)
1166 for (TInt index = 0; index < EMaxNumCaches; ++index)
1168 if (iSessionHandleArray[index] == 0)
1170 iSessionHandleArray[index] = aCache->SessionHandle();
1171 iCacheOffsetArray[index] = reinterpret_cast<TInt>(aCache) - reinterpret_cast<TInt>(this);
1175 return KErrNoMemory;
1178 COpenFontSessionCache* COpenFontSessionCacheList::FindCache(TInt aSessionHandle) const
1180 if (aSessionHandle == 0)
1184 for (TInt index = 0; index < EMaxNumCaches; ++index)
1186 if (iSessionHandleArray[index] == aSessionHandle)
1188 return reinterpret_cast<COpenFontSessionCache*>(reinterpret_cast<TInt>(this) + iCacheOffsetArray[index]);
1194 /** Delete all the items in the session cache if the current cache session handle
1195 matches the passed session handle.
1197 @param aHeap The heap base of the current process.
1198 @param aSessionHandle The session handle of the cache to be deleted.
1200 void COpenFontSessionCacheList::DeleteCache(RHeap* aHeap, TInt aSessionHandle)
1202 if (aSessionHandle == 0)
1206 for (TInt index = 0; index < EMaxNumCaches; ++index)
1208 if (iSessionHandleArray[index] == aSessionHandle)
1210 COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
1211 cache->Delete(aHeap);
1213 iSessionHandleArray[index] = 0;
1214 iCacheOffsetArray[index] = 0;
1220 /** Delete all the items in the current session cache.
1222 @param aHeap The heap base of the current process.
1224 void COpenFontSessionCacheList::Delete(RHeap* aHeap)
1226 for (TInt index = 0; index < EMaxNumCaches; ++index)
1228 if (iCacheOffsetArray[index] != 0)
1230 COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
1231 cache->Delete(aHeap);
1235 Mem::FillZ(this, sizeof(COpenFontSessionCacheList));
1239 Delete all glyphs belonging to a particular font.
1241 void COpenFontSessionCacheList::DeleteFontGlyphs(RHeap* aHeap, const COpenFont* aFont)
1243 for (TInt index = 0; index < EMaxNumCaches; ++index)
1245 if (iCacheOffsetArray[index] != 0)
1247 COpenFontSessionCache* cache = reinterpret_cast<COpenFontSessionCache*>(PtrAdd(this, iCacheOffsetArray[index]));
1248 TInt numEntries = cache->iEntryArray.Count();
1249 for (TInt i = 0; i < numEntries; ++i)
1251 COpenFontSessionCacheEntry* entry = cache->iEntryArray[i];
1252 if (entry != NULL && entry->Font() == aFont)
1254 COpenFontSessionCacheEntry::Delete(aHeap, entry);
1255 cache->iEntryArray.SetAt(i, NULL);
1263 C++ constructor with a CFont parameter.
1265 This creates a TOpenFontMetrics and initialises it with size, ascent, maximum
1266 height, descent, maximum depth and maximum character width information from
1267 the CFont that was passed as a parameter.
1269 @param aFont The font from which to initialise the metrics object.
1271 EXPORT_C TOpenFontMetrics::TOpenFontMetrics(const CFont* aFont)
1273 iDesignHeight = (TInt16) aFont->HeightInPixels();
1274 iAscent = iMaxHeight = (TInt16) aFont->AscentInPixels();
1275 iDescent = iMaxDepth = (TInt16)(iDesignHeight - iAscent);
1276 iMaxWidth = (TInt16)aFont->MaxCharWidthInPixels();
1277 iBaselineCorrection = 0;
1284 @param aBaselineCorrection The baseline correction to be associated with this font
1286 Sets the baseline correction applied to this font; this value is used to offset
1287 the underlinke and strikethrough positions and is used by linked fonts only.
1289 const TUint16 KBitsForUnderline = 10;
1290 const TUint16 KMaskUnderline = (1<<KBitsForUnderline)-1; //bottom bits which are set
1291 const TUint16 KMaskBitmapType = ~KMaskUnderline; //top bits which are set
1292 const TUint16 KSignBit = 1<<(KBitsForUnderline-1); //sign bit for the lower number, which can be signed
1293 const TUint32 KTop16Of32Bits = 0xffff0000;
1295 EXPORT_C void TOpenFontMetrics::SetBaselineCorrection(TInt aBaselineCorrection)
1297 if (aBaselineCorrection >= (1<<(KBitsForUnderline-1)))
1299 OstTrace1( TRACE_FATAL, TOPENFONTMETRICS_SETBASELINECORRECTION, "aBaselineCorrection=%d, Panic(EFntOverFlow)", aBaselineCorrection );
1300 __ASSERT_DEBUG(0, Panic(EFntOverFlow));
1302 if (aBaselineCorrection <= (0-(1<<(KBitsForUnderline-1))))
1304 OstTrace1( TRACE_FATAL, DUP1_TOPENFONTMETRICS_SETBASELINECORRECTION, "aBaselineCorrection=%d, Panic(EFntOverFlow)", aBaselineCorrection );
1305 __ASSERT_DEBUG(0, Panic(EFntOverFlow));
1308 TUint16 value = iBaselineCorrection;
1309 value &=~KMaskUnderline; //zero all the underline position bits
1310 if (aBaselineCorrection<0)
1312 //need to mask out extra sign bits for negative value
1313 iBaselineCorrection = value | (static_cast<TUint16>(aBaselineCorrection)&~KMaskBitmapType);
1317 iBaselineCorrection = value | static_cast<TUint16>(aBaselineCorrection);
1325 Gets the baseline correction applied to this font; this value is used to offset
1326 the underlinke and strikethrough positions and is used by linked fonts only.
1328 @return The baseline correction associated with this font
1331 EXPORT_C TInt TOpenFontMetrics::BaselineCorrection()
1333 TUint16 value = iBaselineCorrection; //read once for improved multi threading
1334 if (!(value & KSignBit))
1336 //value is positive, no need to sign extend
1337 return value & KMaskUnderline;
1341 //value is negative, need to stuff ones into the high bits
1342 //could shift up and shift down
1343 return static_cast<TInt>(static_cast<TUint>(value) | KMaskBitmapType | KTop16Of32Bits);
1348 C++ constructor with UID and filename.
1350 Call this constructor in the constructor for your derived object, passing
1351 it aUid and aFileName arguments.
1353 Non Symbian-platform-native font files are allocated IDs by the font store.
1354 These are passed in by the rasteriser class. UIDs are required by the
1355 font framework. However you should not use the ID to access the file, since
1356 a new UID will need to be allocated when the file is next loaded, e.g. after
1357 a device reboot. Instead use the font file name.
1359 @param aUid The UID of the font file.
1360 @param aFileName The full filename, including the path, of the font file.
1362 EXPORT_C COpenFontFile::COpenFontFile(TInt aUid, const TDesC& aFileName)
1364 iUid(TUid::Uid(aUid)),
1365 iFileName(aFileName),
1373 It is not allowed that file is deleted before its fonts
1374 and the logic is handled in CFontStore::RemoveFile().
1376 EXPORT_C COpenFontFile::~COpenFontFile()
1378 CFontStore *fs = GetFontStore();
1381 fs->CleanupCacheOnOpenFontFileRemoval(this);
1387 Gets the nearest font in pixels.
1389 Implementations of this pure virtual function should create the COpenFont
1390 derived object that most closely matches aFontSpec, and place a pointer to
1391 it in aFont. If this cannot be done, e.g. if the font name doesn't match,
1392 aFont should be set to NULL.
1394 The other two arguments, aHeap and aSessionCacheList, should be passed to
1395 the COpenFont constructor.
1397 Implementations may use the utilitity function GetNearestFontHelper() to get
1398 the attributes of the closest matching font.
1400 @param aHeap Shared heap. This value should be passed to the COpenFont derived
1401 classes' constructor.
1402 @param aSessionCacheList The session cache list. This value should be passed
1403 to the COpenFont derived classes' constructor.
1404 @param aDesiredFontSpec The desired font specification.
1405 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating
1406 the algorithmic slant of the typeface.
1407 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating
1408 the algorithmic slant of the typeface.
1409 @param aFont On return, contains a pointer to the newly created COpenFont
1410 derived object, or NULL if no font matching aDesiredFontSpec exists.
1411 @param aActualFontSpec The actual font specification of the font retrieved
1413 @see GetNearestFontHelper()
1414 @deprecated Use GetNearestFontToDesignHeightInPixels
1416 TInt COpenFontFile::GetNearestFontInPixels(
1418 COpenFontSessionCacheList* aSessionCacheList,
1419 const TOpenFontSpec& aDesiredFontSpec,
1423 TOpenFontSpec& aActualFontSpec)
1425 return GetNearestFontToDesignHeightInPixels(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec);
1429 Gets the nearest font in pixels.
1431 Implementations of this pure virtual function should create the COpenFont
1432 derived object that most closely matches aFontSpec, and place a pointer to
1433 it in aFont. If this cannot be done, e.g. if the font name doesn't match,
1434 aFont should be set to NULL.
1436 The other two arguments, aHeap and aSessionCacheList, should be passed to
1437 the COpenFont constructor.
1439 Implementations may use the utilitity function GetNearestFontHelper() to get
1440 the attributes of the closest matching font.
1442 @param aHeap Shared heap. This value should be passed to the COpenFont derived
1443 classes' constructor.
1444 @param aSessionCacheList The session cache list. This value should be passed
1445 to the COpenFont derived classes' constructor.
1446 @param aDesiredFontSpec The desired font specification.
1447 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating
1448 the algorithmic slant of the typeface.
1449 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating
1450 the algorithmic slant of the typeface.
1451 @param aFont On return, contains a pointer to the newly created COpenFont
1452 derived object, or NULL if no font matching aDesiredFontSpec exists.
1453 @param aActualFontSpec The actual font specification of the font retrieved
1455 @see GetNearestFontHelper()
1457 TInt COpenFontFile::GetNearestFontToDesignHeightInPixels(
1459 COpenFontSessionCacheList* aSessionCacheList,
1460 const TOpenFontSpec& aDesiredFontSpec,
1464 TOpenFontSpec& aActualFontSpec)
1467 TRAPD(error, GetNearestFontToDesignHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec));
1472 void COpenFontFile::GetNearestFontToDesignHeightInPixelsAndAddToListL(
1474 COpenFontSessionCacheList* aSessionCacheList,
1475 const TOpenFontSpec& aDesiredFontSpec,
1479 TOpenFontSpec& aActualFontSpec)
1481 COpenFont* fontPtr = NULL;
1482 GetNearestFontToDesignHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec);
1483 if (fontPtr != NULL)
1484 { // found a matching font
1485 CleanupStack::PushL(fontPtr);
1486 iFontList.AppendL(fontPtr);
1487 // transfer ownership
1489 CleanupStack::Pop(fontPtr);
1495 Gets the nearest font in pixels that fits inside specified max height.
1497 Implementations of this pure virtual function should create the COpenFont
1498 derived object that most closely matches aFontSpec, while fitting within
1499 aMaxHeight, and place a pointer to it in aFont. If this cannot be done,
1500 e.g. if the font name doesn't match, aFont should be set to NULL.
1502 The other two arguments, aHeap and aSessionCacheList, should be passed to
1503 the COpenFont constructor.
1505 Implementations may use the utilitity function GetNearestFontHelper()
1506 to get the attributes of the closest matching font.
1508 @param aHeap Shared heap. This value should be passed to the COpenFont derived
1509 classes' constructor.
1510 @param aSessionCacheList The session cache list. This value should be passed
1511 to the COpenFont derived classes' constructor.
1512 @param aDesiredFontSpec The desired font specification.
1513 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating
1514 the algorithmic slant of the typeface.
1515 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating
1516 the algorithmic slant of the typeface.
1517 @param aFont On return, contains a pointer to the newly created COpenFont
1518 derived object, or NULL if no font matching aDesiredFontSpec exists.
1519 @param aActualFontSpec The actual font specification of the font retrieved
1521 @param aMaxHeight The maximum height within which the font must fit.
1522 @see GetNearestFontHelper()
1524 TInt COpenFontFile::GetNearestFontToMaxHeightInPixels(
1526 COpenFontSessionCacheList* aSessionCacheList,
1527 const TOpenFontSpec& aDesiredFontSpec,
1531 TOpenFontSpec& aActualFontSpec,
1535 TRAPD(error, GetNearestFontToMaxHeightInPixelsAndAddToListL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, aFont, aActualFontSpec, aMaxHeight));
1540 void COpenFontFile::GetNearestFontToMaxHeightInPixelsAndAddToListL(
1542 COpenFontSessionCacheList* aSessionCacheList,
1543 const TOpenFontSpec& aDesiredFontSpec,
1547 TOpenFontSpec& aActualFontSpec,
1550 COpenFont* fontPtr = NULL;
1551 GetNearestFontToMaxHeightInPixelsL(aHeap, aSessionCacheList, aDesiredFontSpec, aPixelWidth, aPixelHeight, fontPtr, aActualFontSpec, aMaxHeight);
1552 if (fontPtr != NULL)
1553 { // found a matching font
1554 CleanupStack::PushL(fontPtr);
1555 iFontList.AppendL(fontPtr);
1556 // transfer ownership
1558 CleanupStack::Pop(fontPtr);
1564 Gets the nearest font helper function.
1566 This function may be used by derived classes in their GetNearestFontInPixelsL()
1567 implementations. It finds the nearest font in the typeface attribute array,
1568 if any, to the provided font specification. If there is a possible match it
1569 places the face index in aFaceIndex and the actual specification (including
1570 algorithmic effects) in aActualFontSpec.
1572 @param aDesiredFontSpec The desired font specification.
1573 @param aPixelWidth The width of a pixel. Used with aPixelHeight for calculating
1574 the algorithmic slant of the typeface.
1575 @param aPixelHeight The height of a pixel. Used with aPixelWidth for calculating
1576 the algorithmic slant of the typeface.
1577 @param aFaceIndex The index of the typeface which contains the closest match
1578 to aDesiredFontSpec.
1579 @param aActualFontSpec The actual font specification of the font with attributes
1580 closest to aDesiredFontSpec.
1581 @return ETrue if there is a possible font match, otherwise EFalse.
1583 EXPORT_C TBool COpenFontFile::GetNearestFontHelper(
1584 const TOpenFontSpec& aDesiredFontSpec,
1588 TOpenFontSpec& aActualFontSpec) const
1590 const TInt faces = FaceCount();
1591 TInt best_points = 0;
1592 TInt best_index = -1;
1594 for (TInt i = 0; i < faces; i++)
1596 TInt cur_points = 0;
1598 if (0 < aDesiredFontSpec.Name().Length())
1600 cur_points = ScoreByName(aDesiredFontSpec, iFaceAttrib[i]);
1604 cur_points = ScoreByStyle(aDesiredFontSpec, iFaceAttrib[i]);
1609 if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
1611 if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
1615 if (cur_points > best_points)
1617 best_points = cur_points;
1622 if (best_index != -1)
1624 aActualFontSpec = aDesiredFontSpec;
1625 // copy attributes & name
1626 aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
1627 aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
1628 // Set an algorithmic slant and adjust it for the pixel aspect ratio.
1629 if ((aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[best_index].IsItalic()) && (0 == aDesiredFontSpec.SlantFactor()))
1631 TInt factor = KDefaultSlantFactor;
1632 if (TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
1634 TOpenFontSpec::ApplyRatio(factor, aPixelWidth, aPixelHeight);
1636 aActualFontSpec.SetSlantFactor(factor);
1640 aFaceIndex = best_index;
1641 return best_index != -1;
1644 TInt COpenFontFile::ScoreByName(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
1646 if (!aDesiredFontSpec.Name().CompareF(aAttrib.FullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFullName()))
1650 else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFullName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFullName()))
1654 else if (!aDesiredFontSpec.Name().CompareF(aAttrib.FamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.LocalFamilyName()))
1658 else if (!aDesiredFontSpec.Name().CompareF(aAttrib.ShortFamilyName()) || !aDesiredFontSpec.Name().CompareF(aAttrib.ShortLocalFamilyName()))
1665 TInt COpenFontFile::ScoreByStyle(const TOpenFontSpec& aDesiredFontSpec, const TAttrib& aAttrib)
1667 if (aDesiredFontSpec.IsSymbol() == aAttrib.IsSymbol())
1671 else if(aDesiredFontSpec.IsMonoWidth() == aAttrib.IsMonoWidth())
1675 else if(aDesiredFontSpec.IsSerif() == aAttrib.IsSerif())
1684 /** @internalComponent */
1685 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec& aDesiredFontSpec, TInt aPixelWidth,TInt aPixelHeight,TInt& aFaceIndex, TOpenFontSpec& aActualFontSpec) const
1687 TInt faces = FaceCount();
1688 TInt best_points = 0;
1689 TInt best_index = -1;
1690 TBool slant = FALSE;
1691 for (TInt i = 0; i < faces; i++)
1693 TPtrC family_name = iFaceAttrib[i].FamilyName();
1694 TPtrC full_name = iFaceAttrib[i].FullName();
1695 TPtrC local_family_name = iFaceAttrib[i].LocalFamilyName();
1696 TPtrC local_full_name = iFaceAttrib[i].LocalFullName();
1697 TPtrC desired_name = aDesiredFontSpec.Name();
1699 TInt cur_points = 0;
1700 if (desired_name.Length() > 0)
1702 if ((full_name.CompareF(desired_name) == 0) || (local_full_name.CompareF(desired_name) == 0))
1704 else if ((family_name.CompareF(desired_name) == 0) || (local_family_name.CompareF(desired_name) == 0))
1709 if ((aDesiredFontSpec.IsSerif() == iFaceAttrib[i].IsSerif()) && (aDesiredFontSpec.IsMonoWidth() == iFaceAttrib[i].IsMonoWidth()) && (aDesiredFontSpec.IsSymbol() == iFaceAttrib[i].IsSymbol()))
1714 if (aDesiredFontSpec.IsItalic() == iFaceAttrib[i].IsItalic())
1716 if (aDesiredFontSpec.IsBold() == iFaceAttrib[i].IsBold())
1718 if (cur_points > best_points)
1720 best_points = cur_points;
1722 slant = (aDesiredFontSpec.IsItalic()) && (!iFaceAttrib[i].IsItalic());
1727 if (best_index != -1)
1729 TInt32 slant_factor = aDesiredFontSpec.SlantFactor();
1731 // Set an algorithmic slant and adjust it for the pixel aspect ratio.
1732 if (slant && slant_factor == 0)
1734 slant_factor = KDefaultSlantFactor;
1735 if (aPixelWidth>0 && aPixelHeight>0 && TOpenFontSpec::IsCompensationForAspectRatioNeeded(aPixelWidth,aPixelHeight))
1737 TOpenFontSpec::ApplyRatio(slant_factor,aPixelWidth,aPixelHeight);
1741 aActualFontSpec = aDesiredFontSpec;
1742 // copy attributes & name
1743 aActualFontSpec.SetAttrib(iFaceAttrib[best_index]);
1744 aActualFontSpec.SetName(iFaceAttrib[best_index].FamilyName());
1745 aActualFontSpec.SetSlantFactor(slant_factor);
1746 aActualFontSpec.SetEffects(0);
1749 aFaceIndex = best_index;
1750 return best_index != -1;
1756 EXPORT_C TBool COpenFontFile::GetNearestFontHelperOld(const TOpenFontSpec&, TInt, TInt, TInt&, TOpenFontSpec&) const
1762 /** This function is called (via iFile) by a COpenFont when it is destroyed. */
1763 void COpenFontFile::RemoveFontFromList(const COpenFont* aFont)
1765 TInt fonts = iFontList.Count();
1766 for (TInt i = 0; i < fonts; i++)
1767 if (iFontList[i] == aFont)
1769 iFontList.Delete(i);
1775 Adds a typeface to this object's typeface array.
1777 This function should be called during construction to add the attributes for
1778 each typeface in the font file to the typeface attribute array.
1782 The typeface array is what is searched for the closest match to a specified
1783 font by GetNearestFontHelper().
1785 @param aAttrib The attributes for a typeface to be added to the typeface attribute
1790 EXPORT_C void COpenFontFile::AddFaceL(const TOpenFontFaceAttrib& aAttrib)
1792 TAttrib& a = iFaceAttrib.ExtendL();
1793 (TOpenFontFaceAttrib&)a = aAttrib;
1796 void COpenFontFile::SetFontStoreL(CFontStore* aFontStore)
1800 iData = new (ELeave) TOpenFontFileData;
1802 iData->iFontStore = aFontStore;
1805 CFontStore* COpenFontFile::GetFontStore()
1807 return iData ? iData->iFontStore : NULL;
1810 CArrayPtrFlat<COpenFont>* COpenFontFile::GetOpenFontList()
1816 static const TInt KTOpenFontSpecBitsNumSymbol = 1;
1817 static const TInt KTOpenFontSpecBitsNumScript = 4;
1818 static const TInt KTOpenFontSpecMaskSymbol = (1 << KTOpenFontSpecBitsNumSymbol) - 1;
1819 static const TInt KTOpenFontSpecMaskScript = ((1 << KTOpenFontSpecBitsNumScript) - 1) << KTOpenFontSpecBitsNumSymbol;
1820 static const TInt KTOpenFontSpecSymbolFlag = 0x1;
1823 Default C++ constructor setting
1824 height to 16 pixels or twips,
1825 width factor to 1 (65536 in 16.16 format),
1826 slant factor to 0 (no slant),
1828 symbol to 0 (assuming EScriptNone = 0),
1829 print position to EPrintPosNormal.
1831 EXPORT_C TOpenFontSpec::TOpenFontSpec()
1833 iWidthFactor(KOneIn16Dot16FixedPointFormat),
1836 iEffects(FontEffect::ENone),
1838 iPrintPosition(EPrintPosNormal),
1844 C++ constructor taking a reference to a TFontSpec.
1846 This object's members are initialised from the values of the aFontSpec parameter.
1848 @param aFontSpec The font specification used to initialise this font specification.
1850 EXPORT_C TOpenFontSpec::TOpenFontSpec(const TFontSpec& aFontSpec)
1856 Assignment operator.
1858 @param aFontSpec The old-style font specification to copy into this font specification.
1860 EXPORT_C void TOpenFontSpec::operator=(const TFontSpec& aFontSpec)
1863 iWidthFactor = KOneIn16Dot16FixedPointFormat;
1864 iHeight = aFontSpec.iHeight; // in twips
1865 iBitmapType = aFontSpec.iFontStyle.BitmapType();
1866 iEffects = aFontSpec.iFontStyle.Effects();
1867 iPrintPosition = aFontSpec.iFontStyle.PrintPosition();
1868 iName = aFontSpec.iTypeface.iName;
1869 SetScriptTypeForMetrics(aFontSpec.iTypeface.ScriptTypeForMetrics());
1870 const TBool symbol = aFontSpec.iTypeface.IsSymbol();
1873 SetCoverage(0); // no appropriate coverage value for the symbol set
1875 SetCoverage(3); // Latin and Latin-1 supplement
1877 if (!aFontSpec.iTypeface.IsProportional())
1878 iStyle |= TOpenFontFaceAttrib::EMonoWidth;
1879 if (aFontSpec.iTypeface.IsSerif())
1880 iStyle |= TOpenFontFaceAttrib::ESerif;
1881 if (aFontSpec.iFontStyle.Posture() == EPostureItalic)
1882 iStyle |= TOpenFontFaceAttrib::EItalic;
1883 if (aFontSpec.iFontStyle.StrokeWeight() == EStrokeWeightBold)
1884 iStyle |= TOpenFontFaceAttrib::EBold;
1889 Adjust the width factor and slant factor to suit a pixel aspect ratio.
1892 @param aPixelWidth The pixel width, in the same units as aPixelHeight.
1893 @param aPixelHeight The pixel height, in the same units as aPixelWidth.
1895 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(TInt aPixelWidth, TInt aPixelHeight)
1897 if (IsCompensationForAspectRatioNeeded(aPixelWidth, aPixelHeight))
1899 ApplyRatio(iWidthFactor, aPixelHeight, aPixelWidth);
1900 ApplyRatio(iSlantFactor, aPixelWidth, aPixelHeight);
1905 Adjust the width factor and slant factor to suit a pixel aspect ratio stored
1906 in a MGraphicsDeviceMap derived object.
1909 @param aMap The MGraphicsDeviceMap defining the pixel aspect ratio.
1911 EXPORT_C void TOpenFontSpec::CompensateForAspectRatio(const MGraphicsDeviceMap& aMap)
1913 CompensateForAspectRatio(aMap.HorizontalPixelsToTwips(1000), aMap.VerticalPixelsToTwips(1000));
1917 The pixel width and height are used to derive a ratio, and so can be
1918 in any units. Aspect ratios differing by less than 1/1000 are treated as 1:1.
1921 TBool TOpenFontSpec::IsCompensationForAspectRatioNeeded(TInt aPixelWidth,TInt aPixelHeight)
1923 if ((aPixelWidth != aPixelHeight) && (0 < aPixelWidth) && (0 < aPixelHeight))
1925 //If nearly square don't transform (0.999 < aPixelHeight/aPixelWidth < 1.001)
1926 TInt64 width = aPixelWidth;
1927 TInt64 height = aPixelHeight;
1928 width *= 999; // Cannot do multiplication on declaration lines above as risk of TInt32 overflow
1930 if (width <= height) // 999 * aPixelWidth <= 1000 * aPixelHeight
1932 width += aPixelWidth;
1933 width += aPixelWidth; // Cannot do with previous line as small risk of TInt32 overflow
1934 if (width >= height) // 1001 * aPixelWidth >= 1000 * aPixelHeight
1941 Multiplies aValue by aNumerator/aDenominator but using TInt64's to avoid any overflows.
1942 Returns ETrue if the final result has an overflow.
1945 TBool TOpenFontSpec::ApplyRatio(TInt& aValue, TInt aNumerator, TInt aDenominator)
1947 TInt64 value(aValue);
1948 value = (value * aNumerator) / aDenominator;
1949 aValue = I64LOW(value);
1950 if (I64HIGH(value) != 0)
1952 OstTrace1( TRACE_FATAL, TOPENFONTSPEC_APPLYRATIO, "value=%ld, Panic(EFntOverFlow)", value );
1953 __ASSERT_DEBUG(0, Panic(EFntOverFlow));
1955 return I64HIGH(value) != 0;
1959 Same as above function but this takes a TInt32 not a TInt
1961 TBool TOpenFontSpec::ApplyRatio(TInt32& aValue, TInt aNumerator, TInt aDenominator)
1963 TInt value = aValue;
1964 TBool ret = ApplyRatio(value, aNumerator, aDenominator);
1969 EXPORT_C void TOpenFontSpec::SetAttrib(const TOpenFontFaceAttribBase& aAttrib)
1971 Sets the font attributes.
1973 @param aAttrib The font attributes.
1976 TOpenFontFaceAttribBase* self = this;
1981 Gets the TFontSpec corresponding to this Open Font System font specification.
1984 @param aFontSpec On return, contains the TFontSpec corresponding to this font
1987 EXPORT_C void TOpenFontSpec::GetTFontSpec(TFontSpec& aFontSpec) const
1989 aFontSpec = TFontSpec();
1990 TPtrC short_name(iName.Ptr(), Min(iName.Length(), KMaxTypefaceNameLength));
1991 aFontSpec.iTypeface.iName = short_name;
1992 aFontSpec.iTypeface.SetIsProportional(!IsMonoWidth());
1993 aFontSpec.iTypeface.SetIsSerif(IsSerif());
1994 aFontSpec.iTypeface.SetIsSymbol(Symbol());
1995 aFontSpec.iTypeface.SetScriptTypeForMetrics(ScriptTypeForMetrics());
1996 aFontSpec.iHeight = iHeight; // as twips
1997 if (IsItalic() || (iSlantFactor > 0))
1998 aFontSpec.iFontStyle.SetPosture(EPostureItalic);
1999 if (IsBold() || IsEffectOn(FontEffect::EAlgorithmicBold))
2000 aFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
2001 aFontSpec.iFontStyle.SetPrintPosition(iPrintPosition);
2002 aFontSpec.iFontStyle.SetBitmapType(BitmapType());
2003 aFontSpec.iFontStyle.SetEffects(iEffects);
2007 Sets a font effect to the given state.
2010 @param aEffect The font effect to be set.
2011 @param aOn True represents on, otherwise off.
2012 @see TOpenFontSpec::IsEffectOn()
2014 EXPORT_C void TOpenFontSpec::SetEffects(FontEffect::TEffect aEffect, TBool aOn)
2016 FontEffect::SetEffect(aEffect, aOn, iEffects);
2019 /** Checks if a font effect is on.
2022 @return True represents the specified font effect is on, otherwise off.
2023 @param aEffect The font effect to be checked.
2024 @see TOpenFontSpec::SetEffects()
2026 EXPORT_C TBool TOpenFontSpec::IsEffectOn(FontEffect::TEffect aEffect) const
2028 return FontEffect::IsEffectOn(aEffect, iEffects);
2032 @deprecated This needs to be maintained to just call the inline methods.
2034 EXPORT_C void TOpenFontSpec::DoSetEffects(TUint32 aEffects)
2036 SetEffects(aEffects);
2040 @deprecated This needs to be maintained to just call the inline methods.
2042 EXPORT_C TUint32 TOpenFontSpec::DoEffects() const
2048 Specifies the script which font metrics calculation will be based on.
2051 @param aLanguage The language used to derive the required script.
2053 EXPORT_C void TOpenFontSpec::SetScriptTypeForMetrics(TLanguage aLanguage)
2055 SetScriptTypeForMetrics(GlyphSample::TLanguage2TScript(aLanguage));
2061 void TOpenFontSpec::SetScriptTypeForMetrics(TInt aScript)
2063 iSymbol &= ~KTOpenFontSpecMaskScript;
2064 iSymbol |= (KTOpenFontSpecMaskScript & (aScript << KTOpenFontSpecBitsNumSymbol));
2068 Gets the script which the font metrics calculation will be based on.
2072 EXPORT_C TInt TOpenFontSpec::ScriptTypeForMetrics() const
2074 return (KTOpenFontSpecMaskScript & iSymbol) >> KTOpenFontSpecBitsNumSymbol;
2080 void TOpenFontSpec::SetSymbol(TBool aSymbol)
2082 iSymbol &= ~KTOpenFontSpecMaskSymbol;
2083 iSymbol |= (aSymbol ? KTOpenFontSpecSymbolFlag : 0);
2089 TBool TOpenFontSpec::Symbol() const
2091 return (KTOpenFontSpecSymbolFlag & iSymbol) > 0;
2095 @deprecated This needs to be maintained to just call the inline methods.
2097 EXPORT_C TBool TOpenFontSpec::OperatorEquality(const TOpenFontSpec& aOpenFontSpec) const
2099 return this->operator == (aOpenFontSpec);
2105 TBool TOpenFontSpec::operator!=(const TOpenFontSpec& aOpenFontSpec) const
2107 return !(this->operator == (aOpenFontSpec));
2111 Static constructor for a TOpenFontGlyphData.
2113 This constructor creates the object on a specified heap. It must be deleted
2114 using RHeap::Free().
2116 @param aHeap The shared heap on which the object is constructed.
2117 @param aBufferSize The amount of memory allocated for the glyph data.
2118 @return A pointer to the newly created object.
2120 EXPORT_C TOpenFontGlyphData* TOpenFontGlyphData::New(RHeap* aHeap, TInt aBufferSize)
2122 if (aBufferSize < 1)
2124 TInt bytes = sizeof(TOpenFontGlyphData) + aBufferSize - 1;
2125 TOpenFontGlyphData* g = (TOpenFontGlyphData*)aHeap->Alloc(bytes);
2128 Mem::FillZ(g, bytes);
2129 g->iBitmapBufferSize = aBufferSize;
2134 // Virtual functions reserved for future expansion.
2139 EXPORT_C void COpenFontRasterizer::ExtendedInterface(TUid, TAny*&)
2143 /** @internalComponent */
2144 EXPORT_C void COpenFontFile::ExtendedInterface(TUid, TAny*&)
2148 EXPORT_C void COpenFont::ExtendedInterface(TUid, TAny*&)
2152 EXPORT_C CShaper::CShaper()
2157 EXPORT_C CShaper::~CShaper()
2161 /** @internalComponent */
2162 EXPORT_C void* CShaper::ExtendedInterface(TUid)
2168 Sets the glyph bitmap type.
2170 Normally the bitmap type belongs to the font, but for linked fonts this can
2171 be different between different font elements making up the linked font.
2173 Note: This is only of use in conjunction with rasterizer based linked fonts.
2178 EXPORT_C void TOpenFontCharMetrics::SetGlyphType(TGlyphBitmapType aGlyphBitmapType)
2180 iGlyphBitmapType = aGlyphBitmapType;
2184 Gets the glyph bitmap type.
2189 EXPORT_C TGlyphBitmapType TOpenFontCharMetrics::GlyphType() const
2191 if (iGlyphBitmapType == 0)
2192 return EGlyphBitmapTypeNotDefined;
2194 return static_cast<TGlyphBitmapType>(iGlyphBitmapType);