mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
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.
This commit is contained in:
parent
cc024bdcc0
commit
d9b2650dcc
Notes:
sideshowbarker
2024-07-19 00:04:34 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/d9b2650dcc5
10 changed files with 57 additions and 38 deletions
|
@ -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() };
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -44,6 +44,11 @@ BlockBox::BlockBox(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::
|
|||
{
|
||||
}
|
||||
|
||||
BlockBox::BlockBox(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values)
|
||||
: Box(document, node, move(computed_values))
|
||||
{
|
||||
}
|
||||
|
||||
BlockBox::~BlockBox()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace Web::Layout {
|
|||
class BlockBox : public Box {
|
||||
public:
|
||||
BlockBox(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
|
||||
BlockBox(DOM::Document&, DOM::Node*, CSS::ComputedValues);
|
||||
virtual ~BlockBox() override;
|
||||
|
||||
virtual void paint(PaintContext&, PaintPhase) override;
|
||||
|
|
|
@ -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<LineBox> m_line_boxes;
|
||||
|
|
|
@ -205,10 +205,16 @@ bool Node::is_fixed_position() const
|
|||
|
||||
NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> 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<BlockBox>(*this);
|
||||
}
|
||||
|
||||
NonnullRefPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const
|
||||
{
|
||||
auto wrapper = adopt(*new BlockBox(const_cast<DOM::Document&>(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<const CSS::ImmutableComputedValues&>(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<NodeWithStyle> create_anonymous_wrapper() const;
|
||||
|
||||
protected:
|
||||
NodeWithStyle(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
|
||||
NodeWithStyle(DOM::Document&, DOM::Node*, CSS::ComputedValues);
|
||||
|
||||
private:
|
||||
CSS::ComputedValues m_computed_values;
|
||||
|
@ -220,7 +219,6 @@ private:
|
|||
float m_font_size { 0 };
|
||||
RefPtr<CSS::ImageStyleValue> m_background_image;
|
||||
|
||||
NonnullRefPtr<CSS::StyleProperties> 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<const NodeWithStyle*>(this)->specified_style();
|
||||
return parent()->specified_style();
|
||||
}
|
||||
|
||||
inline const CSS::ImmutableComputedValues& Node::computed_values() const
|
||||
{
|
||||
if (m_has_style)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/DOM/ParentNode.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
#include <LibWeb/Layout/TableBox.h>
|
||||
|
@ -37,22 +38,10 @@ TreeBuilder::TreeBuilder()
|
|||
{
|
||||
}
|
||||
|
||||
static NonnullRefPtr<CSS::StyleProperties> 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<DOM::Element>(*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<NodeWithStyle>(*layout_node));
|
||||
downcast<DOM::ParentNode>(dom_node).for_each_child([&](auto& dom_child) {
|
||||
create_layout_tree(dom_child);
|
||||
});
|
||||
|
@ -149,7 +140,7 @@ RefPtr<Node> 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<NodeWithStyle>(ancestor));
|
||||
}
|
||||
|
||||
create_layout_tree(dom_node);
|
||||
|
|
|
@ -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<Layout::Node> m_layout_root;
|
||||
Vector<Layout::Node*> m_parent_stack;
|
||||
Vector<Layout::NodeWithStyle*> m_parent_stack;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue