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/RangedArray.h"
28 #include "mozilla/RecursiveMutex.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 using AutoLock
= mozilla::RecursiveMutexAutoLock
;
168 using AutoUnlock
= mozilla::RecursiveMutexAutoUnlock
;
170 // Class used to hold cached copies of the font-name prefs, so that they can
171 // be accessed from non-main-thread callers who are not allowed to touch the
172 // Preferences service.
173 class FontPrefs final
{
175 using HashMap
= nsTHashMap
<nsCStringHashKey
, nsCString
>;
178 ~FontPrefs() = default;
180 FontPrefs(const FontPrefs
& aOther
) = delete;
181 FontPrefs
& operator=(const FontPrefs
& aOther
) = delete;
183 // Lookup the font.name.<foo> or font.name-list.<foo> pref for a given
184 // generic+langgroup pair.
185 bool LookupName(const nsACString
& aPref
, nsACString
& aValue
) const;
186 bool LookupNameList(const nsACString
& aPref
, nsACString
& aValue
) const;
188 // Does the font.name-list.emoji pref have a user-set value?
189 bool EmojiHasUserValue() const { return mEmojiHasUserValue
; }
191 // Expose iterators over all the defined prefs of each type.
192 HashMap::ConstIterator
NameIter() const { return mFontName
.ConstIter(); }
193 HashMap::ConstIterator
NameListIter() const {
194 return mFontNameList
.ConstIter();
198 static constexpr char kNamePrefix
[] = "font.name.";
199 static constexpr char kNameListPrefix
[] = "font.name-list.";
204 HashMap mFontNameList
;
205 bool mEmojiHasUserValue
= false;
208 // For font family lists loaded from user preferences (prefs such as
209 // font.name-list.<generic>.<langGroup>) that map CSS generics to
210 // platform-specific font families.
211 typedef nsTArray
<FontFamily
> PrefFontList
;
213 static gfxPlatformFontList
* PlatformFontList() {
214 // If there is a font-list initialization thread, we need to let it run
215 // to completion before the font list can be used for anything else.
216 if (sInitFontListThread
) {
217 // If we're currently on the initialization thread, just continue;
218 // otherwise wait for it to finish.
219 if (IsInitFontListThread()) {
220 return sPlatformFontList
;
222 PR_JoinThread(sInitFontListThread
);
223 sInitFontListThread
= nullptr;
224 // If font-list initialization failed, the thread will have cleared
225 // the static sPlatformFontList pointer; we cannot proceed without any
227 if (!sPlatformFontList
) {
228 MOZ_CRASH("Could not initialize gfxPlatformFontList");
231 if (!sPlatformFontList
->IsInitialized()) {
232 if (!sPlatformFontList
->InitFontList()) {
233 MOZ_CRASH("Could not initialize gfxPlatformFontList");
236 return sPlatformFontList
;
239 static bool Initialize(gfxPlatformFontList
* aList
);
241 static void Shutdown() {
242 delete sPlatformFontList
;
243 sPlatformFontList
= nullptr;
246 bool IsInitialized() const { return mFontlistInitCount
; }
248 virtual ~gfxPlatformFontList();
250 // Initialize font lists; return true on success, false if something fails.
253 void FontListChanged();
256 * Gathers (from a platform's underlying font system) the information needed
257 * to initialize a fontlist::Family with its Face members.
259 virtual void GetFacesInitDataForFamily(
260 const mozilla::fontlist::Family
* aFamily
,
261 nsTArray
<mozilla::fontlist::Face::InitData
>& aFaces
,
262 bool aLoadCmaps
) const {}
264 virtual void GetFontList(nsAtom
* aLangGroup
, const nsACString
& aGenericFamily
,
265 nsTArray
<nsString
>& aListOfFonts
);
267 // Pass false to notify content that the shared font list has been modified
268 // but not completely invalidated.
269 void UpdateFontList(bool aFullRebuild
= true);
271 void ClearLangGroupPrefFonts() {
272 AutoLock
lock(mLock
);
273 ClearLangGroupPrefFontsLocked();
275 virtual void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock
);
277 void GetFontFamilyList(nsTArray
<RefPtr
<gfxFontFamily
>>& aFamilyArray
);
279 already_AddRefed
<gfxFont
> SystemFindFontForChar(
280 nsPresContext
* aPresContext
, uint32_t aCh
, uint32_t aNextCh
,
281 Script aRunScript
, eFontPresentation aPresentation
,
282 const gfxFontStyle
* aStyle
, FontVisibility
* aVisibility
);
284 // Flags to control optional behaviors in FindAndAddFamilies. The sense
285 // of the bit flags have been chosen such that the default parameter of
286 // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired
287 // behavior, and only a few callsites need to explicitly pass other values.
288 enum class FindFamiliesFlags
{
289 // If set, "other" (e.g. localized) family names should be loaded
290 // immediately; if clear, InitOtherFamilyNames is allowed to defer
291 // loading to avoid blocking.
292 eForceOtherFamilyNamesLoading
= 1 << 0,
294 // If set, FindAndAddFamilies should not check for legacy "styled
295 // family" names to add to the font list. This is used to avoid
296 // a recursive search when using FindFamily to find a potential base
297 // family name for a styled variant.
298 eNoSearchForLegacyFamilyNames
= 1 << 1,
300 // If set, FindAndAddFamilies will not add a missing entry to
302 eNoAddToNamesMissedWhenSearching
= 1 << 2,
304 // If set, the family name was quoted and so must not be treated as a CSS
306 eQuotedFamilyName
= 1 << 3,
308 // If set, "hidden" font families (like ".SF NS Text" on macOS) are
309 // searched in addition to standard user-visible families.
310 eSearchHiddenFamilies
= 1 << 4,
313 // Find family(ies) matching aFamily and append to the aOutput array
314 // (there may be multiple results in the case of fontconfig aliases, etc).
315 // Return true if any match was found and appended, false if none.
316 bool FindAndAddFamilies(
317 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
318 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
319 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
320 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0) {
321 AutoLock
lock(mLock
);
322 return FindAndAddFamiliesLocked(aPresContext
, aGeneric
, aFamily
, aOutput
,
323 aFlags
, aStyle
, aLanguage
, aDevToCssSize
);
325 virtual bool FindAndAddFamiliesLocked(
326 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
327 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
328 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
329 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0)
332 gfxFontEntry
* FindFontForFamily(nsPresContext
* aPresContext
,
333 const nsACString
& aFamily
,
334 const gfxFontStyle
* aStyle
);
336 mozilla::fontlist::FontList
* SharedFontList() const {
337 return mSharedFontList
.get();
340 // Create a handle for a single shmem block (identified by index) ready to
341 // be shared to the given processId.
342 void ShareFontListShmBlockToProcess(uint32_t aGeneration
, uint32_t aIndex
,
343 base::ProcessId aPid
,
344 base::SharedMemoryHandle
* aOut
);
346 // Populate the array aBlocks with the complete list of shmem handles ready
347 // to be shared to the given processId.
348 void ShareFontListToProcess(nsTArray
<base::SharedMemoryHandle
>* aBlocks
,
349 base::ProcessId aPid
);
351 void ShmBlockAdded(uint32_t aGeneration
, uint32_t aIndex
,
352 base::SharedMemoryHandle aHandle
);
354 base::SharedMemoryHandle
ShareShmBlockToProcess(uint32_t aIndex
,
355 base::ProcessId aPid
);
357 void SetCharacterMap(uint32_t aGeneration
,
358 const mozilla::fontlist::Pointer
& aFacePtr
,
359 const gfxSparseBitSet
& aMap
);
361 void SetupFamilyCharMap(uint32_t aGeneration
,
362 const mozilla::fontlist::Pointer
& aFamilyPtr
);
364 // Start the async cmap loading process, if not already under way, from the
365 // given family index. (For use in any process that needs font lookups.)
366 void StartCmapLoadingFromFamily(uint32_t aStartIndex
);
368 // [Parent] Handle request from content process to start cmap loading.
369 void StartCmapLoading(uint32_t aGeneration
, uint32_t aStartIndex
);
371 void CancelLoadCmapsTask() {
372 if (mLoadCmapsRunnable
) {
373 mLoadCmapsRunnable
->Cancel();
374 mLoadCmapsRunnable
= nullptr;
378 // Populate aFamily with face records, and if aLoadCmaps is true, also load
379 // their character maps (rather than leaving this to be done lazily).
380 // Note that even when aFamily->IsInitialized() is true, it can make sense
381 // to call InitializeFamily again if passing aLoadCmaps=true, in order to
382 // ensure cmaps are loaded.
383 [[nodiscard
]] bool InitializeFamily(mozilla::fontlist::Family
* aFamily
,
384 bool aLoadCmaps
= false);
385 void InitializeFamily(uint32_t aGeneration
, uint32_t aFamilyIndex
,
388 // name lookup table methods
390 void AddOtherFamilyNames(gfxFontFamily
* aFamilyEntry
,
391 const nsTArray
<nsCString
>& aOtherFamilyNames
);
393 void AddFullname(gfxFontEntry
* aFontEntry
, const nsCString
& aFullname
) {
394 AutoLock
lock(mLock
);
395 AddFullnameLocked(aFontEntry
, aFullname
);
397 void AddFullnameLocked(gfxFontEntry
* aFontEntry
, const nsCString
& aFullname
)
400 void AddPostscriptName(gfxFontEntry
* aFontEntry
,
401 const nsCString
& aPostscriptName
) {
402 AutoLock
lock(mLock
);
403 AddPostscriptNameLocked(aFontEntry
, aPostscriptName
);
405 void AddPostscriptNameLocked(gfxFontEntry
* aFontEntry
,
406 const nsCString
& aPostscriptName
)
409 bool NeedFullnamePostscriptNames() { return mExtraNames
!= nullptr; }
412 * Read PSName and FullName of the given face, for src:local lookup,
413 * returning true if actually implemented and succeeded.
415 virtual bool ReadFaceNames(mozilla::fontlist::Family
* aFamily
,
416 mozilla::fontlist::Face
* aFace
, nsCString
& aPSName
,
417 nsCString
& aFullName
) {
421 // initialize localized family names
422 bool InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading
);
423 bool InitOtherFamilyNames(uint32_t aGeneration
, bool aDefer
);
425 // pure virtual functions, to be provided by concrete subclasses
427 // get the system default font family
428 FontFamily
GetDefaultFont(nsPresContext
* aPresContext
,
429 const gfxFontStyle
* aStyle
);
430 FontFamily
GetDefaultFontLocked(nsPresContext
* aPresContext
,
431 const gfxFontStyle
* aStyle
)
434 // get the "ultimate" default font, for use if the font list is otherwise
435 // unusable (e.g. in the middle of being updated)
436 gfxFontEntry
* GetDefaultFontEntry() {
437 AutoLock
lock(mLock
);
438 return mDefaultFontEntry
.get();
442 * Look up a font by name on the host platform.
444 * Note that the style attributes (weight, stretch, style) are NOT used in
445 * selecting the platform font, which is looked up by name only; these are
446 * values to be recorded in the new font entry.
448 virtual gfxFontEntry
* LookupLocalFont(nsPresContext
* aPresContext
,
449 const nsACString
& aFontName
,
450 WeightRange aWeightForEntry
,
451 StretchRange aStretchForEntry
,
452 SlantStyleRange aStyleForEntry
) = 0;
455 * Create a new platform font from downloaded data (@font-face).
457 * Note that the style attributes (weight, stretch, style) are NOT related
458 * (necessarily) to any values within the font resource itself; these are
459 * values to be recorded in the new font entry and used for face selection,
460 * in place of whatever inherent style attributes the resource may have.
462 * This method takes ownership of the data block passed in as aFontData,
463 * and must ensure it is free()'d when no longer required.
465 virtual gfxFontEntry
* MakePlatformFont(const nsACString
& aFontName
,
466 WeightRange aWeightForEntry
,
467 StretchRange aStretchForEntry
,
468 SlantStyleRange aStyleForEntry
,
469 const uint8_t* aFontData
,
470 uint32_t aLength
) = 0;
472 // get the standard family name on the platform for a given font name
473 // (platforms may override, eg Mac)
474 virtual bool GetStandardFamilyName(const nsCString
& aFontName
,
475 nsACString
& aFamilyName
);
477 // Get the localized family name for a given font family.
478 bool GetLocalizedFamilyName(const FontFamily
& aFamily
,
479 nsACString
& aFamilyName
);
481 // get the default font name which is available on the system from
482 // font.name-list.*. if there are no available fonts in the pref,
483 // returns an empty FamilyAndGeneric record.
484 FamilyAndGeneric
GetDefaultFontFamily(const nsACString
& aLangGroup
,
485 const nsACString
& aGenericFamily
);
487 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
488 FontListSizes
* aSizes
) const;
489 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
490 FontListSizes
* aSizes
) const;
492 mozilla::fontlist::Pointer
GetShmemCharMap(const gfxSparseBitSet
* aCmap
) {
493 AutoLock
lock(mLock
);
494 return GetShmemCharMapLocked(aCmap
);
496 mozilla::fontlist::Pointer
GetShmemCharMapLocked(const gfxSparseBitSet
* aCmap
)
499 // Search for existing cmap that matches the input; return the input if no
501 already_AddRefed
<gfxCharacterMap
> FindCharMap(gfxCharacterMap
* aCmap
);
503 // Remove the cmap from the shared cmap set.
504 void RemoveCmap(const gfxCharacterMap
* aCharMap
);
506 // Keep track of userfont sets to notify when global fontlist changes occur.
507 void AddUserFontSet(gfxUserFontSet
* aUserFontSet
) {
508 AutoLock
lock(mLock
);
509 mUserFontSetList
.Insert(aUserFontSet
);
512 void RemoveUserFontSet(gfxUserFontSet
* aUserFontSet
) {
513 AutoLock
lock(mLock
);
514 mUserFontSetList
.Remove(aUserFontSet
);
517 static const gfxFontEntry::ScriptRange sComplexScriptRanges
[];
519 void GetFontlistInitInfo(uint32_t& aNumInits
, uint32_t& aLoaderState
) {
520 aNumInits
= mFontlistInitCount
;
521 aLoaderState
= (uint32_t)mState
;
524 virtual void AddGenericFonts(nsPresContext
* aPresContext
,
525 mozilla::StyleGenericFontFamily aGenericType
,
527 nsTArray
<FamilyAndGeneric
>& aFamilyList
);
530 * Given a Face from the shared font list, return a gfxFontEntry usable
531 * by the current process. This returns a cached entry if available,
532 * otherwise it calls the (platform-specific) CreateFontEntry method to
533 * make one, and adds it to the cache.
535 gfxFontEntry
* GetOrCreateFontEntry(mozilla::fontlist::Face
* aFace
,
536 const mozilla::fontlist::Family
* aFamily
) {
537 AutoLock
lock(mLock
);
538 return GetOrCreateFontEntryLocked(aFace
, aFamily
);
540 gfxFontEntry
* GetOrCreateFontEntryLocked(
541 mozilla::fontlist::Face
* aFace
, const mozilla::fontlist::Family
* aFamily
)
544 const FontPrefs
* GetFontPrefs() const MOZ_REQUIRES(mLock
) {
545 return mFontPrefs
.get();
548 bool EmojiPrefHasUserValue() const {
549 AutoLock
lock(mLock
);
550 return mFontPrefs
->EmojiHasUserValue();
553 PrefFontList
* GetPrefFontsLangGroup(
554 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGenericType
,
555 eFontPrefLang aPrefLang
) {
556 AutoLock
lock(mLock
);
557 return GetPrefFontsLangGroupLocked(aPresContext
, aGenericType
, aPrefLang
);
559 PrefFontList
* GetPrefFontsLangGroupLocked(
560 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGenericType
,
561 eFontPrefLang aPrefLang
) MOZ_REQUIRES(mLock
);
563 // in some situations, need to make decisions about ambiguous characters, may
564 // need to look at multiple pref langs
565 void GetLangPrefs(eFontPrefLang aPrefLangs
[], uint32_t& aLen
,
566 eFontPrefLang aCharLang
, eFontPrefLang aPageLang
);
568 // convert a lang group to enum constant (i.e. "zh-TW" ==>
569 // eFontPrefLang_ChineseTW)
570 static eFontPrefLang
GetFontPrefLangFor(const char* aLang
);
572 // convert a lang group atom to enum constant
573 static eFontPrefLang
GetFontPrefLangFor(nsAtom
* aLang
);
575 // convert an enum constant to a lang group atom
576 static nsAtom
* GetLangGroupForPrefLang(eFontPrefLang aLang
);
578 // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW
580 static const char* GetPrefLangName(eFontPrefLang aLang
);
582 // map a char code to a font language for Preferences
583 static eFontPrefLang
GetFontPrefLangFor(uint32_t aCh
);
585 // returns true if a pref lang is CJK
586 static bool IsLangCJK(eFontPrefLang aLang
);
588 // helper method to add a pref lang to an array, if not already in array
589 static void AppendPrefLang(eFontPrefLang aPrefLangs
[], uint32_t& aLen
,
590 eFontPrefLang aAddLang
);
592 // default serif/sans-serif choice based on font.default.xxx prefs
593 mozilla::StyleGenericFontFamily
GetDefaultGeneric(eFontPrefLang aLang
);
595 // Returns true if the font family whitelist is not empty. In this case we
596 // ignore the "CSS visibility level"; only the given fonts are present in
597 // the browser's font list.
598 bool IsFontFamilyWhitelistActive() const {
599 return mFontFamilyWhitelistActive
;
602 static void FontWhitelistPrefChanged(const char* aPref
, void* aClosure
);
604 bool AddWithLegacyFamilyName(const nsACString
& aLegacyName
,
605 gfxFontEntry
* aFontEntry
,
606 FontVisibility aVisibility
);
608 static const char* GetGenericName(
609 mozilla::StyleGenericFontFamily aGenericType
);
611 bool SkipFontFallbackForChar(FontVisibility aVisibility
, uint32_t aCh
) const {
612 AutoLock
lock(mLock
);
613 return mCodepointsWithNoFonts
[aVisibility
].test(aCh
);
616 // Return whether the given font-family record should be visible to CSS,
617 // in a context with the given FontVisibility setting.
618 bool IsVisibleToCSS(const gfxFontFamily
& aFamily
,
619 FontVisibility aVisibility
) const;
620 bool IsVisibleToCSS(const mozilla::fontlist::Family
& aFamily
,
621 FontVisibility aVisibility
) const;
623 // (Re-)initialize the set of codepoints that we know cannot be rendered.
624 void InitializeCodepointsWithNoFonts() MOZ_REQUIRES(mLock
);
626 // If using the shared font list, returns a generation count that is
627 // incremented if/when the platform list is reinitialized (e.g. because
628 // fonts are installed/removed while the browser is running), such that
629 // existing references to shared font family or face objects and character
630 // maps will no longer be valid.
631 // (The legacy (non-shared) list just returns 0 here.)
632 uint32_t GetGeneration() const;
634 // Sometimes we need to know if we're on the InitFontList startup thread.
635 static bool IsInitFontListThread() {
636 return PR_GetCurrentThread() == sInitFontListThread
;
639 bool IsKnownIconFontFamily(const nsAtom
* aFamilyName
) const;
640 void LoadIconFontOverrideList();
642 void Lock() MOZ_CAPABILITY_ACQUIRE(mLock
) { mLock
.Lock(); }
643 void Unlock() MOZ_CAPABILITY_RELEASE(mLock
) { mLock
.Unlock(); }
645 // This is only public because some external callers want to be able to
646 // assert about the locked status.
647 mutable mozilla::RecursiveMutex mLock
;
650 friend class mozilla::fontlist::FontList
;
651 friend class InitOtherFamilyNamesForStylo
;
654 static bool FamilyInList(const nsACString
& aName
, const char* (&aList
)[N
]) {
655 return FamilyInList(aName
, aList
, N
);
657 static bool FamilyInList(const nsACString
& aName
, const char* aList
[],
660 // Check list is correctly sorted (in debug build only; no-op on release).
662 static void CheckFamilyList(const char* (&aList
)[N
]) {
663 CheckFamilyList(aList
, N
);
665 static void CheckFamilyList(const char* aList
[], size_t aCount
);
667 class InitOtherFamilyNamesRunnable
: public mozilla::CancelableRunnable
{
669 InitOtherFamilyNamesRunnable()
670 : CancelableRunnable(
671 "gfxPlatformFontList::InitOtherFamilyNamesRunnable"),
672 mIsCanceled(false) {}
674 NS_IMETHOD
Run() override
{
679 gfxPlatformFontList
* fontList
= gfxPlatformFontList::PlatformFontList();
684 fontList
->InitOtherFamilyNamesInternal(true);
689 nsresult
Cancel() override
{
699 class MemoryReporter final
: public nsIMemoryReporter
{
700 ~MemoryReporter() = default;
704 NS_DECL_NSIMEMORYREPORTER
707 class PrefName final
: public nsAutoCString
{
708 void Init(const nsACString
& aGeneric
, const nsACString
& aLangGroup
) {
710 if (!aLangGroup
.IsEmpty()) {
717 PrefName(const nsACString
& aGeneric
, const nsACString
& aLangGroup
) {
718 Init(aGeneric
, aLangGroup
);
721 PrefName(const char* aGeneric
, const char* aLangGroup
) {
722 Init(nsDependentCString(aGeneric
), nsDependentCString(aLangGroup
));
725 PrefName(const char* aGeneric
, nsAtom
* aLangGroup
) {
727 Init(nsDependentCString(aGeneric
), nsAtomCString(aLangGroup
));
729 Init(nsDependentCString(aGeneric
), nsAutoCString());
734 explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames
= true);
736 static gfxPlatformFontList
* sPlatformFontList
;
739 * Convenience method to return the first matching family (if any) as found
740 * by FindAndAddFamilies(). The family will be initialized (synchronously)
741 * if this has not already been done, so the returned pointer, if non-null,
744 mozilla::fontlist::Family
* FindSharedFamily(
745 nsPresContext
* aPresContext
, const nsACString
& aFamily
,
746 FindFamiliesFlags aFlags
= FindFamiliesFlags(0),
747 gfxFontStyle
* aStyle
= nullptr, nsAtom
* aLanguage
= nullptr,
748 gfxFloat aDevToCssSize
= 1.0) MOZ_REQUIRES(mLock
);
750 gfxFontFamily
* FindUnsharedFamily(
751 nsPresContext
* aPresContext
, const nsACString
& aFamily
,
752 FindFamiliesFlags aFlags
= FindFamiliesFlags(0),
753 gfxFontStyle
* aStyle
= nullptr, nsAtom
* aLanguage
= nullptr,
754 gfxFloat aDevToCssSize
= 1.0) MOZ_REQUIRES(mLock
) {
755 if (SharedFontList()) {
758 AutoTArray
<FamilyAndGeneric
, 1> families
;
759 if (FindAndAddFamiliesLocked(
760 aPresContext
, mozilla::StyleGenericFontFamily::None
, aFamily
,
761 &families
, aFlags
, aStyle
, aLanguage
, aDevToCssSize
)) {
762 return families
[0].mFamily
.mUnshared
;
767 FontFamily
FindFamily(nsPresContext
* aPresContext
, const nsACString
& aFamily
,
768 FindFamiliesFlags aFlags
= FindFamiliesFlags(0),
769 gfxFontStyle
* aStyle
= nullptr,
770 nsAtom
* aLanguage
= nullptr,
771 gfxFloat aDevToCssSize
= 1.0) MOZ_REQUIRES(mLock
) {
772 if (SharedFontList()) {
773 return FontFamily(FindSharedFamily(aPresContext
, aFamily
, aFlags
, aStyle
,
774 aLanguage
, aDevToCssSize
));
776 return FontFamily(FindUnsharedFamily(aPresContext
, aFamily
, aFlags
, aStyle
,
777 aLanguage
, aDevToCssSize
));
780 // Lookup family name in global family list without substitutions or
781 // localized family name lookup. Used for common font fallback families.
782 gfxFontFamily
* FindFamilyByCanonicalName(const nsACString
& aFamily
)
783 MOZ_REQUIRES(mLock
) {
785 gfxFontFamily
* familyEntry
;
786 GenerateFontListKey(aFamily
, key
);
787 if ((familyEntry
= mFontFamilies
.GetWeak(key
))) {
788 return CheckFamily(familyEntry
);
793 // returns default font for a given character, null otherwise
794 already_AddRefed
<gfxFont
> CommonFontFallback(nsPresContext
* aPresContext
,
795 uint32_t aCh
, uint32_t aNextCh
,
797 eFontPresentation aPresentation
,
798 const gfxFontStyle
* aMatchStyle
,
799 FontFamily
& aMatchedFamily
)
802 // Search fonts system-wide for a given character, null if not found.
803 already_AddRefed
<gfxFont
> GlobalFontFallback(
804 nsPresContext
* aPresContext
, uint32_t aCh
, uint32_t aNextCh
,
805 Script aRunScript
, eFontPresentation aPresentation
,
806 const gfxFontStyle
* aMatchStyle
, uint32_t& aCmapCount
,
807 FontFamily
& aMatchedFamily
) MOZ_REQUIRES(mLock
);
809 // Platform-specific implementation of global font fallback, if any;
810 // this may return nullptr in which case the default cmap-based fallback
811 // will be performed.
812 virtual gfxFontEntry
* PlatformGlobalFontFallback(
813 nsPresContext
* aPresContext
, const uint32_t aCh
, Script aRunScript
,
814 const gfxFontStyle
* aMatchStyle
, FontFamily
& aMatchedFamily
) {
818 // whether system-based font fallback is used or not
819 // if system fallback is used, no need to load all cmaps
820 virtual bool UsesSystemFallback() { return false; }
822 void AppendCJKPrefLangs(eFontPrefLang aPrefLangs
[], uint32_t& aLen
,
823 eFontPrefLang aCharLang
, eFontPrefLang aPageLang
)
826 // verifies that a family contains a non-zero font count
827 gfxFontFamily
* CheckFamily(gfxFontFamily
* aFamily
) MOZ_REQUIRES(mLock
);
829 // initialize localized family names
830 void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading
);
831 void CancelInitOtherFamilyNamesTask();
833 void AddToMissedNames(const nsCString
& aKey
) MOZ_REQUIRES(mLock
);
835 // search through font families, looking for a given name, initializing
836 // facename lists along the way. first checks all families with names
837 // close to face name, then searchs all families if not found.
838 gfxFontEntry
* SearchFamiliesForFaceName(const nsACString
& aFaceName
)
841 // helper method for finding fullname/postscript names in facename lists
842 gfxFontEntry
* FindFaceName(const nsACString
& aFaceName
) MOZ_REQUIRES(mLock
);
844 // look up a font by name, for cases where platform font list
845 // maintains explicit mappings of fullname/psname ==> font
846 virtual gfxFontEntry
* LookupInFaceNameLists(const nsACString
& aFaceName
)
849 gfxFontEntry
* LookupInSharedFaceNameList(nsPresContext
* aPresContext
,
850 const nsACString
& aFaceName
,
851 WeightRange aWeightForEntry
,
852 StretchRange aStretchForEntry
,
853 SlantStyleRange aStyleForEntry
)
856 // load the bad underline blocklist from pref.
857 void LoadBadUnderlineList();
859 void GenerateFontListKey(const nsACString
& aKeyName
, nsACString
& aResult
);
861 virtual void GetFontFamilyNames(nsTArray
<nsCString
>& aFontFamilyNames
)
864 // helper function to map lang to lang group
865 nsAtom
* GetLangGroup(nsAtom
* aLanguage
);
867 // gfxFontInfoLoader overrides, used to load in font cmaps
868 void InitLoader() MOZ_REQUIRES(mLock
) override
;
869 bool LoadFontInfo() override
;
870 void CleanupLoader() override
;
872 void ForceGlobalReflowLocked(
873 gfxPlatform::NeedsReframe aNeedsReframe
,
874 gfxPlatform::BroadcastToChildren aBroadcastToChildren
=
875 gfxPlatform::BroadcastToChildren::Yes
) MOZ_REQUIRES(mLock
);
877 // read the loader initialization prefs, and start it
878 void GetPrefsAndStartLoader();
880 // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must
881 // be discarded (not potentially reused to satisfy the rebuilt rules),
882 // because they may no longer be valid.
883 void RebuildLocalFonts(bool aForgetLocalFaces
= false) MOZ_REQUIRES(mLock
);
885 void ResolveGenericFontNames(nsPresContext
* aPresContext
,
886 mozilla::StyleGenericFontFamily aGenericType
,
887 eFontPrefLang aPrefLang
,
888 PrefFontList
* aGenericFamilies
)
891 void ResolveEmojiFontNames(nsPresContext
* aPresContext
,
892 PrefFontList
* aGenericFamilies
)
895 void GetFontFamiliesFromGenericFamilies(
896 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGenericType
,
897 nsTArray
<nsCString
>& aGenericNameFamilies
, nsAtom
* aLangGroup
,
898 PrefFontList
* aFontFamilies
) MOZ_REQUIRES(mLock
);
900 virtual nsresult
InitFontListForPlatform() MOZ_REQUIRES(mLock
) = 0;
901 virtual void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock
) {}
903 virtual gfxFontEntry
* CreateFontEntry(
904 mozilla::fontlist::Face
* aFace
,
905 const mozilla::fontlist::Family
* aFamily
) {
910 * Methods to apply the font.system.whitelist anti-fingerprinting pref,
911 * by filtering the list of installed fonts so that only whitelisted families
913 * There are separate implementations of this for the per-process font list
914 * and for the shared-memory font list.
916 void ApplyWhitelist() MOZ_REQUIRES(mLock
);
917 void ApplyWhitelist(nsTArray
<mozilla::fontlist::Family::InitData
>& aFamilies
);
919 // Create a new gfxFontFamily of the appropriate subclass for the platform,
920 // used when AddWithLegacyFamilyName needs to create a new family.
921 virtual gfxFontFamily
* CreateFontFamily(const nsACString
& aName
,
922 FontVisibility aVisibility
) const = 0;
925 * For the post-startup font info loader task.
926 * Perform platform-specific work to read alternate names (if any) for a
927 * font family, recording them in mAliasTable. Once alternate names have been
928 * loaded for all families, the accumulated records are stored in the shared
929 * font list's mAliases list.
930 * Some platforms (currently Linux/fontconfig) may load alternate names as
931 * part of initially populating the font list with family records, in which
932 * case this method is unused.
934 virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family
* aFamily
,
935 bool aNeedFullnamePostscriptNames
)
936 MOZ_REQUIRES(mLock
) {}
938 typedef nsRefPtrHashtable
<nsCStringHashKey
, gfxFontFamily
> FontFamilyTable
;
939 typedef nsRefPtrHashtable
<nsCStringHashKey
, gfxFontEntry
> FontEntryTable
;
941 // used by memory reporter to accumulate sizes of family names in the table
942 static size_t SizeOfFontFamilyTableExcludingThis(
943 const FontFamilyTable
& aTable
, mozilla::MallocSizeOf aMallocSizeOf
);
944 static size_t SizeOfFontEntryTableExcludingThis(
945 const FontEntryTable
& aTable
, mozilla::MallocSizeOf aMallocSizeOf
);
947 // Platform-specific helper for GetDefaultFont(...).
948 virtual FontFamily
GetDefaultFontForPlatform(nsPresContext
* aPresContext
,
949 const gfxFontStyle
* aStyle
,
950 nsAtom
* aLanguage
= nullptr)
951 MOZ_REQUIRES(mLock
) = 0;
953 // canonical family name ==> family entry (unique, one name per family entry)
954 FontFamilyTable mFontFamilies
MOZ_GUARDED_BY(mLock
);
956 // other family name ==> family entry (not unique, can have multiple names per
957 // family entry, only names *other* than the canonical names are stored here)
958 FontFamilyTable mOtherFamilyNames
MOZ_GUARDED_BY(mLock
);
960 // flag set after InitOtherFamilyNames is called upon first name lookup miss
961 mozilla::Atomic
<bool> mOtherFamilyNamesInitialized
;
963 // The pending InitOtherFamilyNames() task.
964 RefPtr
<mozilla::CancelableRunnable
> mPendingOtherFamilyNameTask
;
966 // flag set after fullname and Postcript name lists are populated
967 mozilla::Atomic
<bool> mFaceNameListsInitialized
;
970 ExtraNames() = default;
972 // fullname ==> font entry (unique, one name per font entry)
973 FontEntryTable mFullnames
{64};
974 // Postscript name ==> font entry (unique, one name per font entry)
975 FontEntryTable mPostscriptNames
{64};
977 // The lock is needed to guard access to the actual name tables, but does not
978 // need to be held to just test whether mExtraNames is non-null as it is set
979 // during initialization before other threads have a chance to see it.
980 mozilla::UniquePtr
<ExtraNames
> mExtraNames
MOZ_PT_GUARDED_BY(mLock
);
982 // face names missed when face name loading takes a long time
983 mozilla::UniquePtr
<nsTHashSet
<nsCString
>> mFaceNamesMissed
984 MOZ_GUARDED_BY(mLock
);
986 // localized family names missed when face name loading takes a long time
987 mozilla::UniquePtr
<nsTHashSet
<nsCString
>> mOtherNamesMissed
988 MOZ_GUARDED_BY(mLock
);
990 typedef mozilla::RangedArray
<mozilla::UniquePtr
<PrefFontList
>,
991 size_t(mozilla::StyleGenericFontFamily::None
),
993 mozilla::StyleGenericFontFamily::MozEmoji
)>
994 PrefFontsForLangGroup
;
995 mozilla::RangedArray
<PrefFontsForLangGroup
, eFontPrefLang_First
,
997 mLangGroupPrefFonts
MOZ_GUARDED_BY(mLock
);
998 mozilla::UniquePtr
<PrefFontList
> mEmojiPrefFont
MOZ_GUARDED_BY(mLock
);
1000 // When system-wide font lookup fails for a character, cache it to skip future
1001 // searches. This is an array of bitsets, one for each FontVisibility level.
1002 mozilla::EnumeratedArray
<FontVisibility
, FontVisibility::Count
,
1004 mCodepointsWithNoFonts
MOZ_GUARDED_BY(mLock
);
1006 // the family to use for U+FFFD fallback, to avoid expensive search every time
1007 // on pages with lots of problems
1008 mozilla::EnumeratedArray
<FontVisibility
, FontVisibility::Count
, FontFamily
>
1009 mReplacementCharFallbackFamily
MOZ_GUARDED_BY(mLock
);
1011 // Sorted array of lowercased family names; use ContainsSorted to test
1012 nsTArray
<nsCString
> mBadUnderlineFamilyNames
;
1014 // character map data shared across families
1015 // contains weak ptrs to cmaps shared by font entry objects
1016 nsTHashtable
<CharMapHashKey
> mSharedCmaps
MOZ_GUARDED_BY(mLock
);
1018 nsTHashtable
<ShmemCharMapHashEntry
> mShmemCharMaps
MOZ_GUARDED_BY(mLock
);
1020 // data used as part of the font cmap loading process
1021 nsTArray
<RefPtr
<gfxFontFamily
>> mFontFamiliesToLoad
;
1022 uint32_t mStartIndex
= 0;
1023 uint32_t mNumFamilies
= 0;
1025 // xxx - info for diagnosing no default font aborts
1026 // see bugs 636957, 1070983, 1189129
1027 uint32_t mFontlistInitCount
= 0; // num times InitFontList called
1029 nsTHashSet
<gfxUserFontSet
*> mUserFontSetList
MOZ_GUARDED_BY(mLock
);
1031 nsLanguageAtomService
* mLangService
= nullptr;
1033 nsTArray
<uint32_t> mCJKPrefLangs
MOZ_GUARDED_BY(mLock
);
1034 nsTArray
<mozilla::StyleGenericFontFamily
> mDefaultGenericsLangGroup
1035 MOZ_GUARDED_BY(mLock
);
1037 nsTArray
<nsCString
> mEnabledFontsList
;
1038 nsTHashSet
<nsCString
> mIconFontsSet
;
1040 mozilla::UniquePtr
<mozilla::fontlist::FontList
> mSharedFontList
;
1042 nsClassHashtable
<nsCStringHashKey
, mozilla::fontlist::AliasData
> mAliasTable
;
1043 nsTHashMap
<nsCStringHashKey
, mozilla::fontlist::LocalFaceRec::InitData
>
1046 nsRefPtrHashtable
<nsPtrHashKey
<mozilla::fontlist::Face
>, gfxFontEntry
>
1047 mFontEntries
MOZ_GUARDED_BY(mLock
);
1049 mozilla::UniquePtr
<FontPrefs
> mFontPrefs
;
1051 RefPtr
<gfxFontEntry
> mDefaultFontEntry
MOZ_GUARDED_BY(mLock
);
1053 RefPtr
<mozilla::CancelableRunnable
> mLoadCmapsRunnable
;
1054 uint32_t mStartedLoadingCmapsFrom
= 0xffffffffu
;
1056 bool mFontFamilyWhitelistActive
= false;
1058 static PRThread
* sInitFontListThread
;
1061 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags
)
1063 #endif /* GFXPLATFORMFONTLIST_H_ */