gfxPlatformFontList.h (43603B)
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/. */ 5 6 #ifndef GFXPLATFORMFONTLIST_H_ 7 #define GFXPLATFORMFONTLIST_H_ 8 9 #include "nsClassHashtable.h" 10 #include "nsTHashMap.h" 11 #include "nsTHashSet.h" 12 #include "nsRefPtrHashtable.h" 13 #include "nsTHashtable.h" 14 15 #include "gfxFontUtils.h" 16 #include "gfxFontInfoLoader.h" 17 #include "gfxFont.h" 18 #include "gfxFontConstants.h" 19 #include "gfxPlatform.h" 20 #include "SharedFontList.h" 21 22 #include "base/process.h" 23 #include "nsIMemoryReporter.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 "mozilla/ipc/SharedMemoryHandle.h" 30 #include "nsLanguageAtomService.h" 31 32 namespace mozilla { 33 namespace fontlist { 34 struct AliasData; 35 } 36 } // namespace mozilla 37 class FontVisibilityProvider; 38 39 class CharMapHashKey : public PLDHashEntryHdr { 40 public: 41 typedef gfxCharacterMap* KeyType; 42 typedef const gfxCharacterMap* KeyTypePointer; 43 44 explicit CharMapHashKey(const gfxCharacterMap* aCharMap) 45 : mCharMap(const_cast<gfxCharacterMap*>(aCharMap)) { 46 MOZ_COUNT_CTOR(CharMapHashKey); 47 } 48 CharMapHashKey(const CharMapHashKey& toCopy) : mCharMap(toCopy.mCharMap) { 49 MOZ_COUNT_CTOR(CharMapHashKey); 50 } 51 MOZ_COUNTED_DTOR(CharMapHashKey) 52 53 gfxCharacterMap* GetKey() const { return mCharMap.get(); } 54 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; 61 } 62 return mCharMap->Equals(aCharMap); 63 } 64 65 static const gfxCharacterMap* KeyToPointer(gfxCharacterMap* aCharMap) { 66 return aCharMap; 67 } 68 static PLDHashNumber HashKey(const gfxCharacterMap* aCharMap) { 69 return aCharMap->mHash; 70 } 71 72 enum { ALLOW_MEMMOVE = true }; 73 74 protected: 75 friend class gfxPlatformFontList; 76 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; 82 }; 83 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. 88 */ 89 class ShmemCharMapHashEntry final : public PLDHashEntryHdr { 90 public: 91 typedef const gfxSparseBitSet* KeyType; 92 typedef const gfxSparseBitSet* KeyTypePointer; 93 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. 98 */ 99 explicit ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap); 100 101 ShmemCharMapHashEntry(ShmemCharMapHashEntry&&) = default; 102 ShmemCharMapHashEntry& operator=(ShmemCharMapHashEntry&&) = default; 103 104 /** 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. 108 */ 109 mozilla::fontlist::Pointer GetCharMap() const { return mCharMap; } 110 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; 117 } 118 119 return mCharMap.ToPtr<const SharedBitSet>(mList)->Equals(aCharMap); 120 } 121 122 static KeyTypePointer KeyToPointer(KeyType aCharMap) { return aCharMap; } 123 static PLDHashNumber HashKey(KeyType aCharMap) { 124 return aCharMap->GetChecksum(); 125 } 126 127 enum { ALLOW_MEMMOVE = false }; // because of the Pointer member 128 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; 136 }; 137 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. 144 145 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on 146 // all platforms. 147 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) 157 }; 158 159 class gfxUserFontSet; 160 class LoadCmapsRunnable; 161 162 class gfxPlatformFontList : public gfxFontInfoLoader { 163 friend class InitOtherFamilyNamesRunnable; 164 165 public: 166 typedef mozilla::StretchRange StretchRange; 167 typedef mozilla::SlantStyleRange SlantStyleRange; 168 typedef mozilla::WeightRange WeightRange; 169 typedef mozilla::intl::Script Script; 170 171 using AutoLock = mozilla::RecursiveMutexAutoLock; 172 using AutoUnlock = mozilla::RecursiveMutexAutoUnlock; 173 174 // Class used to hold cached copies of the font-name prefs, so that they can 175 // be accessed from non-main-thread callers who are not allowed to touch the 176 // Preferences service. 177 class FontPrefs final { 178 public: 179 using HashMap = nsTHashMap<nsCStringHashKey, nsCString>; 180 181 FontPrefs(); 182 ~FontPrefs() = default; 183 184 FontPrefs(const FontPrefs& aOther) = delete; 185 FontPrefs& operator=(const FontPrefs& aOther) = delete; 186 187 // Lookup the font.name.<foo> or font.name-list.<foo> pref for a given 188 // generic+langgroup pair. 189 bool LookupName(const nsACString& aPref, nsACString& aValue) const; 190 bool LookupNameList(const nsACString& aPref, nsACString& aValue) const; 191 192 // Does the font.name-list.emoji pref have a user-set value? 193 bool EmojiHasUserValue() const { return mEmojiHasUserValue; } 194 195 // Expose iterators over all the defined prefs of each type. 196 HashMap::ConstIterator NameIter() const { return mFontName.ConstIter(); } 197 HashMap::ConstIterator NameListIter() const { 198 return mFontNameList.ConstIter(); 199 } 200 201 const nsTArray<eFontPrefLang>& CJKPrefLangs() const { 202 return mCJKPrefLangs; 203 } 204 205 private: 206 static constexpr char kNamePrefix[] = "font.name."; 207 static constexpr char kNameListPrefix[] = "font.name-list."; 208 209 void Init(); 210 211 HashMap mFontName; 212 HashMap mFontNameList; 213 nsTArray<eFontPrefLang> mCJKPrefLangs; 214 bool mEmojiHasUserValue = false; 215 }; 216 217 // For font family lists loaded from user preferences (prefs such as 218 // font.name-list.<generic>.<langGroup>) that map CSS generics to 219 // platform-specific font families. 220 typedef nsTArray<FontFamily> PrefFontList; 221 222 // Return the global font-list singleton, or NULL if aMustInitialize is false 223 // and it has not yet been fully initialized. 224 static gfxPlatformFontList* PlatformFontList(bool aMustInitialize = true) { 225 if (!aMustInitialize && 226 !(sPlatformFontList && sPlatformFontList->IsInitialized())) { 227 return nullptr; 228 } 229 // If there is a font-list initialization thread, we need to let it run 230 // to completion before the font list can be used for anything else. 231 if (sInitFontListThread) { 232 // If we're currently on the initialization thread, just continue; 233 // otherwise wait for it to finish. 234 if (IsInitFontListThread()) { 235 return sPlatformFontList; 236 } 237 PR_JoinThread(sInitFontListThread); 238 sInitFontListThread = nullptr; 239 // If font-list initialization failed, the thread will have cleared 240 // the static sPlatformFontList pointer; we cannot proceed without any 241 // usable fonts. 242 if (!sPlatformFontList) { 243 MOZ_CRASH("Could not initialize gfxPlatformFontList"); 244 } 245 } 246 if (!sPlatformFontList->IsInitialized()) { 247 if (!sPlatformFontList->InitFontList()) { 248 MOZ_CRASH("Could not initialize gfxPlatformFontList"); 249 } 250 } 251 return sPlatformFontList; 252 } 253 254 FontVisibility GetFontVisibility(nsCString& aFont, bool& aFound); 255 bool GetMissingFonts(nsTArray<nsCString>& aMissingFonts); 256 void GetMissingFonts(nsCString& aMissingFonts); 257 258 static bool Initialize(gfxPlatformFontList* aList); 259 260 static void Shutdown() { 261 // Ensure any font-list initialization thread is finished before we delete 262 // the platform fontlist singleton, which that thread may try to use. 263 if (sInitFontListThread && !IsInitFontListThread()) { 264 PR_JoinThread(sInitFontListThread); 265 sInitFontListThread = nullptr; 266 } 267 delete sPlatformFontList; 268 sPlatformFontList = nullptr; 269 } 270 271 bool IsInitialized() const { return mFontlistInitCount; } 272 273 virtual ~gfxPlatformFontList(); 274 275 // Initialize font lists; return true on success, false if something fails. 276 bool InitFontList(); 277 278 /** 279 * Gathers (from a platform's underlying font system) the information needed 280 * to initialize a fontlist::Family with its Face members. 281 */ 282 virtual void GetFacesInitDataForFamily( 283 const mozilla::fontlist::Family* aFamily, 284 nsTArray<mozilla::fontlist::Face::InitData>& aFaces, 285 bool aLoadCmaps) const {} 286 287 virtual void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily, 288 nsTArray<nsString>& aListOfFonts); 289 290 // Pass false to notify content that the shared font list has been modified 291 // but not completely invalidated. 292 void UpdateFontList(bool aFullRebuild = true); 293 294 void ClearLangGroupPrefFonts() { 295 AutoLock lock(mLock); 296 ClearLangGroupPrefFontsLocked(); 297 } 298 virtual void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock); 299 300 void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray); 301 302 already_AddRefed<gfxFont> SystemFindFontForChar( 303 FontVisibilityProvider* aFontVisibilityProvider, uint32_t aCh, 304 uint32_t aNextCh, Script aRunScript, FontPresentation aPresentation, 305 const gfxFontStyle* aStyle, FontVisibility* aVisibility); 306 307 // Flags to control optional behaviors in FindAndAddFamilies. The sense 308 // of the bit flags have been chosen such that the default parameter of 309 // FindFamiliesFlags(0) in FindFamily will give the most commonly-desired 310 // behavior, and only a few callsites need to explicitly pass other values. 311 enum class FindFamiliesFlags { 312 // If set, "other" (e.g. localized) family names should be loaded 313 // immediately; if clear, InitOtherFamilyNames is allowed to defer 314 // loading to avoid blocking. 315 eForceOtherFamilyNamesLoading = 1 << 0, 316 317 // If set, FindAndAddFamilies should not check for legacy "styled 318 // family" names to add to the font list. This is used to avoid 319 // a recursive search when using FindFamily to find a potential base 320 // family name for a styled variant. 321 eNoSearchForLegacyFamilyNames = 1 << 1, 322 323 // If set, FindAndAddFamilies will not add a missing entry to 324 // mOtherNamesMissed 325 eNoAddToNamesMissedWhenSearching = 1 << 2, 326 327 // If set, the family name was quoted and so must not be treated as a CSS 328 // generic. 329 eQuotedFamilyName = 1 << 3, 330 331 // If set, "hidden" font families (like ".SF NS Text" on macOS) are 332 // searched in addition to standard user-visible families. 333 eSearchHiddenFamilies = 1 << 4, 334 }; 335 336 // Find family(ies) matching aFamily and append to the aOutput array 337 // (there may be multiple results in the case of fontconfig aliases, etc). 338 // Return true if any match was found and appended, false if none. 339 bool FindAndAddFamilies(FontVisibilityProvider* aFontVisibilityProvider, 340 mozilla::StyleGenericFontFamily aGeneric, 341 const nsACString& aFamily, 342 nsTArray<FamilyAndGeneric>* aOutput, 343 FindFamiliesFlags aFlags, 344 gfxFontStyle* aStyle = nullptr, 345 nsAtom* aLanguage = nullptr, 346 gfxFloat aDevToCssSize = 1.0); 347 348 virtual bool FindAndAddFamiliesLocked( 349 FontVisibilityProvider* aFontVisibilityProvider, 350 mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, 351 nsTArray<FamilyAndGeneric>* aOutput, FindFamiliesFlags aFlags, 352 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, 353 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock); 354 355 gfxFontEntry* FindFontForFamily( 356 FontVisibilityProvider* aFontVisibilityProvider, 357 const nsACString& aFamily, const gfxFontStyle* aStyle); 358 359 mozilla::fontlist::FontList* SharedFontList() const { 360 return mSharedFontList.get(); 361 } 362 363 // Create a handle for a single shmem block (identified by index) ready to 364 // be shared to the given processId. 365 void ShareFontListShmBlockToProcess( 366 uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid, 367 mozilla::ipc::ReadOnlySharedMemoryHandle* aOut); 368 369 // Populate the array aBlocks with the complete list of shmem handles ready 370 // to be shared to the given processId. 371 void ShareFontListToProcess( 372 nsTArray<mozilla::ipc::ReadOnlySharedMemoryHandle>* aBlocks, 373 base::ProcessId aPid); 374 375 void ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex, 376 mozilla::ipc::ReadOnlySharedMemoryHandle aHandle); 377 378 mozilla::ipc::ReadOnlySharedMemoryHandle ShareShmBlockToProcess( 379 uint32_t aIndex, base::ProcessId aPid); 380 381 void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias, 382 uint32_t aFaceIndex, const gfxSparseBitSet& aMap); 383 384 void SetupFamilyCharMap(uint32_t aGeneration, uint32_t aIndex, bool aAlias); 385 386 // Start the async cmap loading process, if not already under way, from the 387 // given family index. (For use in any process that needs font lookups.) 388 void StartCmapLoadingFromFamily(uint32_t aStartIndex); 389 390 // [Parent] Handle request from content process to start cmap loading. 391 void StartCmapLoading(uint32_t aGeneration, uint32_t aStartIndex); 392 393 void CancelLoadCmapsTask(); 394 395 // Populate aFamily with face records, and if aLoadCmaps is true, also load 396 // their character maps (rather than leaving this to be done lazily). 397 // Note that even when aFamily->IsInitialized() is true, it can make sense 398 // to call InitializeFamily again if passing aLoadCmaps=true, in order to 399 // ensure cmaps are loaded. 400 [[nodiscard]] bool InitializeFamily(mozilla::fontlist::Family* aFamily, 401 bool aLoadCmaps = false); 402 void InitializeFamily(uint32_t aGeneration, uint32_t aFamilyIndex, 403 bool aLoadCmaps); 404 405 // name lookup table methods 406 407 void AddOtherFamilyNames(gfxFontFamily* aFamilyEntry, 408 const nsTArray<nsCString>& aOtherFamilyNames); 409 410 void AddFullname(gfxFontEntry* aFontEntry, const nsCString& aFullname) { 411 AutoLock lock(mLock); 412 AddFullnameLocked(aFontEntry, aFullname); 413 } 414 void AddFullnameLocked(gfxFontEntry* aFontEntry, const nsCString& aFullname) 415 MOZ_REQUIRES(mLock); 416 417 void AddPostscriptName(gfxFontEntry* aFontEntry, 418 const nsCString& aPostscriptName) { 419 AutoLock lock(mLock); 420 AddPostscriptNameLocked(aFontEntry, aPostscriptName); 421 } 422 void AddPostscriptNameLocked(gfxFontEntry* aFontEntry, 423 const nsCString& aPostscriptName) 424 MOZ_REQUIRES(mLock); 425 426 bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; } 427 428 /** 429 * Read PSName and FullName of the given face, for src:local lookup, 430 * returning true if actually implemented and succeeded. 431 */ 432 virtual bool ReadFaceNames(const mozilla::fontlist::Family* aFamily, 433 const mozilla::fontlist::Face* aFace, 434 nsCString& aPSName, nsCString& aFullName) { 435 return false; 436 } 437 438 // initialize localized family names 439 bool InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading); 440 bool InitOtherFamilyNames(uint32_t aGeneration, bool aDefer); 441 442 // pure virtual functions, to be provided by concrete subclasses 443 444 // get the system default font family 445 FontFamily GetDefaultFont(FontVisibilityProvider* aFontVisibilityProvider, 446 const gfxFontStyle* aStyle); 447 FontFamily GetDefaultFontLocked( 448 FontVisibilityProvider* aFontVisibilityProvider, 449 const gfxFontStyle* aStyle) MOZ_REQUIRES(mLock); 450 451 // get the "ultimate" default font, for use if the font list is otherwise 452 // unusable (e.g. in the middle of being updated) 453 gfxFontEntry* GetDefaultFontEntry() { 454 AutoLock lock(mLock); 455 return mDefaultFontEntry.get(); 456 } 457 458 /** 459 * Look up a font by name on the host platform. 460 * 461 * Note that the style attributes (weight, stretch, style) are NOT used in 462 * selecting the platform font, which is looked up by name only; these are 463 * values to be recorded in the new font entry. 464 */ 465 virtual gfxFontEntry* LookupLocalFont( 466 FontVisibilityProvider* aFontVisibilityProvider, 467 const nsACString& aFontName, WeightRange aWeightForEntry, 468 StretchRange aStretchForEntry, SlantStyleRange aStyleForEntry) = 0; 469 470 /** 471 * Create a new platform font from downloaded data (@font-face). 472 * 473 * Note that the style attributes (weight, stretch, style) are NOT related 474 * (necessarily) to any values within the font resource itself; these are 475 * values to be recorded in the new font entry and used for face selection, 476 * in place of whatever inherent style attributes the resource may have. 477 * 478 * This method takes ownership of the data block passed in as aFontData, 479 * and must ensure it is free()'d when no longer required. 480 */ 481 virtual gfxFontEntry* MakePlatformFont(const nsACString& aFontName, 482 WeightRange aWeightForEntry, 483 StretchRange aStretchForEntry, 484 SlantStyleRange aStyleForEntry, 485 const uint8_t* aFontData, 486 uint32_t aLength) = 0; 487 488 // get the standard family name on the platform for a given font name 489 // (platforms may override, eg Mac) 490 virtual bool GetStandardFamilyName(const nsCString& aFontName, 491 nsACString& aFamilyName); 492 493 // Get the localized family name for a given font family. 494 bool GetLocalizedFamilyName(const FontFamily& aFamily, 495 nsACString& aFamilyName); 496 497 // get the default font name which is available on the system from 498 // font.name-list.*. if there are no available fonts in the pref, 499 // returns an empty FamilyAndGeneric record. 500 FamilyAndGeneric GetDefaultFontFamily(const nsACString& aLangGroup, 501 const nsACString& aGenericFamily); 502 503 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 504 FontListSizes* aSizes) const; 505 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 506 FontListSizes* aSizes) const; 507 508 mozilla::fontlist::Pointer GetShmemCharMap(const gfxSparseBitSet* aCmap) { 509 AutoLock lock(mLock); 510 return GetShmemCharMapLocked(aCmap); 511 } 512 mozilla::fontlist::Pointer GetShmemCharMapLocked(const gfxSparseBitSet* aCmap) 513 MOZ_REQUIRES(mLock); 514 515 // Search for existing cmap that matches the input; return the input if no 516 // match is found. 517 already_AddRefed<gfxCharacterMap> FindCharMap(gfxCharacterMap* aCmap); 518 519 // Remove the cmap from the shared cmap set if it holds the only remaining 520 // reference to the object. 521 void MaybeRemoveCmap(gfxCharacterMap* aCharMap); 522 523 // Keep track of userfont sets to notify when global fontlist changes occur. 524 void AddUserFontSet(gfxUserFontSet* aUserFontSet) { 525 AutoLock lock(mLock); 526 mUserFontSetList.Insert(aUserFontSet); 527 } 528 529 void RemoveUserFontSet(gfxUserFontSet* aUserFontSet) { 530 AutoLock lock(mLock); 531 mUserFontSetList.Remove(aUserFontSet); 532 } 533 534 static const gfxFontEntry::ScriptRange sComplexScriptRanges[]; 535 536 void GetFontlistInitInfo(uint32_t& aNumInits, uint32_t& aLoaderState) { 537 aNumInits = mFontlistInitCount; 538 aLoaderState = (uint32_t)mState; 539 } 540 541 virtual void AddGenericFonts(FontVisibilityProvider* aFontVisibilityProvider, 542 mozilla::StyleGenericFontFamily aGenericType, 543 nsAtom* aLanguage, 544 nsTArray<FamilyAndGeneric>& aFamilyList); 545 546 /** 547 * Given a Face from the shared font list, return a gfxFontEntry usable 548 * by the current process. This returns a cached entry if available, 549 * otherwise it calls the (platform-specific) CreateFontEntry method to 550 * make one, and adds it to the cache. 551 */ 552 gfxFontEntry* GetOrCreateFontEntry(mozilla::fontlist::Face* aFace, 553 const mozilla::fontlist::Family* aFamily) { 554 AutoLock lock(mLock); 555 return GetOrCreateFontEntryLocked(aFace, aFamily); 556 } 557 gfxFontEntry* GetOrCreateFontEntryLocked( 558 mozilla::fontlist::Face* aFace, const mozilla::fontlist::Family* aFamily) 559 MOZ_REQUIRES(mLock); 560 561 const FontPrefs* GetFontPrefs() const MOZ_REQUIRES(mLock) { 562 return mFontPrefs.get(); 563 } 564 565 bool EmojiPrefHasUserValue() const { 566 AutoLock lock(mLock); 567 return mFontPrefs->EmojiHasUserValue(); 568 } 569 570 PrefFontList* GetPrefFontsLangGroup( 571 FontVisibilityProvider* aFontVisibilityProvider, 572 mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang) { 573 AutoLock lock(mLock); 574 return GetPrefFontsLangGroupLocked(aFontVisibilityProvider, aGenericType, 575 aPrefLang); 576 } 577 PrefFontList* GetPrefFontsLangGroupLocked( 578 FontVisibilityProvider* aFontVisibilityProvider, 579 mozilla::StyleGenericFontFamily aGenericType, eFontPrefLang aPrefLang) 580 MOZ_REQUIRES(mLock); 581 582 // in some situations, need to make decisions about ambiguous characters, may 583 // need to look at multiple pref langs 584 void GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t& aLen, 585 eFontPrefLang aCharLang, eFontPrefLang aPageLang); 586 587 // convert a lang group to enum constant (i.e. "zh-TW" ==> 588 // eFontPrefLang_ChineseTW) 589 static eFontPrefLang GetFontPrefLangFor(const char* aLang); 590 591 // convert a lang group atom to enum constant 592 static eFontPrefLang GetFontPrefLangFor(nsAtom* aLang); 593 594 // convert an enum constant to a lang group atom 595 static nsAtom* GetLangGroupForPrefLang(eFontPrefLang aLang); 596 597 // convert a enum constant to lang group string (i.e. eFontPrefLang_ChineseTW 598 // ==> "zh-TW") 599 static const char* GetPrefLangName(eFontPrefLang aLang); 600 601 // map a char code to a font language for Preferences 602 static eFontPrefLang GetFontPrefLangFor(uint32_t aCh); 603 604 // returns true if a pref lang is CJK 605 static bool IsLangCJK(eFontPrefLang aLang); 606 607 // helper method to add a pref lang to an array, if not already in array 608 static void AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, 609 eFontPrefLang aAddLang); 610 611 // default serif/sans-serif choice based on font.default.xxx prefs 612 mozilla::StyleGenericFontFamily GetDefaultGeneric(eFontPrefLang aLang); 613 614 // Returns true if the font family whitelist is not empty. In this case we 615 // ignore the "CSS visibility level"; only the given fonts are present in 616 // the browser's font list. 617 bool IsFontFamilyWhitelistActive() const { 618 return mFontFamilyWhitelistActive; 619 }; 620 621 static void FontWhitelistPrefChanged(const char* aPref, void* aClosure); 622 623 bool AddWithLegacyFamilyName(const nsACString& aLegacyName, 624 gfxFontEntry* aFontEntry, 625 FontVisibility aVisibility); 626 627 static const char* GetGenericName( 628 mozilla::StyleGenericFontFamily aGenericType); 629 630 bool SkipFontFallbackForChar(FontVisibility aVisibility, uint32_t aCh) const { 631 AutoLock lock(mLock); 632 return mCodepointsWithNoFonts[aVisibility].test(aCh); 633 } 634 635 // Return whether the given font-family record should be visible to CSS, 636 // in a context with the given FontVisibility setting. 637 bool IsVisibleToCSS(const gfxFontFamily& aFamily, 638 FontVisibility aVisibility) const; 639 bool IsVisibleToCSS(const mozilla::fontlist::Family& aFamily, 640 FontVisibility aVisibility) const; 641 642 // (Re-)initialize the set of codepoints that we know cannot be rendered. 643 void InitializeCodepointsWithNoFonts() MOZ_REQUIRES(mLock); 644 645 // If using the shared font list, returns a generation count that is 646 // incremented if/when the platform list is reinitialized (e.g. because 647 // fonts are installed/removed while the browser is running), such that 648 // existing references to shared font family or face objects and character 649 // maps will no longer be valid. 650 // (The legacy (non-shared) list just returns 0 here.) 651 uint32_t GetGeneration() const; 652 653 // Sometimes we need to know if we're on the InitFontList startup thread. 654 static bool IsInitFontListThread() { 655 return PR_GetCurrentThread() == sInitFontListThread; 656 } 657 658 bool IsKnownIconFontFamily(const nsAtom* aFamilyName) const; 659 void LoadIconFontOverrideList(); 660 661 void Lock() MOZ_CAPABILITY_ACQUIRE(mLock) { mLock.Lock(); } 662 void Unlock() MOZ_CAPABILITY_RELEASE(mLock) { mLock.Unlock(); } 663 664 // This is only public because some external callers want to be able to 665 // assert about the locked status. 666 mutable mozilla::RecursiveMutex mLock; 667 668 protected: 669 virtual nsTArray<std::pair<const char**, uint32_t>> 670 GetFilteredPlatformFontLists() = 0; 671 672 friend class mozilla::fontlist::FontList; 673 friend class InitOtherFamilyNamesForStylo; 674 675 template <size_t N> 676 static bool FamilyInList(const nsACString& aName, const char* (&aList)[N]) { 677 return FamilyInList(aName, aList, N); 678 } 679 static bool FamilyInList(const nsACString& aName, const char* aList[], 680 size_t aCount); 681 682 // Check list is correctly sorted (in debug build only; no-op on release). 683 template <size_t N> 684 static void CheckFamilyList(const char* (&aList)[N]) { 685 CheckFamilyList(aList, N); 686 } 687 static void CheckFamilyList(const char* aList[], size_t aCount); 688 689 class InitOtherFamilyNamesRunnable : public mozilla::CancelableRunnable { 690 public: 691 InitOtherFamilyNamesRunnable() 692 : CancelableRunnable( 693 "gfxPlatformFontList::InitOtherFamilyNamesRunnable"), 694 mIsCanceled(false) {} 695 696 NS_IMETHOD Run() override { 697 if (mIsCanceled) { 698 return NS_OK; 699 } 700 701 gfxPlatformFontList* fontList = gfxPlatformFontList::PlatformFontList(); 702 if (!fontList) { 703 return NS_OK; 704 } 705 706 fontList->InitOtherFamilyNamesInternal(true); 707 708 return NS_OK; 709 } 710 711 nsresult Cancel() override { 712 mIsCanceled = true; 713 714 return NS_OK; 715 } 716 717 private: 718 bool mIsCanceled; 719 }; 720 721 class MemoryReporter final : public nsIMemoryReporter { 722 ~MemoryReporter() = default; 723 724 public: 725 NS_DECL_ISUPPORTS 726 NS_DECL_NSIMEMORYREPORTER 727 }; 728 729 class PrefName final : public nsAutoCString { 730 void Init(const nsACString& aGeneric, const nsACString& aLangGroup) { 731 Assign(aGeneric); 732 if (!aLangGroup.IsEmpty()) { 733 Append('.'); 734 Append(aLangGroup); 735 } 736 } 737 738 public: 739 PrefName(const nsACString& aGeneric, const nsACString& aLangGroup) { 740 Init(aGeneric, aLangGroup); 741 } 742 743 PrefName(const char* aGeneric, const char* aLangGroup) { 744 Init(nsDependentCString(aGeneric), nsDependentCString(aLangGroup)); 745 } 746 747 PrefName(const char* aGeneric, nsAtom* aLangGroup) { 748 if (aLangGroup) { 749 Init(nsDependentCString(aGeneric), nsAtomCString(aLangGroup)); 750 } else { 751 Init(nsDependentCString(aGeneric), nsAutoCString()); 752 } 753 } 754 }; 755 756 explicit gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); 757 758 static gfxPlatformFontList* sPlatformFontList; 759 760 /** 761 * Convenience method to return the first matching family (if any) as found 762 * by FindAndAddFamilies(). The family will be initialized (synchronously) 763 * if this has not already been done, so the returned pointer, if non-null, 764 * is ready for use. 765 */ 766 mozilla::fontlist::Family* FindSharedFamily( 767 FontVisibilityProvider* aFontVisibilityProvider, 768 const nsACString& aFamily, 769 FindFamiliesFlags aFlags = FindFamiliesFlags(0), 770 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, 771 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock); 772 773 gfxFontFamily* FindUnsharedFamily( 774 FontVisibilityProvider* aFontVisibilityProvider, 775 const nsACString& aFamily, 776 FindFamiliesFlags aFlags = FindFamiliesFlags(0), 777 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, 778 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) { 779 if (SharedFontList()) { 780 return nullptr; 781 } 782 AutoTArray<FamilyAndGeneric, 1> families; 783 if (FindAndAddFamiliesLocked( 784 aFontVisibilityProvider, mozilla::StyleGenericFontFamily::None, 785 aFamily, &families, aFlags, aStyle, aLanguage, aDevToCssSize)) { 786 return families[0].mFamily.mUnshared; 787 } 788 return nullptr; 789 } 790 791 FontFamily FindFamily(FontVisibilityProvider* aFontVisibilityProvider, 792 const nsACString& aFamily, 793 FindFamiliesFlags aFlags = FindFamiliesFlags(0), 794 gfxFontStyle* aStyle = nullptr, 795 nsAtom* aLanguage = nullptr, 796 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) { 797 if (SharedFontList()) { 798 return FontFamily(FindSharedFamily(aFontVisibilityProvider, aFamily, 799 aFlags, aStyle, aLanguage, 800 aDevToCssSize)); 801 } 802 return FontFamily(FindUnsharedFamily(aFontVisibilityProvider, aFamily, 803 aFlags, aStyle, aLanguage, 804 aDevToCssSize)); 805 } 806 807 // Lookup family name in global family list without substitutions or 808 // localized family name lookup. Used for common font fallback families. 809 gfxFontFamily* FindFamilyByCanonicalName(const nsACString& aFamily) 810 MOZ_REQUIRES(mLock) { 811 nsAutoCString key; 812 gfxFontFamily* familyEntry; 813 GenerateFontListKey(aFamily, key); 814 if ((familyEntry = mFontFamilies.GetWeak(key))) { 815 return CheckFamily(familyEntry); 816 } 817 return nullptr; 818 } 819 820 // returns default font for a given character, null otherwise 821 already_AddRefed<gfxFont> CommonFontFallback( 822 FontVisibilityProvider* aFontVisibilityProvider, uint32_t aCh, 823 uint32_t aNextCh, Script aRunScript, FontPresentation aPresentation, 824 const gfxFontStyle* aMatchStyle, FontFamily& aMatchedFamily) 825 MOZ_REQUIRES(mLock); 826 827 // Search fonts system-wide for a given character, null if not found. 828 already_AddRefed<gfxFont> GlobalFontFallback( 829 FontVisibilityProvider* aFontVisibilityProvider, uint32_t aCh, 830 uint32_t aNextCh, Script aRunScript, FontPresentation aPresentation, 831 const gfxFontStyle* aMatchStyle, uint32_t& aCmapCount, 832 FontFamily& aMatchedFamily) MOZ_REQUIRES(mLock); 833 834 // Platform-specific implementation of global font fallback, if any; 835 // this may return nullptr in which case the default cmap-based fallback 836 // will be performed. 837 virtual gfxFontEntry* PlatformGlobalFontFallback( 838 FontVisibilityProvider* aFontVisibilityProvider, const uint32_t aCh, 839 Script aRunScript, const gfxFontStyle* aMatchStyle, 840 FontFamily& aMatchedFamily) { 841 return nullptr; 842 } 843 844 // whether system-based font fallback is used or not 845 // if system fallback is used, no need to load all cmaps 846 virtual bool UsesSystemFallback() { return false; } 847 848 void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t& aLen, 849 eFontPrefLang aCharLang, eFontPrefLang aPageLang) 850 MOZ_REQUIRES(mLock); 851 852 // verifies that a family contains a non-zero font count 853 gfxFontFamily* CheckFamily(gfxFontFamily* aFamily) MOZ_REQUIRES(mLock); 854 855 // initialize localized family names 856 void InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading); 857 void CancelInitOtherFamilyNamesTask(); 858 859 void AddToMissedNames(const nsCString& aKey) MOZ_REQUIRES(mLock); 860 861 // search through font families, looking for a given name, initializing 862 // facename lists along the way. first checks all families with names 863 // close to face name, then searchs all families if not found. 864 gfxFontEntry* SearchFamiliesForFaceName(const nsACString& aFaceName) 865 MOZ_REQUIRES(mLock); 866 867 // helper method for finding fullname/postscript names in facename lists 868 gfxFontEntry* FindFaceName(const nsACString& aFaceName) MOZ_REQUIRES(mLock); 869 870 // look up a font by name, for cases where platform font list 871 // maintains explicit mappings of fullname/psname ==> font 872 virtual gfxFontEntry* LookupInFaceNameLists(const nsACString& aFaceName) 873 MOZ_REQUIRES(mLock); 874 875 gfxFontEntry* LookupInSharedFaceNameList( 876 FontVisibilityProvider* aFontVisibilityProvider, 877 const nsACString& aFaceName, WeightRange aWeightForEntry, 878 StretchRange aStretchForEntry, SlantStyleRange aStyleForEntry) 879 MOZ_REQUIRES(mLock); 880 881 // Add an entry for aName to the local names table, but only if it is not 882 // already present, or aName and aData.mFamilyName look like a better match 883 // than the existing entry. 884 void MaybeAddToLocalNameTable( 885 const nsACString& aName, 886 const mozilla::fontlist::LocalFaceRec::InitData& aData) 887 MOZ_REQUIRES(mLock); 888 889 // load the bad underline blocklist from pref. 890 void LoadBadUnderlineList(); 891 892 // This version of the function will not modify aKeyName 893 void GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult); 894 // This version of the function WILL modify aKeyName 895 void GenerateFontListKey(nsACString& aKeyName); 896 897 virtual void GetFontFamilyNames(nsTArray<nsCString>& aFontFamilyNames) 898 MOZ_REQUIRES(mLock); 899 900 // helper function to map lang to lang group 901 nsAtom* GetLangGroup(nsAtom* aLanguage); 902 903 // gfxFontInfoLoader overrides, used to load in font cmaps 904 void InitLoader() MOZ_REQUIRES(mLock) override; 905 bool LoadFontInfo() override; 906 void CleanupLoader() override; 907 908 void ForceGlobalReflow(gfxPlatform::GlobalReflowFlags aFlags); 909 910 void ForceGlobalReflowLocked(gfxPlatform::GlobalReflowFlags aFlags) 911 MOZ_REQUIRES(mLock); 912 913 // read the loader initialization prefs, and start it 914 void GetPrefsAndStartLoader(); 915 916 // If aForgetLocalFaces is true, all gfxFontEntries for src:local fonts must 917 // be discarded (not potentially reused to satisfy the rebuilt rules), 918 // because they may no longer be valid. 919 void RebuildLocalFonts(bool aForgetLocalFaces = false) MOZ_REQUIRES(mLock); 920 921 void ResolveGenericFontNames(FontVisibilityProvider* aFontVisibilityProvider, 922 mozilla::StyleGenericFontFamily aGenericType, 923 eFontPrefLang aPrefLang, 924 PrefFontList* aGenericFamilies) 925 MOZ_REQUIRES(mLock); 926 927 void ResolveEmojiFontNames(FontVisibilityProvider* aFontVisibilityProvider, 928 PrefFontList* aGenericFamilies) 929 MOZ_REQUIRES(mLock); 930 931 void GetFontFamiliesFromGenericFamilies( 932 FontVisibilityProvider* aFontVisibilityProvider, 933 mozilla::StyleGenericFontFamily aGenericType, 934 nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup, 935 PrefFontList* aFontFamilies) MOZ_REQUIRES(mLock); 936 937 virtual nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) = 0; 938 virtual void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) {} 939 940 virtual gfxFontEntry* CreateFontEntry( 941 mozilla::fontlist::Face* aFace, 942 const mozilla::fontlist::Family* aFamily) { 943 return nullptr; 944 } 945 946 /** 947 * Methods to apply the font.system.whitelist anti-fingerprinting pref, 948 * by filtering the list of installed fonts so that only whitelisted families 949 * are exposed. 950 * There are separate implementations of this for the per-process font list 951 * and for the shared-memory font list. 952 */ 953 void ApplyWhitelist() MOZ_REQUIRES(mLock); 954 void ApplyWhitelist(nsTArray<mozilla::fontlist::Family::InitData>& aFamilies); 955 956 // Create a new gfxFontFamily of the appropriate subclass for the platform, 957 // used when AddWithLegacyFamilyName needs to create a new family. 958 virtual gfxFontFamily* CreateFontFamily(const nsACString& aName, 959 FontVisibility aVisibility) const = 0; 960 961 /** 962 * For the post-startup font info loader task. 963 * Perform platform-specific work to read alternate names (if any) for a 964 * font family, recording them in mAliasTable. Once alternate names have been 965 * loaded for all families, the accumulated records are stored in the shared 966 * font list's mAliases list. 967 * Some platforms (currently Linux/fontconfig) may load alternate names as 968 * part of initially populating the font list with family records, in which 969 * case this method is unused. 970 */ 971 virtual void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily, 972 bool aNeedFullnamePostscriptNames) 973 MOZ_REQUIRES(mLock) {} 974 975 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontFamily> FontFamilyTable; 976 typedef nsRefPtrHashtable<nsCStringHashKey, gfxFontEntry> FontEntryTable; 977 978 // used by memory reporter to accumulate sizes of family names in the table 979 static size_t SizeOfFontFamilyTableExcludingThis( 980 const FontFamilyTable& aTable, mozilla::MallocSizeOf aMallocSizeOf); 981 static size_t SizeOfFontEntryTableExcludingThis( 982 const FontEntryTable& aTable, mozilla::MallocSizeOf aMallocSizeOf); 983 984 // Platform-specific helper for GetDefaultFont(...). 985 virtual FontFamily GetDefaultFontForPlatform( 986 FontVisibilityProvider* aFontVisibilityProvider, 987 const gfxFontStyle* aStyle, nsAtom* aLanguage = nullptr) 988 MOZ_REQUIRES(mLock) = 0; 989 990 // canonical family name ==> family entry (unique, one name per family entry) 991 FontFamilyTable mFontFamilies MOZ_GUARDED_BY(mLock); 992 993 // other family name ==> family entry (not unique, can have multiple names per 994 // family entry, only names *other* than the canonical names are stored here) 995 FontFamilyTable mOtherFamilyNames MOZ_GUARDED_BY(mLock); 996 997 // flag set after InitOtherFamilyNames is called upon first name lookup miss 998 mozilla::Atomic<bool> mOtherFamilyNamesInitialized; 999 1000 // The pending InitOtherFamilyNames() task. 1001 RefPtr<mozilla::CancelableRunnable> mPendingOtherFamilyNameTask; 1002 1003 // flag set after fullname and Postcript name lists are populated 1004 mozilla::Atomic<bool> mFaceNameListsInitialized; 1005 1006 struct ExtraNames { 1007 ExtraNames() = default; 1008 1009 // fullname ==> font entry (unique, one name per font entry) 1010 FontEntryTable mFullnames{64}; 1011 // Postscript name ==> font entry (unique, one name per font entry) 1012 FontEntryTable mPostscriptNames{64}; 1013 }; 1014 // The lock is needed to guard access to the actual name tables, but does not 1015 // need to be held to just test whether mExtraNames is non-null as it is set 1016 // during initialization before other threads have a chance to see it. 1017 mozilla::UniquePtr<ExtraNames> mExtraNames MOZ_PT_GUARDED_BY(mLock); 1018 1019 // face names missed when face name loading takes a long time 1020 mozilla::UniquePtr<nsTHashSet<nsCString>> mFaceNamesMissed 1021 MOZ_GUARDED_BY(mLock); 1022 1023 // localized family names missed when face name loading takes a long time 1024 mozilla::UniquePtr<nsTHashSet<nsCString>> mOtherNamesMissed 1025 MOZ_GUARDED_BY(mLock); 1026 1027 typedef mozilla::RangedArray<mozilla::UniquePtr<PrefFontList>, 1028 size_t(mozilla::StyleGenericFontFamily::None), 1029 size_t( 1030 mozilla::StyleGenericFontFamily::MozEmoji)> 1031 PrefFontsForLangGroup; 1032 mozilla::RangedArray<PrefFontsForLangGroup, eFontPrefLang_First, 1033 eFontPrefLang_Count> 1034 mLangGroupPrefFonts MOZ_GUARDED_BY(mLock); 1035 mozilla::UniquePtr<PrefFontList> mEmojiPrefFont MOZ_GUARDED_BY(mLock); 1036 1037 // When system-wide font lookup fails for a character, cache it to skip future 1038 // searches. This is an array of bitsets, one for each FontVisibility level. 1039 mozilla::EnumeratedArray<FontVisibility, gfxSparseBitSet, 1040 size_t(FontVisibility::Count)> 1041 mCodepointsWithNoFonts MOZ_GUARDED_BY(mLock); 1042 1043 // the family to use for U+FFFD fallback, to avoid expensive search every time 1044 // on pages with lots of problems 1045 mozilla::EnumeratedArray<FontVisibility, FontFamily, 1046 size_t(FontVisibility::Count)> 1047 mReplacementCharFallbackFamily MOZ_GUARDED_BY(mLock); 1048 1049 // Sorted array of lowercased family names; use ContainsSorted to test 1050 nsTArray<nsCString> mBadUnderlineFamilyNames; 1051 1052 // character map data shared across families 1053 // contains weak ptrs to cmaps shared by font entry objects 1054 nsTHashtable<CharMapHashKey> mSharedCmaps MOZ_GUARDED_BY(mLock); 1055 1056 nsTHashtable<ShmemCharMapHashEntry> mShmemCharMaps MOZ_GUARDED_BY(mLock); 1057 1058 // data used as part of the font cmap loading process 1059 nsTArray<RefPtr<gfxFontFamily>> mFontFamiliesToLoad MOZ_GUARDED_BY(mLock); 1060 uint32_t mStartIndex MOZ_GUARDED_BY(mLock) = 0; 1061 uint32_t mNumFamilies MOZ_GUARDED_BY(mLock) = 0; 1062 1063 // xxx - info for diagnosing no default font aborts 1064 // see bugs 636957, 1070983, 1189129 1065 uint32_t mFontlistInitCount = 0; // num times InitFontList called 1066 1067 nsTHashSet<gfxUserFontSet*> mUserFontSetList MOZ_GUARDED_BY(mLock); 1068 1069 nsLanguageAtomService* mLangService = nullptr; 1070 1071 nsTArray<mozilla::StyleGenericFontFamily> mDefaultGenericsLangGroup 1072 MOZ_GUARDED_BY(mLock); 1073 1074 nsTArray<nsCString> mEnabledFontsList; 1075 nsTHashSet<nsCString> mIconFontsSet; 1076 1077 mozilla::UniquePtr<mozilla::fontlist::FontList> mSharedFontList; 1078 1079 nsClassHashtable<nsCStringHashKey, mozilla::fontlist::AliasData> mAliasTable; 1080 nsTHashMap<nsCStringHashKey, mozilla::fontlist::LocalFaceRec::InitData> 1081 mLocalNameTable; 1082 1083 nsRefPtrHashtable<nsPtrHashKey<const mozilla::fontlist::Face>, gfxFontEntry> 1084 mFontEntries MOZ_GUARDED_BY(mLock); 1085 1086 mozilla::UniquePtr<FontPrefs> mFontPrefs; 1087 1088 RefPtr<gfxFontEntry> mDefaultFontEntry MOZ_GUARDED_BY(mLock); 1089 1090 RefPtr<LoadCmapsRunnable> mLoadCmapsRunnable; 1091 uint32_t mStartedLoadingCmapsFrom MOZ_GUARDED_BY(mLock) = 0xffffffffu; 1092 1093 bool mFontFamilyWhitelistActive = false; 1094 1095 static PRThread* sInitFontListThread; 1096 }; 1097 1098 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatformFontList::FindFamiliesFlags) 1099 1100 #endif /* GFXPLATFORMFONTLIST_H_ */