Node.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #include <LibHTML/DOM/Node.h>
  2. #include <LibHTML/DOM/Element.h>
  3. #include <LibHTML/CSS/StyleResolver.h>
  4. #include <LibHTML/Layout/LayoutNode.h>
  5. #include <LibHTML/Layout/LayoutBlock.h>
  6. #include <LibHTML/Layout/LayoutDocument.h>
  7. #include <LibHTML/Layout/LayoutInline.h>
  8. #include <LibHTML/Layout/LayoutText.h>
  9. Node::Node(Document& document, NodeType type)
  10. : m_document(document)
  11. , m_type(type)
  12. {
  13. }
  14. Node::~Node()
  15. {
  16. }
  17. RefPtr<LayoutNode> Node::create_layout_node(const StyleResolver& resolver, const StyleProperties* parent_properties) const
  18. {
  19. if (is_document())
  20. return adopt(*new LayoutDocument(static_cast<const Document&>(*this), {}));
  21. auto style_properties = resolver.resolve_style(static_cast<const Element&>(*this), parent_properties);
  22. auto display_property = style_properties.property("display");
  23. String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline";
  24. if (is_text())
  25. return adopt(*new LayoutText(static_cast<const Text&>(*this), move(style_properties)));
  26. if (display == "none")
  27. return nullptr;
  28. if (display == "block" || display == "list-item")
  29. return adopt(*new LayoutBlock(this, move(style_properties)));
  30. if (display == "inline")
  31. return adopt(*new LayoutInline(*this, move(style_properties)));
  32. ASSERT_NOT_REACHED();
  33. }
  34. RefPtr<LayoutNode> Node::create_layout_tree(const StyleResolver& resolver, const StyleProperties* parent_properties) const
  35. {
  36. auto layout_node = create_layout_node(resolver, parent_properties);
  37. if (!layout_node)
  38. return nullptr;
  39. if (!has_children())
  40. return layout_node;
  41. Vector<RefPtr<LayoutNode>> layout_children;
  42. bool have_inline_children = false;
  43. bool have_block_children = false;
  44. static_cast<const ParentNode&>(*this).for_each_child([&](const Node& child) {
  45. auto layout_child = child.create_layout_tree(resolver, &layout_node->style_properties());
  46. if (!layout_child)
  47. return;
  48. if (!layout_child->is_block())
  49. have_inline_children = true;
  50. if (layout_child->is_block())
  51. have_block_children = true;
  52. layout_children.append(move(layout_child));
  53. });
  54. for (auto layout_child : layout_children)
  55. if (have_block_children && have_inline_children && !layout_child->is_block()) {
  56. if (layout_child->is_text() && static_cast<const LayoutText&>(*layout_child).text() == " ")
  57. continue;
  58. layout_node->inline_wrapper().append_child(*layout_child);
  59. } else {
  60. layout_node->append_child(*layout_child);
  61. }
  62. return layout_node;
  63. }