Forráskód Böngészése

LibWeb: Parse `background-clip` and `background-origin`

Including as part of the `background` shorthand. :^)
Sam Atkins 3 éve
szülő
commit
532f1e859d

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

@@ -163,6 +163,7 @@
   "outside",
   "outside",
   "overline",
   "overline",
   "p3",
   "p3",
+  "padding-box",
   "paged",
   "paged",
   "pointer",
   "pointer",
   "portrait",
   "portrait",

+ 34 - 3
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -2399,8 +2399,8 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
     RefPtr<StyleValue> background_position;
     RefPtr<StyleValue> background_position;
     // FIXME: Implement background-size.
     // FIXME: Implement background-size.
     RefPtr<StyleValue> background_attachment;
     RefPtr<StyleValue> background_attachment;
-    // FIXME: Implement background-clip.
-    // FIXME: Implement background-origin.
+    RefPtr<StyleValue> background_clip;
+    RefPtr<StyleValue> background_origin;
 
 
     auto tokens = TokenStream { component_values };
     auto tokens = TokenStream { component_values };
     while (tokens.has_next_token()) {
     while (tokens.has_next_token()) {
@@ -2434,6 +2434,23 @@ 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::BackgroundOrigin, *value)) {
+            // background-origin and background-clip accept the same values. From the spec:
+            //   "If one <box> value is present then it sets both background-origin and background-clip to that value.
+            //    If two values are present, then the first sets background-origin and the second background-clip."
+            //        - https://www.w3.org/TR/css-backgrounds-3/#background
+            // So, we put the first one in background-origin, then if we get a second, we put it in background-clip.
+            // If we only get one, we copy the value before creating the BackgroundStyleValue.
+            if (!background_origin) {
+                background_origin = value.release_nonnull();
+                continue;
+            }
+            if (!background_clip) {
+                background_clip = value.release_nonnull();
+                continue;
+            }
+            return nullptr;
+        }
         if (property_accepts_value(PropertyID::BackgroundPosition, *value)) {
         if (property_accepts_value(PropertyID::BackgroundPosition, *value)) {
             if (background_position)
             if (background_position)
                 return nullptr;
                 return nullptr;
@@ -2488,7 +2505,21 @@ RefPtr<StyleValue> Parser::parse_background_value(ParsingContext const& context,
     if (!background_attachment)
     if (!background_attachment)
         background_attachment = property_initial_value(PropertyID::BackgroundAttachment);
         background_attachment = property_initial_value(PropertyID::BackgroundAttachment);
 
 
-    return BackgroundStyleValue::create(background_color.release_nonnull(), background_image.release_nonnull(), background_position.release_nonnull(), repeat_x.release_nonnull(), repeat_y.release_nonnull(), background_attachment.release_nonnull());
+    if (!background_origin && !background_clip) {
+        background_origin = property_initial_value(PropertyID::BackgroundOrigin);
+        background_clip = property_initial_value(PropertyID::BackgroundClip);
+    } else if (!background_clip) {
+        background_clip = background_origin;
+    }
+
+    return BackgroundStyleValue::create(
+        background_color.release_nonnull(),
+        background_image.release_nonnull(),
+        background_position.release_nonnull(),
+        repeat_x.release_nonnull(), repeat_y.release_nonnull(),
+        background_attachment.release_nonnull(),
+        background_origin.release_nonnull(),
+        background_clip.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)

+ 18 - 0
Userland/Libraries/LibWeb/CSS/Properties.json

@@ -20,6 +20,15 @@
       "scroll"
       "scroll"
     ]
     ]
   },
   },
+  "background-clip": {
+    "inherited": false,
+    "initial": "border-box",
+    "valid-identifiers": [
+      "border-box",
+      "content-box",
+      "padding-box"
+    ]
+  },
   "background-color": {
   "background-color": {
     "inherited": false,
     "inherited": false,
     "initial": "transparent",
     "initial": "transparent",
@@ -40,6 +49,15 @@
       "none"
       "none"
     ]
     ]
   },
   },
+  "background-origin": {
+    "inherited": false,
+    "initial": "padding-box",
+    "valid-identifiers": [
+      "border-box",
+      "content-box",
+      "padding-box"
+    ]
+  },
   "background-position": {
   "background-position": {
     "inherited": false,
     "inherited": false,
     "initial": "0% 0%",
     "initial": "0% 0%",

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

@@ -676,6 +676,8 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
         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);
         auto maybe_background_attachment = property(CSS::PropertyID::BackgroundAttachment);
         auto maybe_background_attachment = property(CSS::PropertyID::BackgroundAttachment);
+        auto maybe_background_origin = property(CSS::PropertyID::BackgroundOrigin);
+        auto maybe_background_clip = property(CSS::PropertyID::BackgroundClip);
 
 
         return BackgroundStyleValue::create(
         return BackgroundStyleValue::create(
             value_or_default(maybe_background_color, InitialStyleValue::the()),
             value_or_default(maybe_background_color, InitialStyleValue::the()),
@@ -683,7 +685,9 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
             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_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_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)),
             value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX)),
             value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX)),
-            value_or_default(maybe_background_attachment, IdentifierStyleValue::create(CSS::ValueID::Scroll)));
+            value_or_default(maybe_background_attachment, IdentifierStyleValue::create(CSS::ValueID::Scroll)),
+            value_or_default(maybe_background_origin, IdentifierStyleValue::create(CSS::ValueID::PaddingBox)),
+            value_or_default(maybe_background_clip, IdentifierStyleValue::create(CSS::ValueID::BorderBox)));
     }
     }
     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()));

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

@@ -305,6 +305,8 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
             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);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundAttachment, background.attachment(), document);
             set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundAttachment, background.attachment(), document);
+            set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundOrigin, background.origin(), document);
+            set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundClip, background.clip(), document);
         };
         };
 
 
         if (value.is_background()) {
         if (value.is_background()) {
@@ -329,6 +331,8 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
         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);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundAttachment, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundAttachment, value, document);
+        set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundOrigin, value, document);
+        set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundClip, value, document);
         return;
         return;
     }
     }
 
 
@@ -347,6 +351,21 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
         return;
         return;
     }
     }
 
 
+    if (property_id == CSS::PropertyID::BackgroundClip) {
+        if (value.is_value_list()) {
+            auto& background_clip_list = value.as_value_list().values();
+            // FIXME: Handle multiple backgrounds.
+            if (!background_clip_list.is_empty()) {
+                auto& background_clip = background_clip_list.first();
+                style.set_property(CSS::PropertyID::BackgroundClip, background_clip);
+            }
+            return;
+        }
+
+        style.set_property(CSS::PropertyID::BackgroundClip, value);
+        return;
+    }
+
     if (property_id == CSS::PropertyID::BackgroundImage) {
     if (property_id == CSS::PropertyID::BackgroundImage) {
         if (value.is_value_list()) {
         if (value.is_value_list()) {
             auto& background_image_list = value.as_value_list().values();
             auto& background_image_list = value.as_value_list().values();
@@ -362,6 +381,21 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
         return;
         return;
     }
     }
 
 
+    if (property_id == CSS::PropertyID::BackgroundOrigin) {
+        if (value.is_value_list()) {
+            auto& background_origin_list = value.as_value_list().values();
+            // FIXME: Handle multiple backgrounds.
+            if (!background_origin_list.is_empty()) {
+                auto& background_origin = background_origin_list.first();
+                style.set_property(CSS::PropertyID::BackgroundOrigin, background_origin);
+            }
+            return;
+        }
+
+        style.set_property(CSS::PropertyID::BackgroundOrigin, value);
+        return;
+    }
+
     if (property_id == CSS::PropertyID::BackgroundPosition) {
     if (property_id == CSS::PropertyID::BackgroundPosition) {
         if (value.is_value_list()) {
         if (value.is_value_list()) {
             auto& background_position_list = value.as_value_list().values();
             auto& background_position_list = value.as_value_list().values();

+ 14 - 6
Userland/Libraries/LibWeb/CSS/StyleValue.h

@@ -380,22 +380,26 @@ public:
         NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_y,
         NonnullRefPtr<StyleValue> repeat_y,
-        NonnullRefPtr<StyleValue> attachment)
+        NonnullRefPtr<StyleValue> attachment,
+        NonnullRefPtr<StyleValue> origin,
+        NonnullRefPtr<StyleValue> clip)
     {
     {
-        return adopt_ref(*new BackgroundStyleValue(color, image, position, repeat_x, repeat_y, attachment));
+        return adopt_ref(*new BackgroundStyleValue(color, image, position, repeat_x, repeat_y, attachment, origin, clip));
     }
     }
     virtual ~BackgroundStyleValue() override { }
     virtual ~BackgroundStyleValue() override { }
 
 
     NonnullRefPtr<StyleValue> attachment() const { return m_attachment; }
     NonnullRefPtr<StyleValue> attachment() const { return m_attachment; }
+    NonnullRefPtr<StyleValue> clip() const { return m_clip; }
     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> origin() const { return m_origin; }
     NonnullRefPtr<StyleValue> position() const { return m_position; }
     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_position->to_string(), m_repeat_x->to_string(), m_repeat_y->to_string(), m_attachment->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(), m_attachment->to_string(), m_origin->to_string(), m_clip->to_string());
     }
     }
 
 
 private:
 private:
@@ -405,7 +409,9 @@ private:
         NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> position,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_x,
         NonnullRefPtr<StyleValue> repeat_y,
         NonnullRefPtr<StyleValue> repeat_y,
-        NonnullRefPtr<StyleValue> attachment)
+        NonnullRefPtr<StyleValue> attachment,
+        NonnullRefPtr<StyleValue> origin,
+        NonnullRefPtr<StyleValue> clip)
         : StyleValue(Type::Background)
         : StyleValue(Type::Background)
         , m_color(color)
         , m_color(color)
         , m_image(image)
         , m_image(image)
@@ -413,6 +419,8 @@ private:
         , m_repeat_x(repeat_x)
         , m_repeat_x(repeat_x)
         , m_repeat_y(repeat_y)
         , m_repeat_y(repeat_y)
         , m_attachment(attachment)
         , m_attachment(attachment)
+        , m_origin(origin)
+        , m_clip(clip)
     {
     {
     }
     }
     NonnullRefPtr<StyleValue> m_color;
     NonnullRefPtr<StyleValue> m_color;
@@ -422,8 +430,8 @@ private:
     NonnullRefPtr<StyleValue> m_repeat_x;
     NonnullRefPtr<StyleValue> m_repeat_x;
     NonnullRefPtr<StyleValue> m_repeat_y;
     NonnullRefPtr<StyleValue> m_repeat_y;
     NonnullRefPtr<StyleValue> m_attachment;
     NonnullRefPtr<StyleValue> m_attachment;
-    // FIXME: background-clip
-    // FIXME: background-origin
+    NonnullRefPtr<StyleValue> m_origin;
+    NonnullRefPtr<StyleValue> m_clip;
 };
 };
 
 
 class PositionStyleValue final : public StyleValue {
 class PositionStyleValue final : public StyleValue {