mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:37:35 +00:00
LibWeb: Limit style update tree traversal to dirty subtrees
This patch adds a second style dirty bit that tracks whether a DOM node has one or more children with dirty style. This allows the style update to skip over entire subtrees where all nodes are clean.
This commit is contained in:
parent
d1479aef56
commit
6809be436b
3 changed files with 32 additions and 7 deletions
|
@ -400,13 +400,25 @@ void Document::update_layout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::update_style()
|
static void update_style_recursively(DOM::Node& node)
|
||||||
{
|
{
|
||||||
for_each_in_subtree_of_type<Element>([&](auto& element) {
|
node.for_each_child([&](auto& child) {
|
||||||
if (element.needs_style_update())
|
if (child.needs_style_update()) {
|
||||||
element.recompute_style();
|
if (is<Element>(child))
|
||||||
|
downcast<Element>(child).recompute_style();
|
||||||
|
child.set_needs_style_update(false);
|
||||||
|
}
|
||||||
|
if (child.child_needs_style_update()) {
|
||||||
|
update_style_recursively(child);
|
||||||
|
child.set_child_needs_style_update(false);
|
||||||
|
}
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::update_style()
|
||||||
|
{
|
||||||
|
update_style_recursively(*this);
|
||||||
update_layout();
|
update_layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -254,8 +254,17 @@ void Node::set_needs_style_update(bool value)
|
||||||
if (m_needs_style_update == value)
|
if (m_needs_style_update == value)
|
||||||
return;
|
return;
|
||||||
m_needs_style_update = value;
|
m_needs_style_update = value;
|
||||||
if (m_needs_style_update)
|
|
||||||
|
if (m_needs_style_update) {
|
||||||
|
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent())
|
||||||
|
ancestor->m_child_needs_style_update = true;
|
||||||
document().schedule_style_update();
|
document().schedule_style_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::inserted_into(Node&)
|
||||||
|
{
|
||||||
|
set_needs_style_update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ public:
|
||||||
Element* parent_element();
|
Element* parent_element();
|
||||||
const Element* parent_element() const;
|
const Element* parent_element() const;
|
||||||
|
|
||||||
virtual void inserted_into(Node&) { }
|
virtual void inserted_into(Node&);
|
||||||
virtual void removed_from(Node&) { }
|
virtual void removed_from(Node&) { }
|
||||||
virtual void children_changed() { }
|
virtual void children_changed() { }
|
||||||
|
|
||||||
|
@ -140,6 +140,9 @@ public:
|
||||||
bool needs_style_update() const { return m_needs_style_update; }
|
bool needs_style_update() const { return m_needs_style_update; }
|
||||||
void set_needs_style_update(bool);
|
void set_needs_style_update(bool);
|
||||||
|
|
||||||
|
bool child_needs_style_update() const { return m_child_needs_style_update; }
|
||||||
|
void set_child_needs_style_update(bool b) { m_child_needs_style_update = b; }
|
||||||
|
|
||||||
void invalidate_style();
|
void invalidate_style();
|
||||||
|
|
||||||
bool is_link() const;
|
bool is_link() const;
|
||||||
|
@ -157,7 +160,8 @@ protected:
|
||||||
Document* m_document { nullptr };
|
Document* m_document { nullptr };
|
||||||
mutable WeakPtr<Layout::Node> m_layout_node;
|
mutable WeakPtr<Layout::Node> m_layout_node;
|
||||||
NodeType m_type { NodeType::INVALID };
|
NodeType m_type { NodeType::INVALID };
|
||||||
bool m_needs_style_update { true };
|
bool m_needs_style_update { false };
|
||||||
|
bool m_child_needs_style_update { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue