mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:47:35 +00:00
LibWeb: Rewrite calculation of available space between floats
This code now works in terms of *intrusion* by left and right side floats into a given box whose insides we're trying to layout. Previously, it worked in terms of space occupied by floats in the root box of the BFC they participated in. That created a bunch of edge cases since the code asking about the information wasn't operating in root coordinate space, but in the coordinate space of some arbitrarily nested block descendant of the root. This finally allows horizontal margins in the containing block chain to affect floats and nested content correctly, and it also allows us to remove a bogus workaround in InlineFormattingContext.
This commit is contained in:
parent
9bd4add734
commit
bab6796099
8 changed files with 159 additions and 40 deletions
|
@ -125,9 +125,8 @@ void BlockFormattingContext::compute_width(Box const& box, AvailableSpace const&
|
|||
// sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3.
|
||||
// CSS2 does not define when a UA may put said element next to the float or by how much said element may
|
||||
// become narrower.
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(box, root(), m_state);
|
||||
auto space = space_used_by_floats(box_in_root_rect.y());
|
||||
auto remaining_width = available_space.width.to_px() - space.left - space.right;
|
||||
auto intrusion = intrusion_by_floats_into_box(box, 0);
|
||||
auto remaining_width = available_space.width.to_px() - intrusion.left - intrusion.right;
|
||||
remaining_available_space.width = AvailableSize::make_definite(remaining_width);
|
||||
}
|
||||
|
||||
|
@ -994,7 +993,13 @@ BlockFormattingContext::SpaceUsedByFloats BlockFormattingContext::space_used_by_
|
|||
// NOTE: The floating box is *not* in the final horizontal position yet, but the size and vertical position is valid.
|
||||
auto rect = margin_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state);
|
||||
if (rect.contains_vertically(y.value())) {
|
||||
space_used_by_floats.left = floating_box.offset_from_edge
|
||||
CSSPixels offset_from_containing_block_chain_margins_between_here_and_root = 0;
|
||||
for (auto const* containing_block = floating_box.box->containing_block(); containing_block && containing_block != &root(); containing_block = containing_block->containing_block()) {
|
||||
auto const& containing_block_state = m_state.get(*containing_block);
|
||||
offset_from_containing_block_chain_margins_between_here_and_root = max(offset_from_containing_block_chain_margins_between_here_and_root, containing_block_state.margin_box_left());
|
||||
}
|
||||
space_used_by_floats.left = offset_from_containing_block_chain_margins_between_here_and_root
|
||||
+ floating_box.offset_from_edge
|
||||
+ floating_box_state.content_width()
|
||||
+ floating_box_state.margin_box_right();
|
||||
break;
|
||||
|
@ -1007,7 +1012,13 @@ BlockFormattingContext::SpaceUsedByFloats BlockFormattingContext::space_used_by_
|
|||
// NOTE: The floating box is *not* in the final horizontal position yet, but the size and vertical position is valid.
|
||||
auto rect = margin_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state);
|
||||
if (rect.contains_vertically(y.value())) {
|
||||
space_used_by_floats.right = floating_box.offset_from_edge
|
||||
CSSPixels offset_from_containing_block_chain_margins_between_here_and_root = 0;
|
||||
for (auto const* containing_block = floating_box.box->containing_block(); containing_block && containing_block != &root(); containing_block = containing_block->containing_block()) {
|
||||
auto const& containing_block_state = m_state.get(*containing_block);
|
||||
offset_from_containing_block_chain_margins_between_here_and_root = max(offset_from_containing_block_chain_margins_between_here_and_root, containing_block_state.margin_box_right());
|
||||
}
|
||||
space_used_by_floats.right = offset_from_containing_block_chain_margins_between_here_and_root
|
||||
+ floating_box.offset_from_edge
|
||||
+ floating_box_state.margin_box_left();
|
||||
break;
|
||||
}
|
||||
|
@ -1016,6 +1027,25 @@ BlockFormattingContext::SpaceUsedByFloats BlockFormattingContext::space_used_by_
|
|||
return space_used_by_floats;
|
||||
}
|
||||
|
||||
FormattingContext::SpaceUsedByFloats BlockFormattingContext::intrusion_by_floats_into_box(Box const& box, CSSPixels y_in_box) const
|
||||
{
|
||||
// NOTE: Floats are relative to the BFC root box, not necessarily the containing block of this IFC.
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(box, root(), m_state);
|
||||
CSSPixels y_in_root = box_in_root_rect.y() + y_in_box;
|
||||
auto space_used_by_floats_in_root = space_used_by_floats(y_in_root);
|
||||
|
||||
auto left_intrusion = max(CSSPixels(0), space_used_by_floats_in_root.left - box_in_root_rect.x());
|
||||
|
||||
CSSPixels offset_from_containing_block_chain_margins_between_here_and_root = 0;
|
||||
for (auto const* containing_block = static_cast<Box const*>(&box); containing_block && containing_block != &root(); containing_block = containing_block->containing_block()) {
|
||||
auto const& containing_block_state = m_state.get(*containing_block);
|
||||
offset_from_containing_block_chain_margins_between_here_and_root = max(offset_from_containing_block_chain_margins_between_here_and_root, containing_block_state.margin_box_right());
|
||||
}
|
||||
auto right_intrusion = max(CSSPixels(0), space_used_by_floats_in_root.right - offset_from_containing_block_chain_margins_between_here_and_root);
|
||||
|
||||
return { left_intrusion, right_intrusion };
|
||||
}
|
||||
|
||||
CSSPixels BlockFormattingContext::greatest_child_width(Box const& box) const
|
||||
{
|
||||
// Similar to FormattingContext::greatest_child_width()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue