diff --git a/Base/res/html/misc/float-stress-2.html b/Base/res/html/misc/float-stress-2.html new file mode 100644 index 0000000000..4f4c5bea6d --- /dev/null +++ b/Base/res/html/misc/float-stress-2.html @@ -0,0 +1,42 @@ + + + + +
first
second
diff --git a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp index 9f11e914df..7e0efc8e1b 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -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)