mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
layout: Partial support for keyword sizes on preferred cross size (#35682)
This changes `FlexItem::content_cross_size` into `Size<Au>` to preserve keyword sizes. The calculation of the hypothetical cross size still ignores them though, that will be addressed in a follow-up. Also, browsers don't follow the spec and treat a stretch size different than a stretch alignment: the former stretches to the containing block, while the latter stretches to the line. This aligns Servo with that behavior (following the spec would require bigger refactorings), so `stretches()` is renamed to `stretches_to_line()` for clarity. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
f3e6e4f04e
commit
ff5683680f
6 changed files with 84 additions and 113 deletions
|
@ -62,7 +62,7 @@ struct FlexContext<'a> {
|
||||||
/// A flex item with some intermediate results
|
/// A flex item with some intermediate results
|
||||||
struct FlexItem<'a> {
|
struct FlexItem<'a> {
|
||||||
box_: &'a FlexItemBox,
|
box_: &'a FlexItemBox,
|
||||||
content_cross_size: AuOrAuto,
|
content_cross_size: Size<Au>,
|
||||||
content_min_size: FlexRelativeVec2<Au>,
|
content_min_size: FlexRelativeVec2<Au>,
|
||||||
content_max_size: FlexRelativeVec2<Option<Au>>,
|
content_max_size: FlexRelativeVec2<Option<Au>>,
|
||||||
padding: FlexRelativeSides<Au>,
|
padding: FlexRelativeSides<Au>,
|
||||||
|
@ -1222,8 +1222,7 @@ impl<'a> FlexItem<'a> {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
box_,
|
box_,
|
||||||
// TODO(#32853): handle size keywords.
|
content_cross_size: flex_relative_content_box_size.cross,
|
||||||
content_cross_size: flex_relative_content_box_size.cross.to_auto_or(),
|
|
||||||
content_min_size: flex_relative_content_min_size,
|
content_min_size: flex_relative_content_min_size,
|
||||||
content_max_size: flex_relative_content_max_size,
|
content_max_size: flex_relative_content_max_size,
|
||||||
padding,
|
padding,
|
||||||
|
@ -1239,8 +1238,11 @@ impl<'a> FlexItem<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stretches(&self) -> bool {
|
fn stretches_to_line(&self) -> bool {
|
||||||
self.content_cross_size.is_auto() &&
|
// Note this returns false for a `stretch` size, because that stretches to the
|
||||||
|
// containing block, not to the flex line.
|
||||||
|
// To be discussed in https://github.com/w3c/csswg-drafts/issues/11784.
|
||||||
|
self.content_cross_size.is_initial() &&
|
||||||
item_with_auto_cross_size_stretches_to_line_size(self.align_self, &self.margin)
|
item_with_auto_cross_size_stretches_to_line_size(self.align_self, &self.margin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1693,7 +1695,7 @@ impl InitialFlexLineLayout<'_> {
|
||||||
let mut item_used_cross_sizes = Vec::with_capacity(item_count);
|
let mut item_used_cross_sizes = Vec::with_capacity(item_count);
|
||||||
let mut item_margins = Vec::with_capacity(item_count);
|
let mut item_margins = Vec::with_capacity(item_count);
|
||||||
for item in self.items.iter_mut() {
|
for item in self.items.iter_mut() {
|
||||||
let stretches = item.item.stretches();
|
let stretches = item.item.stretches_to_line();
|
||||||
let used_cross_size = if stretches {
|
let used_cross_size = if stretches {
|
||||||
(final_line_cross_size - item.item.pbm_auto_is_zero.cross).clamp_between_extremums(
|
(final_line_cross_size - item.item.pbm_auto_is_zero.cross).clamp_between_extremums(
|
||||||
item.item.content_min_size.cross,
|
item.item.content_min_size.cross,
|
||||||
|
@ -1885,15 +1887,6 @@ impl FlexItem<'_> {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let cross_size = match used_cross_size_override {
|
|
||||||
Some(s) => SizeConstraint::Definite(s),
|
|
||||||
None => SizeConstraint::new(
|
|
||||||
self.content_cross_size.non_auto(),
|
|
||||||
self.content_min_size.cross,
|
|
||||||
self.content_max_size.cross,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let independent_formatting_context = &self.box_.independent_formatting_context;
|
let independent_formatting_context = &self.box_.independent_formatting_context;
|
||||||
let item_writing_mode = independent_formatting_context.style().writing_mode;
|
let item_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();
|
||||||
|
@ -1905,19 +1898,40 @@ impl FlexItem<'_> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let (inline_size, block_size) = if cross_axis_is_item_block_axis {
|
let (inline_size, block_size) = if cross_axis_is_item_block_axis {
|
||||||
|
let cross_size = match used_cross_size_override {
|
||||||
|
Some(s) => SizeConstraint::Definite(s),
|
||||||
|
None => {
|
||||||
|
// This means that an auto size with stretch alignment will behave different than
|
||||||
|
// a stretch size. That's not what the spec says, but matches other browsers.
|
||||||
|
// To be discussed in https://github.com/w3c/csswg-drafts/issues/11784.
|
||||||
|
let stretch_size = containing_block
|
||||||
|
.size
|
||||||
|
.block
|
||||||
|
.to_definite()
|
||||||
|
.map(|size| Au::zero().max(size - self.pbm_auto_is_zero.cross));
|
||||||
|
SizeConstraint::new(
|
||||||
|
self.content_cross_size
|
||||||
|
.maybe_resolve_extrinsic(stretch_size),
|
||||||
|
self.content_min_size.cross,
|
||||||
|
self.content_max_size.cross,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
};
|
||||||
(used_main_size, cross_size)
|
(used_main_size, cross_size)
|
||||||
} else {
|
} else {
|
||||||
(
|
let cross_size = used_cross_size_override.unwrap_or_else(|| {
|
||||||
cross_size.to_definite().unwrap_or_else(|| {
|
let style = self.box_.style();
|
||||||
let style = self.box_.style();
|
let automatic_size = if flex_context
|
||||||
let stretch_size =
|
.config
|
||||||
Au::zero().max(containing_block.size.inline - self.pbm_auto_is_zero.cross);
|
.item_with_auto_cross_size_stretches_to_container_size(style, &self.margin)
|
||||||
if flex_context
|
{
|
||||||
.config
|
Size::Stretch
|
||||||
.item_with_auto_cross_size_stretches_to_container_size(style, &self.margin)
|
} else {
|
||||||
{
|
Size::FitContent
|
||||||
return stretch_size;
|
};
|
||||||
}
|
let stretch_size =
|
||||||
|
Au::zero().max(containing_block.size.inline - self.pbm_auto_is_zero.cross);
|
||||||
|
let content_size = LazyCell::new(|| {
|
||||||
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,
|
||||||
|
@ -1926,26 +1940,28 @@ impl FlexItem<'_> {
|
||||||
independent_formatting_context
|
independent_formatting_context
|
||||||
.inline_content_sizes(flex_context.layout_context, &constraint_space)
|
.inline_content_sizes(flex_context.layout_context, &constraint_space)
|
||||||
.sizes
|
.sizes
|
||||||
.shrink_to_fit(stretch_size)
|
});
|
||||||
.clamp_between_extremums(
|
self.content_cross_size
|
||||||
self.content_min_size.cross,
|
.resolve_for_preferred(automatic_size, Some(stretch_size), &content_size)
|
||||||
self.content_max_size.cross,
|
.clamp_between_extremums(
|
||||||
)
|
self.content_min_size.cross,
|
||||||
}),
|
self.content_max_size.cross,
|
||||||
// The main size of a flex item is considered to be definite if its flex basis is definite
|
)
|
||||||
// or the flex container has a definite main size.
|
});
|
||||||
// <https://drafts.csswg.org/css-flexbox-1/#definite-sizes>
|
// The main size of a flex item is considered to be definite if its flex basis is definite
|
||||||
if self.flex_base_size_is_definite ||
|
// or the flex container has a definite main size.
|
||||||
flex_context
|
// <https://drafts.csswg.org/css-flexbox-1/#definite-sizes>
|
||||||
.container_inner_size_constraint
|
let main_size = if self.flex_base_size_is_definite ||
|
||||||
.main
|
flex_context
|
||||||
.is_definite()
|
.container_inner_size_constraint
|
||||||
{
|
.main
|
||||||
SizeConstraint::Definite(used_main_size)
|
.is_definite()
|
||||||
} else {
|
{
|
||||||
SizeConstraint::default()
|
SizeConstraint::Definite(used_main_size)
|
||||||
},
|
} else {
|
||||||
)
|
SizeConstraint::default()
|
||||||
|
};
|
||||||
|
(cross_size, main_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
let container_writing_mode = containing_block.style.writing_mode;
|
let container_writing_mode = containing_block.style.writing_mode;
|
||||||
|
@ -2013,13 +2029,13 @@ impl FlexItem<'_> {
|
||||||
},
|
},
|
||||||
IndependentFormattingContextContents::NonReplaced(non_replaced) => {
|
IndependentFormattingContextContents::NonReplaced(non_replaced) => {
|
||||||
let calculate_hypothetical_cross_size = |content_block_size| {
|
let calculate_hypothetical_cross_size = |content_block_size| {
|
||||||
|
// TODO(#32853): handle size keywords.
|
||||||
self.content_cross_size
|
self.content_cross_size
|
||||||
.auto_is(|| {
|
.to_numeric()
|
||||||
if cross_axis_is_item_block_axis {
|
.unwrap_or(if cross_axis_is_item_block_axis {
|
||||||
content_block_size
|
content_block_size
|
||||||
} else {
|
} else {
|
||||||
inline_size
|
inline_size
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.clamp_between_extremums(
|
.clamp_between_extremums(
|
||||||
self.content_min_size.cross,
|
self.content_min_size.cross,
|
||||||
|
@ -2069,7 +2085,7 @@ impl FlexItem<'_> {
|
||||||
..
|
..
|
||||||
} = layout;
|
} = layout;
|
||||||
let depends_on_block_constraints = depends_on_block_constraints ||
|
let depends_on_block_constraints = depends_on_block_constraints ||
|
||||||
(flex_axis == FlexAxis::Row && self.stretches());
|
(flex_axis == FlexAxis::Row && self.stretches_to_line());
|
||||||
|
|
||||||
let has_child_which_depends_on_block_constraints = fragments.iter().any(|fragment| {
|
let has_child_which_depends_on_block_constraints = fragments.iter().any(|fragment| {
|
||||||
fragment.base().is_some_and(|base|
|
fragment.base().is_some_and(|base|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[orthogonal-writing-modes-and-intrinsic-sizing.html]
|
|
||||||
[.flexbox 2]
|
|
||||||
expected: FAIL
|
|
|
@ -53,15 +53,6 @@
|
||||||
[.test 27]
|
[.test 27]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[.test 28]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 29]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 30]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 31]
|
[.test 31]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -98,6 +89,15 @@
|
||||||
[.test 45]
|
[.test 45]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[.test 46]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[.test 47]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[.test 48]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
[.test 49]
|
[.test 49]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -116,24 +116,6 @@
|
||||||
[.test 54]
|
[.test 54]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[.test 57]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 58]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 59]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 66]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 67]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 68]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 69]
|
[.test 69]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,4 @@
|
||||||
[keyword-sizes-on-flex-item-002.html]
|
[keyword-sizes-on-flex-item-002.html]
|
||||||
[.test 1]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 2]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 3]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 4]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 6]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 7]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 8]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 9]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[.test 10]
|
[.test 10]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
[[data-expected-height\] 8]
|
[[data-expected-height\] 8]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[[data-expected-height\] 19]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
[[data-expected-height\] 21]
|
[[data-expected-height\] 21]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -11,6 +14,9 @@
|
||||||
[[data-expected-height\] 31]
|
[[data-expected-height\] 31]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[[data-expected-height\] 42]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
[[data-expected-height\] 44]
|
[[data-expected-height\] 44]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,11 @@
|
||||||
[[data-expected-width\] 8]
|
[[data-expected-width\] 8]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[[data-expected-width\] 21]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[[data-expected-width\] 22]
|
[[data-expected-width\] 22]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[[data-expected-width\] 31]
|
[[data-expected-width\] 31]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[[data-expected-width\] 44]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[[data-expected-width\] 45]
|
[[data-expected-width\] 45]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue