From 99df80f81eb80df35742015200269e97e0378f95 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Fri, 4 Apr 2025 11:28:03 +0200 Subject: [PATCH] LibWeb: Only apply box offset if the box is not already the ancestor When determining the content/margin box rects within their ancestor's coordinate space, we were returning early if the passed in values already belonged to the requested ancestor. Unfortunately, we had already applied the used values' offset to the rect, which is the offset to the ancestor's ancestor. This simplifies the logic to always apply the rect offset after checking if we've reached the ancestor. Fixes determining float intrusions inside block elements with `margin: auto` set. Fixes #4083. --- Libraries/LibWeb/Layout/FormattingContext.cpp | 28 +++++++++---------- Libraries/LibWeb/Layout/FormattingContext.h | 1 - Libraries/LibWeb/Layout/LayoutState.h | 2 ++ .../float-inside-margin-auto-container.txt | 19 +++++++++++++ .../float-inside-margin-auto-container.html | 23 +++++++++++++++ 5 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index 4714cf39093..9424150d6a6 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1182,10 +1182,9 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el CSSPixelRect FormattingContext::content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const { - auto rect = content_box_rect(box); - if (&box == &ancestor_box) - return rect; - for (auto const* current = box.static_position_containing_block(); current; current = current->static_position_containing_block()) { + auto box_used_values = m_state.get(box); + CSSPixelRect rect = { { 0, 0 }, box_used_values.content_size() }; + for (auto const* current = &box; current; current = current->static_position_containing_block()) { if (current == &ancestor_box) return rect; auto const& current_state = m_state.get(*current); @@ -1761,7 +1760,7 @@ bool FormattingContext::can_skip_is_anonymous_text_run(Box& box) CSSPixelRect FormattingContext::absolute_content_rect(Box const& box) const { auto const& box_state = m_state.get(box); - CSSPixelRect rect { box_state.offset, { box_state.content_width(), box_state.content_height() } }; + CSSPixelRect rect { box_state.offset, box_state.content_size() }; for (auto* block = box_state.containing_block_used_values(); block; block = block->containing_block_used_values()) rect.translate_by(block->offset); return rect; @@ -1825,10 +1824,13 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const return box_state.margin_box_height(); } -CSSPixelRect FormattingContext::margin_box_rect(LayoutState::UsedValues const& used_values) const +[[nodiscard]] static CSSPixelRect margin_box_rect(LayoutState::UsedValues const& used_values) { return { - used_values.offset.translated(-used_values.margin_box_left(), -used_values.margin_box_top()), + { + -used_values.margin_box_left(), + -used_values.margin_box_top(), + }, { used_values.margin_box_left() + used_values.content_width() + used_values.margin_box_right(), used_values.margin_box_top() + used_values.content_height() + used_values.margin_box_bottom(), @@ -1843,15 +1845,13 @@ CSSPixelRect FormattingContext::content_box_rect(Box const& box) const CSSPixelRect FormattingContext::content_box_rect(LayoutState::UsedValues const& used_values) const { - return CSSPixelRect { used_values.offset, { used_values.content_width(), used_values.content_height() } }; + return CSSPixelRect { used_values.offset, used_values.content_size() }; } CSSPixelRect FormattingContext::content_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const& used_values, Box const& ancestor_box) const { - auto rect = content_box_rect(used_values); - if (&used_values.node() == &ancestor_box) - return rect; - for (auto const* current = used_values.containing_block_used_values(); current; current = current->containing_block_used_values()) { + CSSPixelRect rect = { { 0, 0 }, used_values.content_size() }; + for (auto const* current = &used_values; current; current = current->containing_block_used_values()) { if (¤t->node() == &ancestor_box) return rect; rect.translate_by(current->offset); @@ -1863,9 +1863,7 @@ CSSPixelRect FormattingContext::content_box_rect_in_ancestor_coordinate_space(La CSSPixelRect FormattingContext::margin_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const& used_values, Box const& ancestor_box) const { auto rect = margin_box_rect(used_values); - if (&used_values.node() == &ancestor_box) - return rect; - for (auto const* current = used_values.containing_block_used_values(); current; current = current->containing_block_used_values()) { + for (auto const* current = &used_values; current; current = current->containing_block_used_values()) { if (¤t->node() == &ancestor_box) return rect; rect.translate_by(current->offset); diff --git a/Libraries/LibWeb/Layout/FormattingContext.h b/Libraries/LibWeb/Layout/FormattingContext.h index d01e35e46fb..d4b3fbd5dee 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Libraries/LibWeb/Layout/FormattingContext.h @@ -82,7 +82,6 @@ public: [[nodiscard]] CSSPixelRect absolute_content_rect(Box const&) const; [[nodiscard]] CSSPixelRect margin_box_rect_in_ancestor_coordinate_space(Box const&, Box const& ancestor_box) const; - [[nodiscard]] CSSPixelRect margin_box_rect(LayoutState::UsedValues const&) const; [[nodiscard]] CSSPixelRect margin_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const&, Box const& ancestor_box) const; [[nodiscard]] CSSPixelRect content_box_rect(Box const&) const; [[nodiscard]] CSSPixelRect content_box_rect(LayoutState::UsedValues const&) const; diff --git a/Libraries/LibWeb/Layout/LayoutState.h b/Libraries/LibWeb/Layout/LayoutState.h index c6574939c49..a3b9882889a 100644 --- a/Libraries/LibWeb/Layout/LayoutState.h +++ b/Libraries/LibWeb/Layout/LayoutState.h @@ -67,6 +67,8 @@ struct LayoutState { void set_content_width(CSSPixels); void set_content_height(CSSPixels); + CSSPixelSize content_size() const { return { content_width(), content_height() }; } + void set_indefinite_content_width(); void set_indefinite_content_height(); diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt new file mode 100644 index 00000000000..02c07759bc5 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt @@ -0,0 +1,19 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x316 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x300 children: not-inline + BlockContainer at (300,8) content-size 200x300 [BFC] children: inline + TextNode <#text> + BlockContainer at (300,8) content-size 150x150 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer at (300,158) content-size 150x150 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,308) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x316] + PaintableWithLines (BlockContainer) [8,8 784x300] + PaintableWithLines (BlockContainer
.a) [300,8 200x300] + PaintableWithLines (BlockContainer
.b.g) [300,8 150x150] + PaintableWithLines (BlockContainer
.b.r) [300,158 150x150] + PaintableWithLines (BlockContainer(anonymous)) [8,308 784x0] diff --git a/Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html b/Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html new file mode 100644 index 00000000000..ba9a7de42cb --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html @@ -0,0 +1,23 @@ + + +
+
+
+