diff options
author | martinfalisse <martinmotteditfalisse@gmail.com> | 2022-08-10 19:19:44 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-08-14 11:22:52 +0200 |
commit | 65e7126c4839bb839cdbaf00f46e5a1dc6f26074 (patch) | |
tree | 025f0a9c2c4dd81be2968fafcff61f59f1bf16f9 | |
parent | 99ae4fa161a331dde7472ed0ad0b8335e4ae2975 (diff) | |
download | serenity-65e7126c4839bb839cdbaf00f46e5a1dc6f26074.zip |
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.
3 files changed, 58 insertions, 51 deletions
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<float> collapsible_margins; - - auto* relevant_sibling = child_box.previous_sibling_of_type<Layout::BlockContainer>(); - 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<Layout::BlockContainer>(); - } - - 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<float> collapsible_margins; + + auto* relevant_sibling = child_box.previous_sibling_of_type<Layout::BlockContainer>(); + 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<Layout::BlockContainer>(); + } + + 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); |