summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2019-09-25 12:17:29 +0300
committerAndreas Kling <awesomekling@gmail.com>2019-09-28 18:29:42 +0200
commit599edba7a34533e02aaf4218cc77add480674ea3 (patch)
tree578db126e7825d6b20d2664a253604078cc41a92 /Libraries
parent841ae4439234abde6c186f021845dd5448586ab2 (diff)
downloadserenity-599edba7a34533e02aaf4218cc77add480674ea3.zip
LibHTML: Move layout tree building to Node
This also fixes another bug with inline wrappers. Namely, we should only add inline wrappers if a block node has both non-block (inline or text) and block children.
Diffstat (limited to 'Libraries')
-rw-r--r--Libraries/LibHTML/DOM/Node.cpp63
-rw-r--r--Libraries/LibHTML/DOM/Node.h6
-rw-r--r--Libraries/LibHTML/Frame.cpp44
3 files changed, 70 insertions, 43 deletions
diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp
index b1aef1eea7..6e60448850 100644
--- a/Libraries/LibHTML/DOM/Node.cpp
+++ b/Libraries/LibHTML/DOM/Node.cpp
@@ -1,5 +1,11 @@
#include <LibHTML/DOM/Node.h>
+#include <LibHTML/DOM/Element.h>
+#include <LibHTML/CSS/StyleResolver.h>
#include <LibHTML/Layout/LayoutNode.h>
+#include <LibHTML/Layout/LayoutBlock.h>
+#include <LibHTML/Layout/LayoutDocument.h>
+#include <LibHTML/Layout/LayoutInline.h>
+#include <LibHTML/Layout/LayoutText.h>
Node::Node(NodeType type)
: m_type(type)
@@ -9,3 +15,60 @@ Node::Node(NodeType type)
Node::~Node()
{
}
+
+RefPtr<LayoutNode> Node::create_layout_node(const StyleResolver& resolver, const StyleProperties* parent_properties) const
+{
+ if (is_document())
+ return adopt(*new LayoutDocument(static_cast<const Document&>(*this), {}));
+
+ auto style_properties = resolver.resolve_style(static_cast<const Element&>(*this), parent_properties);
+ auto display_property = style_properties.property("display");
+ String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline";
+
+ if (is_text())
+ return adopt(*new LayoutText(static_cast<const Text&>(*this), move(style_properties)));
+ if (display == "none")
+ return nullptr;
+ if (display == "block" || display == "list-item")
+ return adopt(*new LayoutBlock(this, move(style_properties)));
+ if (display == "inline")
+ return adopt(*new LayoutInline(*this, move(style_properties)));
+
+ ASSERT_NOT_REACHED();
+}
+
+
+RefPtr<LayoutNode> Node::create_layout_tree(const StyleResolver& resolver, const StyleProperties* parent_properties) const
+{
+ auto layout_node = create_layout_node(resolver, parent_properties);
+ if (!layout_node)
+ return nullptr;
+
+ if (!has_children())
+ return layout_node;
+
+ Vector<RefPtr<LayoutNode>> layout_children;
+ bool have_inline_children = false;
+ bool have_block_children = false;
+
+ static_cast<const ParentNode&>(*this).for_each_child([&](const Node& child) {
+ auto layout_child = child.create_layout_tree(resolver, &layout_node->style_properties());
+ if (!layout_child)
+ return;
+ if (!layout_child->is_block())
+ have_inline_children = true;
+ if (layout_child->is_block())
+ have_block_children = true;
+ layout_children.append(move(layout_child));
+ });
+
+ for (auto layout_child : layout_children)
+ if (have_block_children && have_inline_children && !layout_child->is_block()) {
+ if (layout_child->is_text() && static_cast<const LayoutText&>(*layout_child).text() == " ")
+ continue;
+ layout_node->inline_wrapper().append_child(*layout_child);
+ } else {
+ layout_node->append_child(*layout_child);
+ }
+ return layout_node;
+}
diff --git a/Libraries/LibHTML/DOM/Node.h b/Libraries/LibHTML/DOM/Node.h
index e04770f01d..c26ed8a5aa 100644
--- a/Libraries/LibHTML/DOM/Node.h
+++ b/Libraries/LibHTML/DOM/Node.h
@@ -13,6 +13,9 @@ enum class NodeType : unsigned {
};
class ParentNode;
+class LayoutNode;
+class StyleResolver;
+class StyleProperties;
class Node : public TreeNode<Node> {
public:
@@ -24,6 +27,9 @@ public:
bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
bool is_parent_node() const { return is_element() || is_document(); }
+ RefPtr<LayoutNode> create_layout_node(const StyleResolver&, const StyleProperties* parent_properties) const;
+ RefPtr<LayoutNode> create_layout_tree(const StyleResolver&, const StyleProperties* parent_properties) const;
+
protected:
explicit Node(NodeType);
diff --git a/Libraries/LibHTML/Frame.cpp b/Libraries/LibHTML/Frame.cpp
index 78005562b3..7681fa3df1 100644
--- a/Libraries/LibHTML/Frame.cpp
+++ b/Libraries/LibHTML/Frame.cpp
@@ -22,54 +22,12 @@ void Frame::set_document(Document* document)
m_document = document;
}
-RefPtr<LayoutNode> Frame::generate_layout_tree()
-{
- auto resolver = m_document->style_resolver();
- auto create_layout_node = [&](const Node& node) -> RefPtr<LayoutNode> {
- if (node.is_document())
- return adopt(*new LayoutDocument(static_cast<const Document&>(node), {}));
-
- auto style_properties = resolver.resolve_style(static_cast<const Element&>(node));
- auto display_property = style_properties.property("display");
- String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline";
-
- if (display == "none")
- return nullptr;
- if (display == "block")
- return adopt(*new LayoutBlock(&node, move(style_properties)));
- if (display == "inline")
- return adopt(*new LayoutInline(node, move(style_properties)));
-
- ASSERT_NOT_REACHED();
- };
-
- Function<RefPtr<LayoutNode>(const Node&)> build_layout_tree;
- build_layout_tree = [&](const Node& node) -> RefPtr<LayoutNode> {
- auto layout_node = create_layout_node(node);
- if (!layout_node)
- return nullptr;
- if (!node.has_children())
- return layout_node;
- static_cast<const ParentNode&>(node).for_each_child([&](const Node& child) {
- auto layout_child = build_layout_tree(child);
- if (!layout_child)
- return;
- if (layout_child->is_inline())
- layout_node->inline_wrapper().append_child(*layout_child);
- else
- layout_node->append_child(*layout_child);
- });
- return layout_node;
- };
- return build_layout_tree(*m_document);
-}
-
void Frame::layout()
{
if (!m_document)
return;
- auto layout_root = generate_layout_tree();
+ auto layout_root = m_document->create_layout_tree(m_document->style_resolver(), nullptr);
layout_root->style().size().set_width(m_size.width());