layout: Fix block SizeConstraint for replaced elements (#37758)

#37433 didn't handle intrinsic contributions. This patch computes the
correct SizeConstraint to be used as the ConstraintSpace's block size
when computing intrinsic inline sizes.

Testing: Adding new test
Fixes: #37478

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-06-30 14:07:37 +02:00 committed by GitHub
parent f23e3e25b8
commit 4cd7c5196b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 168 additions and 33 deletions

View file

@ -1031,31 +1031,52 @@ impl Sizes {
get_content_size: impl FnOnce() -> ContentSizes,
is_table: bool,
) -> Au {
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
// A LazyCell will only invoke it once if needed, and then reuse the result.
let content_size = LazyCell::new(get_content_size);
if is_table && axis == Direction::Block {
// The intrinsic block size of a table already takes sizing properties into account,
// but it can be a smaller amount if there are collapsed rows.
// Therefore, disregard sizing properties and just defer to the intrinsic size.
// This is being discussed in https://github.com/w3c/csswg-drafts/issues/11408
return content_size.max_content;
return get_content_size().max_content;
}
let preferred =
self.preferred
.resolve_for_preferred(automatic_size, stretch_size, &content_size);
let min = self.min.resolve_for_min(
let (preferred, min, max) = self.resolve_each(
automatic_size,
get_automatic_minimum_size,
stretch_size,
&content_size,
get_content_size,
is_table,
);
let max = self.max.resolve_for_max(stretch_size, &content_size);
preferred.clamp_between_extremums(min, max)
}
/// Resolves each of the three sizes into a numerical value, separately.
/// - The 1st returned value is the resolved preferred size.
/// - The 2nd returned value is the resolved minimum size.
/// - The 3rd returned value is the resolved maximum size. `None` means no maximum.
#[inline]
pub(crate) fn resolve_each(
&self,
automatic_size: Size<Au>,
get_automatic_minimum_size: impl FnOnce() -> Au,
stretch_size: Option<Au>,
get_content_size: impl FnOnce() -> ContentSizes,
is_table: bool,
) -> (Au, Au, Option<Au>) {
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
// A LazyCell will only invoke it once if needed, and then reuse the result.
let content_size = LazyCell::new(get_content_size);
(
self.preferred
.resolve_for_preferred(automatic_size, stretch_size, &content_size),
self.min.resolve_for_min(
get_automatic_minimum_size,
stretch_size,
&content_size,
is_table,
),
self.max.resolve_for_max(stretch_size, &content_size),
)
}
/// Tries to extrinsically resolve the three sizes into a single [`SizeConstraint`].
/// Values that are intrinsic or need `stretch_size` when it's `None` are handled as such:
/// - On the preferred size, they make the returned value be an indefinite [`SizeConstraint::MinMax`].