LayoutNode.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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_widget() const { return false; }
  50. virtual bool is_image() const { return false; }
  51. virtual bool is_box() const { return false; }
  52. virtual bool is_table() const { return false; }
  53. virtual bool is_table_row() const { return false; }
  54. virtual bool is_table_cell() const { return false; }
  55. bool has_style() const { return m_has_style; }
  56. bool is_inline() const { return m_inline; }
  57. void set_inline(bool b) { m_inline = b; }
  58. virtual void layout();
  59. virtual void render(RenderingContext&);
  60. const LayoutBlock* containing_block() const;
  61. virtual LayoutNode& inline_wrapper() { return *this; }
  62. const StyleProperties& style() const;
  63. LayoutNodeWithStyle* parent();
  64. const LayoutNodeWithStyle* parent() const;
  65. void inserted_into(LayoutNode&) {}
  66. void removed_from(LayoutNode&) {}
  67. virtual void split_into_lines(LayoutBlock& container);
  68. bool is_visible() const { return m_visible; }
  69. void set_visible(bool visible) { m_visible = visible; }
  70. virtual void set_needs_display();
  71. bool children_are_inline() const { return m_children_are_inline; }
  72. void set_children_are_inline(bool value) { m_children_are_inline = value; }
  73. template<typename U>
  74. const U* next_sibling_of_type() const;
  75. template<typename U>
  76. U* next_sibling_of_type();
  77. template<typename T>
  78. const T* first_child_of_type() const;
  79. template<typename T>
  80. T* first_child_of_type();
  81. template<typename T>
  82. const T* first_ancestor_of_type() const;
  83. template<typename T>
  84. T* first_ancestor_of_type();
  85. FloatPoint box_type_agnostic_position() const;
  86. protected:
  87. explicit LayoutNode(const Node*);
  88. private:
  89. friend class LayoutNodeWithStyle;
  90. const Node* m_node { nullptr };
  91. bool m_inline { false };
  92. bool m_has_style { false };
  93. bool m_visible { true };
  94. bool m_children_are_inline { false };
  95. };
  96. class LayoutNodeWithStyle : public LayoutNode {
  97. public:
  98. virtual ~LayoutNodeWithStyle() override {}
  99. const StyleProperties& style() const { return m_style; }
  100. void set_style(const StyleProperties& style) { m_style = style; }
  101. protected:
  102. explicit LayoutNodeWithStyle(const Node* node, NonnullRefPtr<StyleProperties> style)
  103. : LayoutNode(node)
  104. , m_style(move(style))
  105. {
  106. m_has_style = true;
  107. }
  108. private:
  109. NonnullRefPtr<StyleProperties> m_style;
  110. };
  111. class LayoutNodeWithStyleAndBoxModelMetrics : public LayoutNodeWithStyle {
  112. public:
  113. BoxModelMetrics& box_model() { return m_box_model; }
  114. const BoxModelMetrics& box_model() const { return m_box_model; }
  115. protected:
  116. LayoutNodeWithStyleAndBoxModelMetrics(const Node* node, NonnullRefPtr<StyleProperties> style)
  117. : LayoutNodeWithStyle(node, move(style))
  118. {
  119. }
  120. private:
  121. BoxModelMetrics m_box_model;
  122. };
  123. inline const StyleProperties& LayoutNode::style() const
  124. {
  125. if (m_has_style)
  126. return static_cast<const LayoutNodeWithStyle*>(this)->style();
  127. return parent()->style();
  128. }
  129. inline const LayoutNodeWithStyle* LayoutNode::parent() const
  130. {
  131. return static_cast<const LayoutNodeWithStyle*>(TreeNode<LayoutNode>::parent());
  132. }
  133. inline LayoutNodeWithStyle* LayoutNode::parent()
  134. {
  135. return static_cast<LayoutNodeWithStyle*>(TreeNode<LayoutNode>::parent());
  136. }
  137. template<typename T>
  138. inline bool is(const LayoutNode&)
  139. {
  140. return false;
  141. }
  142. template<typename T>
  143. inline bool is(const LayoutNode* node)
  144. {
  145. return !node || is<T>(*node);
  146. }
  147. template<>
  148. inline bool is<LayoutNode>(const LayoutNode&)
  149. {
  150. return true;
  151. }
  152. template<>
  153. inline bool is<LayoutNodeWithStyle>(const LayoutNode& node)
  154. {
  155. return node.has_style();
  156. }
  157. template<typename T>
  158. inline const T& to(const LayoutNode& node)
  159. {
  160. ASSERT(is<T>(node));
  161. return static_cast<const T&>(node);
  162. }
  163. template<typename T>
  164. inline T* to(LayoutNode* node)
  165. {
  166. ASSERT(is<T>(node));
  167. return static_cast<T*>(node);
  168. }
  169. template<typename T>
  170. inline const T* to(const LayoutNode* node)
  171. {
  172. ASSERT(is<T>(node));
  173. return static_cast<const T*>(node);
  174. }
  175. template<typename T>
  176. inline T& to(LayoutNode& node)
  177. {
  178. ASSERT(is<T>(node));
  179. return static_cast<T&>(node);
  180. }
  181. template<typename T>
  182. inline const T* LayoutNode::next_sibling_of_type() const
  183. {
  184. for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
  185. if (is<T>(*sibling))
  186. return &to<T>(*sibling);
  187. }
  188. return nullptr;
  189. }
  190. template<typename T>
  191. inline T* LayoutNode::next_sibling_of_type()
  192. {
  193. for (auto* sibling = next_sibling(); sibling; sibling = sibling->next_sibling()) {
  194. if (is<T>(*sibling))
  195. return &to<T>(*sibling);
  196. }
  197. return nullptr;
  198. }
  199. template<typename T>
  200. inline const T* LayoutNode::first_child_of_type() const
  201. {
  202. for (auto* child = first_child(); child; child = child->next_sibling()) {
  203. if (is<T>(*child))
  204. return &to<T>(*child);
  205. }
  206. return nullptr;
  207. }
  208. template<typename T>
  209. inline T* LayoutNode::first_child_of_type()
  210. {
  211. for (auto* child = first_child(); child; child = child->next_sibling()) {
  212. if (is<T>(*child))
  213. return &to<T>(*child);
  214. }
  215. return nullptr;
  216. }
  217. template<typename T>
  218. inline const T* LayoutNode::first_ancestor_of_type() const
  219. {
  220. for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
  221. if (is<T>(*ancestor))
  222. return &to<T>(*ancestor);
  223. }
  224. return nullptr;
  225. }
  226. template<typename T>
  227. inline T* LayoutNode::first_ancestor_of_type()
  228. {
  229. for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
  230. if (is<T>(*ancestor))
  231. return &to<T>(*ancestor);
  232. }
  233. return nullptr;
  234. }