From 834d98520ab4de7b727150c2c4255988b1b7560e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 14 Oct 2022 13:50:40 +0200 Subject: LibWeb: Implement basic support for align-content in flex layout This property tells us how to lay out multi-line flex containers. I implemented all modes except `space-between` and `space-around`. Those are left as FIXMEs. --- .../LibWeb/Layout/FlexFormattingContext.cpp | 66 ++++++++++++++++++++-- .../LibWeb/Layout/FlexFormattingContext.h | 2 + 2 files changed, 62 insertions(+), 6 deletions(-) (limited to 'Userland') diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp index a9e640ff78..c5274ead01 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.cpp @@ -155,7 +155,7 @@ void FlexFormattingContext::run(Box const& run_box, LayoutMode, AvailableSpace c calculate_cross_size_of_each_flex_line(); // 9. Handle 'align-content: stretch'. - // FIXME: This + handle_align_content_stretch(); // 10. Collapse visibility:collapse items. // FIXME: This @@ -1372,6 +1372,9 @@ void FlexFormattingContext::determine_flex_container_used_cross_size() // https://www.w3.org/TR/css-flexbox-1/#algo-line-align void FlexFormattingContext::align_all_flex_lines() { + if (m_flex_lines.is_empty()) + return; + // FIXME: Support reverse float cross_size_of_flex_container = specified_cross_size(flex_container()); @@ -1384,16 +1387,39 @@ void FlexFormattingContext::align_all_flex_lines() flex_item->cross_offset += center_of_line; } } else { - // FIXME: Support align-content - float cross_size_per_flex_line = cross_size_of_flex_container / m_flex_lines.size(); - float half_a_flex_line = cross_size_per_flex_line / 2.0f; - float center_of_current_line = 0 + half_a_flex_line; + float sum_of_flex_line_cross_sizes = 0; + for (auto& line : m_flex_lines) + sum_of_flex_line_cross_sizes += line.cross_size; + + float start_of_current_line = 0; + switch (flex_container().computed_values().align_content()) { + case CSS::AlignContent::FlexStart: + start_of_current_line = 0; + break; + case CSS::AlignContent::FlexEnd: + start_of_current_line = cross_size_of_flex_container - sum_of_flex_line_cross_sizes; + break; + case CSS::AlignContent::Center: + start_of_current_line = (cross_size_of_flex_container / 2) - (sum_of_flex_line_cross_sizes / 2); + break; + case CSS::AlignContent::SpaceBetween: + dbgln("FIXME: align-content: space-between"); + break; + case CSS::AlignContent::SpaceAround: + dbgln("FIXME: align-content: space-around"); + break; + case CSS::AlignContent::Stretch: + start_of_current_line = 0; + break; + } + for (auto& flex_line : m_flex_lines) { + float center_of_current_line = start_of_current_line + (flex_line.cross_size / 2); for (auto* flex_item : flex_line.items) { flex_item->cross_offset += center_of_current_line; } - center_of_current_line += cross_size_per_flex_line; + start_of_current_line += flex_line.cross_size; } } } @@ -1828,4 +1854,32 @@ void FlexFormattingContext::resolve_cross_axis_auto_margins() } } +// https://drafts.csswg.org/css-flexbox-1/#algo-line-stretch +void FlexFormattingContext::handle_align_content_stretch() +{ + // If the flex container has a definite cross size, + if (!has_definite_cross_size(flex_container())) + return; + + // align-content is stretch, + if (flex_container().computed_values().align_content() != CSS::AlignContent::Stretch) + return; + + // and the sum of the flex lines' cross sizes is less than the flex container’s inner cross size, + float sum_of_flex_line_cross_sizes = 0; + for (auto& line : m_flex_lines) + sum_of_flex_line_cross_sizes += line.cross_size; + + if (sum_of_flex_line_cross_sizes >= specified_cross_size(flex_container())) + return; + + // increase the cross size of each flex line by equal amounts + // such that the sum of their cross sizes exactly equals the flex container’s inner cross size. + float remainder = specified_cross_size(flex_container()) - sum_of_flex_line_cross_sizes; + float extra_per_line = remainder / m_flex_lines.size(); + + for (auto& line : m_flex_lines) + line.cross_size += extra_per_line; +} + } diff --git a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h index eb6b9e4f94..0f54a66e9f 100644 --- a/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FlexFormattingContext.h @@ -142,6 +142,8 @@ private: void calculate_cross_size_of_each_flex_line(); + void handle_align_content_stretch(); + CSS::AlignItems alignment_for_item(FlexItem const&) const; void determine_used_cross_size_of_each_flex_item(); -- cgit v1.2.3