Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / thebes / gfxPlatformFontList.h
blob5a53d8b9ca0640177e2a35a149ed2ca933070dd1
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/RangedArray.h"
28 #include "mozilla/RecursiveMutex.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.get(); }
55 bool KeyEquals(const gfxCharacterMap* aCharMap) const {
56 MOZ_ASSERT(!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 friend class gfxPlatformFontList;
77 // gfxCharacterMap::Release() will notify us when the refcount of a
78 // charmap drops to 1; at that point, we'll lock the cache, check if
79 // the charmap is owned by the cache and this is still the only ref,
80 // and if so, delete it.
81 RefPtr<gfxCharacterMap> mCharMap;
84 /**
85 * A helper class used to create a SharedBitSet instance in a FontList's shared
86 * memory, while ensuring that we avoid bloating memory by avoiding creating
87 * duplicate instances.
89 class ShmemCharMapHashEntry final : public PLDHashEntryHdr {
90 public:
91 typedef const gfxSparseBitSet* KeyType;
92 typedef const gfxSparseBitSet* KeyTypePointer;
94 /**
95 * Creation from a gfxSparseBitSet creates not only the ShmemCharMapHashEntry
96 * itself, but also a SharedBitSet in shared memory.
97 * Only the parent process creates and manages these entries.
99 explicit ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap);
101 ShmemCharMapHashEntry(ShmemCharMapHashEntry&&) = default;
102 ShmemCharMapHashEntry& operator=(ShmemCharMapHashEntry&&) = default;
105 * Return a shared-memory Pointer that refers to the wrapped SharedBitSet.
106 * This can be passed to content processes to give them access to the same
107 * SharedBitSet as the parent stored.
109 mozilla::fontlist::Pointer GetCharMap() const { return mCharMap; }
111 bool KeyEquals(KeyType aCharMap) const {
112 // mHash is a 32-bit Adler checksum of the bitset; if it doesn't match we
113 // can immediately reject it as non-matching, but if it is equal we still
114 // need to do a full equality check below.
115 if (mHash != aCharMap->GetChecksum()) {
116 return false;
119 return mCharMap.ToPtr<const SharedBitSet>(mList)->Equals(aCharMap);
122 static KeyTypePointer KeyToPointer(KeyType aCharMap) { return aCharMap; }
123 static PLDHashNumber HashKey(KeyType aCharMap) {
124 return aCharMap->GetChecksum();
127 enum { ALLOW_MEMMOVE = false }; // because of the Pointer member
129 private:
130 // charMaps are stored in the shared memory that FontList objects point to,
131 // and are never deleted until the FontList (all referencing font lists,
132 // actually) have gone away.
133 mozilla::fontlist::FontList* mList;
134 mozilla::fontlist::Pointer mCharMap;
135 uint32_t mHash;
138 // gfxPlatformFontList is an abstract class for the global font list on the
139 // system; concrete subclasses for each platform implement the actual interface
140 // to the system fonts. This class exists because we cannot rely on the platform
141 // font-finding APIs to behave in sensible/similar ways, particularly with rich,
142 // complex OpenType families, so we do our own font family/style management here
143 // instead.
145 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on
146 // all platforms.
148 struct FontListSizes {
149 uint32_t mFontListSize; // size of the font list and dependent objects
150 // (font family and face names, etc), but NOT
151 // including the font table cache and the cmaps
152 uint32_t
153 mFontTableCacheSize; // memory used for the gfxFontEntry table caches
154 uint32_t mCharMapsSize; // memory used for cmap coverage info
155 uint32_t mLoaderSize; // memory used for (platform-specific) loader
156 uint32_t mSharedSize; // shared-memory use (reported by parent only)
159 class gfxUserFontSet;
161 class gfxPlatformFontList : public gfxFontInfoLoader {
162 friend class InitOtherFamilyNamesRunnable;
164 public:
165 typedef mozilla::StretchRange StretchRange;
166 typedef mozilla::SlantStyleRange SlantStyleRange;
167 typedef mozilla::WeightRange WeightRange;
168 typedef mozilla::intl::Script Script;
170 using AutoLock = mozilla::RecursiveMutexAutoLock;
171 using AutoUnlock = mozilla::RecursiveMutexAutoUnlock;
173 // Class used to hold cached copies of the font-name prefs, so that they can
174 // be accessed from non-main-thread callers who are not allowed to touch the
175 // Preferences service.
176 class FontPrefs final {
177 public:
178 using HashMap = nsTHashMap<nsCStringHashKey, nsCString>;
180 FontPrefs();
181 ~FontPrefs() = default;
183 FontPrefs(const FontPrefs& aOther) = delete;
184 FontPrefs& operator=(const FontPrefs& aOther) = delete;
186 // Lookup the font.name.<foo> or font.name-list.<foo> pref for a given
187 // generic+langgroup pair.
188 bool LookupName(const nsACString& aPref, nsACString& aValue) const;
189 bool LookupNameList(const nsACString& aPref, nsACString& aValue) const;
191 // Does the font.name-list.emoji pref have a user-set value?
192 bool EmojiHasUserValue() const { return mEmojiHasUserValue; }
194 // Expose iterators over all the defined prefs of each type.
195 HashMap::ConstIterator NameIter() const { return mFontName.ConstIter(); }
196 HashMap::ConstIterator NameListIter() const {
197 return mFontNameList.ConstIter();
200 private:
201 static constexpr char kNamePrefix[] = "font.name.";
202 static constexpr char kNameListPrefix[] = "font.name-list.";
204 void Init();
206 HashMap mFontName;
207 HashMap mFontNameList;
208 bool mEmojiHasUserValue = false;
211 // For font family lists loaded from user preferences (prefs such as
212 // font.name-list.<generic>.<langGroup>) that map CSS generics to
213 // platform-specific font families.
214 typedef nsTArray<FontFamily> PrefFontList;
216 // Return the global font-list singleton, or NULL if aMustInitialize is false
217 // and it has not yet been fully initialized.
218 static gfxPlatformFontList* PlatformFontList(bool aMustInitialize = true) {
219 if (!aMustInitialize &&
220 !(sPlatformFontList && sPlatformFontList->IsInitialized())) {
221 return nullptr;
223 // If there is a font-list initialization thread, we need to let it run
224 // to completion before the font list can be used for anything else.
225 if (sInitFontListThread) {
226 // If we're currently on the initialization thread, just continue;
227 // otherwise wait for it to finish.
228 if (IsInitFontListThread()) {
229 return sPlatformFontList;
231 PR_JoinThread(sInitFontListThread);
232 sInitFontListThread = nullptr;
233 // If font-list initialization failed, the thread will have cleared
234 // the static sPlatformFontList pointer; we cannot proceed without any
235 // usable fonts.
236 if (!sPlatformFontList) {
237 MOZ_CRASH("Could not initialize gfxPlatformFontList");
240 if (!sPlatformFontList->IsInitialized()) {
241 if (!sPlatformFontList->InitFontList()) {
242 MOZ_CRASH("Could not initialize gfxPlatformFontList");
245 return sPlatformFontList;
248 void GetMissingFonts(nsCString& aMissingFonts);
250 static bool Initialize(gfxPlatformFontList* aList);
252 static void Shutdown() {
253 // Ensure any font-list initialization thread is finished before we delete
254 // the platform fontlist singleton, which that thread may try to use.
255 if (sInitFontListThread && !IsInitFontListThread()) {
256 PR_JoinThread(sInitFontListThread);
257 sInitFontListThread = nullptr;
259 delete sPlatformFontList;
260 sPlatformFontList = nullptr;
263 bool IsInitialized() const { return mFontlistInitCount; }
265 virtual ~gfxPlatformFontList();
267 // Initialize font lists; return true on success, false if something fails.
268 bool InitFontList();
270 void FontListChanged();
273 * Gathers (from a platform's underlying font system) the information needed
274 * to initialize a fontlist::Family with its Face members.
276 virtual void GetFacesInitDataForFamily(
277 const mozilla::fontlist::Family* aFamily,
278 nsTArray<mozilla::fontlist::Face::InitData>& aFaces,
279 bool aLoadCmaps) const {}
281 virtual void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily,
282 nsTArray<nsString>& aListOfFonts);
284 // Pass false to notify content that the shared font list has been modified
285 // but not completely invalidated.
286 void UpdateFontList(bool aFullRebuild = true);
288 void ClearLangGroupPrefFonts() {
289 AutoLock lock(mLock);
290 ClearLangGroupPrefFontsLocked();
292 virtual void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock);
294 void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray);
296 already_AddRefed<gfxFont> SystemFindFontForChar(
297 nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
298 Script aRunScript, eFontPresentation aPresentation,
299 const gfxFontStyle* aStyle, FontVisibility* aVisibility);
301 // Flags to control optional behaviors in FindAndAddFamilies. The sense
302 // of the bit flags have been chosen such that the default parameter of
303 // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired
304 // behavior, and only a few callsites need to explicitly pass other values.
305 enum class FindFamiliesFlags {
306 // If set, "other" (e.g. localized) family names should be loaded
307 // immediately; if clear, InitOtherFamilyNames is allowed to defer
308 // loading to avoid blocking.
309 eForceOtherFamilyNamesLoading = 1 << 0,
311 // If set, FindAndAddFamilies should not check for legacy "styled
312 // family" names to add to the font list. This is used to avoid
313 // a recursive search when using FindFamily to find a potential base
314 // family name for a styled variant.
315 eNoSearchForLegacyFamilyNames = 1 << 1,
317 // If set, FindAndAddFamilies will not add a missing entry to
318 // mOtherNamesMissed
319 eNoAddToNamesMissedWhenSearching = 1 << 2,
321 // If set, the family name was quoted and so must not be treated as a CSS
322 // generic.
323 eQuotedFamilyName = 1 << 3,
325 // If set, "hidden" font families (like ".SF NS Text" on macOS) are
326 // searched in addition to standard user-visible families.
327 eSearchHiddenFamilies = 1 << 4,
330 // Find family(ies) matching aFamily and append to the aOutput array
331 // (there may be multiple results in the case of fontconfig aliases, etc).
332 // Return true if any match was found and appended, false if none.
333 bool FindAndAddFamilies(
334 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
335 const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
336 FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
337 nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0);
339 virtual bool FindAndAddFamiliesLocked(
340 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
341 const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
342 FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
343 nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0)
344 MOZ_REQUIRES(mLock);
346 gfxFontEntry* FindFontForFamily(nsPresContext* aPresContext,
347 const nsACString& aFamily,
348 const gfxFontStyle* aStyle);
350 mozilla::fontlist::FontList* SharedFontList() const {
351 return mSharedFontList.get();
354 // Create a handle for a single shmem block (identified by index) ready to
355 // be shared to the given processId.
356 void ShareFontListShmBlockToProcess(uint32_t aGeneration, uint32_t aIndex,
357 base::ProcessId aPid,
358 base::SharedMemoryHandle* aOut);
360 // Populate the array aBlocks with the complete list of shmem handles ready
361 // to be shared to the given processId.
362 void ShareFontListToProcess(nsTArray<base::SharedMemoryHandle>* aBlocks,
363 base::ProcessId aPid);
365 void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
366 base::SharedMemoryHandle aHandle);
368 base::SharedMemoryHandle ShareShmBlockToProcess(uint32_t aIndex,
369 base::ProcessId aPid);
371 void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias,
372 uint32_t aFaceIndex, const gfxSparseBitSet& aMap);
374 void SetupFamilyCharMap(uint32_t aGeneration, uint32_t aIndex, bool aAlias);
376 // Start the async cmap loading process, if not already under way, from the
377 // given family index. (For use in any process that needs font lookups.)
378 void StartCmapLoadingFromFamily(uint32_t aStartIndex);
380 // [Parent] Handle request from content process to start cmap loading.
381 void StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex);
383 void CancelLoadCmapsTask() {
384 if (mLoadCmapsRunnable) {
385 mLoadCmapsRunnable->Cancel();
386 mLoadCmapsRunnable = nullptr;
390 // Populate aFamily with face records, and if aLoadCmaps is true, also load
391 // their character maps (rather than leaving this to be done lazily).
392 // Note that even when aFamily->IsInitialized() is true, it can make sense
393 // to call InitializeFamily again if passing aLoadCmaps=true, in order to
394 // ensure cmaps are loaded.
395 [[nodiscard]] bool InitializeFamily(mozilla::fontlist::Family* aFamily,
396 bool aLoadCmaps = false);
397 void InitializeFamily(uint32_t aGeneration, uint32_t aFamilyIndex,
398 bool aLoadCmaps);
400 // name lookup table methods
402 void AddOtherFamilyNames(gfxFontFamily* aFamilyEntry,
403 const nsTArray<nsCString>& aOtherFamilyNames);
405 void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname) {
406 AutoLock lock(mLock);
407 AddFullnameLocked(aFontEntry, aFullname);
409 void AddFullnameLocked(gfxFontEntry* aFontEntry, const nsCString& aFullname)
410 MOZ_REQUIRES(mLock);
412 void AddPostscriptName(gfxFontEntry* aFontEntry,
413 const nsCString& aPostscriptName) {
414 AutoLock lock(mLock);
415 AddPostscriptNameLocked(aFontEntry, aPostscriptName);
417 void AddPostscriptNameLocked(gfxFontEntry* aFontEntry,
418 const nsCString& aPostscriptName)
419 MOZ_REQUIRES(mLock);
421 bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; }
424 * Read PSName and FullName of the given face, for src:local lookup,
425 * returning true if actually implemented and succeeded.
427 virtual bool ReadFaceNames(const mozilla::fontlist::Family* aFamily,
428 const mozilla::fontlist::Face* aFace,
429 nsCString& aPSName, nsCString& aFullName) {
430 return false;
433 // initialize localized family names
434 bool InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading);
435 bool InitOtherFamilyNames(uint32_t aGeneration, bool aDefer);
437 // pure virtual functions, to be provided by concrete subclasses
439 // get the system default font family
440 FontFamily GetDefaultFont(nsPresContext* aPresContext,
441 const gfxFontStyle* aStyle);
442 FontFamily GetDefaultFontLocked(nsPresContext* aPresContext,
443 const gfxFontStyle* aStyle)
444 MOZ_REQUIRES(mLock);
446 // get the "ultimate" default font, for use if the font list is otherwise
447 // unusable (e.g. in the middle of being updated)
448 gfxFontEntry* GetDefaultFontEntry() {
449 AutoLock lock(mLock);
450 return mDefaultFontEntry.get();
454 * Look up a font by name on the host platform.
456 * Note that the style attributes (weight, stretch, style) are NOT used in
457 * selecting the platform font, which is looked up by name only; these are
458 * values to be recorded in the new font entry.
460 virtual gfxFontEntry* LookupLocalFont(nsPresContext* aPresContext,
461 const nsACString& aFontName,
462 WeightRange aWeightForEntry,
463 StretchRange aStretchForEntry,
464 SlantStyleRange aStyleForEntry) = 0;
467 * Create a new platform font from downloaded data (@font-face).
469 * Note that the style attributes (weight, stretch, style) are NOT related
470 * (necessarily) to any values within the font resource itself; these are
471 * values to be recorded in the new font entry and used for face selection,
472 * in place of whatever inherent style attributes the resource may have.
474 * This method takes ownership of the data block passed in as aFontData,
475 * and must ensure it is free()'d when no longer required.
477 virtual gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
478 WeightRange aWeightForEntry,
479 StretchRange aStretchForEntry,
480 SlantStyleRange aStyleForEntry,
481 const uint8_t* aFontData,
482 uint32_t aLength) = 0;
484 // get the standard family name on the platform for a given font name
485 // (platforms may override, eg Mac)
486 virtual bool GetStandardFamilyName(const nsCString& aFontName,
487 nsACString& aFamilyName);
489 // Get the localized family name for a given font family.
490 bool GetLocalizedFamilyName(const FontFamily& aFamily,
491 nsACString& aFamilyName);
493 // get the default font name which is available on the system from
494 // font.name-list.*. if there are no available fonts in the pref,
495 // returns an empty FamilyAndGeneric record.
496 FamilyAndGeneric GetDefaultFontFamily(const nsACString& aLangGroup,
497 const nsACString& aGenericFamily);
499 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
500 FontListSizes* aSizes) const;
501 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
502 FontListSizes* aSizes) const;
504 mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap) {
505 AutoLock lock(mLock);
506 return GetShmemCharMapLocked(aCmap);
508 mozilla::fontlist::Pointer GetShmemCharMapLocked(const gfxSparseBitSet* aCmap)
509 MOZ_REQUIRES(mLock);
511 // Search for existing cmap that matches the input; return the input if no
512 // match is found.
513 already_AddRefed<gfxCharacterMap> FindCharMap(gfxCharacterMap* aCmap);
515 // Remove the cmap from the shared cmap set if it holds the only remaining
516 // reference to the object.
517 void MaybeRemoveCmap(gfxCharacterMap* aCharMap);
519 // Keep track of userfont sets to notify when global fontlist changes occur.
520 void AddUserFontSet(gfxUserFontSet* aUserFontSet) {
521 AutoLock lock(mLock);
522 mUserFontSetList.Insert(aUserFontSet);
525 void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) {
526 AutoLock lock(mLock);
527 mUserFontSetList.Remove(aUserFontSet);
530 static const gfxFontEntry::ScriptRange sComplexScriptRanges[];
532 void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) {
533 aNumInits = mFontlistInitCount;
534 aLoaderState = (uint32_t)mState;
537 virtual void AddGenericFonts(nsPresContext* aPresContext,
538 mozilla::StyleGenericFontFamily aGenericType,
539 nsAtom* aLanguage,
540 nsTArray<FamilyAndGeneric>& aFamilyList);
543 * Given a Face from the shared font list, return a gfxFontEntry usable
544 * by the current process. This returns a cached entry if available,
545 * otherwise it calls the (platform-specific) CreateFontEntry method to
546 * make one, and adds it to the cache.
548 gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace,
549 const mozilla::fontlist::Family* aFamily) {
550 AutoLock lock(mLock);
551 return GetOrCreateFontEntryLocked(aFace, aFamily);
553 gfxFontEntry* GetOrCreateFontEntryLocked(
554 mozilla::fontlist::Face* aFace, const mozilla::fontlist::Family* aFamily)
555 MOZ_REQUIRES(mLock);
557 const FontPrefs* GetFontPrefs() const MOZ_REQUIRES(mLock) {
558 return mFontPrefs.get();
561 bool EmojiPrefHasUserValue() const {
562 AutoLock lock(mLock);
563 return mFontPrefs->EmojiHasUserValue();
566 PrefFontList* GetPrefFontsLangGroup(
567 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
568 eFontPrefLang aPrefLang) {
569 AutoLock lock(mLock);
570 return GetPrefFontsLangGroupLocked(aPresContext, aGenericType, aPrefLang);
572 PrefFontList* GetPrefFontsLangGroupLocked(
573 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
574 eFontPrefLang aPrefLang) MOZ_REQUIRES(mLock);
576 // in some situations, need to make decisions about ambiguous characters, may
577 // need to look at multiple pref langs
578 void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
579 eFontPrefLang aCharLang, eFontPrefLang aPageLang);
581 // convert a lang group to enum constant (i.e. "zh-TW" ==>
582 // eFontPrefLang_ChineseTW)
583 static eFontPrefLang GetFontPrefLangFor(const char* aLang);
585 // convert a lang group atom to enum constant
586 static eFontPrefLang GetFontPrefLangFor(nsAtom* aLang);
588 // convert an enum constant to a lang group atom
589 static nsAtom* GetLangGroupForPrefLang(eFontPrefLang aLang);
591 // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW
592 // ==> "zh-TW")
593 static const char* GetPrefLangName(eFontPrefLang aLang);
595 // map a char code to a font language for Preferences
596 static eFontPrefLang GetFontPrefLangFor(uint32_t aCh);
598 // returns true if a pref lang is CJK
599 static bool IsLangCJK(eFontPrefLang aLang);
601 // helper method to add a pref lang to an array, if not already in array
602 static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen,
603 eFontPrefLang aAddLang);
605 // default serif/sans-serif choice based on font.default.xxx prefs
606 mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang);
608 // Returns true if the font family whitelist is not empty. In this case we
609 // ignore the "CSS visibility level"; only the given fonts are present in
610 // the browser's font list.
611 bool IsFontFamilyWhitelistActive() const {
612 return mFontFamilyWhitelistActive;
615 static void FontWhitelistPrefChanged(const char* aPref, void* aClosure);
617 bool AddWithLegacyFamilyName(const nsACString& aLegacyName,
618 gfxFontEntry* aFontEntry,
619 FontVisibility aVisibility);
621 static const char* GetGenericName(
622 mozilla::StyleGenericFontFamily aGenericType);
624 bool SkipFontFallbackForChar(FontVisibility aVisibility, uint32_t aCh) const {
625 AutoLock lock(mLock);
626 return mCodepointsWithNoFonts[aVisibility].test(aCh);
629 // Return whether the given font-family record should be visible to CSS,
630 // in a context with the given FontVisibility setting.
631 bool IsVisibleToCSS(const gfxFontFamily& aFamily,
632 FontVisibility aVisibility) const;
633 bool IsVisibleToCSS(const mozilla::fontlist::Family& aFamily,
634 FontVisibility aVisibility) const;
636 // (Re-)initialize the set of codepoints that we know cannot be rendered.
637 void InitializeCodepointsWithNoFonts() MOZ_REQUIRES(mLock);
639 // If using the shared font list, returns a generation count that is
640 // incremented if/when the platform list is reinitialized (e.g. because
641 // fonts are installed/removed while the browser is running), such that
642 // existing references to shared font family or face objects and character
643 // maps will no longer be valid.
644 // (The legacy (non-shared) list just returns 0 here.)
645 uint32_t GetGeneration() const;
647 // Sometimes we need to know if we're on the InitFontList startup thread.
648 static bool IsInitFontListThread() {
649 return PR_GetCurrentThread() == sInitFontListThread;
652 bool IsKnownIconFontFamily(const nsAtom* aFamilyName) const;
653 void LoadIconFontOverrideList();
655 void Lock() MOZ_CAPABILITY_ACQUIRE(mLock) { mLock.Lock(); }
656 void Unlock() MOZ_CAPABILITY_RELEASE(mLock) { mLock.Unlock(); }
658 // This is only public because some external callers want to be able to
659 // assert about the locked status.
660 mutable mozilla::RecursiveMutex mLock;
662 protected:
663 virtual nsTArray<std::pair<const char**, uint32_t>>
664 GetFilteredPlatformFontLists() = 0;
666 friend class mozilla::fontlist::FontList;
667 friend class InitOtherFamilyNamesForStylo;
669 template <size_t N>
670 static bool FamilyInList(const nsACString& aName, const char* (&aList)[N]) {
671 return FamilyInList(aName, aList, N);
673 static bool FamilyInList(const nsACString& aName, const char* aList[],
674 size_t aCount);
676 // Check list is correctly sorted (in debug build only; no-op on release).
677 template <size_t N>
678 static void CheckFamilyList(const char* (&aList)[N]) {
679 CheckFamilyList(aList, N);
681 static void CheckFamilyList(const char* aList[], size_t aCount);
683 class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable {
684 public:
685 InitOtherFamilyNamesRunnable()
686 : CancelableRunnable(
687 "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
688 mIsCanceled(false) {}
690 NS_IMETHOD Run() override {
691 if (mIsCanceled) {
692 return NS_OK;
695 gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList();
696 if (!fontList) {
697 return NS_OK;
700 fontList->InitOtherFamilyNamesInternal(true);
702 return NS_OK;
705 nsresult Cancel() override {
706 mIsCanceled = true;
708 return NS_OK;
711 private:
712 bool mIsCanceled;
715 class MemoryReporter final : public nsIMemoryReporter {
716 ~MemoryReporter() = default;
718 public:
719 NS_DECL_ISUPPORTS
720 NS_DECL_NSIMEMORYREPORTER
723 class PrefName final : public nsAutoCString {
724 void Init(const nsACString& aGeneric, const nsACString& aLangGroup) {
725 Assign(aGeneric);
726 if (!aLangGroup.IsEmpty()) {
727 Append('.');
728 Append(aLangGroup);
732 public:
733 PrefName(const nsACString& aGeneric, const nsACString& aLangGroup) {
734 Init(aGeneric, aLangGroup);
737 PrefName(const char* aGeneric, const char* aLangGroup) {
738 Init(nsDependentCString(aGeneric), nsDependentCString(aLangGroup));
741 PrefName(const char* aGeneric, nsAtom* aLangGroup) {
742 if (aLangGroup) {
743 Init(nsDependentCString(aGeneric), nsAtomCString(aLangGroup));
744 } else {
745 Init(nsDependentCString(aGeneric), nsAutoCString());
750 explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
752 static gfxPlatformFontList* sPlatformFontList;
755 * Convenience method to return the first matching family (if any) as found
756 * by FindAndAddFamilies(). The family will be initialized (synchronously)
757 * if this has not already been done, so the returned pointer, if non-null,
758 * is ready for use.
760 mozilla::fontlist::Family* FindSharedFamily(
761 nsPresContext* aPresContext, const nsACString& aFamily,
762 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
763 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
764 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock);
766 gfxFontFamily* FindUnsharedFamily(
767 nsPresContext* aPresContext, const nsACString& aFamily,
768 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
769 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
770 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) {
771 if (SharedFontList()) {
772 return nullptr;
774 AutoTArray<FamilyAndGeneric, 1> families;
775 if (FindAndAddFamiliesLocked(
776 aPresContext, mozilla::StyleGenericFontFamily::None, aFamily,
777 &families, aFlags, aStyle, aLanguage, aDevToCssSize)) {
778 return families[0].mFamily.mUnshared;
780 return nullptr;
783 FontFamily FindFamily(nsPresContext* aPresContext, const nsACString& aFamily,
784 FindFamiliesFlags aFlags = FindFamiliesFlags(0),
785 gfxFontStyle* aStyle = nullptr,
786 nsAtom* aLanguage = nullptr,
787 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) {
788 if (SharedFontList()) {
789 return FontFamily(FindSharedFamily(aPresContext, aFamily, aFlags, aStyle,
790 aLanguage, aDevToCssSize));
792 return FontFamily(FindUnsharedFamily(aPresContext, aFamily, aFlags, aStyle,
793 aLanguage, aDevToCssSize));
796 // Lookup family name in global family list without substitutions or
797 // localized family name lookup. Used for common font fallback families.
798 gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily)
799 MOZ_REQUIRES(mLock) {
800 nsAutoCString key;
801 gfxFontFamily* familyEntry;
802 GenerateFontListKey(aFamily, key);
803 if ((familyEntry = mFontFamilies.GetWeak(key))) {
804 return CheckFamily(familyEntry);
806 return nullptr;
809 // returns default font for a given character, null otherwise
810 already_AddRefed<gfxFont> CommonFontFallback(nsPresContext* aPresContext,
811 uint32_t aCh, uint32_t aNextCh,
812 Script aRunScript,
813 eFontPresentation aPresentation,
814 const gfxFontStyle* aMatchStyle,
815 FontFamily& aMatchedFamily)
816 MOZ_REQUIRES(mLock);
818 // Search fonts system-wide for a given character, null if not found.
819 already_AddRefed<gfxFont> GlobalFontFallback(
820 nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
821 Script aRunScript, eFontPresentation aPresentation,
822 const gfxFontStyle* aMatchStyle, uint32_t& aCmapCount,
823 FontFamily& aMatchedFamily) MOZ_REQUIRES(mLock);
825 // Platform-specific implementation of global font fallback, if any;
826 // this may return nullptr in which case the default cmap-based fallback
827 // will be performed.
828 virtual gfxFontEntry* PlatformGlobalFontFallback(
829 nsPresContext* aPresContext, const uint32_t aCh, Script aRunScript,
830 const gfxFontStyle* aMatchStyle, FontFamily& aMatchedFamily) {
831 return nullptr;
834 // whether system-based font fallback is used or not
835 // if system fallback is used, no need to load all cmaps
836 virtual bool UsesSystemFallback() { return false; }
838 void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen,
839 eFontPrefLang aCharLang, eFontPrefLang aPageLang)
840 MOZ_REQUIRES(mLock);
842 // verifies that a family contains a non-zero font count
843 gfxFontFamily* CheckFamily(gfxFontFamily* aFamily) MOZ_REQUIRES(mLock);
845 // initialize localized family names
846 void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading);
847 void CancelInitOtherFamilyNamesTask();
849 void AddToMissedNames(const nsCString& aKey) MOZ_REQUIRES(mLock);
851 // search through font families, looking for a given name, initializing
852 // facename lists along the way. first checks all families with names
853 // close to face name, then searchs all families if not found.
854 gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName)
855 MOZ_REQUIRES(mLock);
857 // helper method for finding fullname/postscript names in facename lists
858 gfxFontEntry* FindFaceName(const nsACString& aFaceName) MOZ_REQUIRES(mLock);
860 // look up a font by name, for cases where platform font list
861 // maintains explicit mappings of fullname/psname ==> font
862 virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFaceName)
863 MOZ_REQUIRES(mLock);
865 gfxFontEntry* LookupInSharedFaceNameList(nsPresContext* aPresContext,
866 const nsACString& aFaceName,
867 WeightRange aWeightForEntry,
868 StretchRange aStretchForEntry,
869 SlantStyleRange aStyleForEntry)
870 MOZ_REQUIRES(mLock);
872 // load the bad underline blocklist from pref.
873 void LoadBadUnderlineList();
875 // This version of the function will not modify aKeyName
876 void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult);
877 // This version of the function WILL modify aKeyName
878 void GenerateFontListKey(nsACString& aKeyName);
880 virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames)
881 MOZ_REQUIRES(mLock);
883 // helper function to map lang to lang group
884 nsAtom* GetLangGroup(nsAtom* aLanguage);
886 // gfxFontInfoLoader overrides, used to load in font cmaps
887 void InitLoader() MOZ_REQUIRES(mLock) override;
888 bool LoadFontInfo() override;
889 void CleanupLoader() override;
891 void ForceGlobalReflowLocked(
892 gfxPlatform::NeedsReframe aNeedsReframe,
893 gfxPlatform::BroadcastToChildren aBroadcastToChildren =
894 gfxPlatform::BroadcastToChildren::Yes) MOZ_REQUIRES(mLock);
896 // read the loader initialization prefs, and start it
897 void GetPrefsAndStartLoader();
899 // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
900 // be discarded (not potentially reused to satisfy the rebuilt rules),
901 // because they may no longer be valid.
902 void RebuildLocalFonts(bool aForgetLocalFaces = false) MOZ_REQUIRES(mLock);
904 void ResolveGenericFontNames(nsPresContext* aPresContext,
905 mozilla::StyleGenericFontFamily aGenericType,
906 eFontPrefLang aPrefLang,
907 PrefFontList* aGenericFamilies)
908 MOZ_REQUIRES(mLock);
910 void ResolveEmojiFontNames(nsPresContext* aPresContext,
911 PrefFontList* aGenericFamilies)
912 MOZ_REQUIRES(mLock);
914 void GetFontFamiliesFromGenericFamilies(
915 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGenericType,
916 nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
917 PrefFontList* aFontFamilies) MOZ_REQUIRES(mLock);
919 virtual nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) = 0;
920 virtual void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) {}
922 virtual gfxFontEntry* CreateFontEntry(
923 mozilla::fontlist::Face* aFace,
924 const mozilla::fontlist::Family* aFamily) {
925 return nullptr;
929 * Methods to apply the font.system.whitelist anti-fingerprinting pref,
930 * by filtering the list of installed fonts so that only whitelisted families
931 * are exposed.
932 * There are separate implementations of this for the per-process font list
933 * and for the shared-memory font list.
935 void ApplyWhitelist() MOZ_REQUIRES(mLock);
936 void ApplyWhitelist(nsTArray<mozilla::fontlist::Family::InitData>& aFamilies);
938 // Create a new gfxFontFamily of the appropriate subclass for the platform,
939 // used when AddWithLegacyFamilyName needs to create a new family.
940 virtual gfxFontFamily* CreateFontFamily(const nsACString& aName,
941 FontVisibility aVisibility) const = 0;
944 * For the post-startup font info loader task.
945 * Perform platform-specific work to read alternate names (if any) for a
946 * font family, recording them in mAliasTable. Once alternate names have been
947 * loaded for all families, the accumulated records are stored in the shared
948 * font list's mAliases list.
949 * Some platforms (currently Linux/fontconfig) may load alternate names as
950 * part of initially populating the font list with family records, in which
951 * case this method is unused.
953 virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
954 bool aNeedFullnamePostscriptNames)
955 MOZ_REQUIRES(mLock) {}
957 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontFamily> FontFamilyTable;
958 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontEntry> FontEntryTable;
960 // used by memory reporter to accumulate sizes of family names in the table
961 static size_t SizeOfFontFamilyTableExcludingThis(
962 const FontFamilyTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
963 static size_t SizeOfFontEntryTableExcludingThis(
964 const FontEntryTable& aTable, mozilla::MallocSizeOf aMallocSizeOf);
966 // Platform-specific helper for GetDefaultFont(...).
967 virtual FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
968 const gfxFontStyle* aStyle,
969 nsAtom* aLanguage = nullptr)
970 MOZ_REQUIRES(mLock) = 0;
972 // canonical family name ==> family entry (unique, one name per family entry)
973 FontFamilyTable mFontFamilies MOZ_GUARDED_BY(mLock);
975 // other family name ==> family entry (not unique, can have multiple names per
976 // family entry, only names *other* than the canonical names are stored here)
977 FontFamilyTable mOtherFamilyNames MOZ_GUARDED_BY(mLock);
979 // flag set after InitOtherFamilyNames is called upon first name lookup miss
980 mozilla::Atomic<bool> mOtherFamilyNamesInitialized;
982 // The pending InitOtherFamilyNames() task.
983 RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask;
985 // flag set after fullname and Postcript name lists are populated
986 mozilla::Atomic<bool> mFaceNameListsInitialized;
988 struct ExtraNames {
989 ExtraNames() = default;
991 // fullname ==> font entry (unique, one name per font entry)
992 FontEntryTable mFullnames{64};
993 // Postscript name ==> font entry (unique, one name per font entry)
994 FontEntryTable mPostscriptNames{64};
996 // The lock is needed to guard access to the actual name tables, but does not
997 // need to be held to just test whether mExtraNames is non-null as it is set
998 // during initialization before other threads have a chance to see it.
999 mozilla::UniquePtr<ExtraNames> mExtraNames MOZ_PT_GUARDED_BY(mLock);
1001 // face names missed when face name loading takes a long time
1002 mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed
1003 MOZ_GUARDED_BY(mLock);
1005 // localized family names missed when face name loading takes a long time
1006 mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed
1007 MOZ_GUARDED_BY(mLock);
1009 typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>,
1010 size_t(mozilla::StyleGenericFontFamily::None),
1011 size_t(
1012 mozilla::StyleGenericFontFamily::MozEmoji)>
1013 PrefFontsForLangGroup;
1014 mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First,
1015 eFontPrefLang_Count>
1016 mLangGroupPrefFonts MOZ_GUARDED_BY(mLock);
1017 mozilla::UniquePtr<PrefFontList> mEmojiPrefFont MOZ_GUARDED_BY(mLock);
1019 // When system-wide font lookup fails for a character, cache it to skip future
1020 // searches. This is an array of bitsets, one for each FontVisibility level.
1021 mozilla::EnumeratedArray<FontVisibility, gfxSparseBitSet,
1022 size_t(FontVisibility::Count)>
1023 mCodepointsWithNoFonts MOZ_GUARDED_BY(mLock);
1025 // the family to use for U+FFFD fallback, to avoid expensive search every time
1026 // on pages with lots of problems
1027 mozilla::EnumeratedArray<FontVisibility, FontFamily,
1028 size_t(FontVisibility::Count)>
1029 mReplacementCharFallbackFamily MOZ_GUARDED_BY(mLock);
1031 // Sorted array of lowercased family names; use ContainsSorted to test
1032 nsTArray<nsCString> mBadUnderlineFamilyNames;
1034 // character map data shared across families
1035 // contains weak ptrs to cmaps shared by font entry objects
1036 nsTHashtable<CharMapHashKey> mSharedCmaps MOZ_GUARDED_BY(mLock);
1038 nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps MOZ_GUARDED_BY(mLock);
1040 // data used as part of the font cmap loading process
1041 nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad MOZ_GUARDED_BY(mLock);
1042 uint32_t mStartIndex MOZ_GUARDED_BY(mLock) = 0;
1043 uint32_t mNumFamilies MOZ_GUARDED_BY(mLock) = 0;
1045 // xxx - info for diagnosing no default font aborts
1046 // see bugs 636957, 1070983, 1189129
1047 uint32_t mFontlistInitCount = 0; // num times InitFontList called
1049 nsTHashSet<gfxUserFontSet*> mUserFontSetList MOZ_GUARDED_BY(mLock);
1051 nsLanguageAtomService* mLangService = nullptr;
1053 nsTArray<uint32_t> mCJKPrefLangs MOZ_GUARDED_BY(mLock);
1054 nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup
1055 MOZ_GUARDED_BY(mLock);
1057 nsTArray<nsCString> mEnabledFontsList;
1058 nsTHashSet<nsCString> mIconFontsSet;
1060 mozilla::UniquePtr<mozilla::fontlist::FontList> mSharedFontList;
1062 nsClassHashtable<nsCStringHashKey, mozilla::fontlist::AliasData> mAliasTable;
1063 nsTHashMap<nsCStringHashKey, mozilla::fontlist::LocalFaceRec::InitData>
1064 mLocalNameTable;
1066 nsRefPtrHashtable<nsPtrHashKey<const mozilla::fontlist::Face>, gfxFontEntry>
1067 mFontEntries MOZ_GUARDED_BY(mLock);
1069 mozilla::UniquePtr<FontPrefs> mFontPrefs;
1071 RefPtr<gfxFontEntry> mDefaultFontEntry MOZ_GUARDED_BY(mLock);
1073 RefPtr<mozilla::CancelableRunnable> mLoadCmapsRunnable;
1074 uint32_t mStartedLoadingCmapsFrom MOZ_GUARDED_BY(mLock) = 0xffffffffu;
1076 bool mFontFamilyWhitelistActive = false;
1078 static PRThread* sInitFontListThread;
1081 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags)
1083 #endif /* GFXPLATFORMFONTLIST_H_ */