Refactor computation of preferred aspect ratios (#34416)

* Refactor computation of preferred aspect ratios

Computing min/max-content sizes required a ContainingBlock in order to
resolve the padding and border when determining the preferred aspect
ratio. However, all callers already knew the padding and border, so they
can compute the ratio themselves, and pass it directly instead of
the ContainingBlock.

Signed-off-by: Oriol Brufau <obrufau@igalia.com>

* Put preferred aspect ratio into ConstraintSpace

Signed-off-by: Oriol Brufau <obrufau@igalia.com>

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2024-11-29 12:40:52 +01:00 committed by GitHub
parent 16da1c2721
commit 19a7e95a6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 133 additions and 113 deletions

View file

@ -38,7 +38,7 @@ use crate::positioned::{
}; };
use crate::sizing::{ContentSizes, InlineContentSizesResult, IntrinsicSizingMode}; use crate::sizing::{ContentSizes, InlineContentSizesResult, IntrinsicSizingMode};
use crate::style_ext::{ use crate::style_ext::{
Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin, AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin,
}; };
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint}; use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint};
@ -84,6 +84,9 @@ struct FlexItem<'a> {
/// Whether or not the size of this [`FlexItem`] depends on its block constraints. /// Whether or not the size of this [`FlexItem`] depends on its block constraints.
depends_on_block_constraints: bool, depends_on_block_constraints: bool,
/// <https://drafts.csswg.org/css-sizing-4/#preferred-aspect-ratio>
preferred_aspect_ratio: Option<AspectRatio>,
} }
/// Child of a FlexContainer. Can either be absolutely positioned, or not. If not, /// Child of a FlexContainer. Can either be absolutely positioned, or not. If not,
@ -1105,6 +1108,7 @@ fn allocate_free_cross_space_for_flex_line(
impl<'a> FlexItem<'a> { impl<'a> FlexItem<'a> {
fn new(flex_context: &FlexContext, box_: &'a FlexItemBox) -> Self { fn new(flex_context: &FlexContext, box_: &'a FlexItemBox) -> Self {
let config = &flex_context.config;
let containing_block = flex_context.containing_block; let containing_block = flex_context.containing_block;
let parent_writing_mode = containing_block.style.writing_mode; let parent_writing_mode = containing_block.style.writing_mode;
let item_writing_mode = box_.style().writing_mode; let item_writing_mode = box_.style().writing_mode;
@ -1114,7 +1118,7 @@ impl<'a> FlexItem<'a> {
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis( let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
container_is_horizontal, container_is_horizontal,
item_is_horizontal, item_is_horizontal,
flex_context.config.flex_axis, config.flex_axis,
); );
let ContentBoxSizesAndPBMDeprecated { let ContentBoxSizesAndPBMDeprecated {
@ -1128,6 +1132,9 @@ impl<'a> FlexItem<'a> {
.content_box_sizes_and_padding_border_margin(&containing_block.into()) .content_box_sizes_and_padding_border_margin(&containing_block.into())
.into(); .into();
let preferred_aspect_ratio = box_
.independent_formatting_context
.preferred_aspect_ratio(&pbm.padding_border_sums);
let margin_auto_is_zero = flex_context.sides_to_flex_relative(pbm.margin.auto_is(Au::zero)); let margin_auto_is_zero = flex_context.sides_to_flex_relative(pbm.margin.auto_is(Au::zero));
let padding = flex_context.sides_to_flex_relative(pbm.padding); let padding = flex_context.sides_to_flex_relative(pbm.padding);
let border = flex_context.sides_to_flex_relative(pbm.border); let border = flex_context.sides_to_flex_relative(pbm.border);
@ -1138,9 +1145,8 @@ impl<'a> FlexItem<'a> {
cross: padding_border.cross, cross: padding_border.cross,
} + margin_auto_is_zero.sum_by_axis(); } + margin_auto_is_zero.sum_by_axis();
let item_with_auto_cross_size_stretches_to_container_size = flex_context let item_with_auto_cross_size_stretches_to_container_size =
.config config.item_with_auto_cross_size_stretches_to_container_size(box_.style(), &margin);
.item_with_auto_cross_size_stretches_to_container_size(box_.style(), &margin);
let flex_relative_content_box_size = flex_context.vec2_to_flex_relative(content_box_size); let flex_relative_content_box_size = flex_context.vec2_to_flex_relative(content_box_size);
let flex_relative_content_max_size = let flex_relative_content_max_size =
@ -1156,6 +1162,7 @@ impl<'a> FlexItem<'a> {
flex_relative_content_box_size, flex_relative_content_box_size,
flex_relative_content_min_size, flex_relative_content_min_size,
flex_relative_content_max_size, flex_relative_content_max_size,
preferred_aspect_ratio,
&pbm_auto_is_zero, &pbm_auto_is_zero,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
|item| { |item| {
@ -1167,6 +1174,7 @@ impl<'a> FlexItem<'a> {
content_box_size, content_box_size,
min_size_auto_is_zero, min_size_auto_is_zero,
content_max_box_size, content_max_box_size,
preferred_aspect_ratio,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
IntrinsicSizingMode::Size, IntrinsicSizingMode::Size,
) )
@ -1175,25 +1183,20 @@ impl<'a> FlexItem<'a> {
}), }),
cross: flex_relative_content_min_size.cross.auto_is(Au::zero), cross: flex_relative_content_min_size.cross.auto_is(Au::zero),
}; };
let align_self = AlignItems( let align_self = AlignItems(config.resolve_align_self_for_child(box_.style()));
flex_context
.config
.resolve_align_self_for_child(box_.style()),
);
let (flex_base_size, flex_base_size_is_definite) = box_.flex_base_size( let (flex_base_size, flex_base_size_is_definite) = box_.flex_base_size(
flex_context.layout_context, flex_context.layout_context,
&containing_block.into(),
flex_context.container_definite_inner_size, flex_context.container_definite_inner_size,
cross_axis_is_item_block_axis, cross_axis_is_item_block_axis,
flex_relative_content_box_size, flex_relative_content_box_size,
flex_relative_content_min_size, flex_relative_content_min_size,
flex_relative_content_max_size, flex_relative_content_max_size,
preferred_aspect_ratio,
padding_border, padding_border,
&pbm_auto_is_zero, &pbm_auto_is_zero,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
|item| { |item| {
let min_size = flex_context let min_size = config
.config
.flex_axis .flex_axis
.vec2_to_flow_relative(flex_relative_content_min_size); .vec2_to_flow_relative(flex_relative_content_min_size);
item.layout_for_block_content_size( item.layout_for_block_content_size(
@ -1202,6 +1205,7 @@ impl<'a> FlexItem<'a> {
content_box_size, content_box_size,
min_size, min_size,
content_max_box_size, content_max_box_size,
preferred_aspect_ratio,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
IntrinsicSizingMode::Size, IntrinsicSizingMode::Size,
) )
@ -1228,6 +1232,7 @@ impl<'a> FlexItem<'a> {
hypothetical_main_size, hypothetical_main_size,
align_self, align_self,
depends_on_block_constraints, depends_on_block_constraints,
preferred_aspect_ratio,
} }
} }
@ -1892,11 +1897,8 @@ impl FlexItem<'_> {
}), }),
}; };
let item_writing_mode = self let context = &self.box_.independent_formatting_context;
.box_ let item_writing_mode = context.style().writing_mode;
.independent_formatting_context
.style()
.writing_mode;
let item_is_horizontal = item_writing_mode.is_horizontal(); let item_is_horizontal = item_writing_mode.is_horizontal();
let flex_axis = flex_context.config.flex_axis; let flex_axis = flex_context.config.flex_axis;
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis( let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
@ -1922,14 +1924,10 @@ impl FlexItem<'_> {
let constraint_space = ConstraintSpace::new( let constraint_space = ConstraintSpace::new(
SizeConstraint::Definite(used_main_size), SizeConstraint::Definite(used_main_size),
item_writing_mode, item_writing_mode,
self.preferred_aspect_ratio,
); );
self.box_ context
.independent_formatting_context .inline_content_sizes(flex_context.layout_context, &constraint_space)
.inline_content_sizes(
flex_context.layout_context,
&constraint_space,
&containing_block.into(),
)
.sizes .sizes
.shrink_to_fit(stretch_size) .shrink_to_fit(stretch_size)
.clamp_between_extremums( .clamp_between_extremums(
@ -1951,13 +1949,14 @@ impl FlexItem<'_> {
}; };
let container_writing_mode = containing_block.style.writing_mode; let container_writing_mode = containing_block.style.writing_mode;
match &self.box_.independent_formatting_context { match context {
IndependentFormattingContext::Replaced(replaced) => { IndependentFormattingContext::Replaced(replaced) => {
let size = replaced let size = replaced
.contents .contents
.used_size_as_if_inline_element_from_content_box_sizes( .used_size_as_if_inline_element_from_content_box_sizes(
containing_block, containing_block,
&replaced.style, &replaced.style,
self.preferred_aspect_ratio,
LogicalVec2 { LogicalVec2 {
inline: Size::Numeric(inline_size), inline: Size::Numeric(inline_size),
block: block_size.non_auto().map_or(Size::Initial, Size::Numeric), block: block_size.non_auto().map_or(Size::Initial, Size::Numeric),
@ -2263,6 +2262,9 @@ impl FlexItemBox {
} = style } = style
.content_box_sizes_and_padding_border_margin(containing_block) .content_box_sizes_and_padding_border_margin(containing_block)
.into(); .into();
let preferred_aspect_ratio = self
.independent_formatting_context
.preferred_aspect_ratio(&pbm.padding_border_sums);
let padding = main_start_cross_start.sides_to_flex_relative(pbm.padding); let padding = main_start_cross_start.sides_to_flex_relative(pbm.padding);
let border = main_start_cross_start.sides_to_flex_relative(pbm.border); let border = main_start_cross_start.sides_to_flex_relative(pbm.border);
let margin = main_start_cross_start.sides_to_flex_relative(pbm.margin); let margin = main_start_cross_start.sides_to_flex_relative(pbm.margin);
@ -2283,6 +2285,7 @@ impl FlexItemBox {
flex_axis.vec2_to_flex_relative(content_box_size), flex_axis.vec2_to_flex_relative(content_box_size),
flex_axis.vec2_to_flex_relative(content_min_box_size), flex_axis.vec2_to_flex_relative(content_min_box_size),
flex_axis.vec2_to_flex_relative(content_max_box_size), flex_axis.vec2_to_flex_relative(content_max_box_size),
preferred_aspect_ratio,
&pbm_auto_is_zero, &pbm_auto_is_zero,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
|item| { |item| {
@ -2292,6 +2295,7 @@ impl FlexItemBox {
content_box_size, content_box_size,
content_min_box_size.map(|v| v.auto_is(Au::zero)), content_min_box_size.map(|v| v.auto_is(Au::zero)),
content_max_box_size, content_max_box_size,
preferred_aspect_ratio,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
IntrinsicSizingMode::Size, IntrinsicSizingMode::Size,
) )
@ -2315,6 +2319,7 @@ impl FlexItemBox {
content_box_size, content_box_size,
content_min_size_no_auto, content_min_size_no_auto,
content_max_box_size, content_max_box_size,
preferred_aspect_ratio,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
IntrinsicSizingMode::Size, IntrinsicSizingMode::Size,
) )
@ -2344,6 +2349,7 @@ impl FlexItemBox {
content_box_size, content_box_size,
content_min_size_no_auto, content_min_size_no_auto,
content_max_box_size, content_max_box_size,
preferred_aspect_ratio,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
IntrinsicSizingMode::Contribution, IntrinsicSizingMode::Contribution,
); );
@ -2359,7 +2365,6 @@ impl FlexItemBox {
// we compute the base sizes of the items twice. We should consider caching. // we compute the base sizes of the items twice. We should consider caching.
let (flex_base_size, _) = self.flex_base_size( let (flex_base_size, _) = self.flex_base_size(
layout_context, layout_context,
containing_block,
config config
.flex_axis .flex_axis
.vec2_to_flex_relative(containing_block.size.map(|v| v.non_auto())), .vec2_to_flex_relative(containing_block.size.map(|v| v.non_auto())),
@ -2367,6 +2372,7 @@ impl FlexItemBox {
content_box_size, content_box_size,
content_min_size_no_auto, content_min_size_no_auto,
content_max_size, content_max_size,
preferred_aspect_ratio,
padding_border, padding_border,
&pbm_auto_is_zero, &pbm_auto_is_zero,
item_with_auto_cross_size_stretches_to_container_size, item_with_auto_cross_size_stretches_to_container_size,
@ -2475,6 +2481,7 @@ impl FlexItemBox {
content_box_size: FlexRelativeVec2<AuOrAuto>, content_box_size: FlexRelativeVec2<AuOrAuto>,
min_size: FlexRelativeVec2<GenericLengthPercentageOrAuto<Au>>, min_size: FlexRelativeVec2<GenericLengthPercentageOrAuto<Au>>,
max_size: FlexRelativeVec2<Option<Au>>, max_size: FlexRelativeVec2<Option<Au>>,
preferred_aspect_ratio: Option<AspectRatio>,
pbm_auto_is_zero: &FlexRelativeVec2<Au>, pbm_auto_is_zero: &FlexRelativeVec2<Au>,
auto_cross_size_stretches_to_container_size: bool, auto_cross_size_stretches_to_container_size: bool,
block_content_size_callback: impl FnOnce(&FlexItemBox) -> Au, block_content_size_callback: impl FnOnce(&FlexItemBox) -> Au,
@ -2490,12 +2497,7 @@ impl FlexItemBox {
// > size suggestion is that size. It is otherwise undefined. // > size suggestion is that size. It is otherwise undefined.
let specified_size_suggestion = content_box_size.main.non_auto(); let specified_size_suggestion = content_box_size.main.non_auto();
let (is_replaced, ratio) = match self.independent_formatting_context { let is_replaced = self.independent_formatting_context.is_replaced();
IndependentFormattingContext::NonReplaced(_) => (false, None),
IndependentFormattingContext::Replaced(ref replaced) => {
(true, replaced.preferred_aspect_ratio(containing_block))
},
};
let main_axis = if cross_axis_is_item_block_axis { let main_axis = if cross_axis_is_item_block_axis {
Direction::Inline Direction::Inline
} else { } else {
@ -2522,7 +2524,7 @@ impl FlexItemBox {
// > If the item has a preferred aspect ratio and its preferred cross size is definite, then the // > 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 // > 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. // > are definite), converted through the aspect ratio. It is otherwise undefined.
let transferred_size_suggestion = match (ratio, cross_size) { let transferred_size_suggestion = match (preferred_aspect_ratio, cross_size) {
(Some(ratio), SizeConstraint::Definite(cross_size)) => { (Some(ratio), SizeConstraint::Definite(cross_size)) => {
Some(ratio.compute_dependent_size(main_axis, cross_size)) Some(ratio.compute_dependent_size(main_axis, cross_size))
}, },
@ -2535,15 +2537,16 @@ impl FlexItemBox {
// > aspect ratio. // > aspect ratio.
let main_content_size = if cross_axis_is_item_block_axis { let main_content_size = if cross_axis_is_item_block_axis {
let writing_mode = style.writing_mode; let writing_mode = style.writing_mode;
let constraint_space = ConstraintSpace::new(cross_size, writing_mode); let constraint_space =
ConstraintSpace::new(cross_size, writing_mode, preferred_aspect_ratio);
self.independent_formatting_context self.independent_formatting_context
.inline_content_sizes(layout_context, &constraint_space, containing_block) .inline_content_sizes(layout_context, &constraint_space)
.sizes .sizes
.min_content .min_content
} else { } else {
block_content_size_callback(self) block_content_size_callback(self)
}; };
let content_size_suggestion = ratio let content_size_suggestion = preferred_aspect_ratio
.map(|ratio| { .map(|ratio| {
main_content_size.clamp_between_extremums( main_content_size.clamp_between_extremums(
ratio.compute_dependent_size(main_axis, min_size.cross.auto_is(Au::zero)), ratio.compute_dependent_size(main_axis, min_size.cross.auto_is(Au::zero)),
@ -2573,12 +2576,12 @@ impl FlexItemBox {
fn flex_base_size( fn flex_base_size(
&self, &self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
containing_block: &IndefiniteContainingBlock,
container_definite_inner_size: FlexRelativeVec2<Option<Au>>, container_definite_inner_size: FlexRelativeVec2<Option<Au>>,
cross_axis_is_item_block_axis: bool, cross_axis_is_item_block_axis: bool,
content_box_size: FlexRelativeVec2<AuOrAuto>, content_box_size: FlexRelativeVec2<AuOrAuto>,
content_min_box_size: FlexRelativeVec2<Au>, content_min_box_size: FlexRelativeVec2<Au>,
content_max_box_size: FlexRelativeVec2<Option<Au>>, content_max_box_size: FlexRelativeVec2<Option<Au>>,
preferred_aspect_ratio: Option<AspectRatio>,
padding_border_sums: FlexRelativeVec2<Au>, padding_border_sums: FlexRelativeVec2<Au>,
pbm_auto_is_zero: &FlexRelativeVec2<Au>, pbm_auto_is_zero: &FlexRelativeVec2<Au>,
item_with_auto_cross_size_stretches_to_container_size: bool, item_with_auto_cross_size_stretches_to_container_size: bool,
@ -2649,7 +2652,6 @@ impl FlexItemBox {
// > - a used flex basis of content, and // > - a used flex basis of content, and
// > - a definite cross size, // > - a definite cross size,
// > then the flex base size is calculated from its used cross size and the flex items aspect ratio. // > then the flex base size is calculated from its used cross size and the flex items aspect ratio.
let ratio = flex_item.preferred_aspect_ratio(containing_block);
let main_axis = if cross_axis_is_item_block_axis { let main_axis = if cross_axis_is_item_block_axis {
Direction::Inline Direction::Inline
} else { } else {
@ -2667,7 +2669,7 @@ impl FlexItemBox {
} else { } else {
content_box_size.cross.non_auto() content_box_size.cross.non_auto()
}; };
if let (Some(ratio), Some(cross_size)) = (ratio, cross_size) { if let (Some(ratio), Some(cross_size)) = (preferred_aspect_ratio, cross_size) {
let cross_size = cross_size.clamp_between_extremums( let cross_size = cross_size.clamp_between_extremums(
content_min_box_size.cross, content_min_box_size.cross,
content_max_box_size.cross, content_max_box_size.cross,
@ -2694,12 +2696,13 @@ impl FlexItemBox {
content_max_box_size.cross, content_max_box_size.cross,
), ),
writing_mode, writing_mode,
preferred_aspect_ratio,
); );
let max_content = flex_item let max_content = flex_item
.inline_content_sizes(layout_context, &constraint_space, containing_block) .inline_content_sizes(layout_context, &constraint_space)
.sizes .sizes
.max_content; .max_content;
if let Some(ratio) = ratio { if let Some(ratio) = preferred_aspect_ratio {
max_content.clamp_between_extremums( max_content.clamp_between_extremums(
ratio.compute_dependent_size(main_axis, content_min_box_size.cross), ratio.compute_dependent_size(main_axis, content_min_box_size.cross),
content_max_box_size content_max_box_size
@ -2734,6 +2737,7 @@ impl FlexItemBox {
mut content_box_size: LogicalVec2<AuOrAuto>, mut content_box_size: LogicalVec2<AuOrAuto>,
mut min_size: LogicalVec2<Au>, mut min_size: LogicalVec2<Au>,
mut max_size: LogicalVec2<Option<Au>>, mut max_size: LogicalVec2<Option<Au>>,
preferred_aspect_ratio: Option<AspectRatio>,
item_with_auto_cross_size_stretches_to_container_size: bool, item_with_auto_cross_size_stretches_to_container_size: bool,
intrinsic_sizing_mode: IntrinsicSizingMode, intrinsic_sizing_mode: IntrinsicSizingMode,
) -> Au { ) -> Au {
@ -2756,6 +2760,7 @@ impl FlexItemBox {
.used_size_as_if_inline_element_from_content_box_sizes( .used_size_as_if_inline_element_from_content_box_sizes(
flex_context.containing_block, flex_context.containing_block,
&replaced.style, &replaced.style,
preferred_aspect_ratio,
content_box_size content_box_size
.map(|size| size.non_auto().map_or(Size::Initial, Size::Numeric)), .map(|size| size.non_auto().map_or(Size::Initial, Size::Numeric)),
min_size.map(|size| Size::Numeric(*size)), min_size.map(|size| Size::Numeric(*size)),
@ -2780,12 +2785,15 @@ impl FlexItemBox {
if item_with_auto_cross_size_stretches_to_container_size { if item_with_auto_cross_size_stretches_to_container_size {
containing_block_inline_size_minus_pbm containing_block_inline_size_minus_pbm
} else { } else {
let containing_block_for_children = let constraint_space = ConstraintSpace::new(
ConstraintSpace::new_for_style(&non_replaced.style); SizeConstraint::default(),
non_replaced.style.writing_mode,
non_replaced.preferred_aspect_ratio(),
);
non_replaced non_replaced
.inline_content_sizes( .inline_content_sizes(
flex_context.layout_context, flex_context.layout_context,
&containing_block_for_children, &constraint_space,
) )
.sizes .sizes
.shrink_to_fit(containing_block_inline_size_minus_pbm) .shrink_to_fit(containing_block_inline_size_minus_pbm)

View file

@ -1965,7 +1965,7 @@ impl IndependentFormattingContext {
// Lay out absolutely positioned children if this new atomic establishes a containing block // Lay out absolutely positioned children if this new atomic establishes a containing block
// for absolutes. // for absolutes.
let positioning_context = if matches!(self, IndependentFormattingContext::Replaced(_)) { let positioning_context = if self.is_replaced() {
None None
} else { } else {
if fragment if fragment

View file

@ -235,10 +235,13 @@ impl OutsideMarker {
sequential_layout_state: Option<&mut SequentialLayoutState>, sequential_layout_state: Option<&mut SequentialLayoutState>,
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>, collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
) -> Fragment { ) -> Fragment {
let content_sizes = self.block_container.inline_content_sizes( let constraint_space = ConstraintSpace::new_for_style_and_ratio(
layout_context, &self.marker_style,
&ConstraintSpace::new_for_style(&self.marker_style), None, /* TODO: support preferred aspect ratios on non-replaced boxes */
); );
let content_sizes = self
.block_container
.inline_content_sizes(layout_context, &constraint_space);
let containing_block_for_children = ContainingBlock { let containing_block_for_children = ContainingBlock {
inline_size: content_sizes.sizes.max_content, inline_size: content_sizes.sizes.max_content,
block_size: AuOrAuto::auto(), block_size: AuOrAuto::auto(),
@ -394,7 +397,8 @@ fn calculate_inline_content_size_for_block_level_boxes(
style, style,
containing_block, containing_block,
&LogicalVec2::zero(), &LogicalVec2::zero(),
false, /* auto_block_size_stretches_to_containing_block */ false, /* auto_block_size_stretches_to_containing_block */
|_| None, /* TODO: support preferred aspect ratios on non-replaced boxes */
|constraint_space| { |constraint_space| {
contents.inline_content_sizes(layout_context, constraint_space) contents.inline_content_sizes(layout_context, constraint_space)
}, },
@ -2054,7 +2058,11 @@ impl IndependentFormattingContext {
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size); SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
let content_size = LazyCell::new(|| { let content_size = LazyCell::new(|| {
let constraint_space = ConstraintSpace::new(tentative_block_size, writing_mode); let constraint_space = ConstraintSpace::new(
tentative_block_size,
writing_mode,
non_replaced.preferred_aspect_ratio(),
);
non_replaced non_replaced
.inline_content_sizes(layout_context, &constraint_space) .inline_content_sizes(layout_context, &constraint_space)
.sizes .sizes

View file

@ -185,6 +185,10 @@ impl IndependentFormattingContext {
} }
} }
pub fn is_replaced(&self) -> bool {
matches!(self, Self::Replaced(_))
}
pub fn style(&self) -> &Arc<ComputedValues> { pub fn style(&self) -> &Arc<ComputedValues> {
match self { match self {
Self::NonReplaced(inner) => &inner.style, Self::NonReplaced(inner) => &inner.style,
@ -203,17 +207,14 @@ impl IndependentFormattingContext {
&self, &self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
constraint_space: &ConstraintSpace, constraint_space: &ConstraintSpace,
containing_block: &IndefiniteContainingBlock,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
match self { match self {
Self::NonReplaced(inner) => { Self::NonReplaced(inner) => {
inner.inline_content_sizes(layout_context, constraint_space) inner.inline_content_sizes(layout_context, constraint_space)
}, },
Self::Replaced(inner) => inner.contents.inline_content_sizes( Self::Replaced(inner) => inner
layout_context, .contents
constraint_space, .inline_content_sizes(layout_context, constraint_space),
inner.preferred_aspect_ratio(containing_block),
),
} }
} }
@ -236,12 +237,11 @@ impl IndependentFormattingContext {
containing_block, containing_block,
auto_minimum, auto_minimum,
auto_block_size_stretches_to_containing_block, auto_block_size_stretches_to_containing_block,
|padding_border_sums| replaced.preferred_aspect_ratio(padding_border_sums),
|constraint_space| { |constraint_space| {
replaced.contents.inline_content_sizes( replaced
layout_context, .contents
constraint_space, .inline_content_sizes(layout_context, constraint_space)
replaced.preferred_aspect_ratio(containing_block),
)
}, },
), ),
} }
@ -249,11 +249,11 @@ impl IndependentFormattingContext {
pub(crate) fn preferred_aspect_ratio( pub(crate) fn preferred_aspect_ratio(
&self, &self,
containing_block: &IndefiniteContainingBlock, padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> { ) -> Option<AspectRatio> {
match self { match self {
Self::NonReplaced(_) => None, Self::NonReplaced(non_replaced) => non_replaced.preferred_aspect_ratio(),
Self::Replaced(replaced) => replaced.preferred_aspect_ratio(containing_block), Self::Replaced(replaced) => replaced.preferred_aspect_ratio(padding_border_sums),
} }
} }
} }
@ -293,6 +293,12 @@ impl NonReplacedFormattingContext {
} }
} }
#[inline]
pub(crate) fn preferred_aspect_ratio(&self) -> Option<AspectRatio> {
// TODO: support preferred aspect ratios on non-replaced boxes.
None
}
pub(crate) fn inline_content_sizes( pub(crate) fn inline_content_sizes(
&self, &self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
@ -327,6 +333,7 @@ impl NonReplacedFormattingContext {
containing_block, containing_block,
auto_minimum, auto_minimum,
auto_block_size_stretches_to_containing_block, auto_block_size_stretches_to_containing_block,
|_| self.preferred_aspect_ratio(),
|constraint_space| self.inline_content_sizes(layout_context, constraint_space), |constraint_space| self.inline_content_sizes(layout_context, constraint_space),
) )
} }
@ -352,9 +359,9 @@ impl NonReplacedFormattingContextContents {
impl ReplacedFormattingContext { impl ReplacedFormattingContext {
pub(crate) fn preferred_aspect_ratio( pub(crate) fn preferred_aspect_ratio(
&self, &self,
containing_block: &IndefiniteContainingBlock, padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> { ) -> Option<AspectRatio> {
self.contents self.contents
.preferred_aspect_ratio(containing_block, &self.style) .preferred_aspect_ratio(&self.style, padding_border_sums)
} }
} }

View file

@ -35,24 +35,38 @@ use style::logical_geometry::WritingMode;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use crate::geom::{LogicalVec2, SizeConstraint}; use crate::geom::{LogicalVec2, SizeConstraint};
use crate::style_ext::AspectRatio;
/// Represents the set of constraints that we use when computing the min-content /// Represents the set of constraints that we use when computing the min-content
/// and max-content inline sizes of an element. /// and max-content inline sizes of an element.
pub(crate) struct ConstraintSpace { pub(crate) struct ConstraintSpace {
pub block_size: SizeConstraint, pub block_size: SizeConstraint,
pub writing_mode: WritingMode, pub writing_mode: WritingMode,
pub preferred_aspect_ratio: Option<AspectRatio>,
} }
impl ConstraintSpace { impl ConstraintSpace {
fn new(block_size: SizeConstraint, writing_mode: WritingMode) -> Self { fn new(
block_size: SizeConstraint,
writing_mode: WritingMode,
preferred_aspect_ratio: Option<AspectRatio>,
) -> Self {
Self { Self {
block_size, block_size,
writing_mode, writing_mode,
preferred_aspect_ratio,
} }
} }
fn new_for_style(style: &ComputedValues) -> Self { fn new_for_style_and_ratio(
Self::new(SizeConstraint::default(), style.writing_mode) style: &ComputedValues,
preferred_aspect_ratio: Option<AspectRatio>,
) -> Self {
Self::new(
SizeConstraint::default(),
style.writing_mode,
preferred_aspect_ratio,
)
} }
} }

View file

@ -550,9 +550,10 @@ impl HoistedAbsolutelyPositionedBox {
// The inline axis can be fully resolved, computing intrinsic sizes using the // The inline axis can be fully resolved, computing intrinsic sizes using the
// tentative block size. // tentative block size.
let mut inline_axis = inline_axis_solver.solve(Some(|| { let mut inline_axis = inline_axis_solver.solve(Some(|| {
let constraint_space = ConstraintSpace::new(block_axis.size, style.writing_mode); let ratio = context.preferred_aspect_ratio(&pbm.padding_border_sums);
let constraint_space = ConstraintSpace::new(block_axis.size, style.writing_mode, ratio);
context context
.inline_content_sizes(layout_context, &constraint_space, &containing_block.into()) .inline_content_sizes(layout_context, &constraint_space)
.sizes .sizes
})); }));

View file

@ -31,7 +31,7 @@ use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFrag
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size}; use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size};
use crate::sizing::{ContentSizes, InlineContentSizesResult}; use crate::sizing::{ContentSizes, InlineContentSizesResult};
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM}; use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint}; use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct ReplacedContent { pub(crate) struct ReplacedContent {
@ -282,7 +282,6 @@ impl ReplacedContent {
&self, &self,
_: &LayoutContext, _: &LayoutContext,
constraint_space: &ConstraintSpace, constraint_space: &ConstraintSpace,
preferred_aspect_ratio: Option<AspectRatio>,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
let get_inline_fallback_size = || { let get_inline_fallback_size = || {
let writing_mode = constraint_space.writing_mode; let writing_mode = constraint_space.writing_mode;
@ -292,13 +291,13 @@ impl ReplacedContent {
}; };
let inline_content_size = self.content_size( let inline_content_size = self.content_size(
Direction::Inline, Direction::Inline,
preferred_aspect_ratio, constraint_space.preferred_aspect_ratio,
&|| constraint_space.block_size, &|| constraint_space.block_size,
&get_inline_fallback_size, &get_inline_fallback_size,
); );
InlineContentSizesResult { InlineContentSizesResult {
sizes: inline_content_size.into(), sizes: inline_content_size.into(),
depends_on_block_constraints: preferred_aspect_ratio.is_some(), depends_on_block_constraints: constraint_space.preferred_aspect_ratio.is_some(),
} }
} }
@ -417,13 +416,13 @@ impl ReplacedContent {
pub(crate) fn preferred_aspect_ratio( pub(crate) fn preferred_aspect_ratio(
&self, &self,
containing_block: &IndefiniteContainingBlock,
style: &ComputedValues, style: &ComputedValues,
padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> { ) -> Option<AspectRatio> {
style style
.preferred_aspect_ratio( .preferred_aspect_ratio(
self.inline_size_over_block_size_intrinsic_ratio(style), self.inline_size_over_block_size_intrinsic_ratio(style),
containing_block, padding_border_sums,
) )
.or_else(|| { .or_else(|| {
matches!(self.kind, ReplacedContentKind::Video(_)).then(|| { matches!(self.kind, ReplacedContentKind::Video(_)).then(|| {
@ -450,6 +449,7 @@ impl ReplacedContent {
self.used_size_as_if_inline_element_from_content_box_sizes( self.used_size_as_if_inline_element_from_content_box_sizes(
containing_block, containing_block,
style, style,
self.preferred_aspect_ratio(style, &pbm.padding_border_sums),
content_box_sizes_and_pbm.content_box_size, content_box_sizes_and_pbm.content_box_size,
content_box_sizes_and_pbm.content_min_box_size, content_box_sizes_and_pbm.content_min_box_size,
content_box_sizes_and_pbm.content_max_box_size, content_box_sizes_and_pbm.content_max_box_size,
@ -492,18 +492,17 @@ impl ReplacedContent {
/// ///
/// <https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers> /// <https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers>
/// <https://github.com/w3c/csswg-drafts/issues/6071#issuecomment-2243986313> /// <https://github.com/w3c/csswg-drafts/issues/6071#issuecomment-2243986313>
#[allow(clippy::too_many_arguments)]
pub(crate) fn used_size_as_if_inline_element_from_content_box_sizes( pub(crate) fn used_size_as_if_inline_element_from_content_box_sizes(
&self, &self,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
style: &ComputedValues, style: &ComputedValues,
preferred_aspect_ratio: Option<AspectRatio>,
box_size: LogicalVec2<Size<Au>>, box_size: LogicalVec2<Size<Au>>,
min_box_size: LogicalVec2<Size<Au>>, min_box_size: LogicalVec2<Size<Au>>,
max_box_size: LogicalVec2<Size<Au>>, max_box_size: LogicalVec2<Size<Au>>,
pbm_sums: LogicalVec2<Au>, pbm_sums: LogicalVec2<Au>,
) -> LogicalVec2<Au> { ) -> LogicalVec2<Au> {
// <https://drafts.csswg.org/css-sizing-4/#preferred-aspect-ratio>
let ratio = self.preferred_aspect_ratio(&containing_block.into(), style);
// <https://drafts.csswg.org/css-images-3/#natural-dimensions> // <https://drafts.csswg.org/css-images-3/#natural-dimensions>
// <https://drafts.csswg.org/css-images-3/#default-object-size> // <https://drafts.csswg.org/css-images-3/#default-object-size>
let writing_mode = style.writing_mode; let writing_mode = style.writing_mode;
@ -549,7 +548,7 @@ impl ReplacedContent {
}; };
self.content_size( self.content_size(
Direction::Inline, Direction::Inline,
ratio, preferred_aspect_ratio,
&get_block_size, &get_block_size,
&get_inline_fallback_size, &get_inline_fallback_size,
) )
@ -581,7 +580,7 @@ impl ReplacedContent {
}; };
self.content_size( self.content_size(
Direction::Block, Direction::Block,
ratio, preferred_aspect_ratio,
&get_inline_size, &get_inline_size,
&get_block_fallback_size, &get_block_fallback_size,
) )

View file

@ -13,7 +13,7 @@ use style::properties::ComputedValues;
use style::Zero; use style::Zero;
use crate::geom::Size; use crate::geom::Size;
use crate::style_ext::{Clamp, ComputedValuesExt, ContentBoxSizesAndPBM}; use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2, SizeConstraint}; use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2, SizeConstraint};
#[derive(PartialEq)] #[derive(PartialEq)]
@ -113,6 +113,7 @@ pub(crate) fn outer_inline(
containing_block: &IndefiniteContainingBlock, containing_block: &IndefiniteContainingBlock,
auto_minimum: &LogicalVec2<Au>, auto_minimum: &LogicalVec2<Au>,
auto_block_size_stretches_to_containing_block: bool, auto_block_size_stretches_to_containing_block: bool,
get_preferred_aspect_ratio: impl FnOnce(&LogicalVec2<Au>) -> Option<AspectRatio>,
get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult, get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
let ContentBoxSizesAndPBM { let ContentBoxSizesAndPBM {
@ -153,6 +154,7 @@ pub(crate) fn outer_inline(
get_content_size(&ConstraintSpace::new( get_content_size(&ConstraintSpace::new(
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size), SizeConstraint::new(preferred_block_size, min_block_size, max_block_size),
style.writing_mode, style.writing_mode,
get_preferred_aspect_ratio(&pbm.padding_border_sums),
)) ))
}); });
let resolve_non_initial = |inline_size| { let resolve_non_initial = |inline_size| {

View file

@ -281,10 +281,6 @@ pub(crate) trait ComputedValuesExt {
containing_block: &IndefiniteContainingBlock, containing_block: &IndefiniteContainingBlock,
) -> ContentBoxSizesAndPBM; ) -> ContentBoxSizesAndPBM;
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin; fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
fn padding_border_margin_for_intrinsic_size(
&self,
writing_mode: WritingMode,
) -> PaddingBorderMargin;
fn padding_border_margin_with_writing_mode_and_containing_block_inline_size( fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
&self, &self,
writing_mode: WritingMode, writing_mode: WritingMode,
@ -319,7 +315,7 @@ pub(crate) trait ComputedValuesExt {
fn preferred_aspect_ratio( fn preferred_aspect_ratio(
&self, &self,
natural_aspect_ratio: Option<CSSFloat>, natural_aspect_ratio: Option<CSSFloat>,
containing_block: &IndefiniteContainingBlock, padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio>; ) -> Option<AspectRatio>;
fn background_is_transparent(&self) -> bool; fn background_is_transparent(&self) -> bool;
fn get_webrender_primitive_flags(&self) -> wr::PrimitiveFlags; fn get_webrender_primitive_flags(&self) -> wr::PrimitiveFlags;
@ -579,16 +575,6 @@ impl ComputedValuesExt for ComputedValues {
) )
} }
fn padding_border_margin_for_intrinsic_size(
&self,
writing_mode: WritingMode,
) -> PaddingBorderMargin {
self.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
writing_mode,
Au::zero(),
)
}
fn padding_border_margin_with_writing_mode_and_containing_block_inline_size( fn padding_border_margin_with_writing_mode_and_containing_block_inline_size(
&self, &self,
writing_mode: WritingMode, writing_mode: WritingMode,
@ -878,7 +864,7 @@ impl ComputedValuesExt for ComputedValues {
fn preferred_aspect_ratio( fn preferred_aspect_ratio(
&self, &self,
natural_aspect_ratio: Option<CSSFloat>, natural_aspect_ratio: Option<CSSFloat>,
containing_block: &IndefiniteContainingBlock, padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> { ) -> Option<AspectRatio> {
let GenericAspectRatio { let GenericAspectRatio {
auto, auto,
@ -921,15 +907,7 @@ impl ComputedValuesExt for ComputedValues {
// border when calculating the aspect ratio. // border when calculating the aspect ratio.
let box_sizing_adjustment = match self.clone_box_sizing() { let box_sizing_adjustment = match self.clone_box_sizing() {
BoxSizing::ContentBox => LogicalVec2::zero(), BoxSizing::ContentBox => LogicalVec2::zero(),
BoxSizing::BorderBox => containing_block.size.inline.non_auto().map_or_else( BoxSizing::BorderBox => *padding_border_sums,
|| self.padding_border_margin_for_intrinsic_size(containing_block.writing_mode),
|containing_block_inline_size| self
.padding_border_margin_with_writing_mode_and_containing_block_inline_size(
containing_block.writing_mode,
containing_block_inline_size,
)
)
.padding_border_sums,
}; };
Some(AspectRatio { Some(AspectRatio {
i_over_b: (preferred_ratio.0).0 / (preferred_ratio.1).0, i_over_b: (preferred_ratio.0).0 / (preferred_ratio.1).0,

View file

@ -296,12 +296,13 @@ impl<'a> TableLayout<'a> {
let mut inline_content_sizes = if is_in_fixed_mode { let mut inline_content_sizes = if is_in_fixed_mode {
ContentSizes::zero() ContentSizes::zero()
} else { } else {
let constraint_space = ConstraintSpace::new_for_style_and_ratio(
&cell.style,
None, /* TODO: support preferred aspect ratios on non-replaced boxes */
);
cell.contents cell.contents
.contents .contents
.inline_content_sizes( .inline_content_sizes(layout_context, &constraint_space)
layout_context,
&ConstraintSpace::new_for_style(&cell.style),
)
.sizes .sizes
}; };
inline_content_sizes.min_content += padding_border_sums.inline; inline_content_sizes.min_content += padding_border_sums.inline;

View file

@ -156,6 +156,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
.used_size_as_if_inline_element_from_content_box_sizes( .used_size_as_if_inline_element_from_content_box_sizes(
containing_block, containing_block,
&replaced.style, &replaced.style,
replaced.preferred_aspect_ratio(&pbm.padding_border_sums),
LogicalVec2 { LogicalVec2 {
inline: option_f32_to_size(content_box_known_dimensions.width), inline: option_f32_to_size(content_box_known_dimensions.width),
block: option_f32_to_size(content_box_known_dimensions.height), block: option_f32_to_size(content_box_known_dimensions.height),
@ -226,6 +227,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
None, None,
), ),
writing_mode: self.style.writing_mode, writing_mode: self.style.writing_mode,
preferred_aspect_ratio: non_replaced.preferred_aspect_ratio(),
}; };
let result = non_replaced let result = non_replaced