1 
2 // Copyright 2017 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 
6 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
7 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
8 
9 #include "base/macros.h"
10 #include "third_party/blink/public/platform/task_type.h"
11 #include "third_party/blink/renderer/bindings/core/v8/iterable.h"
12 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
13 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
14 #include "third_party/blink/renderer/core/css/font_face.h"
15 #include "third_party/blink/renderer/core/dom/events/event_listener.h"
16 #include "third_party/blink/renderer/core/dom/events/event_target.h"
17 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
18 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
19 #include "third_party/blink/renderer/platform/fonts/font_selector.h"
20 
21 // Mac OS X 10.6 SDK defines check() macro that interferes with our check()
22 // method
23 #ifdef check
24 #undef check
25 #endif
26 
27 namespace blink {
28 
29 class FontFaceCache;
30 
31 using FontFaceSetIterable = SetlikeIterable<Member<FontFace>>;
32 
33 class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
34                                 public ExecutionContextClient,
35                                 public FontFaceSetIterable,
36                                 public FontFace::LoadFontCallback {
37   DEFINE_WRAPPERTYPEINFO();
38 
39  public:
FontFaceSet(ExecutionContext & context)40   FontFaceSet(ExecutionContext& context)
41       : ExecutionContextClient(&context),
42         ready_(MakeGarbageCollected<ReadyProperty>(GetExecutionContext())) {}
43   ~FontFaceSet() override = default;
44 
45   DEFINE_ATTRIBUTE_EVENT_LISTENER(loading, kLoading)
46   DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingdone, kLoadingdone)
47   DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingerror, kLoadingerror)
48 
49   bool check(const String& font, const String& text, ExceptionState&);
50   ScriptPromise load(ScriptState*, const String& font, const String& text);
51   virtual ScriptPromise ready(ScriptState*) = 0;
52 
GetExecutionContext()53   ExecutionContext* GetExecutionContext() const override {
54     return ExecutionContextClient::GetExecutionContext();
55   }
56 
InterfaceName()57   const AtomicString& InterfaceName() const override {
58     return event_target_names::kFontFaceSet;
59   }
60 
61   FontFaceSet* addForBinding(ScriptState*, FontFace*, ExceptionState&);
62   void clearForBinding(ScriptState*, ExceptionState&);
63   bool deleteForBinding(ScriptState*, FontFace*, ExceptionState&);
64   bool hasForBinding(ScriptState*, FontFace*, ExceptionState&) const;
65 
66   void AddFontFacesToFontFaceCache(FontFaceCache*);
67 
68   wtf_size_t size() const;
69   virtual AtomicString status() const = 0;
70 
71   void Trace(Visitor*) override;
72 
73  protected:
74   static const int kDefaultFontSize;
75   static const char kDefaultFontFamily[];
76 
77   virtual bool ResolveFontStyle(const String&, Font&) = 0;
78   virtual bool InActiveContext() const = 0;
79   virtual FontSelector* GetFontSelector() const = 0;
80   virtual const HeapLinkedHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
81       const = 0;
IsCSSConnectedFontFace(FontFace * font_face)82   bool IsCSSConnectedFontFace(FontFace* font_face) const {
83     return CSSConnectedFontFaceList().Contains(font_face);
84   }
85 
86   virtual void FireDoneEventIfPossible() = 0;
87 
88   void AddToLoadingFonts(FontFace*);
89   void RemoveFromLoadingFonts(FontFace*);
90   void HandlePendingEventsAndPromisesSoon();
91   bool ShouldSignalReady() const;
92   void FireDoneEvent();
93 
94   using ReadyProperty = ScriptPromiseProperty<Member<FontFaceSet>,
95                                               Member<DOMException>>;
96 
97   bool is_loading_ = false;
98   bool should_fire_loading_event_ = false;
99   bool pending_task_queued_ = false;
100   HeapLinkedHashSet<Member<FontFace>> non_css_connected_faces_;
101   HeapHashSet<Member<FontFace>> loading_fonts_;
102   FontFaceArray loaded_fonts_;
103   FontFaceArray failed_fonts_;
104   Member<ReadyProperty> ready_;
105 
106   class IterationSource final : public FontFaceSetIterable::IterationSource {
107    public:
IterationSource(const HeapVector<Member<FontFace>> & font_faces)108     explicit IterationSource(const HeapVector<Member<FontFace>>& font_faces)
109         : index_(0), font_faces_(font_faces) {}
110     bool Next(ScriptState*,
111               Member<FontFace>&,
112               Member<FontFace>&,
113               ExceptionState&) override;
114 
Trace(Visitor * visitor)115     void Trace(Visitor* visitor) override {
116       visitor->Trace(font_faces_);
117       FontFaceSetIterable::IterationSource::Trace(visitor);
118     }
119 
120    private:
121     wtf_size_t index_;
122     HeapVector<Member<FontFace>> font_faces_;
123   };
124 
125   class LoadFontPromiseResolver final
126       : public GarbageCollected<LoadFontPromiseResolver>,
127         public FontFace::LoadFontCallback {
128     USING_GARBAGE_COLLECTED_MIXIN(LoadFontPromiseResolver);
129 
130    public:
LoadFontPromiseResolver(FontFaceArray faces,ScriptState * script_state)131     LoadFontPromiseResolver(FontFaceArray faces, ScriptState* script_state)
132         : num_loading_(faces.size()),
133           error_occured_(false),
134           resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {
135       font_faces_.swap(faces);
136     }
137 
138     void LoadFonts();
Promise()139     ScriptPromise Promise() { return resolver_->Promise(); }
140 
141     void NotifyLoaded(FontFace*) override;
142     void NotifyError(FontFace*) override;
143 
144     void Trace(Visitor*) override;
145 
146    private:
147     HeapVector<Member<FontFace>> font_faces_;
148     int num_loading_;
149     bool error_occured_;
150     Member<ScriptPromiseResolver> resolver_;
151   };
152 
153  private:
154   FontFaceSetIterable::IterationSource* StartIteration(
155       ScriptState*,
156       ExceptionState&) override;
157 
158   void HandlePendingEventsAndPromises();
159   void FireLoadingEvent();
160   DISALLOW_COPY_AND_ASSIGN(FontFaceSet);
161 };
162 
163 }  // namespace blink
164 
165 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_FONT_FACE_SET_H_
166