diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 90b179b7f15..a968926cdca 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -40,7 +40,7 @@ use crate::sizing::{ContentSizes, InlineContentSizesResult, IntrinsicSizingMode} use crate::style_ext::{ Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin, }; -use crate::{ContainingBlock, IndefiniteContainingBlock}; +use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint}; /// Layout parameters and intermediate results about a flex container, /// grouped to avoid passing around many parameters @@ -401,19 +401,17 @@ impl FlexContainer { pub fn inline_content_sizes( &mut self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { match self.config.flex_axis { FlexAxis::Row => { - self.main_content_sizes(layout_context, containing_block_for_children, || { + self.main_content_sizes(layout_context, &constraint_space.into(), || { unreachable!( "Unexpected FlexContext query during row flex intrinsic size calculation." ) }) }, - FlexAxis::Column => { - self.cross_content_sizes(layout_context, containing_block_for_children) - }, + FlexAxis::Column => self.cross_content_sizes(layout_context, &constraint_space.into()), } } @@ -1882,17 +1880,16 @@ impl FlexItem<'_> { } else { ( cross_size.auto_is(|| { - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - item_writing_mode, - AuOrAuto::LengthPercentage(used_main_size), - ); + let constraint_space = ConstraintSpace::new( + SizeConstraint::Definite(used_main_size), + item_writing_mode, + ); let content_contributions = self .box_ .independent_formatting_context .inline_content_sizes( flex_context.layout_context, - &containing_block_for_children, + &constraint_space, &containing_block.into(), ) .sizes @@ -2474,7 +2471,7 @@ impl FlexItemBox { Direction::Block }; - let cross_size = + let cross_size = SizeConstraint::new( if content_box_size.cross.is_auto() && auto_cross_size_stretches_to_container_size { if cross_axis_is_item_block_axis { containing_block.size.block @@ -2485,14 +2482,17 @@ impl FlexItemBox { } else { content_box_size.cross } - .map(|v| v.clamp_between_extremums(min_size.cross.auto_is(Au::zero), max_size.cross)); + .non_auto(), + min_size.cross.auto_is(Au::zero), + max_size.cross, + ); // > **transferred size suggestion** // > If the item has a preferred aspect ratio and its preferred cross size is definite, then the // > transferred size suggestion is that size (clamped by its minimum and maximum cross sizes if they // > are definite), converted through the aspect ratio. It is otherwise undefined. let transferred_size_suggestion = match (ratio, cross_size) { - (Some(ratio), AuOrAuto::LengthPercentage(cross_size)) => { + (Some(ratio), SizeConstraint::Definite(cross_size)) => { Some(ratio.compute_dependent_size(main_axis, cross_size)) }, _ => None, @@ -2504,17 +2504,9 @@ impl FlexItemBox { // > aspect ratio. let main_content_size = if cross_axis_is_item_block_axis { let writing_mode = self.independent_formatting_context.style().writing_mode; - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - writing_mode, - cross_size, - ); + let constraint_space = ConstraintSpace::new(cross_size, writing_mode); self.independent_formatting_context - .inline_content_sizes( - layout_context, - &containing_block_for_children, - containing_block, - ) + .inline_content_sizes(layout_context, &constraint_space, containing_block) .sizes .min_content } else { @@ -2664,23 +2656,16 @@ impl FlexItemBox { // The main axis is the inline axis, so we can get the content size from the normal // preferred widths calculation. let writing_mode = flex_item.style().writing_mode; - let block_size = content_box_size.cross.map(|v| { - v.clamp_between_extremums( + let constraint_space = ConstraintSpace::new( + SizeConstraint::new( + content_box_size.cross.non_auto(), content_min_box_size.cross, content_max_box_size.cross, - ) - }); - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - writing_mode, - block_size, - ); + ), + writing_mode, + ); let max_content = flex_item - .inline_content_sizes( - layout_context, - &containing_block_for_children, - containing_block, - ) + .inline_content_sizes(layout_context, &constraint_space, containing_block) .sizes .max_content; if let Some(ratio) = ratio { @@ -2764,9 +2749,7 @@ impl FlexItemBox { containing_block_inline_size_minus_pbm } else { let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode( - non_replaced.style.writing_mode, - ); + ConstraintSpace::new_for_style(&non_replaced.style); non_replaced .inline_content_sizes( flex_context.layout_context, diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index c4de3a9ca42..13714235b0b 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -128,7 +128,7 @@ use crate::geom::{LogicalRect, LogicalVec2, ToLogical}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::sizing::{ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; -use crate::{ContainingBlock, IndefiniteContainingBlock}; +use crate::{ConstraintSpace, ContainingBlock}; // From gfxFontConstants.h in Firefox. static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20; @@ -1574,9 +1574,9 @@ impl InlineFormattingContext { pub(super) fn inline_content_sizes( &self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { - ContentSizesComputation::compute(self, layout_context, containing_block_for_children) + ContentSizesComputation::compute(self, layout_context, constraint_space) } pub(super) fn layout( @@ -2188,7 +2188,7 @@ fn inline_container_needs_strut( /// A struct which takes care of computing [`ContentSizes`] for an [`InlineFormattingContext`]. struct ContentSizesComputation<'layout_data> { layout_context: &'layout_data LayoutContext<'layout_data>, - containing_block: &'layout_data IndefiniteContainingBlock, + constraint_space: &'layout_data ConstraintSpace, paragraph: ContentSizes, current_line: ContentSizes, /// Size for whitespace pending to be added to this line. @@ -2234,16 +2234,15 @@ impl<'layout_data> ContentSizesComputation<'layout_data> { let inline_box = inline_formatting_context.inline_boxes.get(identifier); let inline_box = (*inline_box).borrow(); let zero = Au::zero(); + let writing_mode = self.constraint_space.writing_mode; let padding = inline_box .style - .padding(self.containing_block.writing_mode) + .padding(writing_mode) .percentages_relative_to(zero); - let border = inline_box - .style - .border_width(self.containing_block.writing_mode); + let border = inline_box.style.border_width(writing_mode); let margin = inline_box .style - .margin(self.containing_block.writing_mode) + .margin(writing_mode) .percentages_relative_to(zero) .auto_is(Au::zero); @@ -2329,7 +2328,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> { depends_on_block_constraints, } = atomic.outer_inline_content_sizes( self.layout_context, - self.containing_block, + &self.constraint_space.into(), &LogicalVec2::zero(), false, /* auto_block_size_stretches_to_containing_block */ ); @@ -2384,11 +2383,11 @@ impl<'layout_data> ContentSizesComputation<'layout_data> { fn compute( inline_formatting_context: &InlineFormattingContext, layout_context: &'layout_data LayoutContext, - containing_block: &'layout_data IndefiniteContainingBlock, + constraint_space: &'layout_data ConstraintSpace, ) -> InlineContentSizesResult { Self { layout_context, - containing_block, + constraint_space, paragraph: ContentSizes::zero(), current_line: ContentSizes::zero(), pending_whitespace: ContentSizes::zero(), diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index a3b4deddccf..94a8bb55931 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -41,7 +41,7 @@ use crate::sizing::{self, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin, }; -use crate::{ContainingBlock, IndefiniteContainingBlock}; +use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint}; mod construct; pub mod float; @@ -235,7 +235,7 @@ impl OutsideMarker { ) -> Fragment { let content_sizes = self.block_container.inline_content_sizes( layout_context, - &IndefiniteContainingBlock::new_for_writing_mode(self.marker_style.writing_mode), + &ConstraintSpace::new_for_style(&self.marker_style), ); let containing_block_for_children = ContainingBlock { inline_size: content_sizes.sizes.max_content, @@ -393,8 +393,8 @@ fn calculate_inline_content_size_for_block_level_boxes( containing_block, &LogicalVec2::zero(), false, /* auto_block_size_stretches_to_containing_block */ - |containing_block_for_children| { - contents.inline_content_sizes(layout_context, containing_block_for_children) + |constraint_space| { + contents.inline_content_sizes(layout_context, constraint_space) }, ); // A block in the same BFC can overlap floats, it's not moved next to them, @@ -528,16 +528,16 @@ impl BlockContainer { pub(super) fn inline_content_sizes( &self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { match &self { Self::BlockLevelBoxes(boxes) => calculate_inline_content_size_for_block_level_boxes( boxes, layout_context, - containing_block_for_children, + &constraint_space.into(), ), Self::InlineFormattingContext(context) => { - context.inline_content_sizes(layout_context, containing_block_for_children) + context.inline_content_sizes(layout_context, constraint_space) }, } } @@ -2030,39 +2030,33 @@ impl IndependentFormattingContext { (fragments, content_rect, None) }, IndependentFormattingContext::NonReplaced(non_replaced) => { - let style = non_replaced.style.clone(); + let writing_mode = non_replaced.style.writing_mode; let available_inline_size = (containing_block.inline_size - pbm_sums.inline_sum()).max(Au::zero()); let available_block_size = containing_block .block_size .non_auto() .map(|block_size| (block_size - pbm_sums.block_sum()).max(Au::zero())); - let tentative_block_size = content_box_sizes_and_pbm + let preferred_block_size = content_box_sizes_and_pbm .content_box_size .block + .maybe_resolve_extrinsic(available_block_size); + let min_block_size = content_box_sizes_and_pbm + .content_min_box_size + .block .maybe_resolve_extrinsic(available_block_size) - .map(|size| { - let min_block_size = content_box_sizes_and_pbm - .content_min_box_size - .block - .maybe_resolve_extrinsic(available_block_size) - .unwrap_or_default(); - let max_block_size = content_box_sizes_and_pbm - .content_max_box_size - .block - .maybe_resolve_extrinsic(available_block_size); - size.clamp_between_extremums(min_block_size, max_block_size) - }) - .map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage); + .unwrap_or_default(); + let max_block_size = content_box_sizes_and_pbm + .content_max_box_size + .block + .maybe_resolve_extrinsic(available_block_size); + let tentative_block_size = + SizeConstraint::new(preferred_block_size, min_block_size, max_block_size); let mut get_content_size = || { - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - style.writing_mode, - tentative_block_size, - ); + let constraint_space = ConstraintSpace::new(tentative_block_size, writing_mode); non_replaced - .inline_content_sizes(layout_context, &containing_block_for_children) + .inline_content_sizes(layout_context, &constraint_space) .sizes }; @@ -2092,12 +2086,12 @@ impl IndependentFormattingContext { let containing_block_for_children = ContainingBlock { inline_size, - block_size: tentative_block_size, - style: &style, + block_size: tentative_block_size.to_auto_or(), + style: &non_replaced.style, }; assert_eq!( container_writing_mode.is_horizontal(), - style.writing_mode.is_horizontal(), + writing_mode.is_horizontal(), "Mixed horizontal and vertical writing modes are not supported yet" ); @@ -2126,7 +2120,8 @@ impl IndependentFormattingContext { .block .resolve_non_initial(stretch_size, &mut get_content_size); let block_size = tentative_block_size - .auto_is(|| independent_layout.content_block_size) + .to_definite() + .unwrap_or(independent_layout.content_block_size) .clamp_between_extremums(min_block_size, max_block_size); (inline_size, block_size) }, diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index d843ca4d32c..6dd214b1580 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -21,7 +21,9 @@ use crate::replaced::ReplacedContent; use crate::sizing::{self, InlineContentSizesResult}; use crate::style_ext::{AspectRatio, DisplayInside}; use crate::table::Table; -use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock, LogicalVec2}; +use crate::{ + ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2, SizeConstraint, +}; /// #[derive(Debug, Serialize)] @@ -36,7 +38,7 @@ pub(crate) struct NonReplacedFormattingContext { #[serde(skip_serializing)] pub style: Arc, /// If it was requested during construction - pub content_sizes_result: Option<(AuOrAuto, InlineContentSizesResult)>, + pub content_sizes_result: Option<(SizeConstraint, InlineContentSizesResult)>, pub contents: NonReplacedFormattingContextContents, } @@ -188,16 +190,16 @@ impl IndependentFormattingContext { pub(crate) fn inline_content_sizes( &mut self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, containing_block: &IndefiniteContainingBlock, ) -> InlineContentSizesResult { match self { Self::NonReplaced(inner) => { - inner.inline_content_sizes(layout_context, containing_block_for_children) + inner.inline_content_sizes(layout_context, constraint_space) }, Self::Replaced(inner) => inner.contents.inline_content_sizes( layout_context, - containing_block_for_children, + constraint_space, inner.preferred_aspect_ratio(containing_block), ), } @@ -222,10 +224,10 @@ impl IndependentFormattingContext { containing_block, auto_minimum, auto_block_size_stretches_to_containing_block, - |containing_block_for_children| { + |constraint_space| { replaced.contents.inline_content_sizes( layout_context, - containing_block_for_children, + constraint_space, replaced.preferred_aspect_ratio(containing_block), ) }, @@ -276,16 +278,11 @@ impl NonReplacedFormattingContext { pub(crate) fn inline_content_sizes( &mut self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { - assert_eq!( - containing_block_for_children.size.inline, - AuOrAuto::Auto, - "inline_content_sizes() got non-auto containing block inline-size", - ); if let Some((previous_cb_block_size, result)) = self.content_sizes_result { if !result.depends_on_block_constraints || - previous_cb_block_size == containing_block_for_children.size.block + previous_cb_block_size == constraint_space.block_size { return result; } @@ -294,9 +291,9 @@ impl NonReplacedFormattingContext { self.content_sizes_result .insert(( - containing_block_for_children.size.block, + constraint_space.block_size, self.contents - .inline_content_sizes(layout_context, containing_block_for_children), + .inline_content_sizes(layout_context, constraint_space), )) .1 } @@ -313,9 +310,7 @@ impl NonReplacedFormattingContext { containing_block, auto_minimum, auto_block_size_stretches_to_containing_block, - |containing_block_for_children| { - self.inline_content_sizes(layout_context, containing_block_for_children) - }, + |constraint_space| self.inline_content_sizes(layout_context, constraint_space), ) } } @@ -324,18 +319,14 @@ impl NonReplacedFormattingContextContents { pub(crate) fn inline_content_sizes( &mut self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { match self { Self::Flow(inner) => inner .contents - .inline_content_sizes(layout_context, containing_block_for_children), - Self::Flex(inner) => { - inner.inline_content_sizes(layout_context, containing_block_for_children) - }, - Self::Table(table) => { - table.inline_content_sizes(layout_context, containing_block_for_children) - }, + .inline_content_sizes(layout_context, constraint_space), + Self::Flex(inner) => inner.inline_content_sizes(layout_context, constraint_space), + Self::Table(table) => table.inline_content_sizes(layout_context, constraint_space), } } } diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index a213fc99d31..ba7349ad81f 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -17,6 +17,7 @@ use style::Zero; use style_traits::CSSPixel; use crate::sizing::ContentSizes; +use crate::style_ext::Clamp; use crate::ContainingBlock; pub type PhysicalPoint = euclid::Point2D; @@ -848,3 +849,45 @@ impl Size { } } } + +/// Represents the sizing constraint that the preferred, min and max sizing properties +/// impose on one axis. +#[derive(Clone, Copy, Debug, PartialEq, Serialize)] +pub(crate) enum SizeConstraint { + /// Represents a definite preferred size, clamped by minimum and maximum sizes (if any). + Definite(Au), + /// Represents an indefinite preferred size that allows a range of values between + /// the first argument (minimum size) and the second one (maximum size). + MinMax(Au, Option), +} + +impl Default for SizeConstraint { + #[inline] + fn default() -> Self { + Self::MinMax(Au::default(), None) + } +} + +impl SizeConstraint { + #[inline] + pub(crate) fn new(preferred_size: Option, min_size: Au, max_size: Option) -> Self { + preferred_size.map_or_else( + || Self::MinMax(min_size, max_size), + |size| Self::Definite(size.clamp_between_extremums(min_size, max_size)), + ) + } + + #[inline] + pub(crate) fn to_definite(self) -> Option { + match self { + Self::Definite(size) => Some(size), + _ => None, + } + } + + #[inline] + pub(crate) fn to_auto_or(self) -> AutoOr { + self.to_definite() + .map_or(AutoOr::Auto, AutoOr::LengthPercentage) + } +} diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index 3d00123aa53..5a4dfc5e72b 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -32,34 +32,44 @@ use geom::AuOrAuto; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; -use crate::geom::LogicalVec2; +use crate::geom::{LogicalVec2, SizeConstraint}; -/// A containing block useful for calculating inline content sizes, which may -/// have inline sizes that depend on block sizes due to aspect ratio. +/// Represents the set of constraints that we use when computing the min-content +/// and max-content inline sizes of an element. +pub(crate) struct ConstraintSpace { + pub block_size: SizeConstraint, + pub writing_mode: WritingMode, +} + +impl ConstraintSpace { + fn new(block_size: SizeConstraint, writing_mode: WritingMode) -> Self { + Self { + block_size, + writing_mode, + } + } + + fn new_for_style(style: &ComputedValues) -> Self { + Self::new(SizeConstraint::default(), style.writing_mode) + } +} + +/// A variant of [`ContainingBlock`] that allows an indefinite inline size. +/// Useful for code that is shared for both layout (where we know the inline size +/// of the containing block) and intrinsic sizing (where we don't know it). pub(crate) struct IndefiniteContainingBlock { pub size: LogicalVec2, pub writing_mode: WritingMode, } -impl IndefiniteContainingBlock { - fn new_for_writing_mode(writing_mode: WritingMode) -> Self { - Self::new_for_writing_mode_and_block_size(writing_mode, AuOrAuto::Auto) - } - - /// Creates an [`IndefiniteContainingBlock`] with the provided style and block size, - /// and the inline size is set to auto. - /// This is useful when finding the min-content or max-content size of an element, - /// since then we ignore its 'inline-size', 'min-inline-size' and 'max-inline-size'. - fn new_for_writing_mode_and_block_size( - writing_mode: WritingMode, - block_size: AuOrAuto, - ) -> Self { +impl From<&ConstraintSpace> for IndefiniteContainingBlock { + fn from(constraint_space: &ConstraintSpace) -> Self { Self { size: LogicalVec2 { inline: AuOrAuto::Auto, - block: block_size, + block: constraint_space.block_size.to_auto_or(), }, - writing_mode, + writing_mode: constraint_space.writing_mode, } } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 100808d012c..8b59b72216f 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -29,8 +29,8 @@ use crate::geom::{ PhysicalRect, PhysicalVec, Size, ToLogical, ToLogicalWithContainingBlock, }; use crate::sizing::ContentSizes; -use crate::style_ext::{Clamp, ComputedValuesExt, DisplayInside}; -use crate::{ContainingBlock, DefiniteContainingBlock, IndefiniteContainingBlock}; +use crate::style_ext::{ComputedValuesExt, DisplayInside}; +use crate::{ConstraintSpace, ContainingBlock, DefiniteContainingBlock, SizeConstraint}; #[derive(Debug, Serialize)] pub(crate) struct AbsolutelyPositionedBox { @@ -546,17 +546,9 @@ impl HoistedAbsolutelyPositionedBox { // The inline axis can be fully resolved, computing intrinsic sizes using the // tentative block size. let mut inline_axis = inline_axis_solver.solve(Some(|| { - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - style.writing_mode, - block_axis.size, - ); + let constraint_space = ConstraintSpace::new(block_axis.size, style.writing_mode); context - .inline_content_sizes( - layout_context, - &containing_block_for_children, - &containing_block.into(), - ) + .inline_content_sizes(layout_context, &constraint_space, &containing_block.into()) .sizes })); @@ -578,10 +570,10 @@ impl HoistedAbsolutelyPositionedBox { IndependentFormattingContext::NonReplaced(non_replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height - let inline_size = inline_axis.size.non_auto().unwrap(); + let inline_size = inline_axis.size.to_definite().unwrap(); let containing_block_for_children = ContainingBlock { inline_size, - block_size: block_axis.size, + block_size: block_axis.size.to_auto_or(), style: &style, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows @@ -608,7 +600,7 @@ impl HoistedAbsolutelyPositionedBox { inline_axis = inline_axis_solver.solve_with_size(table_inline_size); } let table_block_size = independent_layout.content_block_size; - if block_axis.size != AuOrAuto::LengthPercentage(table_block_size) { + if block_axis.size != SizeConstraint::Definite(table_block_size) { block_axis = block_axis_solver.solve_with_size(table_block_size); } (table_block_size, table_inline_size) @@ -617,7 +609,7 @@ impl HoistedAbsolutelyPositionedBox { // Now we can properly solve the block size. block_axis = block_axis_solver .solve(Some(|| independent_layout.content_block_size.into())); - (block_axis.size.non_auto().unwrap(), inline_size) + (block_axis.size.to_definite().unwrap(), inline_size) }, }; @@ -747,7 +739,7 @@ impl Anchor { struct AxisResult { anchor: Anchor, - size: AuOrAuto, + size: SizeConstraint, margin_start: Au, margin_end: Au, } @@ -787,38 +779,37 @@ impl<'a> AbsoluteAxisSolver<'a> { let content_size = LazyCell::new(get_content_size); move || *content_size }); - let mut solve_size = |initial_behavior, stretch_size: Au| { + let mut solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint { let initial_is_stretch = initial_behavior == Size::Stretch; let stretch_size = stretch_size.max(Au::zero()); - get_content_size - .as_mut() - .map(|mut get_content_size| { - let min_size = self - .computed_min_size - .resolve_non_initial(stretch_size, &mut get_content_size) - .unwrap_or_default(); - let max_size = self - .computed_max_size - .resolve_non_initial(stretch_size, &mut get_content_size); - self.computed_size - .resolve(initial_behavior, stretch_size, &mut get_content_size) - .clamp_between_extremums(min_size, max_size) - }) - .or_else(|| { - self.computed_size - .maybe_resolve_extrinsic(Some(stretch_size)) - .or(initial_is_stretch.then_some(stretch_size)) - .map(|size| { - let min_size = self - .computed_min_size - .maybe_resolve_extrinsic(Some(stretch_size)) - .unwrap_or_default(); - let max_size = self - .computed_max_size - .maybe_resolve_extrinsic(Some(stretch_size)); - size.clamp_between_extremums(min_size, max_size) - }) - }) + if let Some(mut get_content_size) = get_content_size.as_mut() { + let preferred_size = Some(self.computed_size.resolve( + initial_behavior, + stretch_size, + &mut get_content_size, + )); + let min_size = self + .computed_min_size + .resolve_non_initial(stretch_size, &mut get_content_size) + .unwrap_or_default(); + let max_size = self + .computed_max_size + .resolve_non_initial(stretch_size, &mut get_content_size); + SizeConstraint::new(preferred_size, min_size, max_size) + } else { + let preferred_size = self + .computed_size + .maybe_resolve_extrinsic(Some(stretch_size)) + .or(initial_is_stretch.then_some(stretch_size)); + let min_size = self + .computed_min_size + .maybe_resolve_extrinsic(Some(stretch_size)) + .unwrap_or_default(); + let max_size = self + .computed_max_size + .maybe_resolve_extrinsic(Some(stretch_size)); + SizeConstraint::new(preferred_size, min_size, max_size) + } }; let mut solve_for_anchor = |anchor: Anchor| { let margin_start = self.computed_margin_start.auto_is(Au::zero); @@ -828,8 +819,7 @@ impl<'a> AbsoluteAxisSolver<'a> { self.padding_border_sum - margin_start - margin_end; - let size = solve_size(Size::FitContent, stretch_size) - .map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage); + let size = solve_size(Size::FitContent, stretch_size); AxisResult { anchor, size, @@ -859,7 +849,9 @@ impl<'a> AbsoluteAxisSolver<'a> { let stretch_size = free_space - self.computed_margin_start.auto_is(Au::zero) - self.computed_margin_end.auto_is(Au::zero); - let used_size = solve_size(Size::Stretch, stretch_size).unwrap(); + let used_size = solve_size(Size::Stretch, stretch_size) + .to_definite() + .unwrap(); free_space -= used_size; let (margin_start, margin_end) = match (self.computed_margin_start, self.computed_margin_end) { @@ -883,7 +875,7 @@ impl<'a> AbsoluteAxisSolver<'a> { }; AxisResult { anchor: Anchor::Start(start), - size: AuOrAuto::LengthPercentage(used_size), + size: SizeConstraint::Definite(used_size), margin_start, margin_end, } diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index ddccda13e4f..8aa2b567212 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -31,7 +31,7 @@ use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFrag use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size}; use crate::sizing::InlineContentSizesResult; use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM}; -use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock}; +use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint}; #[derive(Debug, Serialize)] pub(crate) struct ReplacedContent { @@ -259,36 +259,46 @@ impl ReplacedContent { }) } + #[inline] + fn content_size( + &self, + axis: Direction, + preferred_aspect_ratio: Option, + get_size_in_opposite_axis: &dyn Fn() -> SizeConstraint, + get_fallback_size: &dyn Fn() -> Au, + ) -> Au { + let Some(ratio) = preferred_aspect_ratio else { + return get_fallback_size(); + }; + let transfer = |size| ratio.compute_dependent_size(axis, size); + match get_size_in_opposite_axis() { + SizeConstraint::Definite(size) => transfer(size), + SizeConstraint::MinMax(min_size, max_size) => get_fallback_size() + .clamp_between_extremums(transfer(min_size), max_size.map(transfer)), + } + } + pub fn inline_content_sizes( &self, _: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, preferred_aspect_ratio: Option, ) -> InlineContentSizesResult { - // FIXME: min/max-content of replaced elements is not defined in - // https://dbaron.org/css/intrinsic/ - // This seems sensible? - let block_size = containing_block_for_children.size.block; - match (block_size, preferred_aspect_ratio) { - (AuOrAuto::LengthPercentage(block_size), Some(ratio)) => InlineContentSizesResult { - sizes: ratio - .compute_dependent_size(Direction::Inline, block_size) - .into(), - depends_on_block_constraints: true, - }, - _ => { - let writing_mode = containing_block_for_children.writing_mode; - InlineContentSizesResult { - sizes: self - .flow_relative_natural_size(writing_mode) - .inline - .unwrap_or_else(|| { - Self::flow_relative_default_object_size(writing_mode).inline - }) - .into(), - depends_on_block_constraints: false, - } - }, + let get_inline_fallback_size = || { + let writing_mode = constraint_space.writing_mode; + self.flow_relative_natural_size(writing_mode) + .inline + .unwrap_or_else(|| Self::flow_relative_default_object_size(writing_mode).inline) + }; + let inline_content_size = self.content_size( + Direction::Inline, + preferred_aspect_ratio, + &|| constraint_space.block_size, + &get_inline_fallback_size, + ); + InlineContentSizesResult { + sizes: inline_content_size.into(), + depends_on_block_constraints: preferred_aspect_ratio.is_some(), } } @@ -529,51 +539,51 @@ impl ReplacedContent { .map(|block_size| Au::zero().max(block_size - pbm_sums.block)); // - // FIXME: Use ReplacedContent::inline_content_sizes() once it's fixed to correctly handle - // min and max constraints. let inline_content_size = LazyCell::new(|| { - let Some(ratio) = ratio else { - return get_inline_fallback_size(); + let get_block_size = || { + let block_stretch_size = block_stretch_size.unwrap_or_else(get_block_fallback_size); + SizeConstraint::new( + box_size + .block + .maybe_resolve_extrinsic(Some(block_stretch_size)), + min_box_size + .block + .maybe_resolve_extrinsic(Some(block_stretch_size)) + .unwrap_or_default(), + max_box_size + .block + .maybe_resolve_extrinsic(Some(block_stretch_size)), + ) }; - let block_stretch_size = block_stretch_size.unwrap_or_else(get_block_fallback_size); - let transfer = |size| ratio.compute_dependent_size(Direction::Inline, size); - let min = transfer( - min_box_size - .block - .maybe_resolve_extrinsic(Some(block_stretch_size)) - .unwrap_or_default(), - ); - let max = max_box_size - .block - .maybe_resolve_extrinsic(Some(block_stretch_size)) - .map(transfer); - box_size - .block - .maybe_resolve_extrinsic(Some(block_stretch_size)) - .map_or_else(get_inline_fallback_size, transfer) - .clamp_between_extremums(min, max) + self.content_size( + Direction::Inline, + ratio, + &get_block_size, + &get_inline_fallback_size, + ) }); let block_content_size = LazyCell::new(|| { - let Some(ratio) = ratio else { - return get_block_fallback_size(); + let get_inline_size = || { + let mut get_inline_content_size = || (*inline_content_size).into(); + SizeConstraint::new( + box_size + .inline + .maybe_resolve_extrinsic(Some(inline_stretch_size)), + min_box_size + .inline + .resolve_non_initial(inline_stretch_size, &mut get_inline_content_size) + .unwrap_or_default(), + max_box_size + .inline + .resolve_non_initial(inline_stretch_size, &mut get_inline_content_size), + ) }; - let mut get_inline_content_size = || (*inline_content_size).into(); - let transfer = |size| ratio.compute_dependent_size(Direction::Block, size); - let min = transfer( - min_box_size - .inline - .resolve_non_initial(inline_stretch_size, &mut get_inline_content_size) - .unwrap_or_default(), - ); - let max = max_box_size - .inline - .resolve_non_initial(inline_stretch_size, &mut get_inline_content_size) - .map(transfer); - box_size - .inline - .maybe_resolve_extrinsic(Some(inline_stretch_size)) - .map_or_else(get_block_fallback_size, transfer) - .clamp_between_extremums(min, max) + self.content_size( + Direction::Block, + ratio, + &get_inline_size, + &get_block_fallback_size, + ) }); let mut get_inline_content_size = || (*inline_content_size).into(); let mut get_block_content_size = || (*block_content_size).into(); diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index 60e9128cb86..f7b691dbcde 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -14,7 +14,7 @@ use style::Zero; use crate::geom::Size; use crate::style_ext::{Clamp, ComputedValuesExt, ContentBoxSizesAndPBM}; -use crate::{AuOrAuto, IndefiniteContainingBlock, LogicalVec2}; +use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2, SizeConstraint}; #[derive(PartialEq)] pub(crate) enum IntrinsicSizingMode { @@ -120,7 +120,7 @@ pub(crate) fn outer_inline( containing_block: &IndefiniteContainingBlock, auto_minimum: &LogicalVec2, auto_block_size_stretches_to_containing_block: bool, - get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> InlineContentSizesResult, + get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult, ) -> InlineContentSizesResult { let ContentBoxSizesAndPBM { content_box_size, @@ -140,7 +140,7 @@ pub(crate) fn outer_inline( .block .non_auto() .map(|v| Au::zero().max(v - pbm_sums.block)); - let block_size = if content_box_size.block.is_initial() && + let preferred_block_size = if content_box_size.block.is_initial() && auto_block_size_stretches_to_containing_block { depends_on_block_constraints = true; @@ -149,24 +149,18 @@ pub(crate) fn outer_inline( content_box_size .block .maybe_resolve_extrinsic(available_block_size) - } - .map(|block_size| { - let min_block_size = content_min_box_size - .block - .maybe_resolve_extrinsic(available_block_size) - .unwrap_or(auto_minimum.block); - let max_block_size = content_max_box_size - .block - .maybe_resolve_extrinsic(available_block_size); - block_size.clamp_between_extremums(min_block_size, max_block_size) - }) - .map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage); - let containing_block_for_children = - IndefiniteContainingBlock::new_for_writing_mode_and_block_size( - style.writing_mode, - block_size, - ); - get_content_size(&containing_block_for_children) + }; + let min_block_size = content_min_box_size + .block + .maybe_resolve_extrinsic(available_block_size) + .unwrap_or(auto_minimum.block); + let max_block_size = content_max_box_size + .block + .maybe_resolve_extrinsic(available_block_size); + get_content_size(&ConstraintSpace::new( + SizeConstraint::new(preferred_block_size, min_block_size, max_block_size), + style.writing_mode, + )) }); let resolve_non_initial = |inline_size| { Some(match inline_size { diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 9a521df1927..da49cc00015 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -16,7 +16,6 @@ use style::computed_values::empty_cells::T as EmptyCells; use style::computed_values::position::T as Position; use style::computed_values::table_layout::T as TableLayoutMode; use style::computed_values::visibility::T as Visibility; -use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{ BorderStyle, LengthPercentage as ComputedLengthPercentage, Percentage, @@ -40,7 +39,7 @@ use crate::positioned::{relative_adjustement, PositioningContext, PositioningCon use crate::sizing::{ContentSizes, InlineContentSizesResult}; use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; use crate::table::TableSlotCoordinates; -use crate::{ContainingBlock, IndefiniteContainingBlock}; +use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, WritingMode}; /// A result of a final or speculative layout of a single cell in /// the table. Note that this is only done for slots that are not @@ -301,9 +300,7 @@ impl<'a> TableLayout<'a> { .contents .inline_content_sizes( layout_context, - &IndefiniteContainingBlock::new_for_writing_mode( - cell.style.writing_mode, - ), + &ConstraintSpace::new_for_style(&cell.style), ) .sizes }; @@ -776,8 +773,13 @@ impl<'a> TableLayout<'a> { /// Compute CAPMIN: fn compute_caption_minimum_inline_size(&mut self, layout_context: &LayoutContext) -> Au { - let containing_block = - IndefiniteContainingBlock::new_for_writing_mode(self.table.style.writing_mode); + let containing_block = IndefiniteContainingBlock { + size: LogicalVec2 { + inline: AuOrAuto::Auto, + block: AuOrAuto::Auto, + }, + writing_mode: self.table.style.writing_mode, + }; self.table .captions .iter() @@ -2630,9 +2632,9 @@ impl Table { pub(crate) fn inline_content_sizes( &mut self, layout_context: &LayoutContext, - containing_block_for_children: &IndefiniteContainingBlock, + constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { - let writing_mode = containing_block_for_children.writing_mode; + let writing_mode = constraint_space.writing_mode; let mut layout = TableLayout::new(self); let mut table_content_sizes = layout.compute_grid_min_max(layout_context, writing_mode); diff --git a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-001.xht.ini b/tests/wpt/meta/css/css-sizing/box-sizing-replaced-001.xht.ini deleted file mode 100644 index 7c510f1cca1..00000000000 --- a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-001.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[box-sizing-replaced-001.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-002.xht.ini b/tests/wpt/meta/css/css-sizing/box-sizing-replaced-002.xht.ini deleted file mode 100644 index 57b7669455a..00000000000 --- a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-002.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[box-sizing-replaced-002.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-003.xht.ini b/tests/wpt/meta/css/css-sizing/box-sizing-replaced-003.xht.ini deleted file mode 100644 index ec1d85b6183..00000000000 --- a/tests/wpt/meta/css/css-sizing/box-sizing-replaced-003.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[box-sizing-replaced-003.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-017.html.ini b/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-017.html.ini deleted file mode 100644 index c88b667accd..00000000000 --- a/tests/wpt/meta/css/css-sizing/intrinsic-percent-replaced-017.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[intrinsic-percent-replaced-017.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-video.html.ini b/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-video.html.ini deleted file mode 100644 index 1d10c2cab40..00000000000 --- a/tests/wpt/meta/css/css-sizing/intrinsic-size-fallback-video.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[intrinsic-size-fallback-video.html] - [.wrapper 3] - expected: FAIL - - [.wrapper 4] - expected: FAIL