LibWeb: Cache intrinsic sizes on the root FormattingState

Instead of caching them with the current state, we can cache them at the
root of the state tree. Since intrinsic sizes are immutable during the
same layout, this allows layout to take advantage of intrinsic sizes
discovered during nested layout (and avoids a *lot* of duplicate work.)
This commit is contained in:
Andreas Kling 2022-03-18 12:33:11 +01:00
parent d3932b5880
commit 39ca39204b
Notes: sideshowbarker 2024-07-17 17:11:17 +09:00

View file

@ -811,36 +811,40 @@ void FormattingContext::compute_position(Box const& box)
FormattingState::IntrinsicSizes FormattingContext::calculate_intrinsic_sizes(Layout::Box const& box) const
{
auto& root_state = m_state.m_root;
// If we have cached intrinsic sizes for this box, use them.
auto it = m_state.intrinsic_sizes.find(&box);
if (it != m_state.intrinsic_sizes.end())
auto it = root_state.intrinsic_sizes.find(&box);
if (it != root_state.intrinsic_sizes.end())
return it->value;
// Nothing cached, perform two throwaway layouts to determine the intrinsic sizes.
// FIXME: This should handle replaced elements with "native" intrinsic size properly!
auto& cached_box_sizes = m_state.intrinsic_sizes.ensure(&box);
FormattingState::IntrinsicSizes cached_box_sizes;
auto const& containing_block = *box.containing_block();
{
FormattingState throwaway_state(&m_state);
throwaway_state.get_mutable(containing_block).content_width = INFINITY;
throwaway_state.get_mutable(containing_block).content_height = INFINITY;
auto& containing_block_state = throwaway_state.get_mutable(containing_block);
containing_block_state.content_width = INFINITY;
containing_block_state.content_height = INFINITY;
auto independent_formatting_context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(independent_formatting_context);
independent_formatting_context->run(box, LayoutMode::OnlyRequiredLineBreaks);
cached_box_sizes.max_content_size.set_width(greatest_child_width(throwaway_state, box));
cached_box_sizes.max_content_size.set_width(independent_formatting_context->greatest_child_width(box));
cached_box_sizes.max_content_size.set_height(BlockFormattingContext::compute_theoretical_height(throwaway_state, box));
}
{
FormattingState throwaway_state(&m_state);
throwaway_state.get_mutable(containing_block).content_width = 0;
throwaway_state.get_mutable(containing_block).content_height = 0;
auto& containing_block_state = throwaway_state.get_mutable(containing_block);
containing_block_state.content_width = 0;
containing_block_state.content_height = 0;
auto independent_formatting_context = const_cast<FormattingContext*>(this)->create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(independent_formatting_context);
independent_formatting_context->run(box, LayoutMode::AllPossibleLineBreaks);
cached_box_sizes.min_content_size.set_width(greatest_child_width(throwaway_state, box));
cached_box_sizes.min_content_size.set_width(independent_formatting_context->greatest_child_width(box));
cached_box_sizes.min_content_size.set_height(BlockFormattingContext::compute_theoretical_height(throwaway_state, box));
}
@ -856,6 +860,7 @@ FormattingState::IntrinsicSizes FormattingContext::calculate_intrinsic_sizes(Lay
cached_box_sizes.max_content_size.set_height(tmp);
}
root_state.intrinsic_sizes.set(&box, cached_box_sizes);
return cached_box_sizes;
}