summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Gallo <andigallo@proton.me>2023-05-24 06:57:38 +0000
committerAndreas Kling <kling@serenityos.org>2023-05-26 14:53:53 +0200
commit5cec5171538a003d2880d412d3bcae79e7bd88ca (patch)
tree47966cc9f36532d01e79e41c445270a8da695a0a
parent706a20c4d4acbfc9eb9d980969f29e4b1c7a4d1c (diff)
downloadserenity-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.
-rw-r--r--Tests/LibWeb/Layout/expected/resolve-height-of-containing-block.txt26
-rw-r--r--Tests/LibWeb/Layout/input/resolve-height-of-containing-block.html33
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.cpp6
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp11
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.h6
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;