sl@0: /* sl@0: * Copyright (c) 1995-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 sl@0: #include sl@0: #include sl@0: #include "FNTBODY.H" sl@0: #include "FNTSTD.H" sl@0: #include sl@0: sl@0: #define DO_LOADFONT_OPTIMIZATION 1 sl@0: #include sl@0: #include "linkedfontsprivate.h" sl@0: #include "openfontsprivate.h" sl@0: #include sl@0: #include 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 "FNTSTORETraces.h" sl@0: #endif sl@0: sl@0: sl@0: static const TUint32 KOutlineGlyphIdHashMask = 0x0000ffff; sl@0: static const TUint32 KOutlineFileUidHashMask = 0x00ff0000; sl@0: static const TUint32 KOutlineFaceIndexHashMask = 0x0f000000; sl@0: static const TUint32 KOutlineFontPtrHashMask = 0x0fff0000; sl@0: sl@0: // uncomment to enable some verbose debug prints sl@0: //#define VERBOSE_DEBUG 1 sl@0: sl@0: sl@0: /** These constants set the default pixel width and height, in Twips x1000. sl@0: Hal Data information overrides this if it is available. EDisplayXPixels & EDisplayXTwips, sl@0: EDisplayYPixels & EDisplayYTwips values are required respectively. sl@0: sl@0: (11860 is approx equivalent to 120 pixels per inch.) sl@0: @internalComponent sl@0: */ sl@0: const TInt KDefaultPixelWidthInTwips = 11860; sl@0: const TInt KDefaultPixelHeightInTwips = 11860; sl@0: sl@0: // default granularity for arrays sl@0: const TInt KDefaultArrayGranularity = 8; sl@0: sl@0: /* Maximum height of a character bitmap. When font height in pixel is 1024, each sl@0: character bitmap is equal to (roughly) 1024 x 1024 x 8 bits/pixel = 1 MB. sl@0: @internalComponent sl@0: */ sl@0: const TInt KMaxFontHeightInPixels = 1024; sl@0: sl@0: /* Minimum height of font in pixels that can be displayed on the screen. sl@0: @internalComponent sl@0: */ sl@0: const TInt KMinFontHeightInPixels = 2; sl@0: /** sl@0: The arbitrary list of sizes, in points, returned for scaleable fonts. sl@0: We can't return 2^32 - 1 sizes, or something that reflect the fact sl@0: that any size is okay, because a UI will probably try to create a listbox containing all the sizes. sl@0: sl@0: Array stored in Twips as that is the only form of the value currently used. sl@0: @internalComponent sl@0: */ sl@0: #define POINTSIZE_IN_TWIPS(p) ((p) * 20) sl@0: const TInt gOpenFontSizeInTwipsArray[] = sl@0: { sl@0: // 4pt-18pt in steps of 1pt (15 sizes) sl@0: POINTSIZE_IN_TWIPS(4), POINTSIZE_IN_TWIPS(5), POINTSIZE_IN_TWIPS(6), sl@0: POINTSIZE_IN_TWIPS(7), POINTSIZE_IN_TWIPS(8), POINTSIZE_IN_TWIPS(9), sl@0: POINTSIZE_IN_TWIPS(10), POINTSIZE_IN_TWIPS(11), POINTSIZE_IN_TWIPS(12), sl@0: POINTSIZE_IN_TWIPS(13), POINTSIZE_IN_TWIPS(14), POINTSIZE_IN_TWIPS(15), sl@0: POINTSIZE_IN_TWIPS(16), POINTSIZE_IN_TWIPS(17), POINTSIZE_IN_TWIPS(18), sl@0: // 20pt-36pt in steps of 2pt (9 sizes) sl@0: POINTSIZE_IN_TWIPS(20), POINTSIZE_IN_TWIPS(22), POINTSIZE_IN_TWIPS(24), sl@0: POINTSIZE_IN_TWIPS(26), POINTSIZE_IN_TWIPS(28), POINTSIZE_IN_TWIPS(30), sl@0: POINTSIZE_IN_TWIPS(32), POINTSIZE_IN_TWIPS(34), POINTSIZE_IN_TWIPS(36), sl@0: // 40pt-72pt in steps of 4pt (9 sizes) sl@0: POINTSIZE_IN_TWIPS(40), POINTSIZE_IN_TWIPS(44), POINTSIZE_IN_TWIPS(48), sl@0: POINTSIZE_IN_TWIPS(52), POINTSIZE_IN_TWIPS(56), POINTSIZE_IN_TWIPS(60), sl@0: POINTSIZE_IN_TWIPS(64), POINTSIZE_IN_TWIPS(68), POINTSIZE_IN_TWIPS(72), sl@0: // 80pt-144pt in steps of 8pt (9 sizes) sl@0: POINTSIZE_IN_TWIPS(80), POINTSIZE_IN_TWIPS(88), POINTSIZE_IN_TWIPS(96), sl@0: POINTSIZE_IN_TWIPS(104), POINTSIZE_IN_TWIPS(112), POINTSIZE_IN_TWIPS(120), sl@0: POINTSIZE_IN_TWIPS(128), POINTSIZE_IN_TWIPS(136), POINTSIZE_IN_TWIPS(144) sl@0: }; sl@0: sl@0: const TInt KOpenFontSizeArrayCount = sizeof(gOpenFontSizeInTwipsArray) / sizeof(gOpenFontSizeInTwipsArray[0]); sl@0: sl@0: /** sl@0: @internalTechnology sl@0: The folder used to store linked fonts; the character represents the system drive sl@0: location and the descriptor contains the private path of fbserv. sl@0: */ sl@0: _LIT(KLinkedFontFileFolder, "%c:%Slfonts\\"); sl@0: sl@0: /** sl@0: @internalTechnology sl@0: The folder used to store updated linked fonts; the descriptor should be formatted sl@0: with the formatted version of KLinkedFontFileFolder. Files will be moved from this sl@0: folder to KLinkedFontFileFolder at boot time before the font loading procedure. sl@0: */ sl@0: _LIT(KLinkedFontFileTempFolder, "update\\"); sl@0: sl@0: /** sl@0: The font search string. The Y: directory prefix forces the search to sl@0: start with drive Y:. The drives will be searched in the order Y: to A: then Z: sl@0: */ sl@0: _LIT(KFBSERVFontDirSecure, "y:\\resource\\fonts\\"); sl@0: sl@0: /**The maximum length of the linked font folder path*/ sl@0: const TInt KMaxLinkedFontPathLength = 36; sl@0: sl@0: /**The maximum length of a private path*/ sl@0: const TInt KMaxPrivatePathLength = 19; sl@0: sl@0: /** Container for TTypefaceSupport that describes an Open Font family. sl@0: sl@0: There is an implicit assumption that all fonts in the family will have the same attributes sl@0: as the first instance found. E.g. that the range of font heights is the same. sl@0: sl@0: An array of pointers to the COpenFontFile file objects that hold fonts in this family sl@0: also provides reference counting for the object. sl@0: sl@0: @internalComponent sl@0: */ sl@0: NONSHARABLE_CLASS(CTypefaceSupportInfo) : public CBase sl@0: { sl@0: public: sl@0: CTypefaceSupportInfo(); sl@0: inline TInt AddFontFilePtr(COpenFontFile* aOpenFontFile); sl@0: inline TInt AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib); sl@0: inline TInt FindFontFilePtr(COpenFontFile* aOpenFontFile); sl@0: inline TBool RemoveFontFilePtr(TInt aIndex); sl@0: void SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips); sl@0: inline const TTypefaceSupport* TypefaceSupport() const; sl@0: inline TInt NearestPointSizeIndex() const; sl@0: static TInt CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2); sl@0: ~CTypefaceSupportInfo(); sl@0: sl@0: public: sl@0: TTypefaceSupport iSupport; sl@0: // pointers back to the COpenFontFile object which has one or more typefaces in this family sl@0: RPointerArray iOpenFontFilePtrArray; sl@0: // nearest standard point size index; sl@0: TInt iNearestPointSizeIndex; sl@0: }; sl@0: sl@0: sl@0: /** helper class used with the cleanup stack sl@0: @internalComponent sl@0: */ sl@0: class TCleanupRemoveFontFile sl@0: { sl@0: public: sl@0: inline TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid); sl@0: public: sl@0: CFontStore* iFontStore; sl@0: TUid iFontUid; sl@0: }; sl@0: sl@0: sl@0: // declare static functions sl@0: static TInt MatchFontSpecsInPixels(const TOpenFontSpec& aCandidateFontSpec, sl@0: const TOpenFontSpec& aIdealFontSpec, TInt aCandidateMaxHeight = 0, TInt aIdealMaxHeight = 0); sl@0: static void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength); sl@0: static TUint TtfTableTagFromBufferL(TDes8& aDes); sl@0: sl@0: #ifdef _DEBUG sl@0: static TUint32 StartTiming(void); sl@0: static TUint32 FinishTimingL(TUint32 startTime); sl@0: #endif sl@0: sl@0: static TBool FileIsOnZ(TParse& aFileName); sl@0: static TBool FileIsInList(TParse& aFileName, RArray& aList); sl@0: sl@0: sl@0: /** Helper function for converting a pointer to an offset from the passed sl@0: heap base. Use OffsetToPointer() to convert the returned offset back to a sl@0: useable pointer. sl@0: @param aAny A pointer to be converted to an offset. sl@0: @param aHeapBase The heap base of the current process. sl@0: @return An offset representing the passed pointer that can be converted sl@0: back to a pointer using the function OffsetToPointer(). sl@0: @see OffsetToPointer() sl@0: */ sl@0: LOCAL_C TInt PointerToOffset(const TAny* aAny, TUint8* aHeapBase) sl@0: { sl@0: if (aAny && aHeapBase) sl@0: { sl@0: return reinterpret_cast(aAny) - reinterpret_cast(aHeapBase); sl@0: } sl@0: return 0; sl@0: } sl@0: sl@0: /** Helper function for converting an offset (that was calculated using sl@0: PointerToOffset()) back to a pointer relative to the passed heap base. sl@0: @param aOffset The offset to be converted to a pointer. sl@0: @param aHeapBase The heap base of the current process. sl@0: @return A pointer relative to the passed heap base. sl@0: @see PointerToOffset() sl@0: */ sl@0: LOCAL_C TAny* OffsetToPointer(TInt aOffset, TUint8* aHeapBase) sl@0: { sl@0: if (aOffset && aHeapBase) sl@0: { sl@0: return reinterpret_cast(aOffset + reinterpret_cast(aHeapBase)); sl@0: } sl@0: return NULL; sl@0: } sl@0: sl@0: sl@0: // CTypefaceSupportInfo sl@0: CTypefaceSupportInfo::CTypefaceSupportInfo() sl@0: { sl@0: } sl@0: sl@0: sl@0: CTypefaceSupportInfo::~CTypefaceSupportInfo() sl@0: { // no ownership of font files, so just Close the array sl@0: iOpenFontFilePtrArray.Close(); sl@0: } sl@0: sl@0: sl@0: /** Add a back pointer to an Open Font file, in sorted order. sl@0: @param aOpenFontFile font file that has a typeface in this family. sl@0: @return KErrNone if added, KErrAlreadyExists if file is already referenced, or KErrNoMemory. sl@0: @internalComponent sl@0: */ sl@0: TInt CTypefaceSupportInfo::AddFontFilePtr(COpenFontFile* aOpenFontFile) sl@0: { sl@0: return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile); sl@0: } sl@0: sl@0: /** Add a back pointer to an Open Font file, in sorted order, but only if the font details are unique. sl@0: @param aOpenFontFile font file that has a typeface in this family. sl@0: @return KErrNone if added, KErrInUse if another file already defines this, KErrAlreadyExists if file is already referenced, or KErrNoMemory. sl@0: @internalComponent sl@0: */ sl@0: TInt CTypefaceSupportInfo::AddUniqueFontFilePtr(COpenFontFile* aOpenFontFile,const TOpenFontFaceAttrib& aFaceAttrib) sl@0: { sl@0: #ifdef _DEBUG sl@0: _LIT(KLoadedFont, "TypefaceSupport: already loaded font: %S\n"); sl@0: #endif sl@0: sl@0: TPtrC findName=aFaceAttrib.FullName(); sl@0: for (TInt i=0,maxi=iOpenFontFilePtrArray.Count();iFaceCount();jFaceAttrib(j); sl@0: TPtrC cmpName=cmpFace.FullName(); sl@0: if (cmpName==findName) sl@0: { sl@0: #ifdef _DEBUG sl@0: RDebug::Print(KLoadedFont, &findName); sl@0: #endif sl@0: return KErrInUse; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: return iOpenFontFilePtrArray.InsertInAddressOrder(aOpenFontFile); sl@0: } sl@0: sl@0: /** Check font family for back pointer to an Open Font file. sl@0: @param aOpenFontFile font file that may have a typeface in this family. sl@0: @return KErrNotFound or the index of pointer sl@0: @internalComponent sl@0: */ sl@0: TInt CTypefaceSupportInfo::FindFontFilePtr(COpenFontFile* aOpenFontFile) sl@0: { sl@0: return iOpenFontFilePtrArray.FindInAddressOrder(aOpenFontFile); sl@0: } sl@0: sl@0: sl@0: /** Remove a font file back pointer. sl@0: @param aIndex the index of pointer, from FindFontFilePtr() sl@0: @return ETrue if there are no more implementations of the font family sl@0: @internalComponent sl@0: */ sl@0: TBool CTypefaceSupportInfo::RemoveFontFilePtr(TInt aIndex) sl@0: { sl@0: iOpenFontFilePtrArray.Remove(aIndex); sl@0: return iOpenFontFilePtrArray.Count() == 0; sl@0: } sl@0: sl@0: sl@0: /** Set the details of the typeface family. sl@0: @param aFaceAttrib typeface to parameterise. sl@0: @internalComponent sl@0: */ sl@0: void CTypefaceSupportInfo::SetTypefaceInfo(const TOpenFontFaceAttrib& aFaceAttrib, TInt aMinHeightInTwips) sl@0: { sl@0: iSupport.iTypeface.iName = aFaceAttrib.ShortFamilyName(); sl@0: iSupport.iTypeface.SetIsProportional(!aFaceAttrib.IsMonoWidth()); sl@0: iSupport.iTypeface.SetIsSerif(aFaceAttrib.IsSerif()); sl@0: iSupport.iTypeface.SetIsSymbol(aFaceAttrib.IsSymbol()); sl@0: sl@0: // Find minimum size in twips then find the next higher standard size. sl@0: iSupport.iMinHeightInTwips = aMinHeightInTwips; sl@0: TInt fontSizeIndex = 0; sl@0: for (; fontSizeIndex < KOpenFontSizeArrayCount; ++fontSizeIndex) sl@0: { sl@0: const TInt KMinHeightInTwips = gOpenFontSizeInTwipsArray[fontSizeIndex]; sl@0: if (aMinHeightInTwips <= KMinHeightInTwips) sl@0: { sl@0: aMinHeightInTwips = KMinHeightInTwips; sl@0: break; sl@0: } sl@0: } sl@0: iNearestPointSizeIndex = fontSizeIndex; sl@0: iSupport.iMaxHeightInTwips = Max(gOpenFontSizeInTwipsArray[KOpenFontSizeArrayCount - 1], iSupport.iMinHeightInTwips); sl@0: iSupport.iNumHeights = Max(1,KOpenFontSizeArrayCount - iNearestPointSizeIndex); sl@0: iSupport.iIsScalable = TRUE; sl@0: } sl@0: sl@0: sl@0: /** Get the details of the typeface family. sl@0: @internalComponent sl@0: */ sl@0: const TTypefaceSupport* CTypefaceSupportInfo::TypefaceSupport() const sl@0: { sl@0: return &iSupport; sl@0: } sl@0: sl@0: /** Get the Nearest Standard Point Size Index. sl@0: @internalComponent sl@0: */ sl@0: TInt CTypefaceSupportInfo::NearestPointSizeIndex() const sl@0: { sl@0: return iNearestPointSizeIndex; sl@0: } sl@0: sl@0: // for InsertInOrder sl@0: TInt CTypefaceSupportInfo::CompareFontNames(const CTypefaceSupportInfo& aTypeface1, const CTypefaceSupportInfo& aTypeface2) sl@0: { sl@0: return aTypeface1.iSupport.iTypeface.iName.CompareF(aTypeface2.iSupport.iTypeface.iName); sl@0: } sl@0: sl@0: sl@0: // TCleanupRemoveFontFile sl@0: TCleanupRemoveFontFile::TCleanupRemoveFontFile(CFontStore* aFontStore, TUid aFontUid) : sl@0: iFontStore(aFontStore), iFontUid(aFontUid) sl@0: { sl@0: } sl@0: sl@0: sl@0: TBitmapFontCharacterOffset::TBitmapFontCharacterOffset() sl@0: : iBitmapOffset(0) sl@0: {} sl@0: sl@0: void TBitmapFontCharacterOffset::InternalizeL(RReadStream& aStream) sl@0: { sl@0: iBitmapOffset = aStream.ReadUint16L(); sl@0: }; sl@0: sl@0: EXPORT_C TCharacterMetrics::TCharacterMetrics() sl@0: : iAscentInPixels(0), sl@0: iHeightInPixels(0), sl@0: iLeftAdjustInPixels(0), sl@0: iMoveInPixels(0), sl@0: iRightAdjustInPixels(0) sl@0: { sl@0: } sl@0: sl@0: TBitmapFontCharacterMetrics::TBitmapFontCharacterMetrics() sl@0: : iAscentInPixels(0), sl@0: iHeightInPixels(0), sl@0: iLeftAdjustInPixels(0), sl@0: iMoveInPixels(0), sl@0: iRightAdjustInPixels(0) sl@0: { sl@0: } sl@0: sl@0: void TBitmapFontCharacterMetrics::InternalizeL(RReadStream& aStream) sl@0: { sl@0: iAscentInPixels = aStream.ReadInt8L(); sl@0: iHeightInPixels = aStream.ReadInt8L(); sl@0: iLeftAdjustInPixels = aStream.ReadInt8L(); sl@0: iMoveInPixels = aStream.ReadInt8L(); sl@0: iRightAdjustInPixels = aStream.ReadInt8L(); sl@0: } sl@0: sl@0: /** Constructor. */ sl@0: EXPORT_C TAlgStyle::TAlgStyle() sl@0: : iBaselineOffsetInPixels(0), sl@0: iFlags(0), sl@0: iWidthFactor(1), sl@0: iHeightFactor(1) sl@0: { sl@0: } sl@0: sl@0: /** Sets whether the font is bold. sl@0: sl@0: @param aIsBold ETrue if the font is bold; otherwise EFalse. */ sl@0: EXPORT_C void TAlgStyle::SetIsBold(TBool aIsBold) sl@0: { sl@0: if (aIsBold) sl@0: iFlags |= EBold; sl@0: else sl@0: iFlags &= ~EBold; sl@0: } sl@0: sl@0: /** Sets whether the font is italic. sl@0: sl@0: @param aIsItalic ETrue if the font is italic; otherwise EFalse. */ sl@0: EXPORT_C void TAlgStyle::SetIsItalic(TBool aIsItalic) sl@0: { sl@0: if (aIsItalic) sl@0: iFlags |= EItalic; sl@0: else sl@0: iFlags &= ~EItalic; sl@0: } sl@0: sl@0: /** Sets whether the font is mono width - i.e. all characters have the same width. sl@0: sl@0: @param aIsMono ETrue if the font is mono width; otherwise EFalse. */ sl@0: EXPORT_C void TAlgStyle::SetIsMono(TBool aIsMono) sl@0: { sl@0: if (aIsMono) sl@0: iFlags|=EMono; sl@0: else sl@0: iFlags&=~EMono; sl@0: } sl@0: sl@0: /** Sets the width factor. sl@0: sl@0: @param aWidthFactor A width factor. */ sl@0: EXPORT_C void TAlgStyle::SetWidthFactor(TInt aWidthFactor) sl@0: { sl@0: iWidthFactor=(TInt8) aWidthFactor; sl@0: } sl@0: sl@0: /** Sets the height factor. sl@0: sl@0: @param aHeightFactor A height factor. */ sl@0: EXPORT_C void TAlgStyle::SetHeightFactor(TInt aHeightFactor) sl@0: { sl@0: iHeightFactor=(TInt8) aHeightFactor; sl@0: } sl@0: sl@0: /** Returns whether the font is bold. sl@0: sl@0: @return ETrue if the font is bold; otherwise EFalse. */ sl@0: EXPORT_C TBool TAlgStyle::IsBold() const sl@0: { sl@0: return iFlags&EBold; sl@0: } sl@0: sl@0: /** Returns whether the font is italic. sl@0: sl@0: @return ETrue if the font is italic; otherwise EFalse. */ sl@0: EXPORT_C TBool TAlgStyle::IsItalic() const sl@0: { sl@0: return iFlags&EItalic; sl@0: } sl@0: sl@0: /** Returns whether the font is mono - i.e. all characters have the same width. sl@0: sl@0: @return ETrue if the font is mono; otherwise EFalse. */ sl@0: EXPORT_C TBool TAlgStyle::IsMono() const sl@0: { sl@0: return iFlags&EMono; sl@0: } sl@0: sl@0: /** Returns the width factor. sl@0: sl@0: @return A width factor. */ sl@0: EXPORT_C TInt TAlgStyle::WidthFactor() const sl@0: { sl@0: return iWidthFactor; sl@0: } sl@0: sl@0: /** Returns the height factor. sl@0: sl@0: @return A height factor. */ sl@0: EXPORT_C TInt TAlgStyle::HeightFactor() const sl@0: { sl@0: return iHeightFactor; sl@0: } sl@0: sl@0: EXPORT_C TBool TAlgStyle::operator==(const TAlgStyle& aAlgStyle) const sl@0: { sl@0: return (iFlags==aAlgStyle.iFlags) && sl@0: (iWidthFactor==aAlgStyle.iWidthFactor) && sl@0: (iHeightFactor==aAlgStyle.iHeightFactor) && sl@0: (iBaselineOffsetInPixels==aAlgStyle.iBaselineOffsetInPixels); sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: */ sl@0: TBool TAlgStyle::operator!=(const TAlgStyle& aAlgStyle) const sl@0: { sl@0: return !this->operator==(aAlgStyle); sl@0: } sl@0: sl@0: CBitmapFont::CBitmapFont( sl@0: RHeap* aHeap, sl@0: const TFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: CFontBitmap* aFontBitmap): sl@0: iFontSpecInTwips(aFontSpecInTwips), sl@0: iAlgStyle(aAlgStyle), sl@0: iHeap(aHeap) sl@0: { sl@0: iFontBitmapOffset = (TInt) ((TUint)(aFontBitmap) - (TUint)(this)); sl@0: } sl@0: sl@0: CBitmapFont::CBitmapFont( sl@0: RHeap* aHeap, sl@0: const TFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: COpenFont* aOpenFont): sl@0: iFontSpecInTwips(aFontSpecInTwips), sl@0: iAlgStyle(aAlgStyle), sl@0: iHeap(aHeap) sl@0: { sl@0: // Set iOpenFont to be the offset of aOpenFont from the address of CBitmapFont. sl@0: // In order to be able to identify iOpenFont as an offset instead of a pointer, sl@0: // bitwise or the offset with 1. Pointers will always be word aligned (and therefore even). sl@0: if (aOpenFont) sl@0: { sl@0: __ASSERT_DEBUG(!(reinterpret_cast(aOpenFont) & 1), Panic(EFntPointerNotByteAligned)); sl@0: iOpenFont = reinterpret_cast((reinterpret_cast(aOpenFont) - reinterpret_cast(this)) | 1); sl@0: } sl@0: else sl@0: { sl@0: iOpenFont = NULL; sl@0: } sl@0: } sl@0: sl@0: /** This member is private and not intended for use. */ sl@0: void CBitmapFont::ConstructL() sl@0: { sl@0: if (!IsOpenFont()) sl@0: FontBitmap()->UseL(); sl@0: } sl@0: sl@0: /** This member is private and not intended for use. */ sl@0: CBitmapFont::~CBitmapFont() sl@0: { sl@0: if (!IsOpenFont() && iFontBitmapOffset) sl@0: FontBitmap()->Release(); sl@0: else if (IsOpenFont()) sl@0: delete OpenFont(); sl@0: } sl@0: sl@0: CBitmapFont* CBitmapFont::NewL( sl@0: RHeap* aHeap, sl@0: const TFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: CFontBitmap* aFontBitmap) sl@0: { sl@0: // font is placed in shared heap sl@0: CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont)); sl@0: new(f) CBitmapFont(aHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap); sl@0: CleanupStack::PushL(f); sl@0: f->ConstructL(); sl@0: CleanupStack::Pop(f); sl@0: return f; sl@0: } sl@0: sl@0: CBitmapFont* CBitmapFont::NewL( sl@0: RHeap* aHeap, sl@0: const TFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: COpenFont* aOpenFont) sl@0: { sl@0: // font is placed in shared heap sl@0: CBitmapFont* f = (CBitmapFont*) aHeap->AllocL(sizeof(CBitmapFont)); sl@0: new(f) CBitmapFont(aHeap,aFontSpecInTwips,aAlgStyle,aOpenFont); sl@0: return f; sl@0: } sl@0: sl@0: /** Returns the font type identifier:KCBitmapFontUidVal. sl@0: sl@0: @return The font type identifier. */ sl@0: EXPORT_C TUid CBitmapFont::DoTypeUid() const sl@0: { sl@0: return TUid::Uid(KCBitmapFontUidVal); sl@0: } sl@0: sl@0: /** Returns a font identifier. sl@0: sl@0: If it uses an open font the UID returned has a value of zero. Otherwise it sl@0: has the UID value of the CFontBitmap it uses. sl@0: sl@0: @return A font identifier. */ sl@0: TUid CBitmapFont::Uid() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return TUid::Uid(0); sl@0: else sl@0: return FontBitmap()->iUid; sl@0: } sl@0: sl@0: /** Returns the font height in pixels. sl@0: For an open font this will be the design height (notional rather than exact). sl@0: sl@0: @return Font height in pixels. sl@0: @see FontMaxHeight() sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::DoHeightInPixels() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return Height(OpenFont()->Metrics().Size()); sl@0: else sl@0: return Height(FontBitmap()->iCellHeightInPixels); sl@0: } sl@0: sl@0: /** Returns the font ascent in pixels. sl@0: sl@0: The ascent is usually the height of a Latin capital letter above the baseline. sl@0: For an open font, the returned value is likely to be inaccurate. sl@0: Don't rely on it to get exact metrics at the pixel level. sl@0: sl@0: @return Font ascent in pixels. sl@0: @see FontCapitalAscent() sl@0: @see FontMaxAscent() sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::DoAscentInPixels() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return Height(OpenFont()->Metrics().Ascent()); sl@0: else sl@0: return Height(FontBitmap()->iAscentInPixels); sl@0: } sl@0: sl@0: /** Returns the width, in pixels, of the given character. sl@0: sl@0: If all characters have the same width (i.e. the font is mono - an attribute sl@0: stored in iAlgStyle) then this is the maximum normal width, returned using sl@0: MaxNormalCharWidthInPixels(). sl@0: sl@0: Note: For OpenType fonts this function returns the horizontal advance of sl@0: the character, which may be different from the actual width. sl@0: sl@0: @param aChar A character. sl@0: @return The character width in pixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoCharWidthInPixels(TChar aChar) const sl@0: { sl@0: const TUint8* bytes; sl@0: if (iAlgStyle.IsMono()) sl@0: return MaxNormalCharWidthInPixels(); sl@0: else sl@0: return Width(CharacterMetrics(aChar,bytes).iMoveInPixels); sl@0: } sl@0: sl@0: /** Returns the width, in pixels, of the given text. sl@0: sl@0: @param aText Text string. sl@0: @return Width of the text in pixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText) const sl@0: { sl@0: TMeasureTextInput* dummy = NULL; sl@0: return DoTextWidthInPixels(aText, dummy); sl@0: } sl@0: sl@0: /** Returns the width, in pixels, of the given text. sl@0: sl@0: @param aText Text string. sl@0: @return Width of the text in pixels. */ sl@0: TInt CBitmapFont::DoTextWidthInPixels(const TDesC &aText, const TMeasureTextInput* aParam) const sl@0: { sl@0: TMeasureTextOutput output; sl@0: TInt advance_width = MeasureText(aText,aParam,&output); sl@0: return Max(advance_width,output.iBounds.Width()); sl@0: } sl@0: sl@0: sl@0: /** Returns the baseline offset in pixels, as stored in iAlgStyle. sl@0: sl@0: @return The baseline offset in pixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoBaselineOffsetInPixels() const sl@0: { sl@0: return iAlgStyle.iBaselineOffsetInPixels; sl@0: } sl@0: sl@0: /** Returns the number of whole characters of aText, starting from the beginning, sl@0: that fit into the given pixel width. sl@0: sl@0: @param aText A text string. sl@0: @param aWidthInPixels A width in pixels. sl@0: @return The number of whole characters of aText that fit into aWidthInPixels. sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels) const sl@0: { sl@0: TInt count = 0; sl@0: const TInt length = aText.Length(); sl@0: TInt width = 0; sl@0: // accumulate text width character by character, until target is reached or exceeded sl@0: TInt widthDiff = aWidthInPixels - width; sl@0: while ( (widthDiff > 0) && (length > count) ) sl@0: { sl@0: width += TextWidthInPixels(aText.Mid(count,1)); sl@0: widthDiff = aWidthInPixels - width; sl@0: if (widthDiff >= 0) sl@0: { // width <= aWidthInPixels sl@0: ++count; sl@0: } sl@0: } sl@0: return count; sl@0: } sl@0: sl@0: /** Returns the number of whole characters of aText, starting from the beginning, sl@0: that fit into the given pixel width, and gets the excess width. sl@0: sl@0: @param aText A text descriptor. sl@0: @param aWidthInPixels A width in pixels. sl@0: @param aExcessWidthInPixels On return, the width left over of aWidthInPixels sl@0: after the maximum possible whole number of characters of aText have been fit sl@0: into it. sl@0: @return The number of whole characters of aText that fit into aWidthInPixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoTextCount(const TDesC &aText,TInt aWidthInPixels,TInt &aExcessWidthInPixels) const sl@0: { sl@0: TInt count = TextCount(aText,aWidthInPixels); sl@0: aExcessWidthInPixels = aWidthInPixels - TextWidthInPixels(aText.Left(count)); sl@0: return count; sl@0: } sl@0: sl@0: /** Returns the font's maximum character width in pixels. sl@0: sl@0: @return The maximum character width in pixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoMaxCharWidthInPixels() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return Width(OpenFont()->Metrics().MaxWidth()); sl@0: else sl@0: return Width(FontBitmap()->iMaxCharWidthInPixels); sl@0: } sl@0: sl@0: /** Returns the font's normal maximum character width in pixels. sl@0: sl@0: Note that when a CFontBitmap is used this value is the same as the maximum sl@0: character width in pixels returned by MaxCharWidthInPixels(), but when a COpenFont sl@0: is used the value may be different. sl@0: sl@0: @return The normal maximum character width in pixels. */ sl@0: EXPORT_C TInt CBitmapFont::DoMaxNormalCharWidthInPixels() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return Width(OpenFont()->Metrics().MaxWidth()); sl@0: else sl@0: return Width(FontBitmap()->iMaxNormalCharWidthInPixels); sl@0: } sl@0: sl@0: /** Returns the device-independent font specification for the font. sl@0: sl@0: Note that this is set when the bitmap font object is constructed. sl@0: sl@0: @return A font specification. */ sl@0: EXPORT_C TFontSpec CBitmapFont::DoFontSpecInTwips() const sl@0: { sl@0: return iFontSpecInTwips; sl@0: } sl@0: sl@0: sl@0: /** Attempts to rasterize a character (aCode) into a data area (aGlyphData) in sl@0: shared memory. sl@0: sl@0: This works only for open fonts: where the bitmap font object is using a COpenFont. sl@0: sl@0: Bitmap fonts are deemed to be fully rasterized after they have been loaded sl@0: from file. sl@0: sl@0: Returns ETrue if the character was successfully rasterized or was already sl@0: in the cache. This function can be called only by the server; rasterization sl@0: uses memory and other resources (e.g., file handles) owned by the server. sl@0: sl@0: @param aSessionHandle A session handle for the open font system. sl@0: @param aCode A character code. sl@0: @param aGlyphData A data area in shared memory. sl@0: @return ETrue if the character was successfully rasterized or was already in sl@0: the cache; otherwise EFalse. */ sl@0: EXPORT_C TBool CBitmapFont::Rasterize(TInt aSessionHandle, TInt aCode, TOpenFontGlyphData* aGlyphData) const sl@0: { sl@0: if (IsOpenFont()) sl@0: return OpenFont()->Rasterize(aSessionHandle, aCode, aGlyphData); sl@0: else sl@0: return EFalse; sl@0: } sl@0: sl@0: /** Gets a pointer to a bitmap and the metrics for a specified character, but only sl@0: if a CFontBitmap is being used by the bitmap font object. sl@0: sl@0: This function does not work when a COpenFont is being used, but GetCharacterData() sl@0: can be used instead. sl@0: sl@0: If the specified character does not exist in the font then the bitmap pointer sl@0: and character metrics are gotten for a replacement character, KReplacementCharacter. sl@0: sl@0: @param aCode A character code. sl@0: @param aBytes On return, a pointer to the bitmap for the specified character. sl@0: @return Metrics for the specified character. */ sl@0: EXPORT_C TCharacterMetrics CBitmapFont::CharacterMetrics(TInt aCode,const TUint8*& aBytes) const sl@0: { sl@0: /* sl@0: This function does not work for Open Fonts because the character data need not be sl@0: shared between sessions and a session handle is needed; GetCharacterData should be used instead. sl@0: */ sl@0: if (IsOpenFont()) sl@0: { sl@0: aBytes = NULL; sl@0: return TCharacterMetrics(); sl@0: } sl@0: sl@0: TBitmapFontCharacterMetrics bitmap_font_metrics = FontBitmap()->CharacterMetrics(aCode,aBytes); sl@0: sl@0: // Substitute the replacement character if this character doesn't exist in the font. sl@0: if (aBytes == NULL) sl@0: bitmap_font_metrics = FontBitmap()->CharacterMetrics(KReplacementCharacter,aBytes); sl@0: sl@0: TCharacterMetrics metrics; sl@0: metrics.iAscentInPixels = bitmap_font_metrics.iAscentInPixels; sl@0: metrics.iHeightInPixels = bitmap_font_metrics.iHeightInPixels; sl@0: metrics.iLeftAdjustInPixels = bitmap_font_metrics.iLeftAdjustInPixels; sl@0: metrics.iMoveInPixels = bitmap_font_metrics.iMoveInPixels; sl@0: metrics.iRightAdjustInPixels = bitmap_font_metrics.iRightAdjustInPixels; sl@0: sl@0: if (iAlgStyle.IsMono()) sl@0: { sl@0: TInt width = metrics.iMoveInPixels - metrics.iLeftAdjustInPixels - metrics.iRightAdjustInPixels; sl@0: metrics.iMoveInPixels = FontBitmap()->iMaxNormalCharWidthInPixels; sl@0: metrics.iLeftAdjustInPixels = (TInt16)((metrics.iMoveInPixels - width) / 2); sl@0: metrics.iRightAdjustInPixels = (TInt16)(metrics.iMoveInPixels - width - metrics.iLeftAdjustInPixels); sl@0: } sl@0: sl@0: return metrics; // N.B. Not doubled for double height and double width. sl@0: } sl@0: sl@0: sl@0: /** Gets a pointer to a bitmap and the metrics for a specified character. sl@0: sl@0: Note that this function calls CharacterMetrics() if a CFontBitmap is being sl@0: used by the bitmap font object, and maps the TCharacterMetrics values returned sl@0: by that function to aMetrics. sl@0: sl@0: If the function fails to get the bitmap and metric values (because the character sl@0: is in an open font and has not yet been rasterized) returns EFalse. sl@0: sl@0: @param aSessionHandle A session handle for the open font system. sl@0: @param aCode A character code. sl@0: @param aMetrics On return, metrics for the specified character. sl@0: @param aBitmap On return, a pointer to the bitmap for the specified character. sl@0: @return ETrue if successful, otherwise EFalse. */ sl@0: EXPORT_C TBool CBitmapFont::GetCharacterData(TInt aSessionHandle,TInt aCode, sl@0: TOpenFontCharMetrics& aMetrics,const TUint8*& aBitmap) const sl@0: { sl@0: if (IsOpenFont()) sl@0: { sl@0: const TOpenFontCharMetrics* nm; sl@0: if (OpenFont()->GetCharacterData(aSessionHandle,aCode,nm,aBitmap)) sl@0: { sl@0: aMetrics = *nm; sl@0: return ETrue; sl@0: } sl@0: else sl@0: return EFalse; sl@0: } sl@0: else sl@0: { sl@0: TCharacterMetrics m = CharacterMetrics(aCode,aBitmap); sl@0: aMetrics = TOpenFontCharMetrics(m); sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: /** Gets the open font metrics. sl@0: sl@0: These metrics distinguish between maximum character height and depth and typographic sl@0: ascent and descent, so that the clipping rectangle for text can be distinguished sl@0: from the distance to neighbouring baselines. sl@0: sl@0: @param aMetrics Open font metrics. */ sl@0: sl@0: EXPORT_C void CBitmapFont::GetFontMetrics(TOpenFontMetrics& aMetrics) const sl@0: { sl@0: if (IsOpenFont()) sl@0: aMetrics = OpenFont()->Metrics(); sl@0: else sl@0: { sl@0: new(&aMetrics) TOpenFontMetrics; sl@0: aMetrics.SetSize(CBitmapFont::DoHeightInPixels()); sl@0: aMetrics.SetAscent(CBitmapFont::DoAscentInPixels()); sl@0: aMetrics.SetDescent(aMetrics.Size() - aMetrics.Ascent()); sl@0: aMetrics.SetMaxHeight(aMetrics.Ascent()); sl@0: aMetrics.SetMaxDepth(aMetrics.Descent()); sl@0: aMetrics.SetMaxWidth(CBitmapFont::DoMaxCharWidthInPixels()); sl@0: } sl@0: } sl@0: sl@0: sl@0: /** Gets the open font typeface attributes if possible. sl@0: sl@0: At present no attempt is made to sythesize these attributes for bitmap fonts sl@0: (CFontBitmaps). sl@0: sl@0: @param aAttrib On return, the open font typeface attributes. sl@0: @return ETrue if successful; EFalse if not possible to get the open font typeface sl@0: attributes. */ sl@0: EXPORT_C TBool CBitmapFont::GetFaceAttrib(TOpenFontFaceAttrib& aAttrib) const sl@0: { sl@0: if (IsOpenFont()) sl@0: { sl@0: const TOpenFontFaceAttrib* a = OpenFont()->FaceAttrib(); sl@0: if (a) sl@0: { sl@0: aAttrib = *a; sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: /** Gets encoding if a bitmap font (a CFontBitmap) is used. sl@0: sl@0: @return Bitmap encoding value. */ sl@0: EXPORT_C TInt CBitmapFont::BitmapEncoding() const sl@0: { sl@0: if (IsOpenFont()) sl@0: return 0; sl@0: else sl@0: return FontBitmap()->iBitmapEncoding; sl@0: } sl@0: sl@0: /** Gets whether the open or bitmap font has the specified character. sl@0: sl@0: @param aCode A character code. sl@0: @return ETrue if the font has the specified character; otherwise EFalse. */ sl@0: EXPORT_C TBool CBitmapFont::HasCharacterL(TInt aCode) const sl@0: { sl@0: if (IsOpenFont()) sl@0: return OpenFont()->HasCharacterL(aCode); sl@0: else sl@0: { sl@0: const TUint8* bytes; sl@0: FontBitmap()->CharacterMetrics(aCode,bytes); sl@0: return (bytes != NULL); sl@0: } sl@0: } sl@0: sl@0: /** Gets whether the specified character needs to be rasterised. sl@0: sl@0: False is returned if it is a bitmap font (a CFontBitmap) being used by the sl@0: bitmap font object (so no rasterization is required) or if is an open font sl@0: (a COpenFont) and the character has been rasterized. sl@0: sl@0: @param aSessionHandle A session handle for the open font system. sl@0: @param aCode A character code. sl@0: @return ETrue if the character needs to be rasterized; otherwise EFalse. */ sl@0: EXPORT_C TBool CBitmapFont::CharacterNeedsToBeRasterized(TInt aSessionHandle,TInt aCode) const sl@0: { sl@0: if (IsOpenFont()) sl@0: return OpenFont()->CharacterNeedsToBeRasterized(aSessionHandle,aCode); sl@0: else sl@0: return FALSE; // characters in bitmap fonts do not need to be rasterized sl@0: } sl@0: sl@0: /** Turns text into glyph codes and positions. sl@0: @param aText The Unicode text to shape plus context sl@0: @return The output shape header from the per-font cache, or 0 on failure. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C TShapeHeader* CBitmapFont::ShapeTextL(const TDesC16& aText, sl@0: TInt aSessionHandle, const TShapeMessageParameters& aParams) sl@0: { sl@0: TShapeHeader* shape = 0; sl@0: sl@0: if(IsOpenFont()) sl@0: { sl@0: // get the data in a CShaper::TInput for the shaper sl@0: CShaper::TInput input; sl@0: input.iText = &aText; sl@0: input.iStart = aParams.iStart; sl@0: input.iEnd = aParams.iEnd; sl@0: input.iScript= aParams.iScript; sl@0: input.iLanguage = aParams.iLanguage; sl@0: input.iMaximumAdvance = KMaxTInt; sl@0: input.iFlags = 0; sl@0: input.iSessionHandle = aSessionHandle; sl@0: input.iReserved1 = 0; sl@0: sl@0: TFontShapeFunctionParameters params; sl@0: params.iEnd = input.iEnd; sl@0: params.iLanguage = input.iLanguage; sl@0: params.iScript = input.iScript; sl@0: params.iStart = input.iStart; sl@0: params.iText = input.iText; sl@0: sl@0: COpenFont* openFont = OpenFont(); sl@0: sl@0: //if already exist just increase the reference count for that session sl@0: shape = openFont->GetShapedData(aSessionHandle,¶ms); sl@0: sl@0: if (shape == NULL) sl@0: { sl@0: if (!openFont->HasShaper() sl@0: || (openFont->HasShaper() && ( sl@0: (TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetScript)) != input.iScript sl@0: || (TUint32)(openFont->GetShaper()->ExtendedInterface(KUidShaperGetLang)) != input.iLanguage))) sl@0: { // Install the shaper sl@0: openFont->DeleteShaper(); sl@0: InstallOpenFontShaper(openFont, input); sl@0: } sl@0: sl@0: if (openFont->HasShaper()) sl@0: { sl@0: TInt error = openFont->GetShaper()->ShapeText(shape, input, iHeap); sl@0: if (error != KErrNone) sl@0: User::Leave(error); sl@0: sl@0: // Put this into the session cache sl@0: TShapeHeader* cached_header = openFont->InsertShapedDataIntoCache(aSessionHandle,¶ms, shape); sl@0: if (!cached_header) sl@0: User::LeaveNoMemory(); sl@0: iHeap->Free(shape); sl@0: shape = cached_header; sl@0: } sl@0: } sl@0: } sl@0: return shape; sl@0: } sl@0: sl@0: sl@0: void CBitmapFont::InstallOpenFontShaper(COpenFont* aOpenFont, CShaper::TInput& aShaperInput) sl@0: { sl@0: CShaper* shaper = NULL; sl@0: const CArrayPtrFlat* shaperFactoryList = aOpenFont->File()->GetFontStore()->ShaperFactoryList(); sl@0: sl@0: TInt factoryCount = shaperFactoryList->Count(); sl@0: for (TInt index = 0; index < factoryCount; index++) sl@0: { sl@0: TRAPD(err, shaper = (*shaperFactoryList)[index]->NewShaperL(this, sl@0: aShaperInput.iScript, aShaperInput.iLanguage, iHeap)); sl@0: if (err == KErrNone) sl@0: { sl@0: aOpenFont->SetShaper(shaper); sl@0: OstTrace0( TRACE_IMPORTANT, CBITMAPFONT_INSTALLOPENFONTSHAPER, "A shaper is installed" ); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: /** Frees the memory taken up as a result of shaping sl@0: @internalTechnology */ sl@0: EXPORT_C void CBitmapFont::DeleteShape(TInt aSessionHandle,TShapeHeader* aHeader) sl@0: { sl@0: //safe to assume aHeader is never NULL? sl@0: if (IsOpenFont()) sl@0: { sl@0: //we just need to decrease the reference count, no deletion here sl@0: //as the entry in cache can still be reused by other client sl@0: //only in the case where the memory is full, the freeing will sl@0: //delete any cache entry that is not referenced at all sl@0: TInt ret=OpenFont()->DecrementCachedRefCount(aSessionHandle,aHeader); sl@0: //panic in debug mode if trying to delete something that is not there. sl@0: if ((ret != KErrNone) && (ret != KErrNotFound)) sl@0: { sl@0: OstTrace1( TRACE_FATAL, CBITMAPFONT_DELETESHAPE, "OpenFont()->DecrementCachedRefCount() return %d, Invariant", ret); sl@0: __ASSERT_DEBUG(0, User::Invariant()); sl@0: } sl@0: } sl@0: } sl@0: sl@0: EXPORT_C void CBitmapFont::operator delete(TAny *aThis) sl@0: { sl@0: if (((CBitmapFont *)aThis)->iHeap) sl@0: ((CBitmapFont *)aThis)->iHeap->Free(aThis); sl@0: } sl@0: sl@0: TInt CBitmapFont::Width(TInt aNum) const sl@0: { sl@0: TInt widthfactor=iAlgStyle.WidthFactor(); sl@0: return ((widthfactor==1)? aNum: aNum*widthfactor); sl@0: } sl@0: sl@0: TInt CBitmapFont::Height(TInt aNum) const sl@0: { sl@0: TInt heightfactor=iAlgStyle.HeightFactor(); sl@0: return ((heightfactor==1)? aNum: aNum*heightfactor); sl@0: } sl@0: sl@0: CFontBitmap* CBitmapFont::FontBitmap() const sl@0: /** This member is private and not intended for use. */ sl@0: { sl@0: if (IsOpenFont()) sl@0: { sl@0: OstTrace0( TRACE_FATAL, CBITMAPFONT_FONTBITMAP, "Panic(EFntTypefaceHasNoFontBitmaps)" ); sl@0: __ASSERT_ALWAYS(0, Panic(EFntTypefaceHasNoFontBitmaps)); sl@0: } sl@0: if(iFontBitmapOffset) sl@0: return reinterpret_cast(reinterpret_cast(this)+iFontBitmapOffset); sl@0: else sl@0: return NULL; sl@0: } sl@0: sl@0: /** Gets a font table. sl@0: @param aTag: Input. The name of the font table. sl@0: @param aTableContent: Output. To return the address of the table content. sl@0: @param aLength: Output. To return the length (in bytes) of the table. sl@0: @param aSessionHandle: Input. A handle to the session requesting this table. sl@0: @return KErrNone on success, specific error code on failure. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::GetFontTable(TUint32 aTag, TAny *&aTableContent, sl@0: TInt &aLength, TInt aSessionHandle) sl@0: { sl@0: COpenFont *fontPtr = NULL; sl@0: if (IsOpenFont()) sl@0: fontPtr = OpenFont(); sl@0: else sl@0: return KErrNotSupported; sl@0: sl@0: // try to find it in cache. sl@0: CFontStore *fntStore = fontPtr->File()->GetFontStore(); sl@0: TUid fileUid = fontPtr->File()->Uid(); sl@0: TInt ret = fntStore->FindFontTableInCache(fileUid, aTag, aTableContent, aLength); sl@0: if (KErrNone == ret) sl@0: { sl@0: ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle); sl@0: return ret; sl@0: } sl@0: sl@0: // font table not found in cache. sl@0: ret = fontPtr->GetFontTable(aTag, aTableContent, aLength); sl@0: if (KErrNone == ret) sl@0: { sl@0: ret = fntStore->CacheFontTable(fileUid, aTag, aTableContent, aLength); sl@0: if (KErrNone == ret) sl@0: { sl@0: ret = fntStore->IncFontTableRefCount(fileUid, aTag, aSessionHandle); sl@0: } sl@0: else sl@0: { sl@0: aTableContent = NULL; sl@0: } sl@0: } sl@0: sl@0: return ret; sl@0: } sl@0: sl@0: /** Release a font table. Decrement its reference count. Remove from cache if sl@0: * reference decreases to zero. sl@0: @param aTag: Input. The name of the font table to be released. sl@0: @param aSessionHandle: Input. Handle to the session releasing this table. sl@0: @return KErrNone on success, specific error code on failure. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C void CBitmapFont::ReleaseFontTable(TUint32 aTag, sl@0: TInt aSessionHandle) sl@0: { sl@0: COpenFont *fontPtr = NULL; sl@0: if (IsOpenFont()) sl@0: fontPtr = OpenFont(); sl@0: else sl@0: return; sl@0: sl@0: CFontStore *fntStore = fontPtr->File()->GetFontStore(); sl@0: TUid fileUid = fontPtr->File()->Uid(); sl@0: fntStore->ReleaseFontTable(fileUid, aTag, aSessionHandle); sl@0: } sl@0: sl@0: sl@0: /** Release a number of glyph outlines. Decrement their reference count. sl@0: * Remove it from cache if reference count decreases to zero. sl@0: @param aCount: Input. Number of outlines to be released. sl@0: @param aCodes: Input. An array of codes. Its interpretation depends on the parameter sl@0: 'aIsGlyphId' (see below). sl@0: @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCodes' is an array of glyph ID's. sl@0: When aIsGlyphId==EFalse, 'aCodes' is an array of Unicode values. sl@0: @param aHinted: Input. To indicate if the outlines are hinted or unhinted. sl@0: @param aSessionHandle: Input. Handle to the session releasing the outlines. sl@0: @return KErrNone on success, specific error code on failure. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C void CBitmapFont::ReleaseGlyphOutlines(TInt aCount, const TUint *aCodes, sl@0: TBool aHinted, TInt aSessionHandle) sl@0: { sl@0: COpenFont *fontPtr = NULL; sl@0: if (IsOpenFont()) sl@0: fontPtr = OpenFont(); sl@0: else sl@0: return; sl@0: sl@0: CFontStore *fontStore = fontPtr->File()->GetFontStore(); sl@0: sl@0: for (TInt i = 0; i < aCount; ++i) sl@0: { sl@0: if (aHinted) sl@0: { sl@0: THintedOutlineId outlineId(fontPtr, aCodes[i]); sl@0: fontStore->ReleaseHintedOutline(outlineId, aSessionHandle); sl@0: } sl@0: else sl@0: { sl@0: TInt faceId = fontPtr->FaceIndex(); sl@0: TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCodes[i]); sl@0: fontStore->ReleaseUnhintedOutline(outlineId, aSessionHandle); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** Gets a font table. sl@0: @param aCode: Input. An glyph code. Its interpretation depends on the parameter sl@0: 'aIsGlyphId' (see below). sl@0: @param aIsGlyphId: Input. When aIsGlyphId==ETrue, 'aCode' is a glyph ID. sl@0: When aIsGlyphId==EFalse, 'aCode' is a Unicode values. sl@0: @param aHinted: Input. To indicate if hinted or unhinted outline is needed. sl@0: @param aOutline: Output. A 'void*' pointer, pointing to the outline in memory. sl@0: @param aLength: Output. A TInt, recording the lenght (in bytes) of the outline. sl@0: @param aSessionHandle: Input. Handle to the session requesting this outline. sl@0: @return KErrNone on success, specific error code on failure. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::GetGlyphOutline(TUint aCode, sl@0: TBool aHinted, TAny *&aOutline, TInt &aLength, TInt aSessionHandle) sl@0: { sl@0: COpenFont *fontPtr = NULL; sl@0: if (IsOpenFont()) sl@0: fontPtr = OpenFont(); sl@0: else sl@0: return KErrNotSupported; sl@0: sl@0: CFontStore *fontStore = fontPtr->File()->GetFontStore(); sl@0: TAny *outlineData = NULL; sl@0: TInt len = KErrGeneral; sl@0: TInt ret = KErrNone; sl@0: if (!aHinted) sl@0: { sl@0: TInt faceId = fontPtr->FaceIndex(); sl@0: TUnhintedOutlineId outlineId(fontPtr->File()->Uid(), faceId, aCode); sl@0: ret = fontStore->FindUnhintedOutlineInCache(outlineId, outlineData, len); sl@0: if (KErrNotFound == ret) sl@0: { sl@0: TAny* tmpOutline = 0; sl@0: TInt tmpLen = 0; sl@0: ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen); sl@0: if (KErrNone == ret) sl@0: { sl@0: fontStore->CacheUnhintedOutline(outlineId, sl@0: tmpOutline, (TInt)tmpLen, outlineData, len); sl@0: } sl@0: User::Free(tmpOutline); sl@0: } sl@0: if (KErrNone == ret) sl@0: { sl@0: fontStore->IncreaseUnhintedOutlineRefCount(outlineId, aSessionHandle); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: THintedOutlineId outlineId(fontPtr, aCode); sl@0: ret = fontStore->FindHintedOutlineInCache(outlineId, outlineData, len); sl@0: if (KErrNotFound == ret) sl@0: { sl@0: TAny* tmpOutline = 0; sl@0: TInt tmpLen = 0; sl@0: ret = fontPtr->GetGlyphOutline(aCode, aHinted, tmpOutline, tmpLen); sl@0: if (KErrNone == ret) sl@0: { sl@0: fontStore->CacheHintedOutline(outlineId, sl@0: tmpOutline, (TInt)tmpLen, outlineData, len); sl@0: } sl@0: User::Free(tmpOutline); sl@0: } sl@0: if (KErrNone == ret) sl@0: { sl@0: fontStore->IncreaseHintedOutlineRefCount(outlineId, aSessionHandle); sl@0: } sl@0: } sl@0: sl@0: aOutline = outlineData; sl@0: aLength = len; sl@0: return KErrNone; sl@0: } sl@0: sl@0: EXPORT_C TUint32 CBitmapFont::UniqueFontId() sl@0: { sl@0: return iUniqueFontId; sl@0: } sl@0: sl@0: void CBitmapFont::SetUniqueFontId(TUint32 aUniqueFontId) sl@0: { sl@0: iUniqueFontId = aUniqueFontId; sl@0: } sl@0: sl@0: /** API extension system that enables the caller to access a particular API sl@0: extension function. As an overload of this function in a derived class sl@0: it calls its immediate parent implementation for any extension function Uid sl@0: that it does not recognize and handle. sl@0: @param aInterfaceId UID of the required extension function sl@0: @param aParam Pointer to an arbitrary parameter block that can be used to sl@0: provide and/or return information to/from the particular extension function, sl@0: defaults to NULL. sl@0: @return Integer return value from extension function sl@0: @internalTechnology sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CBitmapFont::DoExtendedFunction(TUid aFunctionId, TAny* aParam) const sl@0: { sl@0: if (KFontCapitalAscent == aFunctionId) sl@0: { sl@0: return Height(IsOpenFont() ? OpenFont()->FontCapitalAscent() : FontBitmap()->FontCapitalAscent()); sl@0: } sl@0: else if (KFontMaxAscent == aFunctionId) sl@0: { sl@0: return Height(IsOpenFont() ? OpenFont()->FontMaxAscent() : FontBitmap()->FontMaxAscent()); sl@0: } sl@0: else if (KFontStandardDescent == aFunctionId) sl@0: { sl@0: return Height(IsOpenFont() ? OpenFont()->FontStandardDescent() : FontBitmap()->FontStandardDescent()); sl@0: } sl@0: else if (KFontMaxDescent == aFunctionId) sl@0: { sl@0: return Height(IsOpenFont() ? OpenFont()->FontMaxDescent() : FontBitmap()->FontMaxDescent()); sl@0: } sl@0: else if (KFontLineGap == aFunctionId) sl@0: { sl@0: return Height(IsOpenFont() ? OpenFont()->FontLineGap() : FontBitmap()->FontLineGap()); sl@0: } sl@0: sl@0: return CFont::DoExtendedFunction(aFunctionId, aParam); sl@0: } sl@0: sl@0: sl@0: CFontTableCacheItem::CFontTableCacheItem(TUid &aFileUid, const TUint32 aTag, sl@0: TInt aOffset, TInt aLength): iFileUid(aFileUid), iTag(aTag), sl@0: iOffset(aOffset), iLength(aLength) sl@0: { sl@0: // a null constructor sl@0: } sl@0: sl@0: CFontTableCacheItem::~CFontTableCacheItem() sl@0: { sl@0: iUsers.ResetAndDestroy(); sl@0: iUsers.Close(); sl@0: } sl@0: sl@0: TBool CFontTableCacheItem::HasOutstandingRefCount() sl@0: { sl@0: TInt count = iUsers.Count(); sl@0: for (TInt j = 0; j < count; ++j) sl@0: { sl@0: if (iUsers[j]->iRefCount > 0) sl@0: { sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: TInt CFontTableCacheItem::FindUser(TInt aSessionHandle, TInt *id) sl@0: { sl@0: TInt len = iUsers.Count(); sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: if (aSessionHandle == iUsers[i]->iSessionHandle) sl@0: { sl@0: *id = i; sl@0: return KErrNone; sl@0: } sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt CFontTableCacheItem::DecRefCount(TInt aSessionHandle) sl@0: { sl@0: TInt id = 0; sl@0: TInt ret = FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: iUsers[id]->iRefCount--; sl@0: if (0 == iUsers[id]->iRefCount) sl@0: { sl@0: delete iUsers[id]; sl@0: iUsers.Remove(id); sl@0: } sl@0: return iUsers.Count(); sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt CFontTableCacheItem::IncRefCount(TInt aSessionHandle) sl@0: { sl@0: TInt id = 0; sl@0: TInt ret = FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: iUsers[id]->iRefCount++; sl@0: } sl@0: else sl@0: { sl@0: TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1); sl@0: if (NULL != newUser) sl@0: { sl@0: TRAP(ret, iUsers.AppendL(newUser)); sl@0: } sl@0: else sl@0: { sl@0: ret = KErrNoMemory; sl@0: } sl@0: //coverity[leaked_storage] sl@0: // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount(). sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: TInt CFontTableCache::Append(TUid aFileUid, TUint32 aTag, sl@0: TAny *&aContent, TInt aLength) sl@0: { sl@0: TInt ret = 0; sl@0: if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem) sl@0: { sl@0: RDebug::Printf("Table/Glyph cache full. Unable to add new item."); sl@0: return KErrNoMemory; sl@0: } sl@0: // make a copy of the table content on the shared heap. sl@0: TAny *sharedCopy = iHeap->Alloc(aLength); sl@0: if (NULL == sharedCopy) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: Mem::Copy(sharedCopy, aContent, aLength); sl@0: sl@0: CFontTableCacheItem *newItem = NULL; sl@0: TInt offset = PointerToOffset(sharedCopy, iHeap->Base()); sl@0: TRAP(ret, newItem = new(ELeave) CFontTableCacheItem(aFileUid, aTag, offset, aLength)); sl@0: if (KErrNone != ret) sl@0: { sl@0: iHeap->Free(sharedCopy); sl@0: return ret; sl@0: } sl@0: sl@0: TRAP(ret, iCacheItems.AppendL(newItem)); sl@0: if (KErrNone == ret) sl@0: { sl@0: // do not free 'aContent', because the mem is managed by sl@0: // rasterizer cache. sl@0: aContent = sharedCopy; sl@0: iCacheMemMon.Inc(aLength); sl@0: } sl@0: else sl@0: { sl@0: iHeap->Free(sharedCopy); sl@0: } sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: return ret; sl@0: } sl@0: sl@0: TInt CFontTableCache::Find(TUid aFileUid, TUint32 aTag, TAny *&aContent, sl@0: TInt &aLength, TInt *id) sl@0: { sl@0: *id = KErrNotFound; sl@0: TInt len = iCacheItems.Count(); sl@0: sl@0: TInt ret = KErrNotFound; sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: CFontTableCacheItem *item = iCacheItems[i]; sl@0: if (item->iFileUid == aFileUid && item->iTag == aTag) sl@0: { sl@0: aContent = OffsetToPointer(item->iOffset, iHeap->Base()); sl@0: aLength = item->iLength; sl@0: *id = i; sl@0: ret = KErrNone; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: return ret; sl@0: } sl@0: sl@0: CFontTableCache::CFontTableCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): sl@0: iCacheMemMon(aMon), iHeap(aHeap) sl@0: { sl@0: // null constructor sl@0: } sl@0: sl@0: CFontTableCache::~CFontTableCache() sl@0: { sl@0: for (TInt i = 0; i < iCacheItems.Count(); ++i) sl@0: { sl@0: iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base())); sl@0: } sl@0: iCacheItems.ResetAndDestroy(); sl@0: iCacheItems.Close(); sl@0: } sl@0: sl@0: TInt CFontTableCache::IncRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle) sl@0: { sl@0: TAny *outline = NULL; sl@0: TInt len = 0; sl@0: TInt id = 0; sl@0: sl@0: TInt ret = Find(aFileUid, aTag, outline, len, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: ret = iCacheItems[id]->IncRefCount(aSessionHandle); sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: return ret; sl@0: } sl@0: sl@0: TInt CFontTableCache::DecRefCount(TUid aFileUid, TUint32 aTag, TInt aSessionHandle) sl@0: { sl@0: TAny *outline = NULL; sl@0: TInt len = 0; sl@0: TInt id = 0; sl@0: sl@0: TInt ret = Find(aFileUid, aTag, outline, len, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: TInt numUsers = iCacheItems[id]->DecRefCount(aSessionHandle); sl@0: if (0 == numUsers) sl@0: { sl@0: // There is no outstanding reference to the cache item. sl@0: iHeap->Free(outline); sl@0: iCacheMemMon.Dec(len); sl@0: delete (iCacheItems[id]); sl@0: iCacheItems.Remove(id); sl@0: } sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: return ret; sl@0: } sl@0: sl@0: TBool CFontTableCache::HasOutstandingRefCount() sl@0: { sl@0: TInt len = iCacheItems.Count(); sl@0: sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: if (iCacheItems[i]->HasOutstandingRefCount()) sl@0: { sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: TBool CFontTableCache::HasOutstandingRefCountWithUid(TUid aFileUid) sl@0: { sl@0: TInt len = iCacheItems.Count(); sl@0: sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: if (iCacheItems[i]->iFileUid == aFileUid) sl@0: { sl@0: if (iCacheItems[i]->HasOutstandingRefCount()) sl@0: { sl@0: return ETrue; sl@0: } sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: void CFontTableCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *) sl@0: { sl@0: // In CFontStore::RemoveFile(), a font file is not allowed to be removed if sl@0: // there are outstanding ref counts on any table in it. If that check passed sl@0: // and this function is called, there shall be no cache item for that file. sl@0: sl@0: // Currently a cache item having a refcount of 0 is removed immediately. sl@0: // If this strategy is changed in the future, we may need to do some sl@0: // cleanup here. sl@0: } sl@0: sl@0: void CFontTableCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle) sl@0: { sl@0: TInt len = iCacheItems.Count(); sl@0: sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: TInt id = -1; sl@0: if (KErrNone == iCacheItems[i]->FindUser(aSessionHandle, &id)) sl@0: { sl@0: iCacheItems[i]->iUsers.Remove(id); sl@0: if (iCacheItems[i]->iUsers.Count() == 0) sl@0: { sl@0: iHeap->Free(OffsetToPointer(iCacheItems[i]->iOffset, iHeap->Base())); sl@0: iCacheMemMon.Dec(iCacheItems[i]->iLength); sl@0: delete iCacheItems[i]; sl@0: iCacheItems.Remove(i); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: #ifdef _DEBUG sl@0: TInt CFontTableCache::GetCacheState(const char *func) sl@0: { sl@0: RDebug::Printf("%s called from %s: ", __func__, func); sl@0: TBuf<256> buf; sl@0: sl@0: int len = iCacheItems.Count(); sl@0: int numTables = 0, numSessions = 0, totalRef = 0; sl@0: buf.Append(_L("Table cache: ")); sl@0: for (int i = 0; i < len; ++i) sl@0: { sl@0: ++numTables; sl@0: TInt abc = iCacheItems[i]->iUsers.Count(); sl@0: numSessions += abc; sl@0: for (int j = 0; j < abc; ++j) sl@0: { sl@0: totalRef += iCacheItems[i]->iUsers[j]->iRefCount; sl@0: } sl@0: } sl@0: if (0 == iCacheItems.Count()) sl@0: { sl@0: buf.Append(_L("cache empty. ")); sl@0: } sl@0: else sl@0: { sl@0: buf.AppendFormat(_L("%d tables referenced by %d sessions, total ref count %d"), sl@0: numTables, numSessions, totalRef); sl@0: } sl@0: RDebug::RawPrint(buf); sl@0: return 0; sl@0: } sl@0: #endif sl@0: sl@0: sl@0: sl@0: TInt COutlineCacheItem::FindUser(TInt aSessionHandle, TInt *id) sl@0: { sl@0: TInt len = iUsers.Count(); sl@0: for (TInt i = 0; i < len; ++i) sl@0: { sl@0: if (aSessionHandle == iUsers[i]->iSessionHandle) sl@0: { sl@0: *id = i; sl@0: return KErrNone; sl@0: } sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: COutlineCacheItem::~COutlineCacheItem() sl@0: { sl@0: iUsers.ResetAndDestroy(); sl@0: } sl@0: sl@0: COutlineCacheItem::COutlineCacheItem(TInt aOffset, TInt aLength): sl@0: iOffset(aOffset), iLength(aLength) sl@0: { sl@0: // a null constructor. sl@0: } sl@0: sl@0: TInt COutlineCacheItem::DecRefCount(TInt aSessionHandle) sl@0: { sl@0: TInt id = 0; sl@0: TInt ret = FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: iUsers[id]->iRefCount--; sl@0: if (0 == iUsers[id]->iRefCount) sl@0: { sl@0: delete iUsers[id]; sl@0: iUsers.Remove(id); sl@0: } sl@0: return iUsers.Count(); sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: TInt COutlineCacheItem::IncRefCount(TInt aSessionHandle) sl@0: { sl@0: TInt id = 0; sl@0: TInt ret = FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: iUsers[id]->iRefCount++; sl@0: } sl@0: else sl@0: { sl@0: TCacheUserInfo *newUser = new TCacheUserInfo(aSessionHandle, 1); sl@0: if (NULL != newUser) sl@0: { sl@0: TRAP(ret, iUsers.AppendL(newUser)); sl@0: } sl@0: else sl@0: { sl@0: ret = KErrNoMemory; sl@0: } sl@0: //coverity[leaked_storage] sl@0: // The 'newUser' is kept in iUsers. It will be deleted in DecRefCount(). sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: TInt CUnhintedOutlineCache::GetCacheState(const char *func) sl@0: { sl@0: RDebug::Printf("%s called from %s: ", __func__, func); sl@0: int numSessions = 0, totalRef = 0; sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: int len = (*data)->iUsers.Count(); sl@0: numSessions += len; sl@0: for (int j = 0; j < len; ++j) sl@0: { sl@0: totalRef += (*data)->iUsers[j]->iRefCount; sl@0: } sl@0: it.NextValue(); sl@0: } sl@0: sl@0: TBuf<256> buf; sl@0: buf.Append(_L("Unhinted outline cache: ")); sl@0: TInt numItems = iItemIdMap.Count(); sl@0: if (0 == numItems) sl@0: { sl@0: buf.Append(_L("empty. ")); sl@0: } sl@0: else sl@0: { sl@0: buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"), sl@0: numItems, numSessions, totalRef); sl@0: } sl@0: sl@0: RDebug::RawPrint(buf); sl@0: sl@0: return 0; sl@0: } sl@0: #endif sl@0: sl@0: CUnhintedOutlineCache::CUnhintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): sl@0: iCacheMemMon(aMon), iHeap(aHeap), sl@0: iItemIdMap(THashFunction32(CUnhintedOutlineCache::IdHash), sl@0: TIdentityRelation(CUnhintedOutlineCache::IdIdentity)) sl@0: { sl@0: sl@0: } sl@0: sl@0: CUnhintedOutlineCache::~CUnhintedOutlineCache() sl@0: { sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: const TUnhintedOutlineId *outlineId = it.CurrentKey(); sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: sl@0: // loop body here! sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: delete (*data); sl@0: iItemIdMap.Remove(*outlineId); sl@0: // end loop body sl@0: sl@0: it.NextValue(); sl@0: } sl@0: return; sl@0: } sl@0: sl@0: sl@0: TInt CUnhintedOutlineCache::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile) sl@0: { sl@0: TUid fileUid = aFontFile->Uid(); sl@0: sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: const TUnhintedOutlineId *outlineId = it.CurrentKey(); sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: sl@0: // loop body here! sl@0: if (outlineId->iFileUid == fileUid) sl@0: { sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: iCacheMemMon.Dec((*data)->iLength); sl@0: delete (*data); sl@0: iItemIdMap.Remove(*outlineId); sl@0: } sl@0: // end loop body sl@0: sl@0: it.NextValue(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CUnhintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle) sl@0: { sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: const TUnhintedOutlineId *outlineId = it.CurrentKey(); sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: sl@0: // loop body here! sl@0: TInt id = 0; sl@0: TInt ret = (*data)->FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: delete (*data)->iUsers[id]; sl@0: (*data)->iUsers.Remove(id); sl@0: if (0 == (*data)->iUsers.Count()) sl@0: { sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: iCacheMemMon.Dec((*data)->iLength); sl@0: delete (*data); sl@0: iItemIdMap.Remove(*outlineId); sl@0: } sl@0: } sl@0: // end loop body sl@0: sl@0: it.NextValue(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt CUnhintedOutlineCache::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, sl@0: TAny* const aData, const TInt aLength, TAny *&aOutline, TInt &aLen) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem) sl@0: { sl@0: RDebug::Printf("Table/Glyph cache full. Unable to add new item."); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: aLen = KErrGeneral; sl@0: TInt ret1= KErrNone; sl@0: sl@0: // make a copy of the outline data on the shared heap. sl@0: TAny *sharedCopy = iHeap->Alloc(aLength); sl@0: if (NULL == sharedCopy) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: Mem::Copy(sharedCopy, aData, aLength); sl@0: sl@0: COutlineCacheItem *newItem = NULL; sl@0: TInt offset = PointerToOffset(sharedCopy, iHeap->Base()); sl@0: TRAP(ret1, newItem = new(ELeave) COutlineCacheItem(offset, aLength)); sl@0: if (KErrNone != ret1) sl@0: { sl@0: iHeap->Free(sharedCopy); sl@0: sharedCopy = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret1, iItemIdMap.InsertL(aOutlineId, newItem)); sl@0: if (KErrNone != ret1) sl@0: { sl@0: delete newItem; sl@0: iHeap->Free(sharedCopy); sl@0: sharedCopy = NULL; sl@0: } sl@0: else sl@0: { sl@0: iCacheMemMon.Inc(aLength); sl@0: aLen = aLength; sl@0: } sl@0: } sl@0: aOutline = sharedCopy; sl@0: return ret1; sl@0: } sl@0: sl@0: TInt CUnhintedOutlineCache::IncRefCount(const TUnhintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); sl@0: if (NULL != ret) sl@0: { sl@0: (*ret)->IncRefCount(aSessionHandle); sl@0: } sl@0: return (NULL==ret?KErrNotFound:KErrNone); sl@0: } sl@0: sl@0: TInt CUnhintedOutlineCache::DecRefCount(const TUnhintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); sl@0: if (NULL != ret) sl@0: { sl@0: TInt numUsers = (*ret)->DecRefCount(aSessionHandle); sl@0: if (0 == numUsers) sl@0: { sl@0: // There is no outstanding reference to the cache item. sl@0: iHeap->Free(OffsetToPointer((*ret)->iOffset, iHeap->Base())); sl@0: iCacheMemMon.Dec((*ret)->iLength); sl@0: delete (*ret); sl@0: iItemIdMap.Remove(aOutlineId); sl@0: } sl@0: } sl@0: return (NULL==ret?KErrNotFound:KErrNone); sl@0: } sl@0: sl@0: TInt CUnhintedOutlineCache::Find(const TUnhintedOutlineId &aOutlineId, TAny *&aData, sl@0: TInt &aLength) sl@0: { sl@0: COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); sl@0: TInt ret2 = KErrNone; sl@0: if (NULL != ret) sl@0: { sl@0: aData = OffsetToPointer((*ret)->iOffset, iHeap->Base()); sl@0: aLength = (*ret)->iLength; sl@0: } sl@0: else sl@0: { sl@0: ret2 = KErrNotFound; sl@0: } sl@0: return ret2; sl@0: } sl@0: sl@0: sl@0: TUint32 CUnhintedOutlineCache::IdHash(const TUnhintedOutlineId &outlineId) sl@0: { sl@0: // The hash value: sl@0: // bits 0-15: glyph id; sl@0: // bits 16-23: lower 8 bit of font file uid sl@0: // bits 24-27: lower 4 bit of the face index sl@0: // bit 28: 'isGlyphId' sl@0: TUint32 ret = 0; sl@0: ret |= (outlineId.iId & KOutlineGlyphIdHashMask); sl@0: ret |= (KOutlineFileUidHashMask & (outlineId.iFileUid.iUid << 16)); sl@0: ret |= (KOutlineFaceIndexHashMask & (outlineId.iFaceIndex << 24)); sl@0: ret = (ret % 701); sl@0: return ret; sl@0: } sl@0: sl@0: TBool CUnhintedOutlineCache::IdIdentity(const TUnhintedOutlineId &id1, const TUnhintedOutlineId &id2) sl@0: { sl@0: return id1.iId == id2.iId && id1.iFaceIndex == id2.iFaceIndex && sl@0: id1.iFileUid == id2.iFileUid; sl@0: } sl@0: sl@0: // hinted outline cache sl@0: #ifdef _DEBUG sl@0: TInt CHintedOutlineCache::GetCacheState(const char *func) sl@0: { sl@0: RDebug::Printf("%s called from %s: ", __func__, func); sl@0: int numSessions = 0, totalRef = 0; sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: int len = (*data)->iUsers.Count(); sl@0: numSessions += len; sl@0: for (int j = 0; j < len; ++j) sl@0: { sl@0: totalRef += (*data)->iUsers[j]->iRefCount; sl@0: } sl@0: it.NextValue(); sl@0: } sl@0: sl@0: TBuf<256> buf; sl@0: buf.Append(_L("Hinted outline cache: ")); sl@0: TInt numItems = iItemIdMap.Count(); sl@0: if (0 == numItems) sl@0: { sl@0: buf.Append(_L("empty. ")); sl@0: } sl@0: else sl@0: { sl@0: buf.AppendFormat(_L("%d glyphs, %d sessions, total refcount %d"), sl@0: numItems, numSessions, totalRef); sl@0: } sl@0: sl@0: RDebug::RawPrint(buf); sl@0: sl@0: return 0; sl@0: } sl@0: #endif sl@0: sl@0: TInt CHintedOutlineCache::CleanupCacheOnOpenFontRemoval(COpenFont *aFont) sl@0: { sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: const THintedOutlineId *outlineId = it.CurrentKey(); sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: sl@0: // loop body here! sl@0: if (outlineId->iFont == aFont) sl@0: { sl@0: iCacheMemMon.Dec((*data)->iLength); sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: delete (*data); sl@0: iItemIdMap.Remove(*outlineId); sl@0: } sl@0: // end loop body sl@0: sl@0: it.NextValue(); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt CHintedOutlineCache::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle) sl@0: { sl@0: THashMapIter it(iItemIdMap); sl@0: it.NextValue(); sl@0: while (it.CurrentValue()) sl@0: { sl@0: const THintedOutlineId *outlineId = it.CurrentKey(); sl@0: COutlineCacheItem **data = it.CurrentValue(); sl@0: sl@0: // loop body here! sl@0: TInt id = 0; sl@0: TInt ret = (*data)->FindUser(aSessionHandle, &id); sl@0: if (KErrNone == ret) sl@0: { sl@0: delete (*data)->iUsers[id]; sl@0: (*data)->iUsers.Remove(id); sl@0: if (0 == (*data)->iUsers.Count()) sl@0: { sl@0: iCacheMemMon.Dec((*data)->iLength); sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: delete (*data); sl@0: iItemIdMap.Remove(*outlineId); sl@0: } sl@0: } sl@0: // end loop body sl@0: sl@0: it.NextValue(); sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: CHintedOutlineCache::CHintedOutlineCache(RHeap *aHeap, TFontTableGlyphOutlineCacheMemMonitor &aMon): sl@0: iCacheMemMon(aMon), iHeap(aHeap), sl@0: iItemIdMap(THashFunction32(CHintedOutlineCache::IdHash), sl@0: TIdentityRelation(CHintedOutlineCache::IdIdentity)) sl@0: { sl@0: // a null constructor sl@0: } sl@0: sl@0: TInt CHintedOutlineCache::CacheHintedOutline(const THintedOutlineId &aOutlineId, sl@0: TAny* aData, TInt aLength, TAny *&aOutline, TInt &aLen) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: if ((TUint32)iCacheMemMon.GetMemUsage() >= KFontTable_GlyphOutline_CacheMaxMem) sl@0: { sl@0: RDebug::Printf("Table/Glyph cache full. Unable to add new item."); sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: aLen = KErrGeneral; sl@0: TInt ret = KErrNone; sl@0: // make a copy of the outline data on the shared heap. sl@0: TAny *sharedCopy = iHeap->Alloc(aLength); sl@0: if (NULL == sharedCopy) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: Mem::Copy(sharedCopy, aData, aLength); sl@0: sl@0: COutlineCacheItem *newItem = NULL; sl@0: TInt offset = PointerToOffset(sharedCopy, iHeap->Base()); sl@0: TRAP(ret, newItem = new(ELeave) COutlineCacheItem(offset, aLength)); sl@0: if (KErrNone != ret) sl@0: { sl@0: iHeap->Free(sharedCopy); sl@0: sharedCopy = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, iItemIdMap.InsertL(aOutlineId, newItem)); sl@0: if (KErrNone != ret) sl@0: { sl@0: delete newItem; sl@0: iHeap->Free(sharedCopy); sl@0: sharedCopy = NULL; sl@0: } sl@0: else sl@0: { sl@0: iCacheMemMon.Inc(aLength); sl@0: aLen = aLength; sl@0: } sl@0: } sl@0: aOutline = sharedCopy; sl@0: return ret; sl@0: } sl@0: sl@0: TInt CHintedOutlineCache::IncRefCount(const THintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: COutlineCacheItem **data = iItemIdMap.Find(aOutlineId); sl@0: if (NULL != data) sl@0: { sl@0: (*data)->IncRefCount(aSessionHandle); sl@0: } sl@0: return (NULL==data?KErrNotFound:KErrNone); sl@0: } sl@0: sl@0: TInt CHintedOutlineCache::DecRefCount(const THintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: #ifdef _DEBUG sl@0: GetCacheState(__func__); sl@0: #endif sl@0: COutlineCacheItem **data = iItemIdMap.Find(aOutlineId); sl@0: if (NULL != data) sl@0: { sl@0: TInt numUsers = (*data)->DecRefCount(aSessionHandle); sl@0: if (0 == numUsers) sl@0: { sl@0: // There is no outstanding reference to the cache item. sl@0: iCacheMemMon.Dec((*data)->iLength); sl@0: iHeap->Free(OffsetToPointer((*data)->iOffset, iHeap->Base())); sl@0: delete (*data); sl@0: iItemIdMap.Remove(aOutlineId); sl@0: } sl@0: } sl@0: return (NULL==data?KErrNotFound:KErrNone); sl@0: } sl@0: sl@0: TInt CHintedOutlineCache::Find(const THintedOutlineId &aOutlineId, sl@0: TAny *&aData, TInt &aLength) sl@0: { sl@0: COutlineCacheItem **ret = iItemIdMap.Find(aOutlineId); sl@0: TInt ret2 = KErrNone; sl@0: if (NULL != ret) sl@0: { sl@0: aData = OffsetToPointer((*ret)->iOffset, iHeap->Base()); sl@0: aLength = (*ret)->iLength; sl@0: } sl@0: else sl@0: { sl@0: ret2 = KErrNotFound; sl@0: } sl@0: return ret2; sl@0: } sl@0: sl@0: sl@0: TUint32 CHintedOutlineCache::IdHash(const THintedOutlineId &outlineId) sl@0: { sl@0: // The hash value: sl@0: // bits 0-15: the outline id sl@0: // bits 16-27: the lower 12 bits of the font pointer sl@0: // bit 28: 'isGlyphId' sl@0: sl@0: TUint32 ret = 0; sl@0: ret |= (KOutlineGlyphIdHashMask & outlineId.iId); sl@0: ret |= (KOutlineFontPtrHashMask & (((TUint32)outlineId.iFont) << 16)); sl@0: ret = ret % 701; sl@0: return ret; sl@0: } sl@0: sl@0: TBool CHintedOutlineCache::IdIdentity(const THintedOutlineId &id1, const THintedOutlineId &id2) sl@0: { sl@0: return id1.iId == id2.iId && id1.iFont == id2.iFont; sl@0: } sl@0: // hinted cache sl@0: sl@0: sl@0: CFontStore::CFontStore(RHeap* aHeap): sl@0: iKPixelWidthInTwips(KDefaultPixelWidthInTwips), sl@0: iKPixelHeightInTwips(KDefaultPixelHeightInTwips), sl@0: iFs(), sl@0: iHeap(aHeap), sl@0: iFontStoreFileList(KDefaultArrayGranularity), // list of EPOC Bitmap font files loaded sl@0: iTypefaceList(KDefaultArrayGranularity), sl@0: iFontBitmapList(KDefaultArrayGranularity), sl@0: iTypefaceFontBitmapList(KDefaultArrayGranularity), sl@0: iOpenFontFileList(KDefaultArrayGranularity), // list of 'Open Font' files loaded sl@0: iOpenFontRasterizerList(KDefaultArrayGranularity), // open rasterizers, in load order sl@0: iOpenFontUid(1), sl@0: iDefaultBitmapType(EMonochromeGlyphBitmap), sl@0: iShaperFactoryList(KDefaultArrayGranularity), sl@0: iOpenFontShaperCacheMemUsage(0), sl@0: iNumberOfShaperCaches(0), sl@0: iOpenFontTypefaceSupportList(KDefaultArrayGranularity), // list of Open Font typefaces available sl@0: iUniqueFontIdCount(0) // used to give every font a unique id sl@0: { sl@0: } sl@0: sl@0: void CFontStore::ConstructL() sl@0: { sl@0: // Cache is placed in the shared heap sl@0: iOpenFontSessionCacheList = (COpenFontSessionCacheList*)iHeap->AllocL(sizeof(COpenFontSessionCacheList)); sl@0: new(iOpenFontSessionCacheList) COpenFontSessionCacheList; sl@0: sl@0: CTypefaceStore::ConstructL(); sl@0: User::LeaveIfError(iFs.Connect()); sl@0: sl@0: TMachineInfoV1Buf machineInfoBuffer; sl@0: User::LeaveIfError(UserHal::MachineInfo(machineInfoBuffer)); sl@0: sl@0: const TSize twipSize = machineInfoBuffer().iPhysicalScreenSize; sl@0: const TSize pixelSize = machineInfoBuffer().iDisplaySizeInPixels; sl@0: sl@0: if (twipSize.iWidth > 0 && pixelSize.iWidth > 0) sl@0: iKPixelWidthInTwips = twipSize.iWidth * 1000 / pixelSize.iWidth; sl@0: sl@0: if (twipSize.iHeight > 0 && pixelSize.iHeight > 0) sl@0: iKPixelHeightInTwips = twipSize.iHeight * 1000 / pixelSize.iHeight; sl@0: sl@0: iCacheMemMon = new(ELeave) TFontTableGlyphOutlineCacheMemMonitor; sl@0: iUnhintedOutlineCache = new(ELeave) CUnhintedOutlineCache(iHeap, *iCacheMemMon); sl@0: iHintedOutlineCache = new(ELeave) CHintedOutlineCache(iHeap, *iCacheMemMon); sl@0: iFontTableCache = new(ELeave) CFontTableCache(iHeap, *iCacheMemMon); sl@0: sl@0: } sl@0: sl@0: /** Creates a new CFontStore object. sl@0: sl@0: Sets iKPixelWidthInTwips and iKPixelHeightInTwips. sl@0: sl@0: Sets the default bitmap type, used when getting bitmap fonts, to EMonochromeGlyphBitmap. sl@0: sl@0: Also initialises other private member variable values . sl@0: sl@0: @param aHeap A pointer to the heap class used for memory allocation. sl@0: @leave KErrNoMemory Insufficient memory available on the heap. */ sl@0: EXPORT_C CFontStore *CFontStore::NewL(RHeap* aHeap) sl@0: { sl@0: User::LeaveIfNull(aHeap); sl@0: CFontStore *fontstore = new(ELeave) CFontStore(aHeap); sl@0: CleanupStack::PushL(fontstore); sl@0: fontstore->ConstructL(); sl@0: CleanupStack::Pop(fontstore); sl@0: return fontstore; sl@0: } sl@0: sl@0: /** Destructor. */ sl@0: EXPORT_C CFontStore::~CFontStore() sl@0: { sl@0: // Remove All font files, and Reset associated arrays sl@0: RemoveFile(KNullUid); sl@0: iOpenFontRasterizerList.ResetAndDestroy(); sl@0: iShaperFactoryList.ResetAndDestroy(); sl@0: if (iOpenFontSessionCacheList) sl@0: { sl@0: iOpenFontSessionCacheList->Delete(iHeap); sl@0: iHeap->Free(iOpenFontSessionCacheList); sl@0: } sl@0: iFs.Close(); sl@0: sl@0: delete iFontTableCache; sl@0: delete iUnhintedOutlineCache; sl@0: delete iHintedOutlineCache; sl@0: delete iCacheMemMon; sl@0: } sl@0: sl@0: sl@0: // local utility functions sl@0: // reads bytes from file, if the requested number of bytes are not available it leaves sl@0: void ReadFromFileL(RFile& aFile, TDes8& aDes, TInt aLength) sl@0: { sl@0: User::LeaveIfError(aFile.Read(aDes, aLength)); sl@0: if (aDes.Length() != aLength) sl@0: { sl@0: OstTrace0( TRACE_DUMP, _READFROMFILEL, "EOF reading structure from font file, Leave(KErrCorrupt)" ); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: } sl@0: sl@0: // local function(s) to read values from buffer & validate them sl@0: TUint TtfTableTagFromBufferL(TDes8& aDes) sl@0: { sl@0: TUint value = 0; sl@0: for (TUint index = 0; index < 4;) sl@0: { sl@0: TUint temp = static_cast(aDes[index++]); sl@0: // must be ASCII character between 32 & 126 inclusive (per Apple's TTF specification document) sl@0: if ( (temp < 32) || (temp > 126) ) sl@0: { sl@0: OstTrace1( TRACE_DUMP, _TTFTABLETAGFROMBUFFERL, "invalid ASCII character (0x%x) in ttf table tag, Leave(KErrCorrupt)", temp); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: value = (value << 8) | temp; sl@0: } sl@0: return value; sl@0: } sl@0: sl@0: /* Sanity check for TrueType Font, checks that the font tables are sensible. sl@0: */ sl@0: void CFontStore::SanityCheckForTtfL(RFile& aFontFile, TUint aFontFileSize, TBool aStrictChecking) sl@0: { sl@0: OstTraceExt2( TRACE_DUMP, CFONTSTORE_SANITYCHECKFORTTFL, "TTF File Size is %u (0x%x) bytes", aFontFileSize, aFontFileSize ); sl@0: // check the Offset Table at the start of the file sl@0: TBuf8<16> fileBuffer; sl@0: sl@0: ReadFromFileL(aFontFile, fileBuffer, 12); sl@0: TUint numTables = (fileBuffer[4] << 8) | (fileBuffer[5]); sl@0: TUint searchRange = (fileBuffer[6] << 8) | (fileBuffer[7]); sl@0: TUint entrySelector = (fileBuffer[8] << 8) | (fileBuffer[9]); sl@0: TUint rangeShift = (fileBuffer[10] << 8) | (fileBuffer[11]); sl@0: sl@0: const TInt tableStart = 12 + (numTables << 4); // lowest possible address for actual table data sl@0: sl@0: if ( (numTables == 0) || (numTables & 0xF0000000) || (tableStart > aFontFileSize) ) sl@0: { sl@0: OstTrace1( TRACE_DUMP, DUP1_CFONTSTORE_SANITYCHECKFORTTFL, "# of tables (%d) in ttf is invalid, Leave(KErrCorrupt)", numTables ); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: #if defined(_DEBUG) && defined(VERBOSE_DEBUG) sl@0: // scalar type is 0x00010000 for Windows fonts, other possible values include 0x74727565 and 0x74797031: not checked sl@0: TUint scalarType = (fileBuffer[0] << 24) | (fileBuffer[1] << 16) | (fileBuffer[2] << 8) | (fileBuffer[3]); sl@0: RDebug::Print(_L("ttf scalarType is 0x%x, # of tables is %u\n"), scalarType, numTables); sl@0: RDebug::Print(_L("searchRange is 0x%x, entrySelector is 0x%x, rangeShift is 0x%x\n"), sl@0: searchRange, entrySelector, rangeShift); sl@0: #endif sl@0: sl@0: // check searchRange, entrySelector & rangeShift values sl@0: // (some not quite TTF files fail the rangeShift check) sl@0: if ( (searchRange < 16) || (entrySelector > 24) sl@0: || (aStrictChecking && (rangeShift != ( (numTables << 4) - searchRange )) ) ) sl@0: { sl@0: OstTraceExt4( TRACE_DUMP, DUP2_CFONTSTORE_SANITYCHECKFORTTFL, "searchRange (0x%x), entrySelector (0x%x) or rangeShift (0x%x) invalid for numTables (%d), Leave(KErrCorrupt)", sl@0: searchRange, entrySelector, rangeShift, numTables ); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: // entrySelector is defined as Log2(Maximum power of 2 <= nmumTables) sl@0: TUint exp = 1 << entrySelector; // log to exponent sl@0: if ( (numTables < exp) || (numTables > (exp << 1)) ) sl@0: { sl@0: OstTraceExt2( TRACE_DUMP, DUP3_CFONTSTORE_SANITYCHECKFORTTFL, "entrySelector (0x%x) wrong for numTables(%d), Leave(KErrCorrupt)", sl@0: entrySelector, numTables ); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: // easy checks on the table directory sl@0: TInt totalFontSize = tableStart; // accumulated total directories plus table sizes sl@0: TInt highestTableEnd = 0; // highest value found for table start plus table length sl@0: TUint lastTableTag = 0; // to check that tags are in order sl@0: TInt tableNum = 0; sl@0: sl@0: do sl@0: { // each entry is 16 bytes, (though we don't check the checksum) sl@0: ReadFromFileL(aFontFile, fileBuffer, 16); sl@0: TUint tableTag = TtfTableTagFromBufferL(fileBuffer); sl@0: TUint offset = (fileBuffer[8] << 24) | (fileBuffer[9] << 16) | (fileBuffer[10] << 8) | (fileBuffer[11]); sl@0: TUint length = (fileBuffer[12] << 24) | (fileBuffer[13] << 16) | (fileBuffer[14] << 8) | (fileBuffer[15]); sl@0: sl@0: #if defined(_DEBUG) && defined(VERBOSE_DEBUG) sl@0: RDebug::Print(_L("ttf table tag ('%c%c%c%c'): offset is 0x%x, length is 0x%x\n"), sl@0: tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F, sl@0: offset, length); sl@0: #endif sl@0: length = (length + 3) & ~3; // round up, all tables must be a multiple of 4 bytes for checksumming sl@0: sl@0: // table Tags must be unique & in order sl@0: if (tableTag <= lastTableTag) sl@0: { sl@0: OstTraceExt4( TRACE_DUMP, DUP4_CFONTSTORE_SANITYCHECKFORTTFL, "ttf table tag ('%c%c%c%c') is out of order, Leave(KErrCorrupt)", sl@0: tableTag >> 24, (tableTag >> 16) & 0x7F, (tableTag >> 8) & 0x7F, tableTag & 0x7F); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: sl@0: // the offset must be 4-byte aligned, and after the table directory sl@0: // offset + length must be bigger than the start offset (!) sl@0: TInt end = length + offset; sl@0: if ( (offset & 3) || (offset < tableStart) || (length == 0) || (end < offset) || (end > aFontFileSize)) sl@0: { sl@0: OstTraceExt2( TRACE_DUMP, DUP5_CFONTSTORE_SANITYCHECKFORTTFL, "offset (0x%x) or length (0x%x) are bad, Leave(KErrCorrupt)", sl@0: offset, length ); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: sl@0: lastTableTag = tableTag; sl@0: totalFontSize += length; sl@0: if (end > highestTableEnd) sl@0: { sl@0: highestTableEnd = end; sl@0: } sl@0: } sl@0: while (++tableNum < numTables); sl@0: sl@0: #if defined(_DEBUG) && defined(VERBOSE_DEBUG) sl@0: RDebug::Print(_L("last address used by any table is 0x%x, Minimum font file size to hold all tables is 0x%x\n"), sl@0: highestTableEnd, totalFontSize); sl@0: #endif sl@0: sl@0: // for single font files highestTableEnd & totalFontSize should be the same sl@0: if (highestTableEnd != totalFontSize) sl@0: { sl@0: OstTraceExt2( TRACE_DUMP, DUP6_CFONTSTORE_SANITYCHECKFORTTFL, "Total Font Size (0x%x) is different from end of the last table (0x%x), Leave(KErrCorrupt)", sl@0: highestTableEnd, totalFontSize); sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: } sl@0: sl@0: /* Sanity checks on font files, currently only knows about TrueType Font files: .ttf and .otf sl@0: Protects FBserv / the client and the rasterizer plug-in from grossly corrupt data. sl@0: @leave KErrCorrupt if the font tables are daft sl@0: */ sl@0: void CFontStore::SanityCheckFontFileL(TParse& aParse) sl@0: { sl@0: sl@0: // try to open the file and getting the file size sl@0: RFile fontFile; sl@0: const TInt openError = fontFile.Open(iFs, aParse.FullName(), EFileRead | EFileShareReadersOnly); sl@0: #ifdef _DEBUG sl@0: if (KErrNone != openError) sl@0: { sl@0: const TDesC& fileName = aParse.FullName(); sl@0: RDebug::Print(_L("Sanity checking font file \"%S\", file open gave error %d\n"), &fileName, openError); sl@0: } sl@0: #endif sl@0: User::LeaveIfError(openError); sl@0: CleanupClosePushL(fontFile); sl@0: TInt fontFileSize = 0; sl@0: User::LeaveIfError(fontFile.Size(fontFileSize)); sl@0: sl@0: if (fontFileSize == 0) sl@0: { // no font can be zero length! sl@0: #ifdef _DEBUG sl@0: RDebug::Print(_L("font file size (%i) is zero\n"), fontFileSize); sl@0: #endif sl@0: User::Leave(KErrCorrupt); sl@0: } sl@0: else sl@0: { sl@0: const TDesC& fileExt = aParse.Ext(); sl@0: // TrueType fonts sl@0: _LIT(KFntStoreTrueTypeExtension,".ttf"); sl@0: // OpenType fonts sl@0: _LIT(KFntStoreOpenTypeExtension,".otf"); sl@0: // other font files that follow TTF format sl@0: _LIT(KFntStoreCccFontFileExtension,".ccc"); sl@0: sl@0: if ( (0 == fileExt.CompareF(KFntStoreTrueTypeExtension)) || (0 == fileExt.CompareF(KFntStoreOpenTypeExtension)) ) sl@0: { // uses TrueType file format, perform strict format check sl@0: SanityCheckForTtfL(fontFile, fontFileSize, ETrue); sl@0: } sl@0: else if (0 == fileExt.CompareF(KFntStoreCccFontFileExtension)) sl@0: { // uses nearly TrueType file format, perform slightly less strict format check sl@0: SanityCheckForTtfL(fontFile, fontFileSize, EFalse); sl@0: } sl@0: sl@0: // extendible if required for other font file types ... sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&fontFile); sl@0: } sl@0: sl@0: sl@0: /** Finds or creates a font file object to support a font file. The specified font sl@0: file must be accessible to any process, i.e. not located inside an sl@0: application's private directory. sl@0: sl@0: If an appropriate font file object exists then no new open font file is created. sl@0: In this case the reference count of the font file object is incremented. sl@0: sl@0: Notes: sl@0: sl@0: If aName is recognised as an open font file, creates a COpenFontFile, which sl@0: will manage the font file specified by aName, and adds it to the file store's sl@0: list of open font files. sl@0: sl@0: The list of open font files is used when getting the nearest font for a font sl@0: specification (i.e. by the GetNearestFont...() functions of this class) if sl@0: the font is generated via a rasterizer. sl@0: sl@0: The appropriate rasterizer, which supports the font format of the font file, sl@0: is used to generate the open font file using COpenFontRasterizer::NewFontFileL(). sl@0: sl@0: If aName is not recognised as an open font file then CFontStoreFile tries to open sl@0: the file as a Symbian Bitmap font. sl@0: sl@0: @param aName The full path and filename of the font file to be supported. sl@0: @return The UID of the font file object supporting aName. sl@0: @leave KErrNotSupported if the file is not recognised at all sl@0: @leave KErrCorrupt if the font file data does not make sense sl@0: @leave or another system-wide error sl@0: */ sl@0: EXPORT_C TUid CFontStore::AddFileL(const TDesC& aName) sl@0: { sl@0: TParse fontFilename; sl@0: User::LeaveIfError(iFs.Parse(aName, fontFilename)); sl@0: sl@0: // increment reference count if font file is already loaded sl@0: TUid fontUid = KNullUid; sl@0: sl@0: if (IncRefCountOfLoadedFont(fontFilename, fontUid)) sl@0: { sl@0: return fontUid; sl@0: } sl@0: sl@0: // Do not validate fonts on Z: (assumed to be ROM created with valid fonts) sl@0: if (!FileIsOnZ(fontFilename)) sl@0: { sl@0: // file is not open - check that the file exists and has a plausible content sl@0: SanityCheckFontFileL(fontFilename); sl@0: } sl@0: sl@0: AddSanityCheckedFontL(fontFilename, fontUid); sl@0: sl@0: return fontUid; sl@0: } sl@0: sl@0: /** sl@0: Finds or creates a font file object to support a font file. sl@0: @param aFileName The filename to check sl@0: @param aUid The list to check sl@0: @see CFontStore::AddFileL sl@0: */ sl@0: void CFontStore::AddSanityCheckedFontL(const TParse& aFileName, TUid& aUid) sl@0: { sl@0: // Try loading the file as an Open Font sl@0: if (!LoadFileAsOpenFontL(aFileName, aUid)) sl@0: { sl@0: // It could not be recognised as an Open Font file so load it as an EPOC bitmap font file. sl@0: // (This always succeeds or Leaves.) sl@0: aUid = LoadFileAsBitmapFontL(aFileName); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Remove a Font File - called via the Cleanup Stack if a leave occurs during font install sl@0: void CFontStore::CleanupRemoveFontFile(TAny* aCleanupInfo) sl@0: { sl@0: TCleanupRemoveFontFile* cleanupInfo = (TCleanupRemoveFontFile *) aCleanupInfo; sl@0: cleanupInfo->iFontStore->RemoveFile(cleanupInfo->iFontUid); sl@0: } sl@0: sl@0: sl@0: /** Search through the rasterizers for one that will open the font filename. sl@0: sl@0: Can leave if the rasterizer encounters an error, such as unexpected end of file, nonsense data, no memory. sl@0: sl@0: @param aName full filename to open sl@0: @param aFontUid set to the font file UID if it is already loaded sl@0: @return ETrue if the font file is loaded, otherwise EFalse sl@0: @internalComponent sl@0: */ sl@0: TBool CFontStore::LoadFileAsOpenFontL(const TParse& aFileName, TUid& aFontUid) sl@0: { sl@0: const TDesC& fullName = aFileName.FullName(); sl@0: sl@0: // ask each of the rasterizers in turn to create a COpenFontFile object. sl@0: const TInt rasterizerCount = iOpenFontRasterizerList.Count(); sl@0: for (TInt index = 0; index < rasterizerCount; index++) sl@0: { sl@0: COpenFontFile* openFontFile = iOpenFontRasterizerList[index]->NewFontFileL(iOpenFontUid, fullName, iFs); sl@0: if (NULL != openFontFile) sl@0: { sl@0: /* Uids for Open Fonts are allocated in order; the sl@0: one for the COpenFontFile just created won't match any existing one. sl@0: (When a file is removed, the fake Uid will match, because the one that was returned here is used.) sl@0: */ sl@0: CleanupStack::PushL(openFontFile); sl@0: openFontFile->SetFontStoreL(this); sl@0: iOpenFontFileList.AppendL(openFontFile); sl@0: openFontFile->IncRefCount(); sl@0: CleanupStack::Pop(openFontFile); sl@0: sl@0: TInt typefaceAddError = AddTypefacesToSupportList(openFontFile); sl@0: if (typefaceAddError) sl@0: { sl@0: // cleanup sl@0: RemoveFile(openFontFile->Uid()); sl@0: // throw the error sl@0: User::Leave(typefaceAddError); sl@0: } sl@0: sl@0: /* sl@0: iOpenFontUid is the fake Uid used for new font files. It is made modulo a 'zillion' (2^28) sl@0: so that it cannot conflict with real Uids, which are >= 2^28. It starts at 1 so that sl@0: it does not conflict with the value 0 (KNullUid) which is used as a sentinel in sl@0: CFontStore::RemoveFileL. sl@0: */ sl@0: ++iOpenFontUid; sl@0: iOpenFontUid = iOpenFontUid % 0x1000000; sl@0: sl@0: aFontUid = openFontFile->Uid(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: /** Search loaded fonts for filename, and increment the reference count sl@0: @param aParse full filename to search for sl@0: @return the font file UID sl@0: @leave KErrNotSupported or another system wide error code sl@0: @internalComponent sl@0: */ sl@0: TUid CFontStore::LoadFileAsBitmapFontL(const TParse& aParse) sl@0: { sl@0: // open the file, presuming it is a bitmap font sl@0: CFontStoreFile* fontStoreFile = CFontStoreFile::NewL(aParse, iFs); sl@0: sl@0: // See if a font with this UID is already open sl@0: TInt match = FindBitmapFontFileIndexByUid(fontStoreFile->iCollectionUid); sl@0: if (match != KErrNotFound) // The file is open. sl@0: { // close the new duplicate, inc the reference count sl@0: delete fontStoreFile; sl@0: fontStoreFile = iFontStoreFileList[match]; sl@0: fontStoreFile->iUsageCount++; sl@0: } sl@0: else sl@0: { sl@0: CleanupStack::PushL(fontStoreFile); sl@0: iFontStoreFileList.AppendL(fontStoreFile); sl@0: CleanupStack::Pop(fontStoreFile); sl@0: sl@0: // special object to removes the font file if a leave occurs during font install sl@0: TCleanupRemoveFontFile cleanupHelper(this, fontStoreFile->iCollectionUid); sl@0: CleanupStack::PushL(TCleanupItem(CleanupRemoveFontFile, &cleanupHelper)); sl@0: // install the new font sl@0: InternalizeFontStoreFileL(fontStoreFile, fontStoreFile->iFontVersion); sl@0: CleanupStack::Pop(&cleanupHelper); // CleanupRemoveFontFile sl@0: } sl@0: return fontStoreFile->iCollectionUid; sl@0: } sl@0: sl@0: sl@0: /** Search open Bitmap font files for matching UID sl@0: @param aUid UID to search for sl@0: @return The index of the matching item in iFontStoreFileList[] array, or KErrNotFound sl@0: @internalComponent sl@0: */ sl@0: TInt CFontStore::FindBitmapFontFileIndexByUid(TUid aUid) sl@0: { sl@0: const TInt fontFileCount = iFontStoreFileList.Count(); sl@0: for (TInt index = 0; index < fontFileCount; index++) sl@0: { sl@0: if (iFontStoreFileList[index]->iCollectionUid == aUid) sl@0: { sl@0: return index; sl@0: } sl@0: } sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: sl@0: /** Search loaded fonts for filename, and increment the reference count sl@0: @param aName full filename to search for sl@0: @param aFontUid set to the font file UID if it is already loaded sl@0: @return ETrue if the font file is already loaded, otherwise EFalse sl@0: @internalComponent sl@0: */ sl@0: TBool CFontStore::IncRefCountOfLoadedFont(const TParse& aFileName, TUid& aFontUid) sl@0: { sl@0: const TDesC& fullName = aFileName.FullName(); sl@0: sl@0: // Is it already in the Open Font list? Compare by full filename, not (fake) Uid; sl@0: const TInt openFontCount = iOpenFontFileList.Count(); sl@0: TInt i = 0; sl@0: for (i = 0; i < openFontCount; ++i) sl@0: { sl@0: COpenFontFile* openFontFile = iOpenFontFileList[i]; sl@0: if (fullName.CompareF(openFontFile->FileName()) == 0) sl@0: { sl@0: // Open Font file already loaded sl@0: openFontFile->IncRefCount(); sl@0: aFontUid = openFontFile->Uid(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: // already open as an EPOC bitmap font file? sl@0: const TInt fontFileCount = iFontStoreFileList.Count(); sl@0: for (i = 0; i < fontFileCount; i++) sl@0: { sl@0: CFontStoreFile* fontStoreFile = iFontStoreFileList[i]; sl@0: if (fullName.CompareF(fontStoreFile->FullName()) == 0) sl@0: { sl@0: // font file already loaded sl@0: ++(fontStoreFile->iUsageCount); sl@0: aFontUid = fontStoreFile->iCollectionUid; sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: /** Releases a hold on one or all font file objects (COpenFontFiles or CFontStoreFiles). sl@0: sl@0: If aFileUid identifies a font file object, then the reference count for this sl@0: object is decremented. If this brings the reference count down to zero then sl@0: the font file object and typefaces associated with this file are removed from sl@0: the font store, provided no fonts associated with this file are being accessed. sl@0: If one or more fonts are being accessed then the file removal request will be ignored. sl@0: sl@0: If, on the other hand, aFileUid's value is NULL, then all font file objects sl@0: are removed, along with all fonts and typefaces in the font store, provided sl@0: that no fonts in the font store are being accessed (i.e. iFontAccess is empty), sl@0: otherwise it has no effect. sl@0: sl@0: (If aFileUid is invalid, then no objects are removed.) sl@0: sl@0: @param aFileUid UID of a hold on a font file object to be released, or KNullUid sl@0: if all font file objects are to be removed. sl@0: */ sl@0: EXPORT_C void CFontStore::RemoveFile(TUid aFileUid) sl@0: { sl@0: TInt i, count; sl@0: if (aFileUid == KNullUid) // this means 'delete all files' sl@0: { sl@0: if(iFontAccess) sl@0: { sl@0: TInt count = iFontAccess->Count(); sl@0: for (TInt i = 0; i < count; i++) sl@0: if((*iFontAccess)[i].iAccessCount) sl@0: return; sl@0: } sl@0: if (iFontTableCache && iFontTableCache->HasOutstandingRefCount()) sl@0: { sl@0: // disallow font file removal if any font tables are still cached sl@0: return; sl@0: } sl@0: sl@0: iTypefaceList.ResetAndDestroy(); sl@0: count = iFontBitmapList.Count(); sl@0: for (TInt i = 0; i < count; i++) sl@0: iFontBitmapList[i]->Release(); sl@0: iFontBitmapList.Reset(); sl@0: iTypefaceFontBitmapList.Reset(); sl@0: iFontStoreFileList.ResetAndDestroy(); sl@0: iOpenFontFileList.ResetAndDestroy(); sl@0: iOpenFontTypefaceSupportList.ResetAndDestroy(); sl@0: } sl@0: else sl@0: { sl@0: // See if it's an Open Font file. sl@0: count = iOpenFontFileList.Count(); sl@0: for (i = 0; i < count; i++) sl@0: { sl@0: TInt fontAccessCount; sl@0: if (iOpenFontFileList[i]->Uid() == aFileUid) sl@0: { // found the file sl@0: if (iFontAccess) sl@0: { // Check to see if there are any references before we consider deleting sl@0: fontAccessCount = iFontAccess->Count(); sl@0: for (TInt kk = 0; kk < fontAccessCount; ++kk) sl@0: { sl@0: CBitmapFont* bitmapFont = reinterpret_cast((*iFontAccess)[kk].iFont); sl@0: COpenFont* openFont = bitmapFont->OpenFont(); sl@0: if (openFont && openFont->File()->Uid() == aFileUid ) sl@0: { sl@0: if ((*iFontAccess)[kk].iAccessCount > 0) sl@0: return; // Outstanding reference found, so ignoring file removal request sl@0: } sl@0: } sl@0: } // Safe to proceed with removing file sl@0: // also check if there are outstanding references to any sl@0: // table in that file. sl@0: if (iFontTableCache && iFontTableCache->HasOutstandingRefCountWithUid(aFileUid)) sl@0: { sl@0: return; // outstanding reference to font table found. sl@0: } sl@0: sl@0: // Safe to proceed with removing file sl@0: if (iOpenFontFileList[i]->DecRefCount()) sl@0: { // unload the font file sl@0: RemoveTypefacesFromSupportList(iOpenFontFileList[i]); sl@0: //linked fonts deleted from this destructor sl@0: delete iOpenFontFileList[i]; sl@0: iOpenFontFileList.Delete(i); sl@0: } sl@0: return; sl@0: } sl@0: } sl@0: sl@0: // Finds first fontstorefile with correct id sl@0: TInt index = FindBitmapFontFileIndexByUid(aFileUid); sl@0: if (index != KErrNotFound) // Checks fontstore file has been found sl@0: { sl@0: iFontStoreFileList[index]->iUsageCount--; sl@0: if (!iFontStoreFileList[index]->iUsageCount) sl@0: { sl@0: TInt tfcount = iTypefaceFontBitmapList.Count(); sl@0: for (i=tfcount-1; i>=0; i--) sl@0: if (aFileUid == iTypefaceFontBitmapList[i].iFontBitmap->FontStoreFile()->iCollectionUid) sl@0: iTypefaceFontBitmapList.Delete(i); sl@0: count = iFontBitmapList.Count(); sl@0: for (i=count-1; i>=0; i--) sl@0: { sl@0: sl@0: if (aFileUid==iFontBitmapList[i]->FontStoreFile()->iCollectionUid) sl@0: { sl@0: iFontBitmapList[i]->Release(); sl@0: iFontBitmapList.Delete(i); sl@0: } sl@0: } sl@0: count = iTypefaceList.Count(); sl@0: for (i=count-1; i>=0; i--) sl@0: { sl@0: TBool inlist=EFalse; sl@0: tfcount = iTypefaceFontBitmapList.Count(); sl@0: for (TInt j=0; j height_diff) sl@0: height_diff = -height_diff; sl@0: } sl@0: score += KFontMaxScoreForHeight - height_diff; sl@0: sl@0: if (aCandidateFontSpec.IsItalic() == aIdealFontSpec.IsItalic() && sl@0: (0 < aCandidateFontSpec.SlantFactor()) == (0 < aIdealFontSpec.SlantFactor())) sl@0: { sl@0: score += KFontMatchScoreForExactItalicAndSlant; sl@0: } sl@0: else if ((aCandidateFontSpec.IsItalic() && 0 < aIdealFontSpec.SlantFactor()) || sl@0: (aIdealFontSpec.IsItalic() && 0 < aCandidateFontSpec.SlantFactor())) sl@0: { sl@0: score += KFontSimilarScoreForItalicAndSlant; sl@0: } sl@0: sl@0: if (aCandidateFontSpec.IsBold() == aIdealFontSpec.IsBold()) sl@0: { sl@0: score += KFontMatchScoreForBold; sl@0: } sl@0: sl@0: TUint effectsFlag = aIdealFontSpec.Effects() & aCandidateFontSpec.Effects(); sl@0: TBool isShadowOutlineEffects = EFalse; sl@0: sl@0: if(effectsFlag & FontEffect::EOutline) sl@0: { sl@0: score += KFontMatchScoreForOutlineOrShadow; sl@0: isShadowOutlineEffects = ETrue; sl@0: } sl@0: if(effectsFlag & FontEffect::EDropShadow) sl@0: { sl@0: score += KFontMatchScoreForOutlineOrShadow; sl@0: isShadowOutlineEffects = ETrue; sl@0: } sl@0: sl@0: //Match for bitmap glyph type only when effects are off. sl@0: //BitmapType in aIdealFontSpec will be set to EFourColourBlendGlyphBitmap by rasterizer only sl@0: //when any of the effects (outline/shadow) are on and if it supports outline and shadow fonts. sl@0: if(!isShadowOutlineEffects && (aCandidateFontSpec.BitmapType() == aIdealFontSpec.BitmapType())) sl@0: { sl@0: score += KFontMatchScoreForBitmapType; sl@0: } sl@0: if (aCandidateFontSpec.IsMonoWidth() == aIdealFontSpec.IsMonoWidth()) sl@0: { sl@0: score += KFontMatchScoreForMonoSpace; sl@0: } sl@0: if (aCandidateFontSpec.IsSerif() == aIdealFontSpec.IsSerif()) sl@0: { sl@0: score += KFontMatchScoreForSerif; sl@0: } sl@0: sl@0: return score; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Find and load the nearest Open Font by sl@0: 1. using aDesiredFontSpec to check if its already loaded, sl@0: 2. using aActualFontSpec to partially match and create a new font. sl@0: Partial match means typeface name must match, other attributes need not match. sl@0: Font must fit vertically within the specified max height if given. sl@0: sl@0: @param aFont Output, is the returned font. sl@0: @param aActualFontSpec Output, is used to represent the returned font and changed to twips. sl@0: @param aDesiredFontSpec Input, the desired font specification sl@0: @param aMaxHeight Input, the maximum height in Pixels, or 0 sl@0: @post if any Open Fonts are available this will always return something sl@0: */ sl@0: void CFontStore::GetNearestOpenFontInPixelsL( sl@0: CFont*& aFont, sl@0: TOpenFontSpec& aActualFontSpec, sl@0: const TOpenFontSpec& aDesiredFontSpec, sl@0: TInt aMaxHeight) sl@0: { sl@0: // Set the baseline offset appropriately for superscript or subscript. sl@0: TAlgStyle algstyle; sl@0: algstyle.iBaselineOffsetInPixels = BaselineOffset(aActualFontSpec.Height(), aActualFontSpec.PrintPosition()); sl@0: sl@0: // Determine if an open font with a perfect match is already loaded. sl@0: if (IsFontLoaded(aFont, algstyle, aDesiredFontSpec, aMaxHeight)) sl@0: { sl@0: aActualFontSpec = aDesiredFontSpec; sl@0: } sl@0: else sl@0: { // If not, find the nearest match for aActualFontSpec. sl@0: COpenFont* nearestFont = NULL; sl@0: sl@0: // fast search, if DO_LOADFONT_OPTIMIZATION is defined, search loaded font names for match sl@0: TInt errorName=GetNearestOpenFontInPixelsByFontName(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight); sl@0: TInt errorSimilar=KErrNone; sl@0: sl@0: if (!nearestFont) sl@0: { sl@0: errorSimilar=GetNearestOpenFontInPixelsBySimilarity(nearestFont, aActualFontSpec, aDesiredFontSpec, aMaxHeight); sl@0: } sl@0: sl@0: // If an imperfect match was found, is it already loaded? If not, create a new CBitmapFont. sl@0: if (nearestFont) sl@0: { sl@0: // sl@0: // Results of everything above are stored in nearestFont, and aActualFontSpec sl@0: // First check if the not-exactly-matched font is already loaded sl@0: // aMaxHeight is 0 to prevent duplicate CBitmapFontObjects being created sl@0: // sl@0: if (IsFontLoaded(aFont, algstyle, aActualFontSpec, 0)) sl@0: { sl@0: delete nearestFont; sl@0: } sl@0: else sl@0: { sl@0: // Set the specification of the nearest match in twips. sl@0: TOpenFontSpec openFontSpec(aActualFontSpec); sl@0: openFontSpec.SetHeight(VerticalPixelsToTwips(openFontSpec.Height())); sl@0: CleanupStack::PushL(nearestFont); sl@0: aFont = NewFontL(openFontSpec, algstyle, nearestFont); sl@0: CleanupStack::Pop(nearestFont); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: User::LeaveIfError(errorSimilar); sl@0: User::LeaveIfError(errorName); sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: /** Using the Desired Font Name try to find a matching font. sl@0: sl@0: @param aNearestOpenFont Output, nearest matching open font sl@0: @param aActualFontSpec Output, is used to represent the returned font sl@0: @param aDesiredFontSpec Input, the desired font specification sl@0: @param aMaxHeight Input, the maximum height in Pixels, or 0 sl@0: */ sl@0: #if(DO_LOADFONT_OPTIMIZATION) sl@0: TInt CFontStore::GetNearestOpenFontInPixelsByFontName( sl@0: COpenFont*& aOpenFont, sl@0: TOpenFontSpec& aActualFontSpec, sl@0: const TOpenFontSpec& aDesiredFontSpec, sl@0: TInt aMaxHeight) sl@0: { sl@0: TOpenFontSpec actualFontSpec; sl@0: COpenFont* nearestFont = NULL; sl@0: sl@0: if (aMaxHeight == 0 && aDesiredFontSpec.Name().Length() > 0) // check if it is a request for OpenFont sl@0: { sl@0: TPtrC requestedName = aDesiredFontSpec.Name(); sl@0: // Typeface files may contain all those typefaces in a family, or may contain only some. sl@0: // The optimization first tries the ShortFullName of the typeface in case the typefaces are sl@0: // put into separate files. sl@0: sl@0: // First check FullName. The following assumes that there are never two COpenFontFiles in the sl@0: // list with the same ShortFullName. So italic and bold flags are not checked. sl@0: sl@0: const TInt openFontFileCount = iOpenFontFileList.Count(); sl@0: TInt index; sl@0: TInt typicalError = KErrNone; sl@0: for (index = 0; index < openFontFileCount; index++) sl@0: { sl@0: COpenFontFile *pFile = iOpenFontFileList[index]; sl@0: const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0); sl@0: sl@0: // Use short names. They are truncated to the same length as the request in TTypeface sl@0: if ((faceAttrib.ShortFullName().CompareF(requestedName)==0) && sl@0: (faceAttrib.IsBold() == aActualFontSpec.IsBold()) && sl@0: (faceAttrib.IsItalic() == aActualFontSpec.IsItalic()) ) sl@0: { sl@0: TInt error=pFile->GetNearestFontToDesignHeightInPixels( sl@0: iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips, sl@0: iKPixelHeightInTwips, nearestFont, actualFontSpec); sl@0: sl@0: // search has finished if a match was found sl@0: if (nearestFont) sl@0: { sl@0: // need to copy the actual to the value that is going to be used down below sl@0: // to make a new font sl@0: aOpenFont = nearestFont; sl@0: aActualFontSpec = actualFontSpec; sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: if (error) sl@0: { sl@0: typicalError=error; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: // If the FullName match above has failed, then the request is being made by sl@0: // something other than a full name (assuming typeface is present). sl@0: // Although there may be more than one typeface in a file, sl@0: // It is not possible to conclude that ALL typefaces of the family are in one file. sl@0: // So to be safe, checks are made on italic and bold, possibly downgrading the optimization. sl@0: // Use short names. They are truncated to the same length as the request in TTypeface sl@0: for (index = 0; index < openFontFileCount; index++) sl@0: { sl@0: COpenFontFile *pFile = iOpenFontFileList[index]; sl@0: const TOpenFontFaceAttrib &faceAttrib = pFile->FaceAttrib(0); sl@0: sl@0: if( (faceAttrib.ShortFamilyName().CompareF(requestedName) == 0) && sl@0: (faceAttrib.IsItalic() == aDesiredFontSpec.IsItalic()) && sl@0: (faceAttrib.IsBold() == aDesiredFontSpec.IsBold()) ) sl@0: { sl@0: TInt error=pFile->GetNearestFontToDesignHeightInPixels( sl@0: iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips, sl@0: iKPixelHeightInTwips, nearestFont, actualFontSpec); sl@0: sl@0: // search has finished if a match was found sl@0: if (nearestFont) sl@0: { sl@0: // need to copy the actual to the value that is going to be used down below sl@0: // to make a new font sl@0: aOpenFont = nearestFont; sl@0: aActualFontSpec = actualFontSpec; sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: if (error) sl@0: { sl@0: typicalError=error; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: // no match sl@0: return typicalError; sl@0: } sl@0: // not open request sl@0: return KErrNone; sl@0: } sl@0: #else sl@0: TInt CFontStore::GetNearestOpenFontInPixelsByFontName( sl@0: COpenFont*& /* aOpenFont */, sl@0: TOpenFontSpec& /* aActualFontSpec */, sl@0: const TOpenFontSpec& /* aDesiredFontSpec */, sl@0: TInt /* aMaxHeight*/) sl@0: { // no match sl@0: return KErrNone; sl@0: } sl@0: #endif sl@0: sl@0: sl@0: /** Using the Desired Font Name try to find a matching font. sl@0: sl@0: @param aNearestOpenFont Output, nearest matching open font sl@0: @param aActualFontSpec Output, is used to represent the returned font sl@0: @param aDesiredFontSpec Input, the desired font specification sl@0: @param aMaxHeight Input, the maximum height in Pixels, or 0 sl@0: */ sl@0: TInt CFontStore::GetNearestOpenFontInPixelsBySimilarity( sl@0: COpenFont*& aNearestOpenFont, sl@0: TOpenFontSpec& aActualFontSpec, sl@0: const TOpenFontSpec& aDesiredFontSpec, sl@0: TInt aMaxHeight) sl@0: { sl@0: const TInt openFontFileCount = iOpenFontFileList.Count(); sl@0: TOpenFontSpec nearestFontSpec; sl@0: COpenFont* nearestFont = NULL; sl@0: TInt nearestMatch = 0; sl@0: TInt typicalError=KErrNone; sl@0: for (TInt index = 0; index < openFontFileCount; index++) sl@0: { sl@0: // ask font file for its best match, if any sl@0: COpenFont* candidateFont = NULL; sl@0: TOpenFontSpec actualFontSpec; sl@0: TInt lastError=KErrNone; sl@0: if (aMaxHeight) sl@0: { sl@0: lastError=iOpenFontFileList[index]->GetNearestFontToMaxHeightInPixels( sl@0: iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips, sl@0: iKPixelHeightInTwips, candidateFont, actualFontSpec, aMaxHeight); sl@0: } sl@0: else sl@0: { sl@0: lastError=iOpenFontFileList[index]->GetNearestFontToDesignHeightInPixels( sl@0: iHeap, iOpenFontSessionCacheList, aActualFontSpec, iKPixelWidthInTwips, sl@0: iKPixelHeightInTwips, candidateFont, actualFontSpec); sl@0: } sl@0: sl@0: // hold on to the best overall match sl@0: if (candidateFont) sl@0: { sl@0: const TInt candidateMatch = MatchFontSpecsInPixels( sl@0: actualFontSpec, aDesiredFontSpec, candidateFont->FontMaxHeight(), aMaxHeight); sl@0: sl@0: if (NULL == nearestFont || candidateMatch > nearestMatch) sl@0: { sl@0: if (nearestFont) sl@0: { sl@0: delete nearestFont; sl@0: } sl@0: nearestFont = candidateFont; sl@0: nearestMatch = candidateMatch; sl@0: nearestFontSpec = actualFontSpec; sl@0: } sl@0: else sl@0: { sl@0: // Font match is no better than the current nearestFont sl@0: // sl@0: // Note this object is newed in GetNearestFontInPixels each time sl@0: // a matching font is found. sl@0: delete candidateFont; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (lastError) sl@0: { sl@0: typicalError=lastError; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (nearestFont != NULL) sl@0: { // result sl@0: aNearestOpenFont = nearestFont; sl@0: aActualFontSpec = nearestFontSpec; sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: return typicalError; sl@0: } sl@0: } sl@0: sl@0: sl@0: /** sl@0: Get the nearest bitmap font to aFontSpec and place it in aFont. Font must sl@0: fit vertically inside specified maximum height if given. GetNearestTypeface is sl@0: called which insists that there is at least one typeface. This function will always sl@0: succeed unless there is an out-of-memory error or other abnormal error. sl@0: Change aFontSpec to represent the returned font and change it to twips. sl@0: */ sl@0: void CFontStore::GetNearestBitmapFontInPixelsL( sl@0: CFont*& aFont, sl@0: TFontSpec& aFontSpec, sl@0: TInt aMaxHeight) sl@0: { sl@0: aFontSpec.iTypeface = *GetNearestTypeface(aFontSpec.iTypeface); sl@0: TTypefaceFontBitmap tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight); sl@0: const TInt height = tffb.HeightInPixels(); sl@0: if (aFontSpec.iFontStyle.PrintPosition() != EPrintPosNormal) sl@0: { sl@0: aFontSpec.iHeight = SuperSubHeight(height, aFontSpec.iFontStyle.PrintPosition()); sl@0: tffb = GetNearestTypefaceFontBitmap(aFontSpec, aMaxHeight); sl@0: } sl@0: aFontSpec.iHeight = height; sl@0: TAlgStyle algstyle; sl@0: algstyle.SetIsBold( sl@0: EStrokeWeightBold == aFontSpec.iFontStyle.StrokeWeight() && sl@0: EStrokeWeightNormal == tffb.iFontBitmap->StrokeWeight()); sl@0: algstyle.SetIsItalic( sl@0: EPostureItalic == aFontSpec.iFontStyle.Posture() && sl@0: EPostureUpright == tffb.iFontBitmap->Posture()); sl@0: algstyle.SetIsMono(!aFontSpec.iTypeface.IsProportional() && tffb.iFontBitmap->IsProportional()); sl@0: TInt widthfactor = sl@0: ((tffb.iWidthFactor * tffb.iFontBitmap->FontStoreFile()->iKPixelAspectRatio * iKPixelWidthInTwips) + (500 * iKPixelHeightInTwips)) / (1000 * iKPixelHeightInTwips); sl@0: if (!widthfactor) sl@0: widthfactor = 1; sl@0: algstyle.SetWidthFactor(widthfactor); sl@0: algstyle.SetHeightFactor( tffb.iHeightFactor ); sl@0: algstyle.iBaselineOffsetInPixels = BaselineOffset(height, aFontSpec.iFontStyle.PrintPosition()); sl@0: if (IsFontLoaded(aFont, algstyle, aFontSpec, tffb.iFontBitmap->iUid)) sl@0: return; sl@0: TFontSpec spec(aFontSpec); sl@0: spec.iHeight = VerticalPixelsToTwips(height); sl@0: spec.iFontStyle.SetBitmapType(EMonochromeGlyphBitmap); sl@0: aFont = NewFontL(spec, algstyle, tffb.iFontBitmap); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() sl@0: yielding (virtually) the same result. However clients are strongly encouraged to use the new sl@0: @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every sl@0: character within any given text string will fit within the given amount of pixels, whereas the design sl@0: height is an aesthetic unit decided by the font designer without strict physical meaning, which sl@0: may result in cropped characters. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @deprecated Use GetNearestFontToDesignHeightInPixels sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TFontSpec& aFontSpec) sl@0: { sl@0: return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: Note that this deprecated function is replaced by the new @c GetNearestFontToDesignHeightInPixels() sl@0: yielding (virtually) the same result. However clients are strongly encouraged to use the new sl@0: @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every sl@0: character within any given text string will fit within the given amount of pixels, whereas the design sl@0: height is an aesthetic unit decided by the font designer without strict physical meaning, which sl@0: may result in cropped characters. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @deprecated Use GetNearestFontToDesignHeightInPixels sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec) sl@0: { sl@0: return GetNearestFontToDesignHeightInPixels(aFont, aFontSpec); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the sl@0: same result. However clients are strongly encouraged to use the new sl@0: @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every sl@0: character within any given text string will fit within the given amount of pixels, whereas the design sl@0: height is an aesthetic unit decided by the font designer without strict physical meaning, which sl@0: may result in cropped characters. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec) sl@0: { sl@0: TOpenFontSpec spec(aFontSpec); sl@0: return GetNearestFontToDesignHeightInPixels(aFont, spec); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: This new function replaces the deprecated @c GetNearestFontInPixels() yielding (virtually) the sl@0: same result. However clients are strongly encouraged to use the new sl@0: @c GetNearestFontToMaxHeightInPixels() function instead. This will guarantee that every sl@0: character within any given text string will fit within the given amount of pixels, whereas the design sl@0: height is an aesthetic unit decided by the font designer without strict physical meaning, which sl@0: may result in cropped characters. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontToDesignHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec) sl@0: { sl@0: return GetNearestFontInPixels(aFont, aFontSpec, 0); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: The font and bitmap server returns a pointer to the nearest matching font sl@0: from those available. Matches to max height of font - this does its best sl@0: to return a font that will fit within the maximum height specified (but sl@0: note that variations due to hinting algorithms may rarely result in this sl@0: height being exceeded by up to one pixel). Problems can also be sl@0: encountered with bitmap fonts where the typeface exists but doesn't have sl@0: a font small enough. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @param aMaxHeight The maximum height within which the font must fit. If maximum height sl@0: is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument sl@0: if equals to 1 pixel. This overrides the height specified in aFontSpec. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TFontSpec& aFontSpec, TInt aMaxHeight) sl@0: { sl@0: TOpenFontSpec spec(aFontSpec); sl@0: return GetNearestFontToMaxHeightInPixels(aFont, spec, aMaxHeight); sl@0: } sl@0: sl@0: /** sl@0: Gets the font which is the nearest to the given font specification. sl@0: sl@0: The font and bitmap server returns a pointer to the nearest matching font sl@0: from those available. Matches to max height of font - this does its best sl@0: to return a font that will fit within the maximum height specified (but sl@0: note that variations due to hinting algorithms may rarely result in this sl@0: height being exceeded by up to one pixel). Problems can also be sl@0: encountered with bitmap fonts where the typeface exists but doesn't have sl@0: a font small enough. sl@0: sl@0: @param aFont On return, contains a pointer to the nearest font. sl@0: @param aFontSpec The specification of the font to be matched. sl@0: @param aMaxHeight The maximum height within which the font must fit. If maximum height sl@0: is greater than 1024 pixels, the function returns KErrTooBig. And returns KErrArgument sl@0: if equals to 1 pixel. This overrides the height specified in aFontSpec. sl@0: @return KErrNone if successful; a system-wide error code otherwise. sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CFontStore::GetNearestFontToMaxHeightInPixels(CFont*& aFont, const TOpenFontSpec& aFontSpec, TInt aMaxHeight) sl@0: { sl@0: if (KMaxFontHeightInPixels < aMaxHeight) sl@0: { sl@0: return KErrTooBig; sl@0: } sl@0: if (aMaxHeight > 0 && aMaxHeight < KMinFontHeightInPixels) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: return GetNearestFontInPixels(aFont, aFontSpec, aMaxHeight); sl@0: } sl@0: sl@0: TInt CFontStore::GetNearestFontInPixels( sl@0: CFont*& aFont, sl@0: const TOpenFontSpec& aDesiredFontSpec, sl@0: TInt aMaxHeight) sl@0: { sl@0: aFont = NULL; sl@0: sl@0: // Determine the ideal version of the font spec. sl@0: TOpenFontSpec originalFontSpec = aDesiredFontSpec; sl@0: originalFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips); sl@0: TOpenFontSpec desiredFontSpec = originalFontSpec; sl@0: if (EDefaultGlyphBitmap == desiredFontSpec.BitmapType()) sl@0: { sl@0: desiredFontSpec.SetBitmapType(iDefaultBitmapType); sl@0: } sl@0: if (EPrintPosNormal != desiredFontSpec.PrintPosition()) sl@0: { sl@0: desiredFontSpec.SetHeight(SuperSubHeight(desiredFontSpec.Height(), desiredFontSpec.PrintPosition())); sl@0: } sl@0: TOpenFontSpec actualOpenFontSpec = desiredFontSpec; sl@0: sl@0: // Try to get an open font. sl@0: CFont* openFont = NULL; sl@0: TRAPD(error, GetNearestOpenFontInPixelsL( sl@0: openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight)); sl@0: sl@0: // Try to get a bitmap font - if getting open font failed or the match was not perfect. sl@0: CFont* bitmapFont = NULL; sl@0: TInt errorBitmap=KErrNone; sl@0: TOpenFontSpec actualBitmapFontSpec; sl@0: if (error || !openFont || actualOpenFontSpec != desiredFontSpec) sl@0: { sl@0: TFontSpec f; sl@0: originalFontSpec.GetTFontSpec(f); sl@0: if (iTypefaceList.Count() > 0) sl@0: { sl@0: TRAP(errorBitmap, GetNearestBitmapFontInPixelsL(bitmapFont, f, aMaxHeight)); sl@0: } sl@0: actualBitmapFontSpec = f; sl@0: actualBitmapFontSpec.CompensateForAspectRatio(iKPixelWidthInTwips, iKPixelHeightInTwips); sl@0: } sl@0: sl@0: //If both attempts fail then there is nothing more we can do... sl@0: if (!openFont && !bitmapFont) sl@0: { sl@0: //If an error caused no fonts to be returned then forward the error sl@0: if (error) sl@0: return error; sl@0: if (errorBitmap) sl@0: return errorBitmap; sl@0: } sl@0: // Choose the best candidate sl@0: if (NULL == openFont && NULL == bitmapFont) sl@0: { sl@0: // Try to get an open font again - unnamed font. sl@0: // See COpenFontFile::GetNearestFontHelper - how it works with unnamed fonts. sl@0: actualOpenFontSpec.SetName(KNullDesC); sl@0: TRAP(error, GetNearestOpenFontInPixelsL( sl@0: openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight)); sl@0: if (KErrNone == error && openFont) sl@0: { sl@0: aFont = openFont; sl@0: return KErrNone; sl@0: } sl@0: else sl@0: { sl@0: OstTraceExt2( TRACE_FATAL, CFONTSTORE_GETNEARESTFONTINPIXELS, "GetNearestOpenFontInPixelsL() return %d, openFont is 0x%x, Panic(EFntNoFontFound)", sl@0: error, (unsigned int)openFont); sl@0: __ASSERT_DEBUG(0, Panic(EFntNoFontFound)); sl@0: return KErrGeneral; sl@0: } sl@0: } sl@0: else if (NULL == openFont) sl@0: { sl@0: if (actualBitmapFontSpec.Name().CompareF(desiredFontSpec.Name()) != 0) sl@0: { sl@0: // Try to get the nearest open font - because no exact bitmap font match for typeface name sl@0: actualOpenFontSpec.SetName(KNullDesC); sl@0: desiredFontSpec.SetName(KNullDesC); sl@0: TRAPD(errorOpen, GetNearestOpenFontInPixelsL( sl@0: openFont, actualOpenFontSpec, desiredFontSpec, aMaxHeight)); sl@0: if (KErrNone == errorOpen && openFont) sl@0: { sl@0: aFont = openFont; sl@0: ReleaseFont(bitmapFont); sl@0: } sl@0: } sl@0: if (aFont == NULL) sl@0: { sl@0: aFont = bitmapFont; sl@0: } sl@0: } sl@0: else if (NULL == bitmapFont) sl@0: { sl@0: aFont = openFont; sl@0: } sl@0: sl@0: if (aFont == NULL) sl@0: { sl@0: // Pick the closest match; for backward compatibility prefer a bitmap font if there is a dead heat. sl@0: const TInt open_match = MatchFontSpecsInPixels( sl@0: actualOpenFontSpec, desiredFontSpec, openFont->FontMaxHeight(), aMaxHeight); sl@0: const TInt bitmap_match = MatchFontSpecsInPixels( sl@0: actualBitmapFontSpec, desiredFontSpec, bitmapFont->FontMaxHeight(), aMaxHeight); sl@0: if (open_match > bitmap_match) sl@0: { sl@0: aFont = openFont; sl@0: ReleaseFont(bitmapFont); sl@0: } sl@0: else sl@0: { sl@0: aFont = bitmapFont; sl@0: ReleaseFont(openFont); sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** Gets a bitmap font using the given font UID and algorithmic style. sl@0: sl@0: Tries to find a bitmap font in the font store with the given UID. If successful, sl@0: the given algorithmic style is applied to the font and this font (which may sl@0: be a suitable one already existing in the store, or may be a newly generated sl@0: font) is stored in aFont. If unsuccessful then no font is stored in aFont. sl@0: sl@0: @param aFont On return, a device-dependent font. sl@0: @param aUid A bitmap font UID. sl@0: @param aAlgStyle An algorithmic style to apply to the font. sl@0: @return KErrNone if the font is found, KErrNotFound if the font is not found, sl@0: or another system-wide error code. */ sl@0: EXPORT_C TInt CFontStore::GetFontById( sl@0: CFont*& aFont, sl@0: TUid aUid, sl@0: const TAlgStyle& aAlgStyle) sl@0: { sl@0: aFont = NULL; sl@0: CFontBitmap* fontbitmap = GetFontBitmapById(aUid); sl@0: if (!fontbitmap) sl@0: { sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: const TInt height = fontbitmap->iCellHeightInPixels * aAlgStyle.HeightFactor(); sl@0: TFontSpec fontspec; sl@0: fontspec.iHeight=height; //Otherwise IsFontLoaded() compares with zero height!!! sl@0: fontspec.iTypeface.SetIsProportional(!aAlgStyle.IsMono() && fontbitmap->IsProportional()); sl@0: if (aAlgStyle.IsBold() || EStrokeWeightBold == fontbitmap->StrokeWeight()) sl@0: { sl@0: fontspec.iFontStyle.SetStrokeWeight(EStrokeWeightBold); sl@0: } sl@0: if (aAlgStyle.IsItalic() || EPostureItalic == fontbitmap->Posture()) sl@0: { sl@0: fontspec.iFontStyle.SetPosture(EPostureItalic); sl@0: } sl@0: if (IsFontLoaded(aFont, aAlgStyle, fontspec, fontbitmap->iUid)) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: // Fill in the typeface by finding a typeface with the same font bitmap. sl@0: fontspec.iHeight = VerticalPixelsToTwips(height); sl@0: const TInt n = iTypefaceFontBitmapList.Count(); sl@0: for (TInt i = 0; i < n; i++) sl@0: { sl@0: if (iTypefaceFontBitmapList[i].iFontBitmap == fontbitmap) sl@0: { sl@0: fontspec.iTypeface = *iTypefaceFontBitmapList[i].iTypeface; sl@0: break; sl@0: } sl@0: } sl@0: TRAPD(ret, aFont = NewFontL(fontspec, aAlgStyle, fontbitmap)); sl@0: return ret; sl@0: } sl@0: sl@0: /** Gets the number of typefaces held in the font store. sl@0: sl@0: Note that this includes both open font typefaces and non-scalable typefaces. sl@0: sl@0: @return The number of supported typefaces. */ sl@0: EXPORT_C TInt CFontStore::NumTypefaces() const sl@0: { sl@0: return iTypefaceList.Count() + iOpenFontTypefaceSupportList.Count(); sl@0: } sl@0: sl@0: /** Gets a typeface support object for the typeface in the font store represented sl@0: by the given index. sl@0: sl@0: Returns benignly with an empty TTypefaceSupport if the index is too high; sl@0: this can happen if another process removes a typeface after the first process sl@0: has already got the number of typefaces. However, if the aTypefaceIndex<0 sl@0: the function panics with EFntTypefaceIndexOutOfRange. sl@0: sl@0: @param aTypefaceSupport On return, a typeface support object. sl@0: @param aTypefaceIndex An index number representing a typeface, which is valid sl@0: if in the range 0 to (NumTypefaces() - 1). */ sl@0: EXPORT_C void CFontStore::TypefaceSupport(TTypefaceSupport &aTypefaceSupport,TInt aTypefaceIndex) const sl@0: { sl@0: if (aTypefaceIndex < 0) sl@0: Panic(EFntTypefaceIndexOutOfRange); sl@0: sl@0: /* sl@0: Return benignly with an empty TTypefaceSupport if the index is too high; this can happen if another sl@0: process removes a font after the first process has already got the number of typefaces. sl@0: */ sl@0: int typefaces = NumTypefaces(); sl@0: if (aTypefaceIndex >= typefaces) sl@0: { sl@0: aTypefaceSupport = TTypefaceSupport(); sl@0: return; sl@0: } sl@0: sl@0: //now return Typeface Support for Open Fonts sl@0: if (aTypefaceIndex >= iTypefaceList.Count()) sl@0: { sl@0: // copy Open Font typeface details sl@0: aTypefaceSupport = *iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()]->TypefaceSupport(); sl@0: return; sl@0: } sl@0: sl@0: if (!((aTypefaceIndex >= 0) && (aTypefaceIndex < iTypefaceList.Count()))) sl@0: { sl@0: OstTraceExt2( TRACE_FATAL, CFONTSTORE_TYPEFACESUPPORT, "aTypefaceIndex=%d, iTypefaceList.Count()=%d Panic(EFntTypefaceIndexOutOfRange)", sl@0: aTypefaceIndex, iTypefaceList.Count()); sl@0: __ASSERT_DEBUG(0,Panic(EFntTypefaceIndexOutOfRange)); sl@0: } sl@0: TTypeface* typeface = iTypefaceList[aTypefaceIndex]; sl@0: aTypefaceSupport.iTypeface = *typeface; sl@0: TInt count = iTypefaceFontBitmapList.Count(); sl@0: TInt i; sl@0: for(i = 0; i < count && iTypefaceFontBitmapList[i].iTypeface != typeface; i++) sl@0: { // Finds first fontbitmap with correct typeface sl@0: } sl@0: aTypefaceSupport.iMinHeightInTwips = VerticalPixelsToTwips(iTypefaceFontBitmapList[i].HeightInPixels()); sl@0: aTypefaceSupport.iNumHeights=0; sl@0: TInt height=0; sl@0: for(; (i= iTypefaceList.Count()) sl@0: { sl@0: // it's an Open Font managed by a COpenFontFile sl@0: if (aTypefaceIndex >= NumTypefaces() || aHeightIndex < 0) sl@0: return 0; sl@0: sl@0: const CTypefaceSupportInfo* supportInfo = iOpenFontTypefaceSupportList[aTypefaceIndex - iTypefaceList.Count()]; sl@0: TInt i = Min( supportInfo->NearestPointSizeIndex() + aHeightIndex, sl@0: KOpenFontSizeArrayCount - 1); sl@0: sl@0: return gOpenFontSizeInTwipsArray[i]; sl@0: } sl@0: else sl@0: { sl@0: return VerticalPixelsToTwips(FontHeightInPixels(aTypefaceIndex,aHeightIndex)); sl@0: } sl@0: } sl@0: sl@0: /** Returns a font height, in pixels, for a certain typeface and height index. sl@0: sl@0: The font height is a height allowed for the typeface represented by aTypefaceIndex. sl@0: The height returned increases with aHeightIndex. sl@0: sl@0: If aTypefaceIndex<0 the function panics with EFntTypefaceIndexOutOfRange. sl@0: If aTypefaceIndex is greater than the number of typefaces or aHeightIndex<0 sl@0: then the function returns 0. If aHeightIndex is greater than the number of sl@0: heights then the function returns the biggest height. sl@0: sl@0: @param aTypefaceIndex An index number representing a typeface, which is valid sl@0: in the range 0 to (NumTypefaces() - 1). sl@0: @param aHeightIndex A font height index number, which is valid in the range sl@0: 0 to (TTypefaceSupport::iNumHeights - 1). Note that the typeface support object sl@0: for the typeface can be got using TypefaceSupport(). sl@0: @return The height of a font, in pixels. sl@0: @see TypefaceSupport() sl@0: */ sl@0: EXPORT_C TInt CFontStore::FontHeightInPixels(TInt aTypefaceIndex,TInt aHeightIndex) const sl@0: { sl@0: sl@0: if (aTypefaceIndex >= iTypefaceList.Count()) // it's an Open Font managed by a COpenFontFile sl@0: return VerticalTwipsToPixels(FontHeightInTwips(aTypefaceIndex,aHeightIndex)); sl@0: else sl@0: { sl@0: if (aTypefaceIndex < 0) sl@0: Panic(EFntTypefaceIndexOutOfRange); sl@0: TTypeface* typeface = iTypefaceList[aTypefaceIndex]; sl@0: TInt count = iTypefaceFontBitmapList.Count(); sl@0: TInt i; sl@0: for(i=0; (i < count) && (iTypefaceFontBitmapList[i].iTypeface != typeface); i++) sl@0: { // Finds first fontbitmap with correct typeface sl@0: } sl@0: TInt height=0,h=0; sl@0: for(; (iiFileStore,aFontStoreFile->iDataStreamId); sl@0: TInt i, size = stream.ReadInt32L(); sl@0: TInt opsPerformed=0; sl@0: for (i=0; iAllocL(sizeof(CFontBitmap)); sl@0: new(fontbitmap) CFontBitmap(iHeap,aFontStoreFile); sl@0: CleanupReleasePushL(*fontbitmap); sl@0: fontbitmap->InternalizeL(stream, aFontVersion); sl@0: if (GetFontBitmapById(fontbitmap->iUid)) sl@0: { sl@0: fontbitmap->Release(); sl@0: } sl@0: else sl@0: { sl@0: iFontBitmapList.AppendL(fontbitmap); sl@0: opsPerformed++; sl@0: } sl@0: // safely internalized & owned sl@0: CleanupStack::Pop(fontbitmap); sl@0: } sl@0: size = stream.ReadInt32L(); sl@0: for (i=0; iInternalizeL(stream); sl@0: TInt index,count=iTypefaceList.Count(); sl@0: for (index=0; (indexiName.CompareF(iTypefaceList[index]->iName); index++) sl@0: { // Looks to see if typeface is already in list sl@0: } sl@0: if (index == count) // If typeface not in list sl@0: { sl@0: iTypefaceList.AppendL(typeface); sl@0: index = iTypefaceList.Count()-1; sl@0: opsPerformed++; sl@0: CleanupStack::Pop(); // typeface sl@0: } sl@0: else sl@0: { sl@0: CleanupStack::Pop(); // typeface sl@0: delete typeface; sl@0: typeface=iTypefaceList[index]; sl@0: } sl@0: TInt num = stream.ReadInt32L(); sl@0: for (TInt j=0; j> uid; sl@0: CFontBitmap* fontbitmap = GetFontBitmapById(uid); sl@0: if (!fontbitmap) sl@0: { sl@0: OstTrace0( TRACE_FATAL, CFONTSTORE_INTERNALIZEFONTSTOREFILEL, "Panic(EFntFontBitmapNotLoaded)" ); sl@0: __ASSERT_DEBUG(0,Panic(EFntFontBitmapNotLoaded)); sl@0: } sl@0: #ifndef _DEBUG sl@0: User::LeaveIfNull(fontbitmap); sl@0: #endif sl@0: TTypefaceFontBitmap typefacefontbitmap(iTypefaceList[index],fontbitmap); sl@0: typefacefontbitmap.iWidthFactor=stream.ReadInt8L(); sl@0: typefacefontbitmap.iHeightFactor=stream.ReadInt8L(); sl@0: count=iTypefaceFontBitmapList.Count(); sl@0: TInt pos; sl@0: if (index == count) sl@0: { sl@0: pos=count; sl@0: } sl@0: else sl@0: { sl@0: sl@0: for (pos=0; (posPosture()Posture()); pos++) sl@0: { // Finds position after fontbitmap with same height sl@0: } sl@0: for (; (posStrokeWeight()StrokeWeight()); pos++) sl@0: { // Finds position after fontbitmap with same height sl@0: } sl@0: } sl@0: TTypefaceFontBitmap* tfbAtPos=(pos==count) sl@0: ? NULL sl@0: : &iTypefaceFontBitmapList[pos]; sl@0: if ( !tfbAtPos sl@0: || tfbAtPos->iTypeface!=typeface sl@0: || tfbAtPos->HeightInPixels()!=typefacefontbitmap.HeightInPixels() sl@0: || tfbAtPos->iFontBitmap->Posture()!=fontbitmap->Posture() sl@0: || tfbAtPos->iFontBitmap->StrokeWeight()!=fontbitmap->StrokeWeight() sl@0: || tfbAtPos->iWidthFactor!=typefacefontbitmap.iWidthFactor sl@0: || tfbAtPos->iHeightFactor!=typefacefontbitmap.iHeightFactor sl@0: ) sl@0: { sl@0: iTypefaceFontBitmapList.InsertL(pos,typefacefontbitmap); sl@0: opsPerformed++; sl@0: } sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(); // stream sl@0: if (!opsPerformed) sl@0: User::Leave(KErrAlreadyExists); sl@0: } sl@0: sl@0: TTypeface* CFontStore::GetNearestTypeface(const TTypeface& aTypeface) const sl@0: { sl@0: TInt index,count = iTypefaceList.Count(); sl@0: if (count <= 0) sl@0: { sl@0: OstTrace1( TRACE_FATAL, CFONTSTORE_GETNEARESTTYPEFACE, "count=%d, Panic(EFntNoTypefaces)", count ); sl@0: __ASSERT_DEBUG(0,Panic(EFntNoTypefaces)); sl@0: } sl@0: for (index=0; (indexiName); index++) sl@0: { // tries matching typeface name sl@0: } sl@0: if (index==count) sl@0: { sl@0: if (!aTypeface.IsSymbol()) sl@0: { sl@0: for (index=0; (indexIsSymbol()) || sl@0: (aTypeface.IsProportional() != iTypefaceList[index]->IsProportional()) || sl@0: (aTypeface.IsSerif() != iTypefaceList[index]->IsSerif())); index++) sl@0: { // tries matching typeface flags sl@0: } sl@0: if (index==count) sl@0: for (index=0; (indexIsSymbol()) || sl@0: (aTypeface.IsProportional()!=iTypefaceList[index]->IsProportional())); index++) sl@0: { // tries matching typeface flags sl@0: } sl@0: if (index==count) sl@0: for (index=0; (indexIsSymbol(); index++) sl@0: { // finds first non-symbol typeface sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (index=0; (indexIsSymbol()); index++) sl@0: { // finds first symbol typeface sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (index==count) sl@0: index=0; sl@0: return iTypefaceList[index]; sl@0: } sl@0: sl@0: TTypefaceFontBitmap CFontStore::GetNearestTypefaceFontBitmap(const TFontSpec& aFontSpecInPixels, TInt aMaxHeight) sl@0: { sl@0: TTypefaceFontBitmap typefacefontbitmap; sl@0: TInt count = iTypefaceFontBitmapList.Count(); sl@0: if (count <= 0) sl@0: { sl@0: OstTrace1( TRACE_FATAL, CFONTSTORE_GETNEARESTTYPEFACEFONTBITMAP, "count=%d, Panic(EFntNoTypefaceFontBitmaps)", count ); sl@0: __ASSERT_DEBUG(0, Panic(EFntNoTypefaceFontBitmaps)); sl@0: } sl@0: TInt i; sl@0: TInt j; sl@0: // Assumes there is at least one fontbitmap per typeface sl@0: for (i = 0; (i < count) && !(aFontSpecInPixels.iTypeface == *iTypefaceFontBitmapList[i].iTypeface); i++) sl@0: { // Finds first fontbitmap with correct typeface sl@0: } sl@0: if (i >= count) sl@0: { sl@0: OstTraceExt2( TRACE_FATAL, DUP1_CFONTSTORE_GETNEARESTTYPEFACEFONTBITMAP, "i=%d, count=%d, Panic(EFntTypefaceHasNoFontBitmaps)", i, count ); sl@0: __ASSERT_DEBUG(i < count, Panic(EFntTypefaceHasNoFontBitmaps)); sl@0: } sl@0: TTypeface* typeface = iTypefaceFontBitmapList[i].iTypeface; sl@0: TInt height = 0; sl@0: if (aMaxHeight > 0) sl@0: { // need to check against max height sl@0: for (j = i; (j < count) && (iTypefaceFontBitmapList[ j ].iTypeface == typeface) sl@0: && (iTypefaceFontBitmapList[j].iFontBitmap->FontMaxHeight() <= aMaxHeight); j++) sl@0: { sl@0: if (iTypefaceFontBitmapList[j].HeightInPixels() != height) sl@0: { sl@0: height = iTypefaceFontBitmapList[j].HeightInPixels(); sl@0: i = j; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { // just check against height sl@0: for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface) sl@0: && (iTypefaceFontBitmapList[j].HeightInPixels() <= aFontSpecInPixels.iHeight); j++) sl@0: { sl@0: if (iTypefaceFontBitmapList[j].HeightInPixels() != height) sl@0: { sl@0: height = iTypefaceFontBitmapList[j].HeightInPixels(); sl@0: i = j; sl@0: } sl@0: } sl@0: } sl@0: for (j = i; (j < count) && (iTypefaceFontBitmapList[j].iTypeface == typeface) sl@0: && (iTypefaceFontBitmapList[j].HeightInPixels() == height); j++) sl@0: { // Finds position after fontbitmap correct posture sl@0: if ((iTypefaceFontBitmapList[j].iFontBitmap->Posture() <= aFontSpecInPixels.iFontStyle.Posture()) && sl@0: (iTypefaceFontBitmapList[j].iFontBitmap->StrokeWeight() <= aFontSpecInPixels.iFontStyle.StrokeWeight())) sl@0: i = j; sl@0: } sl@0: typefacefontbitmap = iTypefaceFontBitmapList[i]; sl@0: return typefacefontbitmap; sl@0: } sl@0: sl@0: CFontBitmap* CFontStore::GetFontBitmapById(TUid aUid) sl@0: { sl@0: CFontBitmap* fontbitmap = NULL; sl@0: TInt i, count = iFontBitmapList.Count(); sl@0: for (i = 0; (i < count) && (aUid != iFontBitmapList[i]->iUid); i++) sl@0: { // finds matching font bitmap sl@0: } sl@0: if (iFontMaxHeight(); } sl@0: static TInt GetHeightShimHeightPixels(CFont* aFont) { return aFont->HeightInPixels(); } sl@0: sl@0: /** sl@0: Font spec comparison is based on sl@0: 1. Max height if its given, otherwise design height sl@0: 2. All other attributes in TFontSpec sl@0: sl@0: @see CFbsTypefaceStore::IsFontLoaded sl@0: @see CPdrTypefaceStore::IsFontLoaded sl@0: */ sl@0: TBool CFontStore::IsFontLoaded( sl@0: CFont*& aFont, sl@0: const TAlgStyle& aAlgStyle, sl@0: const TFontSpec& aFontSpecInPixels, sl@0: TUid aUid, sl@0: TInt aMaxHeight) const sl@0: { //It is not worth copying iFontAccess to frame as it doesn't get register optimised. sl@0: const TInt count = iFontAccess->Count(); sl@0: const TInt reqHeight = aMaxHeight ? aMaxHeight : aFontSpecInPixels.iHeight; sl@0: TInt (*heightFn)(CFont*) = aMaxHeight ? GetHeightShimMaxHeight : GetHeightShimHeightPixels; sl@0: for (TInt i = 0; i < count; i++) sl@0: { sl@0: CBitmapFont* bitmapFont = reinterpret_cast((*iFontAccess)[i].iFont); sl@0: if (bitmapFont->Uid() != aUid || sl@0: bitmapFont->iAlgStyle != aAlgStyle || sl@0: heightFn(bitmapFont) != reqHeight sl@0: ) sl@0: { sl@0: continue; sl@0: } sl@0: TFontSpec fontSpec = bitmapFont->FontSpecInTwips(); sl@0: if ( fontSpec.iFontStyle == aFontSpecInPixels.iFontStyle && sl@0: fontSpec.iTypeface.iName == aFontSpecInPixels.iTypeface.iName sl@0: ) sl@0: { sl@0: (*iFontAccess)[i].iAccessCount++; sl@0: aFont = static_cast(bitmapFont); sl@0: return ETrue; sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: CBitmapFont* CFontStore::NewFontL( sl@0: const TFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: CFontBitmap* aFontBitmap) sl@0: { sl@0: CBitmapFont* f = CBitmapFont::NewL(iHeap, aFontSpecInTwips, aAlgStyle, aFontBitmap); sl@0: CleanupStack::PushL(f); sl@0: AddFontL(f); sl@0: CleanupStack::Pop(); sl@0: f->SetUniqueFontId(++iUniqueFontIdCount); sl@0: return f; sl@0: } sl@0: sl@0: CBitmapFont* CFontStore::NewFontL( sl@0: const TOpenFontSpec& aFontSpecInTwips, sl@0: const TAlgStyle& aAlgStyle, sl@0: COpenFont* aOpenFont) sl@0: { sl@0: TFontSpec spec; sl@0: aFontSpecInTwips.GetTFontSpec(spec); sl@0: CBitmapFont* f = CBitmapFont::NewL(iHeap, spec, aAlgStyle, aOpenFont); sl@0: CleanupStack::PushL(f); sl@0: AddFontL(f); sl@0: CleanupStack::Pop(); sl@0: f->SetUniqueFontId(++iUniqueFontIdCount); sl@0: return f; sl@0: } sl@0: sl@0: // This function is biased towards rounding up sl@0: // The cutoff is effectively at one-third of a pixel sl@0: // This is to match VerticalTwipsToPixels(...) sl@0: TInt CFontStore::VerticalPixelsToTwips(TInt aPixelHeight) const sl@0: { sl@0: return ((aPixelHeight * iKPixelHeightInTwips) + 667) / 1000; // Rounds up above one-third of a pixel sl@0: } sl@0: sl@0: // This function is biased towards rounding down sl@0: // The cutoff is effectively at two-thirds of a twip sl@0: // This is to support the legacy system of rounding down sl@0: // but with a sanity-check cutoff to round up past two-thirds sl@0: TInt CFontStore::VerticalTwipsToPixels(TInt aTwipsHeight) const sl@0: { sl@0: if (!iKPixelHeightInTwips) sl@0: { sl@0: OstTrace0( TRACE_FATAL, CFONTSTORE_VERTICALTWIPSTOPIXELS, "Panic(EFntKPixelHeightInTwipsZero)" ); sl@0: __ASSERT_DEBUG(0, Panic(EFntKPixelHeightInTwipsZero)); sl@0: } sl@0: return ((aTwipsHeight * 1000) + (iKPixelHeightInTwips / 3)) / iKPixelHeightInTwips; // Rounds down below two-thirds of a twip sl@0: } sl@0: sl@0: /** Installs and takes ownership of an Open Font rasterizer. sl@0: sl@0: @param aRasterizer A pointer to an Open Font rasterizer. */ sl@0: EXPORT_C void CFontStore::InstallRasterizerL(COpenFontRasterizer* aRasterizer) sl@0: { sl@0: iOpenFontRasterizerList.AppendL(aRasterizer); sl@0: } sl@0: sl@0: /** Install and takes ownership of the shaper sl@0: sl@0: @param aShaperFactory A pointer to a shaper factory. */ sl@0: EXPORT_C void CFontStore::InstallShaperFactoryL(CShaperFactory* aShaperFactory) sl@0: { sl@0: iShaperFactoryList.AppendL(aShaperFactory); sl@0: } sl@0: sl@0: /** Deletes the glyph cache belonging to a particular client. sl@0: sl@0: Called by ~CFbClient(). sl@0: sl@0: @param aSessionHandle A session handle. */ sl@0: EXPORT_C void CFontStore::DeleteSessionCache(TInt aSessionHandle) sl@0: { sl@0: iOpenFontSessionCacheList->DeleteCache(iHeap,aSessionHandle); sl@0: } sl@0: sl@0: const CArrayPtrFlat* CFontStore::ShaperFactoryList() const sl@0: { sl@0: return &iShaperFactoryList; sl@0: } sl@0: sl@0: /** Returns the list of session caches owned by the COpenFonts sl@0: @internalComponent */ sl@0: COpenFontSessionCacheList* CFontStore::GetSessionCacheList() sl@0: { sl@0: return iOpenFontSessionCacheList; sl@0: } sl@0: sl@0: /** Returns the total cache memory used by all the COpenFonts in the system sl@0: @return Total cache memory usage sl@0: @internalComponent sl@0: */ sl@0: TInt CFontStore::GetShaperCacheMemUsage() sl@0: { sl@0: return iOpenFontShaperCacheMemUsage; sl@0: } sl@0: sl@0: /** Updates the total cache memory used by all the COpenFonts in the system sl@0: @param aUsage New value of total cache memory usage sl@0: @internalComponent sl@0: */ sl@0: void CFontStore::SetShaperCacheMemUsage(TInt aUsage) sl@0: { sl@0: iOpenFontShaperCacheMemUsage = aUsage; sl@0: } sl@0: sl@0: /** Returns the list of COpenFontFiles owned by the CFontStore object sl@0: @internalComponent sl@0: */ sl@0: CArrayPtrFlat* CFontStore::GetOpenFontFileList() sl@0: { sl@0: return &iOpenFontFileList; sl@0: } sl@0: sl@0: void CFontStore::IncNumShaperCaches() sl@0: { sl@0: iNumberOfShaperCaches++; sl@0: } sl@0: sl@0: void CFontStore::DecNumShaperCaches() sl@0: { sl@0: iNumberOfShaperCaches--; sl@0: } sl@0: sl@0: TInt CFontStore::GetNumShaperCaches() sl@0: { sl@0: return iNumberOfShaperCaches; sl@0: } sl@0: sl@0: sl@0: /** Adds the typeface( of the currently added openfont file from the store) to Open Font System typefaces Supported List sl@0: ignoring duplicate family names. sl@0: 1. Prior to adding the entry into the typefaceList, it is searched whether already exists or not sl@0: 2. If it is found only its reference count is incremented. sl@0: 3. If it is not found then its reference count is set to 1 and added that entry into the typefacelist. sl@0: 4. If 0 typefaces are added then KErrAlreadyExists is returned causing the new font to be unloaded. sl@0: @return KErrNone is successful, otherwise a system wide error code sl@0: @internalComponent sl@0: */ sl@0: TInt CFontStore::AddTypefacesToSupportList(COpenFontFile* aOpenFontFile) sl@0: { sl@0: TInt faceCount = aOpenFontFile->FaceCount(); sl@0: CTypefaceSupportInfo* typefaceFamily = NULL; sl@0: TInt error = KErrNone; sl@0: TBool facesAdded=0; sl@0: // go through all fonts, stop early if an error sl@0: for (TInt faceIndex = 0; (faceIndex < faceCount) && (error == KErrNone); ++faceIndex) sl@0: { sl@0: //Preparing the Supported Typeface Entry sl@0: if (typefaceFamily == NULL) sl@0: { // need a new typeface object sl@0: typefaceFamily = new CTypefaceSupportInfo(); sl@0: if (typefaceFamily == NULL) sl@0: { // failed sl@0: error = KErrNoMemory; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // initialise for next type face sl@0: const TOpenFontFaceAttrib& faceAttrib = aOpenFontFile->FaceAttrib(faceIndex); sl@0: typefaceFamily->SetTypefaceInfo(faceAttrib, VerticalPixelsToTwips(faceAttrib.MinSizeInPixels())); sl@0: sl@0: TInt fontPos = -1; // an invalid index sl@0: TInt findError = iOpenFontTypefaceSupportList.FindInOrder(typefaceFamily, fontPos, CTypefaceSupportInfo::CompareFontNames); sl@0: sl@0: // new font family? sl@0: if (findError == KErrNotFound) sl@0: { sl@0: // back reference to the font file sl@0: error = typefaceFamily->AddFontFilePtr(aOpenFontFile); sl@0: if (error == KErrNone) sl@0: { // transfer ownership sl@0: error = iOpenFontTypefaceSupportList.Insert(typefaceFamily, fontPos); sl@0: if (error == KErrNone) sl@0: { sl@0: typefaceFamily = NULL; sl@0: facesAdded++; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // back reference to the new font file (allowed to fail with KErrAlreadyExists) sl@0: TInt addError = iOpenFontTypefaceSupportList[fontPos]->AddUniqueFontFilePtr(aOpenFontFile,faceAttrib); sl@0: if (addError==KErrNone) sl@0: { sl@0: facesAdded++; sl@0: } sl@0: else if (addError == KErrInUse ) sl@0: { sl@0: //remove typeface from loaded font file???? sl@0: } sl@0: else if (addError != KErrAlreadyExists ) sl@0: { sl@0: error = addError; sl@0: } sl@0: //else KErrAlreadyExists because loaded by a lower-indexed face in this font file, so faces won't be zero. sl@0: } sl@0: } sl@0: sl@0: if (typefaceFamily != NULL) sl@0: { sl@0: delete typefaceFamily; sl@0: } sl@0: if (facesAdded==0 && error==KErrNone) sl@0: { sl@0: error= KErrAlreadyExists; sl@0: } sl@0: #ifdef _DEBUG sl@0: // check that array is in order sl@0: const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count(); sl@0: for (TInt fontPos = 0; fontPos < countTypefaceFamilies - 1; ++fontPos) sl@0: { sl@0: TInt cmp = CTypefaceSupportInfo::CompareFontNames(*iOpenFontTypefaceSupportList[fontPos], *iOpenFontTypefaceSupportList[fontPos+1]); sl@0: ASSERT(cmp < 0); sl@0: } sl@0: #endif sl@0: sl@0: return error; sl@0: } sl@0: sl@0: sl@0: /** Removes the typefaces from the Support List corresponding to the fontfile removed from sl@0: the fontstore sl@0: This is done by sl@0: 1. Searching in the typefacesupportList for pointer references to the font file. sl@0: 2. If the file is referenced by the typeface family remove the reference. sl@0: 3. If typeface family no has any implementations remove the family sl@0: @internalComponent sl@0: */ sl@0: void CFontStore::RemoveTypefacesFromSupportList(COpenFontFile* aOpenFontFile) sl@0: { sl@0: const TInt countTypefaceFamilies = iOpenFontTypefaceSupportList.Count(); sl@0: sl@0: // search typeface families sl@0: for (TInt fontPos = countTypefaceFamilies - 1; fontPos >= 0; --fontPos) sl@0: { sl@0: CTypefaceSupportInfo* fontInfo = iOpenFontTypefaceSupportList[fontPos]; sl@0: sl@0: // look for back pointer to this Font File sl@0: TInt fontFileIndex = fontInfo->FindFontFilePtr(aOpenFontFile); sl@0: sl@0: if (fontFileIndex > KErrNotFound) sl@0: { // remove pointer sl@0: if (fontInfo->RemoveFontFilePtr(fontFileIndex)) sl@0: { // last implementation of the family, so delete it sl@0: delete fontInfo; sl@0: iOpenFontTypefaceSupportList.Remove(fontPos); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: This function checks the supplied typeface name against the existing bitmap and open sl@0: typefaces, to see if it present. sl@0: sl@0: @param aName The name of the typeface family name to be checked. sl@0: @return ETrue if the typeface is present, EFalse otherwise. sl@0: sl@0: @released sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C TBool CFontStore::HaveTypefaceFamilyName(const TDesC& aName) sl@0: { sl@0: //there are two lists for typefaces sl@0: //not supporting linked fonts here sl@0: sl@0: //first list is open fonts sl@0: TInt count = iOpenFontTypefaceSupportList.Count(); sl@0: for (TInt index=count-1;index>=0;index--) sl@0: { sl@0: if (aName.CompareF(iOpenFontTypefaceSupportList[index]->iSupport.iTypeface.iName)==0) sl@0: return ETrue; sl@0: } sl@0: sl@0: //now look through bitmap fonts sl@0: count = iTypefaceList.Count(); sl@0: for (TInt index=count-1;index>=0;index--) sl@0: { sl@0: if (aName.CompareF(iTypefaceList[index]->iName)==0) sl@0: return ETrue; sl@0: } sl@0: sl@0: return EFalse; sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CFontStore::CreateLinkedTypeface(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt aSession, TInt& aId) sl@0: { sl@0: TInt err; sl@0: TInt retErr=0; sl@0: TRAP(err,retErr = CreateLinkedTypefaceL(aLinkedTypefaceSpec,aSession,aId)); sl@0: if (err!=KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: else sl@0: { sl@0: return retErr; sl@0: } sl@0: } sl@0: sl@0: /* this function is used to create the linked typeface, the linked typeface is created on sl@0: * the font and bitmap server heap, not the shared heap. sl@0: */ sl@0: TInt CFontStore::CreateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec, TInt /*aSession*/, TInt& /*aId*/) sl@0: //reconstuct a CLinkedTypefaceSpecification - could store as T type, but then the sl@0: // maximum size would be used for every linked typeface sl@0: // sl@0: { sl@0: const TAny* extensionPtr = FontLinkingInterface(); sl@0: sl@0: if (extensionPtr == NULL) sl@0: return KErrNotSupported; sl@0: sl@0: //Convert the TLinkedTypefaceSpecification args into the sl@0: //COpenFontLinkedTypefaceSpecification recognised by the rasteriser sl@0: COpenFontLinkedTypefaceSpecification* spec = sl@0: COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec); sl@0: sl@0: TInt err = ValidateLinkedFontSpecificationL(*spec, EFalse); sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: GenerateLinkedFontFileL(*spec, extensionPtr, EFalse); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(spec); sl@0: return err; sl@0: } sl@0: sl@0: /* sl@0: @internalTechnology sl@0: Retrieve the specification from a linked typeface; the name of the typeface should be specified in the parameter. sl@0: sl@0: @param aLinkedTypefaceSpec An empty linked typeface spec containing the name of the typeface to be retrieved. sl@0: sl@0: @leave One of the system wide error codes. sl@0: */ sl@0: EXPORT_C void CFontStore::GetLinkedTypefaceL(TLinkedTypefaceSpecificationArgs &aLinkedTypefaceSpec) sl@0: { sl@0: const TAny* extensionPtr = FontLinkingInterface(); sl@0: sl@0: if (extensionPtr == NULL) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)extensionPtr; sl@0: sl@0: //Check whether the font is loaded sl@0: CTypefaceSupportInfo* supinfo; sl@0: TTypefaceSupport support; sl@0: COpenFontFile* fetchFont=NULL; sl@0: for (TInt count=0;count<(iOpenFontTypefaceSupportList.Count());count++) sl@0: { sl@0: supinfo = iOpenFontTypefaceSupportList[count]; sl@0: support = supinfo->iSupport; sl@0: sl@0: if (aLinkedTypefaceSpec.iName==support.iTypeface.iName) sl@0: { sl@0: fetchFont = supinfo->iOpenFontFilePtrArray[0]; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: if (fetchFont==NULL) sl@0: { sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: sl@0: COpenFontLinkedTypefaceSpecification* typefaceSpec = COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec.iName); sl@0: TFileName fetchFile = fetchFont->FileName(); sl@0: linkedExt->GetLinkedTypefaceSpecificationL(fetchFile, *typefaceSpec); sl@0: aLinkedTypefaceSpec = *typefaceSpec; sl@0: CleanupStack::PopAndDestroy(typefaceSpec); sl@0: } sl@0: sl@0: /* sl@0: @internalTechnology sl@0: Updates an existing linked typeface to a new specification. sl@0: sl@0: @param aLinkedTypefaceSpec The new specification for the typeface sl@0: sl@0: @leave KErrNotSupported Font linking is not supported by any of the installed rasterizers sl@0: @leave One of the system wide error codes. sl@0: */ sl@0: EXPORT_C void CFontStore::UpdateLinkedTypefaceL(const TLinkedTypefaceSpecificationArgs& aLinkedTypefaceSpec) sl@0: { sl@0: const TAny* extensionPtr = FontLinkingInterface(); sl@0: sl@0: if (extensionPtr == NULL) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: //Convert the TLinkedTypefaceSpecification args into the sl@0: //COpenFontLinkedTypefaceSpecification recognised by the rasteriser sl@0: COpenFontLinkedTypefaceSpecification* spec = sl@0: COpenFontLinkedTypefaceSpecification::NewLC(aLinkedTypefaceSpec); sl@0: sl@0: TInt err = ValidateLinkedFontSpecificationL(*spec, ETrue); sl@0: User::LeaveIfError(err); sl@0: sl@0: GenerateLinkedFontFileL(*spec, extensionPtr, ETrue); sl@0: sl@0: CleanupStack::PopAndDestroy(spec); sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: Performs the loading of font files at boot time. This is a three stage procedure. sl@0: sl@0: 1. Copies linked fonts to be updated from their temporary directory into the linked fonts folder sl@0: 2. Loads all the linked fonts from the linked fonts folder. sl@0: 3. Loads all remaining font files from *:\resource\fonts sl@0: */ sl@0: EXPORT_C void CFontStore::LoadFontsAtStartupL() sl@0: { sl@0: //First copy any updated linked fonts from their temporary dir to the linked font dir sl@0: CFileMan* fm = CFileMan::NewL(iFs); sl@0: CleanupStack::PushL(fm); sl@0: sl@0: //Get the fbserv private folder sl@0: TBuf privPath; sl@0: iFs.PrivatePath(privPath); sl@0: sl@0: //Construct the linked font dir path sl@0: TBuf linkedFontDir; sl@0: linkedFontDir.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath); sl@0: sl@0: //Construct the linked font temp dir path sl@0: TBuf linkedFontTempDir; sl@0: linkedFontTempDir.Append(linkedFontDir); sl@0: linkedFontTempDir.Append(KLinkedFontFileTempFolder); sl@0: sl@0: //Copy the temp folder into the main folder sl@0: TInt err = fm->Copy(linkedFontTempDir, linkedFontDir, CFileMan::EOverWrite); sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: //If sucessful copying remove the temp folder sl@0: //A leave is not thrown as the empty directory remaining is not a significant enough sl@0: //to prevent fbserv from starting sl@0: fm->RmDir(linkedFontTempDir); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(fm); sl@0: sl@0: //Load Linked Fonts sl@0: LoadFontsL(linkedFontDir); sl@0: sl@0: //Load the remaining fonts sl@0: LoadFontsL(KFBSERVFontDirSecure); sl@0: } sl@0: /** sl@0: @internalTechnology sl@0: Returns the pointer to the first rasterizer supporting font linking (KUidLinkedTypefaceRasterizerExtension). sl@0: */ sl@0: const TAny* CFontStore::FontLinkingInterface() const sl@0: { sl@0: TInt rastcount = iOpenFontRasterizerList.Count(); sl@0: COpenFontRasterizer* rast; sl@0: TAny* extensionPtr = NULL; sl@0: sl@0: //Check each rasterizer in turn to check it supports the extended interface. sl@0: //In reality there should only be one but multiple rasterizers are supported. sl@0: for (TInt i = 0 ; i != rastcount ; i++) sl@0: { sl@0: rast = iOpenFontRasterizerList[i]; sl@0: rast->ExtendedInterface(KUidLinkedTypefaceRasterizerExtension, extensionPtr); sl@0: sl@0: if (extensionPtr != NULL) sl@0: break; sl@0: } sl@0: sl@0: return extensionPtr; sl@0: } sl@0: sl@0: /** sl@0: Validates the linked font specification passed as a parameter. sl@0: sl@0: @param aSpec The specification to be validated sl@0: @param aOverwrite ETrue if this is an update operation, EFalse otherwise sl@0: */ sl@0: TInt CFontStore::ValidateLinkedFontSpecificationL(COpenFontLinkedTypefaceSpecification& aSpec, TBool aOverwrite) const sl@0: { sl@0: //see if the typeface is an existing regular typeface. sl@0: if (!aOverwrite) sl@0: { sl@0: TInt numberTypefaces = iTypefaceList.Count(); sl@0: TInt c; sl@0: sl@0: for (c=0;ciName.CompareF(aSpec.Name())) sl@0: { sl@0: //A typeface with this name is already loaded sl@0: return KErrAlreadyExists; sl@0: } sl@0: } sl@0: sl@0: TInt numberOpenFontFiles = iOpenFontFileList.Count(); sl@0: for (c=0;cFaceCount(); sl@0: TInt c2; sl@0: for (c2=0;c2FaceAttrib(c2); sl@0: sl@0: /* only comparing on the name */ sl@0: if (0== attrib.ShortFullName().CompareF(aSpec.Name())) sl@0: { sl@0: //have a matching name, return error sl@0: return KErrAlreadyExists; sl@0: } sl@0: if (0== attrib.ShortFamilyName().CompareF(aSpec.Name())) sl@0: { sl@0: //have a matching name, return error sl@0: return KErrAlreadyExists; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: //For each element, check whether the typeface exists and add the correct filename to the spec if it does sl@0: TInt numTypefaces = aSpec.TypefaceCount(); sl@0: TFileName fileName; sl@0: COpenFontLinkedTypefaceElementSpec* element; sl@0: sl@0: for (TInt counter=0;counterElementName(), fileName)) sl@0: { sl@0: element->SetFileNameL(fileName); sl@0: } sl@0: else sl@0: { sl@0: return KErrNotFound; sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Sends the specification to the font rasterizer to be created/updated. sl@0: sl@0: @param aSpec The linked font specification sl@0: @param aExtension The extension interface of the chosen rasterizer sl@0: @param aUpdate ETrue if the file is being updated, EFalse if it should be created sl@0: sl@0: @leave KErrNotFound Attempting to update a file which does not exist sl@0: */ sl@0: void CFontStore::GenerateLinkedFontFileL(COpenFontLinkedTypefaceSpecification& aSpec, const TAny* aExtension, TBool aUpdate) sl@0: { sl@0: MOpenFontLinkedTypefaceExtension* linkedExt = (MOpenFontLinkedTypefaceExtension*)aExtension; sl@0: sl@0: //Generate the filename for the linked font file (excluding the extension sl@0: //and the .) which are appended by the rasterizer. sl@0: TFileName privPath; sl@0: User::LeaveIfError(iFs.PrivatePath(privPath)); sl@0: TFileName fn; sl@0: fn.Format(KLinkedFontFileFolder, KLinkedFontDrive, &privPath); sl@0: sl@0: //Choose the correct path to write the file to sl@0: if (aUpdate) sl@0: { sl@0: fn.Append(KLinkedFontFileTempFolder); sl@0: } sl@0: sl@0: // Create the directory if it does not exist sl@0: TInt result = iFs.MkDirAll(fn); sl@0: if (result != KErrAlreadyExists) sl@0: { sl@0: User::LeaveIfError(result); sl@0: } sl@0: sl@0: //Append the linked font filename to the path for the rasterizer. sl@0: fn.Append(aSpec.Name()); sl@0: sl@0: // If we are updating, check that the file is a linked typeface before attempting the update. sl@0: if (aUpdate) sl@0: { sl@0: TFileName fn; sl@0: TBool exists = GetFontFilePath(aSpec.Name(), fn); sl@0: sl@0: if (exists) sl@0: { sl@0: COpenFontLinkedTypefaceSpecification* tempSpec = COpenFontLinkedTypefaceSpecification::NewLC(aSpec.Name()); sl@0: TRAPD(ret, linkedExt->GetLinkedTypefaceSpecificationL(fn, *tempSpec)); sl@0: User::LeaveIfError(ret); sl@0: CleanupStack::PopAndDestroy(tempSpec); sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotFound); sl@0: } sl@0: } sl@0: sl@0: //Use the rasterizer extension to create the linked typeface sl@0: linkedExt->CreateLinkedTypefaceL(aSpec, fn); sl@0: sl@0: // Load the new linked typeface sl@0: if (!aUpdate) sl@0: { sl@0: AddFileL(fn); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Function called at system startup to find and load all fonts in the specified sl@0: folder. The value of the folder will be the secure Data-caged private folder sl@0: named "\resource\fonts". sl@0: sl@0: The first font of a given name overrides subsequent ones. sl@0: sl@0: The search order is: Y:, X:, W:, ..., C:, B:, A:, Z: sl@0: sl@0: @see TFindFile sl@0: @param aFontsDir The directory search pattern sl@0: */ sl@0: void CFontStore::LoadFontsL(const TDesC& aFontsDir) sl@0: { sl@0: #ifdef _DEBUG sl@0: _LIT(KLoadStarted, "CFontStore::LoadFontsL Started.\r\n"); sl@0: RDebug::Print(KLoadStarted); sl@0: TUint32 loadStartTime = StartTiming(); sl@0: #endif sl@0: sl@0: RArray fontsToLoad; sl@0: CleanupClosePushL(fontsToLoad); sl@0: TFindFile fileFinder(iFs); sl@0: CDir* foundFileList = NULL; sl@0: sl@0: _LIT(KFBSERVFontFilePattern, "*"); sl@0: TInt findFileComplete = fileFinder.FindWildByDir(KFBSERVFontFilePattern, aFontsDir, foundFileList); sl@0: sl@0: while (!findFileComplete) sl@0: { sl@0: CleanupStack::PushL(foundFileList); sl@0: const TInt foundFileCount = foundFileList->Count(); sl@0: const TDesC& pathInfo = fileFinder.File(); sl@0: sl@0: // Build a list of fonts to be loaded eliminating duplicate filenames. sl@0: for (TInt ii = 0; ii < foundFileCount; ii++) sl@0: { sl@0: TParse fullFontFileName; sl@0: if (fullFontFileName.Set((*foundFileList)[ii].iName, &pathInfo, NULL) == KErrNone) sl@0: { sl@0: // If the font has not already been loaded, validate it then add it to the list. sl@0: if (!FileIsInList(fullFontFileName, fontsToLoad)) sl@0: { sl@0: // Do not validate fonts on Z: (assumed to be ROM created with valid fonts) sl@0: if (FileIsOnZ(fullFontFileName)) sl@0: { sl@0: fontsToLoad.AppendL(fullFontFileName); sl@0: } sl@0: else sl@0: { sl@0: // Test font before loading sl@0: TRAPD(err, SanityCheckFontFileL(fullFontFileName)) sl@0: if (KErrNone == err) sl@0: { sl@0: // Add file sl@0: fontsToLoad.AppendL(fullFontFileName); sl@0: } sl@0: else sl@0: { sl@0: _LIT(KCorruptFont, "CFontStore::LoadFontsL %S could not be loaded.\r\n"); sl@0: RDebug::Print(KCorruptFont, &fullFontFileName.FullName()); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(foundFileList); sl@0: findFileComplete = fileFinder.FindWild(foundFileList); sl@0: } sl@0: sl@0: // Load the fonts in reverse order (i.e. Z:, A: to Y:) this causes sl@0: // fonts on Z: to take priority over fonts on A: to Y: when the internal sl@0: // font names are identical. sl@0: TInt kk = fontsToLoad.Count(); sl@0: while(kk--) sl@0: { sl@0: TUid fontUid = KNullUid; sl@0: sl@0: // Load this font as a new font, and add it to the list of loaded fonts sl@0: TRAPD(addFileError, AddSanityCheckedFontL(fontsToLoad[kk], fontUid)); sl@0: if (addFileError) sl@0: { sl@0: _LIT(KLoadedFont, "CFontStore::LoadFontsL failed with error %i to load font, filename: %S\r\n"); sl@0: RDebug::Print(KLoadedFont, addFileError, &(fontsToLoad[kk].FullName())); sl@0: } sl@0: #ifdef _DEBUG sl@0: else sl@0: { sl@0: // NOTE: This is to make testing of confirming what fonts are loaded a little easier as there is no sl@0: // easy way to get this information from outside the server. sl@0: _LIT(KLoadedFont, "CFontStore::LoadFontsL loaded font filename: %S\r\n"); sl@0: RDebug::Print(KLoadedFont, &(fontsToLoad[kk].FullName())); sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: TUint32 loadTime = FinishTimingL(loadStartTime); sl@0: _LIT(KLoadEnded, "CFontStore::LoadFontsL Finished. Took: %dus\r\n"); sl@0: RDebug::Print(KLoadEnded, loadTime); sl@0: #endif sl@0: CleanupStack::PopAndDestroy(&fontsToLoad); sl@0: } sl@0: /** sl@0: Retrieves the full path and filename of the font with the specified name. This function sl@0: searches through all open font files currently loaded by font store. sl@0: sl@0: @param aFontName The full name of the font to search for sl@0: @param aFilePath An empty descriptor to have the file name filled in sl@0: sl@0: @return ETrue if the font is found; EFalse if not sl@0: */ sl@0: EXPORT_C TBool CFontStore::GetFontFilePath(const TDesC& aFontName, TFileName& aFilePath) const sl@0: { sl@0: TInt numTypefaces = iOpenFontFileList.Count(); sl@0: COpenFontFile* thisFile; sl@0: TOpenFontFaceAttrib faceAttrib; sl@0: sl@0: //For every (Truetype) font file sl@0: for (TInt i = 0 ; i != numTypefaces ; i++) sl@0: { sl@0: thisFile = iOpenFontFileList[i]; sl@0: sl@0: //For every face within this file sl@0: for (TInt face = 0 ; face != thisFile->FaceCount() ; face++) sl@0: { sl@0: faceAttrib = thisFile->FaceAttrib(face); sl@0: if (faceAttrib.FullName().CompareF(aFontName) == 0) sl@0: { sl@0: aFilePath = thisFile->FileName(); sl@0: return ETrue; sl@0: } sl@0: } sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: TInt CFontStore::CacheFontTable(TUid aFileUid, TUint32 aTag, sl@0: TAny *&aContent, TInt aLength) sl@0: { sl@0: return iFontTableCache->Append(aFileUid, aTag, aContent, aLength); sl@0: } sl@0: sl@0: TInt CFontStore::FindFontTableInCache(TUid aFileUid, TUint32 aTag, sl@0: TAny *&aContent, TInt &aLength) sl@0: { sl@0: TInt id; sl@0: return iFontTableCache->Find(aFileUid, aTag, aContent, aLength, &id); sl@0: } sl@0: sl@0: TInt CFontStore::IncreaseUnhintedOutlineRefCount(const TUnhintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iUnhintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::IncreaseHintedOutlineRefCount(const THintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iHintedOutlineCache->IncRefCount(aOutlineId, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::IncFontTableRefCount(TUid aFileUid, TUint32 aTag, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iFontTableCache->IncRefCount(aFileUid, aTag, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::DecFontTableRefCount(TUid aFileUid, TUint32 aTag, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::CacheUnhintedOutline(const TUnhintedOutlineId &aOutlineId, TAny * aData, sl@0: TInt aLength, TAny *&aOutline, TInt &aLen) sl@0: { sl@0: return iUnhintedOutlineCache->CacheUnhintedOutline(aOutlineId, aData, aLength, sl@0: aOutline, aLen); sl@0: } sl@0: sl@0: TInt CFontStore::CacheHintedOutline(const THintedOutlineId &aOutlineId, sl@0: TAny * aData, TInt aLength, TAny *&aOutline, TInt &aLen) sl@0: { sl@0: return iHintedOutlineCache->CacheHintedOutline(aOutlineId, aData, aLength, sl@0: aOutline, aLen); sl@0: } sl@0: sl@0: TInt CFontStore::ReleaseUnhintedOutline(const TUnhintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iUnhintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::ReleaseHintedOutline(const THintedOutlineId &aOutlineId, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iHintedOutlineCache->DecRefCount(aOutlineId, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::ReleaseFontTable(TUid aFileUid, TUint32 aTag, sl@0: TInt aSessionHandle) sl@0: { sl@0: return iFontTableCache->DecRefCount(aFileUid, aTag, aSessionHandle); sl@0: } sl@0: sl@0: TInt CFontStore::FindUnhintedOutlineInCache(const TUnhintedOutlineId &aOutlineId, TAny *&aData, sl@0: TInt &aLength) sl@0: { sl@0: return iUnhintedOutlineCache->Find(aOutlineId, aData, aLength); sl@0: } sl@0: sl@0: TInt CFontStore::FindHintedOutlineInCache(const THintedOutlineId &aOutlineId, sl@0: TAny *&aData, TInt &aLength) sl@0: { sl@0: return iHintedOutlineCache->Find(aOutlineId, aData, aLength); sl@0: } sl@0: sl@0: void CFontStore::CleanupCacheOnOpenFontRemoval(COpenFont *aFont) sl@0: { sl@0: iHintedOutlineCache->CleanupCacheOnOpenFontRemoval(aFont); sl@0: //iUnhintedOutlineCache.OnOpenFontRemoval(aFont); sl@0: } sl@0: sl@0: void CFontStore::CleanupCacheOnOpenFontFileRemoval(COpenFontFile *aFontFile) sl@0: { sl@0: iUnhintedOutlineCache->CleanupCacheOnOpenFontFileRemoval(aFontFile); sl@0: iFontTableCache->CleanupCacheOnOpenFontFileRemoval(aFontFile); sl@0: } sl@0: sl@0: /** Clean up font table and glyph outline caches when an FBS session is terminated. sl@0: * All the reference counts related to that session are cleared. sl@0: @param aSession: Input. A pointer to the terminating session. sl@0: @return always returns KErrNone. sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C sl@0: void CFontStore::CleanupCacheOnFbsSessionTermination(TInt aSessionHandle) sl@0: { sl@0: iHintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle); sl@0: iUnhintedOutlineCache->CleanupCacheOnFbsSessionTermination(aSessionHandle); sl@0: iFontTableCache->CleanupCacheOnFbsSessionTermination(aSessionHandle); sl@0: } sl@0: sl@0: sl@0: void TFontTableGlyphOutlineCacheMemMonitor::Inc(TInt aBytes) sl@0: { sl@0: iBytes += aBytes; sl@0: } sl@0: sl@0: void TFontTableGlyphOutlineCacheMemMonitor::Dec(TInt aBytes) sl@0: { sl@0: iBytes -= aBytes; sl@0: } sl@0: sl@0: TInt TFontTableGlyphOutlineCacheMemMonitor::GetMemUsage() sl@0: { sl@0: return iBytes; sl@0: } sl@0: sl@0: TFontTableGlyphOutlineCacheMemMonitor::TFontTableGlyphOutlineCacheMemMonitor(): sl@0: iBytes(0) sl@0: { sl@0: // null constructor sl@0: } sl@0: sl@0: TUnhintedOutlineId::TUnhintedOutlineId(TUid aFileUid, TInt aFaceIndex, TUint aId): sl@0: iFileUid(aFileUid), iFaceIndex(aFaceIndex), iId(aId) sl@0: { sl@0: // a null constructor; sl@0: } sl@0: sl@0: THintedOutlineId::THintedOutlineId(COpenFont *aFont, TUint aId): sl@0: iFont(aFont), iId(aId) sl@0: { sl@0: // a null constructor; sl@0: } sl@0: sl@0: #ifdef _DEBUG sl@0: /** sl@0: Returns a timestamp for use by FinishTimingL(). sl@0: @return The timestamp. sl@0: @see FinishTimingL sl@0: */ sl@0: TUint32 StartTiming(void) sl@0: { sl@0: return User::FastCounter(); sl@0: } sl@0: sl@0: /** sl@0: Returns the time difference between a given time and now in microseconds. sl@0: @param aStartTime The start time returned by calling StartTiming() sl@0: @return The time difference in microseconds. sl@0: @see StartTiming() sl@0: */ sl@0: TUint32 FinishTimingL(TUint32 aStartTime) sl@0: { sl@0: TInt freq = 0; sl@0: TUint32 endtime = User::FastCounter(); sl@0: User::LeaveIfError(HAL::Get(HALData::EFastCounterFrequency, freq)); sl@0: TUint32 diff = endtime - aStartTime; sl@0: TInt64 diffTime = (1000000 * TInt64(diff)) / (TInt64)freq; sl@0: return TUint32(diffTime); sl@0: } sl@0: #endif sl@0: sl@0: /** sl@0: Returns true if the filename passed in is on the Z: drive sl@0: @param aFileName The filename to check sl@0: @return ETrue if the file is on Z: sl@0: */ sl@0: TBool FileIsOnZ(TParse& aFileName) sl@0: { sl@0: TBool onZ = EFalse; sl@0: sl@0: const TDesC& fileDrive = aFileName.Drive(); sl@0: _LIT(KZDrive,"z:"); sl@0: if (0 == fileDrive.CompareF(KZDrive)) sl@0: { sl@0: onZ = ETrue; sl@0: } sl@0: sl@0: return onZ; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Returns true if the filename passed in is in the supplied list sl@0: @param aFileName The filename to check sl@0: @param aList The list to check sl@0: @return ETrue if the file is in the list sl@0: */ sl@0: TBool FileIsInList(TParse& aFileName, RArray& aList) sl@0: { sl@0: TBool inList = EFalse; sl@0: sl@0: TInt jj = aList.Count(); sl@0: while(jj--) sl@0: { sl@0: TPtrC shortFilename = aFileName.NameAndExt(); sl@0: if (shortFilename.CompareF( aList[jj].NameAndExt() ) == 0) sl@0: { sl@0: #ifdef _DEBUG sl@0: _LIT(KEclipsesFont, "CFontStore::FileIsInList %S eclipses %S\r\n"); sl@0: RDebug::Print(KEclipsesFont, &aList[jj].FullName(), &aFileName.FullName()); sl@0: #endif sl@0: inList = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return inList; sl@0: }