summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/FontLoader.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/css/FontLoader.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/css/FontLoader.cpp')
-rw-r--r--Source/WebCore/css/FontLoader.cpp178
1 files changed, 100 insertions, 78 deletions
diff --git a/Source/WebCore/css/FontLoader.cpp b/Source/WebCore/css/FontLoader.cpp
index 8e1f948ed..e1be4748e 100644
--- a/Source/WebCore/css/FontLoader.cpp
+++ b/Source/WebCore/css/FontLoader.cpp
@@ -35,8 +35,10 @@
#include "CSSSegmentedFontFace.h"
#include "Dictionary.h"
#include "Document.h"
+#include "ExceptionCodeDescription.h"
+#include "FontCascade.h"
#include "FrameView.h"
-#include "StylePropertySet.h"
+#include "StyleProperties.h"
#include "StyleResolver.h"
namespace WebCore {
@@ -46,12 +48,12 @@ static const char* const defaultFontFamily = "sans-serif";
class LoadFontCallback : public CSSSegmentedFontFace::LoadFontCallback {
public:
- static PassRefPtr<LoadFontCallback> create(int numLoading, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
+ static Ref<LoadFontCallback> create(int numLoading, FontLoader& fontLoader, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
{
- return adoptRef<LoadFontCallback>(new LoadFontCallback(numLoading, loadCallback, errorCallback));
+ return adoptRef(*new LoadFontCallback(numLoading, fontLoader, loadCallback, errorCallback));
}
- static PassRefPtr<LoadFontCallback> createFromParams(const Dictionary& params, const FontFamily& family)
+ static PassRefPtr<LoadFontCallback> createFromParams(const Dictionary& params, FontLoader& fontLoader, const FontCascade& font)
{
RefPtr<VoidCallback> onsuccess;
RefPtr<VoidCallback> onerror;
@@ -59,24 +61,30 @@ public:
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);
+ int numFamilies = font.familyCount();
+ return LoadFontCallback::create(numFamilies, fontLoader, onsuccess, onerror);
}
- virtual void notifyLoaded() OVERRIDE;
- virtual void notifyError() OVERRIDE;
+ virtual void notifyLoaded() override;
+ virtual void notifyError() override;
+ virtual ~LoadFontCallback() { };
+
+ int familyCount() const { return m_familyCount; }
+
private:
- LoadFontCallback(int numLoading, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
- : m_numLoading(numLoading)
+ LoadFontCallback(int numLoading, FontLoader& fontLoader, PassRefPtr<VoidCallback> loadCallback, PassRefPtr<VoidCallback> errorCallback)
+ : m_familyCount(numLoading)
+ , m_numLoading(numLoading)
, m_errorOccured(false)
+ , m_fontLoader(fontLoader)
, m_loadCallback(loadCallback)
, m_errorCallback(errorCallback)
{ }
+ int m_familyCount;
int m_numLoading;
bool m_errorOccured;
+ FontLoader& m_fontLoader;
RefPtr<VoidCallback> m_loadCallback;
RefPtr<VoidCallback> m_errorCallback;
};
@@ -87,6 +95,8 @@ void LoadFontCallback::notifyLoaded()
if (m_numLoading)
return;
+ m_fontLoader.loadFontDone(*this);
+
if (m_errorOccured) {
if (m_errorCallback)
m_errorCallback->handleEvent();
@@ -102,10 +112,17 @@ void LoadFontCallback::notifyError()
notifyLoaded();
}
+void FontLoader::loadFontDone(const LoadFontCallback& callback)
+{
+ m_numLoadingFromJS -= callback.familyCount();
+}
+
FontLoader::FontLoader(Document* document)
: ActiveDOMObject(document)
, m_document(document)
- , m_loadingCount(0)
+ , m_numLoadingFromCSS(0)
+ , m_numLoadingFromJS(0)
+ , m_pendingEventsTimer(*this, &FontLoader::firePendingEvents)
{
suspendIfNeeded();
}
@@ -119,14 +136,14 @@ EventTargetData* FontLoader::eventTargetData()
return &m_eventTargetData;
}
-EventTargetData* FontLoader::ensureEventTargetData()
+EventTargetData& FontLoader::ensureEventTargetData()
{
- return &m_eventTargetData;
+ return m_eventTargetData;
}
-const AtomicString& FontLoader::interfaceName() const
+EventTargetInterface FontLoader::eventTargetInterface() const
{
- return eventNames().interfaceForFontLoader;
+ return FontLoaderEventTargetInterfaceType;
}
ScriptExecutionContext* FontLoader::scriptExecutionContext() const
@@ -136,93 +153,100 @@ ScriptExecutionContext* FontLoader::scriptExecutionContext() const
void FontLoader::didLayout()
{
- firePendingEvents();
loadingDone();
}
-void FontLoader::scheduleEvent(PassRefPtr<Event> event)
+const char* FontLoader::activeDOMObjectName() const
{
- if (FrameView* view = m_document->view()) {
- if (view->isInLayout()) {
- m_pendingEvents.append(event);
- return;
- }
- }
- firePendingEvents();
- dispatchEvent(event);
+ return "FontLoader";
+}
+
+bool FontLoader::canSuspendForDocumentSuspension() const
+{
+ return !m_numLoadingFromCSS && !m_numLoadingFromJS;
+}
+
+void FontLoader::scheduleEvent(Ref<Event>&& event)
+{
+ m_pendingEvents.append(WTFMove(event));
+ if (!m_pendingEventsTimer.isActive())
+ m_pendingEventsTimer.startOneShot(0);
}
void FontLoader::firePendingEvents()
{
- if (m_pendingEvents.isEmpty())
+ if (m_pendingEvents.isEmpty() && !m_loadingDoneEvent && !m_callbacks.isEmpty())
return;
- Vector<RefPtr<Event> > pendingEvents;
+ Vector<Ref<Event>> pendingEvents;
m_pendingEvents.swap(pendingEvents);
+
+ bool loadingDone = false;
+ if (m_loadingDoneEvent) {
+ pendingEvents.append(m_loadingDoneEvent.releaseNonNull());
+ loadingDone = true;
+ }
+
for (size_t index = 0; index < pendingEvents.size(); ++index)
- dispatchEvent(pendingEvents[index].release());
+ dispatchEvent(pendingEvents[index]);
+
+ if (loadingDone && !m_callbacks.isEmpty()) {
+ Vector<RefPtr<VoidCallback>> callbacks;
+ m_callbacks.swap(callbacks);
+ for (size_t index = 0; index < callbacks.size(); ++index)
+ callbacks[index]->handleEvent();
+ }
}
void FontLoader::beginFontLoading(CSSFontFaceRule* rule)
{
- ++m_loadingCount;
- if (m_loadingCount == 1 && !m_loadingDoneEvent)
+ ++m_numLoadingFromCSS;
+ if (m_numLoadingFromCSS == 1 && !m_loadingDoneEvent)
scheduleEvent(CSSFontFaceLoadEvent::createForFontFaceRule(eventNames().loadingEvent, rule));
scheduleEvent(CSSFontFaceLoadEvent::createForFontFaceRule(eventNames().loadstartEvent, rule));
}
void FontLoader::fontLoaded(CSSFontFaceRule* rule)
{
- ASSERT(m_loadingCount > 0);
+ ASSERT(m_numLoadingFromCSS > 0);
scheduleEvent(CSSFontFaceLoadEvent::createForFontFaceRule(eventNames().loadEvent, rule));
- --m_loadingCount;
- if (!m_loadingCount)
+ --m_numLoadingFromCSS;
+ if (!m_numLoadingFromCSS)
m_loadingDoneEvent = CSSFontFaceLoadEvent::createForFontFaceRule(eventNames().loadingdoneEvent, rule);
}
void FontLoader::loadError(CSSFontFaceRule* rule, CSSFontFaceSource* source)
{
- ASSERT(m_loadingCount > 0);
+ ASSERT(m_numLoadingFromCSS > 0);
// FIXME: We should report NetworkError in case of timeout, etc.
String errorName = (source && source->isDecodeError()) ? "InvalidFontDataError" : ExceptionCodeDescription(NOT_FOUND_ERR).name;
scheduleEvent(CSSFontFaceLoadEvent::createForError(rule, DOMError::create(errorName)));
- --m_loadingCount;
- if (!m_loadingCount)
+ --m_numLoadingFromCSS;
+ if (!m_numLoadingFromCSS)
m_loadingDoneEvent = CSSFontFaceLoadEvent::createForFontFaceRule(eventNames().loadingdoneEvent, rule);
}
void FontLoader::notifyWhenFontsReady(PassRefPtr<VoidCallback> callback)
{
m_callbacks.append(callback);
- loadingDone();
}
void FontLoader::loadingDone()
{
- if (loading())
+ if (loading() || !m_document->haveStylesheetsLoaded())
return;
- if (!m_loadingDoneEvent && m_callbacks.isEmpty())
+ if (!m_loadingDoneEvent && m_callbacks.isEmpty() && m_pendingEvents.isEmpty())
return;
if (FrameView* view = m_document->view()) {
if (view->isInLayout() || view->needsLayout())
return;
- m_document->updateStyleIfNeeded();
- if (view->needsLayout())
- return;
}
- if (m_loadingDoneEvent)
- dispatchEvent(m_loadingDoneEvent.release());
-
- if (!m_callbacks.isEmpty()) {
- Vector<RefPtr<VoidCallback> > callbacks;
- m_callbacks.swap(callbacks);
- for (size_t index = 0; index < callbacks.size(); ++index)
- callbacks[index]->handleEvent();
- }
+ if (!m_pendingEventsTimer.isActive())
+ m_pendingEventsTimer.startOneShot(0);
}
void FontLoader::loadFont(const Dictionary& params)
@@ -231,13 +255,14 @@ void FontLoader::loadFont(const Dictionary& params)
String fontString;
if (!params.get("font", fontString))
return;
- Font font;
+ FontCascade font;
if (!resolveFontStyle(fontString, font))
return;
- RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(params, font.family());
-
- for (const FontFamily* f = &font.family(); f; f = f->next()) {
- CSSSegmentedFontFace* face = m_document->ensureStyleResolver()->fontSelector()->getFontFace(font.fontDescription(), f->family());
+ RefPtr<LoadFontCallback> callback = LoadFontCallback::createFromParams(params, *this, font);
+ m_numLoadingFromJS += callback->familyCount();
+
+ for (unsigned i = 0; i < font.familyCount(); i++) {
+ CSSSegmentedFontFace* face = m_document->fontSelector().getFontFace(font.fontDescription(), font.familyAt(i));
if (!face) {
if (callback)
callback->notifyError();
@@ -250,51 +275,48 @@ void FontLoader::loadFont(const Dictionary& params)
bool FontLoader::checkFont(const String& fontString, const String&)
{
// FIXME: The second parameter (text) is ignored.
- Font font;
+ FontCascade font;
if (!resolveFontStyle(fontString, font))
return false;
- for (const FontFamily* f = &font.family(); f; f = f->next()) {
- CSSSegmentedFontFace* face = m_document->ensureStyleResolver()->fontSelector()->getFontFace(font.fontDescription(), f->family());
+ for (unsigned i = 0; i < font.familyCount(); i++) {
+ CSSSegmentedFontFace* face = m_document->fontSelector().getFontFace(font.fontDescription(), font.familyAt(i));
if (!face || !face->checkFont())
return false;
}
return true;
}
-static void applyPropertyToCurrentStyle(StyleResolver* styleResolver, CSSPropertyID id, const RefPtr<StylePropertySet>& parsedStyle)
+static void applyPropertyToCurrentStyle(StyleResolver& styleResolver, CSSPropertyID id, const RefPtr<StyleProperties>& parsedStyle)
{
- styleResolver->applyPropertyToCurrentStyle(id, parsedStyle->getPropertyCSSValue(id).get());
+ styleResolver.applyPropertyToCurrentStyle(id, parsedStyle->getPropertyCSSValue(id).get());
}
-bool FontLoader::resolveFontStyle(const String& fontString, Font& font)
+bool FontLoader::resolveFontStyle(const String& fontString, FontCascade& font)
{
// 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);
+ RefPtr<MutableStyleProperties> parsedStyle = MutableStyleProperties::create();
+ CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, CSSStrictMode, nullptr);
if (parsedStyle->isEmpty())
return false;
String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
- if (fontValue == "inherit" || fontValue == "initial")
+ if (fontValue == "inherit" || fontValue == "initial" || fontValue == "unset" || fontValue == "revert")
return false;
RefPtr<RenderStyle> style = RenderStyle::create();
- FontFamily fontFamily;
- fontFamily.setFamily(defaultFontFamily);
-
FontDescription defaultFontDescription;
- defaultFontDescription.setFamily(fontFamily);
+ defaultFontDescription.setOneFamily(defaultFontFamily);
defaultFontDescription.setSpecifiedSize(defaultFontSize);
defaultFontDescription.setComputedSize(defaultFontSize);
style->setFontDescription(defaultFontDescription);
- style->font().update(style->font().fontSelector());
+ style->fontCascade().update(style->fontCascade().fontSelector());
// Now map the font property longhands into the style.
- StyleResolver* styleResolver = m_document->ensureStyleResolver();
- styleResolver->applyPropertyToStyle(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get(), style.get());
+ StyleResolver& styleResolver = m_document->ensureStyleResolver();
+ styleResolver.applyPropertyToStyle(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get(), style.get());
applyPropertyToCurrentStyle(styleResolver, CSSPropertyFontStyle, parsedStyle);
applyPropertyToCurrentStyle(styleResolver, CSSPropertyFontVariant, parsedStyle);
applyPropertyToCurrentStyle(styleResolver, CSSPropertyFontWeight, parsedStyle);
@@ -302,13 +324,13 @@ bool FontLoader::resolveFontStyle(const String& fontString, Font& font)
// As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
// which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122).
// The updateFont() calls below update the fontMetrics and ensure the proper setting of font-size and line-height.
- styleResolver->updateFont();
+ styleResolver.updateFont();
applyPropertyToCurrentStyle(styleResolver, CSSPropertyFontSize, parsedStyle);
- styleResolver->updateFont();
+ styleResolver.updateFont();
applyPropertyToCurrentStyle(styleResolver, CSSPropertyLineHeight, parsedStyle);
- font = style->font();
- font.update(styleResolver->fontSelector());
+ font = style->fontCascade();
+ font.update(&m_document->fontSelector());
return true;
}