mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-05 23:59:49 +00:00
LibWeb: Expose StyleComputer's FontLoader class publicly
We'll want to explicitly load fonts from FontFace and other Web APIs in the future. A future refactor should also move this completely away from StyleComputer and call it something like 'FontCache'.
This commit is contained in:
parent
d76167b8a4
commit
b7526a39b0
Notes:
sideshowbarker
2024-07-17 03:51:15 +09:00
Author: https://github.com/ADKaster
Commit: b7526a39b0
Pull-request: https://github.com/SerenityOS/serenity/pull/24339
2 changed files with 159 additions and 120 deletions
|
@ -72,7 +72,6 @@
|
|||
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||
#include <LibWeb/HighResolutionTime/TimeOrigin.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
#include <LibWeb/Namespace.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Platform/FontPlugin.h>
|
||||
|
@ -103,21 +102,19 @@ StyleComputer::StyleComputer(DOM::Document& document)
|
|||
|
||||
StyleComputer::~StyleComputer() = default;
|
||||
|
||||
class StyleComputer::FontLoader : public ResourceClient {
|
||||
public:
|
||||
explicit FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<URL::URL> urls)
|
||||
FontLoader::FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<URL::URL> urls, Function<void(FontLoader const&)> on_load, Function<void()> on_fail)
|
||||
: m_style_computer(style_computer)
|
||||
, m_family_name(move(family_name))
|
||||
, m_unicode_ranges(move(unicode_ranges))
|
||||
, m_urls(move(urls))
|
||||
, m_on_load(move(on_load))
|
||||
, m_on_fail(move(on_fail))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~FontLoader() override { }
|
||||
FontLoader::~FontLoader() = default;
|
||||
|
||||
Vector<Gfx::UnicodeRange> const& unicode_ranges() const { return m_unicode_ranges; }
|
||||
|
||||
virtual void resource_did_load() override
|
||||
void FontLoader::resource_did_load()
|
||||
{
|
||||
auto result = try_load_font();
|
||||
if (result.is_error()) {
|
||||
|
@ -127,13 +124,18 @@ public:
|
|||
}
|
||||
m_vector_font = result.release_value();
|
||||
m_style_computer.did_load_font(m_family_name);
|
||||
if (m_on_load)
|
||||
m_on_load(*this);
|
||||
}
|
||||
|
||||
virtual void resource_did_fail() override
|
||||
void FontLoader::resource_did_fail()
|
||||
{
|
||||
if (m_on_fail) {
|
||||
m_on_fail();
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font> font_with_point_size(float point_size)
|
||||
RefPtr<Gfx::Font> FontLoader::font_with_point_size(float point_size)
|
||||
{
|
||||
if (!m_vector_font) {
|
||||
start_loading_next_url();
|
||||
|
@ -142,8 +144,7 @@ public:
|
|||
return m_vector_font->scaled_font(point_size);
|
||||
}
|
||||
|
||||
private:
|
||||
void start_loading_next_url()
|
||||
void FontLoader::start_loading_next_url()
|
||||
{
|
||||
if (resource() && resource()->is_pending())
|
||||
return;
|
||||
|
@ -161,7 +162,7 @@ private:
|
|||
set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<Gfx::VectorFont>> try_load_font()
|
||||
ErrorOr<NonnullRefPtr<Gfx::VectorFont>> FontLoader::try_load_font()
|
||||
{
|
||||
// FIXME: This could maybe use the format() provided in @font-face as well, since often the mime type is just application/octet-stream and we have to try every format
|
||||
auto const& mime_type = resource()->mime_type();
|
||||
|
@ -194,13 +195,6 @@ private:
|
|||
return Error::from_string_literal("Automatic format detection failed");
|
||||
}
|
||||
|
||||
StyleComputer& m_style_computer;
|
||||
FlyString m_family_name;
|
||||
Vector<Gfx::UnicodeRange> m_unicode_ranges;
|
||||
RefPtr<Gfx::VectorFont> m_vector_font;
|
||||
Vector<URL::URL> m_urls;
|
||||
};
|
||||
|
||||
struct StyleComputer::MatchingFontCandidate {
|
||||
FontFaceKey key;
|
||||
Variant<FontLoaderList*, Gfx::Typeface const*> loader_or_typeface;
|
||||
|
@ -2566,14 +2560,14 @@ void StyleComputer::did_load_font(FlyString const&)
|
|||
document().invalidate_style();
|
||||
}
|
||||
|
||||
void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
||||
Optional<FontLoader&> StyleComputer::load_font_face(ParsedFontFace const& font_face, Function<void(FontLoader const&)> on_load, Function<void()> on_fail)
|
||||
{
|
||||
for (auto const& rule : static_cast<CSSStyleSheet const&>(sheet).rules()) {
|
||||
if (!is<CSSFontFaceRule>(*rule))
|
||||
continue;
|
||||
auto const& font_face = static_cast<CSSFontFaceRule const&>(*rule).font_face();
|
||||
if (font_face.sources().is_empty())
|
||||
continue;
|
||||
if (font_face.sources().is_empty()) {
|
||||
if (on_fail)
|
||||
on_fail();
|
||||
return {};
|
||||
}
|
||||
|
||||
FontFaceKey key {
|
||||
.family_name = font_face.font_family(),
|
||||
.weight = font_face.weight().value_or(0),
|
||||
|
@ -2581,17 +2575,21 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
|||
};
|
||||
|
||||
Vector<URL::URL> urls;
|
||||
for (auto& source : font_face.sources()) {
|
||||
for (auto const& source : font_face.sources()) {
|
||||
// FIXME: These should be loaded relative to the stylesheet URL instead of the document URL.
|
||||
if (source.local_or_url.has<URL::URL>())
|
||||
urls.append(m_document->parse_url(MUST(source.local_or_url.get<URL::URL>().to_string())));
|
||||
// FIXME: Handle local()
|
||||
}
|
||||
|
||||
if (urls.is_empty())
|
||||
continue;
|
||||
if (urls.is_empty()) {
|
||||
if (on_fail)
|
||||
on_fail();
|
||||
return {};
|
||||
}
|
||||
|
||||
auto loader = make<FontLoader>(const_cast<StyleComputer&>(*this), font_face.font_family(), font_face.unicode_ranges(), move(urls));
|
||||
auto loader = make<FontLoader>(const_cast<StyleComputer&>(*this), font_face.font_family(), font_face.unicode_ranges(), move(urls), move(on_load), move(on_fail));
|
||||
auto& loader_ref = *loader;
|
||||
auto maybe_font_loaders_list = const_cast<StyleComputer&>(*this).m_loaded_fonts.get(key);
|
||||
if (maybe_font_loaders_list.has_value()) {
|
||||
maybe_font_loaders_list->append(move(loader));
|
||||
|
@ -2600,6 +2598,16 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
|||
loaders.append(move(loader));
|
||||
const_cast<StyleComputer&>(*this).m_loaded_fonts.set(key, move(loaders));
|
||||
}
|
||||
// Actual object owned by font loader list inside m_loaded_fonts, this isn't use-after-move/free
|
||||
return loader_ref;
|
||||
}
|
||||
|
||||
void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
|
||||
{
|
||||
for (auto const& rule : sheet.rules()) {
|
||||
if (!is<CSSFontFaceRule>(*rule))
|
||||
continue;
|
||||
(void)load_font_face(static_cast<CSSFontFaceRule const&>(*rule).font_face());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <LibWeb/CSS/Selector.h>
|
||||
#include <LibWeb/CSS/StyleProperties.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -102,6 +103,8 @@ struct FontFaceKey {
|
|||
[[nodiscard]] bool operator==(FontFaceKey const&) const = default;
|
||||
};
|
||||
|
||||
class FontLoader;
|
||||
|
||||
class StyleComputer {
|
||||
public:
|
||||
enum class AllowUnresolved {
|
||||
|
@ -135,6 +138,8 @@ public:
|
|||
|
||||
void did_load_font(FlyString const& family_name);
|
||||
|
||||
Optional<FontLoader&> load_font_face(ParsedFontFace const&, Function<void(FontLoader const&)> on_load = {}, Function<void()> on_fail = {});
|
||||
|
||||
void load_fonts_from_sheet(CSSStyleSheet const&);
|
||||
|
||||
RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth = 0) const;
|
||||
|
@ -153,7 +158,6 @@ private:
|
|||
CreatePseudoElementStyleIfNeeded,
|
||||
};
|
||||
|
||||
class FontLoader;
|
||||
struct MatchingFontCandidate;
|
||||
|
||||
[[nodiscard]] bool should_reject_with_ancestor_filter(Selector const&) const;
|
||||
|
@ -226,4 +230,31 @@ private:
|
|||
CountingBloomFilter<u8, 14> m_ancestor_filter;
|
||||
};
|
||||
|
||||
class FontLoader : public ResourceClient {
|
||||
public:
|
||||
FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<URL::URL> urls, Function<void(FontLoader const&)> on_load = {}, Function<void()> on_fail = {});
|
||||
|
||||
virtual ~FontLoader() override;
|
||||
|
||||
Vector<Gfx::UnicodeRange> const& unicode_ranges() const { return m_unicode_ranges; }
|
||||
RefPtr<Gfx::VectorFont> vector_font() const { return m_vector_font; }
|
||||
|
||||
virtual void resource_did_load() override;
|
||||
virtual void resource_did_fail() override;
|
||||
|
||||
RefPtr<Gfx::Font> font_with_point_size(float point_size);
|
||||
void start_loading_next_url();
|
||||
|
||||
private:
|
||||
ErrorOr<NonnullRefPtr<Gfx::VectorFont>> try_load_font();
|
||||
|
||||
StyleComputer& m_style_computer;
|
||||
FlyString m_family_name;
|
||||
Vector<Gfx::UnicodeRange> m_unicode_ranges;
|
||||
RefPtr<Gfx::VectorFont> m_vector_font;
|
||||
Vector<URL::URL> m_urls;
|
||||
Function<void(FontLoader const&)> m_on_load;
|
||||
Function<void()> m_on_fail;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue