michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef GFXPLATFORMFONTLIST_H_ michael@0: #define GFXPLATFORMFONTLIST_H_ michael@0: michael@0: #include "nsDataHashtable.h" michael@0: #include "nsRefPtrHashtable.h" michael@0: #include "nsTHashtable.h" michael@0: michael@0: #include "gfxFontUtils.h" michael@0: #include "gfxFontInfoLoader.h" michael@0: #include "gfxFont.h" michael@0: #include "gfxPlatform.h" michael@0: michael@0: #include "nsIMemoryReporter.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: michael@0: class CharMapHashKey : public PLDHashEntryHdr michael@0: { michael@0: public: michael@0: typedef gfxCharacterMap* KeyType; michael@0: typedef const gfxCharacterMap* KeyTypePointer; michael@0: michael@0: CharMapHashKey(const gfxCharacterMap *aCharMap) : michael@0: mCharMap(const_cast(aCharMap)) michael@0: { michael@0: MOZ_COUNT_CTOR(CharMapHashKey); michael@0: } michael@0: CharMapHashKey(const CharMapHashKey& toCopy) : michael@0: mCharMap(toCopy.mCharMap) michael@0: { michael@0: MOZ_COUNT_CTOR(CharMapHashKey); michael@0: } michael@0: ~CharMapHashKey() michael@0: { michael@0: MOZ_COUNT_DTOR(CharMapHashKey); michael@0: } michael@0: michael@0: gfxCharacterMap* GetKey() const { return mCharMap; } michael@0: michael@0: bool KeyEquals(const gfxCharacterMap *aCharMap) const { michael@0: NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly, michael@0: "custom cmap used in shared cmap hashtable"); michael@0: // cmaps built on the fly never match michael@0: if (aCharMap->mHash != mCharMap->mHash) michael@0: { michael@0: return false; michael@0: } michael@0: return mCharMap->Equals(aCharMap); michael@0: } michael@0: michael@0: static const gfxCharacterMap* KeyToPointer(gfxCharacterMap *aCharMap) { michael@0: return aCharMap; michael@0: } michael@0: static PLDHashNumber HashKey(const gfxCharacterMap *aCharMap) { michael@0: return aCharMap->mHash; michael@0: } michael@0: michael@0: enum { ALLOW_MEMMOVE = true }; michael@0: michael@0: protected: michael@0: gfxCharacterMap *mCharMap; michael@0: }; michael@0: michael@0: // gfxPlatformFontList is an abstract class for the global font list on the system; michael@0: // concrete subclasses for each platform implement the actual interface to the system fonts. michael@0: // This class exists because we cannot rely on the platform font-finding APIs to behave michael@0: // in sensible/similar ways, particularly with rich, complex OpenType families, michael@0: // so we do our own font family/style management here instead. michael@0: michael@0: // Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms. michael@0: michael@0: struct FontListSizes { michael@0: uint32_t mFontListSize; // size of the font list and dependent objects michael@0: // (font family and face names, etc), but NOT michael@0: // including the font table cache and the cmaps michael@0: uint32_t mFontTableCacheSize; // memory used for the gfxFontEntry table caches michael@0: uint32_t mCharMapsSize; // memory used for cmap coverage info michael@0: }; michael@0: michael@0: class gfxUserFontSet; michael@0: michael@0: class gfxPlatformFontList : public gfxFontInfoLoader michael@0: { michael@0: public: michael@0: static gfxPlatformFontList* PlatformFontList() { michael@0: return sPlatformFontList; michael@0: } michael@0: michael@0: static nsresult Init() { michael@0: NS_ASSERTION(!sPlatformFontList, "What's this doing here?"); michael@0: gfxPlatform::GetPlatform()->CreatePlatformFontList(); michael@0: if (!sPlatformFontList) { michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: static void Shutdown() { michael@0: delete sPlatformFontList; michael@0: sPlatformFontList = nullptr; michael@0: } michael@0: michael@0: virtual ~gfxPlatformFontList(); michael@0: michael@0: // initialize font lists michael@0: virtual nsresult InitFontList(); michael@0: michael@0: void GetFontList (nsIAtom *aLangGroup, michael@0: const nsACString& aGenericFamily, michael@0: nsTArray& aListOfFonts); michael@0: michael@0: virtual bool ResolveFontName(const nsAString& aFontName, michael@0: nsAString& aResolvedFontName); michael@0: michael@0: void UpdateFontList(); michael@0: michael@0: void ClearPrefFonts() { mPrefFonts.Clear(); } michael@0: michael@0: virtual void GetFontFamilyList(nsTArray >& aFamilyArray); michael@0: michael@0: virtual gfxFontEntry* michael@0: SystemFindFontForChar(const uint32_t aCh, michael@0: int32_t aRunScript, michael@0: const gfxFontStyle* aStyle); michael@0: michael@0: // TODO: make this virtual, for lazily adding to the font list michael@0: virtual gfxFontFamily* FindFamily(const nsAString& aFamily); michael@0: michael@0: gfxFontEntry* FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold); michael@0: michael@0: bool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray > *array); michael@0: void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray >& array); michael@0: michael@0: // name lookup table methods michael@0: michael@0: void AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName); michael@0: michael@0: void AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname); michael@0: michael@0: void AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName); michael@0: michael@0: bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; } michael@0: michael@0: // pure virtual functions, to be provided by concrete subclasses michael@0: michael@0: // get the system default font family michael@0: virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle) = 0; michael@0: michael@0: // look up a font by name on the host platform michael@0: virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, michael@0: const nsAString& aFontName) = 0; michael@0: michael@0: // create a new platform font from downloaded data (@font-face) michael@0: // this method is responsible to ensure aFontData is NS_Free()'d michael@0: virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, michael@0: const uint8_t *aFontData, michael@0: uint32_t aLength) = 0; michael@0: michael@0: // get the standard family name on the platform for a given font name michael@0: // (platforms may override, eg Mac) michael@0: virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); michael@0: michael@0: virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: michael@0: // search for existing cmap that matches the input michael@0: // return the input if no match is found michael@0: gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap); michael@0: michael@0: // add a cmap to the shared cmap set michael@0: gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap); michael@0: michael@0: // remove the cmap from the shared cmap set michael@0: void RemoveCmap(const gfxCharacterMap *aCharMap); michael@0: michael@0: // keep track of userfont sets to notify when global fontlist changes occur michael@0: void AddUserFontSet(gfxUserFontSet *aUserFontSet) { michael@0: mUserFontSetList.PutEntry(aUserFontSet); michael@0: } michael@0: michael@0: void RemoveUserFontSet(gfxUserFontSet *aUserFontSet) { michael@0: mUserFontSetList.RemoveEntry(aUserFontSet); michael@0: } michael@0: michael@0: static const gfxFontEntry::ScriptRange sComplexScriptRanges[]; michael@0: michael@0: protected: michael@0: class MemoryReporter MOZ_FINAL : public nsIMemoryReporter michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIMEMORYREPORTER michael@0: }; michael@0: michael@0: gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); michael@0: michael@0: static gfxPlatformFontList *sPlatformFontList; michael@0: michael@0: static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey, michael@0: nsRefPtr& aFamilyEntry, michael@0: void* userArg); michael@0: michael@0: // returns default font for a given character, null otherwise michael@0: gfxFontEntry* CommonFontFallback(const uint32_t aCh, michael@0: int32_t aRunScript, michael@0: const gfxFontStyle* aMatchStyle, michael@0: gfxFontFamily** aMatchedFamily); michael@0: michael@0: // search fonts system-wide for a given character, null otherwise michael@0: virtual gfxFontEntry* GlobalFontFallback(const uint32_t aCh, michael@0: int32_t aRunScript, michael@0: const gfxFontStyle* aMatchStyle, michael@0: uint32_t& aCmapCount, michael@0: gfxFontFamily** aMatchedFamily); michael@0: michael@0: // whether system-based font fallback is used or not michael@0: // if system fallback is used, no need to load all cmaps michael@0: virtual bool UsesSystemFallback() { return false; } michael@0: michael@0: // verifies that a family contains a non-zero font count michael@0: gfxFontFamily* CheckFamily(gfxFontFamily *aFamily); michael@0: michael@0: // initialize localized family names michael@0: void InitOtherFamilyNames(); michael@0: michael@0: static PLDHashOperator michael@0: InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey, michael@0: nsRefPtr& aFamilyEntry, michael@0: void* userArg); michael@0: michael@0: // search through font families, looking for a given name, initializing michael@0: // facename lists along the way. first checks all families with names michael@0: // close to face name, then searchs all families if not found. michael@0: gfxFontEntry* SearchFamiliesForFaceName(const nsAString& aFaceName); michael@0: michael@0: static PLDHashOperator michael@0: ReadFaceNamesProc(nsStringHashKey::KeyType aKey, michael@0: nsRefPtr& aFamilyEntry, michael@0: void* userArg); michael@0: michael@0: // helper method for finding fullname/postscript names in facename lists michael@0: gfxFontEntry* FindFaceName(const nsAString& aFaceName); michael@0: michael@0: // look up a font by name, for cases where platform font list michael@0: // maintains explicit mappings of fullname/psname ==> font michael@0: virtual gfxFontEntry* LookupInFaceNameLists(const nsAString& aFontName); michael@0: michael@0: static PLDHashOperator LookupMissedFaceNamesProc(nsStringHashKey *aKey, michael@0: void *aUserArg); michael@0: michael@0: static PLDHashOperator LookupMissedOtherNamesProc(nsStringHashKey *aKey, michael@0: void *aUserArg); michael@0: michael@0: // commonly used fonts for which the name table should be loaded at startup michael@0: virtual void PreloadNamesList(); michael@0: michael@0: // load the bad underline blacklist from pref. michael@0: void LoadBadUnderlineList(); michael@0: michael@0: // explicitly set fixed-pitch flag for all faces michael@0: void SetFixedPitch(const nsAString& aFamilyName); michael@0: michael@0: void GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult); michael@0: michael@0: static PLDHashOperator michael@0: HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey, michael@0: nsRefPtr& aFamilyEntry, michael@0: void* aUserArg); michael@0: michael@0: virtual void GetFontFamilyNames(nsTArray& aFontFamilyNames); michael@0: michael@0: // gfxFontInfoLoader overrides, used to load in font cmaps michael@0: virtual void InitLoader(); michael@0: virtual bool LoadFontInfo(); michael@0: virtual void CleanupLoader(); michael@0: michael@0: // read the loader initialization prefs, and start it michael@0: void GetPrefsAndStartLoader(); michael@0: michael@0: // for font list changes that affect all documents michael@0: void ForceGlobalReflow(); michael@0: michael@0: // used by memory reporter to accumulate sizes of family names in the hash michael@0: static size_t michael@0: SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey, michael@0: const nsRefPtr& aFamily, michael@0: mozilla::MallocSizeOf aMallocSizeOf, michael@0: void* aUserArg); michael@0: michael@0: // canonical family name ==> family entry (unique, one name per family entry) michael@0: nsRefPtrHashtable mFontFamilies; michael@0: michael@0: // other family name ==> family entry (not unique, can have multiple names per michael@0: // family entry, only names *other* than the canonical names are stored here) michael@0: nsRefPtrHashtable mOtherFamilyNames; michael@0: michael@0: // flag set after InitOtherFamilyNames is called upon first name lookup miss michael@0: bool mOtherFamilyNamesInitialized; michael@0: michael@0: // flag set after fullname and Postcript name lists are populated michael@0: bool mFaceNameListsInitialized; michael@0: michael@0: struct ExtraNames { michael@0: ExtraNames() : mFullnames(100), mPostscriptNames(100) {} michael@0: // fullname ==> font entry (unique, one name per font entry) michael@0: nsRefPtrHashtable mFullnames; michael@0: // Postscript name ==> font entry (unique, one name per font entry) michael@0: nsRefPtrHashtable mPostscriptNames; michael@0: }; michael@0: nsAutoPtr mExtraNames; michael@0: michael@0: // face names missed when face name loading takes a long time michael@0: nsAutoPtr > mFaceNamesMissed; michael@0: michael@0: // localized family names missed when face name loading takes a long time michael@0: nsAutoPtr > mOtherNamesMissed; michael@0: michael@0: // cached pref font lists michael@0: // maps list of family names ==> array of family entries, one per lang group michael@0: nsDataHashtable > > mPrefFonts; michael@0: michael@0: // when system-wide font lookup fails for a character, cache it to skip future searches michael@0: gfxSparseBitSet mCodepointsWithNoFonts; michael@0: michael@0: // the family to use for U+FFFD fallback, to avoid expensive search every time michael@0: // on pages with lots of problems michael@0: nsRefPtr mReplacementCharFallbackFamily; michael@0: michael@0: nsTHashtable mBadUnderlineFamilyNames; michael@0: michael@0: // character map data shared across families michael@0: // contains weak ptrs to cmaps shared by font entry objects michael@0: nsTHashtable mSharedCmaps; michael@0: michael@0: // data used as part of the font cmap loading process michael@0: nsTArray > mFontFamiliesToLoad; michael@0: uint32_t mStartIndex; michael@0: uint32_t mIncrement; michael@0: uint32_t mNumFamilies; michael@0: michael@0: nsTHashtable > mUserFontSetList; michael@0: }; michael@0: michael@0: #endif /* GFXPLATFORMFONTLIST_H_ */