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:
parent
d3932b5880
commit
39ca39204b
Notes:
sideshowbarker
2024-07-17 17:11:17 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/39ca39204b
1 changed files with 14 additions and 9 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue