Переглянути джерело

LibWeb: Add `background-position` to `background` property

This required modifying the background-parsing code to use a
TokenStream, but that turned out to be pretty simple.
Sam Atkins 3 роки тому
батько
коміт
116a5fe5d0

+ 22 - 9
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -2396,14 +2396,15 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
     RefPtr<StyleValue> background_image;
     RefPtr<StyleValue> background_image;
     RefPtr<StyleValue> repeat_x;
     RefPtr<StyleValue> repeat_x;
     RefPtr<StyleValue> repeat_y;
     RefPtr<StyleValue> repeat_y;
-    // FIXME: Implement background-position.
+    RefPtr<StyleValue> background_position;
     // FIXME: Implement background-size.
     // FIXME: Implement background-size.
     // FIXME: Implement background-attachment.
     // FIXME: Implement background-attachment.
     // FIXME: Implement background-clip.
     // FIXME: Implement background-clip.
     // FIXME: Implement background-origin.
     // FIXME: Implement background-origin.
 
 
-    for (size_t i = 0; i < component_values.size(); ++i) {
-        auto& part = component_values[i];
+    auto tokens = TokenStream { component_values };
+    while (tokens.has_next_token()) {
+        auto& part = tokens.next_token();
 
 
         // FIXME: Handle multiple backgrounds, by returning a List of BackgroundStyleValues.
         // FIXME: Handle multiple backgrounds, by returning a List of BackgroundStyleValues.
         if (part.is(Token::Type::Comma)) {
         if (part.is(Token::Type::Comma)) {
@@ -2412,9 +2413,8 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
         }
         }
 
 
         auto value = parse_css_value(context, part);
         auto value = parse_css_value(context, part);
-        if (!value) {
+        if (!value)
             return nullptr;
             return nullptr;
-        }
 
 
         if (property_accepts_value(PropertyID::BackgroundColor, *value)) {
         if (property_accepts_value(PropertyID::BackgroundColor, *value)) {
             if (background_color)
             if (background_color)
@@ -2428,6 +2428,17 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
             background_image = value.release_nonnull();
             background_image = value.release_nonnull();
             continue;
             continue;
         }
         }
+        if (property_accepts_value(PropertyID::BackgroundPosition, *value)) {
+            if (background_position)
+                return nullptr;
+            tokens.reconsume_current_input_token();
+            if (auto maybe_background_position = parse_single_background_position_value(context, tokens)) {
+                background_position = maybe_background_position.release_nonnull();
+                // FIXME: background-size optionally goes here, after a '/'
+                continue;
+            }
+            return nullptr;
+        }
         if (property_accepts_value(PropertyID::BackgroundRepeat, *value)) {
         if (property_accepts_value(PropertyID::BackgroundRepeat, *value)) {
             if (repeat_x)
             if (repeat_x)
                 return nullptr;
                 return nullptr;
@@ -2440,10 +2451,10 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
             }
             }
 
 
             // Check following value, if it's also a repeat, set both.
             // Check following value, if it's also a repeat, set both.
-            if (i + 1 < component_values.size()) {
-                auto next_value = parse_css_value(context, component_values[i + 1]);
+            if (tokens.has_next_token()) {
+                auto next_value = parse_css_value(context, tokens.peek_token());
                 if (next_value && property_accepts_value(PropertyID::BackgroundRepeat, *next_value)) {
                 if (next_value && property_accepts_value(PropertyID::BackgroundRepeat, *next_value)) {
-                    ++i;
+                    tokens.next_token();
                     repeat_x = value.release_nonnull();
                     repeat_x = value.release_nonnull();
                     repeat_y = next_value.release_nonnull();
                     repeat_y = next_value.release_nonnull();
                     continue;
                     continue;
@@ -2462,12 +2473,14 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
         background_color = property_initial_value(PropertyID::BackgroundColor);
         background_color = property_initial_value(PropertyID::BackgroundColor);
     if (!background_image)
     if (!background_image)
         background_image = property_initial_value(PropertyID::BackgroundImage);
         background_image = property_initial_value(PropertyID::BackgroundImage);
+    if (!background_position)
+        background_position = property_initial_value(PropertyID::BackgroundPosition);
     if (!repeat_x)
     if (!repeat_x)
         repeat_x = property_initial_value(PropertyID::BackgroundRepeatX);
         repeat_x = property_initial_value(PropertyID::BackgroundRepeatX);
     if (!repeat_y)
     if (!repeat_y)
         repeat_y = property_initial_value(PropertyID::BackgroundRepeatY);
         repeat_y = property_initial_value(PropertyID::BackgroundRepeatY);
 
 
-    return BackgroundStyleValue::create(background_color.release_nonnull(), background_image.release_nonnull(), repeat_x.release_nonnull(), repeat_y.release_nonnull());
+    return BackgroundStyleValue::create(background_color.release_nonnull(), background_image.release_nonnull(), background_position.release_nonnull(), repeat_x.release_nonnull(), repeat_y.release_nonnull());
 }
 }
 
 
 RefPtr<StyleValue> Parser::parse_background_image_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
 RefPtr<StyleValue> Parser::parse_background_image_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)

+ 7 - 1
Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp

@@ -672,10 +672,16 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
     case CSS::PropertyID::Background: {
     case CSS::PropertyID::Background: {
         auto maybe_background_color = property(CSS::PropertyID::BackgroundColor);
         auto maybe_background_color = property(CSS::PropertyID::BackgroundColor);
         auto maybe_background_image = property(CSS::PropertyID::BackgroundImage);
         auto maybe_background_image = property(CSS::PropertyID::BackgroundImage);
+        auto maybe_background_position = property(CSS::PropertyID::BackgroundPosition);
         auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX);
         auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX);
         auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY);
         auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY);
 
 
-        return BackgroundStyleValue::create(value_or_default(maybe_background_color, InitialStyleValue::the()), value_or_default(maybe_background_image, IdentifierStyleValue::create(CSS::ValueID::None)), value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)), value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX)));
+        return BackgroundStyleValue::create(
+            value_or_default(maybe_background_color, InitialStyleValue::the()),
+            value_or_default(maybe_background_image, IdentifierStyleValue::create(CSS::ValueID::None)),
+            value_or_default(maybe_background_position, PositionStyleValue::create(PositionEdge::Left, Length::make_px(0), PositionEdge::Top, Length::make_px(0))),
+            value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)),
+            value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX)));
     }
     }
     case CSS::PropertyID::ListStyleType:
     case CSS::PropertyID::ListStyleType:
         return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().list_style_type()));
         return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().list_style_type()));

+ 2 - 0
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -301,6 +301,7 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
         auto set_single_background = [&](CSS::BackgroundStyleValue const& background) {
         auto set_single_background = [&](CSS::BackgroundStyleValue const& background) {
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, background.color(), document);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, background.color(), document);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, background.image(), document);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, background.image(), document);
+            set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundPosition, background.position(), document);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, background.repeat_x(), document, true);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, background.repeat_x(), document, true);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, background.repeat_y(), document, true);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, background.repeat_y(), document, true);
         };
         };
@@ -323,6 +324,7 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
 
 
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, value, document);
+        set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundPosition, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, value, document, true);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, value, document, true);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, value, document, true);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, value, document, true);
         return;
         return;

+ 7 - 3
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -377,39 +377,43 @@ public:
     static NonnullRefPtr<BackgroundStyleValue> create(
     static NonnullRefPtr<BackgroundStyleValue> create(
         NonnullRefPtr<StyleValue> color,
         NonnullRefPtr<StyleValue> color,
         NonnullRefPtr<StyleValue> image,
         NonnullRefPtr<StyleValue> image,
+        NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_y)
         NonnullRefPtr<StyleValue> repeat_y)
     {
     {
-        return adopt_ref(*new BackgroundStyleValue(color, image, repeat_x, repeat_y));
+        return adopt_ref(*new BackgroundStyleValue(color, image, position, repeat_x, repeat_y));
     }
     }
     virtual ~BackgroundStyleValue() override { }
     virtual ~BackgroundStyleValue() override { }
 
 
     NonnullRefPtr<StyleValue> color() const { return m_color; }
     NonnullRefPtr<StyleValue> color() const { return m_color; }
     NonnullRefPtr<StyleValue> image() const { return m_image; }
     NonnullRefPtr<StyleValue> image() const { return m_image; }
+    NonnullRefPtr<StyleValue> position() const { return m_position; }
     NonnullRefPtr<StyleValue> repeat_x() const { return m_repeat_x; }
     NonnullRefPtr<StyleValue> repeat_x() const { return m_repeat_x; }
     NonnullRefPtr<StyleValue> repeat_y() const { return m_repeat_y; }
     NonnullRefPtr<StyleValue> repeat_y() const { return m_repeat_y; }
 
 
     virtual String to_string() const override
     virtual String to_string() const override
     {
     {
-        return String::formatted("{} {} {} {}", m_color->to_string(), m_image->to_string(), m_repeat_x->to_string(), m_repeat_y->to_string());
+        return String::formatted("{} {} {} {} {}", m_color->to_string(), m_image->to_string(), m_position->to_string(), m_repeat_x->to_string(), m_repeat_y->to_string());
     }
     }
 
 
 private:
 private:
     BackgroundStyleValue(
     BackgroundStyleValue(
         NonnullRefPtr<StyleValue> color,
         NonnullRefPtr<StyleValue> color,
         NonnullRefPtr<StyleValue> image,
         NonnullRefPtr<StyleValue> image,
+        NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_y)
         NonnullRefPtr<StyleValue> repeat_y)
         : StyleValue(Type::Background)
         : StyleValue(Type::Background)
         , m_color(color)
         , m_color(color)
         , m_image(image)
         , m_image(image)
+        , m_position(position)
         , m_repeat_x(repeat_x)
         , m_repeat_x(repeat_x)
         , m_repeat_y(repeat_y)
         , m_repeat_y(repeat_y)
     {
     {
     }
     }
     NonnullRefPtr<StyleValue> m_color;
     NonnullRefPtr<StyleValue> m_color;
     NonnullRefPtr<StyleValue> m_image;
     NonnullRefPtr<StyleValue> m_image;
-    // FIXME: background-position
+    NonnullRefPtr<StyleValue> m_position;
     // FIXME: background-size
     // FIXME: background-size
     NonnullRefPtr<StyleValue> m_repeat_x;
     NonnullRefPtr<StyleValue> m_repeat_x;
     NonnullRefPtr<StyleValue> m_repeat_y;
     NonnullRefPtr<StyleValue> m_repeat_y;