| 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 "config.h" | 26 #include "config.h" |
| 27 #include "core/css/FontFaceSet.h" | 27 #include "core/css/FontFaceSet.h" |
| 28 | 28 |
| 29 #include "RuntimeEnabledFeatures.h" | 29 #include "RuntimeEnabledFeatures.h" |
| 30 #include "V8FontFaceSet.h" |
| 30 #include "bindings/v8/Dictionary.h" | 31 #include "bindings/v8/Dictionary.h" |
| 32 #include "bindings/v8/ScriptPromiseResolver.h" |
| 33 #include "bindings/v8/ScriptScope.h" |
| 34 #include "bindings/v8/ScriptState.h" |
| 31 #include "core/css/CSSFontFaceLoadEvent.h" | 35 #include "core/css/CSSFontFaceLoadEvent.h" |
| 32 #include "core/css/CSSFontFaceSource.h" | 36 #include "core/css/CSSFontFaceSource.h" |
| 33 #include "core/css/CSSFontSelector.h" | 37 #include "core/css/CSSFontSelector.h" |
| 34 #include "core/css/CSSParser.h" | 38 #include "core/css/CSSParser.h" |
| 35 #include "core/css/CSSSegmentedFontFace.h" | 39 #include "core/css/CSSSegmentedFontFace.h" |
| 36 #include "core/css/StylePropertySet.h" | 40 #include "core/css/StylePropertySet.h" |
| 37 #include "core/css/resolver/StyleResolver.h" | 41 #include "core/css/resolver/StyleResolver.h" |
| 38 #include "core/dom/Document.h" | 42 #include "core/dom/Document.h" |
| 39 #include "core/page/FrameView.h" | 43 #include "core/page/FrameView.h" |
| 40 #include "core/platform/HistogramSupport.h" | 44 #include "core/platform/HistogramSupport.h" |
| 41 | 45 |
| 42 namespace WebCore { | 46 namespace WebCore { |
| 43 | 47 |
| 44 static const int defaultFontSize = 10; | 48 static const int defaultFontSize = 10; |
| 45 static const char* const defaultFontFamily = "sans-serif"; | 49 static const char* const defaultFontFamily = "sans-serif"; |
| 46 | 50 |
| 47 class LoadFontCallback : public CSSSegmentedFontFace::LoadFontCallback { | 51 class LoadFontPromiseResolver : public CSSSegmentedFontFace::LoadFontCallback { |
| 48 public: | 52 public: |
| 49 static PassRefPtr<LoadFontCallback> create(int numLoading, PassRefPtr<VoidCa
llback> loadCallback, PassRefPtr<VoidCallback> errorCallback) | 53 static PassRefPtr<LoadFontPromiseResolver> create(const FontFamily& family,
ScriptExecutionContext* context) |
| 50 { | 54 { |
| 51 return adoptRef<LoadFontCallback>(new LoadFontCallback(numLoading, loadC
allback, errorCallback)); | |
| 52 } | |
| 53 | |
| 54 static PassRefPtr<LoadFontCallback> createFromParams(const Dictionary& param
s, const FontFamily& family) | |
| 55 { | |
| 56 RefPtr<VoidCallback> onsuccess; | |
| 57 RefPtr<VoidCallback> onerror; | |
| 58 params.get("onsuccess", onsuccess); | |
| 59 params.get("onerror", onerror); | |
| 60 if (!onsuccess && !onerror) | |
| 61 return 0; | |
| 62 int numFamilies = 0; | 55 int numFamilies = 0; |
| 63 for (const FontFamily* f = &family; f; f = f->next()) | 56 for (const FontFamily* f = &family; f; f = f->next()) |
| 64 numFamilies++; | 57 numFamilies++; |
| 65 return LoadFontCallback::create(numFamilies, onsuccess, onerror); | 58 return adoptRef<LoadFontPromiseResolver>(new LoadFontPromiseResolver(num
Families, context)); |
| 66 } | 59 } |
| 67 | 60 |
| 68 virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE; | 61 virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE; |
| 69 virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE; | 62 virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE; |
| 70 void loaded(Document*); | 63 void loaded(Document*); |
| 71 void error(Document*); | 64 void error(Document*); |
| 65 void resolve(); |
| 66 |
| 67 ScriptPromise promise() |
| 68 { |
| 69 ScriptPromise promise = m_resolver->promise(); |
| 70 m_resolver->detachPromise(); |
| 71 return promise; |
| 72 } |
| 73 |
| 72 private: | 74 private: |
| 73 LoadFontCallback(int numLoading, PassRefPtr<VoidCallback> loadCallback, Pass
RefPtr<VoidCallback> errorCallback) | 75 LoadFontPromiseResolver(int numLoading, ScriptExecutionContext* context) |
| 74 : m_numLoading(numLoading) | 76 : m_numLoading(numLoading) |
| 75 , m_errorOccured(false) | 77 , m_errorOccured(false) |
| 76 , m_loadCallback(loadCallback) | 78 , m_scriptState(ScriptState::current()) |
| 77 , m_errorCallback(errorCallback) | 79 , m_resolver(ScriptPromiseResolver::create(context)) |
| 78 { } | 80 { } |
| 79 | 81 |
| 80 int m_numLoading; | 82 int m_numLoading; |
| 81 bool m_errorOccured; | 83 bool m_errorOccured; |
| 82 RefPtr<VoidCallback> m_loadCallback; | 84 ScriptState* m_scriptState; |
| 83 RefPtr<VoidCallback> m_errorCallback; | 85 RefPtr<ScriptPromiseResolver> m_resolver; |
| 84 }; | 86 }; |
| 85 | 87 |
| 86 void LoadFontCallback::loaded(Document* document) | 88 void LoadFontPromiseResolver::loaded(Document* document) |
| 87 { | 89 { |
| 88 m_numLoading--; | 90 m_numLoading--; |
| 89 if (m_numLoading || !document) | 91 if (m_numLoading || !document) |
| 90 return; | 92 return; |
| 91 | 93 |
| 92 if (m_errorOccured) { | 94 document->fonts()->scheduleResolve(this); |
| 93 if (m_errorCallback) | |
| 94 document->fonts()->scheduleCallback(m_errorCallback.release()); | |
| 95 } else { | |
| 96 if (m_loadCallback) | |
| 97 document->fonts()->scheduleCallback(m_loadCallback.release()); | |
| 98 } | |
| 99 } | 95 } |
| 100 | 96 |
| 101 void LoadFontCallback::error(Document* document) | 97 void LoadFontPromiseResolver::error(Document* document) |
| 102 { | 98 { |
| 103 m_errorOccured = true; | 99 m_errorOccured = true; |
| 104 loaded(document); | 100 loaded(document); |
| 105 } | 101 } |
| 106 | 102 |
| 107 void LoadFontCallback::notifyLoaded(CSSSegmentedFontFace* face) | 103 void LoadFontPromiseResolver::notifyLoaded(CSSSegmentedFontFace* face) |
| 108 { | 104 { |
| 109 loaded(face->fontSelector()->document()); | 105 loaded(face->fontSelector()->document()); |
| 110 } | 106 } |
| 111 | 107 |
| 112 void LoadFontCallback::notifyError(CSSSegmentedFontFace* face) | 108 void LoadFontPromiseResolver::notifyError(CSSSegmentedFontFace* face) |
| 113 { | 109 { |
| 114 error(face->fontSelector()->document()); | 110 error(face->fontSelector()->document()); |
| 115 } | 111 } |
| 116 | 112 |
| 113 void LoadFontPromiseResolver::resolve() |
| 114 { |
| 115 ScriptScope scope(m_scriptState); |
| 116 if (m_errorOccured) |
| 117 m_resolver->reject(ScriptValue::createNull()); |
| 118 else |
| 119 m_resolver->fulfill(ScriptValue::createNull()); |
| 120 } |
| 121 |
| 122 class FontsReadyPromiseResolver { |
| 123 public: |
| 124 static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptExecutionContext*
context) |
| 125 { |
| 126 return adoptPtr(new FontsReadyPromiseResolver(context)); |
| 127 } |
| 128 |
| 129 void call(PassRefPtr<FontFaceSet> fontFaceSet) |
| 130 { |
| 131 ScriptScope scope(m_scriptState); |
| 132 m_resolver->fulfill(fontFaceSet); |
| 133 } |
| 134 |
| 135 ScriptPromise promise() |
| 136 { |
| 137 ScriptPromise promise = m_resolver->promise(); |
| 138 m_resolver->detachPromise(); |
| 139 return promise; |
| 140 } |
| 141 |
| 142 private: |
| 143 FontsReadyPromiseResolver(ScriptExecutionContext* context) |
| 144 : m_scriptState(ScriptState::current()) |
| 145 , m_resolver(ScriptPromiseResolver::create(context)) |
| 146 { } |
| 147 ScriptState* m_scriptState; |
| 148 RefPtr<ScriptPromiseResolver> m_resolver; |
| 149 }; |
| 150 |
| 117 FontFaceSet::FontFaceSet(Document* document) | 151 FontFaceSet::FontFaceSet(Document* document) |
| 118 : ActiveDOMObject(document) | 152 : ActiveDOMObject(document) |
| 119 , m_loadingCount(0) | 153 , m_loadingCount(0) |
| 120 , m_shouldFireDoneEvent(false) | 154 , m_shouldFireDoneEvent(false) |
| 121 , m_timer(this, &FontFaceSet::timerFired) | 155 , m_timer(this, &FontFaceSet::timerFired) |
| 122 { | 156 { |
| 123 suspendIfNeeded(); | 157 suspendIfNeeded(); |
| 124 } | 158 } |
| 125 | 159 |
| 126 FontFaceSet::~FontFaceSet() | 160 FontFaceSet::~FontFaceSet() |
| (...skipping 18 matching lines...) Expand all Loading... |
| 145 const AtomicString& FontFaceSet::interfaceName() const | 179 const AtomicString& FontFaceSet::interfaceName() const |
| 146 { | 180 { |
| 147 return eventNames().interfaceForFontFaceSet; | 181 return eventNames().interfaceForFontFaceSet; |
| 148 } | 182 } |
| 149 | 183 |
| 150 ScriptExecutionContext* FontFaceSet::scriptExecutionContext() const | 184 ScriptExecutionContext* FontFaceSet::scriptExecutionContext() const |
| 151 { | 185 { |
| 152 return ActiveDOMObject::scriptExecutionContext(); | 186 return ActiveDOMObject::scriptExecutionContext(); |
| 153 } | 187 } |
| 154 | 188 |
| 189 AtomicString FontFaceSet::status() const |
| 190 { |
| 191 DEFINE_STATIC_LOCAL(AtomicString, loading, ("loading", AtomicString::Constru
ctFromLiteral)); |
| 192 DEFINE_STATIC_LOCAL(AtomicString, loaded, ("loaded", AtomicString::Construct
FromLiteral)); |
| 193 return (m_loadingCount > 0 || m_shouldFireDoneEvent) ? loading : loaded; |
| 194 } |
| 195 |
| 155 void FontFaceSet::didLayout() | 196 void FontFaceSet::didLayout() |
| 156 { | 197 { |
| 157 Document* d = document(); | 198 Document* d = document(); |
| 158 if (d->page() && d->page()->mainFrame() == d->frame()) | 199 if (d->page() && d->page()->mainFrame() == d->frame()) |
| 159 m_histogram.record(); | 200 m_histogram.record(); |
| 160 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 201 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
| 161 return; | 202 return; |
| 162 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp
ty())) | 203 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty())
) |
| 163 return; | 204 return; |
| 164 if (!m_timer.isActive()) | 205 if (!m_timer.isActive()) |
| 165 m_timer.startOneShot(0); | 206 m_timer.startOneShot(0); |
| 166 } | 207 } |
| 167 | 208 |
| 168 void FontFaceSet::timerFired(Timer<FontFaceSet>*) | 209 void FontFaceSet::timerFired(Timer<FontFaceSet>*) |
| 169 { | 210 { |
| 170 firePendingEvents(); | 211 firePendingEvents(); |
| 171 firePendingCallbacks(); | 212 resolvePendingLoadPromises(); |
| 172 fireDoneEventIfPossible(); | 213 fireDoneEventIfPossible(); |
| 173 } | 214 } |
| 174 | 215 |
| 175 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) | 216 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) |
| 176 { | 217 { |
| 177 m_pendingEvents.append(event); | 218 m_pendingEvents.append(event); |
| 178 if (!m_timer.isActive()) | 219 if (!m_timer.isActive()) |
| 179 m_timer.startOneShot(0); | 220 m_timer.startOneShot(0); |
| 180 } | 221 } |
| 181 | 222 |
| 182 void FontFaceSet::firePendingEvents() | 223 void FontFaceSet::firePendingEvents() |
| 183 { | 224 { |
| 184 if (m_pendingEvents.isEmpty()) | 225 if (m_pendingEvents.isEmpty()) |
| 185 return; | 226 return; |
| 186 | 227 |
| 187 Vector<RefPtr<Event> > pendingEvents; | 228 Vector<RefPtr<Event> > pendingEvents; |
| 188 m_pendingEvents.swap(pendingEvents); | 229 m_pendingEvents.swap(pendingEvents); |
| 189 for (size_t index = 0; index < pendingEvents.size(); ++index) | 230 for (size_t index = 0; index < pendingEvents.size(); ++index) |
| 190 dispatchEvent(pendingEvents[index].release()); | 231 dispatchEvent(pendingEvents[index].release()); |
| 191 } | 232 } |
| 192 | 233 |
| 193 void FontFaceSet::scheduleCallback(PassRefPtr<VoidCallback> callback) | 234 void FontFaceSet::scheduleResolve(LoadFontPromiseResolver* resolver) |
| 194 { | 235 { |
| 195 m_pendingCallbacks.append(callback); | 236 m_pendingLoadResolvers.append(resolver); |
| 196 if (!m_timer.isActive()) | 237 if (!m_timer.isActive()) |
| 197 m_timer.startOneShot(0); | 238 m_timer.startOneShot(0); |
| 198 } | 239 } |
| 199 | 240 |
| 200 void FontFaceSet::firePendingCallbacks() | 241 void FontFaceSet::resolvePendingLoadPromises() |
| 201 { | 242 { |
| 202 if (m_pendingCallbacks.isEmpty()) | 243 if (m_pendingLoadResolvers.isEmpty()) |
| 203 return; | 244 return; |
| 204 | 245 |
| 205 Vector<RefPtr<VoidCallback> > pendingCallbacks; | 246 Vector<RefPtr<LoadFontPromiseResolver> > resolvers; |
| 206 m_pendingCallbacks.swap(pendingCallbacks); | 247 m_pendingLoadResolvers.swap(resolvers); |
| 207 for (size_t index = 0; index < pendingCallbacks.size(); ++index) | 248 for (size_t index = 0; index < resolvers.size(); ++index) |
| 208 pendingCallbacks[index]->handleEvent(); | 249 resolvers[index]->resolve(); |
| 209 } | 250 } |
| 210 | 251 |
| 211 void FontFaceSet::beginFontLoading(FontFace* fontFace) | 252 void FontFaceSet::beginFontLoading(FontFace* fontFace) |
| 212 { | 253 { |
| 213 m_histogram.incrementCount(); | 254 m_histogram.incrementCount(); |
| 214 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 255 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
| 215 return; | 256 return; |
| 216 | 257 |
| 217 ++m_loadingCount; | 258 ++m_loadingCount; |
| 218 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) | 259 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 241 ASSERT(m_loadingCount > 0); | 282 ASSERT(m_loadingCount > 0); |
| 242 --m_loadingCount; | 283 --m_loadingCount; |
| 243 if (!m_loadingCount) { | 284 if (!m_loadingCount) { |
| 244 ASSERT(!m_shouldFireDoneEvent); | 285 ASSERT(!m_shouldFireDoneEvent); |
| 245 m_shouldFireDoneEvent = true; | 286 m_shouldFireDoneEvent = true; |
| 246 if (!m_timer.isActive()) | 287 if (!m_timer.isActive()) |
| 247 m_timer.startOneShot(0); | 288 m_timer.startOneShot(0); |
| 248 } | 289 } |
| 249 } | 290 } |
| 250 | 291 |
| 251 void FontFaceSet::notifyWhenFontsReady(PassRefPtr<VoidCallback> callback) | 292 ScriptPromise FontFaceSet::ready() |
| 252 { | 293 { |
| 253 m_fontsReadyCallbacks.append(callback); | 294 OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::crea
te(scriptExecutionContext()); |
| 295 ScriptPromise promise = resolver->promise(); |
| 296 m_readyResolvers.append(resolver.release()); |
| 254 if (!m_timer.isActive()) | 297 if (!m_timer.isActive()) |
| 255 m_timer.startOneShot(0); | 298 m_timer.startOneShot(0); |
| 299 return promise; |
| 256 } | 300 } |
| 257 | 301 |
| 258 void FontFaceSet::fireDoneEventIfPossible() | 302 void FontFaceSet::fireDoneEventIfPossible() |
| 259 { | 303 { |
| 260 if (!m_pendingEvents.isEmpty() || !m_pendingCallbacks.isEmpty()) | 304 if (!m_pendingEvents.isEmpty() || !m_pendingLoadResolvers.isEmpty()) |
| 261 return; | 305 return; |
| 262 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp
ty())) | 306 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty())
) |
| 263 return; | 307 return; |
| 264 | 308 |
| 265 // If the layout was invalidated in between when we thought layout | 309 // If the layout was invalidated in between when we thought layout |
| 266 // was updated and when we're ready to fire the event, just wait | 310 // was updated and when we're ready to fire the event, just wait |
| 267 // until after the next layout before firing events. | 311 // until after the next layout before firing events. |
| 268 Document* d = document(); | 312 Document* d = document(); |
| 269 if (!d->view() || d->view()->needsLayout()) | 313 if (!d->view() || d->view()->needsLayout()) |
| 270 return; | 314 return; |
| 271 | 315 |
| 272 if (m_shouldFireDoneEvent) { | 316 if (m_shouldFireDoneEvent) { |
| 273 m_shouldFireDoneEvent = false; | 317 m_shouldFireDoneEvent = false; |
| 274 RefPtr<CSSFontFaceLoadEvent> doneEvent; | 318 RefPtr<CSSFontFaceLoadEvent> doneEvent; |
| 275 RefPtr<CSSFontFaceLoadEvent> errorEvent; | 319 RefPtr<CSSFontFaceLoadEvent> errorEvent; |
| 276 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin
gdoneEvent, m_loadedFonts); | 320 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin
gdoneEvent, m_loadedFonts); |
| 277 m_loadedFonts.clear(); | 321 m_loadedFonts.clear(); |
| 278 if (!m_failedFonts.isEmpty()) { | 322 if (!m_failedFonts.isEmpty()) { |
| 279 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l
oadingerrorEvent, m_failedFonts); | 323 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l
oadingerrorEvent, m_failedFonts); |
| 280 m_failedFonts.clear(); | 324 m_failedFonts.clear(); |
| 281 } | 325 } |
| 282 dispatchEvent(doneEvent); | 326 dispatchEvent(doneEvent); |
| 283 if (errorEvent) | 327 if (errorEvent) |
| 284 dispatchEvent(errorEvent); | 328 dispatchEvent(errorEvent); |
| 285 } | 329 } |
| 286 | 330 |
| 287 if (!m_fontsReadyCallbacks.isEmpty()) { | 331 if (!m_readyResolvers.isEmpty()) { |
| 288 Vector<RefPtr<VoidCallback> > callbacks; | 332 Vector<OwnPtr<FontsReadyPromiseResolver> > resolvers; |
| 289 m_fontsReadyCallbacks.swap(callbacks); | 333 m_readyResolvers.swap(resolvers); |
| 290 for (size_t index = 0; index < callbacks.size(); ++index) | 334 for (size_t index = 0; index < resolvers.size(); ++index) |
| 291 callbacks[index]->handleEvent(); | 335 resolvers[index]->call(this); |
| 292 } | 336 } |
| 293 } | 337 } |
| 294 | 338 |
| 295 void FontFaceSet::loadFont(const Dictionary& params) | 339 Vector<RefPtr<FontFace> > FontFaceSet::match(const String& fontString, const Str
ing&, ExceptionState& es) |
| 296 { | 340 { |
| 297 // FIXME: The text member of params is ignored. | 341 // FIXME: The second parameter (text) is ignored. |
| 298 String fontString; | 342 Vector<RefPtr<FontFace> > matchedFonts; |
| 299 if (!params.get("font", fontString)) | 343 |
| 300 return; | |
| 301 Font font; | 344 Font font; |
| 302 if (!resolveFontStyle(fontString, font)) | 345 if (!resolveFontStyle(fontString, font)) { |
| 303 return; | 346 es.throwDOMException(SyntaxError); |
| 304 RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(param
s, font.family()); | 347 return matchedFonts; |
| 348 } |
| 305 | 349 |
| 306 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 350 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 307 Document* d = document(); | 351 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); |
| 308 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont
Face(font.fontDescription(), f->family()); | 352 if (face) |
| 309 if (!face) { | 353 matchedFonts.append(face->fontFaces()); |
| 310 if (callback) | |
| 311 callback->error(d); | |
| 312 continue; | |
| 313 } | |
| 314 face->loadFont(font.fontDescription(), callback); | |
| 315 } | 354 } |
| 355 return matchedFonts; |
| 316 } | 356 } |
| 317 | 357 |
| 318 bool FontFaceSet::checkFont(const String& fontString, const String&) | 358 ScriptPromise FontFaceSet::load(const String& fontString, const String&, Excepti
onState& es) |
| 319 { | 359 { |
| 320 // FIXME: The second parameter (text) is ignored. | 360 // FIXME: The second parameter (text) is ignored. |
| 321 Font font; | 361 Font font; |
| 322 if (!resolveFontStyle(fontString, font)) | 362 if (!resolveFontStyle(fontString, font)) { |
| 363 es.throwDOMException(SyntaxError); |
| 364 return ScriptPromise(); |
| 365 } |
| 366 |
| 367 Document* d = document(); |
| 368 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f
ont.family(), scriptExecutionContext()); |
| 369 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 370 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont
Face(font.fontDescription(), f->family()); |
| 371 if (!face) { |
| 372 resolver->error(d); |
| 373 continue; |
| 374 } |
| 375 face->loadFont(font.fontDescription(), resolver); |
| 376 } |
| 377 return resolver->promise(); |
| 378 } |
| 379 |
| 380 bool FontFaceSet::check(const String& fontString, const String&, ExceptionState&
es) |
| 381 { |
| 382 // FIXME: The second parameter (text) is ignored. |
| 383 Font font; |
| 384 if (!resolveFontStyle(fontString, font)) { |
| 385 es.throwDOMException(SyntaxError); |
| 323 return false; | 386 return false; |
| 387 } |
| 388 |
| 324 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 389 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 325 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); | 390 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()
->getFontFace(font.fontDescription(), f->family()); |
| 326 if (!face || !face->checkFont()) | 391 if (!face || !face->checkFont()) |
| 327 return false; | 392 return false; |
| 328 } | 393 } |
| 329 return true; | 394 return true; |
| 330 } | 395 } |
| 331 | 396 |
| 332 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) | 397 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) |
| 333 { | 398 { |
| 399 if (fontString.isEmpty()) |
| 400 return false; |
| 401 |
| 334 // Interpret fontString in the same way as the 'font' attribute of CanvasRen
deringContext2D. | 402 // Interpret fontString in the same way as the 'font' attribute of CanvasRen
deringContext2D. |
| 335 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat
e(); | 403 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat
e(); |
| 336 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true,
CSSStrictMode, 0); | 404 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true,
CSSStrictMode, 0); |
| 337 if (parsedStyle->isEmpty()) | 405 if (parsedStyle->isEmpty()) |
| 338 return false; | 406 return false; |
| 339 | 407 |
| 340 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); | 408 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); |
| 341 if (fontValue == "inherit" || fontValue == "initial") | 409 if (fontValue == "inherit" || fontValue == "initial") |
| 342 return false; | 410 return false; |
| 343 | 411 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 374 | 442 |
| 375 void FontFaceSet::FontLoadHistogram::record() | 443 void FontFaceSet::FontLoadHistogram::record() |
| 376 { | 444 { |
| 377 if (m_recorded) | 445 if (m_recorded) |
| 378 return; | 446 return; |
| 379 m_recorded = true; | 447 m_recorded = true; |
| 380 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1
, 100, 50); | 448 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1
, 100, 50); |
| 381 } | 449 } |
| 382 | 450 |
| 383 } // namespace WebCore | 451 } // namespace WebCore |
| OLD | NEW |