LayoutNode.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #pragma once
  2. #include <AK/NonnullRefPtr.h>
  3. #include <AK/Vector.h>
  4. #include <LibDraw/Rect.h>
  5. #include <LibHTML/CSS/StyleProperties.h>
  6. #include <LibHTML/Layout/BoxModelMetrics.h>
  7. #include <LibHTML/RenderingContext.h>
  8. #include <LibHTML/TreeNode.h>
  9. class Document;
  10. class Element;
  11. class LayoutBlock;
  12. class LayoutNode;
  13. class LayoutNodeWithStyle;
  14. class LineBoxFragment;
  15. class Node;
  16. struct HitTestResult {
  17. RefPtr<LayoutNode> layout_node;
  18. };
  19. class LayoutNode : public TreeNode<LayoutNode> {
  20. public:
  21. virtual ~LayoutNode();
  22. virtual HitTestResult hit_test(const Point&) const;
  23. bool is_anonymous() const { return !m_node; }
  24. const Node* node() const { return m_node; }
  25. const Document& document() const;
  26. template<typename Callback>
  27. inline void for_each_child(Callback callback) const
  28. {
  29. for (auto* node = first_child(); node; node = node->next_sibling())
  30. callback(*node);
  31. }
  32. template<typename Callback>
  33. inline void for_each_child(Callback callback)
  34. {
  35. for (auto* node = first_child(); node; node = node->next_sibling())
  36. callback(*node);
  37. }
  38. virtual const char* class_name() const { return "LayoutNode"; }
  39. virtual bool is_text() const { return false; }
  40. virtual bool is_block() const { return false; }
  41. virtual bool is_replaced() const { return false; }
  42. virtual bool is_box() const { return false; }
  43. virtual bool is_table() const { return false; }
  44. virtual bool is_table_row() const { return false; }
  45. virtual bool is_table_cell() const { return false; }
  46. bool has_style() const { return m_has_style; }
  47. bool is_inline() const { return m_inline; }
  48. void set_inline(bool b) { m_inline = b; }
  49. virtual void layout();
  50. virtual void render(RenderingContext&);
  51. const LayoutBlock* containing_block() const;
  52. virtual LayoutNode& inline_wrapper() { return *this; }
  53. const StyleProperties& style() const;
  54. const LayoutNodeWithStyle* parent() const;
  55. void inserted_into(LayoutNode&) {}
  56. void removed_from(LayoutNode&) {}
  57. virtual void split_into_lines(LayoutBlock& container);
  58. bool is_visible() const { return m_visible; }
  59. void set_visible(bool visible) { m_visible = visible; }
  60. virtual void set_needs_display();
  61. template<typename Callback>
  62. void for_each_fragment_of_this(Callback);
  63. bool children_are_inline() const { return m_children_are_inline; }
  64. void set_children_are_inline(bool value) { m_children_are_inline = value; }
  65. template<typename U>
  66. const U* next_sibling_of_type() const;
  67. template<typename U>
  68. U* next_sibling_of_type();
  69. template<typename T>
  70. const T* first_child_of_type() const;
  71. template<typename T>
  72. T* first_child_of_type();
  73. protected:
  74. explicit LayoutNode(const Node*);
  75. private:
  76. friend class LayoutNodeWithStyle;
  77. const Node* m_node { nullptr };
  78. bool m_inline { false };
  79. bool m_has_style { false };
  80. bool m_visible { true };
  81. bool m_children_are_inline { false };
  82. };
  83. class LayoutNodeWithStyle : public LayoutNode {
  84. public:
  85. virtual ~LayoutNodeWithStyle() override {}
  86. const StyleProperties& style() const { return m_style; }
  87. void set_style(const StyleProperties& style) { m_style = style; }
  88. protected:
  89. explicit LayoutNodeWithStyle(const Node* node, NonnullRefPtr<StyleProperties> style)
  90. : LayoutNode(node)
  91. , m_style(move(style))
  92. {
  93. m_has_style = true;
  94. }
  95. private:
  96. NonnullRefPtr<StyleProperties> m_style;
  97. };
  98. class LayoutNodeWithStyleAndBoxModelMetrics : public LayoutNodeWithStyle {
  99. public:
  100. BoxModelMetrics& box_model() { return m_box_model; }
  101. const BoxModelMetrics& box_model() const { return m_box_model; }
  102. protected:
  103. LayoutNodeWithStyleAndBoxModelMetrics(const Node* node, NonnullRefPtr<StyleProperties> style)
  104. : LayoutNodeWithStyle(node, move(style))
  105. {
  106. }
  107. private:
  108. BoxModelMetrics m_box_model;
  109. };
  110. inline const StyleProperties& LayoutNode::style() const
  111. {
  112. if (m_has_style)
  113. return static_cast<const LayoutNodeWithStyle*>(this)->style();
  114. return parent()->style();
  115. }
  116. inline const LayoutNodeWithStyle* LayoutNode::parent() const
  117. {
  118. return static_cast<const LayoutNodeWithStyle*>(TreeNode<LayoutNode>::parent());
  119. }
  120. template<typename T>
  121. inline bool is(const LayoutNode&)
  122. {
  123. return false;
  124. }
  125. template<typename T>
  126. inline bool is(const LayoutNode* node)
  127. {
  128. return !node || is<T>(*node);
  129. }
  130. template<>
  131. inline bool is<LayoutNode>(const LayoutNode&)
  132. {
  133. return true;
  134. }
  135. template<>
  136. inline bool is<LayoutNodeWithStyle>(const LayoutNode& node)
  137. {
  138. return node.has_style();
  139. }
  140. template<typename T>
  141. inline const T& to(const LayoutNode& node)
  142. {
  143. ASSERT(is<T>(node));
  144. return static_cast<const T&>(node);
  145. }
  146. template<typename T>
  147. inline T* to(LayoutNode* node)
  148. {
  149. ASSERT(is<T>(node));
  150. return static_cast<T*>(node);
  151. }
  152. template<typename T>
  153. inline const T* to(const LayoutNode* node)
  154. {
  155. ASSERT(is<T>(node));
  156. return static_cast<const T*>(node);
  157. }
  158. template<typename T>
  159. inline T& to(LayoutNode& node)
  160. {
  161. ASSERT(is<T>(node));
  162. return static_cast<T&>(node);
  163. }
  164. template<typename T>
  165. inline const T* LayoutNode::next_sibling_of_type() const
  166. {
  167. for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
  168. if (is<T>(*sibling))
  169. return &to<T>(*sibling);
  170. }
  171. return nullptr;
  172. }
  173. template<typename T>
  174. inline T* LayoutNode::next_sibling_of_type()
  175. {
  176. for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
  177. if (is<T>(*sibling))
  178. return &to<T>(*sibling);
  179. }
  180. return nullptr;
  181. }
  182. template<typename T>
  183. inline const T* LayoutNode::first_child_of_type() const
  184. {
  185. for (auto* child = first_child(); child; child = child->next_sibling()) {
  186. if (is<T>(*child))
  187. return &to<T>(*child);
  188. }
  189. return nullptr;
  190. }
  191. template<typename T>
  192. inline T* LayoutNode::first_child_of_type()
  193. {
  194. for (auto* child = first_child(); child; child = child->next_sibling()) {
  195. if (is<T>(*child))
  196. return &to<T>(*child);
  197. }
  198. return nullptr;
  199. }