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"
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"
37 } // namespace mozilla
39 class CharMapHashKey
: public PLDHashEntryHdr
{
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
) {
62 return mCharMap
->Equals(aCharMap
);
65 static const gfxCharacterMap
* KeyToPointer(gfxCharacterMap
* aCharMap
) {
68 static PLDHashNumber
HashKey(const gfxCharacterMap
* aCharMap
) {
69 return aCharMap
->mHash
;
72 enum { ALLOW_MEMMOVE
= true };
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
;
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
{
87 typedef const gfxSparseBitSet
* KeyType
;
88 typedef const gfxSparseBitSet
* KeyTypePointer
;
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()) {
115 return static_cast<const SharedBitSet
*>(mCharMap
.ToPtr(mList
))
119 static KeyTypePointer
KeyToPointer(KeyType aCharMap
) { return aCharMap
; }
120 static PLDHashNumber
HashKey(KeyType aCharMap
) {
121 return aCharMap
->GetChecksum();
124 enum { ALLOW_MEMMOVE
= true };
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
;
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
142 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on
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
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
;
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
{
172 using HashMap
= nsTHashMap
<nsCStringHashKey
, nsCString
>;
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();
195 static constexpr char kNamePrefix
[] = "font.name.";
196 static constexpr char kNameListPrefix
[] = "font.name-list.";
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
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.
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
296 eNoAddToNamesMissedWhenSearching
= 1 << 2,
298 // If set, the family name was quoted and so must not be treated as a CSS
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
,
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
) {
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
,
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
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
;
585 friend class mozilla::fontlist::FontList
;
586 friend class InitOtherFamilyNamesForStylo
;
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
[],
595 // Check list is correctly sorted (in debug build only; no-op on release).
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
{
604 InitOtherFamilyNamesRunnable()
605 : CancelableRunnable(
606 "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
607 mIsCanceled(false) {}
609 NS_IMETHOD
Run() override
{
614 gfxPlatformFontList
* fontList
= gfxPlatformFontList::PlatformFontList();
619 fontList
->InitOtherFamilyNamesInternal(true);
624 nsresult
Cancel() override
{
634 class MemoryReporter final
: public nsIMemoryReporter
{
635 ~MemoryReporter() = default;
639 NS_DECL_NSIMEMORYREPORTER
642 class PrefName final
: public nsAutoCString
{
643 void Init(const nsACString
& aGeneric
, const nsACString
& aLangGroup
) {
645 if (!aLangGroup
.IsEmpty()) {
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
) {
662 Init(nsDependentCString(aGeneric
), nsAtomCString(aLangGroup
));
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,
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()) {
693 AutoTArray
<FamilyAndGeneric
, 1> families
;
694 if (FindAndAddFamilies(aPresContext
, mozilla::StyleGenericFontFamily::None
,
695 aFamily
, &families
, aFlags
, aStyle
, aLanguage
,
697 return families
[0].mFamily
.mUnshared
;
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
) {
719 gfxFontFamily
* familyEntry
;
720 GenerateFontListKey(aFamily
, key
);
721 if ((familyEntry
= mFontFamilies
.GetWeak(key
))) {
722 return CheckFamily(familyEntry
);
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
) {
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
) {
828 * Methods to apply the font.system.whitelist anti-fingerprinting pref,
829 * by filtering the list of installed fonts so that only whitelisted families
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;
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
),
907 mozilla::StyleGenericFontFamily::MozEmoji
)>
908 PrefFontsForLangGroup
;
909 mozilla::RangedArray
<PrefFontsForLangGroup
, eFontPrefLang_First
,
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
,
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
>
958 nsRefPtrHashtable
<nsPtrHashKey
<mozilla::fontlist::Face
>, gfxFontEntry
>
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_ */