1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 21:48:13 +00:00

LibWeb: Make intrinsic heights dependent on available width

After speaking with fantasai at CSSWG about this, it turns out I had
misunderstood intrinsic heights. I originally believed all intrinsic
sizes had to be computed with no influence from the surrounding context.

As it turns out, intrinsic heights *are* influenced by the available
width, since it's needed to determine where lines break.

The APIs for calculating min-content and max-content heights now take
the available width as inputs. This instantly improves layout in many
cases where we'd previously make things way too wide.
This commit is contained in:
Andreas Kling 2022-10-03 23:37:38 +02:00
parent b4f9db84ca
commit b13a8706e1
5 changed files with 48 additions and 57 deletions

View file

@ -239,7 +239,7 @@ static Gfx::FloatSize solve_replaced_size_constraint(LayoutState const& state, f
return { w, h };
}
float FormattingContext::compute_auto_height_for_block_level_element(Box const& box) const
float FormattingContext::compute_auto_height_for_block_level_element(Box const& box, AvailableSpace const& available_space) const
{
if (creates_block_formatting_context(box))
return compute_auto_height_for_block_formatting_context_root(verify_cast<BlockContainer>(box));
@ -250,7 +250,7 @@ float FormattingContext::compute_auto_height_for_block_level_element(Box const&
if (display.is_flex_inside()) {
// https://drafts.csswg.org/css-flexbox-1/#algo-main-container
// NOTE: The automatic block size of a block-level flex container is its max-content size.
return calculate_max_content_height(box);
return calculate_max_content_height(box, available_space.width);
}
// https://www.w3.org/TR/CSS22/visudet.html#normal-block
@ -694,11 +694,11 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
box_state.padding_bottom = computed_values.padding().bottom().resolved(box, width_of_containing_block_as_length).to_px(box);
if (computed_height.is_auto() && computed_top.is_auto() && computed_bottom.is_auto()) {
tentative_height = CSS::Length(compute_auto_height_for_block_level_element(box), CSS::Length::Type::Px);
tentative_height = CSS::Length(compute_auto_height_for_block_level_element(box, available_space), CSS::Length::Type::Px);
}
else if (computed_height.is_auto() && !computed_top.is_auto() && computed_bottom.is_auto()) {
tentative_height = CSS::Length(compute_auto_height_for_block_level_element(box), CSS::Length::Type::Px);
tentative_height = CSS::Length(compute_auto_height_for_block_level_element(box, available_space), CSS::Length::Type::Px);
box_state.inset_bottom = height_of_containing_block - tentative_height.to_px(box) - used_top - box_state.margin_top - box_state.padding_top - box_state.border_top - box_state.margin_bottom - box_state.padding_bottom - box_state.border_bottom;
}
@ -926,30 +926,30 @@ float FormattingContext::calculate_fit_content_size(float min_content_size, floa
return max_content_size;
}
float FormattingContext::calculate_fit_content_width(Layout::Box const& box, AvailableSize const& available_size) const
float FormattingContext::calculate_fit_content_width(Layout::Box const& box, AvailableSpace const& available_space) const
{
// When sizing under a min-content constraint, equal to the min-content size.
// NOTE: We check this first, to avoid needlessly calculating the max-content size.
if (available_size.is_min_content())
if (available_space.width.is_min_content())
return calculate_min_content_width(box);
if (available_size.is_max_content())
if (available_space.width.is_max_content())
return calculate_max_content_width(box);
return calculate_fit_content_size(calculate_min_content_width(box), calculate_max_content_width(box), available_size);
return calculate_fit_content_size(calculate_min_content_width(box), calculate_max_content_width(box), available_space.width);
}
float FormattingContext::calculate_fit_content_height(Layout::Box const& box, AvailableSize const& available_size) const
float FormattingContext::calculate_fit_content_height(Layout::Box const& box, AvailableSpace const& available_space) const
{
// When sizing under a min-content constraint, equal to the min-content size.
// NOTE: We check this first, to avoid needlessly calculating the max-content size.
if (available_size.is_min_content())
return calculate_min_content_height(box);
if (available_space.height.is_min_content())
return calculate_min_content_height(box, available_space.width);
if (available_size.is_max_content())
return calculate_max_content_height(box);
if (available_space.height.is_max_content())
return calculate_max_content_height(box, available_space.width);
return calculate_fit_content_size(calculate_min_content_height(box), calculate_max_content_height(box), available_size);
return calculate_fit_content_size(calculate_min_content_height(box, available_space.width), calculate_max_content_height(box, available_space.width), available_space.height);
}
float FormattingContext::calculate_min_content_width(Layout::Box const& box) const
@ -1028,7 +1028,7 @@ float FormattingContext::calculate_max_content_width(Layout::Box const& box) con
return *cache.max_content_width;
}
float FormattingContext::calculate_min_content_height(Layout::Box const& box) const
float FormattingContext::calculate_min_content_height(Layout::Box const& box, AvailableSize const& available_width) const
{
if (box.has_intrinsic_height())
return *box.intrinsic_height();
@ -1047,9 +1047,7 @@ float FormattingContext::calculate_min_content_height(Layout::Box const& box) co
auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(context);
auto available_width = AvailableSize::make_indefinite();
auto available_height = AvailableSize::make_min_content();
context->run(box, LayoutMode::IntrinsicSizing, AvailableSpace(available_width, available_height));
context->run(box, LayoutMode::IntrinsicSizing, AvailableSpace(available_width, AvailableSize::make_min_content()));
cache.min_content_height = context->automatic_content_height();
@ -1062,7 +1060,7 @@ float FormattingContext::calculate_min_content_height(Layout::Box const& box) co
return *cache.min_content_height;
}
float FormattingContext::calculate_max_content_height(Layout::Box const& box) const
float FormattingContext::calculate_max_content_height(Layout::Box const& box, AvailableSize const& available_width) const
{
if (box.has_intrinsic_height())
return *box.intrinsic_height();
@ -1081,9 +1079,7 @@ float FormattingContext::calculate_max_content_height(Layout::Box const& box) co
auto context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(context);
auto available_width = AvailableSize::make_indefinite();
auto available_height = AvailableSize::make_max_content();
context->run(box, LayoutMode::IntrinsicSizing, AvailableSpace(available_width, available_height));
context->run(box, LayoutMode::IntrinsicSizing, AvailableSpace(available_width, AvailableSize::make_max_content()));
cache.max_content_height = context->automatic_content_height();