From 39ca39204bd3ca99719a0dfe20f194a369b19ce8 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 18 Mar 2022 12:33:11 +0100 Subject: [PATCH] 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.) --- .../LibWeb/Layout/FormattingContext.cpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 82e2aa12fe..2d5c1b7473 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -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(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(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; }