diff options
author | Andi Gallo <andigallo@proton.me> | 2023-05-24 06:57:38 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-26 14:53:53 +0200 |
commit | 5cec5171538a003d2880d412d3bcae79e7bd88ca (patch) | |
tree | 47966cc9f36532d01e79e41c445270a8da695a0a | |
parent | 706a20c4d4acbfc9eb9d980969f29e4b1c7a4d1c (diff) | |
download | serenity-5cec5171538a003d2880d412d3bcae79e7bd88ca.zip |
LibWeb: Get reference height from closest non-anonymous ancestor
Ignore anonymous block boxes when resolving percentage weights that
would refer to them, per the CSS 2 visual formatting model
specification. This fixes the case when we create an anonymous block
between an image which uses a percentage height relative to a parent
which specifies a definite height.
Fixes #19052.
5 files changed, 79 insertions, 3 deletions
diff --git a/Tests/LibWeb/Layout/expected/resolve-height-of-containing-block.txt b/Tests/LibWeb/Layout/expected/resolve-height-of-containing-block.txt new file mode 100644 index 0000000000..d8d1dedc68 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/resolve-height-of-containing-block.txt @@ -0,0 +1,26 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer <html> at (0,0) content-size 800x824 [BFC] children: not-inline + BlockContainer <(anonymous)> at (0,0) content-size 800x0 children: inline + TextNode <#text> + BlockContainer <body> at (8,16) content-size 784x800 children: not-inline + BlockContainer <(anonymous)> at (8,16) content-size 784x0 children: inline + TextNode <#text> + BlockContainer <div.foo> at (8,16) content-size 1280x800 children: not-inline + BlockContainer <(anonymous)> at (8,16) content-size 1280x0 children: inline + TextNode <#text> + BlockContainer <div> at (8,16) content-size 1280x600 children: not-inline + BlockContainer <(anonymous)> at (8,16) content-size 1280x0 children: inline + TextNode <#text> + ImageBox <img> at (88,16) content-size 1200x600 floating children: not-inline + TextNode <#text> + BlockContainer <p> at (8,16) content-size 1280x17.46875 children: inline + line 0 width: 37.21875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 4, rect: [8,16 37.21875x17.46875] + "Test" + TextNode <#text> + BlockContainer <(anonymous)> at (8,49.46875) content-size 1280x0 children: inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,616) content-size 1280x0 children: inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,816) content-size 784x0 children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/resolve-height-of-containing-block.html b/Tests/LibWeb/Layout/input/resolve-height-of-containing-block.html new file mode 100644 index 0000000000..b8aa340683 --- /dev/null +++ b/Tests/LibWeb/Layout/input/resolve-height-of-containing-block.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> + +<head> + <style> + .foo { + width: 1280px; + height: 800px; + } + + .foo div { + height: 600px; + } + + .foo div img { + max-height: 100%; + float: right; + } + </style> +</head> + +<body> + + <div class="foo"> + <div> + <img + src="data:image/png;base64,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rDWw4f9TYqar07wWc60Y6bIy+eVlRsvz8zgci/lkzY+BMyxAsAAEC0CwAMECECwAwQK2E3tYgDMsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIQLECwAAQLQLAAwQIQLADBAgQLQLAAwfInAAQLQLAAwQIQLADBAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIQLECwAAQLQLAAwQIQLADBAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsQLAABAtAsADBAhAsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIQLECwAAQLQLAAwQIQLECwAAQLQLAAwQIQLADBAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsAMECBAtAsAAECxAsAMECECxAsAAEC0CwAMECECxAsAAEC0CwAMECECwAwQIEC0CwAAQLECwAwQIQLECwAAQLQLAAwQIQLADBAgQLQLAABAsQLADBAhAsQLAABAtAsADBAhAsQLAABAtAsADBAhAsAMECBAtAsAAEC2i8fwDFkO6lWFprKQAAAABJRU5ErkJggg=="> + <p>Test</p> + </div> + </div> + +</body> + +</html>
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 5682585212..f05884f469 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -262,7 +262,7 @@ static CSSPixelSize solve_replaced_size_constraint(LayoutState const& state, CSS { // 10.4 Minimum and maximum widths: 'min-width' and 'max-width' - auto const& containing_block = *box.containing_block(); + auto const& containing_block = *box.non_anyonymous_containing_block(); auto const& containing_block_state = state.get(containing_block); auto width_of_containing_block = containing_block_state.content_width(); auto height_of_containing_block = containing_block_state.content_height(); @@ -509,7 +509,7 @@ CSSPixels FormattingContext::compute_height_for_replaced_element(LayoutState con // 10.6.6 Floating replaced elements // 10.6.10 'inline-block' replaced elements in normal flow - auto height_of_containing_block = state.get(*box.containing_block()).content_height(); + auto height_of_containing_block = state.get(*box.non_anyonymous_containing_block()).content_height(); auto computed_width = should_treat_width_as_auto(box, available_space) ? CSS::Size::make_auto() : box.computed_values().width(); auto computed_height = should_treat_height_as_auto(box, available_space) ? CSS::Size::make_auto() : box.computed_values().height(); @@ -1358,7 +1358,7 @@ CSS::Length FormattingContext::calculate_inner_width(Layout::Box const& box, Ava CSS::Length FormattingContext::calculate_inner_height(Layout::Box const& box, AvailableSize const&, CSS::Size const& height) const { - auto height_of_containing_block = m_state.get(*box.containing_block()).content_height(); + auto height_of_containing_block = m_state.get(*box.non_anyonymous_containing_block()).content_height(); auto height_of_containing_block_as_length_for_resolve = CSS::Length::make_px(height_of_containing_block); if (height.is_auto()) { return height.resolved(box, height_of_containing_block_as_length_for_resolve); diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 60d4c00485..956e56120f 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -114,6 +114,17 @@ Box const* Node::containing_block() const return nearest_ancestor_capable_of_forming_a_containing_block(*this); } +Box const* Node::non_anyonymous_containing_block() const +{ + auto nearest_ancestor_box = containing_block(); + VERIFY(nearest_ancestor_box); + while (nearest_ancestor_box->is_anonymous()) { + nearest_ancestor_box = nearest_ancestor_box->containing_block(); + VERIFY(nearest_ancestor_box); + } + return nearest_ancestor_box; +} + // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context bool Node::establishes_stacking_context() const { diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 70b1ebd267..0919077882 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -112,6 +112,12 @@ public: Box const* containing_block() const; Box* containing_block() { return const_cast<Box*>(const_cast<Node const*>(this)->containing_block()); } + // Closest non-anonymous ancestor box, to be used when resolving percentage values. + // Anonymous block boxes are ignored when resolving percentage values that would refer to it: + // the closest non-anonymous ancestor box is used instead. + // https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level + Box const* non_anyonymous_containing_block() const; + bool establishes_stacking_context() const; bool can_contain_boxes_with_position_absolute() const; |