| 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 |