From 67214e0b61a6a9ced6b3ce2e3e990d8f059cc040 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 5 Nov 2021 13:44:37 +0000 Subject: [PATCH] LibWeb: Parse `background-size` property --- .../Libraries/LibWeb/CSS/Identifiers.json | 1 + .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 39 +++++++++++++++++++ Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 2 + Userland/Libraries/LibWeb/CSS/Properties.json | 14 +++++++ .../Libraries/LibWeb/CSS/StyleComputer.cpp | 15 +++++++ 5 files changed, 71 insertions(+) diff --git a/Userland/Libraries/LibWeb/CSS/Identifiers.json b/Userland/Libraries/LibWeb/CSS/Identifiers.json index 0623b13112..fc6410f247 100644 --- a/Userland/Libraries/LibWeb/CSS/Identifiers.json +++ b/Userland/Libraries/LibWeb/CSS/Identifiers.json @@ -86,6 +86,7 @@ "contents", "context-menu", "copy", + "cover", "crosshair", "currentcolor", "cursive", diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 01003415aa..cb528c7252 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2751,6 +2751,41 @@ RefPtr Parser::parse_background_repeat_value(ParsingContext const& c return parse_single_background_repeat_value(context, tokens); } +RefPtr Parser::parse_single_background_size_value(ParsingContext const& context, TokenStream& tokens) +{ + auto start_position = tokens.position(); + auto error = [&]() { + tokens.rewind_to_position(start_position); + return nullptr; + }; + + auto maybe_x_value = parse_css_value(context, tokens.next_token()); + if (!maybe_x_value || !property_accepts_value(PropertyID::BackgroundSize, *maybe_x_value)) + return error(); + auto x_value = maybe_x_value.release_nonnull(); + + if (x_value->to_identifier() == ValueID::Cover || x_value->to_identifier() == ValueID::Contain) + return x_value; + + auto maybe_y_value = parse_css_value(context, tokens.peek_token()); + if (!maybe_y_value || !property_accepts_value(PropertyID::BackgroundSize, *maybe_y_value)) + return BackgroundSizeStyleValue::create(x_value->to_length(), x_value->to_length()); + tokens.next_token(); + auto y_value = maybe_y_value.release_nonnull(); + + if (x_value->has_length() && y_value->has_length()) + return BackgroundSizeStyleValue::create(x_value->to_length(), y_value->to_length()); + + return error(); +} + +RefPtr Parser::parse_background_size_value(ParsingContext const& context, Vector const& component_values) +{ + auto tokens = TokenStream { component_values }; + // FIXME: Handle multiple sets of comma-separated values. + return parse_single_background_size_value(context, tokens); +} + RefPtr Parser::parse_border_value(ParsingContext const& context, Vector const& component_values) { if (component_values.size() > 3) @@ -3473,6 +3508,10 @@ Result, Parser::ParsingResult> Parser::parse_css_value if (auto parsed_value = parse_background_repeat_value(m_context, component_values)) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; + case PropertyID::BackgroundSize: + if (auto parsed_value = parse_background_size_value(m_context, component_values)) + return parsed_value.release_nonnull(); + return ParsingResult::SyntaxError; case PropertyID::Border: case PropertyID::BorderBottom: case PropertyID::BorderLeft: diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index a79f704a3d..6592e73dc4 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -218,6 +218,8 @@ private: static RefPtr parse_background_position_value(ParsingContext const&, Vector const&); static RefPtr parse_single_background_repeat_value(ParsingContext const&, TokenStream&); static RefPtr parse_background_repeat_value(ParsingContext const&, Vector const&); + static RefPtr parse_single_background_size_value(ParsingContext const&, TokenStream&); + static RefPtr parse_background_size_value(ParsingContext const&, Vector const&); static RefPtr parse_border_value(ParsingContext const&, Vector const&); static RefPtr parse_border_radius_value(ParsingContext const&, Vector const&); static RefPtr parse_border_radius_shorthand_value(ParsingContext const&, Vector const&); diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 9d3f520891..8112e27c2a 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -90,6 +90,20 @@ "space" ] }, + "background-size": { + "inherited": false, + "initial": "auto", + "max-values": 2, + "valid-types": [ + "length", + "percentage" + ], + "valid-identifiers": [ + "auto", + "cover", + "contain" + ] + }, "border": { "longhands": [ "border-width", diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 96c26702f4..3c11ffd36a 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -418,6 +418,21 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope return; } + if (property_id == CSS::PropertyID::BackgroundSize) { + if (value.is_value_list()) { + auto& background_size_list = value.as_value_list().values(); + // FIXME: Handle multiple backgrounds. + if (!background_size_list.is_empty()) { + auto& background_size = background_size_list.first(); + style.set_property(CSS::PropertyID::BackgroundSize, background_size); + } + return; + } + + style.set_property(CSS::PropertyID::BackgroundSize, value); + return; + } + if (property_id == CSS::PropertyID::Margin) { if (value.is_value_list()) { auto& values_list = value.as_value_list();