LibWeb: Treat replaced size constraint resolutions as mutually exclusive

Previously, we would run through all the constraints in the spec one by
one, but if we check and resolve each constraint in the order they are
defined in the spec, only the first four will ever match.

This leads me to believe that these constraints are meant to be
mutually exclusive instead, meaning that we must check the most
specific constraints first and return upon the first resolution that
matches.
This commit is contained in:
Zaggy1024 2023-09-03 19:07:05 -05:00 committed by Andreas Kling
parent 34c5043cbe
commit 051f357110

View file

@ -259,50 +259,49 @@ FormattingContext::ShrinkToFitResult FormattingContext::calculate_shrink_to_fit_
CSSPixelSize FormattingContext::solve_replaced_size_constraint(CSSPixels input_width, CSSPixels input_height, Box const& box, AvailableSpace const& available_space) const
{
// 10.4 Minimum and maximum widths: 'min-width' and 'max-width'
// https://www.w3.org/TR/CSS22/visudet.html#min-max-widths
auto const& containing_block = *box.non_anonymous_containing_block();
auto const& containing_block_state = m_state.get(containing_block);
auto width_of_containing_block = containing_block_state.content_width();
auto height_of_containing_block = containing_block_state.content_height();
CSSPixels specified_min_width = box.computed_values().min_width().is_auto() ? 0 : box.computed_values().min_width().to_px(box, width_of_containing_block);
CSSPixels specified_max_width = should_treat_max_width_as_none(box, available_space.width) ? input_width : box.computed_values().max_width().to_px(box, width_of_containing_block);
CSSPixels specified_min_height = box.computed_values().min_height().is_auto() ? 0 : box.computed_values().min_height().to_px(box, height_of_containing_block);
CSSPixels specified_max_height = should_treat_max_height_as_none(box, available_space.height) ? input_height : box.computed_values().max_height().to_px(box, height_of_containing_block);
auto min_width = box.computed_values().min_width().is_auto() ? 0 : box.computed_values().min_width().to_px(box, width_of_containing_block);
auto specified_max_width = should_treat_max_width_as_none(box, available_space.width) ? input_width : box.computed_values().max_width().to_px(box, width_of_containing_block);
auto max_width = max(min_width, specified_max_width);
auto min_width = min(specified_min_width, specified_max_width);
auto max_width = max(specified_min_width, specified_max_width);
auto min_height = min(specified_min_height, specified_max_height);
auto max_height = max(specified_min_height, specified_max_height);
auto min_height = box.computed_values().min_height().is_auto() ? 0 : box.computed_values().min_height().to_px(box, height_of_containing_block);
auto specified_max_height = should_treat_max_height_as_none(box, available_space.height) ? input_height : box.computed_values().max_height().to_px(box, height_of_containing_block);
auto max_height = max(min_height, specified_max_height);
struct Size {
CSSPixels width;
CSSPixels height;
} size = { input_width, input_height };
auto& w = size.width;
auto& h = size.height;
auto aspect_ratio = input_width / input_height;
if (w > max_width)
size = { max_width, max(max_width * (h / w), min_height) };
if (w < min_width)
size = { min_width, min(min_width * (h / w), max_height) };
if (h > max_height)
size = { max(max_height * (w / h), min_width), max_height };
if (h < min_height)
size = { min(min_height * (w / h), max_width), min_height };
if ((w > max_width && h > max_height) && (max_width / w <= max_height / h))
size = { max_width, max(min_height, max_width * (h / w)) };
if ((w > max_width && h > max_height) && (max_width / w > max_height / h))
size = { max(min_width, max_height * (w / h)), max_height };
if ((w < min_width && h < min_height) && (min_width / w <= min_height / h))
size = { min(max_width, min_height * (w / h)), min_height };
if ((w < min_width && h < min_height) && (min_width / w > min_height / h))
size = { min_width, min(max_height, min_width * (h / w)) };
if (w < min_width && h > max_height)
size = { min_width, max_height };
if (w > max_width && h < min_height)
size = { max_width, min_height };
return { w, h };
// These are from the "Constraint Violation" table in spec, but reordered so that each condition is
// interpreted as mutually exclusive to any other.
if (input_width < min_width && input_height > max_height)
return { min_width, max_height };
if (input_width > max_width && input_height < min_height)
return { max_width, min_height };
if (input_width > max_width && input_height > max_height && max_width / input_width <= max_height / input_height)
return { max_width, max(min_height, max_width / aspect_ratio) };
if (input_width > max_width && input_height > max_height && max_width / input_width > max_height / input_height)
return { max(min_width, max_height * aspect_ratio), max_height };
if (input_width < min_width && input_height < min_height && min_width / input_width <= min_height / input_height)
return { min(max_width, min_height * aspect_ratio), min_height };
if (input_width < min_width && input_height < min_height && min_width / input_width > min_height / input_height)
return { min_width, min(max_height, min_width / aspect_ratio) };
if (input_width > max_width)
return { max_width, max(max_width / aspect_ratio, min_height) };
if (input_width < min_width)
return { min_width, min(min_width / aspect_ratio, max_height) };
if (input_height > max_height)
return { max(max_height * aspect_ratio, min_width), max_height };
if (input_height < min_height)
return { min(min_height * aspect_ratio, max_width), min_height };
return { input_width, input_height };
}
Optional<CSSPixels> FormattingContext::compute_auto_height_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout before_or_after_inside_layout) const