1 /* -*- Mode: C++; tab-width: 2; 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 mozilla_dom_FontFaceSet_h
7 #define mozilla_dom_FontFaceSet_h
9 #include "mozilla/dom/FontFace.h"
10 #include "mozilla/dom/FontFaceSetBinding.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "gfxUserFontSet.h"
13 #include "nsCSSRules.h"
14 #include "nsICSSLoaderObserver.h"
15 #include "nsPIDOMWindow.h"
17 struct gfxFontFaceSrc
;
18 class gfxUserFontEntry
;
19 class nsFontFaceLoader
;
33 class FontFaceSet MOZ_FINAL
: public DOMEventTargetHelper
34 , public nsIDOMEventListener
35 , public nsICSSLoaderObserver
37 friend class UserFontSet
;
41 * A gfxUserFontSet that integrates with the layout and style systems to
42 * manage @font-face rules and handle network requests for font loading.
44 * We would combine this class and FontFaceSet into the one class if it were
45 * possible; it's not because FontFaceSet is cycle collected and
46 * gfxUserFontSet isn't (and can't be, as gfx classes don't use the cycle
47 * collector). So UserFontSet exists just to override the needed virtual
48 * methods from gfxUserFontSet and to forward them on FontFaceSet.
50 class UserFontSet MOZ_FINAL
: public gfxUserFontSet
52 friend class FontFaceSet
;
55 explicit UserFontSet(FontFaceSet
* aFontFaceSet
)
56 : mFontFaceSet(aFontFaceSet
)
60 FontFaceSet
* GetFontFaceSet() { return mFontFaceSet
; }
62 virtual nsresult
CheckFontLoad(const gfxFontFaceSrc
* aFontFaceSrc
,
63 nsIPrincipal
** aPrincipal
,
64 bool* aBypassCache
) MOZ_OVERRIDE
;
65 virtual nsresult
StartLoad(gfxUserFontEntry
* aUserFontEntry
,
66 const gfxFontFaceSrc
* aFontFaceSrc
) MOZ_OVERRIDE
;
69 virtual bool GetPrivateBrowsing() MOZ_OVERRIDE
;
70 virtual nsresult
SyncLoadFontData(gfxUserFontEntry
* aFontToLoad
,
71 const gfxFontFaceSrc
* aFontFaceSrc
,
73 uint32_t& aBufferLength
) MOZ_OVERRIDE
;
74 virtual nsresult
LogMessage(gfxUserFontEntry
* aUserFontEntry
,
76 uint32_t aFlags
= nsIScriptError::errorFlag
,
77 nsresult aStatus
= NS_OK
) MOZ_OVERRIDE
;
78 virtual void DoRebuildUserFontSet() MOZ_OVERRIDE
;
79 virtual already_AddRefed
<gfxUserFontEntry
> CreateUserFontEntry(
80 const nsTArray
<gfxFontFaceSrc
>& aFontFaceSrcList
,
83 uint32_t aItalicStyle
,
84 const nsTArray
<gfxFontFeature
>& aFeatureSettings
,
85 uint32_t aLanguageOverride
,
86 gfxSparseBitSet
* aUnicodeRanges
) MOZ_OVERRIDE
;
89 nsRefPtr
<FontFaceSet
> mFontFaceSet
;
92 NS_DECL_ISUPPORTS_INHERITED
93 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FontFaceSet
, DOMEventTargetHelper
)
94 NS_DECL_NSIDOMEVENTLISTENER
96 FontFaceSet(nsPIDOMWindow
* aWindow
, nsPresContext
* aPresContext
);
98 virtual JSObject
* WrapObject(JSContext
* aCx
) MOZ_OVERRIDE
;
100 UserFontSet
* EnsureUserFontSet(nsPresContext
* aPresContext
);
101 UserFontSet
* GetUserFontSet() { return mUserFontSet
; }
103 // Called when this font set is no longer associated with a presentation.
104 void DestroyUserFontSet();
106 // Called by nsFontFaceLoader when the loader has completed normally.
107 // It's removed from the mLoaders set.
108 void RemoveLoader(nsFontFaceLoader
* aLoader
);
110 bool UpdateRules(const nsTArray
<nsFontFaceRuleContainer
>& aRules
);
112 nsPresContext
* GetPresContext() { return mPresContext
; }
114 // search for @font-face rule that matches a platform font entry
115 nsCSSFontFaceRule
* FindRuleForEntry(gfxFontEntry
* aFontEntry
);
117 void IncrementGeneration(bool aIsRebuild
= false);
120 * Adds the specified FontFace to the mUnavailableFaces array. This is called
121 * when a new FontFace object has just been created in JS by the author.
123 void AddUnavailableFontFace(FontFace
* aFontFace
);
126 * Removes the specified FontFace from the mUnavailableFaces array. This
127 * is called when a FontFace object is about be destroyed.
129 void RemoveUnavailableFontFace(FontFace
* aFontFace
);
132 * Finds an existing entry in the user font cache or creates a new user
133 * font entry for the given FontFace object.
135 already_AddRefed
<gfxUserFontEntry
>
136 FindOrCreateUserFontEntryFromFontFace(FontFace
* aFontFace
);
139 * Notification method called by a FontFace once it has been initialized.
141 * This is needed for the FontFaceSet to handle a FontFace that was created
142 * and inserted into the set immediately, before the event loop has spun and
143 * the FontFace's initialization tasks have run.
145 void OnFontFaceInitialized(FontFace
* aFontFace
);
148 * Notification method called by a FontFace to indicate that its loading
149 * status has changed.
151 void OnFontFaceStatusChanged(FontFace
* aFontFace
);
154 * Notification method called by the nsPresContext to indicate that the
155 * refresh driver ticked and flushed style and layout.
161 * Returns whether the "layout.css.font-loading-api.enabled" pref is true.
163 static bool PrefEnabled();
165 // nsICSSLoaderObserver
166 NS_IMETHOD
StyleSheetLoaded(mozilla::CSSStyleSheet
* aSheet
,
168 nsresult aStatus
) MOZ_OVERRIDE
;
170 // -- Web IDL --------------------------------------------------------------
172 IMPL_EVENT_HANDLER(loading
)
173 IMPL_EVENT_HANDLER(loadingdone
)
174 IMPL_EVENT_HANDLER(loadingerror
)
175 already_AddRefed
<mozilla::dom::Promise
> Load(const nsAString
& aFont
,
176 const nsAString
& aText
,
177 mozilla::ErrorResult
& aRv
);
178 bool Check(const nsAString
& aFont
,
179 const nsAString
& aText
,
180 mozilla::ErrorResult
& aRv
);
181 mozilla::dom::Promise
* GetReady(mozilla::ErrorResult
& aRv
);
182 mozilla::dom::FontFaceSetLoadStatus
Status();
184 FontFaceSet
* Add(FontFace
& aFontFace
, mozilla::ErrorResult
& aRv
);
186 bool Delete(FontFace
& aFontFace
, mozilla::ErrorResult
& aRv
);
187 bool Has(FontFace
& aFontFace
);
188 FontFace
* IndexedGetter(uint32_t aIndex
, bool& aFound
);
195 * Returns whether the given FontFace is currently "in" the FontFaceSet.
197 bool HasAvailableFontFace(FontFace
* aFontFace
);
200 * Removes any listeners and observers.
205 * Returns whether there might be any pending font loads, which should cause
206 * the mReady Promise not to be resolved yet.
208 bool MightHavePendingFontLoads();
211 * Checks to see whether it is time to replace mReady and dispatch a
214 void CheckLoadingStarted();
217 * Checks to see whether it is time to resolve mReady and dispatch any
218 * "loadingdone" and "loadingerror" events.
220 void CheckLoadingFinished();
223 * Dispatches a CSSFontFaceLoadEvent to this object.
225 void DispatchLoadingFinishedEvent(
226 const nsAString
& aType
,
227 const nsTArray
<FontFace
*>& aFontFaces
);
229 // Note: if you add new cycle collected objects to FontFaceRecord,
230 // make sure to update FontFaceSet's cycle collection macros
232 struct FontFaceRecord
{
233 nsRefPtr
<FontFace
> mFontFace
;
237 already_AddRefed
<gfxUserFontEntry
> FindOrCreateUserFontEntryFromFontFace(
238 const nsAString
& aFamilyName
,
242 // search for @font-face rule that matches a userfont font entry
243 nsCSSFontFaceRule
* FindRuleForUserFontEntry(gfxUserFontEntry
* aUserFontEntry
);
245 nsresult
StartLoad(gfxUserFontEntry
* aUserFontEntry
,
246 const gfxFontFaceSrc
* aFontFaceSrc
);
247 nsresult
CheckFontLoad(const gfxFontFaceSrc
* aFontFaceSrc
,
248 nsIPrincipal
** aPrincipal
,
250 bool GetPrivateBrowsing();
251 nsresult
SyncLoadFontData(gfxUserFontEntry
* aFontToLoad
,
252 const gfxFontFaceSrc
* aFontFaceSrc
,
254 uint32_t& aBufferLength
);
255 nsresult
LogMessage(gfxUserFontEntry
* aUserFontEntry
,
256 const char* aMessage
,
259 void DoRebuildUserFontSet();
261 void InsertRuleFontFace(FontFace
* aFontFace
, uint8_t aSheetType
,
262 nsTArray
<FontFaceRecord
>& aOldRecords
,
263 bool& aFontSetModified
);
264 void InsertNonRuleFontFace(FontFace
* aFontFace
, bool& aFontSetModified
);
267 bool HasRuleFontFace(FontFace
* aFontFace
);
271 * Returns whether we have any loading FontFace objects in the FontFaceSet.
273 bool HasLoadingFontFaces();
275 // Helper function for HasLoadingFontFaces.
276 void UpdateHasLoadingFontFaces();
278 nsRefPtr
<UserFontSet
> mUserFontSet
;
279 nsPresContext
* mPresContext
;
281 // The document this is a FontFaceSet for.
282 nsCOMPtr
<nsIDocument
> mDocument
;
284 // A Promise that is fulfilled once all of the FontFace objects
285 // in mRuleFaces and mNonRuleFaces that started or were loading at the
286 // time the Promise was created have finished loading. It is rejected if
287 // any of those fonts failed to load. mReady is replaced with
288 // a new Promise object whenever mReady is settled and another
289 // FontFace in mRuleFaces or mNonRuleFaces starts to load.
290 nsRefPtr
<mozilla::dom::Promise
> mReady
;
292 // Set of all loaders pointing to us. These are not strong pointers,
293 // but that's OK because nsFontFaceLoader always calls RemoveLoader on
294 // us before it dies (unless we die first).
295 nsTHashtable
< nsPtrHashKey
<nsFontFaceLoader
> > mLoaders
;
297 // The @font-face rule backed FontFace objects in the FontFaceSet.
298 nsTArray
<FontFaceRecord
> mRuleFaces
;
300 // The non rule backed FontFace objects that have been added to this
301 // FontFaceSet and their corresponding user font entries.
302 nsTArray
<nsRefPtr
<FontFace
>> mNonRuleFaces
;
304 // The non rule backed FontFace objects that have not been added to
306 nsTArray
<FontFace
*> mUnavailableFaces
;
308 // The overall status of the loading or loaded fonts in the FontFaceSet.
309 mozilla::dom::FontFaceSetLoadStatus mStatus
;
311 // Whether mNonRuleFaces has changed since last time UpdateRules ran.
312 bool mNonRuleFacesDirty
;
314 // Whether we have called MaybeResolve() on mReady.
315 bool mReadyIsResolved
;
317 // Whether we have already dispatched loading events for the current set
318 // of loading FontFaces.
319 bool mDispatchedLoadingEvent
;
321 // Whether any FontFace objects in mRuleFaces or mNonRuleFaces are
322 // loading. Only valid when mHasLoadingFontFacesIsDirty is false. Don't use
323 // this variable directly; call the HasLoadingFontFaces method instead.
324 bool mHasLoadingFontFaces
;
326 // This variable is only valid when mLoadingDirty is false.
327 bool mHasLoadingFontFacesIsDirty
;
331 } // namespace mozilla
333 #endif // !defined(mozilla_dom_FontFaceSet_h)