LibWeb: Skip cells layout in table box width calculation

There is no need to run full table layout if we are only interested in
calculating its width.

This change reduces compute_table_box_width_inside_table_wrapper()
from ~30% to ~15% in profiles of "File changed" pages on github.
This commit is contained in:
Aliaksandr Kalenik 2024-03-19 10:18:49 +01:00 committed by Andreas Kling
parent 541161d5e0
commit 6fc59039c4
Notes: sideshowbarker 2024-07-17 03:10:07 +09:00
3 changed files with 23 additions and 9 deletions

View File

@ -405,11 +405,6 @@ CSSPixels FormattingContext::compute_table_box_width_inside_table_wrapper(Box co
// table-wrapper can't have borders or paddings but it might have margin taken from table-root.
auto available_width = width_of_containing_block - margin_left.to_px(box) - margin_right.to_px(box);
LayoutState throwaway_state(&m_state);
auto context = create_independent_formatting_context_if_needed(throwaway_state, box);
VERIFY(context);
context->run(box, LayoutMode::IntrinsicSizing, m_state.get(box).available_inner_space_or_constraints_from(available_space));
Optional<Box const&> table_box;
box.for_each_in_subtree_of_type<Box>([&](Box const& child_box) {
if (child_box.display().is_table_inside()) {
@ -420,6 +415,16 @@ CSSPixels FormattingContext::compute_table_box_width_inside_table_wrapper(Box co
});
VERIFY(table_box.has_value());
LayoutState throwaway_state(&m_state);
auto& table_box_state = throwaway_state.get_mutable(*table_box);
auto const& table_box_computed_values = table_box->computed_values();
table_box_state.border_left = table_box_computed_values.border_left().width;
table_box_state.border_right = table_box_computed_values.border_right().width;
auto context = make<TableFormattingContext>(throwaway_state, *table_box, this);
context->run_until_width_calculation(*table_box, m_state.get(*table_box).available_inner_space_or_constraints_from(available_space));
auto table_used_width = throwaway_state.get(*table_box).border_box_width();
return available_space.width.is_definite() ? min(table_used_width, available_width) : table_used_width;
}

View File

@ -1577,12 +1577,10 @@ void TableFormattingContext::finish_grid_initialization(TableGrid const& table_g
}
}
void TableFormattingContext::run(Box const& box, LayoutMode layout_mode, AvailableSpace const& available_space)
void TableFormattingContext::run_until_width_calculation(Box const& box, AvailableSpace const& available_space)
{
m_available_space = available_space;
auto total_captions_height = run_caption_layout(layout_mode, CSS::CaptionSide::Top);
// Determine the number of rows/columns the table requires.
finish_grid_initialization(TableGrid::calculate_row_column_grid(box, m_cells, m_rows));
@ -1603,6 +1601,15 @@ void TableFormattingContext::run(Box const& box, LayoutMode layout_mode, Availab
// Compute the width of the table.
compute_table_width();
}
void TableFormattingContext::run(Box const& box, LayoutMode layout_mode, AvailableSpace const& available_space)
{
m_available_space = available_space;
auto total_captions_height = run_caption_layout(layout_mode, CSS::CaptionSide::Top);
run_until_width_calculation(box, available_space);
if (available_space.width.is_intrinsic_sizing_constraint() && !available_space.height.is_intrinsic_sizing_constraint()) {
return;

View File

@ -23,6 +23,8 @@ public:
explicit TableFormattingContext(LayoutState&, Box const&, FormattingContext* parent);
~TableFormattingContext();
void run_until_width_calculation(Box const&, AvailableSpace const& available_space);
virtual void run(Box const&, LayoutMode, AvailableSpace const&) override;
virtual CSSPixels automatic_content_width() const override;
virtual CSSPixels automatic_content_height() const override;
@ -146,7 +148,7 @@ private:
static TableFormattingContext::ConflictingEdge const& winning_conflicting_edge(TableFormattingContext::ConflictingEdge const& a, TableFormattingContext::ConflictingEdge const& b);
static const CSS::BorderData& border_data_conflicting_edge(ConflictingEdge const& conflicting_edge);
static const Painting::PaintableBox::BorderDataWithElementKind border_data_with_element_kind_from_conflicting_edge(ConflictingEdge const& conflicting_edge);
static Painting::PaintableBox::BorderDataWithElementKind const border_data_with_element_kind_from_conflicting_edge(ConflictingEdge const& conflicting_edge);
class BorderConflictFinder {
public: