Chromium Code Reviews| 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) |
| 149 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) | 121 , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) |
| 150 { | 122 { |
| 151 suspendIfNeeded(); | 123 suspendIfNeeded(); |
| 152 } | 124 } |
| 153 | 125 |
| 154 FontFaceSet::~FontFaceSet() | 126 FontFaceSet::~FontFaceSet() |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 void FontFaceSet::handlePendingEventsAndPromisesSoon() | 164 void FontFaceSet::handlePendingEventsAndPromisesSoon() |
| 193 { | 165 { |
| 194 // m_asyncRunner will be automatically stopped on destruction. | 166 // m_asyncRunner will be automatically stopped on destruction. |
| 195 m_asyncRunner.runAsync(); | 167 m_asyncRunner.runAsync(); |
| 196 } | 168 } |
| 197 | 169 |
| 198 void FontFaceSet::didLayout() | 170 void FontFaceSet::didLayout() |
| 199 { | 171 { |
| 200 if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty()) | 172 if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty()) |
| 201 m_histogram.record(); | 173 m_histogram.record(); |
| 202 if (!m_loadingFonts.isEmpty() || (!m_isLoading && m_readyResolvers.isEmpty() )) | 174 if (!shouldSignalReady()) |
| 203 return; | 175 return; |
| 204 handlePendingEventsAndPromisesSoon(); | 176 handlePendingEventsAndPromisesSoon(); |
| 205 } | 177 } |
| 206 | 178 |
| 179 bool FontFaceSet::shouldSignalReady() const | |
| 180 { | |
| 181 if (!m_loadingFonts.isEmpty()) | |
| 182 return false; | |
| 183 return m_isLoading || (m_ready && m_ready->state() == ReadyProperty::Pending ); | |
| 184 } | |
| 185 | |
| 207 void FontFaceSet::handlePendingEventsAndPromises() | 186 void FontFaceSet::handlePendingEventsAndPromises() |
| 208 { | 187 { |
| 209 fireLoadingEvent(); | 188 fireLoadingEvent(); |
| 210 fireDoneEventIfPossible(); | 189 fireDoneEventIfPossible(); |
| 211 } | 190 } |
| 212 | 191 |
| 213 void FontFaceSet::fireLoadingEvent() | 192 void FontFaceSet::fireLoadingEvent() |
| 214 { | 193 { |
| 215 if (m_shouldFireLoadingEvent) { | 194 if (m_shouldFireLoadingEvent) { |
| 216 m_shouldFireLoadingEvent = false; | 195 m_shouldFireLoadingEvent = false; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 m_histogram.updateStatus(fontFace); | 230 m_histogram.updateStatus(fontFace); |
| 252 m_failedFonts.append(fontFace); | 231 m_failedFonts.append(fontFace); |
| 253 removeFromLoadingFonts(fontFace); | 232 removeFromLoadingFonts(fontFace); |
| 254 } | 233 } |
| 255 | 234 |
| 256 void FontFaceSet::addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) | 235 void FontFaceSet::addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) |
| 257 { | 236 { |
| 258 if (!m_isLoading) { | 237 if (!m_isLoading) { |
| 259 m_isLoading = true; | 238 m_isLoading = true; |
| 260 m_shouldFireLoadingEvent = true; | 239 m_shouldFireLoadingEvent = true; |
| 240 if (m_ready && m_ready->state() != ReadyProperty::Pending) | |
| 241 m_ready->reset(); | |
| 261 handlePendingEventsAndPromisesSoon(); | 242 handlePendingEventsAndPromisesSoon(); |
| 262 } | 243 } |
| 263 m_loadingFonts.add(fontFace); | 244 m_loadingFonts.add(fontFace); |
| 264 } | 245 } |
| 265 | 246 |
| 266 void FontFaceSet::removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFa ce) | 247 void FontFaceSet::removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFa ce) |
| 267 { | 248 { |
| 268 m_loadingFonts.remove(fontFace); | 249 m_loadingFonts.remove(fontFace); |
| 269 if (m_loadingFonts.isEmpty()) | 250 if (m_loadingFonts.isEmpty()) |
| 270 handlePendingEventsAndPromisesSoon(); | 251 handlePendingEventsAndPromisesSoon(); |
| 271 } | 252 } |
| 272 | 253 |
| 273 ScriptPromise FontFaceSet::ready(ScriptState* scriptState) | 254 ScriptPromise FontFaceSet::ready(ScriptState* scriptState) |
| 274 { | 255 { |
| 275 if (!inActiveDocumentContext()) | 256 if (!inActiveDocumentContext()) |
| 276 return ScriptPromise(); | 257 return ScriptPromise(); |
| 277 FontsReadyPromiseResolver* resolver = FontsReadyPromiseResolver::create(scri ptState); | 258 |
| 278 ScriptPromise promise = resolver->promise(); | 259 if (!m_ready) |
|
dominicc (has gone to gerrit)
2015/09/02 00:14:06
Pretty much everyone creates these lazily, and whi
Kunihiko Sakamoto
2015/09/02 05:05:42
Done.
I think m_isLoading is still needed, since F
| |
| 279 m_readyResolvers.append(resolver); | 260 m_ready = new ReadyProperty(executionContext(), this, ReadyProperty::Rea dy); |
| 280 handlePendingEventsAndPromisesSoon(); | 261 handlePendingEventsAndPromisesSoon(); |
| 281 return promise; | 262 return m_ready->promise(scriptState->world()); |
| 282 } | 263 } |
| 283 | 264 |
| 284 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) | 265 void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) |
| 285 { | 266 { |
| 286 if (!inActiveDocumentContext()) | 267 if (!inActiveDocumentContext()) |
| 287 return; | 268 return; |
| 288 if (!fontFace) { | 269 if (!fontFace) { |
| 289 exceptionState.throwTypeError("The argument is not a FontFace."); | 270 exceptionState.throwTypeError("The argument is not a FontFace."); |
| 290 return; | 271 return; |
| 291 } | 272 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 399 { | 380 { |
| 400 if (!inActiveDocumentContext()) | 381 if (!inActiveDocumentContext()) |
| 401 return m_nonCSSConnectedFaces.size(); | 382 return m_nonCSSConnectedFaces.size(); |
| 402 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); | 383 return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); |
| 403 } | 384 } |
| 404 | 385 |
| 405 void FontFaceSet::fireDoneEventIfPossible() | 386 void FontFaceSet::fireDoneEventIfPossible() |
| 406 { | 387 { |
| 407 if (m_shouldFireLoadingEvent) | 388 if (m_shouldFireLoadingEvent) |
| 408 return; | 389 return; |
| 409 if (!m_loadingFonts.isEmpty() || (!m_isLoading && m_readyResolvers.isEmpty() )) | 390 if (!shouldSignalReady()) |
| 410 return; | 391 return; |
| 411 | 392 |
| 412 // If the layout was invalidated in between when we thought layout | 393 // 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 | 394 // was updated and when we're ready to fire the event, just wait |
| 414 // until after the next layout before firing events. | 395 // until after the next layout before firing events. |
| 415 Document* d = document(); | 396 Document* d = document(); |
| 416 if (!d->view() || d->view()->needsLayout()) | 397 if (!d->view() || d->view()->needsLayout()) |
| 417 return; | 398 return; |
| 418 | 399 |
| 419 if (m_isLoading) { | 400 if (m_isLoading) { |
| 420 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> doneEvent = nullptr; | 401 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> doneEvent = nullptr; |
| 421 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> errorEvent = nullptr; | 402 RefPtrWillBeRawPtr<FontFaceSetLoadEvent> errorEvent = nullptr; |
| 422 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa dingdone, m_loadedFonts); | 403 doneEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames::loa dingdone, m_loadedFonts); |
| 423 m_loadedFonts.clear(); | 404 m_loadedFonts.clear(); |
| 424 if (!m_failedFonts.isEmpty()) { | 405 if (!m_failedFonts.isEmpty()) { |
| 425 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames ::loadingerror, m_failedFonts); | 406 errorEvent = FontFaceSetLoadEvent::createForFontFaces(EventTypeNames ::loadingerror, m_failedFonts); |
| 426 m_failedFonts.clear(); | 407 m_failedFonts.clear(); |
| 427 } | 408 } |
| 428 m_isLoading = false; | 409 m_isLoading = false; |
| 429 dispatchEvent(doneEvent); | 410 dispatchEvent(doneEvent); |
| 430 if (errorEvent) | 411 if (errorEvent) |
| 431 dispatchEvent(errorEvent); | 412 dispatchEvent(errorEvent); |
| 432 } | 413 } |
| 433 | 414 |
| 434 if (!m_readyResolvers.isEmpty()) { | 415 if (m_ready && m_ready->state() == ReadyProperty::Pending) |
| 435 HeapVector<Member<FontsReadyPromiseResolver>> resolvers; | 416 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 } | 417 } |
| 441 | 418 |
| 442 ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontStri ng, const String& text) | 419 ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontStri ng, const String& text) |
| 443 { | 420 { |
| 444 if (!inActiveDocumentContext()) | 421 if (!inActiveDocumentContext()) |
| 445 return ScriptPromise(); | 422 return ScriptPromise(); |
| 446 | 423 |
| 447 Font font; | 424 Font font; |
| 448 if (!resolveFontStyle(fontString, font)) { | 425 if (!resolveFontStyle(fontString, font)) { |
| 449 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptSt ate); | 426 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptSt ate); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 | 552 |
| 576 void FontFaceSet::didLayout(Document& document) | 553 void FontFaceSet::didLayout(Document& document) |
| 577 { | 554 { |
| 578 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu ment, supplementName()))) | 555 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu ment, supplementName()))) |
| 579 fonts->didLayout(); | 556 fonts->didLayout(); |
| 580 } | 557 } |
| 581 | 558 |
| 582 DEFINE_TRACE(FontFaceSet) | 559 DEFINE_TRACE(FontFaceSet) |
| 583 { | 560 { |
| 584 #if ENABLE(OILPAN) | 561 #if ENABLE(OILPAN) |
| 562 visitor->trace(m_ready); | |
| 585 visitor->trace(m_loadingFonts); | 563 visitor->trace(m_loadingFonts); |
| 586 visitor->trace(m_readyResolvers); | |
| 587 visitor->trace(m_loadedFonts); | 564 visitor->trace(m_loadedFonts); |
| 588 visitor->trace(m_failedFonts); | 565 visitor->trace(m_failedFonts); |
| 589 visitor->trace(m_nonCSSConnectedFaces); | 566 visitor->trace(m_nonCSSConnectedFaces); |
| 590 HeapSupplement<Document>::trace(visitor); | 567 HeapSupplement<Document>::trace(visitor); |
| 591 #endif | 568 #endif |
| 592 EventTargetWithInlineData::trace(visitor); | 569 EventTargetWithInlineData::trace(visitor); |
| 593 ActiveDOMObject::trace(visitor); | 570 ActiveDOMObject::trace(visitor); |
| 594 } | 571 } |
| 595 | 572 |
| 596 } // namespace blink | 573 } // namespace blink |
| OLD | NEW |