c57b21165d730b71a03d0aa8179d9060fdbb386e
[WebKit-https.git] / Source / WebCore / css / FontFaceSet.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "ActiveDOMObject.h"
29 #include "CSSFontFaceSet.h"
30 #include "DOMPromiseProxy.h"
31 #include "EventTarget.h"
32 #include "JSDOMPromiseDeferred.h"
33 #include "SuspendableTaskQueue.h"
34
35 namespace WebCore {
36
37 class DOMException;
38
39 class FontFaceSet final : public RefCounted<FontFaceSet>, private CSSFontFaceSetClient, public EventTargetWithInlineData, private  ActiveDOMObject {
40     WTF_MAKE_ISO_ALLOCATED(FontFaceSet);
41 public:
42     static Ref<FontFaceSet> create(Document&, const Vector<RefPtr<FontFace>>& initialFaces);
43     static Ref<FontFaceSet> create(Document&, CSSFontFaceSet& backing);
44     virtual ~FontFaceSet();
45
46     bool has(FontFace&) const;
47     size_t size() const;
48     FontFaceSet& add(FontFace&);
49     bool remove(FontFace&);
50     void clear();
51
52     using LoadPromise = DOMPromiseDeferred<IDLSequence<IDLInterface<FontFace>>>;
53     void load(const String& font, const String& text, LoadPromise&&);
54     ExceptionOr<bool> check(const String& font, const String& text);
55
56     enum class LoadStatus { Loading, Loaded };
57     LoadStatus status() const;
58
59     using ReadyPromise = DOMPromiseProxyWithResolveCallback<IDLInterface<FontFaceSet>>;
60     ReadyPromise& ready() { return m_readyPromise; }
61     void didFirstLayout();
62
63     CSSFontFaceSet& backing() { return m_backing; }
64
65     class Iterator {
66     public:
67         explicit Iterator(FontFaceSet&);
68         RefPtr<FontFace> next();
69
70     private:
71         Ref<FontFaceSet> m_target;
72         size_t m_index { 0 }; // FIXME: There needs to be a mechanism to handle when fonts are added or removed from the middle of the FontFaceSet.
73     };
74     Iterator createIterator() { return Iterator(*this); }
75
76     using RefCounted::ref;
77     using RefCounted::deref;
78
79 private:
80     struct PendingPromise : RefCounted<PendingPromise> {
81         static Ref<PendingPromise> create(LoadPromise&& promise)
82         {
83             return adoptRef(*new PendingPromise(WTFMove(promise)));
84         }
85         ~PendingPromise();
86
87     private:
88         PendingPromise(LoadPromise&&);
89
90     public:
91         Vector<Ref<FontFace>> faces;
92         LoadPromise promise;
93         bool hasReachedTerminalState { false };
94     };
95
96     FontFaceSet(Document&, const Vector<RefPtr<FontFace>>&);
97     FontFaceSet(Document&, CSSFontFaceSet&);
98
99     // CSSFontFaceSetClient
100     void startedLoading() final;
101     void completedLoading() final;
102     void faceFinished(CSSFontFace&, CSSFontFace::Status) final;
103
104     // ActiveDOMObject
105     const char* activeDOMObjectName() const final { return "FontFaceSet"; }
106     bool canSuspendForDocumentSuspension() const final;
107
108     // EventTarget
109     EventTargetInterface eventTargetInterface() const final { return FontFaceSetEventTargetInterfaceType; }
110     ScriptExecutionContext* scriptExecutionContext() const final { return ActiveDOMObject::scriptExecutionContext(); }
111     void refEventTarget() final { ref(); }
112     void derefEventTarget() final { deref(); }
113
114     // Callback for ReadyPromise.
115     FontFaceSet& readyPromiseResolve();
116
117     Ref<CSSFontFaceSet> m_backing;
118     HashMap<RefPtr<FontFace>, Vector<Ref<PendingPromise>>> m_pendingPromises;
119     ReadyPromise m_readyPromise;
120     UniqueRef<SuspendableTaskQueue> m_taskQueue;
121     bool m_isFirstLayoutDone { true };
122 };
123
124 }