LibWeb: Check both top and bottom of float position when looking for fit
We have to check that there's enough space at both the top and bottom of the float's margin box, otherwise we risk overlapping existing content.
This commit is contained in:
parent
82e730eba1
commit
389f47f6fe
Notes:
sideshowbarker
2024-07-17 18:23:22 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/389f47f6fe
2 changed files with 63 additions and 16 deletions
42
Base/res/html/misc/float-stress-2.html
Normal file
42
Base/res/html/misc/float-stress-2.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="js" lang="en-US">
|
||||
<head>
|
||||
<style>
|
||||
* {
|
||||
border: 0px solid black !important;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#page {
|
||||
background: cyan;
|
||||
padding-left: 50px;
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
#content_box {
|
||||
float: left;
|
||||
background: lime;
|
||||
width: 400px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.first {
|
||||
background: pink;
|
||||
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.second {
|
||||
background: orange;
|
||||
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
</head><body><div id="page"><div id="content_box"><article class="first">first</article><article class="second">second</article> </div></div></body></html>
|
|
@ -95,27 +95,32 @@ void LineBuilder::append_text_chunk(TextNode const& text_node, size_t offset_in_
|
|||
float LineBuilder::y_for_float_to_be_inserted_here(Box const& box)
|
||||
{
|
||||
auto const& box_state = m_layout_state.get(box);
|
||||
auto width = box_state.margin_box_width();
|
||||
auto const width = box_state.margin_box_width();
|
||||
auto const height = box_state.margin_box_height();
|
||||
|
||||
auto current_line_width = ensure_last_line_box().width();
|
||||
if (roundf(current_line_width + width) > m_available_width_for_current_line) {
|
||||
float candidate_y = m_current_y + m_context.containing_block().line_height();
|
||||
// FIXME: This is super dumb, we move 1px downwards per iteration and stop
|
||||
// when we find an Y value where we don't collide with other floats.
|
||||
while (true) {
|
||||
if (width > m_context.available_space_for_line(candidate_y)) {
|
||||
if (!m_context.any_floats_intrude_at_y(candidate_y)) {
|
||||
return candidate_y;
|
||||
}
|
||||
} else {
|
||||
float candidate_y = m_current_y;
|
||||
|
||||
float current_line_width = ensure_last_line_box().width();
|
||||
// If there's already inline content on the current line, check if the new float can fit
|
||||
// alongside the content. If not, place it on the next line.
|
||||
if (current_line_width > 0 && roundf(current_line_width + width) > m_available_width_for_current_line)
|
||||
candidate_y += m_context.containing_block().line_height();
|
||||
|
||||
// Then, look for the next Y position where we can fit the new float.
|
||||
// FIXME: This is super dumb, we move 1px downwards per iteration and stop
|
||||
// when we find an Y value where we don't collide with other floats.
|
||||
while (true) {
|
||||
auto space_at_y_top = m_context.available_space_for_line(candidate_y);
|
||||
auto space_at_y_bottom = m_context.available_space_for_line(candidate_y + height);
|
||||
if (width >= space_at_y_top || width >= space_at_y_bottom) {
|
||||
if (!m_context.any_floats_intrude_at_y(candidate_y) && !m_context.any_floats_intrude_at_y(candidate_y + height)) {
|
||||
return candidate_y;
|
||||
}
|
||||
candidate_y += 1;
|
||||
} else {
|
||||
return candidate_y;
|
||||
}
|
||||
|
||||
return m_current_y + m_context.containing_block().line_height();
|
||||
candidate_y += 1;
|
||||
}
|
||||
return m_current_y;
|
||||
}
|
||||
|
||||
bool LineBuilder::should_break(float next_item_width)
|
||||
|
|
Loading…
Add table
Reference in a new issue