mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 01:57:45 +00:00
LibWeb: Relax "all children must be either inline or block" invariant
This was implemented too rigidly, which made it impossible to place floats correctly when they occurred in inline flow. The new invariant is "all in-flow children must be either inline or block". Out-of-flow children like floating and absolutely positioned boxes are ignored when deciding when to generate anonymous boxes.
This commit is contained in:
parent
74927fd218
commit
fa64a7f6cc
1 changed files with 33 additions and 4 deletions
|
@ -26,8 +26,32 @@ namespace Web::Layout {
|
|||
|
||||
TreeBuilder::TreeBuilder() = default;
|
||||
|
||||
// The insertion_parent_for_*() functions maintain the invariant that block-level boxes must have either
|
||||
// only block-level children or only inline-level children.
|
||||
static bool has_inline_or_in_flow_block_children(Layout::Node const& layout_node)
|
||||
{
|
||||
for (auto const* child = layout_node.first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_inline())
|
||||
return true;
|
||||
if (!child->is_floating() && !child->is_absolutely_positioned())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool has_in_flow_block_children(Layout::Node const& layout_node)
|
||||
{
|
||||
if (layout_node.children_are_inline())
|
||||
return false;
|
||||
for (auto const* child = layout_node.first_child(); child; child = child->next_sibling()) {
|
||||
if (child->is_inline())
|
||||
continue;
|
||||
if (!child->is_floating() && !child->is_absolutely_positioned())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The insertion_parent_for_*() functions maintain the invariant that the in-flow children of
|
||||
// block-level boxes must be either all block-level or all inline-level.
|
||||
|
||||
static Layout::Node& insertion_parent_for_inline_node(Layout::NodeWithStyle& layout_parent)
|
||||
{
|
||||
|
@ -38,7 +62,7 @@ static Layout::Node& insertion_parent_for_inline_node(Layout::NodeWithStyle& lay
|
|||
layout_parent.append_child(layout_parent.create_anonymous_wrapper());
|
||||
}
|
||||
|
||||
if (!layout_parent.has_children() || layout_parent.children_are_inline())
|
||||
if (!has_in_flow_block_children(layout_parent) || layout_parent.children_are_inline())
|
||||
return layout_parent;
|
||||
|
||||
// Parent has block-level children, insert into an anonymous wrapper block (and create it first if needed)
|
||||
|
@ -50,7 +74,7 @@ static Layout::Node& insertion_parent_for_inline_node(Layout::NodeWithStyle& lay
|
|||
|
||||
static Layout::Node& insertion_parent_for_block_node(Layout::Node& layout_parent, Layout::Node& layout_node)
|
||||
{
|
||||
if (!layout_parent.has_children()) {
|
||||
if (!has_inline_or_in_flow_block_children(layout_parent)) {
|
||||
// Parent block has no children, insert this block into parent.
|
||||
return layout_parent;
|
||||
}
|
||||
|
@ -60,6 +84,11 @@ static Layout::Node& insertion_parent_for_block_node(Layout::Node& layout_parent
|
|||
return layout_parent;
|
||||
}
|
||||
|
||||
if (layout_node.is_floating() || layout_node.is_absolutely_positioned()) {
|
||||
// Block is out-of-flow, it can have inline siblings if necessary.
|
||||
return layout_parent;
|
||||
}
|
||||
|
||||
// Parent block has inline-level children (our siblings).
|
||||
// First move these siblings into an anonymous wrapper block.
|
||||
NonnullRefPtrVector<Layout::Node> children;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue