ladybird/Userland/Libraries/LibWeb/CSS/FontFaceSet.h
Aliaksandr Kalenik 5faca4f027 LibWeb: Resolve document.fonts.ready() after fonts defined in CSS loaded
This is an ad-hoc implementation that resolves the ready() promise once
the document and all fonts collected by the style computer are done
loading. A spec-compliant implementation would include creating a proxy
CSS::FontFace for each @font-face and correctly implementing the
specification steps for font fetching, but we are far from there yet.

This hackish implementation should yield good WPT progress because it
will actually start waiting for the Ahem font to load before capturing
layout measurements. For example, it makes
https://wpt.live/css/css-grid/abspos/positioned-grid-descendants-001.html
go from 0/100 to 36/100 passing subtests.
2024-09-30 08:07:59 +02:00

64 lines
2.2 KiB
C++

/*
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Set.h>
#include <LibJS/Runtime/SetIterator.h>
#include <LibWeb/Bindings/FontFaceSetPrototype.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/CSS/FontFace.h>
#include <LibWeb/DOM/EventTarget.h>
namespace Web::CSS {
class FontFaceSet final : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(FontFaceSet, DOM::EventTarget);
JS_DECLARE_ALLOCATOR(FontFaceSet);
public:
[[nodiscard]] static JS::NonnullGCPtr<FontFaceSet> construct_impl(JS::Realm&, Vector<JS::Handle<FontFace>> const& initial_faces);
[[nodiscard]] static JS::NonnullGCPtr<FontFaceSet> create(JS::Realm&);
virtual ~FontFaceSet() override = default;
JS::NonnullGCPtr<JS::Set> set_entries() const { return m_set_entries; }
WebIDL::ExceptionOr<JS::NonnullGCPtr<FontFaceSet>> add(JS::Handle<FontFace>);
bool delete_(JS::Handle<FontFace>);
void clear();
void set_onloading(WebIDL::CallbackType*);
WebIDL::CallbackType* onloading();
void set_onloadingdone(WebIDL::CallbackType*);
WebIDL::CallbackType* onloadingdone();
void set_onloadingerror(WebIDL::CallbackType*);
WebIDL::CallbackType* onloadingerror();
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> load(String const& font, String const& text);
JS::NonnullGCPtr<JS::Promise> ready() const;
Bindings::FontFaceSetLoadStatus status() const { return m_status; }
void resolve_ready_promise();
private:
FontFaceSet(JS::Realm&, JS::NonnullGCPtr<WebIDL::Promise> ready_promise, JS::NonnullGCPtr<JS::Set> set_entries);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
JS::NonnullGCPtr<JS::Set> m_set_entries;
JS::GCPtr<WebIDL::Promise> m_ready_promise; // [[ReadyPromise]]
Vector<JS::NonnullGCPtr<FontFace>> m_loading_fonts {}; // [[LoadingFonts]]
Vector<JS::NonnullGCPtr<FontFace>> m_loaded_fonts {}; // [[LoadedFonts]]
Vector<JS::NonnullGCPtr<FontFace>> m_failed_fonts {}; // [[FailedFonts]]
Bindings::FontFaceSetLoadStatus m_status { Bindings::FontFaceSetLoadStatus::Loading };
};
}