From 13e2ca6b59e5aebaff98e224c47e723e1721da77 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 25 Aug 2023 10:52:20 +0200 Subject: [PATCH] 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. :^) --- .../expected/css/font-face-src-local-serialization.txt | 1 + .../input/css/font-face-src-local-serialization.html | 10 ++++++++++ Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp | 7 +++++-- Userland/Libraries/LibWeb/CSS/FontFace.h | 2 +- Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 9 ++++++++- Userland/Libraries/LibWeb/CSS/StyleComputer.cpp | 4 +++- Userland/Libraries/LibWeb/Dump.cpp | 5 ++++- 7 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/font-face-src-local-serialization.txt create mode 100644 Tests/LibWeb/Text/input/css/font-face-src-local-serialization.html diff --git a/Tests/LibWeb/Text/expected/css/font-face-src-local-serialization.txt b/Tests/LibWeb/Text/expected/css/font-face-src-local-serialization.txt new file mode 100644 index 0000000000..491578a759 --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/font-face-src-local-serialization.txt @@ -0,0 +1 @@ +@font-face { font-family: "a1"; src: local("xyz"); unicode-range: "U+0-10ffff"; } diff --git a/Tests/LibWeb/Text/input/css/font-face-src-local-serialization.html b/Tests/LibWeb/Text/input/css/font-face-src-local-serialization.html new file mode 100644 index 0000000000..6e1505b29a --- /dev/null +++ b/Tests/LibWeb/Text/input/css/font-face-src-local-serialization.html @@ -0,0 +1,10 @@ + + diff --git a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp index 9e486ab904..4fa5945cbd 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSFontFaceRule.cpp @@ -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()) { + serialize_a_url(builder, source.local_or_url.get().to_deprecated_string()); + } else { + builder.appendff("local({})", source.local_or_url.get()); + } // NOTE: No spec currently exists for format() if (source.format.has_value()) { diff --git a/Userland/Libraries/LibWeb/CSS/FontFace.h b/Userland/Libraries/LibWeb/CSS/FontFace.h index 04a112a2d0..eb46b3de30 100644 --- a/Userland/Libraries/LibWeb/CSS/FontFace.h +++ b/Userland/Libraries/LibWeb/CSS/FontFace.h @@ -16,7 +16,7 @@ namespace Web::CSS { class FontFace { public: struct Source { - AK::URL url; + Variant local_or_url; // FIXME: Do we need to keep this around, or is it only needed to discard unwanted formats during parsing? Optional format; }; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 5f76228272..384a02f4e4 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -4453,7 +4453,14 @@ Vector Parser::parse_font_face_src(TokenStream 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 {}); + continue; + } + dbgln_if(CSS_PARSER_DEBUG, "CSSParser: @font-face src invalid (failed to parse url from: {}); discarding.", first.to_debug_string()); return {}; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 64128d288b..253fbef348 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -2827,7 +2827,9 @@ void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet) Vector 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()) + urls.append(m_document->parse_url(source.local_or_url.get().to_deprecated_string())); + // FIXME: Handle local() } if (urls.is_empty()) diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index e716446212..023d7468c7 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -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()) + builder.appendff("url={}, format={}\n", source.local_or_url.get(), source.format.value_or("???"_string)); + else + builder.appendff("local={}\n", source.local_or_url.get()); } indent(builder, indent_levels + 1);