1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:07:35 +00:00

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 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' // 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 = *box.non_anonymous_containing_block();
auto const& containing_block_state = m_state.get(containing_block); auto const& containing_block_state = m_state.get(containing_block);
auto width_of_containing_block = containing_block_state.content_width(); auto width_of_containing_block = containing_block_state.content_width();
auto height_of_containing_block = containing_block_state.content_height(); 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); auto 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); 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);
CSSPixels specified_min_height = box.computed_values().min_height().is_auto() ? 0 : box.computed_values().min_height().to_px(box, height_of_containing_block); auto max_width = max(min_width, specified_max_width);
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 = min(specified_min_width, specified_max_width); auto min_height = box.computed_values().min_height().is_auto() ? 0 : box.computed_values().min_height().to_px(box, height_of_containing_block);
auto max_width = max(specified_min_width, specified_max_width); 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 min_height = min(specified_min_height, specified_max_height); auto max_height = max(min_height, specified_max_height);
auto max_height = max(specified_min_height, specified_max_height);
struct Size { auto aspect_ratio = input_width / input_height;
CSSPixels width;
CSSPixels height;
} size = { input_width, input_height };
auto& w = size.width;
auto& h = size.height;
if (w > max_width) // These are from the "Constraint Violation" table in spec, but reordered so that each condition is
size = { max_width, max(max_width * (h / w), min_height) }; // interpreted as mutually exclusive to any other.
if (w < min_width) if (input_width < min_width && input_height > max_height)
size = { min_width, min(min_width * (h / w), max_height) }; return { min_width, max_height };
if (h > max_height) if (input_width > max_width && input_height < min_height)
size = { max(max_height * (w / h), min_width), max_height }; return { max_width, min_height };
if (h < min_height)
size = { min(min_height * (w / h), max_width), min_height }; if (input_width > max_width && input_height > max_height && max_width / input_width <= max_height / input_height)
if ((w > max_width && h > max_height) && (max_width / w <= max_height / h)) return { max_width, max(min_height, max_width / aspect_ratio) };
size = { max_width, max(min_height, max_width * (h / w)) }; if (input_width > max_width && input_height > max_height && max_width / input_width > max_height / input_height)
if ((w > max_width && h > max_height) && (max_width / w > max_height / h)) return { max(min_width, max_height * aspect_ratio), max_height };
size = { max(min_width, max_height * (w / h)), max_height }; if (input_width < min_width && input_height < min_height && min_width / input_width <= min_height / input_height)
if ((w < min_width && h < min_height) && (min_width / w <= min_height / h)) return { min(max_width, min_height * aspect_ratio), min_height };
size = { min(max_width, min_height * (w / h)), min_height }; if (input_width < min_width && input_height < min_height && min_width / input_width > min_height / input_height)
if ((w < min_width && h < min_height) && (min_width / w > min_height / h)) return { min_width, min(max_height, min_width / aspect_ratio) };
size = { min_width, min(max_height, min_width * (h / w)) };
if (w < min_width && h > max_height) if (input_width > max_width)
size = { min_width, max_height }; return { max_width, max(max_width / aspect_ratio, min_height) };
if (w > max_width && h < min_height) if (input_width < min_width)
size = { max_width, min_height }; return { min_width, min(min_width / aspect_ratio, max_height) };
return { w, h }; 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 Optional<CSSPixels> FormattingContext::compute_auto_height_for_absolutely_positioned_element(Box const& box, AvailableSpace const& available_space, BeforeOrAfterInsideLayout before_or_after_inside_layout) const