From 4a65dd0425f1ee799e5583da8223f040b024afd2 Mon Sep 17 00:00:00 2001 From: Pu Xingyu Date: Thu, 11 May 2023 00:38:38 +0800 Subject: [PATCH] layout_2020: Implement align-content in flexbox Align all flex lines per `align-content`. --- components/layout_2020/flexbox/layout.rs | 43 +++++++++++++++---- .../properties/longhands/position.mako.rs | 3 +- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 983dcc79eff..8826622276c 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -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>, + 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::(); + // 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::() - }) + .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 }) diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs index 700c964d289..df118faed1a 100644 --- a/components/style/properties/longhands/position.mako.rs +++ b/components/style/properties/longhands/position.mako.rs @@ -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",