OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are met: | 5 * modification, are permitted provided that the following conditions are met: |
6 * | 6 * |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND |
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE | 16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE |
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
23 * DAMAGE. | 23 * DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/css/FontFaceSet.h" | 27 #include "core/css/FontFaceSet.h" |
28 | 28 |
29 #include "RuntimeEnabledFeatures.h" | 29 #include "RuntimeEnabledFeatures.h" |
| 30 #include "V8FontFaceSet.h" |
30 #include "bindings/v8/Dictionary.h" | 31 #include "bindings/v8/Dictionary.h" |
| 32 #include "bindings/v8/ScriptPromiseResolver.h" |
| 33 #include "bindings/v8/ScriptScope.h" |
| 34 #include "bindings/v8/ScriptState.h" |
31 #include "core/css/CSSFontFaceLoadEvent.h" | 35 #include "core/css/CSSFontFaceLoadEvent.h" |
32 #include "core/css/CSSFontFaceSource.h" | 36 #include "core/css/CSSFontFaceSource.h" |
33 #include "core/css/CSSFontSelector.h" | 37 #include "core/css/CSSFontSelector.h" |
34 #include "core/css/CSSParser.h" | 38 #include "core/css/CSSParser.h" |
35 #include "core/css/CSSSegmentedFontFace.h" | 39 #include "core/css/CSSSegmentedFontFace.h" |
36 #include "core/css/StylePropertySet.h" | 40 #include "core/css/StylePropertySet.h" |
37 #include "core/css/resolver/StyleResolver.h" | 41 #include "core/css/resolver/StyleResolver.h" |
38 #include "core/dom/Document.h" | 42 #include "core/dom/Document.h" |
39 #include "core/page/FrameView.h" | 43 #include "core/page/FrameView.h" |
40 #include "core/platform/HistogramSupport.h" | 44 #include "core/platform/HistogramSupport.h" |
41 | 45 |
42 namespace WebCore { | 46 namespace WebCore { |
43 | 47 |
44 static const int defaultFontSize = 10; | 48 static const int defaultFontSize = 10; |
45 static const char* const defaultFontFamily = "sans-serif"; | 49 static const char* const defaultFontFamily = "sans-serif"; |
46 | 50 |
47 class LoadFontCallback : public CSSSegmentedFontFace::LoadFontCallback { | 51 class LoadFontPromiseResolver : public CSSSegmentedFontFace::LoadFontCallback { |
48 public: | 52 public: |
49 static PassRefPtr<LoadFontCallback> create(int numLoading, PassRefPtr<VoidCa
llback> loadCallback, PassRefPtr<VoidCallback> errorCallback) | 53 static PassRefPtr<LoadFontPromiseResolver> create(const FontFamily& family,
ScriptExecutionContext* context) |
50 { | 54 { |
51 return adoptRef<LoadFontCallback>(new LoadFontCallback(numLoading, loadC
allback, errorCallback)); | |
52 } | |
53 | |
54 static PassRefPtr<LoadFontCallback> createFromParams(const Dictionary& param
s, const FontFamily& family) | |
55 { | |
56 RefPtr<VoidCallback> onsuccess; | |
57 RefPtr<VoidCallback> onerror; | |
58 params.get("onsuccess", onsuccess); | |
59 params.get("onerror", onerror); | |
60 if (!onsuccess && !onerror) | |
61 return 0; | |
62 int numFamilies = 0; | 55 int numFamilies = 0; |
63 for (const FontFamily* f = &family; f; f = f->next()) | 56 for (const FontFamily* f = &family; f; f = f->next()) |
64 numFamilies++; | 57 numFamilies++; |
65 return LoadFontCallback::create(numFamilies, onsuccess, onerror); | 58 return adoptRef<LoadFontPromiseResolver>(new LoadFontPromiseResolver(num
Families, context)); |
66 } | 59 } |
67 | 60 |
68 virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE; | 61 virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE; |
69 virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE; | 62 virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE; |
70 void loaded(Document*); | 63 void loaded(Document*); |
71 void error(Document*); | 64 void error(Document*); |
| 65 void resolve(); |
| 66 |
| 67 ScriptPromise promise() |
| 68 { |
| 69 ScriptPromise promise = m_resolver->promise(); |
| 70 m_resolver->detachPromise(); |
| 71 return promise; |
| 72 } |
| 73 |
72 private: | 74 private: |
73 LoadFontCallback(int numLoading, PassRefPtr<VoidCallback> loadCallback, Pass
RefPtr<VoidCallback> errorCallback) | 75 LoadFontPromiseResolver(int numLoading, ScriptExecutionContext* context) |
74 : m_numLoading(numLoading) | 76 : m_numLoading(numLoading) |
75 , m_errorOccured(false) | 77 , m_errorOccured(false) |
76 , m_loadCallback(loadCallback) | 78 , m_scriptState(ScriptState::current()) |
77 , m_errorCallback(errorCallback) | 79 , m_resolver(ScriptPromiseResolver::create(context)) |
78 { } | 80 { } |
79 | 81 |
80 int m_numLoading; | 82 int m_numLoading; |
81 bool m_errorOccured; | 83 bool m_errorOccured; |
82 RefPtr<VoidCallback> m_loadCallback; | 84 ScriptState* m_scriptState; |
83 RefPtr<VoidCallback> m_errorCallback; | 85 RefPtr<ScriptPromiseResolver> m_resolver; |
84 }; | 86 }; |
85 | 87 |
86 void LoadFontCallback::loaded(Document* document) | 88 void LoadFontPromiseResolver::loaded(Document* document) |
87 { | 89 { |
88 m_numLoading--; | 90 m_numLoading--; |
89 if (m_numLoading || !document) | 91 if (m_numLoading || !document) |
90 return; | 92 return; |
91 | 93 |
92 if (m_errorOccured) { | 94 document->fonts()->scheduleResolve(this); |
93 if (m_errorCallback) | |
94 document->fonts()->scheduleCallback(m_errorCallback.release()); | |
95 } else { | |
96 if (m_loadCallback) | |
97 document->fonts()->scheduleCallback(m_loadCallback.release()); | |
98 } | |
99 } | 95 } |
100 | 96 |
101 void LoadFontCallback::error(Document* document) | 97 void LoadFontPromiseResolver::error(Document* document) |
102 { | 98 { |
103 m_errorOccured = true; | 99 m_errorOccured = true; |
104 loaded(document); | 100 loaded(document); |
105 } | 101 } |
106 | 102 |
107 void LoadFontCallback::notifyLoaded(CSSSegmentedFontFace* face) | 103 void LoadFontPromiseResolver::notifyLoaded(CSSSegmentedFontFace* face) |
108 { | 104 { |
109 loaded(face->fontSelector()->document()); | 105 loaded(face->fontSelector()->document()); |
110 } | 106 } |
111 | 107 |
112 void LoadFontCallback::notifyError(CSSSegmentedFontFace* face) | 108 void LoadFontPromiseResolver::notifyError(CSSSegmentedFontFace* face) |
113 { | 109 { |
114 error(face->fontSelector()->document()); | 110 error(face->fontSelector()->document()); |
115 } | 111 } |
116 | 112 |
| 113 void LoadFontPromiseResolver::resolve() |
| 114 { |
| 115 ScriptScope scope(m_scriptState); |
| 116 if (m_errorOccured) |
| 117 m_resolver->reject(ScriptValue::createNull()); |
| 118 else |
| 119 m_resolver->fulfill(ScriptValue::createNull()); |
| 120 } |
| 121 |
| 122 class FontsReadyPromiseResolver { |
| 123 public: |
| 124 static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptExecutionContext*
context) |
| 125 { |
| 126 return adoptPtr(new FontsReadyPromiseResolver(context)); |
| 127 } |
| 128 |
| 129 void call(PassRefPtr<FontFaceSet> fontFaceSet) |
| 130 { |
| 131 ScriptScope scope(m_scriptState); |
| 132 m_resolver->fulfill(fontFaceSet); |
| 133 } |
| 134 |
| 135 ScriptPromise promise() |
| 136 { |
| 137 ScriptPromise promise = m_resolver->promise(); |
| 138 m_resolver->detachPromise(); |
| 139 return promise; |
| 140 } |
| 141 |
| 142 private: |
| 143 FontsReadyPromiseResolver(ScriptExecutionContext* context) |
| 144 : m_scriptState(ScriptState::current()) |
| 145 , m_resolver(ScriptPromiseResolver::create(context)) |
| 146 { } |
| 147 ScriptState* m_scriptState; |
| 148 RefPtr<ScriptPromiseResolver> m_resolver; |
| 149 }; |
| 150 |
117 FontFaceSet::FontFaceSet(Document* document) | 151 FontFaceSet::FontFaceSet(Document* document) |
118 : ActiveDOMObject(document) | 152 : ActiveDOMObject(document) |
119 , m_loadingCount(0) | 153 , m_loadingCount(0) |
120 , m_shouldFireDoneEvent(false) | 154 , m_shouldFireDoneEvent(false) |
121 , m_timer(this, &FontFaceSet::timerFired) | 155 , m_timer(this, &FontFaceSet::timerFired) |
122 { | 156 { |
123 suspendIfNeeded(); | 157 suspendIfNeeded(); |
124 } | 158 } |
125 | 159 |
126 FontFaceSet::~FontFaceSet() | 160 FontFaceSet::~FontFaceSet() |
(...skipping 18 matching lines...) Expand all Loading... |
145 const AtomicString& FontFaceSet::interfaceName() const | 179 const AtomicString& FontFaceSet::interfaceName() const |
146 { | 180 { |
147 return eventNames().interfaceForFontFaceSet; | 181 return eventNames().interfaceForFontFaceSet; |
148 } | 182 } |
149 | 183 |
150 ScriptExecutionContext* FontFaceSet::scriptExecutionContext() const | 184 ScriptExecutionContext* FontFaceSet::scriptExecutionContext() const |
151 { | 185 { |
152 return ActiveDOMObject::scriptExecutionContext(); | 186 return ActiveDOMObject::scriptExecutionContext(); |
153 } | 187 } |
154 | 188 |
| 189 AtomicString FontFaceSet::status() const |
| 190 { |
| 191 DEFINE_STATIC_LOCAL(AtomicString, loading, ("loading", AtomicString::Constru
ctFromLiteral)); |
| 192 DEFINE_STATIC_LOCAL(AtomicString, loaded, ("loaded", AtomicString::Construct
FromLiteral)); |
| 193 return (m_loadingCount > 0 || m_shouldFireDoneEvent) ? loading : loaded; |
| 194 } |
| 195 |
155 void FontFaceSet::didLayout() | 196 void FontFaceSet::didLayout() |
156 { | 197 { |
157 Document* d = document(); | 198 Document* d = document(); |
158 if (d->page() && d->page()->mainFrame() == d->frame()) | 199 if (d->page() && d->page()->mainFrame() == d->frame()) |
159 m_histogram.record(); | 200 m_histogram.record(); |
160 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 201 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
161 return; | 202 return; |
162 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp
ty())) | 203 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty())
) |
163 return; | 204 return; |
164 if (!m_timer.isActive()) | 205 if (!m_timer.isActive()) |
165 m_timer.startOneShot(0); | 206 m_timer.startOneShot(0); |
166 } | 207 } |
167 | 208 |
168 void FontFaceSet::timerFired(Timer<FontFaceSet>*) | 209 void FontFaceSet::timerFired(Timer<FontFaceSet>*) |
169 { | 210 { |
170 firePendingEvents(); | 211 firePendingEvents(); |
171 firePendingCallbacks(); | 212 resolvePendingLoadPromises(); |
172 fireDoneEventIfPossible(); | 213 fireDoneEventIfPossible(); |
173 } | 214 } |
174 | 215 |
175 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) | 216 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) |
176 { | 217 { |
177 m_pendingEvents.append(event); | 218 m_pendingEvents.append(event); |
178 if (!m_timer.isActive()) | 219 if (!m_timer.isActive()) |
179 m_timer.startOneShot(0); | 220 m_timer.startOneShot(0); |
180 } | 221 } |
181 | 222 |
182 void FontFaceSet::firePendingEvents() | 223 void FontFaceSet::firePendingEvents() |
183 { | 224 { |
184 if (m_pendingEvents.isEmpty()) | 225 if (m_pendingEvents.isEmpty()) |
185 return; | 226 return; |
186 | 227 |
187 Vector<RefPtr<Event> > pendingEvents; | 228 Vector<RefPtr<Event> > pendingEvents; |
188 m_pendingEvents.swap(pendingEvents); | 229 m_pendingEvents.swap(pendingEvents); |
189 for (size_t index = 0; index < pendingEvents.size(); ++index) | 230 for (size_t index = 0; index < pendingEvents.size(); ++index) |
190 dispatchEvent(pendingEvents[index].release()); | 231 dispatchEvent(pendingEvents[index].release()); |
191 } | 232 } |
192 | 233 |
193 void FontFaceSet::scheduleCallback(PassRefPtr<VoidCallback> callback) | 234 void FontFaceSet::scheduleResolve(LoadFontPromiseResolver* resolver) |
194 { | 235 { |
195 m_pendingCallbacks.append(callback); | 236 m_pendingLoadResolvers.append(resolver); |
196 if (!m_timer.isActive()) | 237 if (!m_timer.isActive()) |
197 m_timer.startOneShot(0); | 238 m_timer.startOneShot(0); |
198 } | 239 } |
199 | 240 |
200 void FontFaceSet::firePendingCallbacks() | 241 void FontFaceSet::resolvePendingLoadPromises() |
201 { | 242 { |
202 if (m_pendingCallbacks.isEmpty()) | 243 if (m_pendingLoadResolvers.isEmpty()) |
203 return; | 244 return; |
204 | 245 |
205 Vector<RefPtr<VoidCallback> > pendingCallbacks; | 246 Vector<RefPtr<LoadFontPromiseResolver> > resolvers; |
206 m_pendingCallbacks.swap(pendingCallbacks); | 247 m_pendingLoadResolvers.swap(resolvers); |
207 for (size_t index = 0; index < pendingCallbacks.size(); ++index) | 248 for (size_t index = 0; index < resolvers.size(); ++index) |
208 pendingCallbacks[index]->handleEvent(); | 249 resolvers[index]->resolve(); |
209 } | 250 } |
210 | 251 |
211 void FontFaceSet::beginFontLoading(FontFace* fontFace) | 252 void FontFaceSet::beginFontLoading(FontFace* fontFace) |
212 { | 253 { |
213 m_histogram.incrementCount(); | 254 m_histogram.incrementCount(); |
214 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 255 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
215 return; | 256 return; |
216 | 257 |
217 ++m_loadingCount; | 258 ++m_loadingCount; |
218 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) | 259 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) |
(...skipping 22 matching lines...) Expand all Loading... |
241 ASSERT(m_loadingCount > 0); | 282 ASSERT(m_loadingCount > 0); |
242 --m_loadingCount; | 283 --m_loadingCount; |
243 if (!m_loadingCount) { | 284 if (!m_loadingCount) { |
244 ASSERT(!m_shouldFireDoneEvent); | 285 ASSERT(!m_shouldFireDoneEvent); |
245 m_shouldFireDoneEvent = true; | 286 m_shouldFireDoneEvent = true; |
246 if (!m_timer.isActive()) | 287 if (!m_timer.isActive()) |
247 m_timer.startOneShot(0); | 288 m_timer.startOneShot(0); |
248 } | 289 } |
249 } | 290 } |
250 | 291 |
251 void FontFaceSet::notifyWhenFontsReady(PassRefPtr<VoidCallback> callback) | 292 ScriptPromise FontFaceSet::ready() |
252 { | 293 { |
253 m_fontsReadyCallbacks.append(callback); | 294 OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::crea
te(scriptExecutionContext()); |
| 295 ScriptPromise promise = resolver->promise(); |
| 296 m_readyResolvers.append(resolver.release()); |
254 if (!m_timer.isActive()) | 297 if (!m_timer.isActive()) |
255 m_timer.startOneShot(0); | 298 m_timer.startOneShot(0); |
| 299 return promise; |
256 } | 300 } |
257 | 301 |
258 void FontFaceSet::fireDoneEventIfPossible() | 302 void FontFaceSet::fireDoneEventIfPossible() |
259 { | 303 { |
260 if (!m_pendingEvents.isEmpty() || !m_pendingCallbacks.isEmpty()) | 304 if (!m_pendingEvents.isEmpty() || !m_pendingLoadResolvers.isEmpty()) |
261 return; | 305 return; |
262 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp
ty())) | 306 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty())
) |
263 return; | 307 return; |
264 | 308 |
265 // If the layout was invalidated in between when we thought layout | 309 // If the layout was invalidated in between when we thought layout |
266 // was updated and when we're ready to fire the event, just wait | 310 // was updated and when we're ready to fire the event, just wait |
267 // until after the next layout before firing events. | 311 // until after the next layout before firing events. |
268 Document* d = document(); | 312 Document* d = document(); |
269 if (!d->view() || d->view()->needsLayout()) | 313 if (!d->view() || d->view()->needsLayout()) |
270 return; | 314 return; |
271 | 315 |
272 if (m_shouldFireDoneEvent) { | 316 if (m_shouldFireDoneEvent) { |
273 m_shouldFireDoneEvent = false; | 317 m_shouldFireDoneEvent = false; |
274 RefPtr<CSSFontFaceLoadEvent> doneEvent; | 318 RefPtr<CSSFontFaceLoadEvent> doneEvent; |
275 RefPtr<CSSFontFaceLoadEvent> errorEvent; | 319 RefPtr<CSSFontFaceLoadEvent> errorEvent; |
276 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin
gdoneEvent, m_loadedFonts); | 320 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin
gdoneEvent, m_loadedFonts); |
277 m_loadedFonts.clear(); | 321 m_loadedFonts.clear(); |
278 if (!m_failedFonts.isEmpty()) { | 322 if (!m_failedFonts.isEmpty()) { |
279 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l
oadingerrorEvent, m_failedFonts); | 323 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l
oadingerrorEvent, m_failedFonts); |
280 m_failedFonts.clear(); | 324 m_failedFonts.clear(); |
281 } | 325 } |
282 dispatchEvent(doneEvent); | 326 dispatchEvent(doneEvent); |
283 if (errorEvent) | 327 if (errorEvent) |
284 dispatchEvent(errorEvent); | 328 dispatchEvent(errorEvent); |
285 } | 329 } |
286 | 330 |
287 if (!m_fontsReadyCallbacks.isEmpty()) { | 331 if (!m_readyResolvers.isEmpty()) { |
288 Vector<RefPtr<VoidCallback> > callbacks; | 332 Vector<OwnPtr<FontsReadyPromiseResolver> > resolvers; |
289 m_fontsReadyCallbacks.swap(callbacks); | 333 m_readyResolvers.swap(resolvers); |
290 for (size_t index = 0; index < callbacks.size(); ++index) | 334 for (size_t index = 0; index < resolvers.size(); ++index) |
291 callbacks[index]->handleEvent(); | 335 resolvers[index]->call(this); |
292 } | 336 } |
293 } | 337 } |
294 | 338 |
295 void FontFaceSet::loadFont(const Dictionary& params) | 339 Vector<RefPtr<FontFace> > FontFaceSet::match(const String& fontString, const Str
ing&, ExceptionState& es) |
296 { | 340 { |
297 // FIXME: The text member of params is ignored. | 341 // FIXME: The second parameter (text) is ignored. |
298 String fontString; | 342 Vector<RefPtr<FontFace> > matchedFonts; |
299 if (!params.get("font", fontString)) | 343 |
300 return; | |
301 Font font; | 344 Font font; |
302 if (!resolveFontStyle(fontString, font)) | 345 if (!resolveFontStyle(fontString, font)) { |
303 return; | 346 es.throwDOMException(SyntaxError); |
304 RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(param
s, font.family()); | 347 return matchedFonts; |
| 348 } |
305 | 349 |
306 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 350 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
307 Document* d = document(); | 351 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); |
308 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont
Face(font.fontDescription(), f->family()); | 352 if (face) |
309 if (!face) { | 353 matchedFonts.append(face->fontFaces()); |
310 if (callback) | |
311 callback->error(d); | |
312 continue; | |
313 } | |
314 face->loadFont(font.fontDescription(), callback); | |
315 } | 354 } |
| 355 return matchedFonts; |
316 } | 356 } |
317 | 357 |
318 bool FontFaceSet::checkFont(const String& fontString, const String&) | 358 ScriptPromise FontFaceSet::load(const String& fontString, const String&, Excepti
onState& es) |
319 { | 359 { |
320 // FIXME: The second parameter (text) is ignored. | 360 // FIXME: The second parameter (text) is ignored. |
321 Font font; | 361 Font font; |
322 if (!resolveFontStyle(fontString, font)) | 362 if (!resolveFontStyle(fontString, font)) { |
| 363 es.throwDOMException(SyntaxError); |
| 364 return ScriptPromise(); |
| 365 } |
| 366 |
| 367 Document* d = document(); |
| 368 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f
ont.family(), scriptExecutionContext()); |
| 369 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 370 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont
Face(font.fontDescription(), f->family()); |
| 371 if (!face) { |
| 372 resolver->error(d); |
| 373 continue; |
| 374 } |
| 375 face->loadFont(font.fontDescription(), resolver); |
| 376 } |
| 377 return resolver->promise(); |
| 378 } |
| 379 |
| 380 bool FontFaceSet::check(const String& fontString, const String&, ExceptionState&
es) |
| 381 { |
| 382 // FIXME: The second parameter (text) is ignored. |
| 383 Font font; |
| 384 if (!resolveFontStyle(fontString, font)) { |
| 385 es.throwDOMException(SyntaxError); |
323 return false; | 386 return false; |
| 387 } |
| 388 |
324 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 389 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
325 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); | 390 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); |
326 if (!face || !face->checkFont()) | 391 if (!face || !face->checkFont()) |
327 return false; | 392 return false; |
328 } | 393 } |
329 return true; | 394 return true; |
330 } | 395 } |
331 | 396 |
332 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) | 397 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) |
333 { | 398 { |
| 399 if (fontString.isEmpty()) |
| 400 return false; |
| 401 |
334 // Interpret fontString in the same way as the 'font' attribute of CanvasRen
deringContext2D. | 402 // Interpret fontString in the same way as the 'font' attribute of CanvasRen
deringContext2D. |
335 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat
e(); | 403 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat
e(); |
336 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true,
CSSStrictMode, 0); | 404 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true,
CSSStrictMode, 0); |
337 if (parsedStyle->isEmpty()) | 405 if (parsedStyle->isEmpty()) |
338 return false; | 406 return false; |
339 | 407 |
340 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); | 408 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); |
341 if (fontValue == "inherit" || fontValue == "initial") | 409 if (fontValue == "inherit" || fontValue == "initial") |
342 return false; | 410 return false; |
343 | 411 |
(...skipping 30 matching lines...) Expand all Loading... |
374 | 442 |
375 void FontFaceSet::FontLoadHistogram::record() | 443 void FontFaceSet::FontLoadHistogram::record() |
376 { | 444 { |
377 if (m_recorded) | 445 if (m_recorded) |
378 return; | 446 return; |
379 m_recorded = true; | 447 m_recorded = true; |
380 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1
, 100, 50); | 448 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1
, 100, 50); |
381 } | 449 } |
382 | 450 |
383 } // namespace WebCore | 451 } // namespace WebCore |
OLD | NEW |