summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/gfxPlatformFontList.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/gfxPlatformFontList.h')
-rw-r--r--gfx/thebes/gfxPlatformFontList.h895
1 files changed, 895 insertions, 0 deletions
diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h
new file mode 100644
index 0000000000..79b8772703
--- /dev/null
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -0,0 +1,895 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFXPLATFORMFONTLIST_H_
+#define GFXPLATFORMFONTLIST_H_
+
+#include "nsClassHashtable.h"
+#include "nsDataHashtable.h"
+#include "nsRefPtrHashtable.h"
+#include "nsTHashtable.h"
+
+#include "gfxFontUtils.h"
+#include "gfxFontInfoLoader.h"
+#include "gfxFont.h"
+#include "gfxFontConstants.h"
+#include "gfxPlatform.h"
+#include "gfxFontFamilyList.h"
+#include "SharedFontList.h"
+
+#include "nsIMemoryReporter.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/FontPropertyTypes.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/RangedArray.h"
+#include "nsLanguageAtomService.h"
+
+#include "base/shared_memory.h"
+
+namespace mozilla {
+namespace fontlist {
+struct AliasData;
+}
+} // namespace mozilla
+
+class CharMapHashKey : public PLDHashEntryHdr {
+ public:
+ typedef gfxCharacterMap* KeyType;
+ typedef const gfxCharacterMap* KeyTypePointer;
+
+ explicit CharMapHashKey(const gfxCharacterMap* aCharMap)
+ : mCharMap(const_cast<gfxCharacterMap*>(aCharMap)) {
+ MOZ_COUNT_CTOR(CharMapHashKey);
+ }
+ CharMapHashKey(const CharMapHashKey& toCopy) : mCharMap(toCopy.mCharMap) {
+ MOZ_COUNT_CTOR(CharMapHashKey);
+ }
+ MOZ_COUNTED_DTOR(CharMapHashKey)
+
+ gfxCharacterMap* GetKey() const { return mCharMap; }
+
+ bool KeyEquals(const gfxCharacterMap* aCharMap) const {
+ NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly,
+ "custom cmap used in shared cmap hashtable");
+ // cmaps built on the fly never match
+ if (aCharMap->mHash != mCharMap->mHash) {
+ return false;
+ }
+ return mCharMap->Equals(aCharMap);
+ }
+
+ static const gfxCharacterMap* KeyToPointer(gfxCharacterMap* aCharMap) {
+ return aCharMap;
+ }
+ static PLDHashNumber HashKey(const gfxCharacterMap* aCharMap) {
+ return aCharMap->mHash;
+ }
+
+ enum { ALLOW_MEMMOVE = true };
+
+ protected:
+ // charMaps are not owned by the shared cmap cache, but it will be notified
+ // by gfxCharacterMap::Release() when an entry is about to be deleted
+ gfxCharacterMap* MOZ_NON_OWNING_REF mCharMap;
+};
+
+/**
+ * A helper class used to create a SharedBitSet instance in a FontList's shared
+ * memory, while ensuring that we avoid bloating memory by avoiding creating
+ * duplicate instances.
+ */
+class ShmemCharMapHashEntry final : public PLDHashEntryHdr {
+ public:
+ typedef const gfxSparseBitSet* KeyType;
+ typedef const gfxSparseBitSet* KeyTypePointer;
+
+ /**
+ * Creation from a gfxSparseBitSet creates not only the ShmemCharMapHashEntry
+ * itself, but also a SharedBitSet in shared memory.
+ * Only the parent process creates and manages these entries.
+ */
+ explicit ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap);
+
+ ShmemCharMapHashEntry(ShmemCharMapHashEntry&&) = default;
+ ShmemCharMapHashEntry& operator=(ShmemCharMapHashEntry&&) = default;
+
+ /**
+ * Return a shared-memory Pointer that refers to the wrapped SharedBitSet.
+ * This can be passed to content processes to give them access to the same
+ * SharedBitSet as the parent stored.
+ */
+ mozilla::fontlist::Pointer GetCharMap() const { return mCharMap; }
+
+ bool KeyEquals(KeyType aCharMap) const {
+ // mHash is a 32-bit Adler checksum of the bitset; if it doesn't match we
+ // can immediately reject it as non-matching, but if it is equal we still
+ // need to do a full equality check below.
+ if (mHash != aCharMap->GetChecksum()) {
+ return false;
+ }
+
+ return static_cast<const SharedBitSet*>(mCharMap.ToPtr(mList))
+ ->Equals(aCharMap);
+ }
+
+ static KeyTypePointer KeyToPointer(KeyType aCharMap) { return aCharMap; }
+ static PLDHashNumber HashKey(KeyType aCharMap) {
+ return aCharMap->GetChecksum();
+ }
+
+ enum { ALLOW_MEMMOVE = true };
+
+ private:
+ // charMaps are stored in the shared memory that FontList objects point to,
+ // and are never deleted until the FontList (all referencing font lists,
+ // actually) have gone away.
+ mozilla::fontlist::FontList* mList;
+ mozilla::fontlist::Pointer mCharMap;
+ uint32_t mHash;
+};
+
+// gfxPlatformFontList is an abstract class for the global font list on the
+// system; concrete subclasses for each platform implement the actual interface
+// to the system fonts. This class exists because we cannot rely on the platform
+// font-finding APIs to behave in sensible/similar ways, particularly with rich,
+// complex OpenType families, so we do our own font family/style management here
+// instead.
+
+// Much of this is based on the old gfxQuartzFontCache, but adapted for use on
+// all platforms.
+
+struct FontListSizes {
+ uint32_t mFontListSize; // size of the font list and dependent objects
+ // (font family and face names, etc), but NOT
+ // including the font table cache and the cmaps
+ uint32_t
+ mFontTableCacheSize; // memory used for the gfxFontEntry table caches
+ uint32_t mCharMapsSize; // memory used for cmap coverage info
+ uint32_t mLoaderSize; // memory used for (platform-specific) loader
+ uint32_t mSharedSize; // shared-memory use (reported by parent only)
+};
+
+class gfxUserFontSet;
+
+class gfxPlatformFontList : public gfxFontInfoLoader {
+ friend class InitOtherFamilyNamesRunnable;
+
+ public:
+ typedef mozilla::StretchRange StretchRange;
+ typedef mozilla::SlantStyleRange SlantStyleRange;
+ typedef mozilla::WeightRange WeightRange;
+ typedef mozilla::unicode::Script Script;
+
+ // For font family lists loaded from user preferences (prefs such as
+ // font.name-list.<generic>.<langGroup>) that map CSS generics to
+ // platform-specific font families.
+ typedef nsTArray<FontFamily> PrefFontList;
+
+ static gfxPlatformFontList* PlatformFontList() { return sPlatformFontList; }
+
+ static nsresult Init() {
+ NS_ASSERTION(!sPlatformFontList, "What's this doing here?");
+ gfxPlatform::GetPlatform()->CreatePlatformFontList();
+ if (!sPlatformFontList) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ return NS_OK;
+ }
+
+ static void Shutdown() {
+ delete sPlatformFontList;
+ sPlatformFontList = nullptr;
+ }
+
+ virtual ~gfxPlatformFontList();
+
+ // initialize font lists
+ nsresult InitFontList();
+
+ void FontListChanged();
+
+ /**
+ * Gathers (from a platform's underlying font system) the information needed
+ * to initialize a fontlist::Family with its Face members.
+ */
+ virtual void GetFacesInitDataForFamily(
+ const mozilla::fontlist::Family* aFamily,
+ nsTArray<mozilla::fontlist::Face::InitData>& aFaces,
+ bool aLoadCmaps) const {}
+
+ virtual void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
+ nsTArray<nsString>& aListOfFonts);
+
+ // Pass false to notify content that the shared font list has been modified
+ // but not completely invalidated.
+ void UpdateFontList(bool aFullRebuild = true);
+
+ virtual void ClearLangGroupPrefFonts();
+
+ void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray);
+
+ gfxFont* SystemFindFontForChar(uint32_t aCh, uint32_t aNextCh,
+ Script aRunScript,
+ eFontPresentation aPresentation,
+ const gfxFontStyle* aStyle,
+ FontVisibility* aVisibility,
+ FontMatchingStats* aFontMatchingStats);
+
+ // Flags to control optional behaviors in FindAndAddFamilies. The sense
+ // of the bit flags have been chosen such that the default parameter of
+ // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired
+ // behavior, and only a few callsites need to explicitly pass other values.
+ enum class FindFamiliesFlags {
+ // If set, "other" (e.g. localized) family names should be loaded
+ // immediately; if clear, InitOtherFamilyNames is allowed to defer
+ // loading to avoid blocking.
+ eForceOtherFamilyNamesLoading = 1 << 0,
+
+ // If set, FindAndAddFamilies should not check for legacy "styled
+ // family" names to add to the font list. This is used to avoid
+ // a recursive search when using FindFamily to find a potential base
+ // family name for a styled variant.
+ eNoSearchForLegacyFamilyNames = 1 << 1,
+
+ // If set, FindAndAddFamilies will not add a missing entry to
+ // mOtherNamesMissed
+ eNoAddToNamesMissedWhenSearching = 1 << 2,
+
+ // If set, the family name was quoted and so must not be treated as a CSS
+ // generic.
+ eQuotedFamilyName = 1 << 3,
+
+ // If set, "hidden" font families (like ".SF NS Text" on macOS) are
+ // searched in addition to standard user-visible families.
+ eSearchHiddenFamilies = 1 << 4,
+ };
+
+ // Find family(ies) matching aFamily and append to the aOutput array
+ // (there may be multiple results in the case of fontconfig aliases, etc).
+ // Return true if any match was found and appended, false if none.
+ virtual bool FindAndAddFamilies(mozilla::StyleGenericFontFamily aGeneric,
+ const nsACString& aFamily,
+ nsTArray<FamilyAndGeneric>* aOutput,
+ FindFamiliesFlags aFlags,
+ gfxFontStyle* aStyle = nullptr,
+ nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0);
+
+ gfxFontEntry* FindFontForFamily(const nsACString& aFamily,
+ const gfxFontStyle* aStyle);
+
+ mozilla::fontlist::FontList* SharedFontList() const {
+ return mSharedFontList.get();
+ }
+
+ // Create a handle for a single shmem block (identified by index) ready to
+ // be shared to the given processId.
+ void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex,
+ base::ProcessId aPid,
+ base::SharedMemoryHandle* aOut);
+
+ // Populate the array aBlocks with the complete list of shmem handles ready
+ // to be shared to the given processId.
+ void ShareFontListToProcess(nsTArray<base::SharedMemoryHandle>* aBlocks,
+ base::ProcessId aPid);
+
+ void SetCharacterMap(uint32_t aGeneration,
+ const mozilla::fontlist::Pointer& aFacePtr,
+ const gfxSparseBitSet& aMap);
+
+ void SetupFamilyCharMap(uint32_t aGeneration,
+ const mozilla::fontlist::Pointer& aFamilyPtr);
+
+ // Start the async cmap loading process, if not already under way, from the
+ // given family index. (For use in any process that needs font lookups.)
+ void StartCmapLoadingFromFamily(uint32_t aStartIndex);
+
+ // [Parent] Handle request from content process to start cmap loading.
+ void StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex);
+
+ void CancelLoadCmapsTask() {
+ if (mLoadCmapsRunnable) {
+ mLoadCmapsRunnable->Cancel();
+ mLoadCmapsRunnable = nullptr;
+ }
+ }
+
+ // Populate aFamily with face records, and if aLoadCmaps is true, also load
+ // their character maps (rather than leaving this to be done lazily).
+ // Note that even when aFamily->IsInitialized() is true, it can make sense
+ // to call InitializeFamily again if passing aLoadCmaps=true, in order to
+ // ensure cmaps are loaded.
+ [[nodiscard]] bool InitializeFamily(mozilla::fontlist::Family* aFamily,
+ bool aLoadCmaps = false);
+ void InitializeFamily(uint32_t aGeneration, uint32_t aFamilyIndex,
+ bool aLoadCmaps);
+
+ // name lookup table methods
+
+ void AddOtherFamilyName(gfxFontFamily* aFamilyEntry,
+ const nsCString& aOtherFamilyName);
+
+ void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname);
+
+ void AddPostscriptName(gfxFontEntry* aFontEntry,
+ const nsCString& aPostscriptName);
+
+ bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; }
+
+ /**
+ * Read PSName and FullName of the given face, for src:local lookup,
+ * returning true if actually implemented and succeeded.
+ */
+ virtual bool ReadFaceNames(mozilla::fontlist::Family* aFamily,
+ mozilla::fontlist::Face* aFace, nsCString& aPSName,
+ nsCString& aFullName) {
+ return false;
+ }
+
+ // initialize localized family names
+ bool InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading);
+ bool InitOtherFamilyNames(uint32_t aGeneration, bool aDefer);
+
+ // pure virtual functions, to be provided by concrete subclasses
+
+ // get the system default font family
+ FontFamily GetDefaultFont(const gfxFontStyle* aStyle);
+
+ // get the "ultimate" default font, for use if the font list is otherwise
+ // unusable (e.g. in the middle of being updated)
+ gfxFontEntry* GetDefaultFontEntry() { return mDefaultFontEntry.get(); }
+
+ /**
+ * Look up a font by name on the host platform.
+ *
+ * Note that the style attributes (weight, stretch, style) are NOT used in
+ * selecting the platform font, which is looked up by name only; these are
+ * values to be recorded in the new font entry.
+ */
+ virtual gfxFontEntry* LookupLocalFont(const nsACString& aFontName,
+ WeightRange aWeightForEntry,
+ StretchRange aStretchForEntry,
+ SlantStyleRange aStyleForEntry) = 0;
+
+ /**
+ * Create a new platform font from downloaded data (@font-face).
+ *
+ * Note that the style attributes (weight, stretch, style) are NOT related
+ * (necessarily) to any values within the font resource itself; these are
+ * values to be recorded in the new font entry and used for face selection,
+ * in place of whatever inherent style attributes the resource may have.
+ *
+ * This method takes ownership of the data block passed in as aFontData,
+ * and must ensure it is free()'d when no longer required.
+ */
+ virtual gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
+ WeightRange aWeightForEntry,
+ StretchRange aStretchForEntry,
+ SlantStyleRange aStyleForEntry,
+ const uint8_t* aFontData,
+ uint32_t aLength) = 0;
+
+ // get the standard family name on the platform for a given font name
+ // (platforms may override, eg Mac)
+ virtual bool GetStandardFamilyName(const nsCString& aFontName,
+ nsACString& aFamilyName);
+
+ // Get the localized family name for a given font family.
+ bool GetLocalizedFamilyName(const FontFamily& aFamily,
+ nsACString& aFamilyName);
+
+ // get the default font name which is available on the system from
+ // font.name-list.*. if there are no available fonts in the pref,
+ // returns an empty FamilyAndGeneric record.
+ FamilyAndGeneric GetDefaultFontFamily(const nsACString& aLangGroup,
+ const nsACString& aGenericFamily);
+
+ virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
+ FontListSizes* aSizes) const;
+ virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
+ FontListSizes* aSizes) const;
+
+ mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap);
+
+ // search for existing cmap that matches the input
+ // return the input if no match is found
+ gfxCharacterMap* FindCharMap(gfxCharacterMap* aCmap);
+
+ // add a cmap to the shared cmap set
+ gfxCharacterMap* AddCmap(const gfxCharacterMap* aCharMap);
+
+ // remove the cmap from the shared cmap set
+ void RemoveCmap(const gfxCharacterMap* aCharMap);
+
+ // keep track of userfont sets to notify when global fontlist changes occur
+ void AddUserFontSet(gfxUserFontSet* aUserFontSet) {
+ mUserFontSetList.PutEntry(aUserFontSet);
+ }
+
+ void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) {
+ mUserFontSetList.RemoveEntry(aUserFontSet);
+ }
+
+ static const gfxFontEntry::ScriptRange sComplexScriptRanges[];
+
+ void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) {
+ aNumInits = mFontlistInitCount;
+ aLoaderState = (uint32_t)mState;
+ }
+
+ virtual void AddGenericFonts(mozilla::StyleGenericFontFamily aGenericType,
+ nsAtom* aLanguage,
+ nsTArray<FamilyAndGeneric>& aFamilyList);
+
+ /**
+ * Given a Face from the shared font list, return a gfxFontEntry usable
+ * by the current process. This returns a cached entry if available,
+ * otherwise it calls the (platform-specific) CreateFontEntry method to
+ * make one, and adds it to the cache.
+ */
+ gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace,
+ const mozilla::fontlist::Family* aFamily);
+
+ PrefFontList* GetPrefFontsLangGroup(
+ mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang);
+
+ // in some situations, need to make decisions about ambiguous characters, may
+ // need to look at multiple pref langs
+ void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
+ eFontPrefLang aCharLang, eFontPrefLang aPageLang);
+
+ // convert a lang group to enum constant (i.e. "zh-TW" ==>
+ // eFontPrefLang_ChineseTW)
+ static eFontPrefLang GetFontPrefLangFor(const char* aLang);
+
+ // convert a lang group atom to enum constant
+ static eFontPrefLang GetFontPrefLangFor(nsAtom* aLang);
+
+ // convert an enum constant to a lang group atom
+ static nsAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
+
+ // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW
+ // ==> "zh-TW")
+ static const char* GetPrefLangName(eFontPrefLang aLang);
+
+ // map a char code to a font language for Preferences
+ static eFontPrefLang GetFontPrefLangFor(uint32_t aCh);
+
+ // returns true if a pref lang is CJK
+ static bool IsLangCJK(eFontPrefLang aLang);
+
+ // helper method to add a pref lang to an array, if not already in array
+ static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen,
+ eFontPrefLang aAddLang);
+
+ // default serif/sans-serif choice based on font.default.xxx prefs
+ mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang);
+
+ // Returns true if the font family whitelist is not empty. In this case we
+ // ignore the "CSS visibility level"; only the given fonts are present in
+ // the browser's font list.
+ bool IsFontFamilyWhitelistActive() const {
+ return mFontFamilyWhitelistActive;
+ };
+
+ static void FontWhitelistPrefChanged(const char* aPref, void* aClosure);
+
+ bool AddWithLegacyFamilyName(const nsACString& aLegacyName,
+ gfxFontEntry* aFontEntry,
+ FontVisibility aVisibility);
+
+ static const char* GetGenericName(
+ mozilla::StyleGenericFontFamily aGenericType);
+
+ bool SkipFontFallbackForChar(uint32_t aCh) const {
+ return mCodepointsWithNoFonts.test(aCh);
+ }
+
+ // Return whether the given font-family record should be visible to CSS,
+ // given the current font visibility preferences.
+ bool IsVisibleToCSS(const gfxFontFamily& aFamily) const;
+ bool IsVisibleToCSS(const mozilla::fontlist::Family& aFamily) const;
+
+ // Initialize the current visibility level from user prefs.
+ void SetVisibilityLevel();
+
+ // (Re-)initialize the set of codepoints that we know cannot be rendered.
+ void InitializeCodepointsWithNoFonts();
+
+ // If using the shared font list, returns a generation count that is
+ // incremented if/when the platform list is reinitialized (e.g. because
+ // fonts are installed/removed while the browser is running), such that
+ // existing references to shared font family or face objects and character
+ // maps will no longer be valid.
+ // (The legacy (non-shared) list just returns 0 here.)
+ uint32_t GetGeneration() const;
+
+ protected:
+ friend class mozilla::fontlist::FontList;
+ friend class InitOtherFamilyNamesForStylo;
+
+ static bool FamilyInList(const nsACString& aName, const char* aList[],
+ size_t aCount);
+ // Check list is correctly sorted (in debug build only; no-op on release).
+ static void CheckFamilyList(const char* aList[], size_t aCount);
+
+ class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable {
+ public:
+ InitOtherFamilyNamesRunnable()
+ : CancelableRunnable(
+ "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
+ mIsCanceled(false) {}
+
+ NS_IMETHOD Run() override {
+ if (mIsCanceled) {
+ return NS_OK;
+ }
+
+ gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
+ if (!fontList) {
+ return NS_OK;
+ }
+
+ fontList->InitOtherFamilyNamesInternal(true);
+
+ return NS_OK;
+ }
+
+ nsresult Cancel() override {
+ mIsCanceled = true;
+
+ return NS_OK;
+ }
+
+ private:
+ bool mIsCanceled;
+ };
+
+ class MemoryReporter final : public nsIMemoryReporter {
+ ~MemoryReporter() = default;
+
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMEMORYREPORTER
+ };
+
+ template <bool ForNameList>
+ class PrefNameMaker final : public nsAutoCString {
+ void Init(const nsACString& aGeneric, const nsACString& aLangGroup) {
+ if (ForNameList) {
+ AssignLiteral("font.name-list.");
+ } else {
+ AssignLiteral("font.name.");
+ }
+ Append(aGeneric);
+ if (!aLangGroup.IsEmpty()) {
+ Append('.');
+ Append(aLangGroup);
+ }
+ }
+
+ public:
+ PrefNameMaker(const nsACString& aGeneric, const nsACString& aLangGroup) {
+ Init(aGeneric, aLangGroup);
+ }
+
+ PrefNameMaker(const char* aGeneric, const char* aLangGroup) {
+ Init(nsDependentCString(aGeneric), nsDependentCString(aLangGroup));
+ }
+
+ PrefNameMaker(const char* aGeneric, nsAtom* aLangGroup) {
+ if (aLangGroup) {
+ Init(nsDependentCString(aGeneric), nsAtomCString(aLangGroup));
+ } else {
+ Init(nsDependentCString(aGeneric), nsAutoCString());
+ }
+ }
+ };
+
+ typedef PrefNameMaker<false> NamePref;
+ typedef PrefNameMaker<true> NameListPref;
+
+ explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
+
+ static gfxPlatformFontList* sPlatformFontList;
+
+ /**
+ * Convenience method to return the first matching family (if any) as found
+ * by FindAndAddFamilies(). The family will be initialized (synchronously)
+ * if this has not already been done, so the returned pointer, if non-null,
+ * is ready for use.
+ */
+ mozilla::fontlist::Family* FindSharedFamily(
+ const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0);
+
+ gfxFontFamily* FindUnsharedFamily(
+ const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0) {
+ if (SharedFontList()) {
+ return nullptr;
+ }
+ AutoTArray<FamilyAndGeneric, 1> families;
+ if (FindAndAddFamilies(mozilla::StyleGenericFontFamily::None, aFamily,
+ &families, aFlags, aStyle, aLanguage,
+ aDevToCssSize)) {
+ return families[0].mFamily.mUnshared;
+ }
+ return nullptr;
+ }
+
+ FontFamily FindFamily(const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr,
+ nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0) {
+ if (SharedFontList()) {
+ return FontFamily(
+ FindSharedFamily(aFamily, aFlags, aStyle, aLanguage, aDevToCssSize));
+ }
+ return FontFamily(
+ FindUnsharedFamily(aFamily, aFlags, aStyle, aLanguage, aDevToCssSize));
+ }
+
+ // Lookup family name in global family list without substitutions or
+ // localized family name lookup. Used for common font fallback families.
+ gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) {
+ nsAutoCString key;
+ gfxFontFamily* familyEntry;
+ GenerateFontListKey(aFamily, key);
+ if ((familyEntry = mFontFamilies.GetWeak(key))) {
+ return CheckFamily(familyEntry);
+ }
+ return nullptr;
+ }
+
+ // returns default font for a given character, null otherwise
+ gfxFont* CommonFontFallback(uint32_t aCh, uint32_t aNextCh, Script aRunScript,
+ eFontPresentation aPresentation,
+ const gfxFontStyle* aMatchStyle,
+ FontFamily& aMatchedFamily);
+
+ // Search fonts system-wide for a given character, null if not found.
+ gfxFont* GlobalFontFallback(uint32_t aCh, uint32_t aNextCh, Script aRunScript,
+ eFontPresentation aPresentation,
+ const gfxFontStyle* aMatchStyle,
+ uint32_t& aCmapCount, FontFamily& aMatchedFamily,
+ FontMatchingStats* aFontMatchingStats);
+
+ // Platform-specific implementation of global font fallback, if any;
+ // this may return nullptr in which case the default cmap-based fallback
+ // will be performed.
+ virtual gfxFontEntry* PlatformGlobalFontFallback(
+ const uint32_t aCh, Script aRunScript, const gfxFontStyle* aMatchStyle,
+ FontFamily& aMatchedFamily) {
+ return nullptr;
+ }
+
+ // whether system-based font fallback is used or not
+ // if system fallback is used, no need to load all cmaps
+ virtual bool UsesSystemFallback() { return false; }
+
+ void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
+ eFontPrefLang aCharLang, eFontPrefLang aPageLang);
+
+ // verifies that a family contains a non-zero font count
+ gfxFontFamily* CheckFamily(gfxFontFamily* aFamily);
+
+ // initialize localized family names
+ void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
+ void CancelInitOtherFamilyNamesTask();
+
+ // search through font families, looking for a given name, initializing
+ // facename lists along the way. first checks all families with names
+ // close to face name, then searchs all families if not found.
+ gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName);
+
+ // helper method for finding fullname/postscript names in facename lists
+ gfxFontEntry* FindFaceName(const nsACString& aFaceName);
+
+ // look up a font by name, for cases where platform font list
+ // maintains explicit mappings of fullname/psname ==> font
+ virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFontName);
+
+ gfxFontEntry* LookupInSharedFaceNameList(const nsACString& aFaceName,
+ WeightRange aWeightForEntry,
+ StretchRange aStretchForEntry,
+ SlantStyleRange aStyleForEntry);
+
+ // commonly used fonts for which the name table should be loaded at startup
+ virtual void PreloadNamesList();
+
+ // load the bad underline blocklist from pref.
+ void LoadBadUnderlineList();
+
+ void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
+
+ virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames);
+
+ // helper function to map lang to lang group
+ nsAtom* GetLangGroup(nsAtom* aLanguage);
+
+ // gfxFontInfoLoader overrides, used to load in font cmaps
+ void InitLoader() override;
+ bool LoadFontInfo() override;
+ void CleanupLoader() override;
+
+ // read the loader initialization prefs, and start it
+ void GetPrefsAndStartLoader();
+
+ // for font list changes that affect all documents
+ void ForceGlobalReflow();
+
+ // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
+ // be discarded (not potentially reused to satisfy the rebuilt rules),
+ // because they may no longer be valid.
+ void RebuildLocalFonts(bool aForgetLocalFaces = false);
+
+ void ResolveGenericFontNames(mozilla::StyleGenericFontFamily aGenericType,
+ eFontPrefLang aPrefLang,
+ PrefFontList* aGenericFamilies);
+
+ void ResolveEmojiFontNames(PrefFontList* aGenericFamilies);
+
+ void GetFontFamiliesFromGenericFamilies(
+ mozilla::StyleGenericFontFamily aGenericType,
+ nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
+ PrefFontList* aFontFamilies);
+
+ virtual nsresult InitFontListForPlatform() = 0;
+ virtual void InitSharedFontListForPlatform() {}
+
+ virtual gfxFontEntry* CreateFontEntry(
+ mozilla::fontlist::Face* aFace,
+ const mozilla::fontlist::Family* aFamily) {
+ return nullptr;
+ }
+
+ /**
+ * Methods to apply the font.system.whitelist anti-fingerprinting pref,
+ * by filtering the list of installed fonts so that only whitelisted families
+ * are exposed.
+ * There are separate implementations of this for the per-process font list
+ * and for the shared-memory font list.
+ */
+ void ApplyWhitelist();
+ void ApplyWhitelist(nsTArray<mozilla::fontlist::Family::InitData>& aFamilies);
+
+ // Create a new gfxFontFamily of the appropriate subclass for the platform,
+ // used when AddWithLegacyFamilyName needs to create a new family.
+ virtual gfxFontFamily* CreateFontFamily(const nsACString& aName,
+ FontVisibility aVisibility) const = 0;
+
+ /**
+ * For the post-startup font info loader task.
+ * Perform platform-specific work to read alternate names (if any) for a
+ * font family, recording them in mAliasTable. Once alternate names have been
+ * loaded for all families, the accumulated records are stored in the shared
+ * font list's mAliases list.
+ * Some platforms (currently Linux/fontconfig) may load alternate names as
+ * part of initially populating the font list with family records, in which
+ * case this method is unused.
+ */
+ virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
+ bool aNeedFullnamePostscriptNames) {}
+
+ typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontFamily> FontFamilyTable;
+ typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontEntry> FontEntryTable;
+
+ // used by memory reporter to accumulate sizes of family names in the table
+ static size_t SizeOfFontFamilyTableExcludingThis(
+ const FontFamilyTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
+ static size_t SizeOfFontEntryTableExcludingThis(
+ const FontEntryTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
+
+ // Platform-specific helper for GetDefaultFont(...).
+ virtual FontFamily GetDefaultFontForPlatform(const gfxFontStyle* aStyle,
+ nsAtom* aLanguage = nullptr) = 0;
+
+ // Protects mFontFamilies.
+ mozilla::Mutex mFontFamiliesMutex;
+
+ // canonical family name ==> family entry (unique, one name per family entry)
+ FontFamilyTable mFontFamilies;
+
+ // other family name ==> family entry (not unique, can have multiple names per
+ // family entry, only names *other* than the canonical names are stored here)
+ FontFamilyTable mOtherFamilyNames;
+
+ // flag set after InitOtherFamilyNames is called upon first name lookup miss
+ bool mOtherFamilyNamesInitialized;
+
+ // The pending InitOtherFamilyNames() task.
+ RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
+
+ // flag set after fullname and Postcript name lists are populated
+ bool mFaceNameListsInitialized;
+
+ struct ExtraNames {
+ ExtraNames() = default;
+
+ // fullname ==> font entry (unique, one name per font entry)
+ FontEntryTable mFullnames{64};
+ // Postscript name ==> font entry (unique, one name per font entry)
+ FontEntryTable mPostscriptNames{64};
+ };
+ mozilla::UniquePtr<ExtraNames> mExtraNames;
+
+ // face names missed when face name loading takes a long time
+ mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mFaceNamesMissed;
+
+ // localized family names missed when face name loading takes a long time
+ mozilla::UniquePtr<nsTHashtable<nsCStringHashKey>> mOtherNamesMissed;
+
+ typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>,
+ size_t(mozilla::StyleGenericFontFamily::None),
+ size_t(
+ mozilla::StyleGenericFontFamily::MozEmoji)>
+ PrefFontsForLangGroup;
+ mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First,
+ eFontPrefLang_Count>
+ mLangGroupPrefFonts;
+ mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
+
+ // when system-wide font lookup fails for a character, cache it to skip future
+ // searches
+ gfxSparseBitSet mCodepointsWithNoFonts;
+
+ // the family to use for U+FFFD fallback, to avoid expensive search every time
+ // on pages with lots of problems
+ FontFamily mReplacementCharFallbackFamily;
+
+ // Sorted array of lowercased family names; use ContainsSorted to test
+ nsTArray<nsCString> mBadUnderlineFamilyNames;
+
+ // character map data shared across families
+ // contains weak ptrs to cmaps shared by font entry objects
+ nsTHashtable<CharMapHashKey> mSharedCmaps;
+
+ nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps;
+
+ // data used as part of the font cmap loading process
+ nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad;
+ uint32_t mStartIndex;
+ uint32_t mNumFamilies;
+
+ // xxx - info for diagnosing no default font aborts
+ // see bugs 636957, 1070983, 1189129
+ uint32_t mFontlistInitCount; // num times InitFontList called
+
+ nsTHashtable<nsPtrHashKey<gfxUserFontSet>> mUserFontSetList;
+
+ nsLanguageAtomService* mLangService;
+
+ nsTArray<uint32_t> mCJKPrefLangs;
+ nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup;
+
+ mozilla::UniquePtr<mozilla::fontlist::FontList> mSharedFontList;
+
+ nsClassHashtable<nsCStringHashKey, mozilla::fontlist::AliasData> mAliasTable;
+ nsDataHashtable<nsCStringHashKey, mozilla::fontlist::LocalFaceRec::InitData>
+ mLocalNameTable;
+
+ nsRefPtrHashtable<nsPtrHashKey<mozilla::fontlist::Face>, gfxFontEntry>
+ mFontEntries;
+
+ RefPtr<gfxFontEntry> mDefaultFontEntry;
+
+ RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
+ uint32_t mStartedLoadingCmapsFrom = 0xffffffffu;
+
+ FontVisibility mVisibilityLevel = FontVisibility::Unknown;
+
+ bool mFontFamilyWhitelistActive;
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
+
+#endif /* GFXPLATFORMFONTLIST_H_ */