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.h1074
1 files changed, 1074 insertions, 0 deletions
diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h
new file mode 100644
index 0000000000..4d5b9e4015
--- /dev/null
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -0,0 +1,1074 @@
+/* -*- 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 "nsTHashMap.h"
+#include "nsTHashSet.h"
+#include "nsRefPtrHashtable.h"
+#include "nsTHashtable.h"
+
+#include "gfxFontUtils.h"
+#include "gfxFontInfoLoader.h"
+#include "gfxFont.h"
+#include "gfxFontConstants.h"
+#include "gfxPlatform.h"
+#include "SharedFontList.h"
+
+#include "nsIMemoryReporter.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/EnumeratedArray.h"
+#include "mozilla/FontPropertyTypes.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/RangedArray.h"
+#include "mozilla/RecursiveMutex.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.get(); }
+
+ bool KeyEquals(const gfxCharacterMap* aCharMap) const {
+ MOZ_ASSERT(!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:
+ friend class gfxPlatformFontList;
+
+ // gfxCharacterMap::Release() will notify us when the refcount of a
+ // charmap drops to 1; at that point, we'll lock the cache, check if
+ // the charmap is owned by the cache and this is still the only ref,
+ // and if so, delete it.
+ RefPtr<gfxCharacterMap> 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 mCharMap.ToPtr<const SharedBitSet>(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::intl::Script Script;
+
+ using AutoLock = mozilla::RecursiveMutexAutoLock;
+ using AutoUnlock = mozilla::RecursiveMutexAutoUnlock;
+
+ // Class used to hold cached copies of the font-name prefs, so that they can
+ // be accessed from non-main-thread callers who are not allowed to touch the
+ // Preferences service.
+ class FontPrefs final {
+ public:
+ using HashMap = nsTHashMap<nsCStringHashKey, nsCString>;
+
+ FontPrefs();
+ ~FontPrefs() = default;
+
+ FontPrefs(const FontPrefs& aOther) = delete;
+ FontPrefs& operator=(const FontPrefs& aOther) = delete;
+
+ // Lookup the font.name.<foo> or font.name-list.<foo> pref for a given
+ // generic+langgroup pair.
+ bool LookupName(const nsACString& aPref, nsACString& aValue) const;
+ bool LookupNameList(const nsACString& aPref, nsACString& aValue) const;
+
+ // Does the font.name-list.emoji pref have a user-set value?
+ bool EmojiHasUserValue() const { return mEmojiHasUserValue; }
+
+ // Expose iterators over all the defined prefs of each type.
+ HashMap::ConstIterator NameIter() const { return mFontName.ConstIter(); }
+ HashMap::ConstIterator NameListIter() const {
+ return mFontNameList.ConstIter();
+ }
+
+ private:
+ static constexpr char kNamePrefix[] = "font.name.";
+ static constexpr char kNameListPrefix[] = "font.name-list.";
+
+ void Init();
+
+ HashMap mFontName;
+ HashMap mFontNameList;
+ bool mEmojiHasUserValue = false;
+ };
+
+ // 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;
+
+ // Return the global font-list singleton, or NULL if aMustInitialize is false
+ // and it has not yet been fully initialized.
+ static gfxPlatformFontList* PlatformFontList(bool aMustInitialize = true) {
+ if (!aMustInitialize &&
+ !(sPlatformFontList && sPlatformFontList->IsInitialized())) {
+ return nullptr;
+ }
+ // If there is a font-list initialization thread, we need to let it run
+ // to completion before the font list can be used for anything else.
+ if (sInitFontListThread) {
+ // If we're currently on the initialization thread, just continue;
+ // otherwise wait for it to finish.
+ if (IsInitFontListThread()) {
+ return sPlatformFontList;
+ }
+ PR_JoinThread(sInitFontListThread);
+ sInitFontListThread = nullptr;
+ // If font-list initialization failed, the thread will have cleared
+ // the static sPlatformFontList pointer; we cannot proceed without any
+ // usable fonts.
+ if (!sPlatformFontList) {
+ MOZ_CRASH("Could not initialize gfxPlatformFontList");
+ }
+ }
+ if (!sPlatformFontList->IsInitialized()) {
+ if (!sPlatformFontList->InitFontList()) {
+ MOZ_CRASH("Could not initialize gfxPlatformFontList");
+ }
+ }
+ return sPlatformFontList;
+ }
+
+ static bool Initialize(gfxPlatformFontList* aList);
+
+ static void Shutdown() {
+ // Ensure any font-list initialization thread is finished before we delete
+ // the platform fontlist singleton, which that thread may try to use.
+ if (sInitFontListThread && !IsInitFontListThread()) {
+ PR_JoinThread(sInitFontListThread);
+ sInitFontListThread = nullptr;
+ }
+ delete sPlatformFontList;
+ sPlatformFontList = nullptr;
+ }
+
+ bool IsInitialized() const { return mFontlistInitCount; }
+
+ virtual ~gfxPlatformFontList();
+
+ // Initialize font lists; return true on success, false if something fails.
+ bool 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);
+
+ void ClearLangGroupPrefFonts() {
+ AutoLock lock(mLock);
+ ClearLangGroupPrefFontsLocked();
+ }
+ virtual void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock);
+
+ void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray);
+
+ already_AddRefed<gfxFont> SystemFindFontForChar(
+ nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
+ Script aRunScript, eFontPresentation aPresentation,
+ const gfxFontStyle* aStyle, FontVisibility* aVisibility);
+
+ // 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.
+ bool FindAndAddFamilies(
+ nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
+ const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
+ FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
+ nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0);
+
+ virtual bool FindAndAddFamiliesLocked(
+ nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
+ const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
+ FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
+ nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0)
+ MOZ_REQUIRES(mLock);
+
+ gfxFontEntry* FindFontForFamily(nsPresContext* aPresContext,
+ 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 ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
+ base::SharedMemoryHandle aHandle);
+
+ base::SharedMemoryHandle ShareShmBlockToProcess(uint32_t aIndex,
+ base::ProcessId aPid);
+
+ void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias,
+ uint32_t aFaceIndex, const gfxSparseBitSet& aMap);
+
+ void SetupFamilyCharMap(uint32_t aGeneration, uint32_t aIndex, bool aAlias);
+
+ // 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 AddOtherFamilyNames(gfxFontFamily* aFamilyEntry,
+ const nsTArray<nsCString>& aOtherFamilyNames);
+
+ void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname) {
+ AutoLock lock(mLock);
+ AddFullnameLocked(aFontEntry, aFullname);
+ }
+ void AddFullnameLocked(gfxFontEntry* aFontEntry, const nsCString& aFullname)
+ MOZ_REQUIRES(mLock);
+
+ void AddPostscriptName(gfxFontEntry* aFontEntry,
+ const nsCString& aPostscriptName) {
+ AutoLock lock(mLock);
+ AddPostscriptNameLocked(aFontEntry, aPostscriptName);
+ }
+ void AddPostscriptNameLocked(gfxFontEntry* aFontEntry,
+ const nsCString& aPostscriptName)
+ MOZ_REQUIRES(mLock);
+
+ 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(const mozilla::fontlist::Family* aFamily,
+ const 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(nsPresContext* aPresContext,
+ const gfxFontStyle* aStyle);
+ FontFamily GetDefaultFontLocked(nsPresContext* aPresContext,
+ const gfxFontStyle* aStyle)
+ MOZ_REQUIRES(mLock);
+
+ // get the "ultimate" default font, for use if the font list is otherwise
+ // unusable (e.g. in the middle of being updated)
+ gfxFontEntry* GetDefaultFontEntry() {
+ AutoLock lock(mLock);
+ 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(nsPresContext* aPresContext,
+ 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) {
+ AutoLock lock(mLock);
+ return GetShmemCharMapLocked(aCmap);
+ }
+ mozilla::fontlist::Pointer GetShmemCharMapLocked(const gfxSparseBitSet* aCmap)
+ MOZ_REQUIRES(mLock);
+
+ // Search for existing cmap that matches the input; return the input if no
+ // match is found.
+ already_AddRefed<gfxCharacterMap> FindCharMap(gfxCharacterMap* aCmap);
+
+ // Remove the cmap from the shared cmap set if it holds the only remaining
+ // reference to the object.
+ void MaybeRemoveCmap(gfxCharacterMap* aCharMap);
+
+ // Keep track of userfont sets to notify when global fontlist changes occur.
+ void AddUserFontSet(gfxUserFontSet* aUserFontSet) {
+ AutoLock lock(mLock);
+ mUserFontSetList.Insert(aUserFontSet);
+ }
+
+ void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) {
+ AutoLock lock(mLock);
+ mUserFontSetList.Remove(aUserFontSet);
+ }
+
+ static const gfxFontEntry::ScriptRange sComplexScriptRanges[];
+
+ void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) {
+ aNumInits = mFontlistInitCount;
+ aLoaderState = (uint32_t)mState;
+ }
+
+ virtual void AddGenericFonts(nsPresContext* aPresContext,
+ 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) {
+ AutoLock lock(mLock);
+ return GetOrCreateFontEntryLocked(aFace, aFamily);
+ }
+ gfxFontEntry* GetOrCreateFontEntryLocked(
+ mozilla::fontlist::Face* aFace, const mozilla::fontlist::Family* aFamily)
+ MOZ_REQUIRES(mLock);
+
+ const FontPrefs* GetFontPrefs() const MOZ_REQUIRES(mLock) {
+ return mFontPrefs.get();
+ }
+
+ bool EmojiPrefHasUserValue() const {
+ AutoLock lock(mLock);
+ return mFontPrefs->EmojiHasUserValue();
+ }
+
+ PrefFontList* GetPrefFontsLangGroup(
+ nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
+ eFontPrefLang aPrefLang) {
+ AutoLock lock(mLock);
+ return GetPrefFontsLangGroupLocked(aPresContext, aGenericType, aPrefLang);
+ }
+ PrefFontList* GetPrefFontsLangGroupLocked(
+ nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
+ eFontPrefLang aPrefLang) MOZ_REQUIRES(mLock);
+
+ // 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(FontVisibility aVisibility, uint32_t aCh) const {
+ AutoLock lock(mLock);
+ return mCodepointsWithNoFonts[aVisibility].test(aCh);
+ }
+
+ // Return whether the given font-family record should be visible to CSS,
+ // in a context with the given FontVisibility setting.
+ bool IsVisibleToCSS(const gfxFontFamily& aFamily,
+ FontVisibility aVisibility) const;
+ bool IsVisibleToCSS(const mozilla::fontlist::Family& aFamily,
+ FontVisibility aVisibility) const;
+
+ // (Re-)initialize the set of codepoints that we know cannot be rendered.
+ void InitializeCodepointsWithNoFonts() MOZ_REQUIRES(mLock);
+
+ // 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;
+
+ // Sometimes we need to know if we're on the InitFontList startup thread.
+ static bool IsInitFontListThread() {
+ return PR_GetCurrentThread() == sInitFontListThread;
+ }
+
+ bool IsKnownIconFontFamily(const nsAtom* aFamilyName) const;
+ void LoadIconFontOverrideList();
+
+ void Lock() MOZ_CAPABILITY_ACQUIRE(mLock) { mLock.Lock(); }
+ void Unlock() MOZ_CAPABILITY_RELEASE(mLock) { mLock.Unlock(); }
+
+ // This is only public because some external callers want to be able to
+ // assert about the locked status.
+ mutable mozilla::RecursiveMutex mLock;
+
+ protected:
+ friend class mozilla::fontlist::FontList;
+ friend class InitOtherFamilyNamesForStylo;
+
+ template <size_t N>
+ static bool FamilyInList(const nsACString& aName, const char* (&aList)[N]) {
+ return FamilyInList(aName, aList, N);
+ }
+ 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).
+ template <size_t N>
+ static void CheckFamilyList(const char* (&aList)[N]) {
+ CheckFamilyList(aList, N);
+ }
+ 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
+ };
+
+ class PrefName final : public nsAutoCString {
+ void Init(const nsACString& aGeneric, const nsACString& aLangGroup) {
+ Assign(aGeneric);
+ if (!aLangGroup.IsEmpty()) {
+ Append('.');
+ Append(aLangGroup);
+ }
+ }
+
+ public:
+ PrefName(const nsACString& aGeneric, const nsACString& aLangGroup) {
+ Init(aGeneric, aLangGroup);
+ }
+
+ PrefName(const char* aGeneric, const char* aLangGroup) {
+ Init(nsDependentCString(aGeneric), nsDependentCString(aLangGroup));
+ }
+
+ PrefName(const char* aGeneric, nsAtom* aLangGroup) {
+ if (aLangGroup) {
+ Init(nsDependentCString(aGeneric), nsAtomCString(aLangGroup));
+ } else {
+ Init(nsDependentCString(aGeneric), nsAutoCString());
+ }
+ }
+ };
+
+ 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(
+ nsPresContext* aPresContext, const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock);
+
+ gfxFontFamily* FindUnsharedFamily(
+ nsPresContext* aPresContext, const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) {
+ if (SharedFontList()) {
+ return nullptr;
+ }
+ AutoTArray<FamilyAndGeneric, 1> families;
+ if (FindAndAddFamiliesLocked(
+ aPresContext, mozilla::StyleGenericFontFamily::None, aFamily,
+ &families, aFlags, aStyle, aLanguage, aDevToCssSize)) {
+ return families[0].mFamily.mUnshared;
+ }
+ return nullptr;
+ }
+
+ FontFamily FindFamily(nsPresContext* aPresContext, const nsACString& aFamily,
+ FindFamiliesFlags aFlags = FindFamiliesFlags(0),
+ gfxFontStyle* aStyle = nullptr,
+ nsAtom* aLanguage = nullptr,
+ gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) {
+ if (SharedFontList()) {
+ return FontFamily(FindSharedFamily(aPresContext, aFamily, aFlags, aStyle,
+ aLanguage, aDevToCssSize));
+ }
+ return FontFamily(FindUnsharedFamily(aPresContext, 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)
+ MOZ_REQUIRES(mLock) {
+ 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
+ already_AddRefed<gfxFont> CommonFontFallback(nsPresContext* aPresContext,
+ uint32_t aCh, uint32_t aNextCh,
+ Script aRunScript,
+ eFontPresentation aPresentation,
+ const gfxFontStyle* aMatchStyle,
+ FontFamily& aMatchedFamily)
+ MOZ_REQUIRES(mLock);
+
+ // Search fonts system-wide for a given character, null if not found.
+ already_AddRefed<gfxFont> GlobalFontFallback(
+ nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
+ Script aRunScript, eFontPresentation aPresentation,
+ const gfxFontStyle* aMatchStyle, uint32_t& aCmapCount,
+ FontFamily& aMatchedFamily) MOZ_REQUIRES(mLock);
+
+ // 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(
+ nsPresContext* aPresContext, 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)
+ MOZ_REQUIRES(mLock);
+
+ // verifies that a family contains a non-zero font count
+ gfxFontFamily* CheckFamily(gfxFontFamily* aFamily) MOZ_REQUIRES(mLock);
+
+ // initialize localized family names
+ void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
+ void CancelInitOtherFamilyNamesTask();
+
+ void AddToMissedNames(const nsCString& aKey) MOZ_REQUIRES(mLock);
+
+ // 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)
+ MOZ_REQUIRES(mLock);
+
+ // helper method for finding fullname/postscript names in facename lists
+ gfxFontEntry* FindFaceName(const nsACString& aFaceName) MOZ_REQUIRES(mLock);
+
+ // look up a font by name, for cases where platform font list
+ // maintains explicit mappings of fullname/psname ==> font
+ virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFaceName)
+ MOZ_REQUIRES(mLock);
+
+ gfxFontEntry* LookupInSharedFaceNameList(nsPresContext* aPresContext,
+ const nsACString& aFaceName,
+ WeightRange aWeightForEntry,
+ StretchRange aStretchForEntry,
+ SlantStyleRange aStyleForEntry)
+ MOZ_REQUIRES(mLock);
+
+ // load the bad underline blocklist from pref.
+ void LoadBadUnderlineList();
+
+ void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
+
+ virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames)
+ MOZ_REQUIRES(mLock);
+
+ // helper function to map lang to lang group
+ nsAtom* GetLangGroup(nsAtom* aLanguage);
+
+ // gfxFontInfoLoader overrides, used to load in font cmaps
+ void InitLoader() MOZ_REQUIRES(mLock) override;
+ bool LoadFontInfo() override;
+ void CleanupLoader() override;
+
+ void ForceGlobalReflowLocked(
+ gfxPlatform::NeedsReframe aNeedsReframe,
+ gfxPlatform::BroadcastToChildren aBroadcastToChildren =
+ gfxPlatform::BroadcastToChildren::Yes) MOZ_REQUIRES(mLock);
+
+ // read the loader initialization prefs, and start it
+ void GetPrefsAndStartLoader();
+
+ // 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) MOZ_REQUIRES(mLock);
+
+ void ResolveGenericFontNames(nsPresContext* aPresContext,
+ mozilla::StyleGenericFontFamily aGenericType,
+ eFontPrefLang aPrefLang,
+ PrefFontList* aGenericFamilies)
+ MOZ_REQUIRES(mLock);
+
+ void ResolveEmojiFontNames(nsPresContext* aPresContext,
+ PrefFontList* aGenericFamilies)
+ MOZ_REQUIRES(mLock);
+
+ void GetFontFamiliesFromGenericFamilies(
+ nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
+ nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
+ PrefFontList* aFontFamilies) MOZ_REQUIRES(mLock);
+
+ virtual nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) = 0;
+ virtual void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) {}
+
+ 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() MOZ_REQUIRES(mLock);
+ 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)
+ MOZ_REQUIRES(mLock) {}
+
+ 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(nsPresContext* aPresContext,
+ const gfxFontStyle* aStyle,
+ nsAtom* aLanguage = nullptr)
+ MOZ_REQUIRES(mLock) = 0;
+
+ // canonical family name ==> family entry (unique, one name per family entry)
+ FontFamilyTable mFontFamilies MOZ_GUARDED_BY(mLock);
+
+ // 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 MOZ_GUARDED_BY(mLock);
+
+ // flag set after InitOtherFamilyNames is called upon first name lookup miss
+ mozilla::Atomic<bool> mOtherFamilyNamesInitialized;
+
+ // The pending InitOtherFamilyNames() task.
+ RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
+
+ // flag set after fullname and Postcript name lists are populated
+ mozilla::Atomic<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};
+ };
+ // The lock is needed to guard access to the actual name tables, but does not
+ // need to be held to just test whether mExtraNames is non-null as it is set
+ // during initialization before other threads have a chance to see it.
+ mozilla::UniquePtr<ExtraNames> mExtraNames MOZ_PT_GUARDED_BY(mLock);
+
+ // face names missed when face name loading takes a long time
+ mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed
+ MOZ_GUARDED_BY(mLock);
+
+ // localized family names missed when face name loading takes a long time
+ mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed
+ MOZ_GUARDED_BY(mLock);
+
+ 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 MOZ_GUARDED_BY(mLock);
+ mozilla::UniquePtr<PrefFontList> mEmojiPrefFont MOZ_GUARDED_BY(mLock);
+
+ // When system-wide font lookup fails for a character, cache it to skip future
+ // searches. This is an array of bitsets, one for each FontVisibility level.
+ mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count,
+ gfxSparseBitSet>
+ mCodepointsWithNoFonts MOZ_GUARDED_BY(mLock);
+
+ // the family to use for U+FFFD fallback, to avoid expensive search every time
+ // on pages with lots of problems
+ mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count, FontFamily>
+ mReplacementCharFallbackFamily MOZ_GUARDED_BY(mLock);
+
+ // 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 MOZ_GUARDED_BY(mLock);
+
+ nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps MOZ_GUARDED_BY(mLock);
+
+ // data used as part of the font cmap loading process
+ nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad MOZ_GUARDED_BY(mLock);
+ uint32_t mStartIndex MOZ_GUARDED_BY(mLock) = 0;
+ uint32_t mNumFamilies MOZ_GUARDED_BY(mLock) = 0;
+
+ // xxx - info for diagnosing no default font aborts
+ // see bugs 636957, 1070983, 1189129
+ uint32_t mFontlistInitCount = 0; // num times InitFontList called
+
+ nsTHashSet<gfxUserFontSet*> mUserFontSetList MOZ_GUARDED_BY(mLock);
+
+ nsLanguageAtomService* mLangService = nullptr;
+
+ nsTArray<uint32_t> mCJKPrefLangs MOZ_GUARDED_BY(mLock);
+ nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup
+ MOZ_GUARDED_BY(mLock);
+
+ nsTArray<nsCString> mEnabledFontsList;
+ nsTHashSet<nsCString> mIconFontsSet;
+
+ mozilla::UniquePtr<mozilla::fontlist::FontList> mSharedFontList;
+
+ nsClassHashtable<nsCStringHashKey, mozilla::fontlist::AliasData> mAliasTable;
+ nsTHashMap<nsCStringHashKey, mozilla::fontlist::LocalFaceRec::InitData>
+ mLocalNameTable;
+
+ nsRefPtrHashtable<nsPtrHashKey<const mozilla::fontlist::Face>, gfxFontEntry>
+ mFontEntries MOZ_GUARDED_BY(mLock);
+
+ mozilla::UniquePtr<FontPrefs> mFontPrefs;
+
+ RefPtr<gfxFontEntry> mDefaultFontEntry MOZ_GUARDED_BY(mLock);
+
+ RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
+ uint32_t mStartedLoadingCmapsFrom MOZ_GUARDED_BY(mLock) = 0xffffffffu;
+
+ bool mFontFamilyWhitelistActive = false;
+
+ static PRThread* sInitFontListThread;
+};
+
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
+
+#endif /* GFXPLATFORMFONTLIST_H_ */