From 6882a04fb36642862b11efe514251d32070c3d65 Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Thu, 25 Aug 2016 19:20:41 +0300 Subject: Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443) Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev --- Source/WebCore/css/FontLoader.cpp | 178 +++++++++++++++++++++----------------- 1 file changed, 100 insertions(+), 78 deletions(-) (limited to 'Source/WebCore/css/FontLoader.cpp') 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 create(int numLoading, PassRefPtr loadCallback, PassRefPtr errorCallback) + static Ref create(int numLoading, FontLoader& fontLoader, PassRefPtr loadCallback, PassRefPtr errorCallback) { - return adoptRef(new LoadFontCallback(numLoading, loadCallback, errorCallback)); + return adoptRef(*new LoadFontCallback(numLoading, fontLoader, loadCallback, errorCallback)); } - static PassRefPtr createFromParams(const Dictionary& params, const FontFamily& family) + static PassRefPtr createFromParams(const Dictionary& params, FontLoader& fontLoader, const FontCascade& font) { RefPtr onsuccess; RefPtr 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 loadCallback, PassRefPtr errorCallback) - : m_numLoading(numLoading) + LoadFontCallback(int numLoading, FontLoader& fontLoader, PassRefPtr loadCallback, PassRefPtr 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 m_loadCallback; RefPtr 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) +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) +{ + 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 > pendingEvents; + Vector> 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> 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 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 > 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 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 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& parsedStyle) +static void applyPropertyToCurrentStyle(StyleResolver& styleResolver, CSSPropertyID id, const RefPtr& 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 parsedStyle = MutableStylePropertySet::create(); - CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, CSSStrictMode, 0); + RefPtr 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 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; } -- cgit v1.2.1