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 "sky/engine/config.h" | 26 #include "sky/engine/config.h" |
27 #include "sky/engine/core/css/FontFaceSet.h" | 27 #include "sky/engine/core/css/FontFaceSet.h" |
28 | 28 |
29 #include "sky/engine/bindings/core/v8/Dictionary.h" | |
30 #include "sky/engine/bindings/core/v8/ScriptPromiseResolver.h" | |
31 #include "sky/engine/bindings/core/v8/ScriptState.h" | |
32 #include "sky/engine/core/css/CSSFontSelector.h" | 29 #include "sky/engine/core/css/CSSFontSelector.h" |
33 #include "sky/engine/core/css/CSSSegmentedFontFace.h" | 30 #include "sky/engine/core/css/CSSSegmentedFontFace.h" |
34 #include "sky/engine/core/css/FontFaceCache.h" | 31 #include "sky/engine/core/css/FontFaceCache.h" |
35 #include "sky/engine/core/css/FontFaceSetLoadEvent.h" | 32 #include "sky/engine/core/css/FontFaceSetLoadEvent.h" |
36 #include "sky/engine/core/css/StylePropertySet.h" | 33 #include "sky/engine/core/css/StylePropertySet.h" |
37 #include "sky/engine/core/css/parser/BisonCSSParser.h" | 34 #include "sky/engine/core/css/parser/BisonCSSParser.h" |
38 #include "sky/engine/core/css/resolver/StyleResolver.h" | 35 #include "sky/engine/core/css/resolver/StyleResolver.h" |
39 #include "sky/engine/core/dom/Document.h" | 36 #include "sky/engine/core/dom/Document.h" |
40 #include "sky/engine/core/dom/StyleEngine.h" | 37 #include "sky/engine/core/dom/StyleEngine.h" |
41 #include "sky/engine/core/frame/FrameView.h" | 38 #include "sky/engine/core/frame/FrameView.h" |
42 #include "sky/engine/core/frame/LocalFrame.h" | 39 #include "sky/engine/core/frame/LocalFrame.h" |
43 #include "sky/engine/core/rendering/style/RenderStyle.h" | 40 #include "sky/engine/core/rendering/style/RenderStyle.h" |
44 #include "sky/engine/core/rendering/style/StyleInheritedData.h" | 41 #include "sky/engine/core/rendering/style/StyleInheritedData.h" |
45 #include "sky/engine/public/platform/Platform.h" | 42 #include "sky/engine/public/platform/Platform.h" |
46 | 43 |
47 namespace blink { | 44 namespace blink { |
48 | 45 |
49 static const int defaultFontSize = 10; | 46 static const int defaultFontSize = 10; |
50 static const char defaultFontFamily[] = "sans-serif"; | 47 static const char defaultFontFamily[] = "sans-serif"; |
51 | 48 |
52 class LoadFontPromiseResolver final : public FontFace::LoadFontCallback { | |
53 public: | |
54 static PassRefPtr<LoadFontPromiseResolver> create(FontFaceArray faces, Scrip
tState* scriptState) | |
55 { | |
56 return adoptRef(new LoadFontPromiseResolver(faces, scriptState)); | |
57 } | |
58 | |
59 void loadFonts(ExecutionContext*); | |
60 ScriptPromise promise() { return m_resolver->promise(); } | |
61 | |
62 virtual void notifyLoaded(FontFace*) override; | |
63 virtual void notifyError(FontFace*) override; | |
64 | |
65 private: | |
66 LoadFontPromiseResolver(FontFaceArray faces, ScriptState* scriptState) | |
67 : m_numLoading(faces.size()) | |
68 , m_errorOccured(false) | |
69 , m_resolver(ScriptPromiseResolver::create(scriptState)) | |
70 { | |
71 m_fontFaces.swap(faces); | |
72 } | |
73 | |
74 Vector<RefPtr<FontFace> > m_fontFaces; | |
75 int m_numLoading; | |
76 bool m_errorOccured; | |
77 RefPtr<ScriptPromiseResolver> m_resolver; | |
78 }; | |
79 | |
80 void LoadFontPromiseResolver::loadFonts(ExecutionContext* context) | |
81 { | |
82 if (!m_numLoading) { | |
83 m_resolver->resolve(m_fontFaces); | |
84 return; | |
85 } | |
86 | |
87 for (size_t i = 0; i < m_fontFaces.size(); i++) | |
88 m_fontFaces[i]->loadWithCallback(this, context); | |
89 } | |
90 | |
91 void LoadFontPromiseResolver::notifyLoaded(FontFace* fontFace) | |
92 { | |
93 m_numLoading--; | |
94 if (m_numLoading || m_errorOccured) | |
95 return; | |
96 | |
97 m_resolver->resolve(m_fontFaces); | |
98 } | |
99 | |
100 void LoadFontPromiseResolver::notifyError(FontFace* fontFace) | |
101 { | |
102 m_numLoading--; | |
103 if (!m_errorOccured) { | |
104 m_errorOccured = true; | |
105 m_resolver->reject(fontFace->error()); | |
106 } | |
107 } | |
108 | |
109 class FontsReadyPromiseResolver { | |
110 public: | |
111 static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptState* scriptState
) | |
112 { | |
113 return adoptPtr(new FontsReadyPromiseResolver(scriptState)); | |
114 } | |
115 | |
116 void resolve(PassRefPtr<FontFaceSet> fontFaceSet) | |
117 { | |
118 m_resolver->resolve(fontFaceSet); | |
119 } | |
120 | |
121 ScriptPromise promise() { return m_resolver->promise(); } | |
122 | |
123 private: | |
124 explicit FontsReadyPromiseResolver(ScriptState* scriptState) | |
125 : m_resolver(ScriptPromiseResolver::create(scriptState)) | |
126 { | |
127 } | |
128 | |
129 RefPtr<ScriptPromiseResolver> m_resolver; | |
130 }; | |
131 | |
132 FontFaceSet::FontFaceSet(Document& document) | 49 FontFaceSet::FontFaceSet(Document& document) |
133 : ActiveDOMObject(&document) | 50 : ActiveDOMObject(&document) |
134 , m_shouldFireLoadingEvent(false) | 51 , m_shouldFireLoadingEvent(false) |
135 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) | 52 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) |
136 { | 53 { |
137 suspendIfNeeded(); | 54 suspendIfNeeded(); |
138 } | 55 } |
139 | 56 |
140 FontFaceSet::~FontFaceSet() | 57 FontFaceSet::~FontFaceSet() |
141 { | 58 { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 void FontFaceSet::handlePendingEventsAndPromisesSoon() | 95 void FontFaceSet::handlePendingEventsAndPromisesSoon() |
179 { | 96 { |
180 // m_asyncRunner will be automatically stopped on destruction. | 97 // m_asyncRunner will be automatically stopped on destruction. |
181 m_asyncRunner.runAsync(); | 98 m_asyncRunner.runAsync(); |
182 } | 99 } |
183 | 100 |
184 void FontFaceSet::didLayout() | 101 void FontFaceSet::didLayout() |
185 { | 102 { |
186 if (m_loadingFonts.isEmpty()) | 103 if (m_loadingFonts.isEmpty()) |
187 m_histogram.record(); | 104 m_histogram.record(); |
188 if (!m_loadingFonts.isEmpty() || (!hasLoadedFonts() && m_readyResolvers.isEm
pty())) | 105 if (!m_loadingFonts.isEmpty() || !hasLoadedFonts()) |
189 return; | 106 return; |
190 handlePendingEventsAndPromisesSoon(); | 107 handlePendingEventsAndPromisesSoon(); |
191 } | 108 } |
192 | 109 |
193 void FontFaceSet::handlePendingEventsAndPromises() | 110 void FontFaceSet::handlePendingEventsAndPromises() |
194 { | 111 { |
195 fireLoadingEvent(); | 112 fireLoadingEvent(); |
196 fireDoneEventIfPossible(); | 113 fireDoneEventIfPossible(); |
197 } | 114 } |
198 | 115 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 m_loadingFonts.add(fontFace); | 165 m_loadingFonts.add(fontFace); |
249 } | 166 } |
250 | 167 |
251 void FontFaceSet::removeFromLoadingFonts(PassRefPtr<FontFace> fontFace) | 168 void FontFaceSet::removeFromLoadingFonts(PassRefPtr<FontFace> fontFace) |
252 { | 169 { |
253 m_loadingFonts.remove(fontFace); | 170 m_loadingFonts.remove(fontFace); |
254 if (m_loadingFonts.isEmpty()) | 171 if (m_loadingFonts.isEmpty()) |
255 handlePendingEventsAndPromisesSoon(); | 172 handlePendingEventsAndPromisesSoon(); |
256 } | 173 } |
257 | 174 |
258 ScriptPromise FontFaceSet::ready(ScriptState* scriptState) | |
259 { | |
260 if (!inActiveDocumentContext()) | |
261 return ScriptPromise(); | |
262 OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::crea
te(scriptState); | |
263 ScriptPromise promise = resolver->promise(); | |
264 m_readyResolvers.append(resolver.release()); | |
265 handlePendingEventsAndPromisesSoon(); | |
266 return promise; | |
267 } | |
268 | |
269 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) | 175 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) |
270 { | 176 { |
271 if (!inActiveDocumentContext()) | 177 if (!inActiveDocumentContext()) |
272 return; | 178 return; |
273 if (!fontFace) { | 179 if (!fontFace) { |
274 exceptionState.throwTypeError("The argument is not a FontFace."); | 180 exceptionState.ThrowTypeError("The argument is not a FontFace."); |
275 return; | 181 return; |
276 } | 182 } |
277 if (m_nonCSSConnectedFaces.contains(fontFace)) | 183 if (m_nonCSSConnectedFaces.contains(fontFace)) |
278 return; | 184 return; |
279 if (isCSSConnectedFontFace(fontFace)) { | 185 if (isCSSConnectedFontFace(fontFace)) { |
280 exceptionState.throwDOMException(InvalidModificationError, "Cannot add a
CSS-connected FontFace."); | 186 exceptionState.ThrowDOMException(InvalidModificationError, "Cannot add a
CSS-connected FontFace."); |
281 return; | 187 return; |
282 } | 188 } |
283 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); | 189 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); |
284 m_nonCSSConnectedFaces.add(fontFace); | 190 m_nonCSSConnectedFaces.add(fontFace); |
285 fontSelector->fontFaceCache()->addFontFace(fontSelector, fontFace, false); | 191 fontSelector->fontFaceCache()->addFontFace(fontSelector, fontFace, false); |
286 if (fontFace->loadStatus() == FontFace::Loading) | 192 if (fontFace->loadStatus() == FontFace::Loading) |
287 addToLoadingFonts(fontFace); | 193 addToLoadingFonts(fontFace); |
288 fontSelector->fontFaceInvalidated(); | 194 fontSelector->fontFaceInvalidated(); |
289 } | 195 } |
290 | 196 |
(...skipping 10 matching lines...) Expand all Loading... |
301 } | 207 } |
302 m_nonCSSConnectedFaces.clear(); | 208 m_nonCSSConnectedFaces.clear(); |
303 fontSelector->fontFaceInvalidated(); | 209 fontSelector->fontFaceInvalidated(); |
304 } | 210 } |
305 | 211 |
306 bool FontFaceSet::remove(FontFace* fontFace, ExceptionState& exceptionState) | 212 bool FontFaceSet::remove(FontFace* fontFace, ExceptionState& exceptionState) |
307 { | 213 { |
308 if (!inActiveDocumentContext()) | 214 if (!inActiveDocumentContext()) |
309 return false; | 215 return false; |
310 if (!fontFace) { | 216 if (!fontFace) { |
311 exceptionState.throwTypeError("The argument is not a FontFace."); | 217 exceptionState.ThrowTypeError("The argument is not a FontFace."); |
312 return false; | 218 return false; |
313 } | 219 } |
314 ListHashSet<RefPtr<FontFace> >::iterator it = m_nonCSSConnectedFaces.find(fo
ntFace); | 220 ListHashSet<RefPtr<FontFace> >::iterator it = m_nonCSSConnectedFaces.find(fo
ntFace); |
315 if (it != m_nonCSSConnectedFaces.end()) { | 221 if (it != m_nonCSSConnectedFaces.end()) { |
316 m_nonCSSConnectedFaces.remove(it); | 222 m_nonCSSConnectedFaces.remove(it); |
317 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(
); | 223 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(
); |
318 fontSelector->fontFaceCache()->removeFontFace(fontFace, false); | 224 fontSelector->fontFaceCache()->removeFontFace(fontFace, false); |
319 if (fontFace->loadStatus() == FontFace::Loading) | 225 if (fontFace->loadStatus() == FontFace::Loading) |
320 removeFromLoadingFonts(fontFace); | 226 removeFromLoadingFonts(fontFace); |
321 fontSelector->fontFaceInvalidated(); | 227 fontSelector->fontFaceInvalidated(); |
322 return true; | 228 return true; |
323 } | 229 } |
324 if (isCSSConnectedFontFace(fontFace)) | 230 if (isCSSConnectedFontFace(fontFace)) |
325 exceptionState.throwDOMException(InvalidModificationError, "Cannot delet
e a CSS-connected FontFace."); | 231 exceptionState.ThrowDOMException(InvalidModificationError, "Cannot delet
e a CSS-connected FontFace."); |
326 return false; | 232 return false; |
327 } | 233 } |
328 | 234 |
329 bool FontFaceSet::has(FontFace* fontFace, ExceptionState& exceptionState) const | 235 bool FontFaceSet::has(FontFace* fontFace, ExceptionState& exceptionState) const |
330 { | 236 { |
331 if (!inActiveDocumentContext()) | 237 if (!inActiveDocumentContext()) |
332 return false; | 238 return false; |
333 if (!fontFace) { | 239 if (!fontFace) { |
334 exceptionState.throwTypeError("The argument is not a FontFace."); | 240 exceptionState.ThrowTypeError("The argument is not a FontFace."); |
335 return false; | 241 return false; |
336 } | 242 } |
337 return m_nonCSSConnectedFaces.contains(fontFace) || isCSSConnectedFontFace(f
ontFace); | 243 return m_nonCSSConnectedFaces.contains(fontFace) || isCSSConnectedFontFace(f
ontFace); |
338 } | 244 } |
339 | 245 |
340 const ListHashSet<RefPtr<FontFace> >& FontFaceSet::cssConnectedFontFaceList() co
nst | 246 const ListHashSet<RefPtr<FontFace> >& FontFaceSet::cssConnectedFontFaceList() co
nst |
341 { | 247 { |
342 Document* d = document(); | 248 Document* d = document(); |
343 return d->styleEngine()->fontSelector()->fontFaceCache()->cssConnectedFontFa
ces(); | 249 return d->styleEngine()->fontSelector()->fontFaceCache()->cssConnectedFontFa
ces(); |
344 } | 250 } |
345 | 251 |
346 bool FontFaceSet::isCSSConnectedFontFace(FontFace* fontFace) const | 252 bool FontFaceSet::isCSSConnectedFontFace(FontFace* fontFace) const |
347 { | 253 { |
348 return cssConnectedFontFaceList().contains(fontFace); | 254 return cssConnectedFontFaceList().contains(fontFace); |
349 } | 255 } |
350 | 256 |
351 void FontFaceSet::forEach(PassOwnPtr<FontFaceSetForEachCallback> callback, const
ScriptValue& thisArg) const | |
352 { | |
353 forEachInternal(callback, &thisArg); | |
354 } | |
355 | |
356 void FontFaceSet::forEach(PassOwnPtr<FontFaceSetForEachCallback> callback) const | |
357 { | |
358 forEachInternal(callback, 0); | |
359 } | |
360 | |
361 void FontFaceSet::forEachInternal(PassOwnPtr<FontFaceSetForEachCallback> callbac
k, const ScriptValue* thisArg) const | |
362 { | |
363 if (!inActiveDocumentContext()) | |
364 return; | |
365 const ListHashSet<RefPtr<FontFace> >& cssConnectedFaces = cssConnectedFontFa
ceList(); | |
366 Vector<RefPtr<FontFace> > fontFaces; | |
367 fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnecte
dFaces.size()); | |
368 for (ListHashSet<RefPtr<FontFace> >::const_iterator it = cssConnectedFaces.b
egin(); it != cssConnectedFaces.end(); ++it) | |
369 fontFaces.append(*it); | |
370 for (ListHashSet<RefPtr<FontFace> >::const_iterator it = m_nonCSSConnectedFa
ces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) | |
371 fontFaces.append(*it); | |
372 | |
373 for (size_t i = 0; i < fontFaces.size(); ++i) { | |
374 FontFace* face = fontFaces[i].get(); | |
375 if (thisArg) | |
376 callback->handleItem(*thisArg, face, face, const_cast<FontFaceSet*>(
this)); | |
377 else | |
378 callback->handleItem(face, face, const_cast<FontFaceSet*>(this)); | |
379 } | |
380 } | |
381 | |
382 unsigned long FontFaceSet::size() const | 257 unsigned long FontFaceSet::size() const |
383 { | 258 { |
384 if (!inActiveDocumentContext()) | 259 if (!inActiveDocumentContext()) |
385 return m_nonCSSConnectedFaces.size(); | 260 return m_nonCSSConnectedFaces.size(); |
386 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); | 261 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); |
387 } | 262 } |
388 | 263 |
389 void FontFaceSet::fireDoneEventIfPossible() | 264 void FontFaceSet::fireDoneEventIfPossible() |
390 { | 265 { |
391 if (m_shouldFireLoadingEvent) | 266 if (m_shouldFireLoadingEvent) |
392 return; | 267 return; |
393 if (!m_loadingFonts.isEmpty() || (!hasLoadedFonts() && m_readyResolvers.isEm
pty())) | 268 if (!m_loadingFonts.isEmpty() || !hasLoadedFonts()) |
394 return; | 269 return; |
395 | 270 |
396 // If the layout was invalidated in between when we thought layout | 271 // If the layout was invalidated in between when we thought layout |
397 // was updated and when we're ready to fire the event, just wait | 272 // was updated and when we're ready to fire the event, just wait |
398 // until after the next layout before firing events. | 273 // until after the next layout before firing events. |
399 Document* d = document(); | 274 Document* d = document(); |
400 if (!d->view() || d->view()->needsLayout()) | 275 if (!d->view() || d->view()->needsLayout()) |
401 return; | 276 return; |
402 | 277 |
403 if (hasLoadedFonts()) { | 278 if (hasLoadedFonts()) { |
404 RefPtr<FontFaceSetLoadEvent> doneEvent = nullptr; | 279 RefPtr<FontFaceSetLoadEvent> doneEvent = nullptr; |
405 RefPtr<FontFaceSetLoadEvent> errorEvent = nullptr; | 280 RefPtr<FontFaceSetLoadEvent> errorEvent = nullptr; |
406 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa
dingdone, m_loadedFonts); | 281 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa
dingdone, m_loadedFonts); |
407 m_loadedFonts.clear(); | 282 m_loadedFonts.clear(); |
408 if (!m_failedFonts.isEmpty()) { | 283 if (!m_failedFonts.isEmpty()) { |
409 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames
::loadingerror, m_failedFonts); | 284 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames
::loadingerror, m_failedFonts); |
410 m_failedFonts.clear(); | 285 m_failedFonts.clear(); |
411 } | 286 } |
412 dispatchEvent(doneEvent); | 287 dispatchEvent(doneEvent); |
413 if (errorEvent) | 288 if (errorEvent) |
414 dispatchEvent(errorEvent); | 289 dispatchEvent(errorEvent); |
415 } | 290 } |
416 | |
417 if (!m_readyResolvers.isEmpty()) { | |
418 Vector<OwnPtr<FontsReadyPromiseResolver> > resolvers; | |
419 m_readyResolvers.swap(resolvers); | |
420 for (size_t index = 0; index < resolvers.size(); ++index) | |
421 resolvers[index]->resolve(this); | |
422 } | |
423 } | 291 } |
424 | 292 |
425 static const String& nullToSpace(const String& s) | 293 static const String& nullToSpace(const String& s) |
426 { | 294 { |
427 DEFINE_STATIC_LOCAL(String, space, (" ")); | 295 DEFINE_STATIC_LOCAL(String, space, (" ")); |
428 return s.isNull() ? space : s; | 296 return s.isNull() ? space : s; |
429 } | 297 } |
430 | 298 |
431 ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontStri
ng, const String& text) | |
432 { | |
433 if (!inActiveDocumentContext()) | |
434 return ScriptPromise(); | |
435 | |
436 Font font; | |
437 if (!resolveFontStyle(fontString, font)) { | |
438 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(s
criptState); | |
439 ScriptPromise promise = resolver->promise(); | |
440 resolver->reject(DOMException::create(SyntaxError, "Could not resolve '"
+ fontString + "' as a font.")); | |
441 return promise; | |
442 } | |
443 | |
444 FontFaceCache* fontFaceCache = document()->styleEngine()->fontSelector()->fo
ntFaceCache(); | |
445 FontFaceArray faces; | |
446 for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next(
)) { | |
447 CSSSegmentedFontFace* segmentedFontFace = fontFaceCache->get(font.fontDe
scription(), f->family()); | |
448 if (segmentedFontFace) | |
449 segmentedFontFace->match(nullToSpace(text), faces); | |
450 } | |
451 | |
452 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f
aces, scriptState); | |
453 ScriptPromise promise = resolver->promise(); | |
454 resolver->loadFonts(executionContext()); // After this, resolver->promise()
may return null. | |
455 return promise; | |
456 } | |
457 | |
458 bool FontFaceSet::check(const String& fontString, const String& text, ExceptionS
tate& exceptionState) | 299 bool FontFaceSet::check(const String& fontString, const String& text, ExceptionS
tate& exceptionState) |
459 { | 300 { |
460 if (!inActiveDocumentContext()) | 301 if (!inActiveDocumentContext()) |
461 return false; | 302 return false; |
462 | 303 |
463 Font font; | 304 Font font; |
464 if (!resolveFontStyle(fontString, font)) { | 305 if (!resolveFontStyle(fontString, font)) { |
465 exceptionState.throwDOMException(SyntaxError, "Could not resolve '" + fo
ntString + "' as a font."); | 306 exceptionState.ThrowDOMException(SyntaxError, "Could not resolve '" + fo
ntString + "' as a font."); |
466 return false; | 307 return false; |
467 } | 308 } |
468 | 309 |
469 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); | 310 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); |
470 FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); | 311 FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); |
471 | 312 |
472 bool hasLoadedFaces = false; | 313 bool hasLoadedFaces = false; |
473 for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next(
)) { | 314 for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next(
)) { |
474 CSSSegmentedFontFace* face = fontFaceCache->get(font.fontDescription(),
f->family()); | 315 CSSSegmentedFontFace* face = fontFaceCache->get(font.fontDescription(),
f->family()); |
475 if (face) { | 316 if (face) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 return fonts.release(); | 413 return fonts.release(); |
573 } | 414 } |
574 | 415 |
575 void FontFaceSet::didLayout(Document& document) | 416 void FontFaceSet::didLayout(Document& document) |
576 { | 417 { |
577 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) | 418 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) |
578 fonts->didLayout(); | 419 fonts->didLayout(); |
579 } | 420 } |
580 | 421 |
581 } // namespace blink | 422 } // namespace blink |
OLD | NEW |