diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 3f340c5a810..c2dbe4f8f82 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -1147,6 +1147,7 @@ void BlockFormattingContext::layout_floating_box(Box const& box, BlockContainer .margin_box_rect_in_root_coordinate_space = margin_box_rect_in_ancestor_coordinate_space(box_state, root()), })); side_data.current_boxes.append(*side_data.all_boxes.last()); + m_last_inserted_float = *side_data.all_boxes.last(); if (side == FloatSide::Left) { side_data.current_width = offset_from_edge + box_state.content_width() + box_state.margin_box_right(); diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Libraries/LibWeb/Layout/BlockFormattingContext.h index 7ba4077c805..d535bb2bf6f 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -74,6 +74,25 @@ public: void reset_margin_state() { m_margin_state.reset(); } + struct FloatingBox { + GC::Ref box; + + LayoutState::UsedValues& used_values; + + // Offset from left/right edge to the left content edge of `box`. + CSSPixels offset_from_edge { 0 }; + + // Top margin edge of `box`. + CSSPixels top_margin_edge { 0 }; + + // Bottom margin edge of `box`. + CSSPixels bottom_margin_edge { 0 }; + + CSSPixelRect margin_box_rect_in_root_coordinate_space; + }; + + Optional last_inserted_float() { return m_last_inserted_float; } + private: CSSPixels compute_auto_height_for_block_level_element(Box const&, AvailableSpace const&); @@ -99,23 +118,6 @@ private: Right, }; - struct FloatingBox { - GC::Ref box; - - LayoutState::UsedValues& used_values; - - // Offset from left/right edge to the left content edge of `box`. - CSSPixels offset_from_edge { 0 }; - - // Top margin edge of `box`. - CSSPixels top_margin_edge { 0 }; - - // Bottom margin edge of `box`. - CSSPixels bottom_margin_edge { 0 }; - - CSSPixelRect margin_box_rect_in_root_coordinate_space; - }; - struct FloatSideData { // Floating boxes currently accumulating on this side. Vector current_boxes; @@ -189,6 +191,7 @@ private: FloatSideData m_left_floats; FloatSideData m_right_floats; + Optional m_last_inserted_float; bool m_was_notified_after_parent_dimensioned_my_root_box { false }; }; diff --git a/Libraries/LibWeb/Layout/LineBuilder.cpp b/Libraries/LibWeb/Layout/LineBuilder.cpp index a02f516e07a..59d5ed72a02 100644 --- a/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -129,6 +129,14 @@ CSSPixels LineBuilder::y_for_float_to_be_inserted_here(Box const& box) // Then, look for the next Y position where we can fit the new float. auto box_in_root_rect = m_context.parent().content_box_rect_in_ancestor_coordinate_space(box_state, m_context.parent().root()); + // New floats will always be placed vertically at or below the lowest float. + // This applies to all floats, so the last inserted float will always be the lowest. + auto last_float = m_context.parent().last_inserted_float(); + if (last_float.has_value()) { + auto float_box_top = last_float->margin_box_rect_in_root_coordinate_space.top() - box_in_root_rect.y(); + candidate_block_offset = max(candidate_block_offset, float_box_top); + } + HashMap available_space_cache; for (;;) { Optional highest_intersection_bottom; diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt new file mode 100644 index 00000000000..cc391628c45 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt @@ -0,0 +1,33 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x168 [BFC] children: not-inline + BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline + TextNode <#text> + BlockContainer at (8,8) content-size 784x152 children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline + TextNode <#text> + BlockContainer at (9,9) content-size 100x150 children: inline + frag 0 from TextNode start: 1, length: 11, rect: [9,9 99.109375x18] baseline: 13.796875 + "abc abc abc" + frag 1 from TextNode start: 13, length: 11, rect: [9,27 99.109375x18] baseline: 13.796875 + "abc abc abc" + TextNode <#text> + BlockContainer at (9,45) content-size 80x50 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer at (9,95) content-size 40x50 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer at (49,95) content-size 20x50 floating [BFC] children: not-inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,160) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x168] + PaintableWithLines (BlockContainer(anonymous)) [0,0 800x0] + PaintableWithLines (BlockContainer) [8,8 784x152] + PaintableWithLines (BlockContainer(anonymous)) [8,8 784x0] + PaintableWithLines (BlockContainer
.container) [8,8 102x152] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.left.w80.red) [9,45 80x50] + PaintableWithLines (BlockContainer
.left.w40.yellow) [9,95 40x50] + PaintableWithLines (BlockContainer
.left.w20.blue) [49,95 20x50] + PaintableWithLines (BlockContainer(anonymous)) [8,160 784x0] diff --git a/Tests/LibWeb/Layout/input/block-and-inline/float-under-if-would-fit.html b/Tests/LibWeb/Layout/input/block-and-inline/float-under-if-would-fit.html new file mode 100644 index 00000000000..ea36ab652fc --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/float-under-if-would-fit.html @@ -0,0 +1,32 @@ + + + + + +
+ abc abc abc + abc abc abc +
+
+
+
+