Use the proper aspect ratio in flexbox (#33256)

When computing the automatic minimum size, flex layout was using the
natural aspect ratio, ignoring the `aspect-ratio` property.

`ReplacedContent::inline_size_over_block_size_intrinsic_ratio()` is now
made private to avoid more accidental uses.

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-30 08:28:14 +02:00 committed by GitHub
parent 13cbcf614a
commit cd8b803368
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 57 additions and 28 deletions

View file

@ -9,6 +9,7 @@ use app_units::Au;
use atomic_refcell::AtomicRefMut; use atomic_refcell::AtomicRefMut;
use itertools::izip; use itertools::izip;
use style::computed_values::position::T as Position; use style::computed_values::position::T as Position;
use style::logical_geometry::Direction;
use style::properties::longhands::align_items::computed_value::T as AlignItems; use style::properties::longhands::align_items::computed_value::T as AlignItems;
use style::properties::longhands::align_self::computed_value::T as AlignSelf; use style::properties::longhands::align_self::computed_value::T as AlignSelf;
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing; use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
@ -2124,38 +2125,27 @@ 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, main_size_over_cross_size_intrinsic_ratio) = let (is_replaced, ratio) = match self.independent_formatting_context {
match self.independent_formatting_context { IndependentFormattingContext::NonReplaced(_) => (false, None),
IndependentFormattingContext::NonReplaced(_) => (false, None), IndependentFormattingContext::Replaced(ref replaced) => {
IndependentFormattingContext::Replaced(ref replaced) => { (true, replaced.preferred_aspect_ratio(containing_block))
let ratio = replaced },
.contents };
.inline_size_over_block_size_intrinsic_ratio( let main_axis = if cross_axis_is_item_block_axis {
self.independent_formatting_context.style(), Direction::Inline
) } else {
.map(|ratio| { Direction::Block
if cross_axis_is_item_block_axis { };
ratio
} else {
1.0 / ratio
}
});
(true, ratio)
},
};
// > **transferred size suggestion** // > **transferred size suggestion**
// > 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 ( let transferred_size_suggestion = match (ratio, content_box_size.cross) {
main_size_over_cross_size_intrinsic_ratio,
content_box_size.cross,
) {
(Some(ratio), AuOrAuto::LengthPercentage(cross_size)) => { (Some(ratio), AuOrAuto::LengthPercentage(cross_size)) => {
let cross_size = cross_size let cross_size = cross_size
.clamp_between_extremums(min_size.cross.auto_is(Au::zero), max_size.cross); .clamp_between_extremums(min_size.cross.auto_is(Au::zero), max_size.cross);
Some(cross_size.scale_by(ratio)) Some(ratio.compute_dependent_size(main_axis, cross_size))
}, },
_ => None, _ => None,
}; };
@ -2181,11 +2171,13 @@ impl FlexItemBox {
} else { } else {
block_content_size_callback(self) block_content_size_callback(self)
}; };
let content_size_suggestion = main_size_over_cross_size_intrinsic_ratio let content_size_suggestion = ratio
.map(|ratio| { .map(|ratio| {
main_content_size.clamp_between_extremums( main_content_size.clamp_between_extremums(
min_size.cross.auto_is(Au::zero).scale_by(ratio), ratio.compute_dependent_size(main_axis, min_size.cross.auto_is(Au::zero)),
max_size.cross.map(|l| l.scale_by(ratio)), max_size
.cross
.map(|l| ratio.compute_dependent_size(main_axis, l)),
) )
}) })
.unwrap_or(main_content_size); .unwrap_or(main_content_size);

View file

@ -238,7 +238,7 @@ impl ReplacedContent {
LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode()) LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode())
} }
pub(crate) fn inline_size_over_block_size_intrinsic_ratio( fn inline_size_over_block_size_intrinsic_ratio(
&self, &self,
style: &ComputedValues, style: &ComputedValues,
) -> Option<CSSFloat> { ) -> Option<CSSFloat> {

View file

@ -235020,6 +235020,19 @@
{} {}
] ]
], ],
"flex-aspect-ratio-055.html": [
"d512d84c866a283c5e36b61c62062bf72d2b44f4",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square-only.html",
"=="
]
],
{}
]
],
"floats-aspect-ratio-001.html": [ "floats-aspect-ratio-001.html": [
"53627d2134aacff311142d5513a5a662264143de", "53627d2134aacff311142d5513a5a662264143de",
[ [

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#min-size-auto">
<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
<meta name="assert" content="
The automatic minimum size makes the flex item be 50px wide (converted from the height through the aspect ratio).
Adding the borders, the flex container is then a 100x100 square.">
<style>
.flex {
display: inline-flex;
border: solid 25px green;
}
.flex img {
height: 50px;
flex: 0 0 0px;
aspect-ratio: 1 / 1;
}
</style>
<p>Test passes if there is a filled green square.</p>
<div class="flex">
<img src="support/20x50-green.png">
</div>