mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
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:
parent
13cbcf614a
commit
cd8b803368
4 changed files with 57 additions and 28 deletions
|
@ -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);
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
13
tests/wpt/meta/MANIFEST.json
vendored
13
tests/wpt/meta/MANIFEST.json
vendored
|
@ -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",
|
||||||
[
|
[
|
||||||
|
|
24
tests/wpt/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-055.html
vendored
Normal file
24
tests/wpt/tests/css/css-sizing/aspect-ratio/flex-aspect-ratio-055.html
vendored
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue