layout: Add an indefinite containing block for intrinsic sizing (#33204)

When computing the min-content or max-content size of an element we
need to ignore `inline-size`, `min-inline-size` and `max-inline-size`.

However, we should take the block-axis sizing properties into account.
That's because the contents could have percentages depending on them,
which can then affect their inline size via an aspect ratio.

Therefore, this patch adds `IndefiniteContainingBlock`, which is similar
to `ContainingBlock`, but it allows an indefinite inline-size. This
struct is then passed arround during intrinsic sizing.

More refinement will be needed in follow-up patches in order to fully
address the problem.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Oriol Brufau 2024-08-29 16:10:46 +02:00 committed by GitHub
parent 46dbe4ce32
commit 93abdf7cb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 600 additions and 332 deletions

View file

@ -29,8 +29,8 @@ use crate::dom::NodeExt;
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
use crate::sizing::ContentSizes;
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
use crate::{AuOrAuto, ContainingBlock};
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, PaddingBorderMargin};
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock};
#[derive(Debug, Serialize)]
pub(crate) struct ReplacedContent {
@ -238,7 +238,7 @@ impl ReplacedContent {
LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode())
}
pub fn inline_size_over_block_size_intrinsic_ratio(
pub(crate) fn inline_size_over_block_size_intrinsic_ratio(
&self,
style: &ComputedValues,
) -> Option<CSSFloat> {
@ -251,11 +251,16 @@ impl ReplacedContent {
})
}
pub fn inline_content_sizes(&self, style: &ComputedValues) -> ContentSizes {
pub fn inline_content_sizes(
&self,
_: &LayoutContext,
containing_block_for_children: &IndefiniteContainingBlock,
) -> ContentSizes {
// FIXME: min/max-content of replaced elements is not defined in
// https://dbaron.org/css/intrinsic/
// This seems sensible?
self.flow_relative_intrinsic_size(style)
self.flow_relative_intrinsic_size(containing_block_for_children.style)
.inline
.unwrap_or(Au::zero())
.into()
@ -331,6 +336,18 @@ impl ReplacedContent {
}
}
pub(crate) fn preferred_aspect_ratio(
&self,
containing_block: &IndefiniteContainingBlock,
style: &ComputedValues,
) -> Option<AspectRatio> {
style.preferred_aspect_ratio(
self.inline_size_over_block_size_intrinsic_ratio(style),
containing_block.try_into().ok().as_ref(),
containing_block.style.effective_writing_mode(),
)
}
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width>
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height>
///
@ -345,10 +362,7 @@ impl ReplacedContent {
) -> LogicalVec2<Au> {
let mode = style.effective_writing_mode();
let intrinsic_size = self.flow_relative_intrinsic_size(style);
let intrinsic_ratio = style.preferred_aspect_ratio(
self.inline_size_over_block_size_intrinsic_ratio(style),
containing_block,
);
let intrinsic_ratio = self.preferred_aspect_ratio(&containing_block.into(), style);
let box_size = box_size.unwrap_or(
style