gfxUserFontSet.h (30253B)
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 GFX_USER_FONT_SET_H 7 #define GFX_USER_FONT_SET_H 8 9 #include <new> 10 #include "PLDHashTable.h" 11 #include "gfxFontEntry.h" 12 #include "gfxFontUtils.h" 13 #include "mozilla/AlreadyAddRefed.h" 14 #include "mozilla/Atomics.h" 15 #include "mozilla/Attributes.h" 16 #include "mozilla/FontPropertyTypes.h" 17 #include "mozilla/MemoryReporting.h" 18 #include "mozilla/RecursiveMutex.h" 19 #include "mozilla/RefPtr.h" 20 #include "nsCOMPtr.h" 21 #include "nsHashKeys.h" 22 #include "nsIMemoryReporter.h" 23 #include "nsIObserver.h" 24 #include "nsIScriptError.h" 25 #include "nsISupports.h" 26 #include "nsRefPtrHashtable.h" 27 #include "nsString.h" 28 #include "nsTArray.h" 29 #include "nscore.h" 30 31 // Only needed for function bodies. 32 #include <utility> // for move, forward 33 #include "MainThreadUtils.h" // for NS_IsMainThread 34 #include "gfxFontFeatures.h" // for gfxFontFeature 35 #include "gfxFontSrcPrincipal.h" // for gfxFontSrcPrincipal 36 #include "gfxFontSrcURI.h" // for gfxFontSrcURI 37 #include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT_HELPER2, MOZ_ASSERT, MOZ_ASSERT_UNREACHABLE, MOZ_ASSER... 38 #include "mozilla/HashFunctions.h" // for HashBytes, HashGeneric 39 #include "mozilla/TimeStamp.h" // for TimeStamp 40 #include "mozilla/gfx/FontVariation.h" // for FontVariation 41 #include "nsDebug.h" // for NS_WARNING 42 #include "nsIReferrerInfo.h" // for nsIReferrerInfo 43 44 class gfxFont; 45 class gfxUserFontSet; 46 class nsIFontLoadCompleteCallback; 47 class nsIRunnable; 48 struct gfxFontStyle; 49 struct gfxFontVariationAxis; 50 struct gfxFontVariationInstance; 51 template <class T> 52 class nsMainThreadPtrHandle; 53 54 namespace mozilla { 55 class LogModule; 56 class PostTraversalTask; 57 enum class StyleFontDisplay : uint8_t; 58 } // namespace mozilla 59 class nsFontFaceLoader; 60 61 // #define DEBUG_USERFONT_CACHE 62 63 class gfxFontFaceBufferSource { 64 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFaceBufferSource) 65 public: 66 virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength) = 0; 67 68 protected: 69 virtual ~gfxFontFaceBufferSource() = default; 70 }; 71 72 // parsed CSS @font-face rule information 73 // lifetime: from when @font-face rule processed until font is loaded 74 struct gfxFontFaceSrc { 75 enum SourceType { eSourceType_Local, eSourceType_URL, eSourceType_Buffer }; 76 77 SourceType mSourceType; 78 79 // if url, whether to use the origin principal or not 80 bool mUseOriginPrincipal = false; 81 82 // Required font technologies. 83 mozilla::StyleFontFaceSourceTechFlags mTechFlags; 84 85 // Format hint, if any was specified. 86 mozilla::StyleFontFaceSourceFormatKeyword mFormatHint; 87 88 nsCString mLocalName; // full font name if local 89 RefPtr<gfxFontSrcURI> mURI; // uri if url 90 nsCOMPtr<nsIReferrerInfo> mReferrerInfo; // referrer info if url 91 RefPtr<gfxFontSrcPrincipal> 92 mOriginPrincipal; // principal if url and mUseOriginPrincipal 93 94 RefPtr<gfxFontFaceBufferSource> mBuffer; 95 96 // The principal that should be used for the load. Should only be used for 97 // URL sources. 98 already_AddRefed<gfxFontSrcPrincipal> LoadPrincipal( 99 const gfxUserFontSet&) const; 100 }; 101 102 inline bool operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b) { 103 if (a.mSourceType != b.mSourceType) { 104 return false; 105 } 106 switch (a.mSourceType) { 107 case gfxFontFaceSrc::eSourceType_Local: 108 return a.mLocalName == b.mLocalName; 109 case gfxFontFaceSrc::eSourceType_URL: { 110 if (a.mUseOriginPrincipal != b.mUseOriginPrincipal) { 111 return false; 112 } 113 if (a.mUseOriginPrincipal) { 114 if (!a.mOriginPrincipal->Equals(b.mOriginPrincipal)) { 115 return false; 116 } 117 } 118 bool equals; 119 return a.mFormatHint == b.mFormatHint && a.mTechFlags == b.mTechFlags && 120 (a.mURI == b.mURI || a.mURI->Equals(b.mURI)) && 121 NS_SUCCEEDED(a.mReferrerInfo->Equals(b.mReferrerInfo, &equals)) && 122 equals; 123 } 124 case gfxFontFaceSrc::eSourceType_Buffer: 125 return a.mBuffer == b.mBuffer; 126 } 127 NS_WARNING("unexpected mSourceType"); 128 return false; 129 } 130 131 // Subclassed to store platform-specific code cleaned out when font entry is 132 // deleted. 133 // Lifetime: from when platform font is created until it is deactivated. 134 // If the platform does not need to add any platform-specific code/data here, 135 // then the gfxUserFontSet will allocate a base gfxUserFontData and attach 136 // to the entry to track the basic user font info fields here. 137 class gfxUserFontData { 138 public: 139 gfxUserFontData() 140 : mSrcIndex(0), 141 mMetaOrigLen(0), 142 mTechFlags(mozilla::StyleFontFaceSourceTechFlags::Empty()), 143 mFormatHint(mozilla::StyleFontFaceSourceFormatKeyword::None), 144 mCompression(kUnknownCompression), 145 mPrivate(false), 146 mIsBuffer(false) {} 147 virtual ~gfxUserFontData() = default; 148 149 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 150 151 nsTArray<uint8_t> mMetadata; // woff metadata block (compressed), if any 152 RefPtr<gfxFontSrcURI> mURI; // URI of the source, if it was url() 153 RefPtr<gfxFontSrcPrincipal> 154 mPrincipal; // principal for the download, if url() 155 nsCString mLocalName; // font name used for the source, if local() 156 nsCString mRealName; // original fullname from the font resource 157 uint32_t mSrcIndex; // index in the rule's source list 158 uint32_t mMetaOrigLen; // length needed to decompress metadata 159 mozilla::StyleFontFaceSourceTechFlags mTechFlags; // required font tech 160 mozilla::StyleFontFaceSourceFormatKeyword 161 mFormatHint; // format hint for the source used, if any 162 uint8_t mCompression; // compression type 163 bool mPrivate; // whether font belongs to a private window 164 bool mIsBuffer; // whether the font source was a buffer 165 166 enum { 167 kUnknownCompression = 0, 168 kZlibCompression = 1, 169 kBrotliCompression = 2 170 }; 171 }; 172 173 // initially contains a set of userfont font entry objects, replaced with 174 // platform/user fonts as downloaded 175 176 class gfxUserFontFamily : public gfxFontFamily { 177 public: 178 friend class gfxUserFontSet; 179 180 explicit gfxUserFontFamily(const nsACString& aName) 181 : gfxFontFamily(aName, FontVisibility::Webfont) {} 182 183 virtual ~gfxUserFontFamily(); 184 185 // Add the given font entry to the end of the family's list. 186 void AddFontEntry(gfxFontEntry* aFontEntry) { 187 mozilla::AutoWriteLock lock(mLock); 188 MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families"); 189 190 // If this entry is already the last in the list, we can bail out without 191 // doing any work. 192 if (!mAvailableFonts.IsEmpty()) { 193 if (mAvailableFonts.LastElement() == aFontEntry) { 194 return; 195 } 196 } 197 198 // Append new entry: we will search faces from the end, so that the last- 199 // defined font is the first one in the fontlist used for matching, as per 200 // CSS Fonts spec. 201 // (It is possible that the entry is already present earlier in the list, 202 // but duplication is harmless and it's not worth the cost of searching for 203 // an existing entry here.) 204 mAvailableFonts.AppendElement(aFontEntry); 205 206 if (aFontEntry->mFamilyName.IsEmpty()) { 207 aFontEntry->mFamilyName = Name(); 208 } else { 209 #ifdef DEBUG 210 nsCString thisName = Name(); 211 nsCString entryName = aFontEntry->mFamilyName; 212 ToLowerCase(thisName); 213 ToLowerCase(entryName); 214 MOZ_ASSERT(thisName.Equals(entryName)); 215 #endif 216 } 217 ResetCharacterMap(); 218 } 219 220 void RemoveFontEntry(gfxFontEntry* aFontEntry) { 221 mozilla::AutoWriteLock lock(mLock); 222 MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families"); 223 mAvailableFonts.RemoveElement(aFontEntry); 224 } 225 226 // Remove all font entries from the family 227 void DetachFontEntries() { 228 mozilla::AutoWriteLock lock(mLock); 229 mAvailableFonts.Clear(); 230 } 231 }; 232 233 class gfxUserFontEntry; 234 class gfxOTSMessageContext; 235 236 struct gfxUserFontAttributes { 237 using FontStretch = mozilla::FontStretch; 238 using StretchRange = mozilla::StretchRange; 239 using FontSlantStyle = mozilla::FontSlantStyle; 240 using SlantStyleRange = mozilla::SlantStyleRange; 241 using FontWeight = mozilla::FontWeight; 242 using WeightRange = mozilla::WeightRange; 243 using StyleFontFaceSourceListComponent = 244 mozilla::StyleFontFaceSourceListComponent; 245 using RangeFlags = gfxFontEntry::RangeFlags; 246 247 WeightRange mWeight = WeightRange(FontWeight::NORMAL); 248 StretchRange mStretch = StretchRange(FontStretch::NORMAL); 249 SlantStyleRange mStyle = SlantStyleRange(FontSlantStyle::NORMAL); 250 RangeFlags mRangeFlags = RangeFlags::eAutoWeight | RangeFlags::eAutoStretch | 251 RangeFlags::eAutoSlantStyle; 252 mozilla::StyleFontDisplay mFontDisplay = mozilla::StyleFontDisplay::Auto; 253 float mAscentOverride = -1.0; 254 float mDescentOverride = -1.0; 255 float mLineGapOverride = -1.0; 256 float mSizeAdjust = 1.0; 257 uint32_t mLanguageOverride = NO_FONT_LANGUAGE_OVERRIDE; 258 nsTArray<gfxFontFeature> mFeatureSettings; 259 nsTArray<gfxFontVariation> mVariationSettings; 260 RefPtr<gfxCharacterMap> mUnicodeRanges; 261 262 nsCString mFamilyName; 263 AutoTArray<StyleFontFaceSourceListComponent, 8> mSources; 264 }; 265 266 class gfxUserFontSet { 267 friend class gfxUserFontEntry; 268 friend class gfxOTSMessageContext; 269 270 public: 271 using FontStretch = mozilla::FontStretch; 272 using StretchRange = mozilla::StretchRange; 273 using FontSlantStyle = mozilla::FontSlantStyle; 274 using SlantStyleRange = mozilla::SlantStyleRange; 275 using FontWeight = mozilla::FontWeight; 276 using WeightRange = mozilla::WeightRange; 277 using RangeFlags = gfxFontEntry::RangeFlags; 278 279 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 280 281 gfxUserFontSet(); 282 283 void Destroy(); 284 285 // creates a font face without adding it to a particular family 286 // weight - [100, 900] (multiples of 100) 287 // stretch = [FontStretch::UltraCondensed(), FontStretch::UltraExpanded()] 288 // italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL 289 // language override = result of calling 290 // nsLayoutUtils::ParseFontLanguageOverride 291 // TODO: support for unicode ranges not yet implemented 292 virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry( 293 nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList, 294 gfxUserFontAttributes&& aAttr) = 0; 295 296 // creates a font face for the specified family, or returns an existing 297 // matching entry on the family if there is one 298 already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntry( 299 nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList, 300 gfxUserFontAttributes&& aAttr); 301 302 // add in a font face for which we have the gfxUserFontEntry already 303 void AddUserFontEntry(const nsCString& aFamilyName, 304 gfxUserFontEntry* aUserFontEntry); 305 306 // Look up and return the gfxUserFontFamily in mFontFamilies with 307 // the given name 308 virtual already_AddRefed<gfxUserFontFamily> LookupFamily( 309 const nsACString& aName) const; 310 311 virtual already_AddRefed<gfxFontSrcPrincipal> GetStandardFontLoadPrincipal() 312 const = 0; 313 virtual FontVisibilityProvider* GetFontVisibilityProvider() const = 0; 314 315 // check whether content policies allow the given URI to load. 316 virtual bool IsFontLoadAllowed(const gfxFontFaceSrc&) = 0; 317 318 // initialize the process that loads external font data, which upon 319 // completion will call FontDataDownloadComplete method 320 virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry, 321 uint32_t aSrcIndex) = 0; 322 323 // generation - each time a face is loaded, generation is 324 // incremented so that the change can be recognized 325 uint64_t GetGeneration() { return mGeneration; } 326 327 // increment the generation on font load 328 void IncrementGeneration(bool aIsRebuild = false) { 329 mozilla::RecursiveMutexAutoLock lock(mMutex); 330 IncrementGenerationLocked(aIsRebuild); 331 } 332 void IncrementGenerationLocked(bool aIsRebuild = false) MOZ_REQUIRES(mMutex); 333 334 // Generation is bumped on font loads but that doesn't affect name-style 335 // mappings. Rebuilds do however affect name-style mappings so need to 336 // lookup fontlists again when that happens. 337 uint64_t GetRebuildGeneration() { return mRebuildGeneration; } 338 339 // rebuild if local rules have been used 340 void RebuildLocalRules(); 341 342 // Discard any font entries created for src:local(), so that they will 343 // be reloaded next time they're needed. This is called when the platform 344 // font list has changed, which means local font entries that were set up 345 // may no longer be valid. 346 virtual void ForgetLocalFaces(); 347 348 class UserFontCache { 349 public: 350 // Record a loaded user-font in the cache. This requires that the 351 // font-entry's userFontData has been set up already, as it relies 352 // on the URI and Principal recorded there. 353 static void CacheFont(gfxFontEntry* aFontEntry); 354 355 // The given gfxFontEntry is being destroyed, so remove any record that 356 // refers to it. 357 static void ForgetFont(gfxFontEntry* aFontEntry); 358 359 // Return the gfxFontEntry corresponding to a given URI and principal, 360 // and the features of the given userfont entry, or nullptr if none is 361 // available. The aPrivate flag is set for requests coming from private 362 // windows, so we can avoid leaking fonts cached in private windows mode out 363 // to normal windows. 364 static gfxFontEntry* GetFont(const gfxFontFaceSrc&, 365 const gfxUserFontEntry&); 366 367 // Clear everything so that we don't leak URIs and Principals. 368 static void Shutdown(); 369 370 // Memory-reporting support. 371 class MemoryReporter final : public nsIMemoryReporter { 372 private: 373 ~MemoryReporter() = default; 374 375 public: 376 NS_DECL_ISUPPORTS 377 NS_DECL_NSIMEMORYREPORTER 378 }; 379 380 #ifdef DEBUG_USERFONT_CACHE 381 // dump contents 382 static void Dump(); 383 #endif 384 385 private: 386 // Helper that we use to observe the empty-cache notification 387 // from nsICacheService. 388 class Flusher : public nsIObserver { 389 virtual ~Flusher() = default; 390 391 public: 392 NS_DECL_ISUPPORTS 393 NS_DECL_NSIOBSERVER 394 Flusher() = default; 395 }; 396 397 // Key used to look up entries in the user-font cache. 398 // Note that key comparison does *not* use the mFontEntry field 399 // as a whole; it only compares specific fields within the entry 400 // (weight/width/style/features) that could affect font selection 401 // or rendering, and that must match between a font-set's userfont 402 // entry and the corresponding "real" font entry. 403 struct Key { 404 RefPtr<gfxFontSrcURI> mURI; 405 RefPtr<gfxFontSrcPrincipal> mPrincipal; // use nullptr with data: URLs 406 // The font entry MUST notify the cache when it is destroyed 407 // (by calling ForgetFont()). 408 gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry; 409 bool mPrivate; 410 411 Key(gfxFontSrcURI* aURI, gfxFontSrcPrincipal* aPrincipal, 412 gfxFontEntry* aFontEntry, bool aPrivate) 413 : mURI(aURI), 414 mPrincipal(aPrincipal), 415 mFontEntry(aFontEntry), 416 mPrivate(aPrivate) {} 417 }; 418 419 class Entry : public PLDHashEntryHdr { 420 public: 421 typedef const Key& KeyType; 422 typedef const Key* KeyTypePointer; 423 424 explicit Entry(KeyTypePointer aKey) 425 : mURI(aKey->mURI), 426 mPrincipal(aKey->mPrincipal), 427 mFontEntry(aKey->mFontEntry), 428 mPrivate(aKey->mPrivate) {} 429 430 Entry(Entry&& aOther) 431 : PLDHashEntryHdr(std::move(aOther)), 432 mURI(std::move(aOther.mURI)), 433 mPrincipal(std::move(aOther.mPrincipal)), 434 mFontEntry(std::move(aOther.mFontEntry)), 435 mPrivate(std::move(aOther.mPrivate)) {} 436 437 ~Entry() = default; 438 439 bool KeyEquals(const KeyTypePointer aKey) const; 440 441 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } 442 443 static PLDHashNumber HashKey(const KeyTypePointer aKey) { 444 PLDHashNumber principalHash = 445 aKey->mPrincipal ? aKey->mPrincipal->Hash() : 0; 446 return mozilla::HashGeneric( 447 principalHash + int(aKey->mPrivate), aKey->mURI->Hash(), 448 HashFeatures(aKey->mFontEntry->mFeatureSettings), 449 HashVariations(aKey->mFontEntry->mVariationSettings), 450 mozilla::HashString(aKey->mFontEntry->mFamilyName), 451 aKey->mFontEntry->Weight().AsScalar(), 452 aKey->mFontEntry->SlantStyle().AsScalar(), 453 aKey->mFontEntry->Stretch().AsScalar(), 454 aKey->mFontEntry->AutoRangeFlags(), 455 aKey->mFontEntry->mLanguageOverride); 456 } 457 458 enum { ALLOW_MEMMOVE = false }; 459 460 gfxFontSrcURI* GetURI() const { return mURI; } 461 gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; } 462 gfxFontEntry* GetFontEntry() const { return mFontEntry; } 463 bool IsPrivate() const { return mPrivate; } 464 465 void ReportMemory(nsIHandleReportCallback* aHandleReport, 466 nsISupports* aData, bool aAnonymize); 467 468 #ifdef DEBUG_USERFONT_CACHE 469 void Dump(); 470 #endif 471 472 private: 473 static uint32_t HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) { 474 return mozilla::HashBytes(aFeatures.Elements(), 475 aFeatures.Length() * sizeof(gfxFontFeature)); 476 } 477 478 static uint32_t HashVariations( 479 const nsTArray<mozilla::gfx::FontVariation>& aVariations) { 480 return mozilla::HashBytes( 481 aVariations.Elements(), 482 aVariations.Length() * sizeof(mozilla::gfx::FontVariation)); 483 } 484 485 RefPtr<gfxFontSrcURI> mURI; 486 RefPtr<gfxFontSrcPrincipal> mPrincipal; // or nullptr for data: URLs 487 488 // The "real" font entry corresponding to this downloaded font. 489 // The font entry MUST notify the cache when it is destroyed 490 // (by calling ForgetFont()). 491 gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry; 492 493 // Whether this font was loaded from a private window. 494 bool mPrivate; 495 }; 496 497 static nsTHashtable<Entry>* sUserFonts; 498 }; 499 500 void SetLocalRulesUsed() { mLocalRulesUsed = true; } 501 502 static mozilla::LogModule* GetUserFontsLog(); 503 504 // record statistics about font completion 505 virtual void RecordFontLoadDone(uint32_t aFontSize, 506 mozilla::TimeStamp aDoneTime) {} 507 508 void GetLoadStatistics(uint32_t& aLoadCount, uint64_t& aLoadSize) const { 509 aLoadCount = mDownloadCount; 510 aLoadSize = mDownloadSize; 511 } 512 513 protected: 514 // Protected destructor, to discourage deletion outside of Release(): 515 virtual ~gfxUserFontSet(); 516 517 // Return whether the font set is associated with a private-browsing tab. 518 virtual bool GetPrivateBrowsing() = 0; 519 520 // Return whether the font set is associated with a document that was 521 // shift-reloaded, for example, and thus should bypass the font cache. 522 virtual bool BypassCache() = 0; 523 524 // parse data for a data URL 525 virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad, 526 const gfxFontFaceSrc* aFontFaceSrc, 527 uint8_t*& aBuffer, 528 uint32_t& aBufferLength) = 0; 529 530 // report a problem of some kind (implemented in nsUserFontSet) 531 virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, 532 uint32_t aSrcIndex, const char* aMessage, 533 uint32_t aFlags = nsIScriptError::errorFlag, 534 nsresult aStatus = NS_OK) = 0; 535 536 // helper method for performing the actual userfont set rebuild 537 virtual void DoRebuildUserFontSet() = 0; 538 539 // forget about a loader that has been cancelled 540 virtual void RemoveLoader(nsFontFaceLoader* aLoader) = 0; 541 542 // helper method for FindOrCreateUserFontEntry 543 gfxUserFontEntry* FindExistingUserFontEntry( 544 gfxUserFontFamily* aFamily, 545 const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, 546 const gfxUserFontAttributes& aAttr); 547 548 // creates a new gfxUserFontFamily in mFontFamilies, or returns an existing 549 // family if there is one 550 virtual already_AddRefed<gfxUserFontFamily> GetFamily( 551 const nsACString& aFamilyName); 552 553 void ForgetLocalFace(gfxUserFontFamily* aFontFamily); 554 555 // font families defined by @font-face rules 556 nsRefPtrHashtable<nsCStringHashKey, gfxUserFontFamily> mFontFamilies; 557 558 mozilla::Atomic<uint64_t> mGeneration; // bumped on any font load change 559 uint64_t mRebuildGeneration; // only bumped on rebuilds 560 561 // true when local names have been looked up, false otherwise 562 bool mLocalRulesUsed; 563 564 // true when rules using local names need to be redone 565 bool mRebuildLocalRules; 566 567 // performance stats 568 uint32_t mDownloadCount; 569 uint64_t mDownloadSize; 570 571 mutable mozilla::RecursiveMutex mMutex; 572 }; 573 574 // acts a placeholder until the real font is downloaded 575 576 class gfxUserFontEntry : public gfxFontEntry { 577 friend class mozilla::PostTraversalTask; 578 friend class gfxUserFontSet; 579 friend class nsUserFontSet; 580 friend class nsFontFaceLoader; 581 friend class gfxOTSMessageContext; 582 583 public: 584 enum UserFontLoadState { 585 STATUS_NOT_LOADED = 0, 586 STATUS_LOAD_PENDING, 587 STATUS_LOADING, 588 STATUS_LOADED, 589 STATUS_FAILED 590 }; 591 592 gfxUserFontEntry(nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList, 593 gfxUserFontAttributes&& aAttr); 594 595 ~gfxUserFontEntry() override; 596 597 // Update the attributes of the entry to the given values, without disturbing 598 // the associated platform font entry or in-progress downloads. 599 void UpdateAttributes(gfxUserFontAttributes&& aAttr); 600 601 // Return whether the entry matches the given list of attributes 602 bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, 603 const gfxUserFontAttributes& aAttr); 604 605 gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override; 606 607 gfxFontEntry* GetPlatformFontEntry() const { return mPlatformFontEntry; } 608 609 // is the font loading or loaded, or did it fail? 610 UserFontLoadState LoadState() const { return mUserFontLoadState; } 611 612 void LoadCanceled() { 613 MOZ_ASSERT(NS_IsMainThread()); 614 615 mUserFontLoadState = STATUS_NOT_LOADED; 616 mFontDataLoadingState = NOT_LOADING; 617 mLoader = nullptr; 618 // Reset mCurrentSrcIndex so that all potential sources are re-considered. 619 mCurrentSrcIndex = 0; 620 mSeenLocalSource = false; 621 } 622 623 // whether to wait before using fallback font or not 624 bool WaitForUserFont() const { 625 return (mUserFontLoadState == STATUS_LOAD_PENDING || 626 mUserFontLoadState == STATUS_LOADING) && 627 mFontDataLoadingState < LOADING_SLOWLY; 628 } 629 630 // For userfonts, cmap is used to store the unicode range data, 631 // and is inert once set, so locking is not required here. 632 // no cmap ==> all codepoints permitted 633 bool CharacterInUnicodeRange(uint32_t ch) const { 634 if (const auto* map = GetUnicodeRangeMap()) { 635 return map->test(ch); 636 } 637 return true; 638 } 639 640 gfxCharacterMap* GetUnicodeRangeMap() const { return GetCharacterMap(); } 641 void SetUnicodeRangeMap(RefPtr<gfxCharacterMap>&& aCharMap) { 642 auto* oldCmap = GetUnicodeRangeMap(); 643 if (oldCmap != aCharMap) { 644 auto* newCmap = aCharMap.forget().take(); 645 if (mCharacterMap.compareExchange(oldCmap, newCmap)) { 646 NS_IF_RELEASE(oldCmap); 647 } else { 648 NS_IF_RELEASE(newCmap); 649 } 650 } 651 } 652 653 mozilla::StyleFontDisplay GetFontDisplay() const { return mFontDisplay; } 654 655 // load the font - starts the loading of sources which continues until 656 // a valid font resource is found or all sources fail 657 void Load(); 658 659 // Invalidates appropriately when the load finishes. 660 void FontLoadComplete(); 661 662 // methods to expose some information to FontFaceSet::UserFontSet 663 // since we can't make that class a friend 664 void SetLoader(nsFontFaceLoader* aLoader) { 665 MOZ_ASSERT(NS_IsMainThread()); 666 mLoader = aLoader; 667 } 668 669 nsFontFaceLoader* GetLoader() const { 670 MOZ_ASSERT(NS_IsMainThread()); 671 return mLoader; 672 } 673 674 gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; } 675 void GetFamilyNameAndURIForLogging(uint32_t aSrcIndex, 676 nsACString& aFamilyName, nsACString& aURI); 677 678 gfxFontEntry* Clone() const override { 679 MOZ_ASSERT_UNREACHABLE("cannot Clone user fonts"); 680 return nullptr; 681 } 682 683 virtual already_AddRefed<gfxUserFontSet> GetUserFontSet() const = 0; 684 685 const nsTArray<gfxFontFaceSrc>& SourceList() const { return mSrcList; } 686 687 // Returns a weak reference to the requested source record, which is owned 688 // by the gfxUserFontEntry. 689 const gfxFontFaceSrc& SourceAt(uint32_t aSrcIndex) const { 690 return mSrcList[aSrcIndex]; 691 } 692 693 // The variation-query APIs should not be called on placeholders. 694 bool HasVariations() override { 695 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder"); 696 return false; 697 } 698 void GetVariationAxes(nsTArray<gfxFontVariationAxis>&) override { 699 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder"); 700 } 701 void GetVariationInstances(nsTArray<gfxFontVariationInstance>&) override { 702 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder"); 703 } 704 705 protected: 706 struct OTSMessage { 707 nsCString mMessage; 708 int mLevel; // see OTSContext in gfx/ots/include/opentype-sanitizer.h 709 }; 710 711 const uint8_t* SanitizeOpenTypeData(const uint8_t* aData, uint32_t aLength, 712 uint32_t& aSanitaryLength, 713 gfxUserFontType& aFontType, 714 nsTArray<OTSMessage>& aMessages); 715 716 // attempt to load the next resource in the src list. 717 void LoadNextSrc(); 718 void ContinueLoad(); 719 void DoLoadNextSrc(bool aIsContinue); 720 721 // change the load state 722 virtual void SetLoadState(UserFontLoadState aLoadState); 723 724 // when download has been completed, pass back data here 725 // aDownloadStatus == NS_OK ==> download succeeded, error otherwise 726 // Ownership of aFontData is passed in here; the font set must 727 // ensure that it is eventually deleted with free(). 728 void FontDataDownloadComplete(uint32_t aSrcIndex, const uint8_t* aFontData, 729 uint32_t aLength, nsresult aDownloadStatus, 730 nsIFontLoadCompleteCallback* aCallback); 731 732 // helper method for creating a platform font 733 // returns true if platform font creation successful 734 // Ownership of aFontData is passed in here; the font must 735 // ensure that it is eventually deleted with free(). 736 bool LoadPlatformFontSync(uint32_t aSrcIndex, const uint8_t* aFontData, 737 uint32_t aLength); 738 739 void LoadPlatformFontAsync(uint32_t aSrcIndex, const uint8_t* aFontData, 740 uint32_t aLength, 741 nsIFontLoadCompleteCallback* aCallback); 742 743 // helper method for LoadPlatformFontAsync; runs on a background thread 744 void StartPlatformFontLoadOnBackgroundThread( 745 uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength, 746 nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback); 747 748 // helper method for LoadPlatformFontAsync; runs on the main thread 749 void ContinuePlatformFontLoadOnMainThread( 750 uint32_t aSrcIndex, const uint8_t* aOriginalFontData, 751 uint32_t aOriginalLength, gfxUserFontType aFontType, 752 const uint8_t* aSanitizedFontData, uint32_t aSanitizedLength, 753 nsTArray<OTSMessage>&& aMessages, 754 nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback); 755 756 // helper method for LoadPlatformFontSync and 757 // ContinuePlatformFontLoadOnMainThread; runs on the main thread 758 bool LoadPlatformFont(uint32_t aSrcIndex, const uint8_t* aOriginalFontData, 759 uint32_t aOriginalLength, gfxUserFontType aFontType, 760 const uint8_t* aSanitizedFontData, 761 uint32_t aSanitizedLength, 762 nsTArray<OTSMessage>&& aMessages); 763 764 // helper method for FontDataDownloadComplete and 765 // ContinuePlatformFontLoadOnMainThread; runs on the main thread 766 void FontLoadFailed(nsIFontLoadCompleteCallback* aCallback); 767 768 // store metadata and src details for current src into aFontEntry 769 void StoreUserFontData(gfxFontEntry* aFontEntry, uint32_t aSrcIndex, 770 bool aPrivate, const nsACString& aOriginalName, 771 FallibleTArray<uint8_t>* aMetadata, 772 uint32_t aMetaOrigLen, uint8_t aCompression); 773 774 // Clears and then adds to aResult all of the user font sets that this user 775 // font entry has been added to. This will at least include the owner of this 776 // user font entry. 777 virtual void GetUserFontSets(nsTArray<RefPtr<gfxUserFontSet>>& aResult); 778 779 // general load state 780 UserFontLoadState mUserFontLoadState; 781 782 // detailed load state while font data is loading 783 // used to determine whether to use fallback font or not 784 // note that code depends on the ordering of these values! 785 enum FontDataLoadingState { 786 NOT_LOADING = 0, // not started to load any font resources yet 787 LOADING_STARTED, // loading has started; hide fallback font 788 LOADING_ALMOST_DONE, // timeout happened but we're nearly done, 789 // so keep hiding fallback font 790 LOADING_SLOWLY, // timeout happened and we're not nearly done, 791 // so use the fallback font 792 LOADING_TIMED_OUT, // font load took too long 793 LOADING_FAILED // failed to load any source: use fallback 794 }; 795 FontDataLoadingState mFontDataLoadingState; 796 797 bool mSeenLocalSource; 798 bool mUnsupportedFormat; 799 mozilla::StyleFontDisplay mFontDisplay; // timing of userfont fallback 800 801 RefPtr<gfxFontEntry> mPlatformFontEntry; 802 nsTArray<gfxFontFaceSrc> mSrcList; 803 uint32_t mCurrentSrcIndex; // index of src item to be loaded next 804 // This field is managed by the nsFontFaceLoader. In the destructor and 805 // Cancel() methods of nsFontFaceLoader this reference is nulled out. 806 nsFontFaceLoader* MOZ_NON_OWNING_REF 807 mLoader; // current loader for this entry, if any 808 RefPtr<gfxUserFontSet> mLoadingFontSet; 809 RefPtr<gfxFontSrcPrincipal> mPrincipal; 810 }; 811 812 #endif /* GFX_USER_FONT_SET_H */