Bug 1758688 [wpt PR 33067] - [FedCM] Make revoke a non-static method, a=testonly
[gecko.git] / gfx / thebes / gfxPlatformFontList.h
blob3bfef70d5cadf0ff2474944a0d0941226f23fa20
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef GFXPLATFORMFONTLIST_H_
7 #define GFXPLATFORMFONTLIST_H_
9 #include "nsClassHashtable.h"
10 #include "nsTHashMap.h"
11 #include "nsTHashSet.h"
12 #include "nsRefPtrHashtable.h"
13 #include "nsTHashtable.h"
15 #include "gfxFontUtils.h"
16 #include "gfxFontInfoLoader.h"
17 #include "gfxFont.h"
18 #include "gfxFontConstants.h"
19 #include "gfxPlatform.h"
20 #include "SharedFontList.h"
22 #include "nsIMemoryReporter.h"
23 #include "mozilla/Attributes.h"
24 #include "mozilla/EnumeratedArray.h"
25 #include "mozilla/FontPropertyTypes.h"
26 #include "mozilla/MemoryReporting.h"
27 #include "mozilla/Mutex.h"
28 #include "mozilla/RangedArray.h"
29 #include "nsLanguageAtomService.h"
31 #include "base/shared_memory.h"
33 namespace mozilla {
34 namespace fontlist {
35 struct AliasData;
37 } // namespace mozilla
39 class CharMapHashKey : public PLDHashEntryHdr {
40 public:
41 typedef gfxCharacterMap* KeyType;
42 typedef const gfxCharacterMap* KeyTypePointer;
44 explicit CharMapHashKey(const gfxCharacterMap* aCharMap)
45 : mCharMap(const_cast<gfxCharacterMap*>(aCharMap)) {
46 MOZ_COUNT_CTOR(CharMapHashKey);
48 CharMapHashKey(const CharMapHashKey& toCopy) : mCharMap(toCopy.mCharMap) {
49 MOZ_COUNT_CTOR(CharMapHashKey);
51 MOZ_COUNTED_DTOR(CharMapHashKey)
53 gfxCharacterMap* GetKey() const { return mCharMap; }
55 bool KeyEquals(const gfxCharacterMap* aCharMap) const {
56 NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly,
57 "custom cmap used in shared cmap hashtable");
58 // cmaps built on the fly never match
59 if (aCharMap->mHash != mCharMap->mHash) {
60 return false;
62 return mCharMap->Equals(aCharMap);
65 static const gfxCharacterMap* KeyToPointer(gfxCharacterMap* aCharMap) {
66 return aCharMap;
68 static PLDHashNumber HashKey(const gfxCharacterMap* aCharMap) {
69 return aCharMap->mHash;
72 enum { ALLOW_MEMMOVE = true };
74 protected:
75 // charMaps are not owned by the shared cmap cache, but it will be notified
76 // by gfxCharacterMap::Release() when an entry is about to be deleted
77 gfxCharacterMap* MOZ_NON_OWNING_REF mCharMap;
80 /**
81 * A helper class used to create a SharedBitSet instance in a FontList's shared
82 * memory, while ensuring that we avoid bloating memory by avoiding creating
83 * duplicate instances.
85 class ShmemCharMapHashEntry final : public PLDHashEntryHdr {
86 public:
87 typedef const gfxSparseBitSet* KeyType;
88 typedef const gfxSparseBitSet* KeyTypePointer;
90 /**
91 * Creation from a gfxSparseBitSet creates not only the ShmemCharMapHashEntry
92 * itself, but also a SharedBitSet in shared memory.
93 * Only the parent process creates and manages these entries.
95 explicit ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap);
97 ShmemCharMapHashEntry(ShmemCharMapHashEntry&&) = default;
98 ShmemCharMapHashEntry& operator=(ShmemCharMapHashEntry&&) = default;
101 * Return a shared-memory Pointer that refers to the wrapped SharedBitSet.
102 * This can be passed to content processes to give them access to the same
103 * SharedBitSet as the parent stored.
105 mozilla::fontlist::Pointer GetCharMap() const { return mCharMap; }
107 bool KeyEquals(KeyType aCharMap) const {
108 // mHash is a 32-bit Adler checksum of the bitset; if it doesn't match we
109 // can immediately reject it as non-matching, but if it is equal we still
110 // need to do a full equality check below.
111 if (mHash != aCharMap->GetChecksum()) {
112 return false;
115 return static_cast<const SharedBitSet*>(mCharMap.ToPtr(mList))
116 ->Equals(aCharMap);
119 static KeyTypePointer KeyToPointer(KeyType aCharMap) { return aCharMap; }
120 static PLDHashNumber HashKey(KeyType aCharMap) {
121 return aCharMap->GetChecksum();
124 enum { ALLOW_MEMMOVE = true };
126 private:
127 // charMaps are stored in the shared memory that FontList objects point to,
128 // and are never deleted until the FontList (all referencing font lists,
129 // actually) have gone away.
130 mozilla::fontlist::FontList* mList;
131 mozilla::fontlist::Pointer mCharMap;
132 uint32_t mHash;
135 // gfxPlatformFontList is an abstract class for the global font list on the
136 // system; concrete subclasses for each platform implement the actual interface
137 // to the system fonts. This class exists because we cannot rely on the platform
138 // font-finding APIs to behave in sensible/similar ways, particularly with rich,
139 // complex OpenType families, so we do our own font family/style management here
140 // instead.
142 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on
143 // all platforms.
145 struct FontListSizes {
146 uint32_t mFontListSize; // size of the font list and dependent objects
147 // (font family and face names, etc), but NOT
148 // including the font table cache and the cmaps
149 uint32_t
150 mFontTableCacheSize; // memory used for the gfxFontEntry table caches
151 uint32_t mCharMapsSize; // memory used for cmap coverage info
152 uint32_t mLoaderSize; // memory used for (platform-specific) loader
153 uint32_t mSharedSize; // shared-memory use (reported by parent only)
156 class gfxUserFontSet;
158 class gfxPlatformFontList : public gfxFontInfoLoader {
159 friend class InitOtherFamilyNamesRunnable;
161 public:
162 typedef mozilla::StretchRange StretchRange;
163 typedef mozilla::SlantStyleRange SlantStyleRange;
164 typedef mozilla::WeightRange WeightRange;
165 typedef mozilla::intl::Script Script;
167 // Class used to hold cached copies of the font-name prefs, so that they can
168 // be accessed from non-main-thread callers who are not allowed to touch the
169 // Preferences service.
170 class FontPrefs final {
171 public:
172 using HashMap = nsTHashMap<nsCStringHashKey, nsCString>;
174 FontPrefs();
175 ~FontPrefs() = default;
177 FontPrefs(const FontPrefs& aOther) = delete;
178 FontPrefs& operator=(const FontPrefs& aOther) = delete;
180 // Lookup the font.name.<foo> or font.name-list.<foo> pref for a given
181 // generic+langgroup pair.
182 bool LookupName(const nsACString& aPref, nsACString& aValue) const;
183 bool LookupNameList(const nsACString& aPref, nsACString& aValue) const;
185 // Does the font.name-list.emoji pref have a user-set value?
186 bool EmojiHasUserValue() const { return mEmojiHasUserValue; }
188 // Expose iterators over all the defined prefs of each type.
189 HashMap::ConstIterator NameIter() const { return mFontName.ConstIter(); }
190 HashMap::ConstIterator NameListIter() const {
191 return mFontNameList.ConstIter();
194 private:
195 static constexpr char kNamePrefix[] = "font.name.";
196 static constexpr char kNameListPrefix[] = "font.name-list.";
198 void Init();
200 HashMap mFontName;
201 HashMap mFontNameList;
202 bool mEmojiHasUserValue = false;
205 // For font family lists loaded from user preferences (prefs such as
206 // font.name-list.<generic>.<langGroup>) that map CSS generics to
207 // platform-specific font families.
208 typedef nsTArray<FontFamily> PrefFontList;
210 static gfxPlatformFontList* PlatformFontList() {
211 // If there is a font-list initialization thread, we need to let it run
212 // to completion before the font list can be used for anything else.
213 if (sInitFontListThread) {
214 // If we're currently on the initialization thread, just continue;
215 // otherwise wait for it to finish.
216 if (IsInitFontListThread()) {
217 return sPlatformFontList;
219 PR_JoinThread(sInitFontListThread);
220 sInitFontListThread = nullptr;
221 // If font-list initialization failed, the thread will have cleared
222 // the static sPlatformFontList pointer; we cannot proceed without any
223 // usable fonts.
224 if (!sPlatformFontList) {
225 MOZ_CRASH("Could not initialize gfxPlatformFontList");
228 if (!sPlatformFontList->IsInitialized()) {
229 if (!sPlatformFontList->InitFontList()) {
230 MOZ_CRASH("Could not initialize gfxPlatformFontList");
233 return sPlatformFontList;
236 static bool Initialize(gfxPlatformFontList* aList);
238 static void Shutdown() {
239 delete sPlatformFontList;
240 sPlatformFontList = nullptr;
243 bool IsInitialized() const { return mFontlistInitCount; }
245 virtual ~gfxPlatformFontList();
247 // Initialize font lists; return true on success, false if something fails.
248 bool InitFontList();
250 void FontListChanged();
253 * Gathers (from a platform's underlying font system) the information needed
254 * to initialize a fontlist::Family with its Face members.
256 virtual void GetFacesInitDataForFamily(
257 const mozilla::fontlist::Family* aFamily,
258 nsTArray<mozilla::fontlist::Face::InitData>& aFaces,
259 bool aLoadCmaps) const {}
261 virtual void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
262 nsTArray<nsString>& aListOfFonts);
264 // Pass false to notify content that the shared font list has been modified
265 // but not completely invalidated.
266 void UpdateFontList(bool aFullRebuild = true);
268 virtual void ClearLangGroupPrefFonts();
270 void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray);
272 gfxFont* SystemFindFontForChar(nsPresContext* aPresContext, uint32_t aCh,
273 uint32_t aNextCh, Script aRunScript,
274 eFontPresentation aPresentation,
275 const gfxFontStyle* aStyle,
276 FontVisibility* aVisibility);
278 // Flags to control optional behaviors in FindAndAddFamilies. The sense
279 // of the bit flags have been chosen such that the default parameter of
280 // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired
281 // behavior, and only a few callsites need to explicitly pass other values.
282 enum class FindFamiliesFlags {
283 // If set, "other" (e.g. localized) family names should be loaded
284 // immediately; if clear, InitOtherFamilyNames is allowed to defer
285 // loading to avoid blocking.
286 eForceOtherFamilyNamesLoading = 1 << 0,
288 // If set, FindAndAddFamilies should not check for legacy "styled
289 // family" names to add to the font list. This is used to avoid
290 // a recursive search when using FindFamily to find a potential base
291 // family name for a styled variant.
292 eNoSearchForLegacyFamilyNames = 1 << 1,
294 // If set, FindAndAddFamilies will not add a missing entry to
295 // mOtherNamesMissed
296 eNoAddToNamesMissedWhenSearching = 1 << 2,
298 // If set, the family name was quoted and so must not be treated as a CSS
299 // generic.
300 eQuotedFamilyName = 1 << 3,
302 // If set, "hidden" font families (like ".SF NS Text" on macOS) are
303 // searched in addition to standard user-visible families.
304 eSearchHiddenFamilies = 1 << 4,
307 // Find family(ies) matching aFamily and append to the aOutput array
308 // (there may be multiple results in the case of fontconfig aliases, etc).
309 // Return true if any match was found and appended, false if none.
310 virtual bool FindAndAddFamilies(
311 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
312 const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
313 FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
314 nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0);
316 gfxFontEntry* FindFontForFamily(nsPresContext* aPresContext,
317 const nsACString& aFamily,
318 const gfxFontStyle* aStyle);
320 mozilla::fontlist::FontList* SharedFontList() const {
321 return mSharedFontList.get();
324 // Create a handle for a single shmem block (identified by index) ready to
325 // be shared to the given processId.
326 void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex,
327 base::ProcessId aPid,
328 base::SharedMemoryHandle* aOut);
330 // Populate the array aBlocks with the complete list of shmem handles ready
331 // to be shared to the given processId.
332 void ShareFontListToProcess(nsTArray<base::SharedMemoryHandle>* aBlocks,
333 base::ProcessId aPid);
335 void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
336 base::SharedMemoryHandle aHandle);
338 base::SharedMemoryHandle ShareShmBlockToProcess(uint32_t aIndex,
339 base::ProcessId aPid);
341 void SetCharacterMap(uint32_t aGeneration,
342 const mozilla::fontlist::Pointer& aFacePtr,
343 const gfxSparseBitSet& aMap);
345 void SetupFamilyCharMap(uint32_t aGeneration,
346 const mozilla::fontlist::Pointer& aFamilyPtr);
348 // Start the async cmap loading process, if not already under way, from the
349 // given family index. (For use in any process that needs font lookups.)
350 void StartCmapLoadingFromFamily(uint32_t aStartIndex);
352 // [Parent] Handle request from content process to start cmap loading.
353 void StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex);
355 void CancelLoadCmapsTask() {
356 if (mLoadCmapsRunnable) {
357 mLoadCmapsRunnable->Cancel();
358 mLoadCmapsRunnable = nullptr;
362 // Populate aFamily with face records, and if aLoadCmaps is true, also load
363 // their character maps (rather than leaving this to be done lazily).
364 // Note that even when aFamily->IsInitialized() is true, it can make sense
365 // to call InitializeFamily again if passing aLoadCmaps=true, in order to
366 // ensure cmaps are loaded.
367 [[nodiscard]] bool InitializeFamily(mozilla::fontlist::Family* aFamily,
368 bool aLoadCmaps = false);
369 void InitializeFamily(uint32_t aGeneration, uint32_t aFamilyIndex,
370 bool aLoadCmaps);
372 // name lookup table methods
374 void AddOtherFamilyName(gfxFontFamily* aFamilyEntry,
375 const nsCString& aOtherFamilyName);
377 void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname);
379 void AddPostscriptName(gfxFontEntry* aFontEntry,
380 const nsCString& aPostscriptName);
382 bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; }
385 * Read PSName and FullName of the given face, for src:local lookup,
386 * returning true if actually implemented and succeeded.
388 virtual bool ReadFaceNames(mozilla::fontlist::Family* aFamily,
389 mozilla::fontlist::Face* aFace, nsCString& aPSName,
390 nsCString& aFullName) {
391 return false;
394 // initialize localized family names
395 bool InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading);
396 bool InitOtherFamilyNames(uint32_t aGeneration, bool aDefer);
398 // pure virtual functions, to be provided by concrete subclasses
400 // get the system default font family
401 FontFamily GetDefaultFont(nsPresContext* aPresContext,
402 const gfxFontStyle* aStyle);
404 // get the "ultimate" default font, for use if the font list is otherwise
405 // unusable (e.g. in the middle of being updated)
406 gfxFontEntry* GetDefaultFontEntry() { return mDefaultFontEntry.get(); }
409 * Look up a font by name on the host platform.
411 * Note that the style attributes (weight, stretch, style) are NOT used in
412 * selecting the platform font, which is looked up by name only; these are
413 * values to be recorded in the new font entry.
415 virtual gfxFontEntry* LookupLocalFont(nsPresContext* aPresContext,
416 const nsACString& aFontName,
417 WeightRange aWeightForEntry,
418 StretchRange aStretchForEntry,
419 SlantStyleRange aStyleForEntry) = 0;
422 * Create a new platform font from downloaded data (@font-face).
424 * Note that the style attributes (weight, stretch, style) are NOT related
425 * (necessarily) to any values within the font resource itself; these are
426 * values to be recorded in the new font entry and used for face selection,
427 * in place of whatever inherent style attributes the resource may have.
429 * This method takes ownership of the data block passed in as aFontData,
430 * and must ensure it is free()'d when no longer required.
432 virtual gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
433 WeightRange aWeightForEntry,
434 StretchRange aStretchForEntry,
435 SlantStyleRange aStyleForEntry,
436 const uint8_t* aFontData,
437 uint32_t aLength) = 0;
439 // get the standard family name on the platform for a given font name
440 // (platforms may override, eg Mac)
441 virtual bool GetStandardFamilyName(const nsCString& aFontName,
442 nsACString& aFamilyName);
444 // Get the localized family name for a given font family.
445 bool GetLocalizedFamilyName(const FontFamily& aFamily,
446 nsACString& aFamilyName);
448 // get the default font name which is available on the system from
449 // font.name-list.*. if there are no available fonts in the pref,
450 // returns an empty FamilyAndGeneric record.
451 FamilyAndGeneric GetDefaultFontFamily(const nsACString& aLangGroup,
452 const nsACString& aGenericFamily);
454 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
455 FontListSizes* aSizes) const;
456 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
457 FontListSizes* aSizes) const;
459 mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap);
461 // search for existing cmap that matches the input
462 // return the input if no match is found
463 gfxCharacterMap* FindCharMap(gfxCharacterMap* aCmap);
465 // add a cmap to the shared cmap set
466 gfxCharacterMap* AddCmap(const gfxCharacterMap* aCharMap);
468 // remove the cmap from the shared cmap set
469 void RemoveCmap(const gfxCharacterMap* aCharMap);
471 // keep track of userfont sets to notify when global fontlist changes occur
472 void AddUserFontSet(gfxUserFontSet* aUserFontSet) {
473 mUserFontSetList.Insert(aUserFontSet);
476 void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) {
477 mUserFontSetList.Remove(aUserFontSet);
480 static const gfxFontEntry::ScriptRange sComplexScriptRanges[];
482 void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) {
483 aNumInits = mFontlistInitCount;
484 aLoaderState = (uint32_t)mState;
487 virtual void AddGenericFonts(nsPresContext* aPresContext,
488 mozilla::StyleGenericFontFamily aGenericType,
489 nsAtom* aLanguage,
490 nsTArray<FamilyAndGeneric>& aFamilyList);
493 * Given a Face from the shared font list, return a gfxFontEntry usable
494 * by the current process. This returns a cached entry if available,
495 * otherwise it calls the (platform-specific) CreateFontEntry method to
496 * make one, and adds it to the cache.
498 gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace,
499 const mozilla::fontlist::Family* aFamily);
501 const FontPrefs* GetFontPrefs() const { return mFontPrefs.get(); }
503 bool EmojiPrefHasUserValue() const { return mFontPrefs->EmojiHasUserValue(); }
505 PrefFontList* GetPrefFontsLangGroup(
506 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
507 eFontPrefLang aPrefLang);
509 // in some situations, need to make decisions about ambiguous characters, may
510 // need to look at multiple pref langs
511 void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
512 eFontPrefLang aCharLang, eFontPrefLang aPageLang);
514 // convert a lang group to enum constant (i.e. "zh-TW" ==>
515 // eFontPrefLang_ChineseTW)
516 static eFontPrefLang GetFontPrefLangFor(const char* aLang);
518 // convert a lang group atom to enum constant
519 static eFontPrefLang GetFontPrefLangFor(nsAtom* aLang);
521 // convert an enum constant to a lang group atom
522 static nsAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
524 // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW
525 // ==> "zh-TW")
526 static const char* GetPrefLangName(eFontPrefLang aLang);
528 // map a char code to a font language for Preferences
529 static eFontPrefLang GetFontPrefLangFor(uint32_t aCh);
531 // returns true if a pref lang is CJK
532 static bool IsLangCJK(eFontPrefLang aLang);
534 // helper method to add a pref lang to an array, if not already in array
535 static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen,
536 eFontPrefLang aAddLang);
538 // default serif/sans-serif choice based on font.default.xxx prefs
539 mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang);
541 // Returns true if the font family whitelist is not empty. In this case we
542 // ignore the "CSS visibility level"; only the given fonts are present in
543 // the browser's font list.
544 bool IsFontFamilyWhitelistActive() const {
545 return mFontFamilyWhitelistActive;
548 static void FontWhitelistPrefChanged(const char* aPref, void* aClosure);
550 bool AddWithLegacyFamilyName(const nsACString& aLegacyName,
551 gfxFontEntry* aFontEntry,
552 FontVisibility aVisibility);
554 static const char* GetGenericName(
555 mozilla::StyleGenericFontFamily aGenericType);
557 bool SkipFontFallbackForChar(FontVisibility aVisibility, uint32_t aCh) const {
558 return mCodepointsWithNoFonts[aVisibility].test(aCh);
561 // Return whether the given font-family record should be visible to CSS,
562 // in a context with the given FontVisibility setting.
563 bool IsVisibleToCSS(const gfxFontFamily& aFamily,
564 FontVisibility aVisibility) const;
565 bool IsVisibleToCSS(const mozilla::fontlist::Family& aFamily,
566 FontVisibility aVisibility) const;
568 // (Re-)initialize the set of codepoints that we know cannot be rendered.
569 void InitializeCodepointsWithNoFonts();
571 // If using the shared font list, returns a generation count that is
572 // incremented if/when the platform list is reinitialized (e.g. because
573 // fonts are installed/removed while the browser is running), such that
574 // existing references to shared font family or face objects and character
575 // maps will no longer be valid.
576 // (The legacy (non-shared) list just returns 0 here.)
577 uint32_t GetGeneration() const;
579 // Sometimes we need to know if we're on the InitFontList startup thread.
580 static bool IsInitFontListThread() {
581 return PR_GetCurrentThread() == sInitFontListThread;
584 protected:
585 friend class mozilla::fontlist::FontList;
586 friend class InitOtherFamilyNamesForStylo;
588 template <size_t N>
589 static bool FamilyInList(const nsACString& aName, const char* (&aList)[N]) {
590 return FamilyInList(aName, aList, N);
592 static bool FamilyInList(const nsACString& aName, const char* aList[],
593 size_t aCount);
595 // Check list is correctly sorted (in debug build only; no-op on release).
596 template <size_t N>
597 static void CheckFamilyList(const char* (&aList)[N]) {
598 CheckFamilyList(aList, N);
600 static void CheckFamilyList(const char* aList[], size_t aCount);
602 class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable {
603 public:
604 InitOtherFamilyNamesRunnable()
605 : CancelableRunnable(
606 "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
607 mIsCanceled(false) {}
609 NS_IMETHOD Run() override {
610 if (mIsCanceled) {
611 return NS_OK;
614 gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
615 if (!fontList) {
616 return NS_OK;
619 fontList->InitOtherFamilyNamesInternal(true);
621 return NS_OK;
624 nsresult Cancel() override {
625 mIsCanceled = true;
627 return NS_OK;
630 private:
631 bool mIsCanceled;
634 class MemoryReporter final : public nsIMemoryReporter {
635 ~MemoryReporter() = default;
637 public:
638 NS_DECL_ISUPPORTS
639 NS_DECL_NSIMEMORYREPORTER
642 class PrefName final : public nsAutoCString {
643 void Init(const nsACString& aGeneric, const nsACString& aLangGroup) {
644 Assign(aGeneric);
645 if (!aLangGroup.IsEmpty()) {
646 Append('.');
647 Append(aLangGroup);
651 public:
652 PrefName(const nsACString& aGeneric, const nsACString& aLangGroup) {
653 Init(aGeneric, aLangGroup);
656 PrefName(const char* aGeneric, const char* aLangGroup) {
657 Init(nsDependentCString(aGeneric), nsDependentCString(aLangGroup));
660 PrefName(const char* aGeneric, nsAtom* aLangGroup) {
661 if (aLangGroup) {
662 Init(nsDependentCString(aGeneric), nsAtomCString(aLangGroup));
663 } else {
664 Init(nsDependentCString(aGeneric), nsAutoCString());
669 explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
671 static gfxPlatformFontList* sPlatformFontList;
674 * Convenience method to return the first matching family (if any) as found
675 * by FindAndAddFamilies(). The family will be initialized (synchronously)
676 * if this has not already been done, so the returned pointer, if non-null,
677 * is ready for use.
679 mozilla::fontlist::Family* FindSharedFamily(
680 nsPresContext* aPresContext, const nsACString& aFamily,
681 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
682 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
683 gfxFloat aDevToCssSize = 1.0);
685 gfxFontFamily* FindUnsharedFamily(
686 nsPresContext* aPresContext, const nsACString& aFamily,
687 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
688 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
689 gfxFloat aDevToCssSize = 1.0) {
690 if (SharedFontList()) {
691 return nullptr;
693 AutoTArray<FamilyAndGeneric, 1> families;
694 if (FindAndAddFamilies(aPresContext, mozilla::StyleGenericFontFamily::None,
695 aFamily, &families, aFlags, aStyle, aLanguage,
696 aDevToCssSize)) {
697 return families[0].mFamily.mUnshared;
699 return nullptr;
702 FontFamily FindFamily(nsPresContext* aPresContext, const nsACString& aFamily,
703 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
704 gfxFontStyle* aStyle = nullptr,
705 nsAtom* aLanguage = nullptr,
706 gfxFloat aDevToCssSize = 1.0) {
707 if (SharedFontList()) {
708 return FontFamily(FindSharedFamily(aPresContext, aFamily, aFlags, aStyle,
709 aLanguage, aDevToCssSize));
711 return FontFamily(FindUnsharedFamily(aPresContext, aFamily, aFlags, aStyle,
712 aLanguage, aDevToCssSize));
715 // Lookup family name in global family list without substitutions or
716 // localized family name lookup. Used for common font fallback families.
717 gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) {
718 nsAutoCString key;
719 gfxFontFamily* familyEntry;
720 GenerateFontListKey(aFamily, key);
721 if ((familyEntry = mFontFamilies.GetWeak(key))) {
722 return CheckFamily(familyEntry);
724 return nullptr;
727 // returns default font for a given character, null otherwise
728 gfxFont* CommonFontFallback(nsPresContext* aPresContext, uint32_t aCh,
729 uint32_t aNextCh, Script aRunScript,
730 eFontPresentation aPresentation,
731 const gfxFontStyle* aMatchStyle,
732 FontFamily& aMatchedFamily);
734 // Search fonts system-wide for a given character, null if not found.
735 gfxFont* GlobalFontFallback(nsPresContext* aPresContext, uint32_t aCh,
736 uint32_t aNextCh, Script aRunScript,
737 eFontPresentation aPresentation,
738 const gfxFontStyle* aMatchStyle,
739 uint32_t& aCmapCount, FontFamily& aMatchedFamily);
741 // Platform-specific implementation of global font fallback, if any;
742 // this may return nullptr in which case the default cmap-based fallback
743 // will be performed.
744 virtual gfxFontEntry* PlatformGlobalFontFallback(
745 nsPresContext* aPresContext, const uint32_t aCh, Script aRunScript,
746 const gfxFontStyle* aMatchStyle, FontFamily& aMatchedFamily) {
747 return nullptr;
750 // whether system-based font fallback is used or not
751 // if system fallback is used, no need to load all cmaps
752 virtual bool UsesSystemFallback() { return false; }
754 void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
755 eFontPrefLang aCharLang, eFontPrefLang aPageLang);
757 // verifies that a family contains a non-zero font count
758 gfxFontFamily* CheckFamily(gfxFontFamily* aFamily);
760 // initialize localized family names
761 void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
762 void CancelInitOtherFamilyNamesTask();
764 // search through font families, looking for a given name, initializing
765 // facename lists along the way. first checks all families with names
766 // close to face name, then searchs all families if not found.
767 gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName);
769 // helper method for finding fullname/postscript names in facename lists
770 gfxFontEntry* FindFaceName(const nsACString& aFaceName);
772 // look up a font by name, for cases where platform font list
773 // maintains explicit mappings of fullname/psname ==> font
774 virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFontName);
776 gfxFontEntry* LookupInSharedFaceNameList(nsPresContext* aPresContext,
777 const nsACString& aFaceName,
778 WeightRange aWeightForEntry,
779 StretchRange aStretchForEntry,
780 SlantStyleRange aStyleForEntry);
782 // load the bad underline blocklist from pref.
783 void LoadBadUnderlineList();
785 void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
787 virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames);
789 // helper function to map lang to lang group
790 nsAtom* GetLangGroup(nsAtom* aLanguage);
792 // gfxFontInfoLoader overrides, used to load in font cmaps
793 void InitLoader() override;
794 bool LoadFontInfo() override;
795 void CleanupLoader() override;
797 // read the loader initialization prefs, and start it
798 void GetPrefsAndStartLoader();
800 // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
801 // be discarded (not potentially reused to satisfy the rebuilt rules),
802 // because they may no longer be valid.
803 void RebuildLocalFonts(bool aForgetLocalFaces = false);
805 void ResolveGenericFontNames(nsPresContext* aPresContext,
806 mozilla::StyleGenericFontFamily aGenericType,
807 eFontPrefLang aPrefLang,
808 PrefFontList* aGenericFamilies);
810 void ResolveEmojiFontNames(nsPresContext* aPresContext,
811 PrefFontList* aGenericFamilies);
813 void GetFontFamiliesFromGenericFamilies(
814 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
815 nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
816 PrefFontList* aFontFamilies);
818 virtual nsresult InitFontListForPlatform() = 0;
819 virtual void InitSharedFontListForPlatform() {}
821 virtual gfxFontEntry* CreateFontEntry(
822 mozilla::fontlist::Face* aFace,
823 const mozilla::fontlist::Family* aFamily) {
824 return nullptr;
828 * Methods to apply the font.system.whitelist anti-fingerprinting pref,
829 * by filtering the list of installed fonts so that only whitelisted families
830 * are exposed.
831 * There are separate implementations of this for the per-process font list
832 * and for the shared-memory font list.
834 void ApplyWhitelist();
835 void ApplyWhitelist(nsTArray<mozilla::fontlist::Family::InitData>& aFamilies);
837 // Create a new gfxFontFamily of the appropriate subclass for the platform,
838 // used when AddWithLegacyFamilyName needs to create a new family.
839 virtual gfxFontFamily* CreateFontFamily(const nsACString& aName,
840 FontVisibility aVisibility) const = 0;
843 * For the post-startup font info loader task.
844 * Perform platform-specific work to read alternate names (if any) for a
845 * font family, recording them in mAliasTable. Once alternate names have been
846 * loaded for all families, the accumulated records are stored in the shared
847 * font list's mAliases list.
848 * Some platforms (currently Linux/fontconfig) may load alternate names as
849 * part of initially populating the font list with family records, in which
850 * case this method is unused.
852 virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
853 bool aNeedFullnamePostscriptNames) {}
855 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontFamily> FontFamilyTable;
856 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontEntry> FontEntryTable;
858 // used by memory reporter to accumulate sizes of family names in the table
859 static size_t SizeOfFontFamilyTableExcludingThis(
860 const FontFamilyTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
861 static size_t SizeOfFontEntryTableExcludingThis(
862 const FontEntryTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
864 // Platform-specific helper for GetDefaultFont(...).
865 virtual FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
866 const gfxFontStyle* aStyle,
867 nsAtom* aLanguage = nullptr) = 0;
869 // Protects mFontFamilies.
870 mozilla::Mutex mFontFamiliesMutex MOZ_UNANNOTATED;
872 // canonical family name ==> family entry (unique, one name per family entry)
873 FontFamilyTable mFontFamilies;
875 // other family name ==> family entry (not unique, can have multiple names per
876 // family entry, only names *other* than the canonical names are stored here)
877 FontFamilyTable mOtherFamilyNames;
879 // flag set after InitOtherFamilyNames is called upon first name lookup miss
880 bool mOtherFamilyNamesInitialized = false;
882 // The pending InitOtherFamilyNames() task.
883 RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
885 // flag set after fullname and Postcript name lists are populated
886 bool mFaceNameListsInitialized = false;
888 struct ExtraNames {
889 ExtraNames() = default;
891 // fullname ==> font entry (unique, one name per font entry)
892 FontEntryTable mFullnames{64};
893 // Postscript name ==> font entry (unique, one name per font entry)
894 FontEntryTable mPostscriptNames{64};
896 mozilla::UniquePtr<ExtraNames> mExtraNames;
898 // face names missed when face name loading takes a long time
899 mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed;
901 // localized family names missed when face name loading takes a long time
902 mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed;
904 typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>,
905 size_t(mozilla::StyleGenericFontFamily::None),
906 size_t(
907 mozilla::StyleGenericFontFamily::MozEmoji)>
908 PrefFontsForLangGroup;
909 mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First,
910 eFontPrefLang_Count>
911 mLangGroupPrefFonts;
912 mozilla::UniquePtr<PrefFontList> mEmojiPrefFont;
914 // When system-wide font lookup fails for a character, cache it to skip future
915 // searches. This is an array of bitsets, one for each FontVisibility level.
916 mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count,
917 gfxSparseBitSet>
918 mCodepointsWithNoFonts;
920 // the family to use for U+FFFD fallback, to avoid expensive search every time
921 // on pages with lots of problems
922 mozilla::EnumeratedArray<FontVisibility, FontVisibility::Count, FontFamily>
923 mReplacementCharFallbackFamily;
925 // Sorted array of lowercased family names; use ContainsSorted to test
926 nsTArray<nsCString> mBadUnderlineFamilyNames;
928 // character map data shared across families
929 // contains weak ptrs to cmaps shared by font entry objects
930 nsTHashtable<CharMapHashKey> mSharedCmaps;
932 nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps;
934 // data used as part of the font cmap loading process
935 nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad;
936 uint32_t mStartIndex = 0;
937 uint32_t mNumFamilies = 0;
939 // xxx - info for diagnosing no default font aborts
940 // see bugs 636957, 1070983, 1189129
941 uint32_t mFontlistInitCount = 0; // num times InitFontList called
943 nsTHashSet<gfxUserFontSet*> mUserFontSetList;
945 nsLanguageAtomService* mLangService = nullptr;
947 nsTArray<uint32_t> mCJKPrefLangs;
948 nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup;
950 nsTArray<nsCString> mEnabledFontsList;
952 mozilla::UniquePtr<mozilla::fontlist::FontList> mSharedFontList;
954 nsClassHashtable<nsCStringHashKey, mozilla::fontlist::AliasData> mAliasTable;
955 nsTHashMap<nsCStringHashKey, mozilla::fontlist::LocalFaceRec::InitData>
956 mLocalNameTable;
958 nsRefPtrHashtable<nsPtrHashKey<mozilla::fontlist::Face>, gfxFontEntry>
959 mFontEntries;
961 mozilla::UniquePtr<FontPrefs> mFontPrefs;
963 RefPtr<gfxFontEntry> mDefaultFontEntry;
965 RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
966 uint32_t mStartedLoadingCmapsFrom = 0xffffffffu;
968 bool mFontFamilyWhitelistActive = false;
970 static PRThread* sInitFontListThread;
973 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
975 #endif /* GFXPLATFORMFONTLIST_H_ */