1/*
2 * Copyright (C) 2007, 2008, 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 "FontSelectionValueInlines.h"
29#include "FontTaggedSettings.h"
30#include "StyleRule.h"
31#include "TextFlags.h"
32#include "Timer.h"
33#include <memory>
34#include <wtf/Forward.h>
35#include <wtf/HashSet.h>
36#include <wtf/RefCounted.h>
37#include <wtf/Vector.h>
38#include <wtf/WeakPtr.h>
39
40namespace JSC {
41class ExecState;
42}
43
44namespace WebCore {
45
46class CSSFontFaceSource;
47class CSSFontSelector;
48class CSSSegmentedFontFace;
49class CSSValue;
50class CSSValueList;
51class Document;
52class FontDescription;
53class Font;
54class FontFace;
55enum class ExternalResourceDownloadPolicy;
56
57class CSSFontFace final : public RefCounted<CSSFontFace> {
58public:
59 static Ref<CSSFontFace> create(CSSFontSelector* fontSelector, StyleRuleFontFace* cssConnection = nullptr, FontFace* wrapper = nullptr, bool isLocalFallback = false)
60 {
61 return adoptRef(*new CSSFontFace(fontSelector, cssConnection, wrapper, isLocalFallback));
62 }
63 virtual ~CSSFontFace();
64
65 // FIXME: These functions don't need to have boolean return values.
66 // Callers only call this with known-valid CSS values.
67 bool setFamilies(CSSValue&);
68 void setStyle(CSSValue&);
69 void setWeight(CSSValue&);
70 void setStretch(CSSValue&);
71 bool setUnicodeRange(CSSValue&);
72 bool setVariantLigatures(CSSValue&);
73 bool setVariantPosition(CSSValue&);
74 bool setVariantCaps(CSSValue&);
75 bool setVariantNumeric(CSSValue&);
76 bool setVariantAlternates(CSSValue&);
77 bool setVariantEastAsian(CSSValue&);
78 void setFeatureSettings(CSSValue&);
79 void setLoadingBehavior(CSSValue&);
80
81 enum class Status : uint8_t;
82 struct UnicodeRange;
83 const CSSValueList* families() const { return m_families.get(); }
84 FontSelectionRange weight() const { return m_fontSelectionCapabilities.computeWeight(); }
85 FontSelectionRange stretch() const { return m_fontSelectionCapabilities.computeWidth(); }
86 FontSelectionRange italic() const { return m_fontSelectionCapabilities.computeSlope(); }
87 FontSelectionCapabilities fontSelectionCapabilities() const { return m_fontSelectionCapabilities.computeFontSelectionCapabilities(); }
88 const Vector<UnicodeRange>& ranges() const { return m_ranges; }
89 const FontFeatureSettings& featureSettings() const { return m_featureSettings; }
90 const FontVariantSettings& variantSettings() const { return m_variantSettings; }
91 FontLoadingBehavior loadingBehavior() const { return m_loadingBehavior; }
92 void setVariantSettings(const FontVariantSettings& variantSettings) { m_variantSettings = variantSettings; }
93 void setWeight(FontSelectionRange weight) { m_fontSelectionCapabilities.weight = weight; }
94 void setStretch(FontSelectionRange stretch) { m_fontSelectionCapabilities.width = stretch; }
95 void setStyle(FontSelectionRange italic) { m_fontSelectionCapabilities.slope = italic; }
96 void setFontSelectionCapabilities(FontSelectionCapabilities capabilities) { m_fontSelectionCapabilities = capabilities; }
97 bool isLocalFallback() const { return m_isLocalFallback; }
98 Status status() const { return m_status; }
99 StyleRuleFontFace* cssConnection() const { return m_cssConnection.get(); }
100
101 class Client;
102 void addClient(Client&);
103 void removeClient(Client&);
104
105 bool computeFailureState() const;
106
107 void opportunisticallyStartFontDataURLLoading(CSSFontSelector&);
108
109 void adoptSource(std::unique_ptr<CSSFontFaceSource>&&);
110 void sourcesPopulated() { m_sourcesPopulated = true; }
111
112 void fontLoaded(CSSFontFaceSource&);
113
114 void load();
115
116 RefPtr<Font> font(const FontDescription&, bool syntheticBold, bool syntheticItalic, ExternalResourceDownloadPolicy);
117
118 static void appendSources(CSSFontFace&, CSSValueList&, Document*, bool isInitiatingElementInUserAgentShadowTree);
119
120 class Client {
121 public:
122 virtual ~Client() = default;
123 virtual void fontLoaded(CSSFontFace&) { }
124 virtual void fontStateChanged(CSSFontFace&, Status /*oldState*/, Status /*newState*/) { }
125 virtual void fontPropertyChanged(CSSFontFace&, CSSValueList* /*oldFamilies*/ = nullptr) { }
126 virtual void ref() = 0;
127 virtual void deref() = 0;
128 };
129
130 // Pending => Loading => TimedOut
131 // || \\ // ||
132 // || \\ // ||
133 // || \\// ||
134 // || // ||
135 // || //\\ ||
136 // || // \\ ||
137 // \/ \/ \/ \/
138 // Success Failure
139 enum class Status : uint8_t { Pending, Loading, TimedOut, Success, Failure };
140
141 struct UnicodeRange {
142 UChar32 from;
143 UChar32 to;
144 bool operator==(const UnicodeRange& other) const { return from == other.from && to == other.to; }
145 bool operator!=(const UnicodeRange& other) const { return !(*this == other); }
146 };
147
148 bool rangesMatchCodePoint(UChar32) const;
149
150 // We don't guarantee that the FontFace wrapper will be the same every time you ask for it.
151 Ref<FontFace> wrapper();
152 void setWrapper(FontFace&);
153 FontFace* existingWrapper() { return m_wrapper.get(); }
154
155 struct FontLoadTiming {
156 Seconds blockPeriod;
157 Seconds swapPeriod;
158 };
159 FontLoadTiming fontLoadTiming() const;
160 bool shouldIgnoreFontLoadCompletions() const;
161
162 bool purgeable() const;
163
164 AllowUserInstalledFonts allowUserInstalledFonts() const;
165
166 void updateStyleIfNeeded();
167
168#if ENABLE(SVG_FONTS)
169 bool hasSVGFontFaceSource() const;
170#endif
171
172private:
173 CSSFontFace(CSSFontSelector*, StyleRuleFontFace*, FontFace*, bool isLocalFallback);
174
175 size_t pump(ExternalResourceDownloadPolicy);
176 void setStatus(Status);
177 void notifyClientsOfFontPropertyChange();
178
179 void initializeWrapper();
180
181 void fontLoadEventOccurred();
182 void timeoutFired();
183
184 RefPtr<CSSValueList> m_families;
185 Vector<UnicodeRange> m_ranges;
186
187 FontFeatureSettings m_featureSettings;
188 FontVariantSettings m_variantSettings;
189 FontLoadingBehavior m_loadingBehavior { FontLoadingBehavior::Auto };
190
191 Vector<std::unique_ptr<CSSFontFaceSource>, 0, CrashOnOverflow, 0> m_sources;
192 RefPtr<CSSFontSelector> m_fontSelector; // FIXME: https://bugs.webkit.org/show_bug.cgi?id=196437 There's a retain cycle: CSSFontSelector -> CSSFontFaceSet -> CSSFontFace -> CSSFontSelector
193 RefPtr<StyleRuleFontFace> m_cssConnection;
194 HashSet<Client*> m_clients;
195 WeakPtr<FontFace> m_wrapper;
196 FontSelectionSpecifiedCapabilities m_fontSelectionCapabilities;
197
198 Status m_status { Status::Pending };
199 bool m_isLocalFallback { false };
200 bool m_sourcesPopulated { false };
201 bool m_mayBePurged { true };
202
203 Timer m_timeoutTimer;
204};
205
206}
207