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 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 #include "core/dom/StyleEngine.h" | 42 #include "core/dom/StyleEngine.h" |
43 #include "core/frame/FrameView.h" | 43 #include "core/frame/FrameView.h" |
44 #include "core/frame/LocalFrame.h" | 44 #include "core/frame/LocalFrame.h" |
45 #include "public/platform/Platform.h" | 45 #include "public/platform/Platform.h" |
46 | 46 |
47 namespace WebCore { | 47 namespace WebCore { |
48 | 48 |
49 static const int defaultFontSize = 10; | 49 static const int defaultFontSize = 10; |
50 static const char defaultFontFamily[] = "sans-serif"; | 50 static const char defaultFontFamily[] = "sans-serif"; |
51 | 51 |
52 class LoadFontPromiseResolver : public CSSSegmentedFontFace::LoadFontCallback { | 52 class LoadFontPromiseResolver : public FontFace::LoadFontCallback { |
53 public: | 53 public: |
54 static PassRefPtr<LoadFontPromiseResolver> create(const FontFamily& family,
ExecutionContext* context) | 54 static PassRefPtr<LoadFontPromiseResolver> create(FontFaceArray faces, Execu
tionContext* context) |
55 { | 55 { |
56 int numFamilies = 0; | 56 return adoptRef(new LoadFontPromiseResolver(faces, context)); |
57 for (const FontFamily* f = &family; f; f = f->next()) | |
58 numFamilies++; | |
59 return adoptRef<LoadFontPromiseResolver>(new LoadFontPromiseResolver(num
Families, context)); | |
60 } | 57 } |
61 | 58 |
| 59 void loadFonts(ExecutionContext*); |
62 ScriptPromise promise() { return m_resolver->promise(); } | 60 ScriptPromise promise() { return m_resolver->promise(); } |
63 | 61 |
64 virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE { loaded(); } | 62 virtual void notifyLoaded(FontFace*) OVERRIDE; |
65 virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE { error(); } | 63 virtual void notifyError(FontFace*) OVERRIDE; |
66 void loaded(); | |
67 void error(); | |
68 | 64 |
69 private: | 65 private: |
70 LoadFontPromiseResolver(int numLoading, ExecutionContext* context) | 66 LoadFontPromiseResolver(FontFaceArray faces, ExecutionContext* context) |
71 : m_numLoading(numLoading) | 67 : m_numLoading(faces.size()) |
72 , m_errorOccured(false) | 68 , m_errorOccured(false) |
73 , m_scriptState(ScriptState::current()) | 69 , m_scriptState(ScriptState::current()) |
74 , m_resolver(ScriptPromiseResolver::create(context)) | 70 , m_resolver(ScriptPromiseResolver::create(context)) |
75 { } | 71 { |
| 72 m_fontFaces.swap(faces); |
| 73 } |
76 | 74 |
| 75 FontFaceArray m_fontFaces; |
77 int m_numLoading; | 76 int m_numLoading; |
78 bool m_errorOccured; | 77 bool m_errorOccured; |
79 ScriptState* m_scriptState; | 78 ScriptState* m_scriptState; |
80 RefPtr<ScriptPromiseResolver> m_resolver; | 79 RefPtr<ScriptPromiseResolver> m_resolver; |
81 }; | 80 }; |
82 | 81 |
83 void LoadFontPromiseResolver::loaded() | 82 void LoadFontPromiseResolver::loadFonts(ExecutionContext* context) |
| 83 { |
| 84 if (!m_numLoading) { |
| 85 m_resolver->resolve(m_fontFaces); |
| 86 return; |
| 87 } |
| 88 |
| 89 for (size_t i = 0; i < m_fontFaces.size(); i++) |
| 90 m_fontFaces[i]->load(this, context); |
| 91 } |
| 92 |
| 93 void LoadFontPromiseResolver::notifyLoaded(FontFace* fontFace) |
84 { | 94 { |
85 m_numLoading--; | 95 m_numLoading--; |
86 if (m_numLoading) | 96 if (m_numLoading || m_errorOccured) |
87 return; | 97 return; |
88 | 98 |
89 ScriptScope scope(m_scriptState); | 99 ScriptScope scope(m_scriptState); |
90 if (m_errorOccured) | 100 m_resolver->resolve(m_fontFaces); |
91 m_resolver->reject(ScriptValue::createNull()); | |
92 else | |
93 m_resolver->resolve(ScriptValue::createNull()); | |
94 } | 101 } |
95 | 102 |
96 void LoadFontPromiseResolver::error() | 103 void LoadFontPromiseResolver::notifyError(FontFace* fontFace) |
97 { | 104 { |
98 m_errorOccured = true; | 105 m_numLoading--; |
99 loaded(); | 106 if (!m_errorOccured) { |
| 107 m_errorOccured = true; |
| 108 ScriptScope scope(m_scriptState); |
| 109 m_resolver->reject(fontFace->error()); |
| 110 } |
100 } | 111 } |
101 | 112 |
102 class FontsReadyPromiseResolver { | 113 class FontsReadyPromiseResolver { |
103 public: | 114 public: |
104 static PassOwnPtr<FontsReadyPromiseResolver> create(ExecutionContext* contex
t) | 115 static PassOwnPtr<FontsReadyPromiseResolver> create(ExecutionContext* contex
t) |
105 { | 116 { |
106 return adoptPtr(new FontsReadyPromiseResolver(context)); | 117 return adoptPtr(new FontsReadyPromiseResolver(context)); |
107 } | 118 } |
108 | 119 |
109 void resolve(PassRefPtr<FontFaceSet> fontFaceSet) | 120 void resolve(PassRefPtr<FontFaceSet> fontFaceSet) |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 resolvers[index]->resolve(this); | 427 resolvers[index]->resolve(this); |
417 } | 428 } |
418 } | 429 } |
419 | 430 |
420 static const String& nullToSpace(const String& s) | 431 static const String& nullToSpace(const String& s) |
421 { | 432 { |
422 DEFINE_STATIC_LOCAL(String, space, (" ")); | 433 DEFINE_STATIC_LOCAL(String, space, (" ")); |
423 return s.isNull() ? space : s; | 434 return s.isNull() ? space : s; |
424 } | 435 } |
425 | 436 |
426 ScriptPromise FontFaceSet::load(const String& fontString, const String& text, Ex
ceptionState& exceptionState) | 437 ScriptPromise FontFaceSet::load(const String& fontString, const String& text) |
427 { | 438 { |
428 if (!inActiveDocumentContext()) | 439 if (!inActiveDocumentContext()) |
429 return ScriptPromise(); | 440 return ScriptPromise(); |
430 | 441 |
431 Font font; | 442 Font font; |
432 if (!resolveFontStyle(fontString, font)) { | 443 if (!resolveFontStyle(fontString, font)) { |
433 exceptionState.throwDOMException(SyntaxError, "Could not resolve '" + fo
ntString + "' as a font."); | 444 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(e
xecutionContext()); |
434 return ScriptPromise(); | 445 ScriptPromise promise = resolver->promise(); |
| 446 resolver->reject(DOMError::create(SyntaxError, "Could not resolve '" + f
ontString + "' as a font.")); |
| 447 return promise; |
435 } | 448 } |
436 | 449 |
437 CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); | 450 FontFaceCache* fontFaceCache = document()->styleEngine()->fontSelector()->fo
ntFaceCache(); |
438 FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); | 451 FontFaceArray faces; |
439 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f
ont.fontDescription().family(), executionContext()); | 452 for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next(
)) { |
| 453 CSSSegmentedFontFace* segmentedFontFace = fontFaceCache->get(font.fontDe
scription(), f->family()); |
| 454 if (segmentedFontFace) |
| 455 segmentedFontFace->match(nullToSpace(text), faces); |
| 456 } |
| 457 |
| 458 RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(f
aces, executionContext()); |
440 ScriptPromise promise = resolver->promise(); | 459 ScriptPromise promise = resolver->promise(); |
441 for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next(
)) { | 460 resolver->loadFonts(executionContext()); // After this, resolver->promise()
may return null. |
442 CSSSegmentedFontFace* face = fontFaceCache->get(font.fontDescription(),
f->family()); | |
443 if (!face) { | |
444 resolver->error(); | |
445 continue; | |
446 } | |
447 face->loadFont(font.fontDescription(), nullToSpace(text), resolver); | |
448 } | |
449 fontSelector->loadPendingFonts(); | |
450 return promise; | 461 return promise; |
451 } | 462 } |
452 | 463 |
453 bool FontFaceSet::check(const String& fontString, const String& text, ExceptionS
tate& exceptionState) | 464 bool FontFaceSet::check(const String& fontString, const String& text, ExceptionS
tate& exceptionState) |
454 { | 465 { |
455 if (!inActiveDocumentContext()) | 466 if (!inActiveDocumentContext()) |
456 return false; | 467 return false; |
457 | 468 |
458 Font font; | 469 Font font; |
459 if (!resolveFontStyle(fontString, font)) { | 470 if (!resolveFontStyle(fontString, font)) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 } | 566 } |
556 | 567 |
557 void FontFaceSet::didLayout(Document& document) | 568 void FontFaceSet::didLayout(Document& document) |
558 { | 569 { |
559 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) | 570 if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(docu
ment, supplementName()))) |
560 fonts->didLayout(); | 571 fonts->didLayout(); |
561 } | 572 } |
562 | 573 |
563 | 574 |
564 } // namespace WebCore | 575 } // namespace WebCore |
OLD | NEW |