mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 08:41:15 +00:00
LibWeb: Build stacking context tree lazily
There's no actual need to build the stacking context tree before performing layout. Instead, make it lazy and build the tree when it's actually needed for something. This avoids a bunch of work in situations where multiple synchronous layouts are forced (typically by JavaScript) without painting or hit testing taking place in between. It also opens up for style invalidations that only target the stacking context tree.
This commit is contained in:
parent
89086c337c
commit
59afdb959f
Notes:
sideshowbarker
2024-07-17 17:00:08 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/59afdb959f
|
@ -585,8 +585,6 @@ void Document::update_layout()
|
|||
root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Normal);
|
||||
formatting_state.commit();
|
||||
|
||||
m_layout_root->build_stacking_context_tree();
|
||||
|
||||
browsing_context()->set_needs_display();
|
||||
|
||||
if (browsing_context()->is_top_level()) {
|
||||
|
|
|
@ -18,13 +18,19 @@ InitialContainingBlock::InitialContainingBlock(DOM::Document& document, NonnullR
|
|||
|
||||
InitialContainingBlock::~InitialContainingBlock() = default;
|
||||
|
||||
void InitialContainingBlock::build_stacking_context_tree_if_needed()
|
||||
{
|
||||
if (paint_box()->stacking_context())
|
||||
return;
|
||||
build_stacking_context_tree();
|
||||
}
|
||||
|
||||
void InitialContainingBlock::build_stacking_context_tree()
|
||||
{
|
||||
const_cast<Painting::PaintableWithLines*>(paint_box())->set_stacking_context(make<Painting::StackingContext>(*this, nullptr));
|
||||
|
||||
for_each_in_inclusive_subtree_of_type<Box>([&](Box& box) {
|
||||
if (&box == this)
|
||||
return IterationDecision::Continue;
|
||||
for_each_in_subtree_of_type<Box>([&](Box& box) {
|
||||
const_cast<Painting::PaintableBox*>(box.paint_box())->invalidate_stacking_context();
|
||||
if (!box.establishes_stacking_context()) {
|
||||
VERIFY(!box.paint_box()->stacking_context());
|
||||
return IterationDecision::Continue;
|
||||
|
@ -40,6 +46,7 @@ void InitialContainingBlock::build_stacking_context_tree()
|
|||
|
||||
void InitialContainingBlock::paint_all_phases(PaintContext& context)
|
||||
{
|
||||
build_stacking_context_tree_if_needed();
|
||||
context.painter().fill_rect(enclosing_int_rect(paint_box()->absolute_rect()), context.palette().base());
|
||||
context.painter().translate(-context.viewport_rect().location());
|
||||
paint_box()->stacking_context()->paint(context);
|
||||
|
|
|
@ -24,11 +24,11 @@ public:
|
|||
void set_selection(const LayoutRange&);
|
||||
void set_selection_end(const LayoutPosition&);
|
||||
|
||||
void build_stacking_context_tree();
|
||||
|
||||
void build_stacking_context_tree_if_needed();
|
||||
void recompute_selection_states();
|
||||
|
||||
private:
|
||||
void build_stacking_context_tree();
|
||||
virtual bool is_initial_containing_block_box() const override { return true; }
|
||||
|
||||
LayoutRange m_selection;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||
#include <LibWeb/Layout/BlockContainer.h>
|
||||
#include <LibWeb/Layout/InitialContainingBlock.h>
|
||||
#include <LibWeb/Painting/BackgroundPainting.h>
|
||||
#include <LibWeb/Painting/PaintableBox.h>
|
||||
#include <LibWeb/Painting/ShadowPainting.h>
|
||||
|
@ -28,6 +29,11 @@ PaintableBox::~PaintableBox()
|
|||
{
|
||||
}
|
||||
|
||||
void PaintableBox::invalidate_stacking_context()
|
||||
{
|
||||
m_stacking_context = nullptr;
|
||||
}
|
||||
|
||||
PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box)
|
||||
: PaintableBox(layout_box)
|
||||
{
|
||||
|
@ -524,8 +530,10 @@ void PaintableBox::for_each_child_in_paint_order(Callback callback) const
|
|||
|
||||
HitTestResult PaintableBox::hit_test(Gfx::FloatPoint const& position, HitTestType type) const
|
||||
{
|
||||
if (layout_box().is_initial_containing_block_box())
|
||||
if (layout_box().is_initial_containing_block_box()) {
|
||||
const_cast<Layout::InitialContainingBlock&>(static_cast<Layout::InitialContainingBlock const&>(layout_box())).build_stacking_context_tree_if_needed();
|
||||
return stacking_context()->hit_test(position, type);
|
||||
}
|
||||
|
||||
HitTestResult result { absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
for_each_child_in_paint_order([&](auto& child) {
|
||||
|
|
|
@ -117,6 +117,8 @@ public:
|
|||
|
||||
virtual HitTestResult hit_test(Gfx::FloatPoint const&, HitTestType) const override;
|
||||
|
||||
void invalidate_stacking_context();
|
||||
|
||||
protected:
|
||||
explicit PaintableBox(Layout::Box const&);
|
||||
|
||||
|
|
Loading…
Reference in a new issue