diff --git a/LibHTML/CSS/Default.css b/LibHTML/CSS/Default.css
index a1afc54130..d32efb969d 100644
--- a/LibHTML/CSS/Default.css
+++ b/LibHTML/CSS/Default.css
@@ -1,5 +1,5 @@
html {
- display: inline;
+ display: block;
font-family: Katica;
}
diff --git a/LibHTML/CSS/StyleResolver.cpp b/LibHTML/CSS/StyleResolver.cpp
index 47c28e8580..88d693c374 100644
--- a/LibHTML/CSS/StyleResolver.cpp
+++ b/LibHTML/CSS/StyleResolver.cpp
@@ -36,7 +36,7 @@ static bool matches(const Selector& selector, const Element& element)
NonnullRefPtrVector StyleResolver::collect_matching_rules(const Element& element) const
{
NonnullRefPtrVector matching_rules;
- for (auto& sheet : m_sheets) {
+ for (auto& sheet : document().stylesheets()) {
for (auto& rule : sheet.rules()) {
for (auto& selector : rule.selectors()) {
if (matches(selector, element)) {
diff --git a/LibHTML/CSS/StyleResolver.h b/LibHTML/CSS/StyleResolver.h
index eec7042b29..2e093b687f 100644
--- a/LibHTML/CSS/StyleResolver.h
+++ b/LibHTML/CSS/StyleResolver.h
@@ -18,8 +18,6 @@ public:
Document& document() { return m_document; }
const Document& document() const { return m_document; }
- void add_sheet(const StyleSheet& sheet) { m_sheets.append(sheet); }
-
NonnullRefPtr create_styled_node(const Element&);
NonnullRefPtr create_styled_node(const Document&);
@@ -28,6 +26,4 @@ public:
private:
Document& m_document;
-
- NonnullRefPtrVector m_sheets;
};
diff --git a/LibHTML/CSS/StyledNode.cpp b/LibHTML/CSS/StyledNode.cpp
index ed8a1ec211..57745b9858 100644
--- a/LibHTML/CSS/StyledNode.cpp
+++ b/LibHTML/CSS/StyledNode.cpp
@@ -8,3 +8,18 @@ StyledNode::StyledNode(const Node* node)
StyledNode::~StyledNode()
{
}
+
+Display StyledNode::display() const
+{
+ auto it = m_property_values.find("display");
+ if (it == m_property_values.end())
+ return Display::Inline;
+ auto value = it->value->to_string();
+ if (value == "none")
+ return Display::None;
+ if (value == "block")
+ return Display::Block;
+ if (value == "inline")
+ return Display::Inline;
+ ASSERT_NOT_REACHED();
+}
diff --git a/LibHTML/CSS/StyledNode.h b/LibHTML/CSS/StyledNode.h
index 61d43b5156..0cef5f3f26 100644
--- a/LibHTML/CSS/StyledNode.h
+++ b/LibHTML/CSS/StyledNode.h
@@ -8,6 +8,12 @@
class Node;
+enum class Display {
+ None,
+ Block,
+ Inline,
+};
+
class StyledNode : public TreeNode {
public:
static NonnullRefPtr create(const Node& node)
@@ -44,6 +50,8 @@ public:
m_property_values.set(name, move(value));
}
+ Display display() const;
+
protected:
explicit StyledNode(const Node*);
diff --git a/LibHTML/DOM/Document.cpp b/LibHTML/DOM/Document.cpp
index 95bf199f0a..36c937e6d7 100644
--- a/LibHTML/DOM/Document.cpp
+++ b/LibHTML/DOM/Document.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -12,31 +13,9 @@ Document::~Document()
{
}
-static void create_layout_tree_for_node(Node& node)
+StyleResolver& Document::style_resolver()
{
- if (auto layout_node = node.create_layout_node()) {
- node.set_layout_node(*layout_node);
-#ifdef DEBUG_LAYOUT_TREE_BUILD
- if (node.is_element()) {
- printf("created layout node for <%s>, parent is %p, parent ln is %p\n", static_cast(node).tag_name().characters(), node.parent_node(), node.parent_node()->layout_node());
- }
-#endif
- if (node.parent() && node.parent()->layout_node())
- node.parent()->layout_node()->append_child(*layout_node);
- }
- if (node.is_parent_node()) {
- static_cast(node).for_each_child([&](auto& child) {
- create_layout_tree_for_node(child);
- });
- }
-}
-
-void Document::build_layout_tree()
-{
- create_layout_tree_for_node(*this);
-}
-
-RefPtr Document::create_layout_node()
-{
- return adopt(*new LayoutDocument(*this));
+ if (!m_style_resolver)
+ m_style_resolver = make(*this);
+ return *m_style_resolver;
}
diff --git a/LibHTML/DOM/Document.h b/LibHTML/DOM/Document.h
index 86846cfeb8..50f245175d 100644
--- a/LibHTML/DOM/Document.h
+++ b/LibHTML/DOM/Document.h
@@ -1,18 +1,27 @@
#pragma once
#include
+#include
+#include
+#include
+#include
#include
class LayoutNode;
+class StyleResolver;
+class StyleSheet;
class Document : public ParentNode {
public:
Document();
virtual ~Document() override;
- virtual RefPtr create_layout_node() override;
+ StyleResolver& style_resolver();
- void build_layout_tree();
+ void add_sheet(const StyleSheet& sheet) { m_sheets.append(sheet); }
+ const NonnullRefPtrVector& stylesheets() const { return m_sheets; }
private:
+ OwnPtr m_style_resolver;
+ NonnullRefPtrVector m_sheets;
};
diff --git a/LibHTML/DOM/Element.cpp b/LibHTML/DOM/Element.cpp
index 7808170a60..e9329e15f3 100644
--- a/LibHTML/DOM/Element.cpp
+++ b/LibHTML/DOM/Element.cpp
@@ -62,18 +62,3 @@ bool Element::has_class(const StringView& class_name) const
}
return false;
}
-
-RefPtr Element::create_layout_node()
-{
- if (m_tag_name == "html")
- return adopt(*new LayoutBlock(*this));
- if (m_tag_name == "body")
- return adopt(*new LayoutBlock(*this));
- if (m_tag_name == "h1")
- return adopt(*new LayoutBlock(*this));
- if (m_tag_name == "p")
- return adopt(*new LayoutBlock(*this));
- if (m_tag_name == "b")
- return adopt(*new LayoutInline(*this));
- return nullptr;
-}
diff --git a/LibHTML/DOM/Element.h b/LibHTML/DOM/Element.h
index f3133656ca..2b91860ff7 100644
--- a/LibHTML/DOM/Element.h
+++ b/LibHTML/DOM/Element.h
@@ -42,8 +42,6 @@ public:
bool has_class(const StringView&) const;
- virtual RefPtr create_layout_node() override;
-
private:
Attribute* find_attribute(const String& name);
const Attribute* find_attribute(const String& name) const;
diff --git a/LibHTML/DOM/Node.cpp b/LibHTML/DOM/Node.cpp
index b8d2007da1..b1aef1eea7 100644
--- a/LibHTML/DOM/Node.cpp
+++ b/LibHTML/DOM/Node.cpp
@@ -9,13 +9,3 @@ Node::Node(NodeType type)
Node::~Node()
{
}
-
-RefPtr Node::create_layout_node()
-{
- return nullptr;
-}
-
-void Node::set_layout_node(NonnullRefPtr layout_node)
-{
- m_layout_node = move(layout_node);
-}
diff --git a/LibHTML/DOM/Node.h b/LibHTML/DOM/Node.h
index 73008fcaab..e04770f01d 100644
--- a/LibHTML/DOM/Node.h
+++ b/LibHTML/DOM/Node.h
@@ -12,7 +12,6 @@ enum class NodeType : unsigned {
DOCUMENT_NODE = 9,
};
-class LayoutNode;
class ParentNode;
class Node : public TreeNode {
@@ -25,16 +24,8 @@ public:
bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
bool is_parent_node() const { return is_element() || is_document(); }
- virtual RefPtr create_layout_node();
-
- const LayoutNode* layout_node() const { return m_layout_node; }
- LayoutNode* layout_node() { return m_layout_node; }
-
- void set_layout_node(NonnullRefPtr);
-
protected:
explicit Node(NodeType);
NodeType m_type { NodeType::INVALID };
- RefPtr m_layout_node;
};
diff --git a/LibHTML/DOM/Text.cpp b/LibHTML/DOM/Text.cpp
index 8bb807270c..8d8d8ace25 100644
--- a/LibHTML/DOM/Text.cpp
+++ b/LibHTML/DOM/Text.cpp
@@ -10,8 +10,3 @@ Text::Text(const String& data)
Text::~Text()
{
}
-
-RefPtr Text::create_layout_node()
-{
- return adopt(*new LayoutText(*this));
-}
diff --git a/LibHTML/DOM/Text.h b/LibHTML/DOM/Text.h
index e7ce724026..db1c9e4bac 100644
--- a/LibHTML/DOM/Text.h
+++ b/LibHTML/DOM/Text.h
@@ -10,8 +10,6 @@ public:
const String& data() const { return m_data; }
- virtual RefPtr create_layout_node() override;
-
private:
String m_data;
};
diff --git a/LibHTML/Frame.cpp b/LibHTML/Frame.cpp
index 73e35b0665..147216e4f0 100644
--- a/LibHTML/Frame.cpp
+++ b/LibHTML/Frame.cpp
@@ -1,5 +1,12 @@
+#include
+#include
+#include
+#include
+#include
#include
-#include
+#include
+#include
+#include
Frame::Frame()
: m_size(800, 600)
@@ -15,17 +22,78 @@ void Frame::set_document(Document* document)
m_document = document;
}
+RefPtr Frame::generate_style_tree()
+{
+ if (!m_document)
+ return nullptr;
+
+ auto& resolver = m_document->style_resolver();
+ Function(const Node&, StyledNode*)> resolve_style = [&](const Node& node, StyledNode* parent_styled_node) -> RefPtr {
+ RefPtr styled_node;
+ if (node.is_element())
+ styled_node = resolver.create_styled_node(static_cast(node));
+ else if (node.is_document())
+ styled_node = resolver.create_styled_node(static_cast(node));
+ if (!styled_node)
+ return nullptr;
+ if (parent_styled_node)
+ parent_styled_node->append_child(*styled_node);
+ static_cast(node).for_each_child([&](const Node& child) {
+ if (!child.is_element())
+ return;
+ auto styled_child_node = resolve_style(static_cast(child), styled_node.ptr());
+ printf("Created StyledNode{%p} for Element{%p}\n", styled_child_node.ptr(), &node);
+ });
+ return styled_node;
+ };
+ auto styled_root = resolve_style(*m_document, nullptr);
+ dump_tree(*styled_root);
+ return styled_root;
+}
+
void Frame::layout()
{
if (!m_document)
return;
- if (!m_document->layout_node())
- m_document->create_layout_node();
+ auto styled_root = generate_style_tree();
- ASSERT(m_document->layout_node());
+ auto create_layout_node = [](const StyledNode& styled_node) -> RefPtr {
+ switch (styled_node.display()) {
+ case Display::None:
+ return nullptr;
+ case Display::Block:
+ return adopt(*new LayoutBlock(*styled_node.node()));
+ case Display::Inline:
+ return adopt(*new LayoutInline(*styled_node.node()));
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ };
- m_document->layout_node()->style().size().set_width(m_size.width());
+ Function(const StyledNode&, LayoutNode*)> resolve_layout = [&](const StyledNode& styled_node, LayoutNode* parent_layout_node) -> RefPtr {
+ auto layout_node = create_layout_node(styled_node);
+ if (!layout_node)
+ return nullptr;
+ if (parent_layout_node)
+ parent_layout_node->append_child(*layout_node);
+ if (styled_node.has_children()) {
+ for (auto* child = styled_node.first_child(); child; child = child->next_sibling()) {
+ resolve_layout(*child, layout_node.ptr());
+ }
+ }
+ return layout_node;
+ };
- m_document->layout_node()->layout();
+ auto layout_root = resolve_layout(*styled_root, nullptr);
+
+ layout_root->style().size().set_width(m_size.width());
+
+ printf("\033[33;1mLayout tree before layout:\033[0m\n");
+ dump_tree(*layout_root);
+
+ layout_root->layout();
+
+ printf("\033[33;1mLayout tree after layout:\033[0m\n");
+ dump_tree(*layout_root);
}
diff --git a/LibHTML/Frame.h b/LibHTML/Frame.h
index 9fd4467dc0..89abbc454e 100644
--- a/LibHTML/Frame.h
+++ b/LibHTML/Frame.h
@@ -16,6 +16,8 @@ public:
void layout();
private:
+ RefPtr generate_style_tree();
+
RefPtr m_document;
Size m_size;
};
diff --git a/LibHTML/Layout/LayoutBlock.cpp b/LibHTML/Layout/LayoutBlock.cpp
index 9495ffd280..fd47af1ed0 100644
--- a/LibHTML/Layout/LayoutBlock.cpp
+++ b/LibHTML/Layout/LayoutBlock.cpp
@@ -1,8 +1,8 @@
#include
#include
-LayoutBlock::LayoutBlock(Element& element)
- : LayoutNode(&element)
+LayoutBlock::LayoutBlock(const Node& node)
+ : LayoutNode(&node)
{
}
diff --git a/LibHTML/Layout/LayoutBlock.h b/LibHTML/Layout/LayoutBlock.h
index 47981eead3..cc8a283245 100644
--- a/LibHTML/Layout/LayoutBlock.h
+++ b/LibHTML/Layout/LayoutBlock.h
@@ -6,7 +6,7 @@ class Element;
class LayoutBlock : public LayoutNode {
public:
- explicit LayoutBlock(Element&);
+ explicit LayoutBlock(const Node&);
virtual ~LayoutBlock() override;
virtual const char* class_name() const override { return "LayoutBlock"; }
diff --git a/LibHTML/Layout/LayoutInline.cpp b/LibHTML/Layout/LayoutInline.cpp
index 04c1fa12e7..ac68b2818c 100644
--- a/LibHTML/Layout/LayoutInline.cpp
+++ b/LibHTML/Layout/LayoutInline.cpp
@@ -1,8 +1,8 @@
#include
#include
-LayoutInline::LayoutInline(Element& element)
- : LayoutNode(&element)
+LayoutInline::LayoutInline(const Node& node)
+ : LayoutNode(&node)
{
}
diff --git a/LibHTML/Layout/LayoutInline.h b/LibHTML/Layout/LayoutInline.h
index cf3075921f..73def302cb 100644
--- a/LibHTML/Layout/LayoutInline.h
+++ b/LibHTML/Layout/LayoutInline.h
@@ -6,7 +6,7 @@ class Element;
class LayoutInline : public LayoutNode {
public:
- explicit LayoutInline(Element&);
+ explicit LayoutInline(const Node&);
virtual ~LayoutInline() override;
virtual const char* class_name() const override { return "LayoutInline"; }
diff --git a/LibHTML/test.cpp b/LibHTML/test.cpp
index e3d23837d8..e3e052ff36 100644
--- a/LibHTML/test.cpp
+++ b/LibHTML/test.cpp
@@ -1,10 +1,12 @@
#include
-#include
-#include
-#include
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
#include
#include
@@ -23,47 +25,12 @@ int main(int argc, char** argv)
dump_sheet(sheet);
String html = String::copy(f.read_all());
- auto doc = parse_html(html);
- dump_tree(doc);
-
- StyleResolver resolver(*doc);
- resolver.add_sheet(*sheet);
-
- Function(const Node&, StyledNode*)> resolve_style = [&](const Node& node, StyledNode* parent_styled_node) -> RefPtr {
- auto styled_node = [&]() -> RefPtr {
- if (node.is_element())
- return resolver.create_styled_node(static_cast(node));
- if (node.is_document())
- return resolver.create_styled_node(static_cast(node));
- return nullptr;
- }();
- if (!styled_node)
- return nullptr;
- if (parent_styled_node)
- parent_styled_node->append_child(*styled_node);
- static_cast(node).for_each_child([&](const Node& child) {
- if (!child.is_element())
- return;
- auto styled_child_node = resolve_style(static_cast(child), styled_node.ptr());
- printf("Created StyledNode{%p} for Element{%p}\n", styled_child_node.ptr(), &node);
- });
- return styled_node;
- };
- auto styled_root = resolve_style(*doc, nullptr);
-
- dump_tree(*styled_root);
-
- doc->build_layout_tree();
- ASSERT(doc->layout_node());
-
- printf("\033[33;1mLayout tree before layout:\033[0m\n");
- dump_tree(*doc->layout_node());
+ auto document = parse_html(html);
+ dump_tree(document);
+ document->add_sheet(*sheet);
auto frame = make();
- frame->set_document(doc);
+ frame->set_document(document);
frame->layout();
-
- printf("\033[33;1mLayout tree after layout:\033[0m\n");
- dump_tree(*doc->layout_node());
return 0;
}