mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibWeb: Resolve relpos fragment offsets only for inline paintables
Prior to this change, we iterated through all fragments within each PaintableWithLines to resolve the relative position offset. This happened before transferring the fragments to their corresponding inline paintables. With this change, we significantly reduce amount of work by attempting to resolve relative position offsets only for those contained within inline paintables. Performance improvement on https://html.spec.whatwg.org/
This commit is contained in:
parent
de9fa25e11
commit
b317620486
Notes:
sideshowbarker
2024-07-16 22:26:05 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/b317620486 Pull-request: https://github.com/SerenityOS/serenity/pull/22843
2 changed files with 46 additions and 36 deletions
|
@ -139,48 +139,22 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box)
|
|||
return scrollable_overflow_rect;
|
||||
}
|
||||
|
||||
void LayoutState::resolve_relative_positions(Vector<Painting::PaintableWithLines&> const& paintables_with_lines)
|
||||
void LayoutState::resolve_relative_positions()
|
||||
{
|
||||
// This function resolves relative position offsets of all the boxes & fragments in the paint tree.
|
||||
// This function resolves relative position offsets of fragments that belong to inline paintables.
|
||||
// It runs *after* the paint tree has been constructed, so it modifies paintable node & fragment offsets directly.
|
||||
|
||||
// Regular boxes (not line box fragments):
|
||||
for (auto& it : used_values_per_layout_node) {
|
||||
auto& used_values = *it.value;
|
||||
auto& node = const_cast<NodeWithStyle&>(used_values.node());
|
||||
|
||||
if (!node.is_box())
|
||||
auto* paintable = node.paintable();
|
||||
if (!paintable)
|
||||
continue;
|
||||
if (!is<Painting::InlinePaintable>(*paintable))
|
||||
continue;
|
||||
|
||||
auto& paintable = static_cast<Painting::PaintableBox&>(*node.paintable());
|
||||
CSSPixelPoint offset;
|
||||
|
||||
if (used_values.containing_line_box_fragment.has_value()) {
|
||||
// Atomic inline case:
|
||||
// We know that `node` is an atomic inline because `containing_line_box_fragments` refers to the
|
||||
// line box fragment in the parent block container that contains it.
|
||||
auto const& containing_line_box_fragment = used_values.containing_line_box_fragment.value();
|
||||
auto const& containing_block = *node.containing_block();
|
||||
auto const& containing_block_used_values = get(containing_block);
|
||||
auto const& fragment = containing_block_used_values.line_boxes[containing_line_box_fragment.line_box_index].fragments()[containing_line_box_fragment.fragment_index];
|
||||
|
||||
// The fragment has the final offset for the atomic inline, so we just need to copy it from there.
|
||||
offset = fragment.offset();
|
||||
} else {
|
||||
// Not an atomic inline, much simpler case.
|
||||
offset = used_values.offset;
|
||||
}
|
||||
// Apply relative position inset if appropriate.
|
||||
if (node.computed_values().position() == CSS::Positioning::Relative && is<NodeWithStyleAndBoxModelMetrics>(node)) {
|
||||
auto& inset = static_cast<NodeWithStyleAndBoxModelMetrics const&>(node).box_model().inset;
|
||||
offset.translate_by(inset.left, inset.top);
|
||||
}
|
||||
paintable.set_offset(offset);
|
||||
}
|
||||
|
||||
// Line box fragments:
|
||||
for (auto const& paintable_with_lines : paintables_with_lines) {
|
||||
for (auto& fragment : paintable_with_lines.fragments()) {
|
||||
auto const& inline_paintable = static_cast<Painting::InlinePaintable&>(*paintable);
|
||||
for (auto& fragment : inline_paintable.fragments()) {
|
||||
auto const& fragment_node = fragment.layout_node();
|
||||
if (!is<Layout::NodeWithStyleAndBoxModelMetrics>(*fragment_node.parent()))
|
||||
continue;
|
||||
|
@ -489,7 +463,41 @@ void LayoutState::commit(Box& root)
|
|||
}
|
||||
}
|
||||
|
||||
resolve_relative_positions(paintables_with_lines);
|
||||
// Resolve relative positions for regular boxes (not line box fragments):
|
||||
// NOTE: This needs to occur before fragments are transferred into the corresponding inline paintables, because
|
||||
// after this transfer, the containing_line_box_fragment will no longer be valid.
|
||||
for (auto& it : used_values_per_layout_node) {
|
||||
auto& used_values = *it.value;
|
||||
auto& node = const_cast<NodeWithStyle&>(used_values.node());
|
||||
|
||||
if (!node.is_box())
|
||||
continue;
|
||||
|
||||
auto& paintable = static_cast<Painting::PaintableBox&>(*node.paintable());
|
||||
CSSPixelPoint offset;
|
||||
|
||||
if (used_values.containing_line_box_fragment.has_value()) {
|
||||
// Atomic inline case:
|
||||
// We know that `node` is an atomic inline because `containing_line_box_fragments` refers to the
|
||||
// line box fragment in the parent block container that contains it.
|
||||
auto const& containing_line_box_fragment = used_values.containing_line_box_fragment.value();
|
||||
auto const& containing_block = *node.containing_block();
|
||||
auto const& containing_block_used_values = get(containing_block);
|
||||
auto const& fragment = containing_block_used_values.line_boxes[containing_line_box_fragment.line_box_index].fragments()[containing_line_box_fragment.fragment_index];
|
||||
|
||||
// The fragment has the final offset for the atomic inline, so we just need to copy it from there.
|
||||
offset = fragment.offset();
|
||||
} else {
|
||||
// Not an atomic inline, much simpler case.
|
||||
offset = used_values.offset;
|
||||
}
|
||||
// Apply relative position inset if appropriate.
|
||||
if (node.computed_values().position() == CSS::Positioning::Relative && is<NodeWithStyleAndBoxModelMetrics>(node)) {
|
||||
auto const& inset = static_cast<NodeWithStyleAndBoxModelMetrics const&>(node).box_model().inset;
|
||||
offset.translate_by(inset.left, inset.top);
|
||||
}
|
||||
paintable.set_offset(offset);
|
||||
}
|
||||
|
||||
// Make a pass over all the line boxes to:
|
||||
// - Collect all text nodes, so we can create paintables for them later.
|
||||
|
@ -522,6 +530,8 @@ void LayoutState::commit(Box& root)
|
|||
|
||||
build_paint_tree(root);
|
||||
|
||||
resolve_relative_positions();
|
||||
|
||||
// Measure overflow in scroll containers.
|
||||
for (auto& it : used_values_per_layout_node) {
|
||||
auto& used_values = *it.value;
|
||||
|
|
|
@ -188,7 +188,7 @@ struct LayoutState {
|
|||
LayoutState const& m_root;
|
||||
|
||||
private:
|
||||
void resolve_relative_positions(Vector<Painting::PaintableWithLines&> const&);
|
||||
void resolve_relative_positions();
|
||||
void resolve_border_radii();
|
||||
void resolve_box_shadow_data();
|
||||
void resolve_text_shadows(Vector<Painting::PaintableWithLines&> const& paintables_with_lines);
|
||||
|
|
Loading…
Reference in a new issue