mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:07:34 +00:00
LibWeb: Improve FFC step 7 (hypothetical cross size)
- Avoid performing inside layout on definite-size flex items (since their computed size can be used as-is.) - Use FormattingState::clone() to generate a throwaway layout instead of mutating the tree in-place. - Update spec link & comments based on current CSSWG draft. The latest version is quite a bit clearer on how this should work.
This commit is contained in:
parent
b904bff838
commit
1ce1af5d8b
2 changed files with 31 additions and 28 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
|
||||||
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
@ -117,7 +117,7 @@ void FlexFormattingContext::run(Box const& run_box, LayoutMode)
|
||||||
// Cross Size Determination
|
// Cross Size Determination
|
||||||
// 7. Determine the hypothetical cross size of each item
|
// 7. Determine the hypothetical cross size of each item
|
||||||
for (auto& flex_item : m_flex_items) {
|
for (auto& flex_item : m_flex_items) {
|
||||||
flex_item.hypothetical_cross_size = determine_hypothetical_cross_size_of_item(flex_item.box);
|
determine_hypothetical_cross_size_of_item(flex_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. Calculate the cross size of each flex line.
|
// 8. Calculate the cross size of each flex line.
|
||||||
|
@ -825,36 +825,39 @@ void FlexFormattingContext::resolve_flexible_lengths(float const main_available_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-flexbox-1/#algo-cross-item
|
// https://drafts.csswg.org/css-flexbox-1/#algo-cross-item
|
||||||
float FlexFormattingContext::determine_hypothetical_cross_size_of_item(Box const& box)
|
void FlexFormattingContext::determine_hypothetical_cross_size_of_item(FlexItem& item)
|
||||||
{
|
{
|
||||||
bool cross_constrained = false;
|
// Determine the hypothetical cross size of each item by performing layout
|
||||||
if (is_row_layout()) {
|
// as if it were an in-flow block-level box with the used main size
|
||||||
if (!is_undefined_or_auto(box.computed_values().height()) || !is_undefined_or_auto(box.computed_values().min_height())) {
|
// and the given available space, treating auto as fit-content.
|
||||||
cross_constrained = true;
|
|
||||||
}
|
// If we have a definite cross size, this is easy! No need to perform layout, we can just use it as-is.
|
||||||
|
if (has_definite_cross_size(item.box)) {
|
||||||
|
auto const& cross_value = is_row_layout() ? item.box.computed_values().height() : item.box.computed_values().width();
|
||||||
|
item.hypothetical_cross_size = cross_value->length().to_px(item.box);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For indefinite cross sizes, we perform a throwaway layout and then measure it.
|
||||||
|
auto throwaway_state = m_state;
|
||||||
|
auto& tmp_container_state = throwaway_state.get_mutable(flex_container());
|
||||||
|
tmp_container_state.content_width = is_row_layout() ? m_available_space->main : m_available_space->cross;
|
||||||
|
|
||||||
|
VERIFY(item.box.containing_block() == &flex_container());
|
||||||
|
if (auto independent_formatting_context = create_independent_formatting_context_if_needed(throwaway_state, item.box)) {
|
||||||
|
independent_formatting_context->run(item.box, LayoutMode::Default);
|
||||||
} else {
|
} else {
|
||||||
if (!is_undefined_or_auto(box.computed_values().width()) || !is_undefined_or_auto(box.computed_values().min_width())) {
|
// NOTE: Flex items should always create an independent formatting context!
|
||||||
cross_constrained = true;
|
VERIFY_NOT_REACHED();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cross_constrained && box.children_are_inline()) {
|
auto const& box_state = throwaway_state.get(item.box);
|
||||||
auto& block_container = verify_cast<BlockContainer>(box);
|
if (is_row_layout()) {
|
||||||
BlockFormattingContext bfc(m_state, block_container, this);
|
item.hypothetical_cross_size = BlockFormattingContext::compute_theoretical_height(throwaway_state, item.box);
|
||||||
bfc.run(box, LayoutMode::Default);
|
} else {
|
||||||
InlineFormattingContext ifc(m_state, block_container, bfc);
|
item.hypothetical_cross_size = box_state.content_width;
|
||||||
ifc.run(box, LayoutMode::OnlyRequiredLineBreaks);
|
|
||||||
|
|
||||||
auto const& box_state = m_state.get(box);
|
|
||||||
return is_row_layout() ? box_state.content_height : box_state.content_width;
|
|
||||||
}
|
}
|
||||||
if (is_row_layout())
|
|
||||||
return BlockFormattingContext::compute_theoretical_height(m_state, box);
|
|
||||||
|
|
||||||
BlockFormattingContext context(m_state, verify_cast<BlockContainer>(box), this);
|
|
||||||
context.compute_width(box);
|
|
||||||
return m_state.get(box).content_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-flexbox-1/#algo-cross-line
|
// https://www.w3.org/TR/css-flexbox-1/#algo-cross-line
|
||||||
|
|
|
@ -96,7 +96,7 @@ private:
|
||||||
|
|
||||||
void resolve_flexible_lengths(float main_available_size);
|
void resolve_flexible_lengths(float main_available_size);
|
||||||
|
|
||||||
float determine_hypothetical_cross_size_of_item(Box const&);
|
void determine_hypothetical_cross_size_of_item(FlexItem&);
|
||||||
|
|
||||||
void calculate_cross_size_of_each_flex_line(float cross_min_size, float cross_max_size);
|
void calculate_cross_size_of_each_flex_line(float cross_min_size, float cross_max_size);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue