mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 11:42:38 +03:00
LibWeb: Load and use fonts described by @font-face rules :^)
When encountering a @font-face rule, StyleComputer will now fire off a resource request and download the first source URL specified. Once downloaded, we try to parse it as a TrueType font file, and if it works, it's added to a cache in StyleComputer. This effectively makes fonts per-document since every document has its own StyleComputer. This is very unoptimized and could definitely use some caching, etc. But it does work on Acid3. :^)
This commit is contained in:
parent
dcb24e943d
commit
1f9aed2617
Notes:
sideshowbarker
2024-07-17 16:35:41 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/1f9aed2617
@ -12,6 +12,8 @@
|
||||
#include <LibGfx/Font.h>
|
||||
#include <LibGfx/FontDatabase.h>
|
||||
#include <LibGfx/FontStyleMapping.h>
|
||||
#include <LibGfx/TrueTypeFont/Font.h>
|
||||
#include <LibWeb/CSS/CSSFontFaceRule.h>
|
||||
#include <LibWeb/CSS/CSSStyleRule.h>
|
||||
#include <LibWeb/CSS/Parser/Parser.h>
|
||||
#include <LibWeb/CSS/SelectorEngine.h>
|
||||
@ -21,6 +23,7 @@
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/FontCache.h>
|
||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||
#include <LibWeb/Loader/ResourceLoader.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
@ -30,6 +33,47 @@ StyleComputer::StyleComputer(DOM::Document& document)
|
||||
{
|
||||
}
|
||||
|
||||
StyleComputer::~StyleComputer() = default;
|
||||
|
||||
class StyleComputer::FontLoader : public ResourceClient {
|
||||
public:
|
||||
explicit FontLoader(StyleComputer& style_computer, FlyString family_name, AK::URL url)
|
||||
: m_style_computer(style_computer)
|
||||
, m_family_name(move(family_name))
|
||||
{
|
||||
LoadRequest request;
|
||||
request.set_url(move(url));
|
||||
set_resource(ResourceLoader::the().load_resource(Resource::Type::Generic, request));
|
||||
}
|
||||
|
||||
virtual ~FontLoader() override { }
|
||||
|
||||
virtual void resource_did_load() override
|
||||
{
|
||||
auto result = TTF::Font::try_load_from_externally_owned_memory(resource()->encoded_data());
|
||||
if (result.is_error())
|
||||
return;
|
||||
m_ttf_font = result.release_value();
|
||||
m_style_computer.did_load_font(m_family_name);
|
||||
}
|
||||
|
||||
virtual void resource_did_fail() override
|
||||
{
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font> font_with_point_size(float point_size) const
|
||||
{
|
||||
if (!m_ttf_font)
|
||||
return nullptr;
|
||||
return adopt_ref(*new TTF::ScaledFont(*m_ttf_font, point_size, point_size));
|
||||
}
|
||||
|
||||
private:
|
||||
StyleComputer& m_style_computer;
|
||||
FlyString m_family_name;
|
||||
RefPtr<TTF::Font> m_ttf_font;
|
||||
};
|
||||
|
||||
static StyleSheet& default_stylesheet()
|
||||
{
|
||||
static StyleSheet* sheet;
|
||||
@ -880,6 +924,12 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
|
||||
float font_size_in_pt = font_size_in_px * 0.75f;
|
||||
font_selector = { family, font_size_in_pt, weight, slope };
|
||||
|
||||
if (auto it = m_loaded_fonts.find(family); it != m_loaded_fonts.end()) {
|
||||
auto& loader = *it->value;
|
||||
if (auto found_font = loader.font_with_point_size(font_size_in_pt))
|
||||
return found_font;
|
||||
}
|
||||
|
||||
if (auto found_font = FontCache::the().get(font_selector))
|
||||
return found_font;
|
||||
|
||||
@ -1041,6 +1091,7 @@ NonnullRefPtr<StyleProperties> StyleComputer::create_document_style() const
|
||||
|
||||
NonnullRefPtr<StyleProperties> StyleComputer::compute_style(DOM::Element& element, Optional<CSS::Selector::PseudoElement> pseudo_element) const
|
||||
{
|
||||
load_fonts_if_needed();
|
||||
build_rule_cache_if_needed();
|
||||
|
||||
auto style = StyleProperties::create();
|
||||
@ -1183,4 +1234,28 @@ Gfx::IntRect StyleComputer::viewport_rect() const
|
||||
return {};
|
||||
}
|
||||
|
||||
void StyleComputer::did_load_font([[maybe_unused]] FlyString const& family_name)
|
||||
{
|
||||
document().invalidate_style();
|
||||
}
|
||||
|
||||
void StyleComputer::load_fonts_if_needed() const
|
||||
{
|
||||
for_each_stylesheet(CascadeOrigin::Author, [&](StyleSheet const& sheet) {
|
||||
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 (m_loaded_fonts.contains(font_face.font_family()))
|
||||
continue;
|
||||
|
||||
LoadRequest request;
|
||||
auto url = m_document.parse_url(font_face.sources().first().url.to_string());
|
||||
auto loader = make<FontLoader>(const_cast<StyleComputer&>(*this), font_face.font_family(), move(url));
|
||||
const_cast<StyleComputer&>(*this).m_loaded_fonts.set(font_face.font_family(), move(loader));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibWeb/CSS/CSSFontFaceRule.h>
|
||||
#include <LibWeb/CSS/CSSStyleDeclaration.h>
|
||||
#include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
|
||||
#include <LibWeb/CSS/Selector.h>
|
||||
@ -48,7 +49,7 @@ private:
|
||||
class StyleComputer {
|
||||
public:
|
||||
explicit StyleComputer(DOM::Document&);
|
||||
~StyleComputer() = default;
|
||||
~StyleComputer();
|
||||
|
||||
DOM::Document& document() { return m_document; }
|
||||
DOM::Document const& document() const { return m_document; }
|
||||
@ -71,6 +72,8 @@ public:
|
||||
|
||||
Gfx::Font const& initial_font() const;
|
||||
|
||||
void did_load_font(FlyString const& family_name);
|
||||
|
||||
private:
|
||||
void compute_cascaded_values(StyleProperties&, DOM::Element&, Optional<CSS::Selector::PseudoElement>) const;
|
||||
void compute_font(StyleProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement>) const;
|
||||
@ -109,6 +112,11 @@ private:
|
||||
Vector<MatchingRule> other_rules;
|
||||
};
|
||||
OwnPtr<RuleCache> m_rule_cache;
|
||||
|
||||
void load_fonts_if_needed() const;
|
||||
|
||||
class FontLoader;
|
||||
HashMap<String, NonnullOwnPtr<FontLoader>> m_loaded_fonts;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user