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

@ -7,6 +7,7 @@ use malloc_size_of_derive::MallocSizeOf;
use script::layout_dom::{ServoLayoutElement, ServoLayoutNode};
use servo_arc::Arc;
use style::context::SharedStyleContext;
use style::logical_geometry::Direction;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
@ -21,7 +22,7 @@ use crate::layout_box_base::{
};
use crate::positioned::PositioningContext;
use crate::replaced::ReplacedContents;
use crate::sizing::{self, ComputeInlineContentSizes, InlineContentSizesResult};
use crate::sizing::{self, ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
use crate::style_ext::{AspectRatio, DisplayInside, LayoutStyle};
use crate::table::Table;
use crate::taffy::TaffyContainer;
@ -175,6 +176,35 @@ impl IndependentFormattingContext {
}
}
/// Computes the tentative intrinsic block sizes that may be needed while computing
/// the intrinsic inline sizes. Therefore, this ignores the values of the sizing
/// properties in both axes.
/// A return value of `None` indicates that there is no suitable tentative intrinsic
/// block size, so intrinsic keywords in the block sizing properties will be ignored,
/// possibly resulting in an indefinite [`SizeConstraint`] for computing the intrinsic
/// inline sizes and laying out the contents.
/// A return value of `Some` indicates that intrinsic keywords in the block sizing
/// properties will be resolved as the contained value, guaranteeing a definite amount
/// for computing the intrinsic inline sizes and laying out the contents.
pub(crate) fn tentative_block_content_size(
&self,
preferred_aspect_ratio: Option<AspectRatio>,
) -> Option<ContentSizes> {
// See <https://github.com/w3c/csswg-drafts/issues/12333> regarding the difference
// in behavior for the replaced and non-replaced cases.
match &self.contents {
IndependentFormattingContextContents::NonReplaced(_) => None,
IndependentFormattingContextContents::Replaced(contents) => {
// For replaced elements with no ratio, the returned value doesn't matter.
let ratio = preferred_aspect_ratio?;
let writing_mode = self.style().writing_mode;
let inline_size = contents.fallback_inline_size(writing_mode);
let block_size = ratio.compute_dependent_size(Direction::Block, inline_size);
Some(block_size.into())
},
}
}
pub(crate) fn outer_inline_content_sizes(
&self,
layout_context: &LayoutContext,
@ -191,6 +221,7 @@ impl IndependentFormattingContext {
true, /* establishes_containing_block */
|padding_border_sums| self.preferred_aspect_ratio(padding_border_sums),
|constraint_space| self.inline_content_sizes(layout_context, constraint_space),
|preferred_aspect_ratio| self.tentative_block_content_size(preferred_aspect_ratio),
)
}