mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 04:09:13 +00:00
LibWeb/CSS: Use CSS::URL for font-fetching
ParsedFontFace and FontLoader now both keep track of which CSSStyleSheet (if any) was the source of the font-face, so the URLs can be completed correctly.
This commit is contained in:
parent
14fb567a0f
commit
9e2e796f2d
Notes:
github-actions[bot]
2025-05-03 11:02:47 +00:00
Author: https://github.com/AtkinsSJ
Commit: 9e2e796f2d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4536
9 changed files with 38 additions and 31 deletions
|
@ -483,6 +483,7 @@ GC::Ref<WebIDL::Promise> FontFace::load()
|
|||
|
||||
// FIXME: The ParsedFontFace is kind of expensive to create. We should be using a shared sub-object for the data
|
||||
ParsedFontFace parsed_font_face {
|
||||
nullptr,
|
||||
font->m_family,
|
||||
font->m_weight.to_number<int>(),
|
||||
0, // FIXME: slope
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <LibWeb/CSS/CSSFontFaceDescriptors.h>
|
||||
#include <LibWeb/CSS/CSSRule.h>
|
||||
#include <LibWeb/CSS/ParsedFontFace.h>
|
||||
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
|
||||
|
@ -38,7 +39,7 @@ Vector<ParsedFontFace::Source> ParsedFontFace::sources_from_style_value(CSSStyle
|
|||
[&](FontSourceStyleValue::Local const& local) {
|
||||
sources.empend(extract_font_name(local.name), OptionalNone {});
|
||||
},
|
||||
[&](::URL::URL const& url) {
|
||||
[&](URL const& url) {
|
||||
// FIXME: tech()
|
||||
sources.empend(url, font_source.format());
|
||||
});
|
||||
|
@ -171,6 +172,7 @@ ParsedFontFace ParsedFontFace::from_descriptors(CSSFontFaceDescriptors const& de
|
|||
}
|
||||
|
||||
return ParsedFontFace {
|
||||
descriptors.parent_rule()->parent_style_sheet(),
|
||||
move(font_family),
|
||||
move(weight),
|
||||
move(slope),
|
||||
|
@ -188,8 +190,9 @@ ParsedFontFace ParsedFontFace::from_descriptors(CSSFontFaceDescriptors const& de
|
|||
};
|
||||
}
|
||||
|
||||
ParsedFontFace::ParsedFontFace(FlyString font_family, Optional<int> weight, Optional<int> slope, Optional<int> width, Vector<Source> sources, Vector<Gfx::UnicodeRange> unicode_ranges, Optional<Percentage> ascent_override, Optional<Percentage> descent_override, Optional<Percentage> line_gap_override, FontDisplay font_display, Optional<FlyString> font_named_instance, Optional<FlyString> font_language_override, Optional<OrderedHashMap<FlyString, i64>> font_feature_settings, Optional<OrderedHashMap<FlyString, double>> font_variation_settings)
|
||||
: m_font_family(move(font_family))
|
||||
ParsedFontFace::ParsedFontFace(GC::Ptr<CSSStyleSheet> parent_style_sheet, FlyString font_family, Optional<int> weight, Optional<int> slope, Optional<int> width, Vector<Source> sources, Vector<Gfx::UnicodeRange> unicode_ranges, Optional<Percentage> ascent_override, Optional<Percentage> descent_override, Optional<Percentage> line_gap_override, FontDisplay font_display, Optional<FlyString> font_named_instance, Optional<FlyString> font_language_override, Optional<OrderedHashMap<FlyString, i64>> font_feature_settings, Optional<OrderedHashMap<FlyString, double>> font_variation_settings)
|
||||
: m_parent_style_sheet(parent_style_sheet)
|
||||
, m_font_family(move(font_family))
|
||||
, m_font_named_instance(move(font_named_instance))
|
||||
, m_weight(weight)
|
||||
, m_slope(slope)
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
#include <AK/FlyString.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibGfx/Font/UnicodeRange.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <LibWeb/CSS/Enums.h>
|
||||
#include <LibWeb/CSS/Percentage.h>
|
||||
#include <LibWeb/CSS/URL.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class ParsedFontFace {
|
||||
public:
|
||||
struct Source {
|
||||
Variant<FlyString, ::URL::URL> local_or_url;
|
||||
Variant<FlyString, URL> local_or_url;
|
||||
// FIXME: Do we need to keep this around, or is it only needed to discard unwanted formats during parsing?
|
||||
Optional<FlyString> format;
|
||||
};
|
||||
|
@ -27,9 +27,10 @@ public:
|
|||
static Vector<Source> sources_from_style_value(CSSStyleValue const&);
|
||||
static ParsedFontFace from_descriptors(CSSFontFaceDescriptors const&);
|
||||
|
||||
ParsedFontFace(FlyString font_family, Optional<int> weight, Optional<int> slope, Optional<int> width, Vector<Source> sources, Vector<Gfx::UnicodeRange> unicode_ranges, Optional<Percentage> ascent_override, Optional<Percentage> descent_override, Optional<Percentage> line_gap_override, FontDisplay font_display, Optional<FlyString> font_named_instance, Optional<FlyString> font_language_override, Optional<OrderedHashMap<FlyString, i64>> font_feature_settings, Optional<OrderedHashMap<FlyString, double>> font_variation_settings);
|
||||
ParsedFontFace(GC::Ptr<CSSStyleSheet> parent_style_sheet, FlyString font_family, Optional<int> weight, Optional<int> slope, Optional<int> width, Vector<Source> sources, Vector<Gfx::UnicodeRange> unicode_ranges, Optional<Percentage> ascent_override, Optional<Percentage> descent_override, Optional<Percentage> line_gap_override, FontDisplay font_display, Optional<FlyString> font_named_instance, Optional<FlyString> font_language_override, Optional<OrderedHashMap<FlyString, i64>> font_feature_settings, Optional<OrderedHashMap<FlyString, double>> font_variation_settings);
|
||||
~ParsedFontFace() = default;
|
||||
|
||||
GC::Ptr<CSSStyleSheet> parent_style_sheet() const { return m_parent_style_sheet; }
|
||||
Optional<Percentage> ascent_override() const { return m_ascent_override; }
|
||||
Optional<Percentage> descent_override() const { return m_descent_override; }
|
||||
FontDisplay font_display() const { return m_font_display; }
|
||||
|
@ -46,6 +47,7 @@ public:
|
|||
Vector<Gfx::UnicodeRange> const& unicode_ranges() const { return m_unicode_ranges; }
|
||||
|
||||
private:
|
||||
GC::Ptr<CSSStyleSheet> m_parent_style_sheet;
|
||||
FlyString m_font_family;
|
||||
Optional<FlyString> m_font_named_instance;
|
||||
Optional<int> m_weight;
|
||||
|
|
|
@ -3813,10 +3813,6 @@ RefPtr<FontSourceStyleValue const> Parser::parse_font_source_value(TokenStream<C
|
|||
auto url = parse_url_function(tokens);
|
||||
if (!url.has_value())
|
||||
return nullptr;
|
||||
// FIXME: Stop completing the URL here
|
||||
auto completed_url = complete_url(url->url());
|
||||
if (!completed_url.has_value())
|
||||
return nullptr;
|
||||
|
||||
Optional<FlyString> format;
|
||||
|
||||
|
@ -3859,7 +3855,7 @@ RefPtr<FontSourceStyleValue const> Parser::parse_font_source_value(TokenStream<C
|
|||
// FIXME: [ tech( <font-tech>#)]?
|
||||
|
||||
transaction.commit();
|
||||
return FontSourceStyleValue::create(completed_url.release_value(), move(format));
|
||||
return FontSourceStyleValue::create(url.release_value(), move(format));
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue const> Parser::resolve_unresolved_style_value(ParsingParams const& context, DOM::Element& element, Optional<PseudoElement> pseudo_element, PropertyID property_id, UnresolvedStyleValue const& unresolved)
|
||||
|
|
|
@ -187,8 +187,9 @@ StyleComputer::StyleComputer(DOM::Document& document)
|
|||
|
||||
StyleComputer::~StyleComputer() = default;
|
||||
|
||||
FontLoader::FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<::URL::URL> urls, Function<void(RefPtr<Gfx::Typeface const>)> on_load)
|
||||
FontLoader::FontLoader(StyleComputer& style_computer, GC::Ptr<CSSStyleSheet> parent_style_sheet, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<URL> urls, Function<void(RefPtr<Gfx::Typeface const>)> on_load)
|
||||
: m_style_computer(style_computer)
|
||||
, m_parent_style_sheet(parent_style_sheet)
|
||||
, m_family_name(move(family_name))
|
||||
, m_unicode_ranges(move(unicode_ranges))
|
||||
, m_urls(move(urls))
|
||||
|
@ -225,8 +226,8 @@ void FontLoader::start_loading_next_url()
|
|||
// To fetch a font given a selected <url> url for @font-face rule, fetch url, with stylesheet being rule’s parent
|
||||
// CSS style sheet, destination "font", CORS mode "cors", and processResponse being the following steps given
|
||||
// response res and null, failure or a byte stream stream:
|
||||
// FIXME: Get the rule's parent style sheet from somewhere
|
||||
auto maybe_fetch_controller = fetch_a_style_resource(m_urls.take_first(), GC::Ref { m_style_computer.document() }, Fetch::Infrastructure::Request::Destination::Font, CorsMode::Cors,
|
||||
auto style_sheet_or_document = m_parent_style_sheet ? StyleSheetOrDocument { *m_parent_style_sheet } : StyleSheetOrDocument { m_style_computer.document() };
|
||||
auto maybe_fetch_controller = fetch_a_style_resource(m_urls.take_first(), style_sheet_or_document, Fetch::Infrastructure::Request::Destination::Font, CorsMode::Cors,
|
||||
[weak_loader = make_weak_ptr()](auto response, auto stream) {
|
||||
// NB: If the FontLoader died before this fetch completed, nobody wants the data.
|
||||
if (weak_loader.is_null())
|
||||
|
@ -3049,11 +3050,10 @@ Optional<FontLoader&> StyleComputer::load_font_face(ParsedFontFace const& font_f
|
|||
};
|
||||
|
||||
// FIXME: Pass the sources directly, so the font loader can make use of the format information, or load local fonts.
|
||||
Vector<::URL::URL> urls;
|
||||
Vector<URL> urls;
|
||||
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->encoding_parse_url(source.local_or_url.get<::URL::URL>().to_string()));
|
||||
if (source.local_or_url.has<URL>())
|
||||
urls.append(source.local_or_url.get<URL>());
|
||||
// FIXME: Handle local()
|
||||
}
|
||||
|
||||
|
@ -3063,7 +3063,7 @@ Optional<FontLoader&> StyleComputer::load_font_face(ParsedFontFace const& font_f
|
|||
return {};
|
||||
}
|
||||
|
||||
auto loader = make<FontLoader>(*this, font_face.font_family(), font_face.unicode_ranges(), move(urls), move(on_load));
|
||||
auto loader = make<FontLoader>(*this, font_face.parent_style_sheet(), font_face.font_family(), font_face.unicode_ranges(), move(urls), move(on_load));
|
||||
auto& loader_ref = *loader;
|
||||
auto maybe_font_loaders_list = m_loaded_fonts.get(key);
|
||||
if (maybe_font_loaders_list.has_value()) {
|
||||
|
|
|
@ -315,7 +315,7 @@ private:
|
|||
|
||||
class FontLoader : public Weakable<FontLoader> {
|
||||
public:
|
||||
FontLoader(StyleComputer& style_computer, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<::URL::URL> urls, ESCAPING Function<void(RefPtr<Gfx::Typeface const>)> on_load = {});
|
||||
FontLoader(StyleComputer& style_computer, GC::Ptr<CSSStyleSheet> parent_style_sheet, FlyString family_name, Vector<Gfx::UnicodeRange> unicode_ranges, Vector<URL> urls, ESCAPING Function<void(RefPtr<Gfx::Typeface const>)> on_load = {});
|
||||
|
||||
virtual ~FontLoader();
|
||||
|
||||
|
@ -333,10 +333,11 @@ private:
|
|||
void font_did_load_or_fail(RefPtr<Gfx::Typeface const>);
|
||||
|
||||
StyleComputer& m_style_computer;
|
||||
GC::Ptr<CSSStyleSheet> m_parent_style_sheet;
|
||||
FlyString m_family_name;
|
||||
Vector<Gfx::UnicodeRange> m_unicode_ranges;
|
||||
RefPtr<Gfx::Typeface const> m_vector_font;
|
||||
Vector<::URL::URL> m_urls;
|
||||
Vector<URL> m_urls;
|
||||
GC::Root<Fetch::Infrastructure::FetchController> m_fetch_controller;
|
||||
Function<void(RefPtr<Gfx::Typeface const>)> m_on_load;
|
||||
};
|
||||
|
|
|
@ -34,11 +34,11 @@ String FontSourceStyleValue::to_string(SerializationMode) const
|
|||
builder.append(')');
|
||||
return builder.to_string_without_validation();
|
||||
},
|
||||
[this](::URL::URL const& url) {
|
||||
[this](URL const& url) {
|
||||
// <url> [ format(<font-format>)]? [ tech( <font-tech>#)]?
|
||||
// FIXME: tech()
|
||||
StringBuilder builder;
|
||||
serialize_a_url(builder, url.to_string());
|
||||
builder.append(url.to_string());
|
||||
|
||||
if (m_format.has_value()) {
|
||||
builder.append(" format("sv);
|
||||
|
@ -59,8 +59,8 @@ bool FontSourceStyleValue::properties_equal(FontSourceStyleValue const& other) c
|
|||
}
|
||||
return false;
|
||||
},
|
||||
[&other](::URL::URL const& url) {
|
||||
if (auto* other_url = other.m_source.get_pointer<::URL::URL>()) {
|
||||
[&other](URL const& url) {
|
||||
if (auto* other_url = other.m_source.get_pointer<URL>()) {
|
||||
return url == *other_url;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <AK/FlyString.h>
|
||||
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||
#include <LibWeb/CSS/URL.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -16,7 +17,7 @@ public:
|
|||
struct Local {
|
||||
NonnullRefPtr<CSSStyleValue const> name;
|
||||
};
|
||||
using Source = Variant<Local, ::URL::URL>;
|
||||
using Source = Variant<Local, URL>;
|
||||
|
||||
static ValueComparingNonnullRefPtr<FontSourceStyleValue const> create(Source source, Optional<FlyString> format)
|
||||
{
|
||||
|
|
|
@ -728,12 +728,15 @@ void dump_font_face_rule(StringBuilder& builder, CSS::CSSFontFaceRule const& rul
|
|||
|
||||
indent(builder, indent_levels + 1);
|
||||
builder.append("sources:\n"sv);
|
||||
for (auto const& source : font_face.sources()) {
|
||||
for (auto const& [local_or_url, format] : font_face.sources()) {
|
||||
indent(builder, indent_levels + 2);
|
||||
if (source.local_or_url.has<URL::URL>())
|
||||
builder.appendff("url={}, format={}\n", source.local_or_url.get<URL::URL>(), source.format.value_or("???"_string));
|
||||
else
|
||||
builder.appendff("local={}\n", source.local_or_url.get<FlyString>());
|
||||
local_or_url.visit(
|
||||
[&builder, &format](CSS::URL const& url) {
|
||||
builder.appendff("url={}, format={}\n", url, format.value_or("???"_string));
|
||||
},
|
||||
[&builder](FlyString const& local) {
|
||||
builder.appendff("local={}\n", local);
|
||||
});
|
||||
}
|
||||
|
||||
indent(builder, indent_levels + 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue