123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef mozilla_dom_FontFaceSet_h
- #define mozilla_dom_FontFaceSet_h
- #include "mozilla/dom/FontFace.h"
- #include "mozilla/dom/FontFaceSetBinding.h"
- #include "mozilla/DOMEventTargetHelper.h"
- #include "gfxUserFontSet.h"
- #include "nsCSSRules.h"
- #include "nsICSSLoaderObserver.h"
- struct gfxFontFaceSrc;
- class gfxUserFontEntry;
- class nsFontFaceLoader;
- class nsIPrincipal;
- class nsPIDOMWindowInner;
- namespace mozilla {
- namespace css {
- class FontFamilyListRefCnt;
- } // namespace css
- namespace dom {
- class FontFace;
- class Promise;
- } // namespace dom
- } // namespace mozilla
- namespace mozilla {
- namespace dom {
- class FontFaceSet final : public DOMEventTargetHelper
- , public nsIDOMEventListener
- , public nsICSSLoaderObserver
- {
- friend class UserFontSet;
- public:
- /**
- * A gfxUserFontSet that integrates with the layout and style systems to
- * manage @font-face rules and handle network requests for font loading.
- *
- * We would combine this class and FontFaceSet into the one class if it were
- * possible; it's not because FontFaceSet is cycle collected and
- * gfxUserFontSet isn't (and can't be, as gfx classes don't use the cycle
- * collector). So UserFontSet exists just to override the needed virtual
- * methods from gfxUserFontSet and to forward them on FontFaceSet.
- */
- class UserFontSet final : public gfxUserFontSet
- {
- friend class FontFaceSet;
- public:
- explicit UserFontSet(FontFaceSet* aFontFaceSet)
- : mFontFaceSet(aFontFaceSet)
- {
- }
- FontFaceSet* GetFontFaceSet() { return mFontFaceSet; }
- virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
- nsIPrincipal** aPrincipal,
- bool* aBypassCache) override;
- virtual bool IsFontLoadAllowed(nsIURI* aFontLocation,
- nsIPrincipal* aPrincipal) override;
- virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
- const gfxFontFaceSrc* aFontFaceSrc) override;
- void RecordFontLoadDone(uint32_t aFontSize,
- mozilla::TimeStamp aDoneTime) override;
- protected:
- virtual bool GetPrivateBrowsing() override;
- virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
- const gfxFontFaceSrc* aFontFaceSrc,
- uint8_t*& aBuffer,
- uint32_t& aBufferLength) override;
- virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
- const char* aMessage,
- uint32_t aFlags = nsIScriptError::errorFlag,
- nsresult aStatus = NS_OK) override;
- virtual void DoRebuildUserFontSet() override;
- virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry(
- const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
- uint32_t aWeight,
- int32_t aStretch,
- uint8_t aStyle,
- const nsTArray<gfxFontFeature>& aFeatureSettings,
- uint32_t aLanguageOverride,
- gfxSparseBitSet* aUnicodeRanges,
- uint8_t aFontDisplay) override;
- private:
- RefPtr<FontFaceSet> mFontFaceSet;
- };
- NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FontFaceSet, DOMEventTargetHelper)
- NS_DECL_NSIDOMEVENTLISTENER
- FontFaceSet(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument);
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
- UserFontSet* GetUserFontSet() { return mUserFontSet; }
- // Called by nsFontFaceLoader when the loader has completed normally.
- // It's removed from the mLoaders set.
- void RemoveLoader(nsFontFaceLoader* aLoader);
- bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);
- nsPresContext* GetPresContext();
- // search for @font-face rule that matches a platform font entry
- nsCSSFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry);
- void IncrementGeneration(bool aIsRebuild = false);
- /**
- * Finds an existing entry in the user font cache or creates a new user
- * font entry for the given FontFace object.
- */
- static already_AddRefed<gfxUserFontEntry>
- FindOrCreateUserFontEntryFromFontFace(FontFace* aFontFace);
- /**
- * Notification method called by a FontFace to indicate that its loading
- * status has changed.
- */
- void OnFontFaceStatusChanged(FontFace* aFontFace);
- /**
- * Notification method called by the nsPresContext to indicate that the
- * refresh driver ticked and flushed style and layout.
- * were just flushed.
- */
- void DidRefresh();
- /**
- * Returns whether the "layout.css.font-loading-api.enabled" pref is true.
- */
- static bool PrefEnabled();
- // nsICSSLoaderObserver
- NS_IMETHOD StyleSheetLoaded(mozilla::StyleSheet* aSheet,
- bool aWasAlternate,
- nsresult aStatus) override;
- FontFace* GetFontFaceAt(uint32_t aIndex);
- void FlushUserFontSet();
- static nsPresContext* GetPresContextFor(gfxUserFontSet* aUserFontSet)
- {
- FontFaceSet* set = static_cast<UserFontSet*>(aUserFontSet)->mFontFaceSet;
- return set ? set->GetPresContext() : nullptr;
- }
- // -- Web IDL --------------------------------------------------------------
- IMPL_EVENT_HANDLER(loading)
- IMPL_EVENT_HANDLER(loadingdone)
- IMPL_EVENT_HANDLER(loadingerror)
- already_AddRefed<mozilla::dom::Promise> Load(JSContext* aCx,
- const nsAString& aFont,
- const nsAString& aText,
- mozilla::ErrorResult& aRv);
- bool Check(const nsAString& aFont,
- const nsAString& aText,
- mozilla::ErrorResult& aRv);
- mozilla::dom::Promise* GetReady(mozilla::ErrorResult& aRv);
- mozilla::dom::FontFaceSetLoadStatus Status();
- FontFaceSet* Add(FontFace& aFontFace, mozilla::ErrorResult& aRv);
- void Clear();
- bool Delete(FontFace& aFontFace);
- bool Has(FontFace& aFontFace);
- uint32_t Size();
- already_AddRefed<mozilla::dom::FontFaceSetIterator> Entries();
- already_AddRefed<mozilla::dom::FontFaceSetIterator> Values();
- void ForEach(JSContext* aCx, FontFaceSetForEachCallback& aCallback,
- JS::Handle<JS::Value> aThisArg,
- mozilla::ErrorResult& aRv);
- private:
- ~FontFaceSet();
- /**
- * Returns whether the given FontFace is currently "in" the FontFaceSet.
- */
- bool HasAvailableFontFace(FontFace* aFontFace);
- /**
- * Removes any listeners and observers.
- */
- void Disconnect();
- void RemoveDOMContentLoadedListener();
- /**
- * Returns whether there might be any pending font loads, which should cause
- * the mReady Promise not to be resolved yet.
- */
- bool MightHavePendingFontLoads();
- /**
- * Checks to see whether it is time to replace mReady and dispatch a
- * "loading" event.
- */
- void CheckLoadingStarted();
- /**
- * Checks to see whether it is time to resolve mReady and dispatch any
- * "loadingdone" and "loadingerror" events.
- */
- void CheckLoadingFinished();
- /**
- * Callback for invoking CheckLoadingFinished after going through the
- * event loop. See OnFontFaceStatusChanged.
- */
- void CheckLoadingFinishedAfterDelay();
- /**
- * Dispatches a FontFaceSetLoadEvent to this object.
- */
- void DispatchLoadingFinishedEvent(
- const nsAString& aType,
- const nsTArray<FontFace*>& aFontFaces);
- // Note: if you add new cycle collected objects to FontFaceRecord,
- // make sure to update FontFaceSet's cycle collection macros
- // accordingly.
- struct FontFaceRecord {
- RefPtr<FontFace> mFontFace;
- SheetType mSheetType; // only relevant for mRuleFaces entries
- // When true, indicates that when finished loading, the FontFace should be
- // included in the subsequent loadingdone/loadingerror event fired at the
- // FontFaceSet.
- bool mLoadEventShouldFire;
- };
- static already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntryFromFontFace(
- const nsAString& aFamilyName,
- FontFace* aFontFace,
- SheetType aSheetType);
- // search for @font-face rule that matches a userfont font entry
- nsCSSFontFaceRule* FindRuleForUserFontEntry(gfxUserFontEntry* aUserFontEntry);
- nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
- const gfxFontFaceSrc* aFontFaceSrc);
- nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
- nsIPrincipal** aPrincipal,
- bool* aBypassCache);
- bool IsFontLoadAllowed(nsIURI* aFontLocation, nsIPrincipal* aPrincipal);
- bool GetPrivateBrowsing();
- nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
- const gfxFontFaceSrc* aFontFaceSrc,
- uint8_t*& aBuffer,
- uint32_t& aBufferLength);
- nsresult LogMessage(gfxUserFontEntry* aUserFontEntry,
- const char* aMessage,
- uint32_t aFlags,
- nsresult aStatus);
- void RebuildUserFontSet();
- void InsertRuleFontFace(FontFace* aFontFace, SheetType aSheetType,
- nsTArray<FontFaceRecord>& aOldRecords,
- bool& aFontSetModified);
- void InsertNonRuleFontFace(FontFace* aFontFace, bool& aFontSetModified);
- #ifdef DEBUG
- bool HasRuleFontFace(FontFace* aFontFace);
- #endif
- /**
- * Returns whether we have any loading FontFace objects in the FontFaceSet.
- */
- bool HasLoadingFontFaces();
- // Helper function for HasLoadingFontFaces.
- void UpdateHasLoadingFontFaces();
- void ParseFontShorthandForMatching(
- const nsAString& aFont,
- RefPtr<mozilla::css::FontFamilyListRefCnt>& aFamilyList,
- uint32_t& aWeight,
- int32_t& aStretch,
- uint8_t& aStyle,
- ErrorResult& aRv);
- void FindMatchingFontFaces(const nsAString& aFont,
- const nsAString& aText,
- nsTArray<FontFace*>& aFontFaces,
- mozilla::ErrorResult& aRv);
- TimeStamp GetNavigationStartTimeStamp();
- RefPtr<UserFontSet> mUserFontSet;
- // The document this is a FontFaceSet for.
- nsCOMPtr<nsIDocument> mDocument;
- // A Promise that is fulfilled once all of the FontFace objects
- // in mRuleFaces and mNonRuleFaces that started or were loading at the
- // time the Promise was created have finished loading. It is rejected if
- // any of those fonts failed to load. mReady is replaced with
- // a new Promise object whenever mReady is settled and another
- // FontFace in mRuleFaces or mNonRuleFaces starts to load.
- // Note that mReady is created lazily when GetReady() is called.
- RefPtr<mozilla::dom::Promise> mReady;
- // Whether the ready promise must be resolved when it's created.
- bool mResolveLazilyCreatedReadyPromise;
- // Set of all loaders pointing to us. These are not strong pointers,
- // but that's OK because nsFontFaceLoader always calls RemoveLoader on
- // us before it dies (unless we die first).
- nsTHashtable< nsPtrHashKey<nsFontFaceLoader> > mLoaders;
- // The @font-face rule backed FontFace objects in the FontFaceSet.
- nsTArray<FontFaceRecord> mRuleFaces;
- // The non rule backed FontFace objects that have been added to this
- // FontFaceSet.
- nsTArray<FontFaceRecord> mNonRuleFaces;
- // The overall status of the loading or loaded fonts in the FontFaceSet.
- mozilla::dom::FontFaceSetLoadStatus mStatus;
- // Whether mNonRuleFaces has changed since last time UpdateRules ran.
- bool mNonRuleFacesDirty;
- // Whether any FontFace objects in mRuleFaces or mNonRuleFaces are
- // loading. Only valid when mHasLoadingFontFacesIsDirty is false. Don't use
- // this variable directly; call the HasLoadingFontFaces method instead.
- bool mHasLoadingFontFaces;
- // This variable is only valid when mLoadingDirty is false.
- bool mHasLoadingFontFacesIsDirty;
- // Whether CheckLoadingFinished calls should be ignored. See comment in
- // OnFontFaceStatusChanged.
- bool mDelayedLoadCheck;
- };
- } // namespace dom
- } // namespace mozilla
- #endif // !defined(mozilla_dom_FontFaceSet_h)
|