diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index fd760c77ff..0c7ccf6780 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -76,6 +77,13 @@ struct ResolvedBackdropFilter { Vector filters; }; +struct ObjectPosition { + PositionEdge edge_x { PositionEdge::Left }; + CSS::LengthPercentage offset_x { Percentage(50) }; + PositionEdge edge_y { PositionEdge::Top }; + CSS::LengthPercentage offset_y { Percentage(50) }; +}; + class InitialValues { public: static AspectRatio aspect_ratio() { return AspectRatio { true, {} }; } @@ -154,6 +162,7 @@ public: static Vector> grid_template_areas() { return {}; } static CSS::Time transition_delay() { return CSS::Time::make_seconds(0); } static CSS::ObjectFit object_fit() { return CSS::ObjectFit::Fill; } + static CSS::ObjectPosition object_position() { return {}; } static Color outline_color() { return Color::Black; } static CSS::Length outline_offset() { return CSS::Length::make_px(0); } static CSS::OutlineStyle outline_style() { return CSS::OutlineStyle::None; } @@ -359,6 +368,7 @@ public: CSS::BorderCollapse border_collapse() const { return m_inherited.border_collapse; } Vector> const& grid_template_areas() const { return m_noninherited.grid_template_areas; } CSS::ObjectFit object_fit() const { return m_noninherited.object_fit; } + CSS::ObjectPosition object_position() const { return m_noninherited.object_position; } CSS::LengthBox const& inset() const { return m_noninherited.inset; } const CSS::LengthBox& margin() const { return m_noninherited.margin; } @@ -548,6 +558,7 @@ protected: CSS::Length outline_width { InitialValues::outline_width() }; CSS::TableLayout table_layout { InitialValues::table_layout() }; CSS::ObjectFit object_fit { InitialValues::object_fit() }; + CSS::ObjectPosition object_position { InitialValues::object_position() }; Optional mask; CSS::MaskType mask_type { InitialValues::mask_type() }; @@ -660,6 +671,7 @@ public: void set_table_layout(CSS::TableLayout value) { m_noninherited.table_layout = value; } void set_quotes(CSS::QuotesData value) { m_inherited.quotes = value; } void set_object_fit(CSS::ObjectFit value) { m_noninherited.object_fit = value; } + void set_object_position(CSS::ObjectPosition value) { m_noninherited.object_position = value; } void set_fill(SVGPaint value) { m_inherited.fill = value; } void set_stroke(SVGPaint value) { m_inherited.stroke = value; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index cff065d557..a64ca77e53 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -1026,10 +1026,24 @@ Optional StyleProperties::object_fit() const return value_id_to_object_fit(value->to_identifier()); } -CSS::PositionStyleValue const& StyleProperties::object_position() const +CSS::ObjectPosition StyleProperties::object_position() const { auto value = property(CSS::PropertyID::ObjectPosition); - return value->as_position(); + auto const& position = value->as_position(); + CSS::ObjectPosition object_position; + auto const& edge_x = position.edge_x(); + auto const& edge_y = position.edge_y(); + if (edge_x->is_edge()) { + auto const& edge = edge_x->as_edge(); + object_position.edge_x = edge.edge(); + object_position.offset_x = edge.offset(); + } + if (edge_y->is_edge()) { + auto const& edge = edge_y->as_edge(); + object_position.edge_y = edge.edge(); + object_position.offset_y = edge.offset(); + } + return object_position; } Optional StyleProperties::table_layout() const diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index 01798b8782..f6fee7d702 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -114,7 +114,7 @@ public: Vector> grid_template_areas() const; String grid_area() const; Optional object_fit() const; - CSS::PositionStyleValue const& object_position() const; + CSS::ObjectPosition object_position() const; Optional table_layout() const; static Vector transformations_for_style_value(StyleValue const& value); diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 5d7a57c4b5..4d638dfa01 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -833,6 +833,8 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) if (auto object_fit = computed_style.object_fit(); object_fit.has_value()) computed_values.set_object_fit(object_fit.value()); + computed_values.set_object_position(computed_style.object_position()); + propagate_style_to_anonymous_wrappers(); } diff --git a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp index d6fa0653dc..cff8897c9d 100644 --- a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -71,7 +71,6 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const auto image_int_rect = image_rect.to_type(); auto bitmap_rect = bitmap->rect(); auto scaling_mode = to_gfx_scaling_mode(computed_values().image_rendering(), bitmap_rect, image_int_rect); - auto& dom_element = verify_cast(*dom_node()); auto bitmap_aspect_ratio = (float)bitmap_rect.height() / bitmap_rect.width(); auto image_aspect_ratio = (float)image_rect.height().value() / image_rect.width().value(); @@ -121,37 +120,27 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const bitmap_intersect.set_x((bitmap_rect.width() - bitmap_intersect.width()) / 2); bitmap_intersect.set_y((bitmap_rect.height() - bitmap_intersect.height()) / 2); - CSS::PositionStyleValue const& object_position = dom_element.computed_css_values()->object_position(); + auto const& object_position = computed_values().object_position(); auto offset_x = 0; - auto const& horizontal = object_position.edge_x(); - if (horizontal->is_edge()) { - auto const& horizontal_edge = horizontal->as_edge(); - auto const& offset = horizontal_edge.offset(); - if (horizontal_edge.edge() == CSS::PositionEdge::Left) { - offset_x = offset.to_px(layout_node(), residual_horizontal).to_int(); - bitmap_intersect.set_x(0); - } else if (horizontal_edge.edge() == CSS::PositionEdge::Right) { - offset_x = residual_horizontal.to_int() - offset.to_px(layout_node(), residual_horizontal).to_int(); - } - if (image_int_rect.width() < scaled_bitmap_width) - bitmap_intersect.set_x(-(offset_x / scale_x)); + if (object_position.edge_x == CSS::PositionEdge::Left) { + offset_x = object_position.offset_x.to_px(layout_node(), residual_horizontal).to_int(); + bitmap_intersect.set_x(0); + } else if (object_position.edge_x == CSS::PositionEdge::Right) { + offset_x = residual_horizontal.to_int() - object_position.offset_x.to_px(layout_node(), residual_horizontal).to_int(); } + if (image_int_rect.width() < scaled_bitmap_width) + bitmap_intersect.set_x(-(offset_x / scale_x)); auto offset_y = 0; - auto const& vertical = object_position.edge_y(); - if (vertical->is_edge()) { - auto const& vertical_edge = vertical->as_edge(); - auto const& offset = vertical_edge.offset(); - if (vertical_edge.edge() == CSS::PositionEdge::Top) { - offset_y = offset.to_px(layout_node(), residual_vertical).to_int(); - bitmap_intersect.set_y(0); - } else if (vertical_edge.edge() == CSS::PositionEdge::Bottom) { - offset_y = residual_vertical.to_int() - offset.to_px(layout_node(), residual_vertical).to_int(); - } - if (image_int_rect.height() < scaled_bitmap_height) - bitmap_intersect.set_y(-(offset_y / scale_y)); + if (object_position.edge_y == CSS::PositionEdge::Top) { + offset_y = object_position.offset_y.to_px(layout_node(), residual_vertical).to_int(); + bitmap_intersect.set_y(0); + } else if (object_position.edge_y == CSS::PositionEdge::Bottom) { + offset_y = residual_vertical.to_int() - object_position.offset_y.to_px(layout_node(), residual_vertical).to_int(); } + if (image_int_rect.height() < scaled_bitmap_height) + bitmap_intersect.set_y(-(offset_y / scale_y)); Gfx::IntRect draw_rect = { image_int_rect.x() + offset_x,