1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:57:43 +00:00

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.
This commit is contained in:
Andreas Kling 2022-09-07 13:29:58 +02:00
parent a42506c8b9
commit 514fa83708
5 changed files with 64 additions and 9 deletions

View file

@ -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();

View file

@ -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;
}

View file

@ -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<Box>(*current)) {
auto const& current_state = state.get(static_cast<Box const&>(*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);

View file

@ -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&);
}