From 514fa837086c08b118e1d6b9a8a95dbc47b330cc Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 7 Sep 2022 13:29:58 +0200 Subject: [PATCH] LibWeb: Improve `float: right` behavior - Use the border box of the floated element when testing if something needs to flow around it. - Take the floated element's containing block size into account (instead of the BFC root) when calculating available space on a line where a right-side float intrudes. --- Base/res/html/misc/float-around-things.html | 29 +++++++++++++++++++ .../LibWeb/Layout/BlockFormattingContext.cpp | 8 ++--- .../LibWeb/Layout/InlineFormattingContext.cpp | 9 +++--- .../Libraries/LibWeb/Layout/LayoutState.cpp | 25 ++++++++++++++++ .../Libraries/LibWeb/Layout/LayoutState.h | 2 ++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 Base/res/html/misc/float-around-things.html diff --git a/Base/res/html/misc/float-around-things.html b/Base/res/html/misc/float-around-things.html new file mode 100644 index 0000000000..4901e4229f --- /dev/null +++ b/Base/res/html/misc/float-around-things.html @@ -0,0 +1,29 @@ + +
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin convallis sagittis velit ut suscipit. Maecenas sit amet maximus nunc. Integer a sem odio. Nunc cursus sollicitudin mauris, sed malesuada ipsum. Nulla ac euismod libero, ac gravida arcu. Phasellus convallis ornare metus, a vulputate dui rhoncus in. Cras mattis arcu vel nibh ultrices suscipit lobortis id libero. + +
+Integer in rhoncus sem, sit amet pellentesque sapien. Donec eu velit aliquam, pharetra dui ut, tempor ante. Duis vitae metus ac mauris porta aliquam. Vestibulum vestibulum dignissim ligula ac varius. Fusce condimentum pellentesque neque, at finibus neque suscipit non. Suspendisse arcu urna, condimentum eget massa et, ornare convallis metus. Nunc malesuada fermentum diam. Ut rutrum dignissim eros, quis sollicitudin elit interdum vel. Vivamus tortor diam, tristique vitae mauris vitae, mollis pellentesque sapien. Cras pellentesque finibus lacinia. Aliquam at leo dapibus, consectetur leo id, ultrices augue. Praesent vitae magna metus. Aliquam condimentum urna eu rhoncus efficitur. Fusce elementum diam eget tincidunt bibendum. + +Donec vel tellus eu mi hendrerit sagittis ac interdum purus. Etiam a sodales lacus. Maecenas vehicula diam vitae elit convallis, quis sagittis metus accumsan. Mauris lacus risus, dictum vitae fermentum sit amet, finibus nec tellus. Nunc eros tortor, rhoncus et eros eget, finibus aliquet dui. Sed venenatis, sem quis mollis pharetra, elit ipsum dignissim felis, id feugiat arcu metus vitae eros. Curabitur ac porta odio. Vivamus placerat sodales maximus. Praesent tincidunt, urna sit amet dignissim luctus, erat erat ultricies quam, a maximus massa metus vehicula diam. Aenean pharetra augue massa, in luctus neque interdum quis. Sed mattis magna egestas semper elementum. Morbi vitae velit eu nunc fringilla aliquam sed at diam. Cras vulputate vel magna id scelerisque. Praesent condimentum vehicula ipsum, sit amet consectetur tortor volutpat at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index da7e9ad96e..0513c42f80 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -626,7 +626,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer offset_from_edge = box_state.content_width() + box_state.margin_box_right(); }; - auto box_in_root_rect = margin_box_rect_in_ancestor_coordinate_space(box, root(), m_state); + auto box_in_root_rect = border_box_rect_in_ancestor_coordinate_space(box, root(), m_state); float y_in_root = box_in_root_rect.y(); float y = box_state.offset.y(); @@ -649,7 +649,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer } if (fits_on_line) { - auto const previous_rect = margin_box_rect_in_ancestor_coordinate_space(previous_box.box, root(), m_state); + auto const previous_rect = border_box_rect_in_ancestor_coordinate_space(previous_box.box, root(), m_state); if (previous_rect.contains_vertically(y_in_root + side_data.y_offset)) { // This box touches another already floating box. Stack after others. offset_from_edge = wanted_offset_from_edge; @@ -747,7 +747,7 @@ BlockFormattingContext::SpaceUsedByFloats BlockFormattingContext::space_used_by_ for (auto const& floating_box : m_left_floats.current_boxes.in_reverse()) { auto const& floating_box_state = m_state.get(floating_box.box); // NOTE: The floating box is *not* in the final horizontal position yet, but the size and vertical position is valid. - auto rect = margin_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state); + auto rect = border_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state); if (rect.contains_vertically(y)) { space_used_by_floats.left = floating_box.offset_from_edge + floating_box_state.content_width() @@ -759,7 +759,7 @@ BlockFormattingContext::SpaceUsedByFloats BlockFormattingContext::space_used_by_ for (auto const& floating_box : m_right_floats.current_boxes.in_reverse()) { auto const& floating_box_state = m_state.get(floating_box.box); // NOTE: The floating box is *not* in the final horizontal position yet, but the size and vertical position is valid. - auto rect = margin_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state); + auto rect = border_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state); if (rect.contains_vertically(y)) { space_used_by_floats.right = floating_box.offset_from_edge + floating_box_state.margin_box_left(); diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index bb4c67e4a9..379425c3e9 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -52,7 +52,7 @@ BlockFormattingContext const& InlineFormattingContext::parent() const float InlineFormattingContext::leftmost_x_offset_at(float y) const { // NOTE: Floats are relative to the BFC root box, not necessarily the containing block of this IFC. - auto box_in_root_rect = margin_box_rect_in_ancestor_coordinate_space(containing_block(), parent().root(), m_state); + auto box_in_root_rect = border_box_rect_in_ancestor_coordinate_space(containing_block(), parent().root(), m_state); float y_in_root = box_in_root_rect.y() + y; auto space = parent().space_used_by_floats(y_in_root); float containing_block_x = m_containing_block_state.offset.x(); @@ -67,14 +67,13 @@ float InlineFormattingContext::available_space_for_line(float y) const return INFINITY; // NOTE: Floats are relative to the BFC root box, not necessarily the containing block of this IFC. - auto box_in_root_rect = margin_box_rect_in_ancestor_coordinate_space(containing_block(), parent().root(), m_state); + auto& root_block = parent().root(); + auto box_in_root_rect = border_box_rect_in_ancestor_coordinate_space(containing_block(), root_block, m_state); float y_in_root = box_in_root_rect.y() + y; auto space = parent().space_used_by_floats(y_in_root); - auto const& root_block_state = m_state.get(parent().root()); - space.left = max(space.left, m_containing_block_state.offset.x()) - m_containing_block_state.offset.x(); - space.right = min(root_block_state.content_width() - space.right, m_containing_block_state.offset.x() + m_effective_containing_block_width); + space.right = min(m_containing_block_state.content_width() - space.right, m_containing_block_state.offset.x() + m_effective_containing_block_width); return space.right - space.left; } diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index 5535070023..9d8aeae629 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -107,6 +107,31 @@ Gfx::FloatRect margin_box_rect(Box const& box, LayoutState const& state) return rect; } +Gfx::FloatRect border_box_rect(Box const& box, LayoutState const& state) +{ + auto const& box_state = state.get(box); + auto rect = Gfx::FloatRect { box_state.offset, { box_state.content_width(), box_state.content_height() } }; + rect.set_x(rect.x() - box_state.border_box_left()); + rect.set_width(rect.width() + box_state.border_box_left() + box_state.border_box_right()); + rect.set_y(rect.y() - box_state.border_box_top()); + rect.set_height(rect.height() + box_state.border_box_top() + box_state.border_box_bottom()); + return rect; +} + +Gfx::FloatRect border_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const& state) +{ + auto rect = border_box_rect(box, state); + for (auto const* current = box.parent(); current; current = current->parent()) { + if (current == &ancestor_box) + break; + if (is(*current)) { + auto const& current_state = state.get(static_cast(*current)); + rect.translate_by(current_state.offset); + } + } + return rect; +} + Gfx::FloatRect margin_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const& state) { auto rect = margin_box_rect(box, state); diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.h b/Userland/Libraries/LibWeb/Layout/LayoutState.h index b315068348..ddb4238499 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.h +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.h @@ -149,5 +149,7 @@ struct LayoutState { Gfx::FloatRect absolute_content_rect(Box const&, LayoutState const&); Gfx::FloatRect margin_box_rect(Box const&, LayoutState const&); Gfx::FloatRect margin_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const&); +Gfx::FloatRect border_box_rect(Box const&, LayoutState const&); +Gfx::FloatRect border_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const&); }