layout_2020: Implement align-content in flexbox

Align all flex lines per `align-content`.
This commit is contained in:
Pu Xingyu 2023-05-11 00:38:38 +08:00
parent 03574d8191
commit 4a65dd0425
2 changed files with 36 additions and 10 deletions

View file

@ -17,6 +17,7 @@ use crate::style_ext::ComputedValuesExt;
use crate::ContainingBlock;
use atomic_refcell::AtomicRefMut;
use std::cell::Cell;
use style::properties::longhands::align_content::computed_value::T as AlignContent;
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::box_sizing::computed_value::T as BoxSizing;
@ -46,6 +47,7 @@ struct FlexContext<'a> {
flex_axis: FlexAxis,
main_start_cross_start_sides_are: MainStartCrossStart,
container_definite_inner_size: FlexRelativeVec2<Option<Length>>,
align_content: AlignContent,
align_items: AlignItems,
justify_content: JustifyContent,
}
@ -261,6 +263,7 @@ fn layout<'context, 'boxes>(
FlexWrap::Nowrap | FlexWrap::Wrap => false,
FlexWrap::WrapReverse => true,
};
let align_content = containing_block.style.clone_align_content();
let align_items = containing_block.style.clone_align_items();
let justify_content = containing_block.style.clone_justify_content();
@ -272,6 +275,7 @@ fn layout<'context, 'boxes>(
container_max_cross_size,
container_is_single_line,
flex_axis,
align_content,
align_items,
justify_content,
main_start_cross_start_sides_are: MainStartCrossStart::from(
@ -315,30 +319,51 @@ fn layout<'context, 'boxes>(
|flex_context, mut line| line.layout(flex_context, container_main_size),
);
let content_cross_size = flex_lines
.iter()
.map(|line| line.cross_size)
.sum::<Length>();
// https://drafts.csswg.org/css-flexbox/#algo-cross-container
let container_cross_size = flex_context
.container_definite_inner_size
.cross
.unwrap_or_else(|| {
flex_lines
.iter()
.map(|line| line.cross_size)
.sum::<Length>()
})
.unwrap_or(content_cross_size)
.clamp_between_extremums(
flex_context.container_min_cross_size,
flex_context.container_max_cross_size,
);
// https://drafts.csswg.org/css-flexbox/#algo-line-align
// Align all flex lines per `align-content`.
let line_count = flex_lines.len();
let mut cross_start_position_cursor = Length::zero();
let line_interval = match flex_context.container_definite_inner_size.cross {
Some(cross_size) if line_count >= 2 => {
let free_space = cross_size - content_cross_size;
cross_start_position_cursor = match flex_context.align_content {
AlignContent::Center => free_space / 2.0,
AlignContent::SpaceAround => free_space / (line_count * 2) as CSSFloat,
AlignContent::FlexEnd => free_space,
_ => Length::zero(),
};
match flex_context.align_content {
AlignContent::SpaceBetween => free_space / (line_count - 1) as CSSFloat,
AlignContent::SpaceAround => free_space / line_count as CSSFloat,
_ => Length::zero(),
}
},
_ => Length::zero(),
};
let line_cross_start_positions = flex_lines
.iter()
.map(|line| {
// FIXME: “Align all flex lines per `align-content`.”
// For now we hard-code the behavior of `align-content: flex-start`.
let cross_start = cross_start_position_cursor;
let cross_end = cross_start + line.cross_size;
let cross_end = cross_start + line.cross_size + line_interval;
cross_start_position_cursor = cross_end;
cross_start
})

View file

@ -134,7 +134,8 @@ ${helpers.single_keyword(
${helpers.single_keyword(
"align-content",
"stretch flex-start flex-end center space-between space-around",
engines="servo-2013",
engines="servo-2013 servo-2020",
servo_2020_pref="layout.flexbox.enabled",
extra_prefixes="webkit",
spec="https://drafts.csswg.org/css-align/#propdef-align-content",
animation_value_type="discrete",