Commit 3a08bf90 authored by Fernando Serboncini's avatar Fernando Serboncini Committed by Commit Bot

Adds FontFaceSetForWorkers

Bug: 722511
Change-Id: I4a8f5eb5c5a4bae215690979f737bbdfb446a449
Reviewed-on: https://chromium-review.googlesource.com/726341Reviewed-by: default avatarJustin Novosad <junov@chromium.org>
Reviewed-by: default avatarKunihiko Sakamoto <ksakamoto@chromium.org>
Commit-Queue: Fernando Serboncini <fserb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512873}
parent a536ab7a
...@@ -198,6 +198,8 @@ blink_core_sources("css") { ...@@ -198,6 +198,8 @@ blink_core_sources("css") {
"FontFaceSetDocument.h", "FontFaceSetDocument.h",
"FontFaceSetLoadEvent.cpp", "FontFaceSetLoadEvent.cpp",
"FontFaceSetLoadEvent.h", "FontFaceSetLoadEvent.h",
"FontFaceSetWorker.cpp",
"FontFaceSetWorker.h",
"FontFaceSource.cpp", "FontFaceSource.cpp",
"FontFaceSource.h", "FontFaceSource.h",
"FontSize.cpp", "FontSize.cpp",
......
...@@ -30,8 +30,10 @@ ...@@ -30,8 +30,10 @@
#include "core/css/CSSFontSelector.h" #include "core/css/CSSFontSelector.h"
#include "core/css/CSSSegmentedFontFace.h" #include "core/css/CSSSegmentedFontFace.h"
#include "core/css/FontFaceSetDocument.h" #include "core/css/FontFaceSetDocument.h"
#include "core/css/FontFaceSetWorker.h"
#include "core/css/RemoteFontFaceSource.h" #include "core/css/RemoteFontFaceSource.h"
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
#include "core/workers/WorkerGlobalScope.h"
#include "platform/fonts/FontDescription.h" #include "platform/fonts/FontDescription.h"
#include "platform/fonts/SimpleFontData.h" #include "platform/fonts/SimpleFontData.h"
...@@ -185,12 +187,20 @@ void CSSFontFace::SetLoadStatus(FontFace::LoadStatusType new_status) { ...@@ -185,12 +187,20 @@ void CSSFontFace::SetLoadStatus(FontFace::LoadStatusType new_status) {
else else
font_face_->SetLoadStatus(new_status); font_face_->SetLoadStatus(new_status);
if (!segmented_font_face_ || !font_face_->GetExecutionContext() || if (!segmented_font_face_ || !font_face_->GetExecutionContext())
!font_face_->GetExecutionContext()->IsDocument())
return; return;
Document* document = ToDocument(font_face_->GetExecutionContext());
if (document && new_status == FontFace::kLoading) if (font_face_->GetExecutionContext()->IsDocument()) {
FontFaceSetDocument::From(*document)->BeginFontLoading(font_face_); Document* document = ToDocument(font_face_->GetExecutionContext());
if (new_status == FontFace::kLoading)
FontFaceSetDocument::From(*document)->BeginFontLoading(font_face_);
}
if (font_face_->GetExecutionContext()->IsWorkerGlobalScope()) {
WorkerGlobalScope* scope =
ToWorkerGlobalScope(font_face_->GetExecutionContext());
if (new_status == FontFace::kLoading)
FontFaceSetWorker::From(*scope)->BeginFontLoading(font_face_);
}
} }
void CSSFontFace::Trace(blink::Visitor* visitor) { void CSSFontFace::Trace(blink::Visitor* visitor) {
......
...@@ -60,7 +60,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector { ...@@ -60,7 +60,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector {
const AtomicString& family_name, const AtomicString& family_name,
const FontDataForRangeSet&) override; const FontDataForRangeSet&) override;
bool IsPlatformFamilyMatchAvailable(const FontDescription&, bool IsPlatformFamilyMatchAvailable(const FontDescription&,
const AtomicString& family); const AtomicString& family) override;
void FontFaceInvalidated() override; void FontFaceInvalidated() override;
...@@ -71,7 +71,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector { ...@@ -71,7 +71,7 @@ class CORE_EXPORT CSSFontSelector : public FontSelector {
void UnregisterForInvalidationCallbacks(FontSelectorClient*) override; void UnregisterForInvalidationCallbacks(FontSelectorClient*) override;
ExecutionContext* GetExecutionContext() const override { return document_; } ExecutionContext* GetExecutionContext() const override { return document_; }
FontFaceCache* GetFontFaceCache() { return &font_face_cache_; } FontFaceCache* GetFontFaceCache() override { return &font_face_cache_; }
const GenericFontFamilySettings& GetGenericFontFamilySettings() const { const GenericFontFamilySettings& GetGenericFontFamilySettings() const {
return generic_font_family_settings_; return generic_font_family_settings_;
......
...@@ -4,8 +4,306 @@ ...@@ -4,8 +4,306 @@
#include "core/css/FontFaceSet.h" #include "core/css/FontFaceSet.h"
#include "core/css/FontFaceCache.h"
#include "core/css/FontFaceSetLoadEvent.h"
#include "platform/fonts/Font.h"
namespace blink { namespace blink {
void FontFaceSet::Suspend() {
async_runner_->Suspend();
}
void FontFaceSet::Resume() {
async_runner_->Resume();
}
void FontFaceSet::ContextDestroyed(ExecutionContext*) {
async_runner_->Stop();
}
void FontFaceSet::HandlePendingEventsAndPromisesSoon() {
// async_runner_ will be automatically stopped on destruction.
async_runner_->RunAsync();
}
void FontFaceSet::HandlePendingEventsAndPromises() {
FireLoadingEvent();
FireDoneEventIfPossible();
}
void FontFaceSet::FireLoadingEvent() {
if (should_fire_loading_event_) {
should_fire_loading_event_ = false;
DispatchEvent(
FontFaceSetLoadEvent::CreateForFontFaces(EventTypeNames::loading));
}
}
FontFaceSet* FontFaceSet::addForBinding(ScriptState*,
FontFace* font_face,
ExceptionState&) {
DCHECK(font_face);
if (!InActiveContext())
return this;
if (non_css_connected_faces_.Contains(font_face))
return this;
if (IsCSSConnectedFontFace(font_face))
return this;
FontSelector* font_selector = GetFontSelector();
non_css_connected_faces_.insert(font_face);
font_selector->GetFontFaceCache()->AddFontFace(font_face, false);
if (font_face->LoadStatus() == FontFace::kLoading)
AddToLoadingFonts(font_face);
font_selector->FontFaceInvalidated();
return this;
}
void FontFaceSet::clearForBinding(ScriptState*, ExceptionState&) {
if (!InActiveContext() || non_css_connected_faces_.IsEmpty())
return;
FontSelector* font_selector = GetFontSelector();
FontFaceCache* font_face_cache = font_selector->GetFontFaceCache();
for (const auto& font_face : non_css_connected_faces_) {
font_face_cache->RemoveFontFace(font_face.Get(), false);
if (font_face->LoadStatus() == FontFace::kLoading)
RemoveFromLoadingFonts(font_face);
}
non_css_connected_faces_.clear();
font_selector->FontFaceInvalidated();
}
bool FontFaceSet::deleteForBinding(ScriptState*,
FontFace* font_face,
ExceptionState&) {
DCHECK(font_face);
if (!InActiveContext())
return false;
HeapListHashSet<Member<FontFace>>::iterator it =
non_css_connected_faces_.find(font_face);
if (it != non_css_connected_faces_.end()) {
non_css_connected_faces_.erase(it);
FontSelector* font_selector = GetFontSelector();
font_selector->GetFontFaceCache()->RemoveFontFace(font_face, false);
if (font_face->LoadStatus() == FontFace::kLoading)
RemoveFromLoadingFonts(font_face);
font_selector->FontFaceInvalidated();
return true;
}
return false;
}
bool FontFaceSet::hasForBinding(ScriptState*,
FontFace* font_face,
ExceptionState&) const {
DCHECK(font_face);
if (!InActiveContext())
return false;
return non_css_connected_faces_.Contains(font_face) ||
IsCSSConnectedFontFace(font_face);
}
void FontFaceSet::Trace(blink::Visitor* visitor) {
visitor->Trace(non_css_connected_faces_);
visitor->Trace(loading_fonts_);
visitor->Trace(loaded_fonts_);
visitor->Trace(failed_fonts_);
visitor->Trace(ready_);
visitor->Trace(async_runner_);
SuspendableObject::Trace(visitor);
EventTargetWithInlineData::Trace(visitor);
FontFace::LoadFontCallback::Trace(visitor);
}
size_t FontFaceSet::size() const {
if (!InActiveContext())
return non_css_connected_faces_.size();
return CSSConnectedFontFaceList().size() + non_css_connected_faces_.size();
}
void FontFaceSet::AddFontFacesToFontFaceCache(FontFaceCache* font_face_cache) {
for (const auto& font_face : non_css_connected_faces_)
font_face_cache->AddFontFace(font_face, false);
}
void FontFaceSet::AddToLoadingFonts(FontFace* font_face) {
if (!is_loading_) {
is_loading_ = true;
should_fire_loading_event_ = true;
if (ready_->GetState() != ReadyProperty::kPending)
ready_->Reset();
HandlePendingEventsAndPromisesSoon();
}
loading_fonts_.insert(font_face);
font_face->AddCallback(this);
}
void FontFaceSet::RemoveFromLoadingFonts(FontFace* font_face) {
loading_fonts_.erase(font_face);
if (loading_fonts_.IsEmpty())
HandlePendingEventsAndPromisesSoon();
}
void FontFaceSet::LoadFontPromiseResolver::LoadFonts() {
if (!num_loading_) {
resolver_->Resolve(font_faces_);
return;
}
for (size_t i = 0; i < font_faces_.size(); i++)
font_faces_[i]->LoadWithCallback(this);
}
ScriptPromise FontFaceSet::load(ScriptState* script_state,
const String& font_string,
const String& text) {
if (!InActiveContext())
return ScriptPromise();
Font font;
if (!ResolveFontStyle(font_string, font)) {
ScriptPromiseResolver* resolver =
ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
resolver->Reject(DOMException::Create(
kSyntaxError, "Could not resolve '" + font_string + "' as a font."));
return promise;
}
FontFaceCache* font_face_cache = GetFontSelector()->GetFontFaceCache();
FontFaceArray faces;
for (const FontFamily* f = &font.GetFontDescription().Family(); f;
f = f->Next()) {
CSSSegmentedFontFace* segmented_font_face =
font_face_cache->Get(font.GetFontDescription(), f->Family());
if (segmented_font_face)
segmented_font_face->Match(text, faces);
}
LoadFontPromiseResolver* resolver =
LoadFontPromiseResolver::Create(faces, script_state);
ScriptPromise promise = resolver->Promise();
// After this, resolver->promise() may return null.
resolver->LoadFonts();
return promise;
}
bool FontFaceSet::check(const String& font_string,
const String& text,
ExceptionState& exception_state) {
if (!InActiveContext())
return false;
Font font;
if (!ResolveFontStyle(font_string, font)) {
exception_state.ThrowDOMException(
kSyntaxError, "Could not resolve '" + font_string + "' as a font.");
return false;
}
FontSelector* font_selector = GetFontSelector();
FontFaceCache* font_face_cache = font_selector->GetFontFaceCache();
bool has_loaded_faces = false;
for (const FontFamily* f = &font.GetFontDescription().Family(); f;
f = f->Next()) {
CSSSegmentedFontFace* face =
font_face_cache->Get(font.GetFontDescription(), f->Family());
if (face) {
if (!face->CheckFont(text))
return false;
has_loaded_faces = true;
}
}
if (has_loaded_faces)
return true;
for (const FontFamily* f = &font.GetFontDescription().Family(); f;
f = f->Next()) {
if (font_selector->IsPlatformFamilyMatchAvailable(font.GetFontDescription(),
f->Family()))
return true;
}
return false;
}
void FontFaceSet::FireDoneEvent() {
if (is_loading_) {
FontFaceSetLoadEvent* done_event = nullptr;
FontFaceSetLoadEvent* error_event = nullptr;
done_event = FontFaceSetLoadEvent::CreateForFontFaces(
EventTypeNames::loadingdone, loaded_fonts_);
loaded_fonts_.clear();
if (!failed_fonts_.IsEmpty()) {
error_event = FontFaceSetLoadEvent::CreateForFontFaces(
EventTypeNames::loadingerror, failed_fonts_);
failed_fonts_.clear();
}
is_loading_ = false;
DispatchEvent(done_event);
if (error_event)
DispatchEvent(error_event);
}
if (ready_->GetState() == ReadyProperty::kPending)
ready_->Resolve(this);
}
bool FontFaceSet::ShouldSignalReady() const {
if (!loading_fonts_.IsEmpty())
return false;
return is_loading_ || ready_->GetState() == ReadyProperty::kPending;
}
void FontFaceSet::LoadFontPromiseResolver::NotifyLoaded(FontFace* font_face) {
num_loading_--;
if (num_loading_ || error_occured_)
return;
resolver_->Resolve(font_faces_);
}
void FontFaceSet::LoadFontPromiseResolver::NotifyError(FontFace* font_face) {
num_loading_--;
if (!error_occured_) {
error_occured_ = true;
resolver_->Reject(font_face->GetError());
}
}
void FontFaceSet::LoadFontPromiseResolver::Trace(blink::Visitor* visitor) {
visitor->Trace(font_faces_);
visitor->Trace(resolver_);
LoadFontCallback::Trace(visitor);
}
bool FontFaceSet::IterationSource::Next(ScriptState*,
Member<FontFace>& key,
Member<FontFace>& value,
ExceptionState&) {
if (font_faces_.size() <= index_)
return false;
key = value = font_faces_[index_++];
return true;
}
FontFaceSetIterable::IterationSource* FontFaceSet::StartIteration(
ScriptState*,
ExceptionState&) {
// Setlike should iterate each item in insertion order, and items should
// be keep on up to date. But since blink does not have a way to hook up CSS
// modification, take a snapshot here, and make it ordered as follows.
HeapVector<Member<FontFace>> font_faces;
if (InActiveContext()) {
const HeapListHashSet<Member<FontFace>>& css_connected_faces =
CSSConnectedFontFaceList();
font_faces.ReserveInitialCapacity(css_connected_faces.size() +
non_css_connected_faces_.size());
for (const auto& font_face : css_connected_faces)
font_faces.push_back(font_face);
for (const auto& font_face : non_css_connected_faces_)
font_faces.push_back(font_face);
}
return new IterationSource(font_faces);
}
} // namespace blink } // namespace blink
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -7,10 +8,14 @@ ...@@ -7,10 +8,14 @@
#include "bindings/core/v8/Iterable.h" #include "bindings/core/v8/Iterable.h"
#include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/css/FontFace.h" #include "core/css/FontFace.h"
#include "core/dom/SuspendableObject.h"
#include "core/dom/events/EventListener.h" #include "core/dom/events/EventListener.h"
#include "core/dom/events/EventTarget.h" #include "core/dom/events/EventTarget.h"
#include "platform/AsyncMethodRunner.h"
#include "platform/bindings/ScriptWrappable.h" #include "platform/bindings/ScriptWrappable.h"
#include "platform/fonts/FontSelector.h"
// Mac OS X 10.6 SDK defines check() macro that interferes with our check() // Mac OS X 10.6 SDK defines check() macro that interferes with our check()
// method // method
...@@ -20,55 +25,94 @@ ...@@ -20,55 +25,94 @@
namespace blink { namespace blink {
class FontFaceCache;
using FontFaceSetIterable = SetlikeIterable<Member<FontFace>>; using FontFaceSetIterable = SetlikeIterable<Member<FontFace>>;
class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData, class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
public FontFaceSetIterable { public SuspendableObject,
public FontFaceSetIterable,
public FontFace::LoadFontCallback {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
WTF_MAKE_NONCOPYABLE(FontFaceSet); WTF_MAKE_NONCOPYABLE(FontFaceSet);
public: public:
FontFaceSet() {} FontFaceSet(ExecutionContext& context)
: SuspendableObject(&context),
is_loading_(false),
should_fire_loading_event_(false),
ready_(new ReadyProperty(GetExecutionContext(),
this,
ReadyProperty::kReady)),
async_runner_(AsyncMethodRunner<FontFaceSet>::Create(
this,
&FontFaceSet::HandlePendingEventsAndPromises)) {}
~FontFaceSet() {} ~FontFaceSet() {}
DEFINE_ATTRIBUTE_EVENT_LISTENER(loading); DEFINE_ATTRIBUTE_EVENT_LISTENER(loading);
DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingdone); DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingdone);
DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingerror); DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingerror);
virtual bool check(const String& font, bool check(const String& font, const String& text, ExceptionState&);
const String& text, ScriptPromise load(ScriptState*, const String& font, const String& text);
ExceptionState&) = 0;
virtual ScriptPromise load(ScriptState*,
const String& font,
const String& text) = 0;
virtual ScriptPromise ready(ScriptState*) = 0; virtual ScriptPromise ready(ScriptState*) = 0;
virtual ExecutionContext* GetExecutionContext() const = 0; ExecutionContext* GetExecutionContext() const {
return SuspendableObject::GetExecutionContext();
}
const AtomicString& InterfaceName() const { const AtomicString& InterfaceName() const {
return EventTargetNames::FontFaceSet; return EventTargetNames::FontFaceSet;
} }
virtual FontFaceSet* addForBinding(ScriptState*, FontFaceSet* addForBinding(ScriptState*, FontFace*, ExceptionState&);
FontFace*, void clearForBinding(ScriptState*, ExceptionState&);
ExceptionState&) = 0; bool deleteForBinding(ScriptState*, FontFace*, ExceptionState&);
virtual void clearForBinding(ScriptState*, ExceptionState&) = 0; bool hasForBinding(ScriptState*, FontFace*, ExceptionState&) const;
virtual bool deleteForBinding(ScriptState*, FontFace*, ExceptionState&) = 0;
virtual bool hasForBinding(ScriptState*,
FontFace*,
ExceptionState&) const = 0;
virtual size_t size() const = 0; void AddFontFacesToFontFaceCache(FontFaceCache*);
// SuspendableObject
void Suspend() override;
void Resume() override;
void ContextDestroyed(ExecutionContext*) override;
size_t size() const;
virtual AtomicString status() const = 0; virtual AtomicString status() const = 0;
virtual void Trace(blink::Visitor* visitor) { virtual void Trace(blink::Visitor*);
EventTargetWithInlineData::Trace(visitor);
}
protected: protected:
// Iterable overrides. virtual bool ResolveFontStyle(const String&, Font&) = 0;
virtual FontFaceSetIterable::IterationSource* StartIteration( virtual bool InActiveContext() const = 0;
ScriptState*, virtual FontSelector* GetFontSelector() const = 0;
ExceptionState&) = 0; virtual const HeapListHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
const = 0;
bool IsCSSConnectedFontFace(FontFace* font_face) const {
return CSSConnectedFontFaceList().Contains(font_face);
}
virtual void FireDoneEventIfPossible() = 0;
void AddToLoadingFonts(FontFace*);
void RemoveFromLoadingFonts(FontFace*);
void HandlePendingEventsAndPromisesSoon();
bool ShouldSignalReady() const;
void FireDoneEvent();
using ReadyProperty = ScriptPromiseProperty<Member<FontFaceSet>,
Member<FontFaceSet>,
Member<DOMException>>;
bool is_loading_;
bool should_fire_loading_event_;
HeapListHashSet<Member<FontFace>> non_css_connected_faces_;
HeapHashSet<Member<FontFace>> loading_fonts_;
FontFaceArray loaded_fonts_;
FontFaceArray failed_fonts_;
Member<ReadyProperty> ready_;
Member<AsyncMethodRunner<FontFaceSet>> async_runner_;
class IterationSource final : public FontFaceSetIterable::IterationSource { class IterationSource final : public FontFaceSetIterable::IterationSource {
public: public:
...@@ -88,6 +132,47 @@ class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData, ...@@ -88,6 +132,47 @@ class CORE_EXPORT FontFaceSet : public EventTargetWithInlineData,
size_t index_; size_t index_;
HeapVector<Member<FontFace>> font_faces_; HeapVector<Member<FontFace>> font_faces_;
}; };
class LoadFontPromiseResolver final
: public GarbageCollectedFinalized<LoadFontPromiseResolver>,
public FontFace::LoadFontCallback {
USING_GARBAGE_COLLECTED_MIXIN(LoadFontPromiseResolver);
public:
static LoadFontPromiseResolver* Create(FontFaceArray faces,
ScriptState* script_state) {
return new LoadFontPromiseResolver(faces, script_state);
}
void LoadFonts();
ScriptPromise Promise() { return resolver_->Promise(); }
void NotifyLoaded(FontFace*) override;
void NotifyError(FontFace*) override;
void Trace(blink::Visitor*);
private:
LoadFontPromiseResolver(FontFaceArray faces, ScriptState* script_state)
: num_loading_(faces.size()),
error_occured_(false),
resolver_(ScriptPromiseResolver::Create(script_state)) {
font_faces_.swap(faces);
}
HeapVector<Member<FontFace>> font_faces_;
int num_loading_;
bool error_occured_;
Member<ScriptPromiseResolver> resolver_;
};
private:
FontFaceSetIterable::IterationSource* StartIteration(
ScriptState*,
ExceptionState&) override;
void HandlePendingEventsAndPromises();
void FireLoadingEvent();
}; };
} // namespace blink } // namespace blink
......
...@@ -32,11 +32,12 @@ ...@@ -32,11 +32,12 @@
enum FontFaceSetLoadStatus { "loading", "loaded" }; enum FontFaceSetLoadStatus { "loading", "loaded" };
// TODO(foolip): This interface should be [Exposed=Window,Worker] and should // TODO(foolip): This interface should have a constructor and thos not have
// have a constructor, and thus not have [NoInterfaceObject]. // [NoInterfaceObject]
[ [
DependentLifetime, DependentLifetime,
NoInterfaceObject NoInterfaceObject,
Exposed(Window StableBlinkFeatures, Worker ExperimentalCanvasFeatures)
] interface FontFaceSet : EventTarget { ] interface FontFaceSet : EventTarget {
setlike<FontFace>; setlike<FontFace>;
......
...@@ -28,8 +28,10 @@ ...@@ -28,8 +28,10 @@
#include "bindings/core/v8/Iterable.h" #include "bindings/core/v8/Iterable.h"
#include "bindings/core/v8/ScriptPromise.h" #include "bindings/core/v8/ScriptPromise.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/FontFace.h" #include "core/css/FontFace.h"
#include "core/css/FontFaceSet.h" #include "core/css/FontFaceSet.h"
#include "core/css/StyleEngine.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/dom/SuspendableObject.h" #include "core/dom/SuspendableObject.h"
#include "core/dom/events/EventListener.h" #include "core/dom/events/EventListener.h"
...@@ -39,46 +41,22 @@ ...@@ -39,46 +41,22 @@
#include "platform/wtf/Allocator.h" #include "platform/wtf/Allocator.h"
#include "platform/wtf/Vector.h" #include "platform/wtf/Vector.h"
// Mac OS X 10.6 SDK defines check() macro that interferes with our check()
// method
#ifdef check
#undef check
#endif
namespace blink { namespace blink {
class ExceptionState;
class Font; class Font;
class FontFaceCache;
class ExecutionContext; class CORE_EXPORT FontFaceSetDocument final : public FontFaceSet,
public Supplement<Document> {
class CORE_EXPORT FontFaceSetDocument final
: public FontFaceSet,
public Supplement<Document>,
public SuspendableObject,
public FontFace::LoadFontCallback {
USING_GARBAGE_COLLECTED_MIXIN(FontFaceSetDocument); USING_GARBAGE_COLLECTED_MIXIN(FontFaceSetDocument);
WTF_MAKE_NONCOPYABLE(FontFaceSetDocument); WTF_MAKE_NONCOPYABLE(FontFaceSetDocument);
public: public:
~FontFaceSetDocument() override; ~FontFaceSetDocument() override;
bool check(const String& font, const String& text, ExceptionState&) override;
ScriptPromise load(ScriptState*,
const String& font,
const String& text) override;
ScriptPromise ready(ScriptState*) override; ScriptPromise ready(ScriptState*) override;
FontFaceSet* addForBinding(ScriptState*, FontFace*, ExceptionState&) override;
void clearForBinding(ScriptState*, ExceptionState&) override;
bool deleteForBinding(ScriptState*, FontFace*, ExceptionState&) override;
bool hasForBinding(ScriptState*, FontFace*, ExceptionState&) const override;
size_t size() const override;
AtomicString status() const override; AtomicString status() const override;
ExecutionContext* GetExecutionContext() const override;
Document* GetDocument() const; Document* GetDocument() const;
void DidLayout(); void DidLayout();
...@@ -90,31 +68,34 @@ class CORE_EXPORT FontFaceSetDocument final ...@@ -90,31 +68,34 @@ class CORE_EXPORT FontFaceSetDocument final
size_t ApproximateBlankCharacterCount() const; size_t ApproximateBlankCharacterCount() const;
// SuspendableObject
void Suspend() override;
void Resume() override;
void ContextDestroyed(ExecutionContext*) override;
static FontFaceSetDocument* From(Document&); static FontFaceSetDocument* From(Document&);
static void DidLayout(Document&); static void DidLayout(Document&);
static size_t ApproximateBlankCharacterCount(Document&); static size_t ApproximateBlankCharacterCount(Document&);
static const char* SupplementName() { return "FontFaceSetDocument"; } static const char* SupplementName() { return "FontFaceSetDocument"; }
void AddFontFacesToFontFaceCache(FontFaceCache*);
virtual void Trace(blink::Visitor*); virtual void Trace(blink::Visitor*);
virtual void TraceWrappers(const ScriptWrappableVisitor*) const; virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
private: protected:
FontFaceSetIterable::IterationSource* StartIteration( bool InActiveContext() const override;
ScriptState*, FontSelector* GetFontSelector() const override {
ExceptionState&) override; return GetDocument()->GetStyleEngine().GetFontSelector();
}
bool ResolveFontStyle(const String&, Font&) override;
private:
static FontFaceSetDocument* Create(Document& document) { static FontFaceSetDocument* Create(Document& document) {
return new FontFaceSetDocument(document); return new FontFaceSetDocument(document);
} }
explicit FontFaceSetDocument(Document&);
void FireDoneEventIfPossible() override;
const HeapListHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
const override;
class FontLoadHistogram { class FontLoadHistogram {
DISALLOW_NEW(); DISALLOW_NEW();
...@@ -130,35 +111,6 @@ class CORE_EXPORT FontFaceSetDocument final ...@@ -130,35 +111,6 @@ class CORE_EXPORT FontFaceSetDocument final
int count_; int count_;
bool recorded_; bool recorded_;
}; };
explicit FontFaceSetDocument(Document&);
bool InActiveDocumentContext() const;
void AddToLoadingFonts(FontFace*);
void RemoveFromLoadingFonts(FontFace*);
void FireLoadingEvent();
void FireDoneEventIfPossible();
bool ResolveFontStyle(const String&, Font&);
void HandlePendingEventsAndPromisesSoon();
void HandlePendingEventsAndPromises();
const HeapListHashSet<Member<FontFace>>& CssConnectedFontFaceList() const;
bool IsCSSConnectedFontFace(FontFace*) const;
bool ShouldSignalReady() const;
using ReadyProperty = ScriptPromiseProperty<Member<FontFaceSetDocument>,
Member<FontFaceSetDocument>,
Member<DOMException>>;
HeapHashSet<Member<FontFace>> loading_fonts_;
bool should_fire_loading_event_;
bool is_loading_;
Member<ReadyProperty> ready_;
FontFaceArray loaded_fonts_;
FontFaceArray failed_fonts_;
HeapListHashSet<Member<FontFace>> non_css_connected_faces_;
Member<AsyncMethodRunner<FontFaceSetDocument>> async_runner_;
FontLoadHistogram histogram_; FontLoadHistogram histogram_;
}; };
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/css/FontFaceSetWorker.h"
#include "bindings/core/v8/Dictionary.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/css/CSSSegmentedFontFace.h"
#include "core/css/FontFaceCache.h"
#include "core/css/FontFaceSetLoadEvent.h"
#include "core/css/OffscreenFontSelector.h"
#include "core/css/StylePropertySet.h"
#include "core/css/parser/CSSParser.h"
#include "core/css/resolver/FontStyleResolver.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameView.h"
#include "core/style/ComputedStyle.h"
#include "platform/bindings/ScriptState.h"
namespace blink {
static const int kDefaultFontSize = 10;
static const char kDefaultFontFamily[] = "sans-serif";
FontFaceSetWorker::FontFaceSetWorker(WorkerGlobalScope& worker)
: FontFaceSet(worker), Supplement<WorkerGlobalScope>(worker) {
SuspendIfNeeded();
}
FontFaceSetWorker::~FontFaceSetWorker() {}
WorkerGlobalScope* FontFaceSetWorker::GetWorker() const {
return ToWorkerGlobalScope(GetExecutionContext());
}
AtomicString FontFaceSetWorker::status() const {
DEFINE_STATIC_LOCAL(AtomicString, loading, ("loading"));
DEFINE_STATIC_LOCAL(AtomicString, loaded, ("loaded"));
return is_loading_ ? loading : loaded;
}
void FontFaceSetWorker::BeginFontLoading(FontFace* font_face) {
AddToLoadingFonts(font_face);
}
void FontFaceSetWorker::NotifyLoaded(FontFace* font_face) {
loaded_fonts_.push_back(font_face);
RemoveFromLoadingFonts(font_face);
}
void FontFaceSetWorker::NotifyError(FontFace* font_face) {
failed_fonts_.push_back(font_face);
RemoveFromLoadingFonts(font_face);
}
ScriptPromise FontFaceSetWorker::ready(ScriptState* script_state) {
return ready_->Promise(script_state->World());
}
void FontFaceSetWorker::FireDoneEventIfPossible() {
if (should_fire_loading_event_)
return;
if (!ShouldSignalReady())
return;
FireDoneEvent();
}
bool FontFaceSetWorker::ResolveFontStyle(const String& font_string,
Font& font) {
if (font_string.IsEmpty())
return false;
// Interpret fontString in the same way as the 'font' attribute of
// CanvasRenderingContext2D.
MutableStylePropertySet* parsed_style =
MutableStylePropertySet::Create(kHTMLStandardMode);
CSSParser::ParseValue(parsed_style, CSSPropertyFont, font_string, true);
if (parsed_style->IsEmpty())
return false;
String font_value = parsed_style->GetPropertyValue(CSSPropertyFont);
if (font_value == "inherit" || font_value == "initial")
return false;
FontFamily font_family;
font_family.SetFamily(kDefaultFontFamily);
FontDescription default_font_description;
default_font_description.SetFamily(font_family);
default_font_description.SetSpecifiedSize(kDefaultFontSize);
default_font_description.SetComputedSize(kDefaultFontSize);
FontDescription description = FontStyleResolver::ComputeFont(
*parsed_style, GetWorker()->GetFontSelector());
font = Font(description);
font.Update(GetWorker()->GetFontSelector());
return true;
}
FontFaceSetWorker* FontFaceSetWorker::From(WorkerGlobalScope& worker) {
FontFaceSetWorker* fonts = static_cast<FontFaceSetWorker*>(
Supplement<WorkerGlobalScope>::From(worker, SupplementName()));
if (!fonts) {
fonts = FontFaceSetWorker::Create(worker);
Supplement<WorkerGlobalScope>::ProvideTo(worker, SupplementName(), fonts);
}
return fonts;
}
void FontFaceSetWorker::Trace(Visitor* visitor) {
Supplement<WorkerGlobalScope>::Trace(visitor);
FontFaceSet::Trace(visitor);
}
} // namespace blink
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FontFaceSetWorker_h
#define FontFaceSetWorker_h
#include "bindings/core/v8/Iterable.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "core/css/FontFace.h"
#include "core/css/FontFaceSet.h"
#include "core/css/OffscreenFontSelector.h"
#include "core/dom/SuspendableObject.h"
#include "core/workers/WorkerGlobalScope.h"
#include "platform/AsyncMethodRunner.h"
#include "platform/heap/Handle.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/Vector.h"
namespace blink {
class Font;
class CORE_EXPORT FontFaceSetWorker final
: public FontFaceSet,
public Supplement<WorkerGlobalScope> {
USING_GARBAGE_COLLECTED_MIXIN(FontFaceSetWorker);
WTF_MAKE_NONCOPYABLE(FontFaceSetWorker);
public:
~FontFaceSetWorker() override;
ScriptPromise ready(ScriptState*) override;
AtomicString status() const override;
WorkerGlobalScope* GetWorker() const;
// FontFace::LoadFontCallback
void NotifyLoaded(FontFace*) override;
void NotifyError(FontFace*) override;
void BeginFontLoading(FontFace*);
static FontFaceSetWorker* From(WorkerGlobalScope&);
static const char* SupplementName() { return "FontFaceSetWorker"; }
void Trace(Visitor*) override;
protected:
bool InActiveContext() const override { return true; }
FontSelector* GetFontSelector() const override {
return GetWorker()->GetFontSelector();
}
// For workers, this is always an empty list.
const HeapListHashSet<Member<FontFace>>& CSSConnectedFontFaceList()
const override {
DCHECK(
GetFontSelector()->GetFontFaceCache()->CssConnectedFontFaces().size() ==
0);
return GetFontSelector()->GetFontFaceCache()->CssConnectedFontFaces();
}
bool ResolveFontStyle(const String&, Font&) override;
private:
static FontFaceSetWorker* Create(WorkerGlobalScope& worker) {
return new FontFaceSetWorker(worker);
}
explicit FontFaceSetWorker(WorkerGlobalScope&);
void FireDoneEventIfPossible() override;
};
} // namespace blink
#endif // FontFaceSetWorker_h
...@@ -51,10 +51,11 @@ class CORE_EXPORT OffscreenFontSelector : public FontSelector { ...@@ -51,10 +51,11 @@ class CORE_EXPORT OffscreenFontSelector : public FontSelector {
void UpdateGenericFontFamilySettings(const GenericFontFamilySettings&); void UpdateGenericFontFamilySettings(const GenericFontFamilySettings&);
FontFaceCache* GetFontFaceCache() { return &font_face_cache_; } FontFaceCache* GetFontFaceCache() override { return &font_face_cache_; }
bool IsPlatformFamilyMatchAvailable(const FontDescription&, bool IsPlatformFamilyMatchAvailable(
const AtomicString& passed_family); const FontDescription&,
const AtomicString& passed_family) override;
ExecutionContext* GetExecutionContext() const override { ExecutionContext* GetExecutionContext() const override {
return execution_context_; return execution_context_;
......
...@@ -38,6 +38,7 @@ namespace blink { ...@@ -38,6 +38,7 @@ namespace blink {
class ExecutionContext; class ExecutionContext;
class FontData; class FontData;
class FontDescription; class FontDescription;
class FontFaceCache;
class FontSelectorClient; class FontSelectorClient;
class GenericFontFamilySettings; class GenericFontFamilySettings;
...@@ -67,6 +68,12 @@ class PLATFORM_EXPORT FontSelector : public FontCacheClient { ...@@ -67,6 +68,12 @@ class PLATFORM_EXPORT FontSelector : public FontCacheClient {
virtual ExecutionContext* GetExecutionContext() const = 0; virtual ExecutionContext* GetExecutionContext() const = 0;
virtual FontFaceCache* GetFontFaceCache() = 0;
virtual bool IsPlatformFamilyMatchAvailable(
const FontDescription&,
const AtomicString& passed_family) = 0;
protected: protected:
static AtomicString FamilyNameFromSettings( static AtomicString FamilyNameFromSettings(
const GenericFontFamilySettings&, const GenericFontFamilySettings&,
......
...@@ -53,11 +53,18 @@ class TestFontSelector : public FontSelector { ...@@ -53,11 +53,18 @@ class TestFontSelector : public FontSelector {
unsigned Version() const override { return 0; } unsigned Version() const override { return 0; }
void FontCacheInvalidated() override {} void FontCacheInvalidated() override {}
void ReportNotDefGlyph() const override {} void ReportNotDefGlyph() const override {}
ExecutionContext* GetExecutionContext() const { return nullptr; } ExecutionContext* GetExecutionContext() const override { return nullptr; }
FontFaceCache* GetFontFaceCache() override { return nullptr; }
void RegisterForInvalidationCallbacks(FontSelectorClient*) override {} void RegisterForInvalidationCallbacks(FontSelectorClient*) override {}
void UnregisterForInvalidationCallbacks(FontSelectorClient*) override {} void UnregisterForInvalidationCallbacks(FontSelectorClient*) override {}
bool IsPlatformFamilyMatchAvailable(
const FontDescription&,
const AtomicString& passed_family) override {
return false;
}
private: private:
TestFontSelector(scoped_refptr<FontCustomPlatformData> custom_platform_data) TestFontSelector(scoped_refptr<FontCustomPlatformData> custom_platform_data)
: custom_platform_data_(std::move(custom_platform_data)) { : custom_platform_data_(std::move(custom_platform_data)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment