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 |