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