From 65e7126c4839bb839cdbaf00f46e5a1dc6f26074 Mon Sep 17 00:00:00 2001 From: martinfalisse Date: Wed, 10 Aug 2022 19:19:44 +0200 Subject: LibWeb: Factor out compute_y_position Factor out the code that computes the vertical position of a Box with respect to its siblings so that it can be used when computing the absolutely positioned divs as well. --- .../LibWeb/Layout/BlockFormattingContext.cpp | 52 +------------------- .../Libraries/LibWeb/Layout/FormattingContext.cpp | 55 ++++++++++++++++++++++ .../Libraries/LibWeb/Layout/FormattingContext.h | 2 + 3 files changed, 58 insertions(+), 51 deletions(-) (limited to 'Userland/Libraries/LibWeb/Layout') diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 2b971bca00..da7e9ad96e 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -505,57 +505,7 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically compute_vertical_box_model_metrics(child_box, containing_block); - float y = box_state.border_box_top(); - - Vector collapsible_margins; - - auto* relevant_sibling = child_box.previous_sibling_of_type(); - while (relevant_sibling != nullptr) { - if (!relevant_sibling->is_absolutely_positioned() && !relevant_sibling->is_floating()) { - auto const& relevant_sibling_state = m_state.get(*relevant_sibling); - collapsible_margins.append(relevant_sibling_state.margin_bottom); - // NOTE: Empty (0-height) preceding siblings have their margins collapsed with *their* preceding sibling, etc. - if (relevant_sibling_state.border_box_height() > 0) - break; - collapsible_margins.append(relevant_sibling_state.margin_top); - } - relevant_sibling = relevant_sibling->previous_sibling_of_type(); - } - - if (relevant_sibling) { - // Collapse top margin with the collapsed margin(s) of preceding siblings. - collapsible_margins.append(box_state.margin_top); - - float smallest_margin = 0; - float largest_margin = 0; - size_t negative_margin_count = 0; - for (auto margin : collapsible_margins) { - if (margin < 0) - ++negative_margin_count; - largest_margin = max(largest_margin, margin); - smallest_margin = min(smallest_margin, margin); - } - - float collapsed_margin = 0; - if (negative_margin_count == collapsible_margins.size()) { - // When all margins are negative, the size of the collapsed margin is the smallest (most negative) margin. - collapsed_margin = smallest_margin; - } else if (negative_margin_count > 0) { - // When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin. - collapsed_margin = largest_margin + smallest_margin; - } else { - // Otherwise, collapse all the adjacent margins by using only the largest one. - collapsed_margin = largest_margin; - } - - auto const& relevant_sibling_state = m_state.get(*relevant_sibling); - y += relevant_sibling_state.offset.y() - + relevant_sibling_state.content_height() - + relevant_sibling_state.border_box_bottom() - + collapsed_margin; - } else { - y += box_state.margin_top; - } + auto y = FormattingContext::compute_box_y_position_with_respect_to_siblings(child_box, box_state); auto clear_floating_boxes = [&](FloatSideData& float_side) { if (!float_side.current_boxes.is_empty()) { diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 68e1de5c66..f264018608 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1089,4 +1089,59 @@ float FormattingContext::containing_block_height_for(Box const& box, LayoutState VERIFY_NOT_REACHED(); } +float FormattingContext::compute_box_y_position_with_respect_to_siblings(Box const& child_box, LayoutState::UsedValues const& box_state) +{ + float y = box_state.border_box_top(); + + Vector collapsible_margins; + + auto* relevant_sibling = child_box.previous_sibling_of_type(); + while (relevant_sibling != nullptr) { + if (!relevant_sibling->is_absolutely_positioned() && !relevant_sibling->is_floating()) { + auto const& relevant_sibling_state = m_state.get(*relevant_sibling); + collapsible_margins.append(relevant_sibling_state.margin_bottom); + // NOTE: Empty (0-height) preceding siblings have their margins collapsed with *their* preceding sibling, etc. + if (relevant_sibling_state.border_box_height() > 0) + break; + collapsible_margins.append(relevant_sibling_state.margin_top); + } + relevant_sibling = relevant_sibling->previous_sibling_of_type(); + } + + if (relevant_sibling) { + // Collapse top margin with the collapsed margin(s) of preceding siblings. + collapsible_margins.append(box_state.margin_top); + + float smallest_margin = 0; + float largest_margin = 0; + size_t negative_margin_count = 0; + for (auto margin : collapsible_margins) { + if (margin < 0) + ++negative_margin_count; + largest_margin = max(largest_margin, margin); + smallest_margin = min(smallest_margin, margin); + } + + float collapsed_margin = 0; + if (negative_margin_count == collapsible_margins.size()) { + // When all margins are negative, the size of the collapsed margin is the smallest (most negative) margin. + collapsed_margin = smallest_margin; + } else if (negative_margin_count > 0) { + // When negative margins are involved, the size of the collapsed margin is the sum of the largest positive margin and the smallest (most negative) negative margin. + collapsed_margin = largest_margin + smallest_margin; + } else { + // Otherwise, collapse all the adjacent margins by using only the largest one. + collapsed_margin = largest_margin; + } + + auto const& relevant_sibling_state = m_state.get(*relevant_sibling); + return y + relevant_sibling_state.offset.y() + + relevant_sibling_state.content_height() + + relevant_sibling_state.border_box_bottom() + + collapsed_margin; + } else { + return y + box_state.margin_top; + } +} + } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index e79cc9d406..6ab8ff073e 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -63,6 +63,8 @@ public: virtual void run_intrinsic_sizing(Box const&); + float compute_box_y_position_with_respect_to_siblings(Box const&, LayoutState::UsedValues const&); + protected: FormattingContext(Type, LayoutState&, Box const&, FormattingContext* parent = nullptr); -- cgit v1.2.3