summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormartinfalisse <martinmotteditfalisse@gmail.com>2022-08-10 19:19:44 +0200
committerAndreas Kling <kling@serenityos.org>2022-08-14 11:22:52 +0200
commit65e7126c4839bb839cdbaf00f46e5a1dc6f26074 (patch)
tree025f0a9c2c4dd81be2968fafcff61f59f1bf16f9
parent99ae4fa161a331dde7472ed0ad0b8335e4ae2975 (diff)
downloadserenity-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.
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp52
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.cpp55
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.h2
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);