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

LibWeb: Move FFC layout algorithm step 3 to a separate function

This commit is contained in:
Andreas Kling 2021-10-13 21:49:28 +02:00
parent c19358e157
commit 3375953918
2 changed files with 90 additions and 80 deletions

View file

@ -72,40 +72,6 @@ void FlexFormattingContext::run(Box& flex_container, LayoutMode)
bool is_row = is_row_layout();
auto layout_for_maximum_main_size = [&](Box& box) {
bool main_constrained = false;
if (is_row) {
if (!box.computed_values().width().is_undefined_or_auto() || !box.computed_values().min_width().is_undefined_or_auto()) {
main_constrained = true;
}
} else {
if (!box.computed_values().height().is_undefined_or_auto() || !box.computed_values().min_height().is_undefined_or_auto()) {
main_constrained = true;
}
}
if (!main_constrained && box.children_are_inline()) {
auto& block_container = verify_cast<BlockContainer>(box);
BlockFormattingContext bfc(block_container, this);
bfc.run(box, LayoutMode::Default);
InlineFormattingContext ifc(block_container, &bfc);
if (is_row) {
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
return box.width();
} else {
ifc.run(box, LayoutMode::AllPossibleLineBreaks);
return box.height();
}
}
if (is_row) {
layout_inside(box, LayoutMode::OnlyRequiredLineBreaks);
return box.width();
} else {
return BlockFormattingContext::compute_theoretical_height(box);
}
};
auto calculate_hypothetical_cross_size = [&is_row, this](Box& box) {
bool cross_constrained = false;
if (is_row) {
@ -157,52 +123,7 @@ void FlexFormattingContext::run(Box& flex_container, LayoutMode)
// 3. Determine the flex base size and hypothetical main size of each item
for (auto& flex_item : flex_items) {
auto& child_box = flex_item.box;
auto flex_basis = child_box.computed_values().flex_basis();
if (flex_basis.type == CSS::FlexBasis::Length) {
// A
auto specified_base_size = get_pixel_size(child_box, flex_basis.length);
if (specified_base_size == 0)
flex_item.flex_base_size = calculated_main_size(flex_item.box);
else
flex_item.flex_base_size = specified_base_size;
} else if (flex_basis.type == CSS::FlexBasis::Content
&& has_definite_cross_size(child_box)
// FIXME: && has intrinsic aspect ratio.
&& false) {
// B
TODO();
// flex_base_size is calculated from definite cross size and intrinsic aspect ratio
} else if (flex_basis.type == CSS::FlexBasis::Content
// FIXME: && sized under min-content or max-content contstraints
&& false) {
// C
TODO();
// Size child_box under the constraints, flex_base_size is then the resulting main_size.
} else if (flex_basis.type == CSS::FlexBasis::Content
// FIXME: && main_size is infinite && inline axis is parallel to the main axis
&& false && false) {
// D
TODO();
// Use rules for a flex_container in orthogonal flow
} else {
// E
// FIXME: This is probably too naive.
// FIXME: Care about FlexBasis::Auto
if (has_definite_main_size(child_box)) {
flex_item.flex_base_size = specified_main_size_of_child_box(flex_container, child_box);
} else {
flex_item.flex_base_size = layout_for_maximum_main_size(child_box);
}
}
auto clamp_min = has_main_min_size(child_box)
? specified_main_min_size(child_box)
: 0;
auto clamp_max = has_main_max_size(child_box)
? specified_main_max_size(child_box)
: NumericLimits<float>::max();
flex_item.hypothetical_main_size = clamp(flex_item.flex_base_size, clamp_min, clamp_max);
determine_flex_base_size_and_hypothetical_main_size(flex_container, flex_item);
}
// 4. Determine the main size of the flex container
@ -908,4 +829,90 @@ FlexFormattingContext::AvailableSpace FlexFormattingContext::determine_available
return AvailableSpace { .main = main_available_space, .cross = cross_available_space };
}
float FlexFormattingContext::layout_for_maximum_main_size(Box& box)
{
bool main_constrained = false;
if (is_row_layout()) {
if (!box.computed_values().width().is_undefined_or_auto() || !box.computed_values().min_width().is_undefined_or_auto()) {
main_constrained = true;
}
} else {
if (!box.computed_values().height().is_undefined_or_auto() || !box.computed_values().min_height().is_undefined_or_auto()) {
main_constrained = true;
}
}
if (!main_constrained && box.children_are_inline()) {
auto& block_container = verify_cast<BlockContainer>(box);
BlockFormattingContext bfc(block_container, this);
bfc.run(box, LayoutMode::Default);
InlineFormattingContext ifc(block_container, &bfc);
if (is_row_layout()) {
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
return box.width();
} else {
ifc.run(box, LayoutMode::AllPossibleLineBreaks);
return box.height();
}
}
if (is_row_layout()) {
layout_inside(box, LayoutMode::OnlyRequiredLineBreaks);
return box.width();
} else {
return BlockFormattingContext::compute_theoretical_height(box);
}
}
// https://www.w3.org/TR/css-flexbox-1/#algo-main-item
void FlexFormattingContext::determine_flex_base_size_and_hypothetical_main_size(Box const& flex_container, FlexItem& flex_item)
{
auto& child_box = flex_item.box;
auto const& flex_basis = child_box.computed_values().flex_basis();
if (flex_basis.type == CSS::FlexBasis::Length) {
// A
auto specified_base_size = get_pixel_size(child_box, flex_basis.length);
if (specified_base_size == 0)
flex_item.flex_base_size = calculated_main_size(flex_item.box);
else
flex_item.flex_base_size = specified_base_size;
} else if (flex_basis.type == CSS::FlexBasis::Content
&& has_definite_cross_size(child_box)
// FIXME: && has intrinsic aspect ratio.
&& false) {
// B
TODO();
// flex_base_size is calculated from definite cross size and intrinsic aspect ratio
} else if (flex_basis.type == CSS::FlexBasis::Content
// FIXME: && sized under min-content or max-content contstraints
&& false) {
// C
TODO();
// Size child_box under the constraints, flex_base_size is then the resulting main_size.
} else if (flex_basis.type == CSS::FlexBasis::Content
// FIXME: && main_size is infinite && inline axis is parallel to the main axis
&& false && false) {
// D
TODO();
// Use rules for a flex_container in orthogonal flow
} else {
// E
// FIXME: This is probably too naive.
// FIXME: Care about FlexBasis::Auto
if (has_definite_main_size(child_box)) {
flex_item.flex_base_size = specified_main_size_of_child_box(flex_container, child_box);
} else {
flex_item.flex_base_size = layout_for_maximum_main_size(child_box);
}
}
auto clamp_min = has_main_min_size(child_box)
? specified_main_min_size(child_box)
: 0;
auto clamp_max = has_main_max_size(child_box)
? specified_main_max_size(child_box)
: NumericLimits<float>::max();
flex_item.hypothetical_main_size = clamp(flex_item.flex_base_size, clamp_min, clamp_max);
}
}