From 85e28a29f01824581a85a2a8ec9da046a6b76fb2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Wed, 26 Mar 2025 11:55:39 +0000 Subject: [PATCH] LibWeb: Replace 1px iteration in y_for_float_to_be_inserted_here() ...with a loop through already inserted floating boxes that probes potential insertion points on their edges. Makes www.nyan.cat go faster. --- .../LibWeb/Layout/BlockFormattingContext.h | 13 +++++++++++++ Libraries/LibWeb/Layout/LineBuilder.cpp | 19 ++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Libraries/LibWeb/Layout/BlockFormattingContext.h index 3488bad179a..7ba4077c805 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -40,6 +40,19 @@ public: void resolve_used_height_if_not_treated_as_auto(Box const&, AvailableSpace const&); void resolve_used_height_if_treated_as_auto(Box const&, AvailableSpace const&, FormattingContext const* box_formatting_context = nullptr); + template + void for_each_floating_box(Callback callback) + { + for (auto const& floating_box : m_left_floats.all_boxes) { + if (callback(*floating_box) == IterationDecision::Break) + return; + } + for (auto const& floating_box : m_right_floats.all_boxes) { + if (callback(*floating_box) == IterationDecision::Break) + return; + } + } + SpaceUsedAndContainingMarginForFloats space_used_and_containing_margin_for_floats(CSSPixels y) const; [[nodiscard]] SpaceUsedByFloats intrusion_by_floats_into_box(Box const&, CSSPixels y_in_box) const; [[nodiscard]] SpaceUsedByFloats intrusion_by_floats_into_box(LayoutState::UsedValues const&, CSSPixels y_in_box) const; diff --git a/Libraries/LibWeb/Layout/LineBuilder.cpp b/Libraries/LibWeb/Layout/LineBuilder.cpp index 58a096e57c6..4268931db31 100644 --- a/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -124,20 +124,25 @@ CSSPixels LineBuilder::y_for_float_to_be_inserted_here(Box const& box) candidate_block_offset += current_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 box_in_root_rect = m_context.parent().content_box_rect_in_ancestor_coordinate_space(box_state, m_context.parent().root()); + m_context.parent().for_each_floating_box([&](auto const& float_box) { + auto candidate_block_offset_in_root = box_in_root_rect.y() + candidate_block_offset; + if (float_box.margin_box_rect_in_root_coordinate_space.bottom() < candidate_block_offset_in_root) + return IterationDecision::Continue; auto space_at_y_top = m_context.available_space_for_line(candidate_block_offset); auto space_at_y_bottom = m_context.available_space_for_line(candidate_block_offset + height); if (width > space_at_y_top || width > space_at_y_bottom) { if (!m_context.any_floats_intrude_at_block_offset(candidate_block_offset) && !m_context.any_floats_intrude_at_block_offset(candidate_block_offset + height)) { - return candidate_block_offset; + return IterationDecision::Break; } } else { - return candidate_block_offset; + return IterationDecision::Break; } - candidate_block_offset += 1; - } + // candidate_block_offset needs to stay relative to the current box + candidate_block_offset = float_box.margin_box_rect_in_root_coordinate_space.bottom() - box_in_root_rect.y(); + return IterationDecision::Continue; + }); + return candidate_block_offset; } bool LineBuilder::should_break(CSSPixels next_item_width)