LibWeb: Parse src: local(...) in CSS @font-face rules

Note that we don't load the local font as specified, but at least we no
longer reject such src properties in the CSS parser.

This makes the custom fonts used on http://apple.com/ actually load. :^)
This commit is contained in:
Andreas Kling 2023-08-25 10:52:20 +02:00
parent e924ea002f
commit 13e2ca6b59
Notes: sideshowbarker 2024-07-17 07:16:27 +09:00
7 changed files with 32 additions and 6 deletions

View file

@ -0,0 +1 @@
@font-face { font-family: "a1"; src: local("xyz"); unicode-range: "U+0-10ffff"; }

View file

@ -0,0 +1,10 @@
<script src="../include.js"></script>
<script>
test(() => {
let style = document.createElement("style");
style.innerText = "@font-face { font-family: 'a1'; src: local('xyz'); }";
document.head.appendChild(style);
let sheet = style.sheet;
println(sheet.cssRules[0].cssText);
});
</script>

View file

@ -62,8 +62,11 @@ DeprecatedString CSSFontFaceRule::serialized() const
// 2. The result of invoking serialize a comma-separated list on performing serialize a URL or serialize a LOCAL for each source on the source list.
serialize_a_comma_separated_list(builder, m_font_face.sources(), [&](StringBuilder& builder, FontFace::Source source) -> void {
// FIXME: Serialize locals once we support those
serialize_a_url(builder, source.url.to_deprecated_string());
if (source.local_or_url.has<AK::URL>()) {
serialize_a_url(builder, source.local_or_url.get<AK::URL>().to_deprecated_string());
} else {
builder.appendff("local({})", source.local_or_url.get<String>());
}
// NOTE: No spec currently exists for format()
if (source.format.has_value()) {

View file

@ -16,7 +16,7 @@ namespace Web::CSS {
class FontFace {
public:
struct Source {
AK::URL url;
Variant<String, AK::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;
};

View file

@ -4453,7 +4453,14 @@ Vector<FontFace::Source> Parser::parse_font_face_src(TokenStream<ComponentValue>
continue;
}
// FIXME: Implement `local()`.
if (first.is_function() && first.function().name().equals_ignoring_ascii_case("local"sv)) {
if (first.function().values().is_empty()) {
continue;
}
supported_sources.empend(first.function().values().first().to_string(), Optional<FlyString> {});
continue;
}
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: @font-face src invalid (failed to parse url from: {}); discarding.", first.to_debug_string());
return {};
}

View file

@ -2827,7 +2827,9 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
Vector<AK::URL> urls;
for (auto& source : font_face.sources()) {
// FIXME: These should be loaded relative to the stylesheet URL instead of the document URL.
urls.append(m_document->parse_url(source.url.to_deprecated_string()));
if (source.local_or_url.has<AK::URL>())
urls.append(m_document->parse_url(source.local_or_url.get<AK::URL>().to_deprecated_string()));
// FIXME: Handle local()
}
if (urls.is_empty())

View file

@ -654,7 +654,10 @@ void dump_font_face_rule(StringBuilder& builder, CSS::CSSFontFaceRule const& rul
builder.append("sources:\n"sv);
for (auto const& source : font_face.sources()) {
indent(builder, indent_levels + 2);
builder.appendff("url={}, format={}\n", source.url, source.format.value_or("???"_string));
if (source.local_or_url.has<AK::URL>())
builder.appendff("url={}, format={}\n", source.local_or_url.get<AK::URL>(), source.format.value_or("???"_string));
else
builder.appendff("local={}\n", source.local_or_url.get<AK::String>());
}
indent(builder, indent_levels + 1);