LibWeb: Fix "box-sizing: border-box" resolution for abspos items

The `calculate_inner_width()` and `calculate_inner_height()` resolve
percentage paddings using the width returned by
`containing_block_width_for()`. However, this function does not account
for grids where the containing block is defined by the grid area to
which an item belongs.

This change fixes the issue by modifying `calculate_inner_width()` and
`calculate_inner_height()` to use the already resolved paddings from the
layout state. Corresponding changes ensure that paddings are resolved
and saved in the state before box-sizing is handled.

As a side effect, this change also improves abspos layout for BFC where
now paddings are resolved using padding box of containing block instead
of content box of containing block.
This commit is contained in:
Aliaksandr Kalenik 2024-09-16 16:58:44 +02:00 committed by Andreas Kling
commit 5f74da6ae8
Notes: github-actions[bot] 2024-09-17 05:57:08 +00:00
7 changed files with 105 additions and 31 deletions

View file

@ -667,13 +667,14 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele
auto width_of_containing_block = available_space.width.to_px_or_zero();
auto const& computed_values = box.computed_values();
auto zero_value = CSS::Length::make_px(0);
auto& box_state = m_state.get_mutable(box);
auto margin_left = CSS::Length::make_auto();
auto margin_right = CSS::Length::make_auto();
auto const border_left = computed_values.border_left().width;
auto const border_right = computed_values.border_right().width;
auto const padding_left = computed_values.padding().left().to_px(box, width_of_containing_block);
auto const padding_right = computed_values.padding().right().to_px(box, width_of_containing_block);
auto const padding_left = box_state.padding_left;
auto const padding_right = box_state.padding_right;
auto computed_left = computed_values.inset().left();
auto computed_right = computed_values.inset().right();
@ -835,14 +836,11 @@ void FormattingContext::compute_width_for_absolutely_positioned_non_replaced_ele
}
}
auto& box_state = m_state.get_mutable(box);
box_state.set_content_width(used_width.to_px(box));
box_state.inset_left = left;
box_state.inset_right = right;
box_state.margin_left = margin_left.to_px(box);
box_state.margin_right = margin_right.to_px(box);
box_state.padding_left = padding_left;
box_state.padding_right = padding_right;
}
void FormattingContext::compute_width_for_absolutely_positioned_replaced_element(Box const& box, AvailableSpace const& available_space)
@ -962,7 +960,7 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
auto top = box.computed_values().inset().top();
auto bottom = box.computed_values().inset().bottom();
auto width_of_containing_block = containing_block_width_for(box);
auto width_of_containing_block = available_space.width.to_px_or_zero();
auto height_of_containing_block = available_space.height.to_px_or_zero();
enum class ClampToZero {
@ -970,15 +968,16 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
Yes,
};
auto& state = m_state.get(box);
auto try_compute_height = [&](CSS::Length height) -> CSS::Length {
auto solve_for = [&](CSS::Length length, ClampToZero clamp_to_zero = ClampToZero::No) {
auto unclamped_value = height_of_containing_block
- top.to_px(box, height_of_containing_block)
- margin_top.to_px(box, width_of_containing_block)
- box.computed_values().border_top().width
- box.computed_values().padding().top().to_px(box, width_of_containing_block)
- state.padding_top
- apply_min_max_height_constraints(height).to_px(box)
- box.computed_values().padding().bottom().to_px(box, width_of_containing_block)
- state.padding_bottom
- box.computed_values().border_bottom().width
- margin_bottom.to_px(box, width_of_containing_block)
- bottom.to_px(box, height_of_containing_block)
@ -1157,8 +1156,6 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
box_state.inset_bottom = bottom.to_px(box, height_of_containing_block);
box_state.margin_top = margin_top.to_px(box, width_of_containing_block);
box_state.margin_bottom = margin_bottom.to_px(box, width_of_containing_block);
box_state.padding_top = box.computed_values().padding().top().to_px(box, width_of_containing_block);
box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, width_of_containing_block);
}
// NOTE: This is different from content_box_rect_in_ancestor_coordinate_space() as this does *not* follow the containing block chain up, but rather the parent() chain.
@ -1241,6 +1238,12 @@ void FormattingContext::layout_absolutely_positioned_element(Box const& box, Ava
box_state.border_top = box.computed_values().border_top().width;
box_state.border_bottom = box.computed_values().border_bottom().width;
auto const containing_block_width = available_space.width.to_px_or_zero();
box_state.padding_left = box.computed_values().padding().left().to_px(box, containing_block_width);
box_state.padding_right = box.computed_values().padding().right().to_px(box, containing_block_width);
box_state.padding_top = box.computed_values().padding().top().to_px(box, containing_block_width);
box_state.padding_bottom = box.computed_values().padding().bottom().to_px(box, containing_block_width);
compute_width_for_absolutely_positioned_element(box, available_space);
// NOTE: We compute height before *and* after doing inside layout.
@ -1625,14 +1628,12 @@ CSSPixels FormattingContext::calculate_inner_width(Layout::Box const& box, Avail
auto& computed_values = box.computed_values();
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
auto const padding_left = computed_values.padding().left().resolved(box, width_of_containing_block);
auto const padding_right = computed_values.padding().right().resolved(box, width_of_containing_block);
auto const& state = m_state.get(box);
auto inner_width = width.to_px(box, width_of_containing_block)
- computed_values.border_left().width
- padding_left.to_px(box)
- state.padding_left
- computed_values.border_right().width
- padding_right.to_px(box);
- state.padding_right;
return max(inner_width, 0);
}
@ -1645,16 +1646,12 @@ CSSPixels FormattingContext::calculate_inner_height(Layout::Box const& box, Avai
auto height_of_containing_block = available_height.to_px_or_zero();
auto& computed_values = box.computed_values();
if (computed_values.box_sizing() == CSS::BoxSizing::BorderBox) {
auto width_of_containing_block = containing_block_width_for(box);
auto const padding_top = computed_values.padding().top().resolved(box, width_of_containing_block);
auto const padding_bottom = computed_values.padding().bottom().resolved(box, width_of_containing_block);
auto const& state = m_state.get(box);
auto inner_height = height.to_px(box, height_of_containing_block)
- computed_values.border_top().width
- padding_top.to_px(box)
- state.padding_top
- computed_values.border_bottom().width
- padding_bottom.to_px(box);
- state.padding_bottom;
return max(inner_height, 0);
}