소스 검색

LibWeb: Parse `background-size` property

Sam Atkins 3 년 전
부모
커밋
67214e0b61

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Identifiers.json

@@ -86,6 +86,7 @@
   "contents",
   "context-menu",
   "copy",
+  "cover",
   "crosshair",
   "currentcolor",
   "cursive",

+ 39 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -2751,6 +2751,41 @@ RefPtr<StyleValue> Parser::parse_background_repeat_value(ParsingContext const& c
     return parse_single_background_repeat_value(context, tokens);
 }
 
+RefPtr<StyleValue> Parser::parse_single_background_size_value(ParsingContext const& context, TokenStream<StyleComponentValueRule>& 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<StyleValue> Parser::parse_background_size_value(ParsingContext const& context, Vector<StyleComponentValueRule> 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<StyleValue> Parser::parse_border_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
 {
     if (component_values.size() > 3)
@@ -3473,6 +3508,10 @@ Result<NonnullRefPtr<StyleValue>, 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:

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -218,6 +218,8 @@ private:
     static RefPtr<StyleValue> parse_background_position_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_single_background_repeat_value(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
     static RefPtr<StyleValue> parse_background_repeat_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
+    static RefPtr<StyleValue> parse_single_background_size_value(ParsingContext const&, TokenStream<StyleComponentValueRule>&);
+    static RefPtr<StyleValue> parse_background_size_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_border_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_border_radius_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
     static RefPtr<StyleValue> parse_border_radius_shorthand_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);

+ 14 - 0
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",

+ 15 - 0
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();