LayoutState.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/HashMap.h>
  8. #include <LibGfx/Point.h>
  9. #include <LibWeb/Layout/Box.h>
  10. #include <LibWeb/Layout/LineBox.h>
  11. #include <LibWeb/Painting/PaintableBox.h>
  12. namespace Web::Layout {
  13. enum class SizeConstraint {
  14. None,
  15. MinContent,
  16. MaxContent,
  17. };
  18. struct LayoutState {
  19. LayoutState()
  20. : m_root(*this)
  21. {
  22. }
  23. explicit LayoutState(LayoutState const* parent)
  24. : m_parent(parent)
  25. , m_root(find_root())
  26. {
  27. used_values_per_layout_node.resize(m_root.used_values_per_layout_node.size());
  28. }
  29. LayoutState const& find_root() const
  30. {
  31. LayoutState const* root = this;
  32. for (auto* state = m_parent; state; state = state->m_parent)
  33. root = state;
  34. return *root;
  35. }
  36. struct UsedValues {
  37. NodeWithStyleAndBoxModelMetrics const& node() const { return *m_node; }
  38. void set_node(NodeWithStyleAndBoxModelMetrics&, UsedValues const* containing_block_used_values);
  39. float content_width() const { return m_content_width; }
  40. float content_height() const { return m_content_height; }
  41. void set_content_width(float);
  42. void set_content_height(float);
  43. bool has_definite_width() const { return m_has_definite_width && width_constraint == SizeConstraint::None; }
  44. bool has_definite_height() const { return m_has_definite_height && height_constraint == SizeConstraint::None; }
  45. void set_has_definite_width(bool value) { m_has_definite_width = value; }
  46. void set_has_definite_height(bool value) { m_has_definite_height = value; }
  47. Gfx::FloatPoint offset;
  48. SizeConstraint width_constraint { SizeConstraint::None };
  49. SizeConstraint height_constraint { SizeConstraint::None };
  50. float margin_left { 0 };
  51. float margin_right { 0 };
  52. float margin_top { 0 };
  53. float margin_bottom { 0 };
  54. float border_left { 0 };
  55. float border_right { 0 };
  56. float border_top { 0 };
  57. float border_bottom { 0 };
  58. float padding_left { 0 };
  59. float padding_right { 0 };
  60. float padding_top { 0 };
  61. float padding_bottom { 0 };
  62. float inset_left { 0 };
  63. float inset_right { 0 };
  64. float inset_top { 0 };
  65. float inset_bottom { 0 };
  66. Vector<LineBox> line_boxes;
  67. float margin_box_left() const { return margin_left + border_left + padding_left; }
  68. float margin_box_right() const { return margin_right + border_right + padding_right; }
  69. float margin_box_top() const { return margin_top + border_top + padding_top; }
  70. float margin_box_bottom() const { return margin_bottom + border_bottom + padding_bottom; }
  71. float margin_box_width() const { return margin_box_left() + content_width() + margin_box_right(); }
  72. float margin_box_height() const { return margin_box_top() + content_height() + margin_box_bottom(); }
  73. float border_box_left() const { return border_left + padding_left; }
  74. float border_box_right() const { return border_right + padding_right; }
  75. float border_box_top() const { return border_top + padding_top; }
  76. float border_box_bottom() const { return border_bottom + padding_bottom; }
  77. float border_box_width() const { return border_box_left() + content_width() + border_box_right(); }
  78. float border_box_height() const { return border_box_top() + content_height() + border_box_bottom(); }
  79. Optional<Painting::PaintableBox::OverflowData> overflow_data;
  80. Painting::PaintableBox::OverflowData& ensure_overflow_data()
  81. {
  82. if (!overflow_data.has_value())
  83. overflow_data = Painting::PaintableBox::OverflowData {};
  84. return *overflow_data;
  85. }
  86. Optional<LineBoxFragmentCoordinate> containing_line_box_fragment;
  87. private:
  88. Layout::NodeWithStyleAndBoxModelMetrics* m_node { nullptr };
  89. float m_content_width { 0 };
  90. float m_content_height { 0 };
  91. bool m_has_definite_width { false };
  92. bool m_has_definite_height { false };
  93. };
  94. void commit();
  95. // NOTE: get_mutable() will CoW the UsedValues if it's inherited from an ancestor state;
  96. UsedValues& get_mutable(NodeWithStyleAndBoxModelMetrics const&);
  97. // NOTE: get() will not CoW the UsedValues.
  98. UsedValues const& get(NodeWithStyleAndBoxModelMetrics const&) const;
  99. Vector<OwnPtr<UsedValues>> used_values_per_layout_node;
  100. // We cache intrinsic sizes once determined, as they will not change over the course of a full layout.
  101. // This avoids computing them several times while performing flex layout.
  102. struct IntrinsicSizes {
  103. Optional<float> min_content_width;
  104. Optional<float> max_content_width;
  105. Optional<float> min_content_height;
  106. Optional<float> max_content_height;
  107. };
  108. HashMap<NodeWithStyleAndBoxModelMetrics const*, NonnullOwnPtr<IntrinsicSizes>> mutable intrinsic_sizes;
  109. HashMap<Box const*, float> mutable flex_item_size_cache;
  110. LayoutState const* m_parent { nullptr };
  111. LayoutState const& m_root;
  112. };
  113. Gfx::FloatRect absolute_content_rect(Box const&, LayoutState const&);
  114. Gfx::FloatRect margin_box_rect(Box const&, LayoutState const&);
  115. Gfx::FloatRect margin_box_rect_in_ancestor_coordinate_space(Box const& box, Box const& ancestor_box, LayoutState const&);
  116. }