Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: Source/core/css/FontFaceSet.cpp

Issue 1313853003: CSS Font Loading: FontFaceSet.ready should return the same promise each time (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« LayoutTests/fast/css/fontfaceset-ready.html ('K') | « Source/core/css/FontFaceSet.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698