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