mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:12:43 +00:00 
			
		
		
		
	LibWeb: Handle overlapping floating box and left margin
Allow the left margin of a box which creates a block formatting context to overlap with left floating boxes which are siblings in the document tree. Fixes #20233 and the comment layout on https://lobste.rs.
This commit is contained in:
		
							parent
							
								
									34c702e6e8
								
							
						
					
					
						commit
						6a17a30e2e
					
				
					 6 changed files with 100 additions and 2 deletions
				
			
		|  | @ -8,12 +8,16 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline | ||||||
|       BlockContainer <div.ab> at (108,8) content-size 684x17.46875 children: not-inline |       BlockContainer <div.ab> at (108,8) content-size 684x17.46875 children: not-inline | ||||||
|         BlockContainer <(anonymous)> at (108,8) content-size 684x0 children: inline |         BlockContainer <(anonymous)> at (108,8) content-size 684x0 children: inline | ||||||
|           TextNode <#text> |           TextNode <#text> | ||||||
|  |         BlockContainer <div> at (108,8) content-size 684x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|           BlockContainer <div.a> at (108,8) content-size 14.265625x17.46875 floating [BFC] children: inline |           BlockContainer <div.a> at (108,8) content-size 14.265625x17.46875 floating [BFC] children: inline | ||||||
|             line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 |             line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|               frag 0 from TextNode start: 0, length: 1, rect: [108,8 14.265625x17.46875] |               frag 0 from TextNode start: 0, length: 1, rect: [108,8 14.265625x17.46875] | ||||||
|                 "A" |                 "A" | ||||||
|             TextNode <#text> |             TextNode <#text> | ||||||
|           TextNode <#text> |           TextNode <#text> | ||||||
|  |         BlockContainer <(anonymous)> at (108,8) content-size 684x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|         BlockContainer <div.b> at (122.265625,8) content-size 669.734375x17.46875 [BFC] children: inline |         BlockContainer <div.b> at (122.265625,8) content-size 669.734375x17.46875 [BFC] children: inline | ||||||
|           line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 |           line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|             frag 0 from TextNode start: 0, length: 1, rect: [122.265625,8 9.34375x17.46875] |             frag 0 from TextNode start: 0, length: 1, rect: [122.265625,8 9.34375x17.46875] | ||||||
|  |  | ||||||
|  | @ -0,0 +1,47 @@ | ||||||
|  | Viewport <#document> at (0,0) content-size 800x600 children: not-inline | ||||||
|  |   BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline | ||||||
|  |     BlockContainer <body> at (8,8) content-size 784x34.9375 children: not-inline | ||||||
|  |       BlockContainer <div> at (8,8) content-size 784x34.9375 children: not-inline | ||||||
|  |         BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|  |         BlockContainer <div> at (8,8) content-size 784x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|  |           BlockContainer <div.a> at (8,8) content-size 57.0625x34.9375 floating [BFC] children: not-inline | ||||||
|  |             BlockContainer <(anonymous)> at (8,8) content-size 57.0625x0 children: inline | ||||||
|  |               TextNode <#text> | ||||||
|  |             BlockContainer <div.a4> at (8,8) content-size 57.0625x17.46875 children: inline | ||||||
|  |               line 0 width: 57.0625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|  |                 frag 0 from TextNode start: 0, length: 4, rect: [8,8 57.0625x17.46875] | ||||||
|  |                   "AAAA" | ||||||
|  |               TextNode <#text> | ||||||
|  |             BlockContainer <(anonymous)> at (8,25.46875) content-size 57.0625x0 children: inline | ||||||
|  |               TextNode <#text> | ||||||
|  |             BlockContainer <div> at (8,25.46875) content-size 57.0625x17.46875 children: inline | ||||||
|  |               line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|  |                 frag 0 from TextNode start: 0, length: 1, rect: [8,25.46875 14.265625x17.46875] | ||||||
|  |                   "A" | ||||||
|  |               TextNode <#text> | ||||||
|  |             BlockContainer <(anonymous)> at (8,42.9375) content-size 57.0625x0 children: inline | ||||||
|  |               TextNode <#text> | ||||||
|  |           TextNode <#text> | ||||||
|  |         BlockContainer <(anonymous)> at (8,8) content-size 784x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|  |         BlockContainer <div> at (108,8) content-size 684x34.9375 children: not-inline | ||||||
|  |           BlockContainer <(anonymous)> at (108,8) content-size 684x0 children: inline | ||||||
|  |             TextNode <#text> | ||||||
|  |           BlockContainer <div> at (108,8) content-size 684x17.46875 children: inline | ||||||
|  |             line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|  |               frag 0 from TextNode start: 0, length: 1, rect: [108,8 9.34375x17.46875] | ||||||
|  |                 "B" | ||||||
|  |             TextNode <#text> | ||||||
|  |           BlockContainer <(anonymous)> at (108,25.46875) content-size 684x0 children: inline | ||||||
|  |             TextNode <#text> | ||||||
|  |           BlockContainer <div.c> at (108,25.46875) content-size 684x17.46875 [BFC] children: inline | ||||||
|  |             line 0 width: 10.3125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 | ||||||
|  |               frag 0 from TextNode start: 0, length: 1, rect: [108,25.46875 10.3125x17.46875] | ||||||
|  |                 "C" | ||||||
|  |             TextNode <#text> | ||||||
|  |           BlockContainer <(anonymous)> at (108,42.9375) content-size 684x0 children: inline | ||||||
|  |             TextNode <#text> | ||||||
|  |         BlockContainer <(anonymous)> at (8,42.9375) content-size 784x0 children: inline | ||||||
|  |           TextNode <#text> | ||||||
|  | @ -20,7 +20,9 @@ | ||||||
| 
 | 
 | ||||||
| <body> | <body> | ||||||
|     <div class="ab"> |     <div class="ab"> | ||||||
|         <div class="a">A</div> |         <div> | ||||||
|  |             <div class="a">A</div> | ||||||
|  |         </div> | ||||||
|         <div class="b">B</div> |         <div class="b">B</div> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | <style> | ||||||
|  |     .a { | ||||||
|  |         float: left; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .a4 { | ||||||
|  |         display: block; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .c { | ||||||
|  |         overflow: hidden; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  | 
 | ||||||
|  | <div> | ||||||
|  |     <div> | ||||||
|  |         <div class="a"> | ||||||
|  |             <div class="a4">AAAA</div> | ||||||
|  |             <div>A</div> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <div style="margin-left: 100px"> | ||||||
|  |         <div>B</div> | ||||||
|  |         <div class="c">C</div> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
|  | @ -802,6 +802,18 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically | ||||||
|     box_state.set_content_offset(CSSPixelPoint { box_state.offset.x(), y }); |     box_state.set_content_offset(CSSPixelPoint { box_state.offset.x(), y }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Returns whether the given box has the given ancestor on the path to root, ignoring the anonymous blocks.
 | ||||||
|  | static bool box_has_ancestor_in_non_anonymous_containing_block_chain(Box const* box, Box const& ancestor, Box const& root) | ||||||
|  | { | ||||||
|  |     Box const* current_ancestor = box ? box->non_anonymous_containing_block() : &root; | ||||||
|  |     while (current_ancestor != &root) { | ||||||
|  |         if (current_ancestor == &ancestor) | ||||||
|  |             return true; | ||||||
|  |         current_ancestor = current_ancestor->non_anonymous_containing_block(); | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontally(Box const& child_box, AvailableSpace const& available_space) | void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontally(Box const& child_box, AvailableSpace const& available_space) | ||||||
| { | { | ||||||
|     auto& box_state = m_state.get_mutable(child_box); |     auto& box_state = m_state.get_mutable(child_box); | ||||||
|  | @ -814,7 +826,12 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontal | ||||||
|         auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(child_box, root()); |         auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(child_box, root()); | ||||||
|         auto space_and_containing_margin = space_used_and_containing_margin_for_floats(box_in_root_rect.y()); |         auto space_and_containing_margin = space_used_and_containing_margin_for_floats(box_in_root_rect.y()); | ||||||
|         available_width_within_containing_block -= space_and_containing_margin.left_used_space + space_and_containing_margin.right_used_space; |         available_width_within_containing_block -= space_and_containing_margin.left_used_space + space_and_containing_margin.right_used_space; | ||||||
|         x += space_and_containing_margin.left_used_space; |         auto const& containing_box_state = m_state.get(*child_box.containing_block()); | ||||||
|  |         if (box_has_ancestor_in_non_anonymous_containing_block_chain(space_and_containing_margin.matching_left_float_box, *child_box.non_anonymous_containing_block(), root())) | ||||||
|  |             x = space_and_containing_margin.left_used_space; | ||||||
|  |         else | ||||||
|  |             // If the floating box doesn't share a containing block with the child box, the child box margin should overlap with the width of the floating box.
 | ||||||
|  |             x = max(space_and_containing_margin.left_used_space - containing_box_state.margin_left, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (child_box.containing_block()->computed_values().text_align() == CSS::TextAlign::LibwebCenter) { |     if (child_box.containing_block()->computed_values().text_align() == CSS::TextAlign::LibwebCenter) { | ||||||
|  | @ -1056,6 +1073,7 @@ BlockFormattingContext::SpaceUsedAndContainingMarginForFloats BlockFormattingCon | ||||||
|                 + floating_box_state.content_width() |                 + floating_box_state.content_width() | ||||||
|                 + floating_box_state.margin_box_right(); |                 + floating_box_state.margin_box_right(); | ||||||
|             space_and_containing_margin.left_total_containing_margin = offset_from_containing_block_chain_margins_between_here_and_root; |             space_and_containing_margin.left_total_containing_margin = offset_from_containing_block_chain_margins_between_here_and_root; | ||||||
|  |             space_and_containing_margin.matching_left_float_box = floating_box.box.ptr(); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -121,6 +121,7 @@ protected: | ||||||
|         // Each block in the containing chain adds its own margin and we store the total here.
 |         // Each block in the containing chain adds its own margin and we store the total here.
 | ||||||
|         CSSPixels left_total_containing_margin; |         CSSPixels left_total_containing_margin; | ||||||
|         CSSPixels right_total_containing_margin; |         CSSPixels right_total_containing_margin; | ||||||
|  |         Box const* matching_left_float_box { nullptr }; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct ShrinkToFitResult { |     struct ShrinkToFitResult { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andi Gallo
						Andi Gallo