mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 12:05:15 +00:00
LibWeb: Use cached UsedValues pointer in IFC and its helper classes
This avoids expensive LayoutState lookups when we already have the pointer sitting around anyway.
This commit is contained in:
parent
43ef3dc0ab
commit
1cea4e6407
Notes:
sideshowbarker
2024-07-16 21:39:23 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/1cea4e6407 Pull-request: https://github.com/SerenityOS/serenity/pull/23602
7 changed files with 48 additions and 45 deletions
|
@ -472,7 +472,7 @@ void BlockFormattingContext::layout_inline_children(BlockContainer const& block_
|
|||
|
||||
auto& block_container_state = m_state.get_mutable(block_container);
|
||||
|
||||
InlineFormattingContext context(m_state, block_container, *this);
|
||||
InlineFormattingContext context(m_state, block_container, block_container_state, *this);
|
||||
context.run(
|
||||
block_container,
|
||||
layout_mode,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2024, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -18,9 +18,13 @@
|
|||
|
||||
namespace Web::Layout {
|
||||
|
||||
InlineFormattingContext::InlineFormattingContext(LayoutState& state, BlockContainer const& containing_block, BlockFormattingContext& parent)
|
||||
InlineFormattingContext::InlineFormattingContext(
|
||||
LayoutState& state,
|
||||
BlockContainer const& containing_block,
|
||||
LayoutState::UsedValues& containing_block_used_values,
|
||||
BlockFormattingContext& parent)
|
||||
: FormattingContext(Type::Inline, state, containing_block, &parent)
|
||||
, m_containing_block_state(state.get(containing_block))
|
||||
, m_containing_block_used_values(containing_block_used_values)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,7 +43,7 @@ BlockFormattingContext const& InlineFormattingContext::parent() const
|
|||
CSSPixels InlineFormattingContext::leftmost_x_offset_at(CSSPixels y) const
|
||||
{
|
||||
// NOTE: Floats are relative to the BFC root box, not necessarily the containing block of this IFC.
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(m_containing_block_state, parent().root());
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(m_containing_block_used_values, parent().root());
|
||||
CSSPixels y_in_root = box_in_root_rect.y() + y;
|
||||
auto space_and_containing_margin = parent().space_used_and_containing_margin_for_floats(y_in_root);
|
||||
auto left_side_floats_limit_to_right = space_and_containing_margin.left_total_containing_margin + space_and_containing_margin.left_used_space;
|
||||
|
@ -55,7 +59,7 @@ CSSPixels InlineFormattingContext::leftmost_x_offset_at(CSSPixels y) const
|
|||
|
||||
AvailableSize InlineFormattingContext::available_space_for_line(CSSPixels y) const
|
||||
{
|
||||
auto intrusions = parent().intrusion_by_floats_into_box(m_containing_block_state, y);
|
||||
auto intrusions = parent().intrusion_by_floats_into_box(m_containing_block_used_values, y);
|
||||
if (m_available_space->width.is_definite()) {
|
||||
return AvailableSize::make_definite(m_available_space->width.to_px_or_zero() - (intrusions.left + intrusions.right));
|
||||
} else {
|
||||
|
@ -81,7 +85,7 @@ void InlineFormattingContext::run(Box const&, LayoutMode layout_mode, AvailableS
|
|||
|
||||
CSSPixels content_height = 0;
|
||||
|
||||
for (auto& line_box : m_containing_block_state.line_boxes) {
|
||||
for (auto& line_box : m_containing_block_used_values.line_boxes) {
|
||||
content_height += line_box.height();
|
||||
}
|
||||
|
||||
|
@ -174,7 +178,7 @@ void InlineFormattingContext::dimension_box_on_line(Box const& box, LayoutMode l
|
|||
|
||||
// NOTE: Flex containers with `auto` height are treated as `max-content`, so we can compute their height early.
|
||||
if (box_state.has_definite_height() || box.display().is_flex_inside())
|
||||
parent().compute_height(box, AvailableSpace(AvailableSize::make_definite(width), AvailableSize::make_definite(m_containing_block_state.content_height())));
|
||||
parent().compute_height(box, AvailableSpace(AvailableSize::make_definite(width), AvailableSize::make_definite(m_containing_block_used_values.content_height())));
|
||||
|
||||
auto independent_formatting_context = layout_inside(box, layout_mode, box_state.available_inner_space_or_constraints_from(*m_available_space));
|
||||
|
||||
|
@ -183,7 +187,7 @@ void InlineFormattingContext::dimension_box_on_line(Box const& box, LayoutMode l
|
|||
// FIXME: (10.6.6) If 'height' is 'auto', the height depends on the element's descendants per 10.6.7.
|
||||
parent().compute_height(box, AvailableSpace(AvailableSize::make_indefinite(), AvailableSize::make_indefinite()));
|
||||
} else {
|
||||
auto inner_height = calculate_inner_height(box, AvailableSize::make_definite(m_containing_block_state.content_height()), height_value);
|
||||
auto inner_height = calculate_inner_height(box, AvailableSize::make_definite(m_containing_block_used_values.content_height()), height_value);
|
||||
box_state.set_content_height(inner_height);
|
||||
}
|
||||
|
||||
|
@ -242,12 +246,11 @@ void InlineFormattingContext::apply_justification_to_fragments(CSS::TextJustify
|
|||
|
||||
void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
|
||||
{
|
||||
auto& containing_block_state = m_state.get_mutable(containing_block());
|
||||
auto& line_boxes = containing_block_state.line_boxes;
|
||||
auto& line_boxes = m_containing_block_used_values.line_boxes;
|
||||
line_boxes.clear_with_capacity();
|
||||
|
||||
InlineLevelIterator iterator(*this, m_state, containing_block(), layout_mode);
|
||||
LineBuilder line_builder(*this, m_state);
|
||||
InlineLevelIterator iterator(*this, m_state, containing_block(), m_containing_block_used_values, layout_mode);
|
||||
LineBuilder line_builder(*this, m_state, m_containing_block_used_values);
|
||||
|
||||
// NOTE: When we ignore collapsible whitespace chunks at the start of a line,
|
||||
// we have to remember how much start margin that chunk had in the inline
|
||||
|
@ -371,7 +374,7 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
|
|||
|
||||
bool InlineFormattingContext::any_floats_intrude_at_y(CSSPixels y) const
|
||||
{
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(m_containing_block_state, parent().root());
|
||||
auto box_in_root_rect = content_box_rect_in_ancestor_coordinate_space(m_containing_block_used_values, parent().root());
|
||||
CSSPixels y_in_root = box_in_root_rect.y() + y;
|
||||
auto space_and_containing_margin = parent().space_used_and_containing_margin_for_floats(y_in_root);
|
||||
return space_and_containing_margin.left_used_space > 0 || space_and_containing_margin.right_used_space > 0;
|
||||
|
@ -379,8 +382,8 @@ bool InlineFormattingContext::any_floats_intrude_at_y(CSSPixels y) const
|
|||
|
||||
bool InlineFormattingContext::can_fit_new_line_at_y(CSSPixels y) const
|
||||
{
|
||||
auto top_intrusions = parent().intrusion_by_floats_into_box(m_containing_block_state, y);
|
||||
auto bottom_intrusions = parent().intrusion_by_floats_into_box(m_containing_block_state, y + containing_block().computed_values().line_height() - 1);
|
||||
auto top_intrusions = parent().intrusion_by_floats_into_box(m_containing_block_used_values, y);
|
||||
auto bottom_intrusions = parent().intrusion_by_floats_into_box(m_containing_block_used_values, y + containing_block().computed_values().line_height() - 1);
|
||||
|
||||
auto left_edge = [](auto& space) -> CSSPixels {
|
||||
return space.left;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2024, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -15,7 +15,7 @@ namespace Web::Layout {
|
|||
|
||||
class InlineFormattingContext final : public FormattingContext {
|
||||
public:
|
||||
InlineFormattingContext(LayoutState&, BlockContainer const& containing_block, BlockFormattingContext& parent);
|
||||
InlineFormattingContext(LayoutState&, BlockContainer const& containing_block, LayoutState::UsedValues& containing_block_used_values, BlockFormattingContext& parent);
|
||||
~InlineFormattingContext();
|
||||
|
||||
BlockFormattingContext& parent();
|
||||
|
@ -41,7 +41,7 @@ private:
|
|||
void generate_line_boxes(LayoutMode);
|
||||
void apply_justification_to_fragments(CSS::TextJustify, LineBox&, bool is_last_line);
|
||||
|
||||
LayoutState::UsedValues const& m_containing_block_state;
|
||||
LayoutState::UsedValues& m_containing_block_used_values;
|
||||
|
||||
Optional<AvailableSpace> m_available_space;
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
|
||||
namespace Web::Layout {
|
||||
|
||||
InlineLevelIterator::InlineLevelIterator(Layout::InlineFormattingContext& inline_formatting_context, Layout::LayoutState& layout_state, Layout::BlockContainer const& container, LayoutMode layout_mode)
|
||||
InlineLevelIterator::InlineLevelIterator(Layout::InlineFormattingContext& inline_formatting_context, Layout::LayoutState& layout_state, Layout::BlockContainer const& containing_block, LayoutState::UsedValues const& containing_block_used_values, LayoutMode layout_mode)
|
||||
: m_inline_formatting_context(inline_formatting_context)
|
||||
, m_layout_state(layout_state)
|
||||
, m_container(container)
|
||||
, m_container_state(layout_state.get(container))
|
||||
, m_next_node(container.first_child())
|
||||
, m_containing_block(containing_block)
|
||||
, m_containing_block_used_values(containing_block_used_values)
|
||||
, m_next_node(containing_block.first_child())
|
||||
, m_layout_mode(layout_mode)
|
||||
{
|
||||
skip_to_next();
|
||||
|
@ -34,9 +34,9 @@ void InlineLevelIterator::enter_node_with_box_model_metrics(Layout::NodeWithStyl
|
|||
auto& used_values = m_layout_state.get_mutable(node);
|
||||
auto const& computed_values = node.computed_values();
|
||||
|
||||
used_values.margin_left = computed_values.margin().left().to_px(node, m_container_state.content_width());
|
||||
used_values.margin_left = computed_values.margin().left().to_px(node, m_containing_block_used_values.content_width());
|
||||
used_values.border_left = computed_values.border_left().width;
|
||||
used_values.padding_left = computed_values.padding().left().to_px(node, m_container_state.content_width());
|
||||
used_values.padding_left = computed_values.padding().left().to_px(node, m_containing_block_used_values.content_width());
|
||||
|
||||
m_extra_leading_metrics->margin += used_values.margin_left;
|
||||
m_extra_leading_metrics->border += used_values.border_left;
|
||||
|
@ -57,9 +57,9 @@ void InlineLevelIterator::exit_node_with_box_model_metrics()
|
|||
auto& used_values = m_layout_state.get_mutable(node);
|
||||
auto const& computed_values = node->computed_values();
|
||||
|
||||
used_values.margin_right = computed_values.margin().right().to_px(node, m_container_state.content_width());
|
||||
used_values.margin_right = computed_values.margin().right().to_px(node, m_containing_block_used_values.content_width());
|
||||
used_values.border_right = computed_values.border_right().width;
|
||||
used_values.padding_right = computed_values.padding().right().to_px(node, m_container_state.content_width());
|
||||
used_values.padding_right = computed_values.padding().right().to_px(node, m_containing_block_used_values.content_width());
|
||||
|
||||
m_extra_trailing_metrics->margin += used_values.margin_right;
|
||||
m_extra_trailing_metrics->border += used_values.border_right;
|
||||
|
@ -107,7 +107,7 @@ void InlineLevelIterator::compute_next()
|
|||
if (m_next_node == nullptr)
|
||||
return;
|
||||
do {
|
||||
m_next_node = next_inline_node_in_pre_order(*m_next_node, m_container);
|
||||
m_next_node = next_inline_node_in_pre_order(*m_next_node, m_containing_block);
|
||||
} while (m_next_node && (!m_next_node->is_inline() && !m_next_node->is_out_of_flow(m_inline_formatting_context)));
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
InlineLevelIterator(Layout::InlineFormattingContext&, LayoutState&, Layout::BlockContainer const&, LayoutMode);
|
||||
InlineLevelIterator(Layout::InlineFormattingContext&, LayoutState&, Layout::BlockContainer const& containing_block, LayoutState::UsedValues const& containing_block_used_values, LayoutMode);
|
||||
|
||||
Optional<Item> next();
|
||||
CSSPixels next_non_whitespace_sequence_width();
|
||||
|
@ -71,8 +71,8 @@ private:
|
|||
|
||||
Layout::InlineFormattingContext& m_inline_formatting_context;
|
||||
Layout::LayoutState& m_layout_state;
|
||||
JS::NonnullGCPtr<Layout::BlockContainer const> m_container;
|
||||
Layout::LayoutState::UsedValues const& m_container_state;
|
||||
JS::NonnullGCPtr<BlockContainer const> m_containing_block;
|
||||
LayoutState::UsedValues const& m_containing_block_used_values;
|
||||
JS::GCPtr<Layout::Node const> m_current_node;
|
||||
JS::GCPtr<Layout::Node const> m_next_node;
|
||||
LayoutMode const m_layout_mode;
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
namespace Web::Layout {
|
||||
|
||||
LineBuilder::LineBuilder(InlineFormattingContext& context, LayoutState& layout_state)
|
||||
LineBuilder::LineBuilder(InlineFormattingContext& context, LayoutState& layout_state, LayoutState::UsedValues& containing_block_used_values)
|
||||
: m_context(context)
|
||||
, m_layout_state(layout_state)
|
||||
, m_containing_block_state(layout_state.get_mutable(context.containing_block()))
|
||||
, m_containing_block_used_values(containing_block_used_values)
|
||||
{
|
||||
m_text_indent = m_context.containing_block().computed_values().text_indent().to_px(m_context.containing_block(), m_containing_block_state.content_width());
|
||||
m_text_indent = m_context.containing_block().computed_values().text_indent().to_px(m_context.containing_block(), m_containing_block_used_values.content_width());
|
||||
begin_new_line(false);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ void LineBuilder::break_line(ForcedBreak forced_break, Optional<CSSPixels> next_
|
|||
size_t break_count = 0;
|
||||
bool floats_intrude_at_current_y = false;
|
||||
do {
|
||||
m_containing_block_state.line_boxes.append(LineBox());
|
||||
m_containing_block_used_values.line_boxes.append(LineBox());
|
||||
begin_new_line(true, break_count == 0);
|
||||
break_count++;
|
||||
floats_intrude_at_current_y = m_context.any_floats_intrude_at_y(m_current_y);
|
||||
|
@ -71,14 +71,14 @@ void LineBuilder::begin_new_line(bool increment_y, bool is_first_break_in_sequen
|
|||
m_last_line_needs_update = true;
|
||||
|
||||
// FIXME: Support text-indent with "each-line".
|
||||
if (m_containing_block_state.line_boxes.size() <= 1) {
|
||||
if (m_containing_block_used_values.line_boxes.size() <= 1) {
|
||||
ensure_last_line_box().m_width += m_text_indent;
|
||||
}
|
||||
}
|
||||
|
||||
LineBox& LineBuilder::ensure_last_line_box()
|
||||
{
|
||||
auto& line_boxes = m_containing_block_state.line_boxes;
|
||||
auto& line_boxes = m_containing_block_used_values.line_boxes;
|
||||
if (line_boxes.is_empty())
|
||||
line_boxes.append(LineBox {});
|
||||
return line_boxes.last();
|
||||
|
@ -92,7 +92,7 @@ void LineBuilder::append_box(Box const& box, CSSPixels leading_size, CSSPixels t
|
|||
m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.margin_box_height());
|
||||
|
||||
box_state.containing_line_box_fragment = LineBoxFragmentCoordinate {
|
||||
.line_box_index = m_containing_block_state.line_boxes.size() - 1,
|
||||
.line_box_index = m_containing_block_used_values.line_boxes.size() - 1,
|
||||
.fragment_index = line_box.fragments().size() - 1,
|
||||
};
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ bool LineBuilder::should_break(CSSPixels next_item_width)
|
|||
if (m_available_width_for_current_line.is_max_content())
|
||||
return false;
|
||||
|
||||
auto const& line_boxes = m_containing_block_state.line_boxes;
|
||||
auto const& line_boxes = m_containing_block_used_values.line_boxes;
|
||||
if (line_boxes.is_empty() || line_boxes.last().is_empty()) {
|
||||
// If we don't have a single line box yet *and* there are no floats intruding
|
||||
// at this Y coordinate, we don't need to break before inserting anything.
|
||||
|
@ -155,7 +155,7 @@ bool LineBuilder::should_break(CSSPixels next_item_width)
|
|||
void LineBuilder::update_last_line()
|
||||
{
|
||||
m_last_line_needs_update = false;
|
||||
auto& line_boxes = m_containing_block_state.line_boxes;
|
||||
auto& line_boxes = m_containing_block_used_values.line_boxes;
|
||||
|
||||
if (line_boxes.is_empty())
|
||||
return;
|
||||
|
@ -330,7 +330,7 @@ void LineBuilder::update_last_line()
|
|||
void LineBuilder::remove_last_line_if_empty()
|
||||
{
|
||||
// If there's an empty line box at the bottom, just remove it instead of giving it height.
|
||||
auto& line_boxes = m_containing_block_state.line_boxes;
|
||||
auto& line_boxes = m_containing_block_used_values.line_boxes;
|
||||
if (!line_boxes.is_empty() && line_boxes.last().is_empty()) {
|
||||
line_boxes.take_last();
|
||||
m_last_line_needs_update = false;
|
||||
|
@ -343,8 +343,8 @@ void LineBuilder::recalculate_available_space()
|
|||
auto available_at_top_of_line_box = m_context.available_space_for_line(m_current_y);
|
||||
auto available_at_bottom_of_line_box = m_context.available_space_for_line(m_current_y + current_line_height - 1);
|
||||
m_available_width_for_current_line = min(available_at_bottom_of_line_box, available_at_top_of_line_box);
|
||||
if (!m_containing_block_state.line_boxes.is_empty())
|
||||
m_containing_block_state.line_boxes.last().m_original_available_width = m_available_width_for_current_line;
|
||||
if (!m_containing_block_used_values.line_boxes.is_empty())
|
||||
m_containing_block_used_values.line_boxes.last().m_original_available_width = m_available_width_for_current_line;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class LineBuilder {
|
|||
AK_MAKE_NONMOVABLE(LineBuilder);
|
||||
|
||||
public:
|
||||
LineBuilder(InlineFormattingContext&, LayoutState&);
|
||||
LineBuilder(InlineFormattingContext&, LayoutState&, LayoutState::UsedValues& containing_block_used_values);
|
||||
~LineBuilder();
|
||||
|
||||
enum class ForcedBreak {
|
||||
|
@ -58,7 +58,7 @@ private:
|
|||
|
||||
InlineFormattingContext& m_context;
|
||||
LayoutState& m_layout_state;
|
||||
LayoutState::UsedValues& m_containing_block_state;
|
||||
LayoutState::UsedValues& m_containing_block_used_values;
|
||||
AvailableSize m_available_width_for_current_line { AvailableSize::make_indefinite() };
|
||||
CSSPixels m_current_y { 0 };
|
||||
CSSPixels m_max_height_on_current_line { 0 };
|
||||
|
|
Loading…
Add table
Reference in a new issue