diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 0808501508..5d9df0c6a9 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -49,8 +49,8 @@ struct BackgroundLayerData { CSS::PositionEdge position_edge_y { CSS::PositionEdge::Top }; CSS::Length position_offset_y { CSS::Length::make_px(0) }; CSS::BackgroundSize size_type { CSS::BackgroundSize::LengthPercentage }; - CSS::Length size_x { CSS::Length::make_auto() }; - CSS::Length size_y { CSS::Length::make_auto() }; + CSS::LengthPercentage size_x { CSS::Length::make_auto() }; + CSS::LengthPercentage size_y { CSS::Length::make_auto() }; CSS::Repeat repeat_x { CSS::Repeat::Repeat }; CSS::Repeat repeat_y { CSS::Repeat::Repeat }; }; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 3f8ba8c4f5..3b7e93a13e 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2940,6 +2940,14 @@ RefPtr Parser::parse_single_background_size_value(TokenStream Optional { + if (style_value.is_percentage()) + return LengthPercentage { style_value.as_percentage().percentage() }; + if (style_value.has_length()) + return LengthPercentage { style_value.to_length() }; + return {}; + }; + auto maybe_x_value = parse_css_value(tokens.next_token()); if (!maybe_x_value || !property_accepts_value(PropertyID::BackgroundSize, *maybe_x_value)) return error(); @@ -2949,13 +2957,20 @@ RefPtr Parser::parse_single_background_size_value(TokenStreamto_length(), x_value->to_length()); + if (!maybe_y_value || !property_accepts_value(PropertyID::BackgroundSize, *maybe_y_value)) { + auto x_size = get_length_percentage(*x_value); + if (!x_size.has_value()) + return error(); + return BackgroundSizeStyleValue::create(x_size.value(), x_size.value()); + } + tokens.next_token(); auto y_value = maybe_y_value.release_nonnull(); + auto x_size = get_length_percentage(*x_value); + auto y_size = get_length_percentage(*y_value); - if (x_value->has_length() && y_value->has_length()) - return BackgroundSizeStyleValue::create(x_value->to_length(), y_value->to_length()); + if (x_size.has_value() && y_size.has_value()) + return BackgroundSizeStyleValue::create(x_size.release_value(), y_size.release_value()); return error(); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 7397a1d70e..32b7344494 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -499,14 +499,14 @@ private: // NOTE: This is not used for identifier sizes, like `cover` and `contain`. class BackgroundSizeStyleValue final : public StyleValue { public: - static NonnullRefPtr create(Length size_x, Length size_y) + static NonnullRefPtr create(LengthPercentage size_x, LengthPercentage size_y) { return adopt_ref(*new BackgroundSizeStyleValue(size_x, size_y)); } virtual ~BackgroundSizeStyleValue() override { } - Length size_x() const { return m_size_x; } - Length size_y() const { return m_size_y; } + LengthPercentage size_x() const { return m_size_x; } + LengthPercentage size_y() const { return m_size_y; } virtual String to_string() const override { @@ -514,15 +514,15 @@ public: } private: - BackgroundSizeStyleValue(Length size_x, Length size_y) + BackgroundSizeStyleValue(LengthPercentage size_x, LengthPercentage size_y) : StyleValue(Type::BackgroundSize) , m_size_x(size_x) , m_size_y(size_y) { } - Length m_size_x; - Length m_size_y; + LengthPercentage m_size_x; + LengthPercentage m_size_y; }; class BorderStyleValue final : public StyleValue { diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index 0b60e82e68..9e4afb5db1 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -82,18 +82,28 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet case CSS::BackgroundSize::LengthPercentage: { int width; int height; - if (layer.size_x.is_auto() && layer.size_y.is_auto()) { + bool x_is_auto = layer.size_x.is_length() && layer.size_x.length().is_auto(); + bool y_is_auto = layer.size_y.is_length() && layer.size_y.length().is_auto(); + if (x_is_auto && y_is_auto) { width = image.width(); height = image.height(); - } else if (layer.size_x.is_auto()) { - height = layer.size_y.resolved_or_zero(layout_node, background_positioning_area.height()).to_px(layout_node); + } else if (x_is_auto) { + height = layer.size_y.resolved(CSS::Length::make_px(background_positioning_area.height())) + .resolved_or_zero(layout_node, background_positioning_area.height()) + .to_px(layout_node); width = roundf(image.width() * ((float)height / (float)image.height())); - } else if (layer.size_y.is_auto()) { - width = layer.size_x.resolved_or_zero(layout_node, background_positioning_area.width()).to_px(layout_node); + } else if (y_is_auto) { + width = layer.size_x.resolved(CSS::Length::make_px(background_positioning_area.width())) + .resolved_or_zero(layout_node, background_positioning_area.width()) + .to_px(layout_node); height = roundf(image.height() * ((float)width / (float)image.width())); } else { - width = layer.size_x.resolved_or_zero(layout_node, background_positioning_area.width()).to_px(layout_node); - height = layer.size_y.resolved_or_zero(layout_node, background_positioning_area.height()).to_px(layout_node); + width = layer.size_x.resolved(CSS::Length::make_px(background_positioning_area.width())) + .resolved_or_zero(layout_node, background_positioning_area.width()) + .to_px(layout_node); + height = layer.size_y.resolved(CSS::Length::make_px(background_positioning_area.height())) + .resolved_or_zero(layout_node, background_positioning_area.height()) + .to_px(layout_node); } image_rect.set_size(width, height); @@ -120,10 +130,10 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet // for the other dimension, then there is a third step: that other dimension is scaled // so that the original aspect ratio is restored. if (layer.repeat_x != layer.repeat_y) { - if (layer.size_x.is_auto()) { + if (layer.size_x.is_length() && layer.size_x.length().is_auto()) { image_rect.set_width((float)image.width() * ((float)image_rect.height() / (float)image.height())); } - if (layer.size_y.is_auto()) { + if (layer.size_y.is_length() && layer.size_y.length().is_auto()) { image_rect.set_height((float)image.height() * ((float)image_rect.width() / (float)image.width())); } }