From d9b2650dcc53943a5a5ab837f598365652afda5b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 6 Jan 2021 14:10:53 +0100 Subject: [PATCH] LibWeb: Remove specified style from layout nodes Layout nodes now only carry CSS computer values with them. The main idea here is to give them only what they need to perform layout, and leave the rest back in the DOM. --- Libraries/LibWeb/CSS/ComputedValues.h | 7 ++++++ Libraries/LibWeb/DOM/Element.cpp | 1 - Libraries/LibWeb/Layout/BlockBox.cpp | 5 +++++ Libraries/LibWeb/Layout/BlockBox.h | 1 + Libraries/LibWeb/Layout/Box.h | 5 +++++ Libraries/LibWeb/Layout/Node.cpp | 21 ++++++++++++++++-- Libraries/LibWeb/Layout/Node.h | 20 +++++++---------- Libraries/LibWeb/Layout/TextNode.h | 2 -- Libraries/LibWeb/Layout/TreeBuilder.cpp | 29 +++++++++---------------- Libraries/LibWeb/Layout/TreeBuilder.h | 4 ++-- 10 files changed, 57 insertions(+), 38 deletions(-) diff --git a/Libraries/LibWeb/CSS/ComputedValues.h b/Libraries/LibWeb/CSS/ComputedValues.h index 35025f9b17f..588468ced75 100644 --- a/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Libraries/LibWeb/CSS/ComputedValues.h @@ -84,6 +84,13 @@ public: CSS::ListStyleType list_style_type() const { return m_inherited.list_style_type; } + ComputedValues clone_inherited_values() const + { + ComputedValues clone; + clone.m_inherited = m_inherited; + return clone; + } + protected: struct { Color color { InitialValues::color() }; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 2746e67eb20..e23b5ccb66c 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -220,7 +220,6 @@ void Element::recompute_style() diff = compute_style_difference(*old_specified_css_values, *new_specified_css_values, document()); if (diff == StyleDifference::None) return; - layout_node()->set_specified_style(*new_specified_css_values); layout_node()->apply_style(*new_specified_css_values); if (diff == StyleDifference::NeedsRelayout) { document().force_layout(); diff --git a/Libraries/LibWeb/Layout/BlockBox.cpp b/Libraries/LibWeb/Layout/BlockBox.cpp index b25a4598865..aab1430afc0 100644 --- a/Libraries/LibWeb/Layout/BlockBox.cpp +++ b/Libraries/LibWeb/Layout/BlockBox.cpp @@ -44,6 +44,11 @@ BlockBox::BlockBox(DOM::Document& document, DOM::Node* node, NonnullRefPtr); + BlockBox(DOM::Document&, DOM::Node*, CSS::ComputedValues); virtual ~BlockBox() override; virtual void paint(PaintContext&, PaintPhase) override; diff --git a/Libraries/LibWeb/Layout/Box.h b/Libraries/LibWeb/Layout/Box.h index a9517b6437d..b43f969fad3 100644 --- a/Libraries/LibWeb/Layout/Box.h +++ b/Libraries/LibWeb/Layout/Box.h @@ -113,6 +113,11 @@ protected: { } + Box(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values) + : NodeWithStyleAndBoxModelMetrics(document, node, move(computed_values)) + { + } + virtual void did_set_rect() { } Vector m_line_boxes; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 14e007a9063..e447976bf67 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -205,10 +205,16 @@ bool Node::is_fixed_position() const NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, NonnullRefPtr specified_style) : Node(document, node) - , m_specified_style(move(specified_style)) { m_has_style = true; - apply_style(*m_specified_style); + apply_style(*specified_style); +} + +NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values) + : Node(document, node) + , m_computed_values(move(computed_values)) +{ + m_has_style = true; } void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style) @@ -315,4 +321,15 @@ bool Node::is_inline_block() const { return is_inline() && is(*this); } + +NonnullRefPtr NodeWithStyle::create_anonymous_wrapper() const +{ + auto wrapper = adopt(*new BlockBox(const_cast(document()), nullptr, m_computed_values.clone_inherited_values())); + wrapper->m_font = m_font; + wrapper->m_font_size = m_font_size; + wrapper->m_line_height = m_line_height; + wrapper->m_background_image = m_background_image; + return wrapper; +} + } diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index d59cec6ebe5..de7ed3e7bf1 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -126,7 +126,6 @@ public: bool can_contain_boxes_with_position_absolute() const; const Gfx::Font& font() const; - const CSS::StyleProperties& specified_style() const; const CSS::ImmutableComputedValues& computed_values() const; NodeWithStyle* parent(); @@ -198,9 +197,6 @@ class NodeWithStyle : public Node { public: virtual ~NodeWithStyle() override { } - const CSS::StyleProperties& specified_style() const { return m_specified_style; } - void set_specified_style(const CSS::StyleProperties& style) { m_specified_style = style; } - const CSS::ImmutableComputedValues& computed_values() const { return static_cast(m_computed_values); } void apply_style(const CSS::StyleProperties&); @@ -210,8 +206,11 @@ public: float font_size() const { return m_font_size; } const CSS::ImageStyleValue* background_image() const { return m_background_image; } + NonnullRefPtr create_anonymous_wrapper() const; + protected: NodeWithStyle(DOM::Document&, DOM::Node*, NonnullRefPtr); + NodeWithStyle(DOM::Document&, DOM::Node*, CSS::ComputedValues); private: CSS::ComputedValues m_computed_values; @@ -220,7 +219,6 @@ private: float m_font_size { 0 }; RefPtr m_background_image; - NonnullRefPtr m_specified_style; CSS::Position m_position; }; @@ -235,6 +233,11 @@ protected: { } + NodeWithStyleAndBoxModelMetrics(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values) + : NodeWithStyle(document, node, move(computed_values)) + { + } + private: BoxModelMetrics m_box_model; }; @@ -253,13 +256,6 @@ inline float Node::font_size() const return parent()->font_size(); } -inline const CSS::StyleProperties& Node::specified_style() const -{ - if (m_has_style) - return static_cast(this)->specified_style(); - return parent()->specified_style(); -} - inline const CSS::ImmutableComputedValues& Node::computed_values() const { if (m_has_style) diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h index 85189a77b4b..0752689cc08 100644 --- a/Libraries/LibWeb/Layout/TextNode.h +++ b/Libraries/LibWeb/Layout/TextNode.h @@ -47,8 +47,6 @@ public: virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override; - const CSS::StyleProperties& specified_style() const { return parent()->specified_style(); } - private: void split_into_lines_by_rules(InlineFormattingContext&, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks); void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const; diff --git a/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Libraries/LibWeb/Layout/TreeBuilder.cpp index 2f3831f58de..e73507c140b 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -37,22 +38,10 @@ TreeBuilder::TreeBuilder() { } -static NonnullRefPtr style_for_anonymous_block(Node& parent_box) -{ - auto new_style = CSS::StyleProperties::create(); - - parent_box.specified_style().for_each_property([&](auto property_id, auto& value) { - if (CSS::StyleResolver::is_inherited_property(property_id)) - new_style->set_property(property_id, value); - }); - - return new_style; -} - // The insertion_parent_for_*() functions maintain the invariant that block-level boxes must have either // only block-level children or only inline-level children. -static Layout::Node& insertion_parent_for_inline_node(Layout::Node& layout_parent, Layout::Node& layout_node) +static Layout::Node& insertion_parent_for_inline_node(Layout::NodeWithStyle& layout_parent) { if (layout_parent.is_inline() && !layout_parent.is_inline_block()) return layout_parent; @@ -62,7 +51,7 @@ static Layout::Node& insertion_parent_for_inline_node(Layout::Node& layout_paren // Parent has block-level children, insert into an anonymous wrapper block (and create it first if needed) if (!layout_parent.last_child()->is_anonymous() || !layout_parent.last_child()->children_are_inline()) { - layout_parent.append_child(adopt(*new BlockBox(layout_node.document(), nullptr, style_for_anonymous_block(layout_parent)))); + layout_parent.append_child(layout_parent.create_anonymous_wrapper()); } return *layout_parent.last_child(); } @@ -86,7 +75,7 @@ static Layout::Node& insertion_parent_for_block_node(Layout::Node& layout_parent layout_parent.remove_child(*child); children.append(child.release_nonnull()); } - layout_parent.append_child(adopt(*new BlockBox(layout_node.document(), nullptr, style_for_anonymous_block(layout_parent)))); + layout_parent.append_child(adopt(*new BlockBox(layout_node.document(), nullptr, layout_parent.computed_values().clone_inherited_values()))); layout_parent.set_children_are_inline(false); for (auto& child : children) { layout_parent.last_child()->append_child(child); @@ -102,7 +91,9 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node) if (dom_node.parent() && !dom_node.parent()->layout_node()) return; - const CSS::StyleProperties* parent_style = m_parent_stack.is_empty() ? nullptr : &m_parent_stack.last()->specified_style(); + const CSS::StyleProperties* parent_style = nullptr; + if (!m_parent_stack.is_empty() && m_parent_stack.last()->dom_node() && m_parent_stack.last()->dom_node()->is_element()) + parent_style = downcast(*m_parent_stack.last()->dom_node()).specified_css_values(); auto layout_node = dom_node.create_layout_node(parent_style); if (!layout_node) @@ -117,7 +108,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node) } else { if (layout_node->is_inline()) { // Inlines can be inserted into the nearest ancestor. - auto& insertion_point = insertion_parent_for_inline_node(*m_parent_stack.last(), *layout_node); + auto& insertion_point = insertion_parent_for_inline_node(*m_parent_stack.last()); insertion_point.append_child(*layout_node); insertion_point.set_children_are_inline(true); } else { @@ -136,7 +127,7 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node) } if (dom_node.has_children() && layout_node->can_have_children()) { - push_parent(*layout_node); + push_parent(downcast(*layout_node)); downcast(dom_node).for_each_child([&](auto& dom_child) { create_layout_tree(dom_child); }); @@ -149,7 +140,7 @@ RefPtr TreeBuilder::build(DOM::Node& dom_node) if (dom_node.parent()) { // We're building a partial layout tree, so start by building up the stack of parent layout nodes. for (auto* ancestor = dom_node.parent()->layout_node(); ancestor; ancestor = ancestor->parent()) - m_parent_stack.prepend(ancestor); + m_parent_stack.prepend(downcast(ancestor)); } create_layout_tree(dom_node); diff --git a/Libraries/LibWeb/Layout/TreeBuilder.h b/Libraries/LibWeb/Layout/TreeBuilder.h index 40c79bb3ade..563338a740e 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.h +++ b/Libraries/LibWeb/Layout/TreeBuilder.h @@ -41,11 +41,11 @@ public: private: void create_layout_tree(DOM::Node&); - void push_parent(Layout::Node& node) { m_parent_stack.append(&node); } + void push_parent(Layout::NodeWithStyle& node) { m_parent_stack.append(&node); } void pop_parent() { m_parent_stack.take_last(); } RefPtr m_layout_root; - Vector m_parent_stack; + Vector m_parent_stack; }; }