Bug 1932613 - temporarily disable browser_ml_end_to_end.js for permanent failures...
[gecko.git] / gfx / thebes / gfxUserFontSet.h
bloba876219382cc11eb689c2559a2071934d0c72c80
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 GFX_USER_FONT_SET_H
7 #define GFX_USER_FONT_SET_H
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"
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
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;
54 namespace mozilla {
55 class LogModule;
56 class PostTraversalTask;
57 enum class StyleFontDisplay : uint8_t;
58 } // namespace mozilla
59 class nsFontFaceLoader;
61 // #define DEBUG_USERFONT_CACHE
63 class gfxFontFaceBufferSource {
64 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFaceBufferSource)
65 public:
66 virtual void TakeBuffer(uint8_t*& aBuffer, uint32_t& aLength) = 0;
68 protected:
69 virtual ~gfxFontFaceBufferSource() = default;
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 };
77 SourceType mSourceType;
79 // if url, whether to use the origin principal or not
80 bool mUseOriginPrincipal = false;
82 // Required font technologies.
83 mozilla::StyleFontFaceSourceTechFlags mTechFlags;
85 // Format hint, if any was specified.
86 mozilla::StyleFontFaceSourceFormatKeyword mFormatHint;
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
94 RefPtr<gfxFontFaceBufferSource> mBuffer;
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;
102 inline bool operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b) {
103 if (a.mSourceType != b.mSourceType) {
104 return false;
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;
113 if (a.mUseOriginPrincipal) {
114 if (!a.mOriginPrincipal->Equals(b.mOriginPrincipal)) {
115 return false;
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;
124 case gfxFontFaceSrc::eSourceType_Buffer:
125 return a.mBuffer == b.mBuffer;
127 NS_WARNING("unexpected mSourceType");
128 return false;
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;
149 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
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
166 enum {
167 kUnknownCompression = 0,
168 kZlibCompression = 1,
169 kBrotliCompression = 2
173 // initially contains a set of userfont font entry objects, replaced with
174 // platform/user fonts as downloaded
176 class gfxUserFontFamily : public gfxFontFamily {
177 public:
178 friend class gfxUserFontSet;
180 explicit gfxUserFontFamily(const nsACString& aName)
181 : gfxFontFamily(aName, FontVisibility::Webfont) {}
183 virtual ~gfxUserFontFamily();
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 // keep ref while removing existing entry
190 RefPtr<gfxFontEntry> fe = aFontEntry;
191 // remove existing entry, if already present
192 mAvailableFonts.RemoveElement(aFontEntry);
193 // insert at the beginning so that the last-defined font is the first
194 // one in the fontlist used for matching, as per CSS Fonts spec
195 mAvailableFonts.InsertElementAt(0, aFontEntry);
197 if (aFontEntry->mFamilyName.IsEmpty()) {
198 aFontEntry->mFamilyName = Name();
199 } else {
200 #ifdef DEBUG
201 nsCString thisName = Name();
202 nsCString entryName = aFontEntry->mFamilyName;
203 ToLowerCase(thisName);
204 ToLowerCase(entryName);
205 MOZ_ASSERT(thisName.Equals(entryName));
206 #endif
208 ResetCharacterMap();
211 void RemoveFontEntry(gfxFontEntry* aFontEntry) {
212 mozilla::AutoWriteLock lock(mLock);
213 MOZ_ASSERT(!mIsSimpleFamily, "not valid for user-font families");
214 mAvailableFonts.RemoveElement(aFontEntry);
217 // Remove all font entries from the family
218 void DetachFontEntries() {
219 mozilla::AutoWriteLock lock(mLock);
220 mAvailableFonts.Clear();
224 class gfxUserFontEntry;
225 class gfxOTSMessageContext;
227 struct gfxUserFontAttributes {
228 using FontStretch = mozilla::FontStretch;
229 using StretchRange = mozilla::StretchRange;
230 using FontSlantStyle = mozilla::FontSlantStyle;
231 using SlantStyleRange = mozilla::SlantStyleRange;
232 using FontWeight = mozilla::FontWeight;
233 using WeightRange = mozilla::WeightRange;
234 using StyleFontFaceSourceListComponent =
235 mozilla::StyleFontFaceSourceListComponent;
236 using RangeFlags = gfxFontEntry::RangeFlags;
238 WeightRange mWeight = WeightRange(FontWeight::NORMAL);
239 StretchRange mStretch = StretchRange(FontStretch::NORMAL);
240 SlantStyleRange mStyle = SlantStyleRange(FontSlantStyle::NORMAL);
241 RangeFlags mRangeFlags = RangeFlags::eAutoWeight | RangeFlags::eAutoStretch |
242 RangeFlags::eAutoSlantStyle;
243 mozilla::StyleFontDisplay mFontDisplay = mozilla::StyleFontDisplay::Auto;
244 float mAscentOverride = -1.0;
245 float mDescentOverride = -1.0;
246 float mLineGapOverride = -1.0;
247 float mSizeAdjust = 1.0;
248 uint32_t mLanguageOverride = NO_FONT_LANGUAGE_OVERRIDE;
249 nsTArray<gfxFontFeature> mFeatureSettings;
250 nsTArray<gfxFontVariation> mVariationSettings;
251 RefPtr<gfxCharacterMap> mUnicodeRanges;
253 nsCString mFamilyName;
254 AutoTArray<StyleFontFaceSourceListComponent, 8> mSources;
257 class gfxUserFontSet {
258 friend class gfxUserFontEntry;
259 friend class gfxOTSMessageContext;
261 public:
262 using FontStretch = mozilla::FontStretch;
263 using StretchRange = mozilla::StretchRange;
264 using FontSlantStyle = mozilla::FontSlantStyle;
265 using SlantStyleRange = mozilla::SlantStyleRange;
266 using FontWeight = mozilla::FontWeight;
267 using WeightRange = mozilla::WeightRange;
268 using RangeFlags = gfxFontEntry::RangeFlags;
270 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
272 gfxUserFontSet();
274 void Destroy();
276 // creates a font face without adding it to a particular family
277 // weight - [100, 900] (multiples of 100)
278 // stretch = [FontStretch::UltraCondensed(), FontStretch::UltraExpanded()]
279 // italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL
280 // language override = result of calling
281 // nsLayoutUtils::ParseFontLanguageOverride
282 // TODO: support for unicode ranges not yet implemented
283 virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry(
284 nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList,
285 gfxUserFontAttributes&& aAttr) = 0;
287 // creates a font face for the specified family, or returns an existing
288 // matching entry on the family if there is one
289 already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntry(
290 nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList,
291 gfxUserFontAttributes&& aAttr);
293 // add in a font face for which we have the gfxUserFontEntry already
294 void AddUserFontEntry(const nsCString& aFamilyName,
295 gfxUserFontEntry* aUserFontEntry);
297 // Look up and return the gfxUserFontFamily in mFontFamilies with
298 // the given name
299 virtual already_AddRefed<gfxUserFontFamily> LookupFamily(
300 const nsACString& aName) const;
302 virtual already_AddRefed<gfxFontSrcPrincipal> GetStandardFontLoadPrincipal()
303 const = 0;
304 virtual nsPresContext* GetPresContext() const = 0;
306 // check whether content policies allow the given URI to load.
307 virtual bool IsFontLoadAllowed(const gfxFontFaceSrc&) = 0;
309 // initialize the process that loads external font data, which upon
310 // completion will call FontDataDownloadComplete method
311 virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
312 uint32_t aSrcIndex) = 0;
314 // generation - each time a face is loaded, generation is
315 // incremented so that the change can be recognized
316 uint64_t GetGeneration() { return mGeneration; }
318 // increment the generation on font load
319 void IncrementGeneration(bool aIsRebuild = false) {
320 mozilla::RecursiveMutexAutoLock lock(mMutex);
321 IncrementGenerationLocked(aIsRebuild);
323 void IncrementGenerationLocked(bool aIsRebuild = false) MOZ_REQUIRES(mMutex);
325 // Generation is bumped on font loads but that doesn't affect name-style
326 // mappings. Rebuilds do however affect name-style mappings so need to
327 // lookup fontlists again when that happens.
328 uint64_t GetRebuildGeneration() { return mRebuildGeneration; }
330 // rebuild if local rules have been used
331 void RebuildLocalRules();
333 // Discard any font entries created for src:local(), so that they will
334 // be reloaded next time they're needed. This is called when the platform
335 // font list has changed, which means local font entries that were set up
336 // may no longer be valid.
337 virtual void ForgetLocalFaces();
339 class UserFontCache {
340 public:
341 // Record a loaded user-font in the cache. This requires that the
342 // font-entry's userFontData has been set up already, as it relies
343 // on the URI and Principal recorded there.
344 static void CacheFont(gfxFontEntry* aFontEntry);
346 // The given gfxFontEntry is being destroyed, so remove any record that
347 // refers to it.
348 static void ForgetFont(gfxFontEntry* aFontEntry);
350 // Return the gfxFontEntry corresponding to a given URI and principal,
351 // and the features of the given userfont entry, or nullptr if none is
352 // available. The aPrivate flag is set for requests coming from private
353 // windows, so we can avoid leaking fonts cached in private windows mode out
354 // to normal windows.
355 static gfxFontEntry* GetFont(const gfxFontFaceSrc&,
356 const gfxUserFontEntry&);
358 // Clear everything so that we don't leak URIs and Principals.
359 static void Shutdown();
361 // Memory-reporting support.
362 class MemoryReporter final : public nsIMemoryReporter {
363 private:
364 ~MemoryReporter() = default;
366 public:
367 NS_DECL_ISUPPORTS
368 NS_DECL_NSIMEMORYREPORTER
371 #ifdef DEBUG_USERFONT_CACHE
372 // dump contents
373 static void Dump();
374 #endif
376 private:
377 // Helper that we use to observe the empty-cache notification
378 // from nsICacheService.
379 class Flusher : public nsIObserver {
380 virtual ~Flusher() = default;
382 public:
383 NS_DECL_ISUPPORTS
384 NS_DECL_NSIOBSERVER
385 Flusher() = default;
388 // Key used to look up entries in the user-font cache.
389 // Note that key comparison does *not* use the mFontEntry field
390 // as a whole; it only compares specific fields within the entry
391 // (weight/width/style/features) that could affect font selection
392 // or rendering, and that must match between a font-set's userfont
393 // entry and the corresponding "real" font entry.
394 struct Key {
395 RefPtr<gfxFontSrcURI> mURI;
396 RefPtr<gfxFontSrcPrincipal> mPrincipal; // use nullptr with data: URLs
397 // The font entry MUST notify the cache when it is destroyed
398 // (by calling ForgetFont()).
399 gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
400 bool mPrivate;
402 Key(gfxFontSrcURI* aURI, gfxFontSrcPrincipal* aPrincipal,
403 gfxFontEntry* aFontEntry, bool aPrivate)
404 : mURI(aURI),
405 mPrincipal(aPrincipal),
406 mFontEntry(aFontEntry),
407 mPrivate(aPrivate) {}
410 class Entry : public PLDHashEntryHdr {
411 public:
412 typedef const Key& KeyType;
413 typedef const Key* KeyTypePointer;
415 explicit Entry(KeyTypePointer aKey)
416 : mURI(aKey->mURI),
417 mPrincipal(aKey->mPrincipal),
418 mFontEntry(aKey->mFontEntry),
419 mPrivate(aKey->mPrivate) {}
421 Entry(Entry&& aOther)
422 : PLDHashEntryHdr(std::move(aOther)),
423 mURI(std::move(aOther.mURI)),
424 mPrincipal(std::move(aOther.mPrincipal)),
425 mFontEntry(std::move(aOther.mFontEntry)),
426 mPrivate(std::move(aOther.mPrivate)) {}
428 ~Entry() = default;
430 bool KeyEquals(const KeyTypePointer aKey) const;
432 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
434 static PLDHashNumber HashKey(const KeyTypePointer aKey) {
435 PLDHashNumber principalHash =
436 aKey->mPrincipal ? aKey->mPrincipal->Hash() : 0;
437 return mozilla::HashGeneric(
438 principalHash + int(aKey->mPrivate), aKey->mURI->Hash(),
439 HashFeatures(aKey->mFontEntry->mFeatureSettings),
440 HashVariations(aKey->mFontEntry->mVariationSettings),
441 mozilla::HashString(aKey->mFontEntry->mFamilyName),
442 aKey->mFontEntry->Weight().AsScalar(),
443 aKey->mFontEntry->SlantStyle().AsScalar(),
444 aKey->mFontEntry->Stretch().AsScalar(),
445 aKey->mFontEntry->AutoRangeFlags(),
446 aKey->mFontEntry->mLanguageOverride);
449 enum { ALLOW_MEMMOVE = false };
451 gfxFontSrcURI* GetURI() const { return mURI; }
452 gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; }
453 gfxFontEntry* GetFontEntry() const { return mFontEntry; }
454 bool IsPrivate() const { return mPrivate; }
456 void ReportMemory(nsIHandleReportCallback* aHandleReport,
457 nsISupports* aData, bool aAnonymize);
459 #ifdef DEBUG_USERFONT_CACHE
460 void Dump();
461 #endif
463 private:
464 static uint32_t HashFeatures(const nsTArray<gfxFontFeature>& aFeatures) {
465 return mozilla::HashBytes(aFeatures.Elements(),
466 aFeatures.Length() * sizeof(gfxFontFeature));
469 static uint32_t HashVariations(
470 const nsTArray<mozilla::gfx::FontVariation>& aVariations) {
471 return mozilla::HashBytes(
472 aVariations.Elements(),
473 aVariations.Length() * sizeof(mozilla::gfx::FontVariation));
476 RefPtr<gfxFontSrcURI> mURI;
477 RefPtr<gfxFontSrcPrincipal> mPrincipal; // or nullptr for data: URLs
479 // The "real" font entry corresponding to this downloaded font.
480 // The font entry MUST notify the cache when it is destroyed
481 // (by calling ForgetFont()).
482 gfxFontEntry* MOZ_NON_OWNING_REF mFontEntry;
484 // Whether this font was loaded from a private window.
485 bool mPrivate;
488 static nsTHashtable<Entry>* sUserFonts;
491 void SetLocalRulesUsed() { mLocalRulesUsed = true; }
493 static mozilla::LogModule* GetUserFontsLog();
495 // record statistics about font completion
496 virtual void RecordFontLoadDone(uint32_t aFontSize,
497 mozilla::TimeStamp aDoneTime) {}
499 void GetLoadStatistics(uint32_t& aLoadCount, uint64_t& aLoadSize) const {
500 aLoadCount = mDownloadCount;
501 aLoadSize = mDownloadSize;
504 protected:
505 // Protected destructor, to discourage deletion outside of Release():
506 virtual ~gfxUserFontSet();
508 // Return whether the font set is associated with a private-browsing tab.
509 virtual bool GetPrivateBrowsing() = 0;
511 // Return whether the font set is associated with a document that was
512 // shift-reloaded, for example, and thus should bypass the font cache.
513 virtual bool BypassCache() = 0;
515 // parse data for a data URL
516 virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
517 const gfxFontFaceSrc* aFontFaceSrc,
518 uint8_t*& aBuffer,
519 uint32_t& aBufferLength) = 0;
521 // report a problem of some kind (implemented in nsUserFontSet)
522 virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
523 uint32_t aSrcIndex, const char* aMessage,
524 uint32_t aFlags = nsIScriptError::errorFlag,
525 nsresult aStatus = NS_OK) = 0;
527 // helper method for performing the actual userfont set rebuild
528 virtual void DoRebuildUserFontSet() = 0;
530 // forget about a loader that has been cancelled
531 virtual void RemoveLoader(nsFontFaceLoader* aLoader) = 0;
533 // helper method for FindOrCreateUserFontEntry
534 gfxUserFontEntry* FindExistingUserFontEntry(
535 gfxUserFontFamily* aFamily,
536 const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
537 const gfxUserFontAttributes& aAttr);
539 // creates a new gfxUserFontFamily in mFontFamilies, or returns an existing
540 // family if there is one
541 virtual already_AddRefed<gfxUserFontFamily> GetFamily(
542 const nsACString& aFamilyName);
544 void ForgetLocalFace(gfxUserFontFamily* aFontFamily);
546 // font families defined by @font-face rules
547 nsRefPtrHashtable<nsCStringHashKey, gfxUserFontFamily> mFontFamilies;
549 mozilla::Atomic<uint64_t> mGeneration; // bumped on any font load change
550 uint64_t mRebuildGeneration; // only bumped on rebuilds
552 // true when local names have been looked up, false otherwise
553 bool mLocalRulesUsed;
555 // true when rules using local names need to be redone
556 bool mRebuildLocalRules;
558 // performance stats
559 uint32_t mDownloadCount;
560 uint64_t mDownloadSize;
562 mutable mozilla::RecursiveMutex mMutex;
565 // acts a placeholder until the real font is downloaded
567 class gfxUserFontEntry : public gfxFontEntry {
568 friend class mozilla::PostTraversalTask;
569 friend class gfxUserFontSet;
570 friend class nsUserFontSet;
571 friend class nsFontFaceLoader;
572 friend class gfxOTSMessageContext;
574 public:
575 enum UserFontLoadState {
576 STATUS_NOT_LOADED = 0,
577 STATUS_LOAD_PENDING,
578 STATUS_LOADING,
579 STATUS_LOADED,
580 STATUS_FAILED
583 gfxUserFontEntry(nsTArray<gfxFontFaceSrc>&& aFontFaceSrcList,
584 gfxUserFontAttributes&& aAttr);
586 ~gfxUserFontEntry() override;
588 // Update the attributes of the entry to the given values, without disturbing
589 // the associated platform font entry or in-progress downloads.
590 void UpdateAttributes(gfxUserFontAttributes&& aAttr);
592 // Return whether the entry matches the given list of attributes
593 bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
594 const gfxUserFontAttributes& aAttr);
596 gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override;
598 gfxFontEntry* GetPlatformFontEntry() const { return mPlatformFontEntry; }
600 // is the font loading or loaded, or did it fail?
601 UserFontLoadState LoadState() const { return mUserFontLoadState; }
603 void LoadCanceled() {
604 MOZ_ASSERT(NS_IsMainThread());
606 mUserFontLoadState = STATUS_NOT_LOADED;
607 mFontDataLoadingState = NOT_LOADING;
608 mLoader = nullptr;
609 // Reset mCurrentSrcIndex so that all potential sources are re-considered.
610 mCurrentSrcIndex = 0;
611 mSeenLocalSource = false;
614 // whether to wait before using fallback font or not
615 bool WaitForUserFont() const {
616 return (mUserFontLoadState == STATUS_LOAD_PENDING ||
617 mUserFontLoadState == STATUS_LOADING) &&
618 mFontDataLoadingState < LOADING_SLOWLY;
621 // For userfonts, cmap is used to store the unicode range data,
622 // and is inert once set, so locking is not required here.
623 // no cmap ==> all codepoints permitted
624 bool CharacterInUnicodeRange(uint32_t ch) const {
625 if (const auto* map = GetUnicodeRangeMap()) {
626 return map->test(ch);
628 return true;
631 gfxCharacterMap* GetUnicodeRangeMap() const { return GetCharacterMap(); }
632 void SetUnicodeRangeMap(RefPtr<gfxCharacterMap>&& aCharMap) {
633 auto* oldCmap = GetUnicodeRangeMap();
634 if (oldCmap != aCharMap) {
635 auto* newCmap = aCharMap.forget().take();
636 if (mCharacterMap.compareExchange(oldCmap, newCmap)) {
637 NS_IF_RELEASE(oldCmap);
638 } else {
639 NS_IF_RELEASE(newCmap);
644 mozilla::StyleFontDisplay GetFontDisplay() const { return mFontDisplay; }
646 // load the font - starts the loading of sources which continues until
647 // a valid font resource is found or all sources fail
648 void Load();
650 // Invalidates appropriately when the load finishes.
651 void FontLoadComplete();
653 // methods to expose some information to FontFaceSet::UserFontSet
654 // since we can't make that class a friend
655 void SetLoader(nsFontFaceLoader* aLoader) {
656 MOZ_ASSERT(NS_IsMainThread());
657 mLoader = aLoader;
660 nsFontFaceLoader* GetLoader() const {
661 MOZ_ASSERT(NS_IsMainThread());
662 return mLoader;
665 gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; }
666 void GetFamilyNameAndURIForLogging(uint32_t aSrcIndex,
667 nsACString& aFamilyName, nsACString& aURI);
669 gfxFontEntry* Clone() const override {
670 MOZ_ASSERT_UNREACHABLE("cannot Clone user fonts");
671 return nullptr;
674 virtual already_AddRefed<gfxUserFontSet> GetUserFontSet() const = 0;
676 const nsTArray<gfxFontFaceSrc>& SourceList() const { return mSrcList; }
678 // Returns a weak reference to the requested source record, which is owned
679 // by the gfxUserFontEntry.
680 const gfxFontFaceSrc& SourceAt(uint32_t aSrcIndex) const {
681 return mSrcList[aSrcIndex];
684 // The variation-query APIs should not be called on placeholders.
685 bool HasVariations() override {
686 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder");
687 return false;
689 void GetVariationAxes(nsTArray<gfxFontVariationAxis>&) override {
690 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder");
692 void GetVariationInstances(nsTArray<gfxFontVariationInstance>&) override {
693 MOZ_ASSERT_UNREACHABLE("not meaningful for a userfont placeholder");
696 protected:
697 struct OTSMessage {
698 nsCString mMessage;
699 int mLevel; // see OTSContext in gfx/ots/include/opentype-sanitizer.h
702 const uint8_t* SanitizeOpenTypeData(const uint8_t* aData, uint32_t aLength,
703 uint32_t& aSanitaryLength,
704 gfxUserFontType& aFontType,
705 nsTArray<OTSMessage>& aMessages);
707 // attempt to load the next resource in the src list.
708 void LoadNextSrc();
709 void ContinueLoad();
710 void DoLoadNextSrc(bool aIsContinue);
712 // change the load state
713 virtual void SetLoadState(UserFontLoadState aLoadState);
715 // when download has been completed, pass back data here
716 // aDownloadStatus == NS_OK ==> download succeeded, error otherwise
717 // Ownership of aFontData is passed in here; the font set must
718 // ensure that it is eventually deleted with free().
719 void FontDataDownloadComplete(uint32_t aSrcIndex, const uint8_t* aFontData,
720 uint32_t aLength, nsresult aDownloadStatus,
721 nsIFontLoadCompleteCallback* aCallback);
723 // helper method for creating a platform font
724 // returns true if platform font creation successful
725 // Ownership of aFontData is passed in here; the font must
726 // ensure that it is eventually deleted with free().
727 bool LoadPlatformFontSync(uint32_t aSrcIndex, const uint8_t* aFontData,
728 uint32_t aLength);
730 void LoadPlatformFontAsync(uint32_t aSrcIndex, const uint8_t* aFontData,
731 uint32_t aLength,
732 nsIFontLoadCompleteCallback* aCallback);
734 // helper method for LoadPlatformFontAsync; runs on a background thread
735 void StartPlatformFontLoadOnBackgroundThread(
736 uint32_t aSrcIndex, const uint8_t* aFontData, uint32_t aLength,
737 nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback);
739 // helper method for LoadPlatformFontAsync; runs on the main thread
740 void ContinuePlatformFontLoadOnMainThread(
741 uint32_t aSrcIndex, const uint8_t* aOriginalFontData,
742 uint32_t aOriginalLength, gfxUserFontType aFontType,
743 const uint8_t* aSanitizedFontData, uint32_t aSanitizedLength,
744 nsTArray<OTSMessage>&& aMessages,
745 nsMainThreadPtrHandle<nsIFontLoadCompleteCallback> aCallback);
747 // helper method for LoadPlatformFontSync and
748 // ContinuePlatformFontLoadOnMainThread; runs on the main thread
749 bool LoadPlatformFont(uint32_t aSrcIndex, const uint8_t* aOriginalFontData,
750 uint32_t aOriginalLength, gfxUserFontType aFontType,
751 const uint8_t* aSanitizedFontData,
752 uint32_t aSanitizedLength,
753 nsTArray<OTSMessage>&& aMessages);
755 // helper method for FontDataDownloadComplete and
756 // ContinuePlatformFontLoadOnMainThread; runs on the main thread
757 void FontLoadFailed(nsIFontLoadCompleteCallback* aCallback);
759 // store metadata and src details for current src into aFontEntry
760 void StoreUserFontData(gfxFontEntry* aFontEntry, uint32_t aSrcIndex,
761 bool aPrivate, const nsACString& aOriginalName,
762 FallibleTArray<uint8_t>* aMetadata,
763 uint32_t aMetaOrigLen, uint8_t aCompression);
765 // Clears and then adds to aResult all of the user font sets that this user
766 // font entry has been added to. This will at least include the owner of this
767 // user font entry.
768 virtual void GetUserFontSets(nsTArray<RefPtr<gfxUserFontSet>>& aResult);
770 // general load state
771 UserFontLoadState mUserFontLoadState;
773 // detailed load state while font data is loading
774 // used to determine whether to use fallback font or not
775 // note that code depends on the ordering of these values!
776 enum FontDataLoadingState {
777 NOT_LOADING = 0, // not started to load any font resources yet
778 LOADING_STARTED, // loading has started; hide fallback font
779 LOADING_ALMOST_DONE, // timeout happened but we're nearly done,
780 // so keep hiding fallback font
781 LOADING_SLOWLY, // timeout happened and we're not nearly done,
782 // so use the fallback font
783 LOADING_TIMED_OUT, // font load took too long
784 LOADING_FAILED // failed to load any source: use fallback
786 FontDataLoadingState mFontDataLoadingState;
788 bool mSeenLocalSource;
789 bool mUnsupportedFormat;
790 mozilla::StyleFontDisplay mFontDisplay; // timing of userfont fallback
792 RefPtr<gfxFontEntry> mPlatformFontEntry;
793 nsTArray<gfxFontFaceSrc> mSrcList;
794 uint32_t mCurrentSrcIndex; // index of src item to be loaded next
795 // This field is managed by the nsFontFaceLoader. In the destructor and
796 // Cancel() methods of nsFontFaceLoader this reference is nulled out.
797 nsFontFaceLoader* MOZ_NON_OWNING_REF
798 mLoader; // current loader for this entry, if any
799 RefPtr<gfxUserFontSet> mLoadingFontSet;
800 RefPtr<gfxFontSrcPrincipal> mPrincipal;
803 #endif /* GFX_USER_FONT_SET_H */