LayoutNode.h 6.9 KB

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