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

LibWeb: Keep the "remaining free space" across flexbox algo steps

Instead of recomputing the "remaining free space" per flex line,
remember it after calculating it during the "resolve flexible lengths"
step so we can reuse it later.
This commit is contained in:
Andreas Kling 2022-07-06 19:15:31 +02:00
parent 83a6be593c
commit 4935055407
2 changed files with 13 additions and 15 deletions

View file

@ -853,6 +853,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
};
float initial_free_space = calculate_free_space();
flex_line.remaining_free_space = initial_free_space;
// 6.4 Loop
auto for_each_unfrozen_item = [&flex_line](auto callback) {
@ -864,7 +865,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
while (number_of_unfrozen_items_on_line > 0) {
// b Calculate the remaining free space
auto remaining_free_space = calculate_free_space();
flex_line.remaining_free_space = calculate_free_space();
float sum_of_unfrozen_flex_items_flex_factors = 0;
for_each_unfrozen_item([&](FlexItem* item) {
sum_of_unfrozen_flex_items_flex_factors += item->flex_factor.value_or(1);
@ -872,17 +873,17 @@ void FlexFormattingContext::resolve_flexible_lengths()
if (sum_of_unfrozen_flex_items_flex_factors < 1) {
auto intermediate_free_space = initial_free_space * sum_of_unfrozen_flex_items_flex_factors;
if (AK::abs(intermediate_free_space) < AK::abs(remaining_free_space))
remaining_free_space = intermediate_free_space;
if (AK::abs(intermediate_free_space) < AK::abs(flex_line.remaining_free_space))
flex_line.remaining_free_space = intermediate_free_space;
}
// c Distribute free space proportional to the flex factors
if (remaining_free_space != 0) {
if (flex_line.remaining_free_space != 0) {
if (used_flex_factor == FlexFactor::FlexGrowFactor) {
float sum_of_flex_grow_factor_of_unfrozen_items = sum_of_unfrozen_flex_items_flex_factors;
for_each_unfrozen_item([&](FlexItem* flex_item) {
float ratio = flex_item->flex_factor.value_or(1) / sum_of_flex_grow_factor_of_unfrozen_items;
flex_item->target_main_size = flex_item->flex_base_size + (remaining_free_space * ratio);
flex_item->target_main_size = flex_item->flex_base_size + (flex_line.remaining_free_space * ratio);
});
} else if (used_flex_factor == FlexFactor::FlexShrinkFactor) {
float sum_of_scaled_flex_shrink_factor_of_unfrozen_items = 0;
@ -895,7 +896,7 @@ void FlexFormattingContext::resolve_flexible_lengths()
float ratio = 1.0f;
if (sum_of_scaled_flex_shrink_factor_of_unfrozen_items != 0.0f)
ratio = flex_item->scaled_flex_shrink_factor / sum_of_scaled_flex_shrink_factor_of_unfrozen_items;
flex_item->target_main_size = flex_item->flex_base_size - (AK::abs(remaining_free_space) * ratio);
flex_item->target_main_size = flex_item->flex_base_size - (AK::abs(flex_line.remaining_free_space) * ratio);
});
}
} else {
@ -1088,17 +1089,13 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
used_main_space += flex_item->main_size;
if (is_main_axis_margin_first_auto(flex_item->box))
++auto_margins;
else
used_main_space += flex_item->margins.main_before + flex_item->borders.main_before + flex_item->padding.main_before;
if (is_main_axis_margin_second_auto(flex_item->box))
++auto_margins;
else
used_main_space += flex_item->margins.main_after + flex_item->borders.main_after + flex_item->padding.main_after;
}
float remaining_free_space = m_available_space->main.value_or(NumericLimits<float>::max()) - used_main_space;
if (remaining_free_space > 0) {
float size_per_auto_margin = remaining_free_space / (float)auto_margins;
if (flex_line.remaining_free_space > 0) {
float size_per_auto_margin = flex_line.remaining_free_space / (float)auto_margins;
for (auto& flex_item : flex_line.items) {
if (is_main_axis_margin_first_auto(flex_item->box))
set_main_axis_first_margin(*flex_item, size_per_auto_margin);
@ -1129,10 +1126,10 @@ void FlexFormattingContext::distribute_any_remaining_free_space()
space_before_first_item = (m_available_space->main.value_or(NumericLimits<float>::max()) - used_main_space) / 2.0f;
break;
case CSS::JustifyContent::SpaceBetween:
space_between_items = remaining_free_space / (number_of_items - 1);
space_between_items = flex_line.remaining_free_space / (number_of_items - 1);
break;
case CSS::JustifyContent::SpaceAround:
space_between_items = remaining_free_space / number_of_items;
space_between_items = flex_line.remaining_free_space / number_of_items;
space_before_first_item = space_between_items / 2.0f;
break;
}