Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(640)

Unified Diff: Source/core/css/FontFaceSet.cpp

Issue 23717059: [Font Load Events] Implement FontFaceSet methods (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/css/FontFaceSet.h ('k') | Source/core/css/FontFaceSet.idl » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/css/FontFaceSet.cpp
diff --git a/Source/core/css/FontFaceSet.cpp b/Source/core/css/FontFaceSet.cpp
index 0af91b4b87649c1a9cbe255bac1b1e3fc1088a6e..c9838d2df51298ff3a7e460aa6f16527939f448c 100644
--- a/Source/core/css/FontFaceSet.cpp
+++ b/Source/core/css/FontFaceSet.cpp
@@ -27,7 +27,11 @@
#include "core/css/FontFaceSet.h"
#include "RuntimeEnabledFeatures.h"
+#include "V8FontFaceSet.h"
#include "bindings/v8/Dictionary.h"
+#include "bindings/v8/ScriptPromiseResolver.h"
+#include "bindings/v8/ScriptScope.h"
+#include "bindings/v8/ScriptState.h"
#include "core/css/CSSFontFaceLoadEvent.h"
#include "core/css/CSSFontFaceSource.h"
#include "core/css/CSSFontSelector.h"
@@ -44,76 +48,106 @@ namespace WebCore {
static const int defaultFontSize = 10;
static const char* const defaultFontFamily = "sans-serif";
-class LoadFontCallback : public CSSSegmentedFontFace::LoadFontCallback {
+class LoadFontPromiseResolver : public CSSSegmentedFontFace::LoadFontCallback {
public:
- static PassRefPtr<LoadFontCallback> create(int numLoading, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
+ static PassRefPtr<LoadFontPromiseResolver> create(const FontFamily& family, ScriptExecutionContext* context)
{
- return adoptRef<LoadFontCallback>(new LoadFontCallback(numLoading, loadCallback, errorCallback));
- }
-
- static PassRefPtr<LoadFontCallback> createFromParams(const Dictionary& params, const FontFamily& family)
- {
- RefPtr<VoidCallback> onsuccess;
- RefPtr<VoidCallback> onerror;
- params.get("onsuccess", onsuccess);
- params.get("onerror", onerror);
- if (!onsuccess && !onerror)
- return 0;
int numFamilies = 0;
for (const FontFamily* f = &family; f; f = f->next())
numFamilies++;
- return LoadFontCallback::create(numFamilies, onsuccess, onerror);
+ return adoptRef<LoadFontPromiseResolver>(new LoadFontPromiseResolver(numFamilies, context));
}
virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE;
virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE;
void loaded(Document*);
void error(Document*);
+ void resolve();
+
+ ScriptPromise promise()
+ {
+ ScriptPromise promise = m_resolver->promise();
+ m_resolver->detachPromise();
+ return promise;
+ }
+
private:
- LoadFontCallback(int numLoading, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
+ LoadFontPromiseResolver(int numLoading, ScriptExecutionContext* context)
: m_numLoading(numLoading)
, m_errorOccured(false)
- , m_loadCallback(loadCallback)
- , m_errorCallback(errorCallback)
+ , m_scriptState(ScriptState::current())
+ , m_resolver(ScriptPromiseResolver::create(context))
{ }
int m_numLoading;
bool m_errorOccured;
- RefPtr<VoidCallback> m_loadCallback;
- RefPtr<VoidCallback> m_errorCallback;
+ ScriptState* m_scriptState;
+ RefPtr<ScriptPromiseResolver> m_resolver;
};
-void LoadFontCallback::loaded(Document* document)
+void LoadFontPromiseResolver::loaded(Document* document)
{
m_numLoading--;
if (m_numLoading || !document)
return;
- if (m_errorOccured) {
- if (m_errorCallback)
- document->fonts()->scheduleCallback(m_errorCallback.release());
- } else {
- if (m_loadCallback)
- document->fonts()->scheduleCallback(m_loadCallback.release());
- }
+ document->fonts()->scheduleResolve(this);
}
-void LoadFontCallback::error(Document* document)
+void LoadFontPromiseResolver::error(Document* document)
{
m_errorOccured = true;
loaded(document);
}
-void LoadFontCallback::notifyLoaded(CSSSegmentedFontFace* face)
+void LoadFontPromiseResolver::notifyLoaded(CSSSegmentedFontFace* face)
{
loaded(face->fontSelector()->document());
}
-void LoadFontCallback::notifyError(CSSSegmentedFontFace* face)
+void LoadFontPromiseResolver::notifyError(CSSSegmentedFontFace* face)
{
error(face->fontSelector()->document());
}
+void LoadFontPromiseResolver::resolve()
+{
+ ScriptScope scope(m_scriptState);
+ if (m_errorOccured)
+ m_resolver->reject(ScriptValue::createNull());
+ else
+ m_resolver->fulfill(ScriptValue::createNull());
+}
+
+class FontsReadyPromiseResolver {
+public:
+ static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptExecutionContext* context)
+ {
+ return adoptPtr(new FontsReadyPromiseResolver(context));
+ }
+
+ void call(PassRefPtr<FontFaceSet> fontFaceSet)
+ {
+ ScriptScope scope(m_scriptState);
+ m_resolver->fulfill(fontFaceSet);
+ }
+
+ ScriptPromise promise()
+ {
+ ScriptPromise promise = m_resolver->promise();
+ m_resolver->detachPromise();
+ return promise;
+ }
+
+private:
+ FontsReadyPromiseResolver(ScriptExecutionContext* context)
+ : m_scriptState(ScriptState::current())
+ , m_resolver(ScriptPromiseResolver::create(context))
+ { }
+ ScriptState* m_scriptState;
+ RefPtr<ScriptPromiseResolver> m_resolver;
+};
+
FontFaceSet::FontFaceSet(Document* document)
: ActiveDOMObject(document)
, m_loadingCount(0)
@@ -152,6 +186,13 @@ ScriptExecutionContext* FontFaceSet::scriptExecutionContext() const
return ActiveDOMObject::scriptExecutionContext();
}
+AtomicString FontFaceSet::status() const
+{
+ DEFINE_STATIC_LOCAL(AtomicString, loading, ("loading", AtomicString::ConstructFromLiteral));
+ DEFINE_STATIC_LOCAL(AtomicString, loaded, ("loaded", AtomicString::ConstructFromLiteral));
+ return (m_loadingCount > 0 || m_shouldFireDoneEvent) ? loading : loaded;
+}
+
void FontFaceSet::didLayout()
{
Document* d = document();
@@ -159,7 +200,7 @@ void FontFaceSet::didLayout()
m_histogram.record();
if (!RuntimeEnabledFeatures::fontLoadEventsEnabled())
return;
- if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmpty()))
+ if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty()))
return;
if (!m_timer.isActive())
m_timer.startOneShot(0);
@@ -168,7 +209,7 @@ void FontFaceSet::didLayout()
void FontFaceSet::timerFired(Timer<FontFaceSet>*)
{
firePendingEvents();
- firePendingCallbacks();
+ resolvePendingLoadPromises();
fireDoneEventIfPossible();
}
@@ -190,22 +231,22 @@ void FontFaceSet::firePendingEvents()
dispatchEvent(pendingEvents[index].release());
}
-void FontFaceSet::scheduleCallback(PassRefPtr<VoidCallback> callback)
+void FontFaceSet::scheduleResolve(LoadFontPromiseResolver* resolver)
{
- m_pendingCallbacks.append(callback);
+ m_pendingLoadResolvers.append(resolver);
if (!m_timer.isActive())
m_timer.startOneShot(0);
}
-void FontFaceSet::firePendingCallbacks()
+void FontFaceSet::resolvePendingLoadPromises()
{
- if (m_pendingCallbacks.isEmpty())
+ if (m_pendingLoadResolvers.isEmpty())
return;
- Vector<RefPtr<VoidCallback> > pendingCallbacks;
- m_pendingCallbacks.swap(pendingCallbacks);
- for (size_t index = 0; index < pendingCallbacks.size(); ++index)
- pendingCallbacks[index]->handleEvent();
+ Vector<RefPtr<LoadFontPromiseResolver> > resolvers;
+ m_pendingLoadResolvers.swap(resolvers);
+ for (size_t index = 0; index < resolvers.size(); ++index)
+ resolvers[index]->resolve();
}
void FontFaceSet::beginFontLoading(FontFace* fontFace)
@@ -248,18 +289,21 @@ void FontFaceSet::queueDoneEvent(FontFace* fontFace)
}
}
-void FontFaceSet::notifyWhenFontsReady(PassRefPtr<VoidCallback> callback)
+ScriptPromise FontFaceSet::ready()
{
- m_fontsReadyCallbacks.append(callback);
+ OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::create(scriptExecutionContext());
+ ScriptPromise promise = resolver->promise();
+ m_readyResolvers.append(resolver.release());
if (!m_timer.isActive())
m_timer.startOneShot(0);
+ return promise;
}
void FontFaceSet::fireDoneEventIfPossible()
{
- if (!m_pendingEvents.isEmpty() || !m_pendingCallbacks.isEmpty())
+ if (!m_pendingEvents.isEmpty() || !m_pendingLoadResolvers.isEmpty())
return;
- if (m_loadingCount || (!m_shouldFireDoneEvent && m_fontsReadyCallbacks.isEmpty()))
+ if (m_loadingCount || (!m_shouldFireDoneEvent && m_readyResolvers.isEmpty()))
return;
// If the layout was invalidated in between when we thought layout
@@ -284,43 +328,64 @@ void FontFaceSet::fireDoneEventIfPossible()
dispatchEvent(errorEvent);
}
- if (!m_fontsReadyCallbacks.isEmpty()) {
- Vector<RefPtr<VoidCallback> > callbacks;
- m_fontsReadyCallbacks.swap(callbacks);
- for (size_t index = 0; index < callbacks.size(); ++index)
- callbacks[index]->handleEvent();
+ if (!m_readyResolvers.isEmpty()) {
+ Vector<OwnPtr<FontsReadyPromiseResolver> > resolvers;
+ m_readyResolvers.swap(resolvers);
+ for (size_t index = 0; index < resolvers.size(); ++index)
+ resolvers[index]->call(this);
}
}
-void FontFaceSet::loadFont(const Dictionary& params)
+Vector<RefPtr<FontFace> > FontFaceSet::match(const String& fontString, const String&, ExceptionState& es)
{
- // FIXME: The text member of params is ignored.
- String fontString;
- if (!params.get("font", fontString))
- return;
+ // FIXME: The second parameter (text) is ignored.
+ Vector<RefPtr<FontFace> > matchedFonts;
+
Font font;
- if (!resolveFontStyle(fontString, font))
- return;
- RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(params, font.family());
+ if (!resolveFontStyle(fontString, font)) {
+ es.throwDOMException(SyntaxError);
+ return matchedFonts;
+ }
+
+ for (const FontFamily* f = &font.family(); f; f = f->next()) {
+ CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()->getFontFace(font.fontDescription(), f->family());
+ if (face)
+ matchedFonts.append(face->fontFaces());
+ }
+ return matchedFonts;
+}
+
+ScriptPromise FontFaceSet::load(const String& fontString, const String&, ExceptionState& es)
+{
+ // FIXME: The second parameter (text) is ignored.
+ Font font;
+ if (!resolveFontStyle(fontString, font)) {
+ es.throwDOMException(SyntaxError);
+ return ScriptPromise();
+ }
+ Document* d = document();
+ RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(font.family(), scriptExecutionContext());
for (const FontFamily* f = &font.family(); f; f = f->next()) {
- Document* d = document();
CSSSegmentedFontFace* face = d->styleResolver()->fontSelector()->getFontFace(font.fontDescription(), f->family());
if (!face) {
- if (callback)
- callback->error(d);
+ resolver->error(d);
continue;
}
- face->loadFont(font.fontDescription(), callback);
+ face->loadFont(font.fontDescription(), resolver);
}
+ return resolver->promise();
}
-bool FontFaceSet::checkFont(const String& fontString, const String&)
+bool FontFaceSet::check(const String& fontString, const String&, ExceptionState& es)
{
// FIXME: The second parameter (text) is ignored.
Font font;
- if (!resolveFontStyle(fontString, font))
+ if (!resolveFontStyle(fontString, font)) {
+ es.throwDOMException(SyntaxError);
return false;
+ }
+
for (const FontFamily* f = &font.family(); f; f = f->next()) {
CSSSegmentedFontFace* face = document()->styleResolver()->fontSelector()->getFontFace(font.fontDescription(), f->family());
if (!face || !face->checkFont())
@@ -331,6 +396,9 @@ bool FontFaceSet::checkFont(const String& fontString, const String&)
bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font)
{
+ if (fontString.isEmpty())
+ return false;
+
// Interpret fontString in the same way as the 'font' attribute of CanvasRenderingContext2D.
RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create();
CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, CSSStrictMode, 0);
« no previous file with comments | « Source/core/css/FontFaceSet.h ('k') | Source/core/css/FontFaceSet.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698