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 |
| 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 ScriptPromise promise() { return m_resolver->promise(); } | |
| 66 void resolve(); | |
| 72 private: | 67 private: |
| 73 LoadFontCallback(int numLoading, PassRefPtr<VoidCallback> loadCallback, Pass RefPtr<VoidCallback> errorCallback) | 68 LoadFontPromiseResolver(int numLoading, ScriptExecutionContext* context) |
| 74 : m_numLoading(numLoading) | 69 : m_numLoading(numLoading) |
| 75 , m_errorOccured(false) | 70 , m_errorOccured(false) |
| 76 , m_loadCallback(loadCallback) | 71 , m_scriptState(ScriptState::current()) |
| 77 , m_errorCallback(errorCallback) | 72 , m_resolver(ScriptPromiseResolver::create(context)) |
| 78 { } | 73 { } |
| 79 | 74 |
| 80 int m_numLoading; | 75 int m_numLoading; |
| 81 bool m_errorOccured; | 76 bool m_errorOccured; |
| 82 RefPtr<VoidCallback> m_loadCallback; | 77 ScriptState* m_scriptState; |
| 83 RefPtr<VoidCallback> m_errorCallback; | 78 RefPtr<ScriptPromiseResolver> m_resolver; |
| 84 }; | 79 }; |
| 85 | 80 |
| 86 void LoadFontCallback::loaded(Document* document) | 81 void LoadFontPromiseResolver::loaded(Document* document) |
| 87 { | 82 { |
| 88 m_numLoading--; | 83 m_numLoading--; |
| 89 if (m_numLoading || !document) | 84 if (m_numLoading || !document) |
| 90 return; | 85 return; |
| 91 | 86 |
| 92 if (m_errorOccured) { | 87 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 } | 88 } |
| 100 | 89 |
| 101 void LoadFontCallback::error(Document* document) | 90 void LoadFontPromiseResolver::error(Document* document) |
| 102 { | 91 { |
| 103 m_errorOccured = true; | 92 m_errorOccured = true; |
| 104 loaded(document); | 93 loaded(document); |
| 105 } | 94 } |
| 106 | 95 |
| 107 void LoadFontCallback::notifyLoaded(CSSSegmentedFontFace* face) | 96 void LoadFontPromiseResolver::notifyLoaded(CSSSegmentedFontFace* face) |
| 108 { | 97 { |
| 109 loaded(face->fontSelector()->document()); | 98 loaded(face->fontSelector()->document()); |
| 110 } | 99 } |
| 111 | 100 |
| 112 void LoadFontCallback::notifyError(CSSSegmentedFontFace* face) | 101 void LoadFontPromiseResolver::notifyError(CSSSegmentedFontFace* face) |
| 113 { | 102 { |
| 114 error(face->fontSelector()->document()); | 103 error(face->fontSelector()->document()); |
| 115 } | 104 } |
| 116 | 105 |
| 106 void LoadFontPromiseResolver::resolve() | |
| 107 { | |
| 108 ScriptScope scope(m_scriptState); | |
| 109 if (m_errorOccured) | |
| 110 m_resolver->reject(ScriptValue::createNull()); | |
| 111 else | |
| 112 m_resolver->fulfill(ScriptValue::createNull()); | |
| 113 } | |
| 114 | |
| 115 class FontsReadyPromiseResolver { | |
| 116 public: | |
| 117 static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptExecutionContext* context) | |
| 118 { | |
| 119 return adoptPtr(new FontsReadyPromiseResolver(context)); | |
| 120 } | |
| 121 | |
| 122 void call(PassRefPtr<FontFaceSet> fontFaceSet) | |
| 123 { | |
| 124 ScriptScope scope(m_scriptState); | |
| 125 m_resolver->fulfill(fontFaceSet); | |
| 126 } | |
| 127 | |
| 128 ScriptPromise promise() { return m_resolver->promise(); } | |
| 129 | |
| 130 private: | |
| 131 FontsReadyPromiseResolver(ScriptExecutionContext* context) | |
| 132 : m_scriptState(ScriptState::current()) | |
| 133 , m_resolver(ScriptPromiseResolver::create(context)) | |
| 134 { } | |
| 135 ScriptState* m_scriptState; | |
| 136 RefPtr<ScriptPromiseResolver> m_resolver; | |
| 137 }; | |
| 138 | |
| 117 FontFaceSet::FontFaceSet(Document* document) | 139 FontFaceSet::FontFaceSet(Document* document) |
| 118 : ActiveDOMObject(document) | 140 : ActiveDOMObject(document) |
| 119 , m_loadingCount(0) | 141 , m_loadingCount(0) |
| 120 , m_shouldFireDoneEvent(false) | 142 , m_shouldFireDoneEvent(false) |
| 121 , m_timer(this, &FontFaceSet::timerFired) | 143 , m_timer(this, &FontFaceSet::timerFired) |
| 122 { | 144 { |
| 123 suspendIfNeeded(); | 145 suspendIfNeeded(); |
| 124 } | 146 } |
| 125 | 147 |
| 126 FontFaceSet::~FontFaceSet() | 148 FontFaceSet::~FontFaceSet() |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 152 return ActiveDOMObject::scriptExecutionContext(); | 174 return ActiveDOMObject::scriptExecutionContext(); |
| 153 } | 175 } |
| 154 | 176 |
| 155 void FontFaceSet::didLayout() | 177 void FontFaceSet::didLayout() |
| 156 { | 178 { |
| 157 Document* d = document(); | 179 Document* d = document(); |
| 158 if (d->page() && d->page()->mainFrame() == d->frame()) | 180 if (d->page() && d->page()->mainFrame() == d->frame()) |
| 159 m_histogram.record(); | 181 m_histogram.record(); |
| 160 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 182 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
| 161 return; | 183 return; |
| 162 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp ty())) | 184 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyPromises.isEmpty())) |
| 163 return; | 185 return; |
| 164 if (!m_timer.isActive()) | 186 if (!m_timer.isActive()) |
| 165 m_timer.startOneShot(0); | 187 m_timer.startOneShot(0); |
| 166 } | 188 } |
| 167 | 189 |
| 168 void FontFaceSet::timerFired(Timer<FontFaceSet>*) | 190 void FontFaceSet::timerFired(Timer<FontFaceSet>*) |
| 169 { | 191 { |
| 170 firePendingEvents(); | 192 firePendingEvents(); |
| 171 firePendingCallbacks(); | 193 resolvePendingLoadPromises(); |
| 172 fireDoneEventIfPossible(); | 194 fireDoneEventIfPossible(); |
| 173 } | 195 } |
| 174 | 196 |
| 175 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) | 197 void FontFaceSet::scheduleEvent(PassRefPtr<Event> event) |
| 176 { | 198 { |
| 177 m_pendingEvents.append(event); | 199 m_pendingEvents.append(event); |
| 178 if (!m_timer.isActive()) | 200 if (!m_timer.isActive()) |
| 179 m_timer.startOneShot(0); | 201 m_timer.startOneShot(0); |
| 180 } | 202 } |
| 181 | 203 |
| 182 void FontFaceSet::firePendingEvents() | 204 void FontFaceSet::firePendingEvents() |
| 183 { | 205 { |
| 184 if (m_pendingEvents.isEmpty()) | 206 if (m_pendingEvents.isEmpty()) |
| 185 return; | 207 return; |
| 186 | 208 |
| 187 Vector<RefPtr<Event> > pendingEvents; | 209 Vector<RefPtr<Event> > pendingEvents; |
| 188 m_pendingEvents.swap(pendingEvents); | 210 m_pendingEvents.swap(pendingEvents); |
| 189 for (size_t index = 0; index < pendingEvents.size(); ++index) | 211 for (size_t index = 0; index < pendingEvents.size(); ++index) |
| 190 dispatchEvent(pendingEvents[index].release()); | 212 dispatchEvent(pendingEvents[index].release()); |
| 191 } | 213 } |
| 192 | 214 |
| 193 void FontFaceSet::scheduleCallback(PassRefPtr<VoidCallback> callback) | 215 void FontFaceSet::scheduleResolve(LoadFontPromiseResolver* resolver) |
| 194 { | 216 { |
| 195 m_pendingCallbacks.append(callback); | 217 m_pendingLoadPromises.append(resolver); |
| 196 if (!m_timer.isActive()) | 218 if (!m_timer.isActive()) |
| 197 m_timer.startOneShot(0); | 219 m_timer.startOneShot(0); |
| 198 } | 220 } |
| 199 | 221 |
| 200 void FontFaceSet::firePendingCallbacks() | 222 void FontFaceSet::resolvePendingLoadPromises() |
| 201 { | 223 { |
| 202 if (m_pendingCallbacks.isEmpty()) | 224 if (m_pendingLoadPromises.isEmpty()) |
| 203 return; | 225 return; |
| 204 | 226 |
| 205 Vector<RefPtr<VoidCallback> > pendingCallbacks; | 227 Vector<RefPtr<LoadFontPromiseResolver> > resolvers; |
| 206 m_pendingCallbacks.swap(pendingCallbacks); | 228 m_pendingLoadPromises.swap(resolvers); |
| 207 for (size_t index = 0; index < pendingCallbacks.size(); ++index) | 229 for (size_t index = 0; index < resolvers.size(); ++index) |
| 208 pendingCallbacks[index]->handleEvent(); | 230 resolvers[index]->resolve(); |
| 209 } | 231 } |
| 210 | 232 |
| 211 void FontFaceSet::beginFontLoading(FontFace* fontFace) | 233 void FontFaceSet::beginFontLoading(FontFace* fontFace) |
| 212 { | 234 { |
| 213 m_histogram.incrementCount(); | 235 m_histogram.incrementCount(); |
| 214 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) | 236 if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) |
| 215 return; | 237 return; |
| 216 | 238 |
| 217 ++m_loadingCount; | 239 ++m_loadingCount; |
| 218 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) | 240 if (m_loadingCount == 1 && !m_shouldFireDoneEvent) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 241 ASSERT(m_loadingCount > 0); | 263 ASSERT(m_loadingCount > 0); |
| 242 --m_loadingCount; | 264 --m_loadingCount; |
| 243 if (!m_loadingCount) { | 265 if (!m_loadingCount) { |
| 244 ASSERT(!m_shouldFireDoneEvent); | 266 ASSERT(!m_shouldFireDoneEvent); |
| 245 m_shouldFireDoneEvent = true; | 267 m_shouldFireDoneEvent = true; |
| 246 if (!m_timer.isActive()) | 268 if (!m_timer.isActive()) |
| 247 m_timer.startOneShot(0); | 269 m_timer.startOneShot(0); |
| 248 } | 270 } |
| 249 } | 271 } |
| 250 | 272 |
| 251 void FontFaceSet::notifyWhenFontsReady(PassRefPtr<VoidCallback> callback) | 273 ScriptPromise FontFaceSet::ready() |
| 252 { | 274 { |
| 253 m_fontsReadyCallbacks.append(callback); | 275 OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::crea te(scriptExecutionContext()); |
| 276 ScriptPromise promise = resolver->promise(); | |
|
yhirano
2013/09/18 11:49:45
You should call ScriptPromiseResolver::detachPromi
Kunihiko Sakamoto
2013/09/19 01:14:26
Changed FontsReadyPromiseResolver::promise() detac
| |
| 277 m_readyPromises.append(resolver.release()); | |
| 254 if (!m_timer.isActive()) | 278 if (!m_timer.isActive()) |
| 255 m_timer.startOneShot(0); | 279 m_timer.startOneShot(0); |
| 280 return promise; | |
| 256 } | 281 } |
| 257 | 282 |
| 258 void FontFaceSet::fireDoneEventIfPossible() | 283 void FontFaceSet::fireDoneEventIfPossible() |
| 259 { | 284 { |
| 260 if (!m_pendingEvents.isEmpty() || !m_pendingCallbacks.isEmpty()) | 285 if (!m_pendingEvents.isEmpty() || !m_pendingLoadPromises.isEmpty()) |
| 261 return; | 286 return; |
| 262 if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmp ty())) | 287 if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyPromises.isEmpty())) |
| 263 return; | 288 return; |
| 264 | 289 |
| 265 // If the layout was invalidated in between when we thought layout | 290 // 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 | 291 // was updated and when we're ready to fire the event, just wait |
| 267 // until after the next layout before firing events. | 292 // until after the next layout before firing events. |
| 268 Document* d = document(); | 293 Document* d = document(); |
| 269 if (!d->view() || d->view()->needsLayout()) | 294 if (!d->view() || d->view()->needsLayout()) |
| 270 return; | 295 return; |
| 271 | 296 |
| 272 if (m_shouldFireDoneEvent) { | 297 if (m_shouldFireDoneEvent) { |
| 273 m_shouldFireDoneEvent = false; | 298 m_shouldFireDoneEvent = false; |
| 274 RefPtr<CSSFontFaceLoadEvent> doneEvent; | 299 RefPtr<CSSFontFaceLoadEvent> doneEvent; |
| 275 RefPtr<CSSFontFaceLoadEvent> errorEvent; | 300 RefPtr<CSSFontFaceLoadEvent> errorEvent; |
| 276 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin gdoneEvent, m_loadedFonts); | 301 doneEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().loadin gdoneEvent, m_loadedFonts); |
| 277 m_loadedFonts.clear(); | 302 m_loadedFonts.clear(); |
| 278 if (!m_failedFonts.isEmpty()) { | 303 if (!m_failedFonts.isEmpty()) { |
| 279 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l oadingerrorEvent, m_failedFonts); | 304 errorEvent = CSSFontFaceLoadEvent::createForFontFaces(eventNames().l oadingerrorEvent, m_failedFonts); |
| 280 m_failedFonts.clear(); | 305 m_failedFonts.clear(); |
| 281 } | 306 } |
| 282 dispatchEvent(doneEvent); | 307 dispatchEvent(doneEvent); |
| 283 if (errorEvent) | 308 if (errorEvent) |
| 284 dispatchEvent(errorEvent); | 309 dispatchEvent(errorEvent); |
| 285 } | 310 } |
| 286 | 311 |
| 287 if (!m_fontsReadyCallbacks.isEmpty()) { | 312 if (!m_readyPromises.isEmpty()) { |
| 288 Vector<RefPtr<VoidCallback> > callbacks; | 313 Vector<OwnPtr<FontsReadyPromiseResolver> > resolvers; |
| 289 m_fontsReadyCallbacks.swap(callbacks); | 314 m_readyPromises.swap(resolvers); |
| 290 for (size_t index = 0; index < callbacks.size(); ++index) | 315 for (size_t index = 0; index < resolvers.size(); ++index) |
| 291 callbacks[index]->handleEvent(); | 316 resolvers[index]->call(this); |
| 292 } | 317 } |
| 293 } | 318 } |
| 294 | 319 |
| 295 void FontFaceSet::loadFont(const Dictionary& params) | 320 Vector<RefPtr<FontFace> > FontFaceSet::match(const String& fontString, const Str ing&, ExceptionState& es) |
| 296 { | 321 { |
| 297 // FIXME: The text member of params is ignored. | 322 // FIXME: The second parameter (text) is ignored. |
| 298 String fontString; | 323 Vector<RefPtr<FontFace> > matchedFonts; |
| 299 if (!params.get("font", fontString)) | 324 |
| 300 return; | |
| 301 Font font; | 325 Font font; |
| 302 if (!resolveFontStyle(fontString, font)) | 326 if (!resolveFontStyle(fontString, font)) { |
| 303 return; | 327 es.throwDOMException(SyntaxError); |
| 304 RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(param s, font.family()); | 328 return matchedFonts; |
| 329 } | |
| 305 | 330 |
| 306 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 331 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 332 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector() ->getFontFace(font.fontDescription(), f->family()); | |
| 333 if (face) | |
| 334 matchedFonts.append(face->fontFaces()); | |
| 335 } | |
| 336 return matchedFonts; | |
| 337 } | |
| 338 | |
| 339 ScriptPromise FontFaceSet::load(const String& fontString, const String&, Excepti onState& es) | |
| 340 { | |
| 341 // FIXME: The second parameter (text) is ignored. | |
| 342 Font font; | |
| 343 if (!resolveFontStyle(fontString, font)) { | |
| 344 es.throwDOMException(SyntaxError); | |
| 345 return ScriptPromise(); | |
| 346 } | |
| 347 | |
| 348 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f ont.family(), scriptExecutionContext()); | |
| 349 for (const FontFamily* f = &font.family(); f; f = f->next()) { | |
| 307 Document* d = document(); | 350 Document* d = document(); |
| 308 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont Face(font.fontDescription(), f->family()); | 351 CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFont Face(font.fontDescription(), f->family()); |
| 309 if (!face) { | 352 if (!face) { |
| 310 if (callback) | 353 resolver->error(d); |
| 311 callback->error(d); | |
| 312 continue; | 354 continue; |
| 313 } | 355 } |
| 314 face->loadFont(font.fontDescription(), callback); | 356 face->loadFont(font.fontDescription(), resolver); |
| 315 } | 357 } |
|
yhirano
2013/09/18 11:49:45
What happens if face == NULL for all f in the loop
Kunihiko Sakamoto
2013/09/19 01:14:26
Then FontFaceSet::scheduleResolve is called inside
| |
| 358 return resolver->promise(); | |
|
yhirano
2013/09/18 11:49:45
You should call ScriptPromiseResolver::detachPromi
Kunihiko Sakamoto
2013/09/19 01:14:26
Now LoadFontPromiseResolver::promise() does that.
| |
| 316 } | 359 } |
| 317 | 360 |
| 318 bool FontFaceSet::checkFont(const String& fontString, const String&) | 361 bool FontFaceSet::check(const String& fontString, const String&, ExceptionState& es) |
| 319 { | 362 { |
| 320 // FIXME: The second parameter (text) is ignored. | 363 // FIXME: The second parameter (text) is ignored. |
| 321 Font font; | 364 Font font; |
| 322 if (!resolveFontStyle(fontString, font)) | 365 if (!resolveFontStyle(fontString, font)) { |
| 366 es.throwDOMException(SyntaxError); | |
| 323 return false; | 367 return false; |
| 368 } | |
| 369 | |
| 324 for (const FontFamily* f = &font.family(); f; f = f->next()) { | 370 for (const FontFamily* f = &font.family(); f; f = f->next()) { |
| 325 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector() ->getFontFace(font.fontDescription(), f->family()); | 371 CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector() ->getFontFace(font.fontDescription(), f->family()); |
| 326 if (!face || !face->checkFont()) | 372 if (!face || !face->checkFont()) |
| 327 return false; | 373 return false; |
| 328 } | 374 } |
| 329 return true; | 375 return true; |
| 330 } | 376 } |
| 331 | 377 |
| 332 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) | 378 bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) |
| 333 { | 379 { |
| 380 if (fontString.isEmpty()) | |
| 381 return false; | |
| 382 | |
| 334 // Interpret fontString in the same way as the 'font' attribute of CanvasRen deringContext2D. | 383 // Interpret fontString in the same way as the 'font' attribute of CanvasRen deringContext2D. |
| 335 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat e(); | 384 RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::creat e(); |
| 336 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, CSSStrictMode, 0); | 385 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, CSSStrictMode, 0); |
| 337 if (parsedStyle->isEmpty()) | 386 if (parsedStyle->isEmpty()) |
| 338 return false; | 387 return false; |
| 339 | 388 |
| 340 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); | 389 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); |
| 341 if (fontValue == "inherit" || fontValue == "initial") | 390 if (fontValue == "inherit" || fontValue == "initial") |
| 342 return false; | 391 return false; |
| 343 | 392 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 374 | 423 |
| 375 void FontFaceSet::FontLoadHistogram::record() | 424 void FontFaceSet::FontLoadHistogram::record() |
| 376 { | 425 { |
| 377 if (m_recorded) | 426 if (m_recorded) |
| 378 return; | 427 return; |
| 379 m_recorded = true; | 428 m_recorded = true; |
| 380 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1 , 100, 50); | 429 HistogramSupport::histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1 , 100, 50); |
| 381 } | 430 } |
| 382 | 431 |
| 383 } // namespace WebCore | 432 } // namespace WebCore |
| OLD | NEW |