summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Ananyin <ananinegor@gmail.com>2021-04-17 09:09:57 +0300
committerAndreas Kling <kling@serenityos.org>2021-04-17 09:48:27 +0200
commit1d343116a9c814869bc708dffb61d9b100be0eda (patch)
tree732a7fa1de49e9d7cb4a7710d2f3a1854ed35b12
parent602f98fe671a56724f2febcceb7b03b0da80a51c (diff)
downloadserenity-1d343116a9c814869bc708dffb61d9b100be0eda.zip
LibWeb: Fix height calculation for absolutely positioned boxes
This commit fixes algorithm for computing auto height (CSS 2.2 10.6.7) by including floating boxes into computation and implements one of the cases for computing the height of absolutely positioned, non-replaced elements (10.6.4 rule 3)
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp43
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.cpp68
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.h1
4 files changed, 68 insertions, 46 deletions
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
index 195658fb77..82b518edfa 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
@@ -267,49 +267,6 @@ void BlockFormattingContext::compute_width_for_block_level_replaced_element_in_n
box.set_width(compute_width_for_replaced_element(box));
}
-float BlockFormattingContext::compute_auto_height_for_block_level_element(const Box& box)
-{
- Optional<float> top;
- Optional<float> bottom;
-
- if (box.children_are_inline()) {
- // If it only has inline-level children, the height is the distance between
- // the top of the topmost line box and the bottom of the bottommost line box.
- if (!box.line_boxes().is_empty()) {
- for (auto& fragment : box.line_boxes().first().fragments()) {
- if (!top.has_value() || fragment.offset().y() < top.value())
- top = fragment.offset().y();
- }
- for (auto& fragment : box.line_boxes().last().fragments()) {
- if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
- bottom = fragment.offset().y() + fragment.height();
- }
- }
- } else {
- // If it has block-level children, the height is the distance between
- // the top margin-edge of the topmost block-level child box
- // and the bottom margin-edge of the bottommost block-level child box.
- box.for_each_child_of_type<Box>([&](Layout::Box& child_box) {
- if (child_box.is_absolutely_positioned())
- return IterationDecision::Continue;
- if ((box.computed_values().overflow_y() == CSS::Overflow::Visible) && child_box.is_floating())
- return IterationDecision::Continue;
-
- float child_box_top = child_box.effective_offset().y() - child_box.box_model().margin_box().top;
- float child_box_bottom = child_box.effective_offset().y() + child_box.height() + child_box.box_model().margin_box().bottom;
-
- if (!top.has_value() || child_box_top < top.value())
- top = child_box_top;
-
- if (!bottom.has_value() || child_box_bottom > bottom.value())
- bottom = child_box_bottom;
-
- return IterationDecision::Continue;
- });
- }
- return bottom.value_or(0) - top.value_or(0);
-}
-
void BlockFormattingContext::compute_height(Box& box)
{
auto& computed_values = box.computed_values();
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
index 7cc5d6fac5..13852f74de 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
@@ -56,8 +56,6 @@ private:
void compute_width_for_block_level_replaced_element_in_normal_flow(ReplacedBox&);
- [[nodiscard]] static float compute_auto_height_for_block_level_element(const Box&);
-
void layout_initial_containing_block(LayoutMode);
void layout_block_level_children(Box&, LayoutMode);
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
index 5df5ba312f..dfda823476 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
@@ -180,6 +180,63 @@ static Gfx::FloatSize solve_replaced_size_constraint(float w, float h, const Rep
return { w, h };
}
+float FormattingContext::compute_auto_height_for_block_level_element(const Box& box)
+{
+ Optional<float> top;
+ Optional<float> bottom;
+
+ if (box.children_are_inline()) {
+ // If it only has inline-level children, the height is the distance between
+ // the top of the topmost line box and the bottom of the bottommost line box.
+ if (!box.line_boxes().is_empty()) {
+ for (auto& fragment : box.line_boxes().first().fragments()) {
+ if (!top.has_value() || fragment.offset().y() < top.value())
+ top = fragment.offset().y();
+ }
+ for (auto& fragment : box.line_boxes().last().fragments()) {
+ if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value())
+ bottom = fragment.offset().y() + fragment.height();
+ }
+ }
+ } else {
+ // If it has block-level children, the height is the distance between
+ // the top margin-edge of the topmost block-level child box
+ // and the bottom margin-edge of the bottommost block-level child box.
+ box.for_each_child_of_type<Box>([&](Layout::Box& child_box) {
+ if (child_box.is_absolutely_positioned())
+ return IterationDecision::Continue;
+ if ((box.computed_values().overflow_y() == CSS::Overflow::Visible) && child_box.is_floating())
+ return IterationDecision::Continue;
+
+ float child_box_top = child_box.effective_offset().y() - child_box.box_model().margin_box().top;
+ float child_box_bottom = child_box.effective_offset().y() + child_box.height() + child_box.box_model().margin_box().bottom;
+
+ if (!top.has_value() || child_box_top < top.value())
+ top = child_box_top;
+
+ if (!bottom.has_value() || child_box_bottom > bottom.value())
+ bottom = child_box_bottom;
+
+ return IterationDecision::Continue;
+ });
+ // In addition, if the element has any floating descendants
+ // whose bottom margin edge is below the element's bottom content edge,
+ // then the height is increased to include those edges.
+ box.for_each_child_of_type<Box>([&](Layout::Box& child_box) {
+ if (!child_box.is_floating())
+ return IterationDecision::Continue;
+
+ float child_box_bottom = child_box.effective_offset().y() + child_box.height();
+
+ if (!bottom.has_value() || child_box_bottom > bottom.value())
+ bottom = child_box_bottom;
+
+ return IterationDecision::Continue;
+ });
+ }
+ return bottom.value_or(0) - top.value_or(0);
+}
+
float FormattingContext::tentative_width_for_replaced_element(const ReplacedBox& box, const CSS::Length& width)
{
auto& containing_block = *box.containing_block();
@@ -487,7 +544,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
box.box_model().padding.top = computed_values.padding().top.resolved_or_zero(box, containing_block.width()).to_px(box);
box.box_model().padding.bottom = computed_values.padding().bottom.resolved_or_zero(box, containing_block.width()).to_px(box);
- if (specified_height.is_auto() && !specified_top.is_auto() && !specified_bottom.is_auto()) {
+ if (specified_height.is_auto() && !specified_top.is_auto() && specified_bottom.is_auto()) {
+ const auto& margin = box.box_model().margin;
+ const auto& padding = box.box_model().padding;
+ const auto& border = box.box_model().border;
+
+ specified_height = CSS::Length(compute_auto_height_for_block_level_element(box), CSS::Length::Type::Px);
+ box.box_model().offset.bottom = containing_block.height() - specified_height.to_px(box) - specified_top.to_px(box) - margin.top - padding.top - border.top - margin.bottom - padding.bottom - border.bottom;
+ }
+
+ else if (specified_height.is_auto() && !specified_top.is_auto() && !specified_bottom.is_auto()) {
const auto& margin = box.box_model().margin;
const auto& padding = box.box_model().padding;
const auto& border = box.box_model().border;
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
index aad024a04e..213be06a1b 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
@@ -58,6 +58,7 @@ protected:
float preferred_minimum_width { 0 };
};
+ static float compute_auto_height_for_block_level_element(const Box& box);
static float tentative_width_for_replaced_element(const ReplacedBox&, const CSS::Length& width);
static float tentative_height_for_replaced_element(const ReplacedBox&, const CSS::Length& width);