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 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 } | 107 } |
108 } | 108 } |
109 | 109 |
110 DEFINE_TRACE(LoadFontPromiseResolver) | 110 DEFINE_TRACE(LoadFontPromiseResolver) |
111 { | 111 { |
112 visitor->trace(m_fontFaces); | 112 visitor->trace(m_fontFaces); |
113 visitor->trace(m_resolver); | 113 visitor->trace(m_resolver); |
114 LoadFontCallback::trace(visitor); | 114 LoadFontCallback::trace(visitor); |
115 } | 115 } |
116 | 116 |
117 class FontsReadyPromiseResolver final : public GarbageCollected<FontsReadyPromis
eResolver> { | |
118 public: | |
119 static FontsReadyPromiseResolver* create(ScriptState* scriptState) | |
120 { | |
121 return new FontsReadyPromiseResolver(scriptState); | |
122 } | |
123 | |
124 void resolve(PassRefPtrWillBeRawPtr<FontFaceSet> fontFaceSet) | |
125 { | |
126 m_resolver->resolve(fontFaceSet); | |
127 } | |
128 | |
129 ScriptPromise promise() { return m_resolver->promise(); } | |
130 | |
131 DEFINE_INLINE_TRACE() | |
132 { | |
133 visitor->trace(m_resolver); | |
134 } | |
135 | |
136 private: | |
137 explicit FontsReadyPromiseResolver(ScriptState* scriptState) | |
138 : m_resolver(ScriptPromiseResolver::create(scriptState)) | |
139 { | |
140 } | |
141 | |
142 Member<ScriptPromiseResolver> m_resolver; | |
143 }; | |
144 | |
145 FontFaceSet::FontFaceSet(Document& document) | 117 FontFaceSet::FontFaceSet(Document& document) |
146 : ActiveDOMObject(&document) | 118 : ActiveDOMObject(&document) |
147 , m_shouldFireLoadingEvent(false) | 119 , m_shouldFireLoadingEvent(false) |
148 , m_isLoading(false) | 120 , m_isLoading(false) |
| 121 , m_ready(new ReadyProperty(executionContext(), this, ReadyProperty::Ready)) |
149 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) | 122 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) |
150 { | 123 { |
151 suspendIfNeeded(); | 124 suspendIfNeeded(); |
152 } | 125 } |
153 | 126 |
154 FontFaceSet::~FontFaceSet() | 127 FontFaceSet::~FontFaceSet() |
155 { | 128 { |
156 } | 129 } |
157 | 130 |
158 Document* FontFaceSet::document() const | 131 Document* FontFaceSet::document() const |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 void FontFaceSet::handlePendingEventsAndPromisesSoon() | 165 void FontFaceSet::handlePendingEventsAndPromisesSoon() |
193 { | 166 { |
194 // m_asyncRunner will be automatically stopped on destruction. | 167 // m_asyncRunner will be automatically stopped on destruction. |
195 m_asyncRunner.runAsync(); | 168 m_asyncRunner.runAsync(); |
196 } | 169 } |
197 | 170 |
198 void FontFaceSet::didLayout() | 171 void FontFaceSet::didLayout() |
199 { | 172 { |
200 if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty()) | 173 if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty()) |
201 m_histogram.record(); | 174 m_histogram.record(); |
202 if (!m_loadingFonts.isEmpty() || (!m_isLoading && m_readyResolvers.isEmpty()
)) | 175 if (!shouldSignalReady()) |
203 return; | 176 return; |
204 handlePendingEventsAndPromisesSoon(); | 177 handlePendingEventsAndPromisesSoon(); |
205 } | 178 } |
206 | 179 |
| 180 bool FontFaceSet::shouldSignalReady() const |
| 181 { |
| 182 if (!m_loadingFonts.isEmpty()) |
| 183 return false; |
| 184 return m_isLoading || m_ready->state() == ReadyProperty::Pending; |
| 185 } |
| 186 |
207 void FontFaceSet::handlePendingEventsAndPromises() | 187 void FontFaceSet::handlePendingEventsAndPromises() |
208 { | 188 { |
209 fireLoadingEvent(); | 189 fireLoadingEvent(); |
210 fireDoneEventIfPossible(); | 190 fireDoneEventIfPossible(); |
211 } | 191 } |
212 | 192 |
213 void FontFaceSet::fireLoadingEvent() | 193 void FontFaceSet::fireLoadingEvent() |
214 { | 194 { |
215 if (m_shouldFireLoadingEvent) { | 195 if (m_shouldFireLoadingEvent) { |
216 m_shouldFireLoadingEvent = false; | 196 m_shouldFireLoadingEvent = false; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 m_histogram.updateStatus(fontFace); | 231 m_histogram.updateStatus(fontFace); |
252 m_failedFonts.append(fontFace); | 232 m_failedFonts.append(fontFace); |
253 removeFromLoadingFonts(fontFace); | 233 removeFromLoadingFonts(fontFace); |
254 } | 234 } |
255 | 235 |
256 void FontFaceSet::addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) | 236 void FontFaceSet::addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) |
257 { | 237 { |
258 if (!m_isLoading) { | 238 if (!m_isLoading) { |
259 m_isLoading = true; | 239 m_isLoading = true; |
260 m_shouldFireLoadingEvent = true; | 240 m_shouldFireLoadingEvent = true; |
| 241 if (m_ready->state() != ReadyProperty::Pending) |
| 242 m_ready->reset(); |
261 handlePendingEventsAndPromisesSoon(); | 243 handlePendingEventsAndPromisesSoon(); |
262 } | 244 } |
263 m_loadingFonts.add(fontFace); | 245 m_loadingFonts.add(fontFace); |
264 } | 246 } |
265 | 247 |
266 void FontFaceSet::removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFa
ce) | 248 void FontFaceSet::removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFa
ce) |
267 { | 249 { |
268 m_loadingFonts.remove(fontFace); | 250 m_loadingFonts.remove(fontFace); |
269 if (m_loadingFonts.isEmpty()) | 251 if (m_loadingFonts.isEmpty()) |
270 handlePendingEventsAndPromisesSoon(); | 252 handlePendingEventsAndPromisesSoon(); |
271 } | 253 } |
272 | 254 |
273 ScriptPromise FontFaceSet::ready(ScriptState* scriptState) | 255 ScriptPromise FontFaceSet::ready(ScriptState* scriptState) |
274 { | 256 { |
275 if (!inActiveDocumentContext()) | 257 return m_ready->promise(scriptState->world()); |
276 return ScriptPromise(); | |
277 FontsReadyPromiseResolver* resolver = FontsReadyPromiseResolver::create(scri
ptState); | |
278 ScriptPromise promise = resolver->promise(); | |
279 m_readyResolvers.append(resolver); | |
280 handlePendingEventsAndPromisesSoon(); | |
281 return promise; | |
282 } | 258 } |
283 | 259 |
284 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) | 260 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) |
285 { | 261 { |
286 if (!inActiveDocumentContext()) | 262 if (!inActiveDocumentContext()) |
287 return; | 263 return; |
288 if (!fontFace) { | 264 if (!fontFace) { |
289 exceptionState.throwTypeError("The argument is not a FontFace."); | 265 exceptionState.throwTypeError("The argument is not a FontFace."); |
290 return; | 266 return; |
291 } | 267 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 { | 375 { |
400 if (!inActiveDocumentContext()) | 376 if (!inActiveDocumentContext()) |
401 return m_nonCSSConnectedFaces.size(); | 377 return m_nonCSSConnectedFaces.size(); |
402 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); | 378 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); |
403 } | 379 } |
404 | 380 |
405 void FontFaceSet::fireDoneEventIfPossible() | 381 void FontFaceSet::fireDoneEventIfPossible() |
406 { | 382 { |
407 if (m_shouldFireLoadingEvent) | 383 if (m_shouldFireLoadingEvent) |
408 return; | 384 return; |
409 if (!m_loadingFonts.isEmpty() || (!m_isLoading && m_readyResolvers.isEmpty()
)) | 385 if (!shouldSignalReady()) |
410 return; | 386 return; |
411 | 387 |
412 // If the layout was invalidated in between when we thought layout | 388 // If the layout was invalidated in between when we thought layout |
413 // was updated and when we're ready to fire the event, just wait | 389 // was updated and when we're ready to fire the event, just wait |
414 // until after the next layout before firing events. | 390 // until after the next layout before firing events. |
415 Document* d = document(); | 391 Document* d = document(); |
416 if (!d->view() || d->view()->needsLayout()) | 392 if (!d->view() || d->view()->needsLayout()) |
417 return; | 393 return; |
418 | 394 |
419 if (m_isLoading) { | 395 if (m_isLoading) { |
420 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> doneEvent = nullptr; | 396 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> doneEvent = nullptr; |
421 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> errorEvent = nullptr; | 397 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> errorEvent = nullptr; |
422 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa
dingdone, m_loadedFonts); | 398 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa
dingdone, m_loadedFonts); |
423 m_loadedFonts.clear(); | 399 m_loadedFonts.clear(); |
424 if (!m_failedFonts.isEmpty()) { | 400 if (!m_failedFonts.isEmpty()) { |
425 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames
::loadingerror, m_failedFonts); | 401 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames
::loadingerror, m_failedFonts); |
426 m_failedFonts.clear(); | 402 m_failedFonts.clear(); |
427 } | 403 } |
428 m_isLoading = false; | 404 m_isLoading = false; |
429 dispatchEvent(doneEvent); | 405 dispatchEvent(doneEvent); |
430 if (errorEvent) | 406 if (errorEvent) |
431 dispatchEvent(errorEvent); | 407 dispatchEvent(errorEvent); |
432 } | 408 } |
433 | 409 |
434 if (!m_readyResolvers.isEmpty()) { | 410 if (m_ready->state() == ReadyProperty::Pending) |
435 HeapVector<Member<FontsReadyPromiseResolver>> resolvers; | 411 m_ready->resolve(this); |
436 m_readyResolvers.swap(resolvers); | |
437 for (size_t index = 0; index < resolvers.size(); ++index) | |
438 resolvers[index]->resolve(this); | |
439 } | |
440 } | 412 } |
441 | 413 |
442 ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontStri
ng, const String& text) | 414 ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontStri
ng, const String& text) |
443 { | 415 { |
444 if (!inActiveDocumentContext()) | 416 if (!inActiveDocumentContext()) |
445 return ScriptPromise(); | 417 return ScriptPromise(); |
446 | 418 |
447 Font font; | 419 Font font; |
448 if (!resolveFontStyle(fontString, font)) { | 420 if (!resolveFontStyle(fontString, font)) { |
449 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptSt
ate); | 421 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptSt
ate); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 547 |
576 void FontFaceSet::didLayout(Document& document) | 548 void FontFaceSet::didLayout(Document& document) |
577 { | 549 { |
578 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) | 550 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) |
579 fonts->didLayout(); | 551 fonts->didLayout(); |
580 } | 552 } |
581 | 553 |
582 DEFINE_TRACE(FontFaceSet) | 554 DEFINE_TRACE(FontFaceSet) |
583 { | 555 { |
584 #if ENABLE(OILPAN) | 556 #if ENABLE(OILPAN) |
| 557 visitor->trace(m_ready); |
585 visitor->trace(m_loadingFonts); | 558 visitor->trace(m_loadingFonts); |
586 visitor->trace(m_readyResolvers); | |
587 visitor->trace(m_loadedFonts); | 559 visitor->trace(m_loadedFonts); |
588 visitor->trace(m_failedFonts); | 560 visitor->trace(m_failedFonts); |
589 visitor->trace(m_nonCSSConnectedFaces); | 561 visitor->trace(m_nonCSSConnectedFaces); |
590 HeapSupplement<Document>::trace(visitor); | 562 HeapSupplement<Document>::trace(visitor); |
591 #endif | 563 #endif |
592 EventTargetWithInlineData::trace(visitor); | 564 EventTargetWithInlineData::trace(visitor); |
593 ActiveDOMObject::trace(visitor); | 565 ActiveDOMObject::trace(visitor); |
594 } | 566 } |
595 | 567 |
596 } // namespace blink | 568 } // namespace blink |
OLD | NEW |