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

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
« no previous file with comments | « Source/core/css/FontFaceSet.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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)
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/css/FontFaceSet.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698