summaryrefslogtreecommitdiffstats
path: root/layout/style/FontFaceSet.h
blob: 04de363df3452ab2d3d957138f1fea93cf2e836d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/dom/FontFaceSetImpl.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "nsICSSLoaderObserver.h"
#include "nsIDOMEventListener.h"

class nsFontFaceLoader;
class nsIPrincipal;
class nsIGlobalObject;

namespace mozilla {
class PostTraversalTask;
class SharedFontList;
namespace dom {
class Promise;
class WorkerPrivate;
}  // namespace dom
}  // namespace mozilla

namespace mozilla::dom {

class FontFaceSet final : public DOMEventTargetHelper {
  friend class mozilla::PostTraversalTask;

 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FontFaceSet, DOMEventTargetHelper)

  static bool IsEnabled();

  static bool IsEnabled(JSContext* aCx, JSObject* aObj) { return IsEnabled(); }

  static already_AddRefed<FontFaceSet> CreateForDocument(
      dom::Document* aDocument);

  static already_AddRefed<FontFaceSet> CreateForWorker(
      nsIGlobalObject* aParent, WorkerPrivate* aWorkerPrivate);

  virtual JSObject* WrapObject(JSContext* aCx,
                               JS::Handle<JSObject*> aGivenProto) override;

  bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);

  /**
   * Notification method called by the nsPresContext to indicate that the
   * refresh driver ticked and flushed style and layout.
   * were just flushed.
   */
  void DidRefresh();

  void FlushUserFontSet();

  void RefreshStandardFontLoadPrincipal();

  void CopyNonRuleFacesTo(FontFaceSet* aFontFaceSet) const;

  void CacheFontLoadability() { mImpl->CacheFontLoadability(); }

  FontFaceSetImpl* GetImpl() const { return mImpl; }

  // -- Web IDL --------------------------------------------------------------

  IMPL_EVENT_HANDLER(loading)
  IMPL_EVENT_HANDLER(loadingdone)
  IMPL_EVENT_HANDLER(loadingerror)
  already_AddRefed<dom::Promise> Load(JSContext* aCx, const nsACString& aFont,
                                      const nsAString& aText, ErrorResult& aRv);
  bool Check(const nsACString& aFont, const nsAString& aText, ErrorResult& aRv);
  dom::Promise* GetReady(ErrorResult& aRv);
  dom::FontFaceSetLoadStatus Status();

  void Add(FontFace& aFontFace, ErrorResult& aRv);
  void Clear();
  bool Delete(FontFace& aFontFace);
  bool Has(FontFace& aFontFace);
  /**
   * This returns the number of Author origin fonts only.
   * (see also SizeIncludingNonAuthorOrigins() below)
   */
  uint32_t Size();
  already_AddRefed<dom::FontFaceSetIterator> Entries();
  already_AddRefed<dom::FontFaceSetIterator> Values();
  MOZ_CAN_RUN_SCRIPT
  void ForEach(JSContext* aCx, FontFaceSetForEachCallback& aCallback,
               JS::Handle<JS::Value> aThisArg, ErrorResult& aRv);

  /**
   * Unlike Size(), this returns the size including non-Author origin fonts.
   */
  uint32_t SizeIncludingNonAuthorOrigins();

  void MaybeResolve();

  void DispatchLoadingFinishedEvent(
      const nsAString& aType, nsTArray<OwningNonNull<FontFace>>&& aFontFaces);

  void DispatchLoadingEventAndReplaceReadyPromise();
  void DispatchCheckLoadingFinishedAfterDelay();

  // Whether mReady is pending, or would be when created.
  bool ReadyPromiseIsPending() const;

  void InsertRuleFontFace(FontFace* aFontFace, StyleOrigin aOrigin);

 private:
  friend mozilla::dom::FontFaceSetIterator;  // needs GetFontFaceAt()

  explicit FontFaceSet(nsIGlobalObject* aParent);
  ~FontFaceSet();

  /**
   * Returns whether the given FontFace is currently "in" the FontFaceSet.
   */
  bool HasAvailableFontFace(FontFace* aFontFace);

  /**
   * Removes any listeners and observers.
   */
  void Destroy();

  /**
   * Returns the font at aIndex if it's an Author origin font, or nullptr
   * otherwise.
   */
  FontFace* GetFontFaceAt(uint32_t aIndex);

  // 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;
    Maybe<StyleOrigin> mOrigin;  // 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;
  };

#ifdef DEBUG
  bool HasRuleFontFace(FontFace* aFontFace);
#endif

  // The underlying implementation for FontFaceSet.
  RefPtr<FontFaceSetImpl> mImpl;

  // 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<dom::Promise> mReady;
  // Whether the ready promise must be resolved when it's created.
  bool mResolveLazilyCreatedReadyPromise = false;

  // 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;
};

}  // namespace mozilla::dom

#endif  // !defined(mozilla_dom_FontFaceSet_h)