LibWeb: Use relative coordinates for available_space_for_line()

We were accidentally providing it with absolute Y-coordinates, messing
up stacked floating boxes that would otherwise intrude on each other.

Fixes #4160.
This commit is contained in:
Jelle Raaijmakers 2025-04-01 13:22:22 +02:00
parent b2ffef4659
commit b44d5a5d3e
3 changed files with 49 additions and 14 deletions

View file

@ -133,14 +133,12 @@ CSSPixels LineBuilder::y_for_float_to_be_inserted_here(Box const& box)
HashMap<CSSPixels, AvailableSize> available_space_cache;
for (;;) {
Optional<CSSPixels> highest_intersection_bottom;
auto candidate_block_top_in_root = box_in_root_rect.y() + candidate_block_offset;
auto candidate_block_bottom_in_root = candidate_block_top_in_root + height;
auto candidate_block_bottom = candidate_block_offset + height;
m_context.parent().for_each_floating_box([&](auto const& float_box) {
auto float_box_top = float_box.margin_box_rect_in_root_coordinate_space.top();
auto float_box_bottom = float_box.margin_box_rect_in_root_coordinate_space.bottom();
if (float_box_bottom <= candidate_block_top_in_root)
auto float_box_top = float_box.margin_box_rect_in_root_coordinate_space.top() - box_in_root_rect.y();
auto float_box_bottom = float_box.margin_box_rect_in_root_coordinate_space.bottom() - box_in_root_rect.y();
if (float_box_bottom <= candidate_block_offset)
return IterationDecision::Continue;
auto intersection_test = [&](auto y_coordinate, auto top, auto bottom) {
@ -149,16 +147,14 @@ CSSPixels LineBuilder::y_for_float_to_be_inserted_here(Box const& box)
auto available_space = available_space_cache.ensure(y_coordinate, [&]() {
return m_context.available_space_for_line(y_coordinate);
});
if (width > available_space) {
auto bottom_relative = float_box_bottom - box_in_root_rect.y();
highest_intersection_bottom = min(highest_intersection_bottom.value_or(bottom_relative), bottom_relative);
}
if (width > available_space)
highest_intersection_bottom = min(highest_intersection_bottom.value_or(float_box_bottom), float_box_bottom);
};
intersection_test(float_box_top, candidate_block_top_in_root, candidate_block_bottom_in_root);
intersection_test(float_box_bottom, candidate_block_top_in_root, candidate_block_bottom_in_root);
intersection_test(candidate_block_top_in_root, float_box_top, float_box_bottom);
intersection_test(candidate_block_bottom_in_root, float_box_top, float_box_bottom);
intersection_test(float_box_top, candidate_block_offset, candidate_block_bottom);
intersection_test(float_box_bottom, candidate_block_offset, candidate_block_bottom);
intersection_test(candidate_block_offset, float_box_top, float_box_bottom);
intersection_test(candidate_block_bottom, float_box_top, float_box_bottom);
return IterationDecision::Continue;
});

View file

@ -0,0 +1,18 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x158 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x50 children: not-inline
BlockContainer <div.a> at (8,8) content-size 784x50 children: not-inline
BlockContainer <(anonymous)> at (8,58) content-size 784x0 children: inline
TextNode <#text>
BlockContainer <div.b.bug> at (8,58) content-size 784x50 floating [BFC] children: not-inline
TextNode <#text>
BlockContainer <div.c.bug> at (8,108) content-size 784x50 floating [BFC] children: not-inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x158]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x50]
PaintableWithLines (BlockContainer<DIV>.a) [8,8 784x50]
PaintableWithLines (BlockContainer(anonymous)) [8,58 784x0]
PaintableWithLines (BlockContainer<DIV>.b.bug) [8,58 784x50]
PaintableWithLines (BlockContainer<DIV>.c.bug) [8,108 784x50]

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<style>
.a {
background: red;
height: 50px;
}
.b {
background: green;
}
.c {
background: blue;
}
.bug {
float: left;
height: 50px;
width: 100%;
}
</style>
<div class="a"></div>
<div class="b bug"></div>
<div class="c bug"></div>