LayoutNode.h 7.0 KB

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