1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:57:45 +00:00

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.
This commit is contained in:
martinfalisse 2022-08-10 19:19:44 +02:00 committed by Andreas Kling
parent 99ae4fa161
commit 65e7126c48
3 changed files with 58 additions and 51 deletions

View file

@ -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;
}
}
}