diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 701a6e3c6e2..188326e9ca5 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -1924,6 +1924,11 @@ void Node::set_paintable(JS::GCPtr paintable) m_paintable = paintable; } +void Node::clear_paintable() +{ + m_paintable = nullptr; +} + Painting::Paintable const* Node::paintable() const { return m_paintable; diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index 615b5c08d5d..694845d5506 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -248,6 +248,7 @@ public: Painting::Paintable* paintable(); void set_paintable(JS::GCPtr); + void clear_paintable(); void set_layout_node(Badge, JS::NonnullGCPtr); void detach_layout_node(Badge); diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index 07af38d5bb6..12ed05b39b2 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index d2b25311403..dd14b630826 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace Web::Layout { diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index 02bc67fc773..139532460c6 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -221,11 +221,11 @@ void LayoutState::commit(Box& root) // from the layout tree. This is done to ensure that we don't end up with any old-tree pointers // when text paintables shift around in the tree. root.for_each_in_inclusive_subtree([&](Layout::Node& node) { - node.set_paintable(nullptr); + node.clear_paintables(); return TraversalDecision::Continue; }); root.document().for_each_shadow_including_inclusive_descendant([&](DOM::Node& node) { - node.set_paintable(nullptr); + node.clear_paintable(); return TraversalDecision::Continue; }); @@ -248,7 +248,7 @@ void LayoutState::commit(Box& root) auto paintable = node.create_paintable(); - node.set_paintable(paintable); + node.add_paintable(paintable); // For boxes, transfer all the state needed for painting. if (paintable && is(*paintable)) { @@ -351,7 +351,7 @@ void LayoutState::commit(Box& root) } for (auto* text_node : text_nodes) { - text_node->set_paintable(text_node->create_paintable()); + text_node->add_paintable(text_node->create_paintable()); auto* paintable = text_node->paintable(); auto const& font = text_node->first_available_font(); auto const glyph_height = CSSPixels::nearest_value_for(font.pixel_size()); diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp index 4ccd5d3fa5b..c37ffdb9544 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index d5a88905abe..aa9b4f10667 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -48,7 +48,9 @@ void Node::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_dom_node); - visitor.visit(m_paintable); + for (auto const& paintable : m_paintable) { + visitor.visit(JS::GCPtr { &paintable }); + } visitor.visit(m_pseudo_element_generator); TreeNode::visit_edges(visitor); } @@ -1015,9 +1017,16 @@ void NodeWithStyle::transfer_table_box_computed_values_to_wrapper_computed_value reset_table_box_computed_values_used_by_wrapper_to_init_values(); } -void Node::set_paintable(JS::GCPtr paintable) +void Node::add_paintable(JS::GCPtr paintable) { - m_paintable = move(paintable); + if (!paintable) + return; + m_paintable.append(*paintable); +} + +void Node::clear_paintables() +{ + m_paintable.clear(); } JS::GCPtr Node::create_paintable() const diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 80391bef8e7..1b488224da9 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace Web::Layout { @@ -64,9 +65,12 @@ public: m_pseudo_element_generator = &element; } - Painting::Paintable* paintable() { return m_paintable; } - Painting::Paintable const* paintable() const { return m_paintable; } - void set_paintable(JS::GCPtr); + using PaintableList = IntrusiveList<&Painting::Paintable::m_list_node>; + + Painting::Paintable* paintable() { return m_paintable.first(); } + Painting::Paintable const* paintable() const { return m_paintable.first(); } + void add_paintable(JS::GCPtr); + void clear_paintables(); virtual JS::GCPtr create_paintable() const; @@ -181,7 +185,7 @@ private: friend class NodeWithStyle; JS::NonnullGCPtr m_dom_node; - JS::GCPtr m_paintable; + PaintableList m_paintable; JS::GCPtr m_pseudo_element_generator; diff --git a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp index 448b0e34160..2ca9a1b4d47 100644 --- a/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -309,7 +309,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node, TreeBuilder::Context& if (!layout_node) { dom_node.for_each_in_inclusive_subtree([&](auto& node) { node.detach_layout_node({}); - node.set_paintable(nullptr); + node.clear_paintable(); if (is(node)) static_cast(node).clear_pseudo_element_nodes({}); return TraversalDecision::Continue; diff --git a/Userland/Libraries/LibWeb/Layout/Viewport.cpp b/Userland/Libraries/LibWeb/Layout/Viewport.cpp index d74fc94ad73..533d6e81500 100644 --- a/Userland/Libraries/LibWeb/Layout/Viewport.cpp +++ b/Userland/Libraries/LibWeb/Layout/Viewport.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index d7273e0af9a..121e5fba973 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.cpp b/Userland/Libraries/LibWeb/Painting/Paintable.cpp index 8e792403f01..a8cd8e35e4b 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/Paintable.cpp @@ -51,6 +51,38 @@ bool Paintable::is_visible() const return computed_values.visibility() == CSS::Visibility::Visible && computed_values.opacity() != 0; } +DOM::Document const& Paintable::document() const +{ + return layout_node().document(); +} + +DOM::Document& Paintable::document() +{ + return layout_node().document(); +} + +CSS::Display Paintable::display() const +{ + return layout_node().display(); +} + +PaintableBox* Paintable::containing_block() const +{ + if (!m_containing_block.has_value()) { + auto containing_layout_box = m_layout_node->containing_block(); + if (containing_layout_box) + m_containing_block = const_cast(containing_layout_box->paintable_box()); + else + m_containing_block = nullptr; + } + return *m_containing_block; +} + +CSS::ImmutableComputedValues const& Paintable::computed_values() const +{ + return m_layout_node->computed_values(); +} + void Paintable::set_dom_node(JS::GCPtr dom_node) { m_dom_node = dom_node; diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index 74a582675e3..6da2d9aabb5 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -7,10 +7,11 @@ #pragma once #include +#include #include -#include #include -#include +#include +#include namespace Web::Painting { @@ -62,7 +63,7 @@ public: [[nodiscard]] bool is_floating() const { return m_floating; } [[nodiscard]] bool is_inline() const { return m_inline; } [[nodiscard]] bool is_selected() const { return m_selected; } - [[nodiscard]] CSS::Display display() const { return layout_node().display(); } + [[nodiscard]] CSS::Display display() const; template TraversalDecision for_each_in_inclusive_subtree_of_type(Callback callback) @@ -194,7 +195,7 @@ public: [[nodiscard]] JS::GCPtr dom_node() const; void set_dom_node(JS::GCPtr); - auto const& computed_values() const { return m_layout_node->computed_values(); } + CSS::ImmutableComputedValues const& computed_values() const; bool visible_for_hit_testing() const { return computed_values().pointer_events() != CSS::PointerEvents::None; } @@ -202,17 +203,7 @@ public: virtual void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes); - PaintableBox* containing_block() const - { - if (!m_containing_block.has_value()) { - auto containing_layout_box = m_layout_node->containing_block(); - if (containing_layout_box) - m_containing_block = const_cast(containing_layout_box->paintable_box()); - else - m_containing_block = nullptr; - } - return *m_containing_block; - } + PaintableBox* containing_block() const; template bool fast_is() const = delete; @@ -223,8 +214,8 @@ public: [[nodiscard]] virtual bool is_svg_paintable() const { return false; } [[nodiscard]] virtual bool is_text_paintable() const { return false; } - DOM::Document const& document() const { return layout_node().document(); } - DOM::Document& document() { return layout_node().document(); } + DOM::Document const& document() const; + DOM::Document& document(); CSSPixelPoint box_type_agnostic_position() const; @@ -242,7 +233,15 @@ public: Gfx::AffineTransform compute_combined_css_transform() const; - virtual void resolve_paint_properties() {}; + virtual void resolve_paint_properties() { } + + virtual void finalize() override + { + if (m_list_node.is_in_list()) + m_list_node.remove(); + } + + friend class Layout::Node; protected: explicit Paintable(Layout::Node const&); @@ -250,6 +249,7 @@ protected: virtual void visit_edges(Cell::Visitor&) override; private: + IntrusiveListNode m_list_node; JS::GCPtr m_dom_node; JS::NonnullGCPtr m_layout_node; Optional> mutable m_containing_block; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index ade8d75422a..7543940e0f8 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -7,6 +7,8 @@ #pragma once #include +#include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/Painting/TextPaintable.h b/Userland/Libraries/LibWeb/Painting/TextPaintable.h index 3d4a309ccb0..647b0ccbf50 100644 --- a/Userland/Libraries/LibWeb/Painting/TextPaintable.h +++ b/Userland/Libraries/LibWeb/Painting/TextPaintable.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace Web::Painting { diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 26d658ed1ab..69164e55d4e 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include