1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:27:35 +00:00

LibWeb: Move FFC layout algorithm step 2 into a separate function

Determining the available main and cross space is now done by a separate
function. The signature is a little bit hairy since this function
computes some things that are used by subsequent algorithm steps.

Factoring can definitely be improved further.
This commit is contained in:
Andreas Kling 2021-10-13 21:41:35 +02:00
parent cd6b97ab9e
commit c19358e157
2 changed files with 77 additions and 61 deletions

View file

@ -72,8 +72,6 @@ void FlexFormattingContext::run(Box& flex_container, LayoutMode)
bool is_row = is_row_layout();
// Determine main/cross direction
auto main_size_is_infinite = false;
auto layout_for_maximum_main_size = [&](Box& box) {
bool main_constrained = false;
if (is_row) {
@ -107,19 +105,7 @@ void FlexFormattingContext::run(Box& flex_container, LayoutMode)
return BlockFormattingContext::compute_theoretical_height(box);
}
};
auto containing_block_effective_main_size = [&is_row, &main_size_is_infinite](Box& box) {
if (is_row) {
if (box.containing_block()->has_definite_width())
return box.containing_block()->width();
main_size_is_infinite = true;
return NumericLimits<float>::max();
} else {
if (box.containing_block()->has_definite_height())
return box.containing_block()->height();
main_size_is_infinite = true;
return NumericLimits<float>::max();
}
};
auto calculate_hypothetical_cross_size = [&is_row, this](Box& box) {
bool cross_constrained = false;
if (is_row) {
@ -158,56 +144,16 @@ void FlexFormattingContext::run(Box& flex_container, LayoutMode)
generate_anonymous_flex_items(flex_container, flex_items);
// 2. Determine the available main and cross space for the flex items
float main_available_size = 0;
[[maybe_unused]] float cross_available_size = 0;
[[maybe_unused]] float main_max_size = NumericLimits<float>::max();
[[maybe_unused]] float main_min_size = 0;
float main_max_size = NumericLimits<float>::max();
float main_min_size = 0;
float cross_max_size = NumericLimits<float>::max();
float cross_min_size = 0;
bool main_is_constrained = false;
bool cross_is_constrained = false;
if (has_definite_main_size(flex_container)) {
main_is_constrained = true;
main_available_size = specified_main_size(flex_container);
} else {
if (has_main_max_size(flex_container)) {
main_max_size = specified_main_max_size(flex_container);
main_available_size = main_max_size;
main_is_constrained = true;
}
if (has_main_min_size(flex_container)) {
main_min_size = specified_main_min_size(flex_container);
main_is_constrained = true;
}
if (!main_is_constrained) {
auto available_main_size = containing_block_effective_main_size(flex_container);
main_available_size = available_main_size - sum_of_margin_padding_border_in_main_axis(flex_container);
if (flex_container.computed_values().flex_wrap() == CSS::FlexWrap::Wrap || flex_container.computed_values().flex_wrap() == CSS::FlexWrap::WrapReverse) {
main_available_size = specified_main_size(*flex_container.containing_block());
main_is_constrained = true;
}
}
}
if (has_definite_cross_size(flex_container)) {
cross_available_size = specified_cross_size(flex_container);
} else {
if (has_cross_max_size(flex_container)) {
cross_max_size = specified_cross_max_size(flex_container);
cross_is_constrained = true;
}
if (has_cross_min_size(flex_container)) {
cross_min_size = specified_cross_min_size(flex_container);
cross_is_constrained = true;
}
// FIXME: Is this right? Probably not.
if (!cross_is_constrained)
cross_available_size = cross_max_size;
}
bool main_size_is_infinite = false;
auto available_space = determine_available_main_and_cross_space(flex_container, main_size_is_infinite, main_is_constrained, cross_is_constrained, main_min_size, main_max_size, cross_min_size, cross_max_size);
auto main_available_size = available_space.main;
[[maybe_unused]] auto cross_available_size = available_space.cross;
// 3. Determine the flex base size and hypothetical main size of each item
for (auto& flex_item : flex_items) {
@ -898,4 +844,68 @@ float FlexFormattingContext::sum_of_margin_padding_border_in_main_axis(Box const
}
}
// https://www.w3.org/TR/css-flexbox-1/#algo-available
FlexFormattingContext::AvailableSpace FlexFormattingContext::determine_available_main_and_cross_space(const Box& flex_container, bool& main_size_is_infinite, bool& main_is_constrained, bool& cross_is_constrained, float& main_min_size, float& main_max_size, float& cross_min_size, float& cross_max_size) const
{
auto containing_block_effective_main_size = [&](Box const& box) {
if (is_row_layout()) {
if (box.containing_block()->has_definite_width())
return box.containing_block()->width();
main_size_is_infinite = true;
return NumericLimits<float>::max();
} else {
if (box.containing_block()->has_definite_height())
return box.containing_block()->height();
main_size_is_infinite = true;
return NumericLimits<float>::max();
}
};
float main_available_space = 0;
float cross_available_space = 0;
if (has_definite_main_size(flex_container)) {
main_is_constrained = true;
main_available_space = specified_main_size(flex_container);
} else {
if (has_main_max_size(flex_container)) {
main_max_size = specified_main_max_size(flex_container);
main_available_space = main_max_size;
main_is_constrained = true;
}
if (has_main_min_size(flex_container)) {
main_min_size = specified_main_min_size(flex_container);
main_is_constrained = true;
}
if (!main_is_constrained) {
auto available_main_size = containing_block_effective_main_size(flex_container);
main_available_space = available_main_size - sum_of_margin_padding_border_in_main_axis(flex_container);
if (flex_container.computed_values().flex_wrap() == CSS::FlexWrap::Wrap || flex_container.computed_values().flex_wrap() == CSS::FlexWrap::WrapReverse) {
main_available_space = specified_main_size(*flex_container.containing_block());
main_is_constrained = true;
}
}
}
if (has_definite_cross_size(flex_container)) {
cross_available_space = specified_cross_size(flex_container);
} else {
if (has_cross_max_size(flex_container)) {
cross_max_size = specified_cross_max_size(flex_container);
cross_is_constrained = true;
}
if (has_cross_min_size(flex_container)) {
cross_min_size = specified_cross_min_size(flex_container);
cross_is_constrained = true;
}
// FIXME: Is this right? Probably not.
if (!cross_is_constrained)
cross_available_space = cross_max_size;
}
return AvailableSpace { .main = main_available_space, .cross = cross_available_space };
}
}