FlexFormattingContext.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <LibWeb/Layout/Box.h>
  8. #include <LibWeb/Layout/FormattingContext.h>
  9. namespace Web::Layout {
  10. class FlexFormattingContext final : public FormattingContext {
  11. public:
  12. FlexFormattingContext(LayoutState&, Box const& flex_container, FormattingContext* parent);
  13. ~FlexFormattingContext();
  14. virtual bool inhibits_floating() const override { return true; }
  15. virtual void run(Box const&, LayoutMode, AvailableSpace const&) override;
  16. virtual float automatic_content_height() const override;
  17. Box const& flex_container() const { return context_box(); }
  18. virtual bool can_determine_size_of_child() const override;
  19. virtual void determine_width_of_child(Box const&, AvailableSpace const&) override;
  20. virtual void determine_height_of_child(Box const&, AvailableSpace const&) override;
  21. private:
  22. void dump_items() const;
  23. struct DirectionAgnosticMargins {
  24. float main_before { 0 };
  25. float main_after { 0 };
  26. float cross_before { 0 };
  27. float cross_after { 0 };
  28. bool main_before_is_auto { false };
  29. bool main_after_is_auto { false };
  30. bool cross_before_is_auto { false };
  31. bool cross_after_is_auto { false };
  32. };
  33. struct FlexItem {
  34. Box& box;
  35. CSS::FlexBasisData used_flex_basis {};
  36. bool used_flex_basis_is_definite { false };
  37. float flex_base_size { 0 };
  38. float hypothetical_main_size { 0 };
  39. float hypothetical_cross_size { 0 };
  40. float hypothetical_cross_size_with_margins() { return hypothetical_cross_size + margins.cross_before + margins.cross_after + borders.cross_after + borders.cross_before + padding.cross_after + padding.cross_before; }
  41. float target_main_size { 0 };
  42. bool frozen { false };
  43. Optional<float> flex_factor {};
  44. float scaled_flex_shrink_factor { 0 };
  45. float desired_flex_fraction { 0 };
  46. float main_size { 0 };
  47. float cross_size { 0 };
  48. float main_offset { 0 };
  49. float cross_offset { 0 };
  50. DirectionAgnosticMargins margins {};
  51. DirectionAgnosticMargins borders {};
  52. DirectionAgnosticMargins padding {};
  53. bool is_min_violation { false };
  54. bool is_max_violation { false };
  55. float add_main_margin_box_sizes(float content_size) const
  56. {
  57. return content_size + margins.main_before + margins.main_after + borders.main_before + borders.main_after + padding.main_before + padding.main_after;
  58. }
  59. float add_cross_margin_box_sizes(float content_size) const
  60. {
  61. return content_size + margins.cross_before + margins.cross_after + borders.cross_before + borders.cross_after + padding.cross_before + padding.cross_after;
  62. }
  63. };
  64. struct FlexLine {
  65. Vector<FlexItem*> items;
  66. float cross_size { 0 };
  67. float remaining_free_space { 0 };
  68. float chosen_flex_fraction { 0 };
  69. };
  70. bool has_definite_main_size(Box const&) const;
  71. bool has_definite_cross_size(Box const&) const;
  72. float specified_main_size(Box const&) const;
  73. float specified_cross_size(Box const&) const;
  74. float resolved_definite_main_size(FlexItem const&) const;
  75. float resolved_definite_cross_size(FlexItem const&) const;
  76. bool has_main_min_size(Box const&) const;
  77. bool has_cross_min_size(Box const&) const;
  78. float specified_main_max_size(Box const&) const;
  79. float specified_cross_max_size(Box const&) const;
  80. bool is_cross_auto(Box const&) const;
  81. float specified_main_min_size(Box const&) const;
  82. float specified_cross_min_size(Box const&) const;
  83. bool has_main_max_size(Box const&) const;
  84. bool has_cross_max_size(Box const&) const;
  85. float automatic_minimum_size(FlexItem const&) const;
  86. float content_based_minimum_size(FlexItem const&) const;
  87. Optional<float> specified_size_suggestion(FlexItem const&) const;
  88. Optional<float> transferred_size_suggestion(FlexItem const&) const;
  89. float content_size_suggestion(FlexItem const&) const;
  90. CSS::Size const& computed_main_size(Box const&) const;
  91. CSS::Size const& computed_main_min_size(Box const&) const;
  92. CSS::Size const& computed_main_max_size(Box const&) const;
  93. CSS::Size const& computed_cross_size(Box const&) const;
  94. CSS::Size const& computed_cross_min_size(Box const&) const;
  95. CSS::Size const& computed_cross_max_size(Box const&) const;
  96. float get_pixel_width(Box const& box, Optional<CSS::Size> const& length_percentage) const;
  97. float get_pixel_height(Box const& box, Optional<CSS::Size> const& length_percentage) const;
  98. bool flex_item_is_stretched(FlexItem const&) const;
  99. void set_main_size(Box const&, float size);
  100. void set_cross_size(Box const&, float size);
  101. void set_offset(Box const&, float main_offset, float cross_offset);
  102. void set_main_axis_first_margin(FlexItem&, float margin);
  103. void set_main_axis_second_margin(FlexItem&, float margin);
  104. void copy_dimensions_from_flex_items_to_boxes();
  105. void generate_anonymous_flex_items();
  106. void determine_available_space_for_items(AvailableSpace const&);
  107. float calculate_indefinite_main_size(FlexItem const&);
  108. void determine_flex_base_size_and_hypothetical_main_size(FlexItem&);
  109. void determine_main_size_of_flex_container();
  110. void collect_flex_items_into_flex_lines();
  111. void resolve_flexible_lengths();
  112. void resolve_cross_axis_auto_margins();
  113. void determine_hypothetical_cross_size_of_item(FlexItem&, bool resolve_percentage_min_max_sizes);
  114. void calculate_cross_size_of_each_flex_line();
  115. CSS::AlignItems alignment_for_item(FlexItem const&) const;
  116. void determine_used_cross_size_of_each_flex_item();
  117. void distribute_any_remaining_free_space();
  118. void align_all_flex_items_along_the_cross_axis();
  119. void determine_flex_container_used_cross_size();
  120. void align_all_flex_lines();
  121. bool is_row_layout() const { return m_flex_direction == CSS::FlexDirection::Row || m_flex_direction == CSS::FlexDirection::RowReverse; }
  122. bool is_single_line() const { return flex_container().computed_values().flex_wrap() == CSS::FlexWrap::Nowrap; }
  123. bool is_direction_reverse() const { return m_flex_direction == CSS::FlexDirection::ColumnReverse || m_flex_direction == CSS::FlexDirection::RowReverse; }
  124. void populate_specified_margins(FlexItem&, CSS::FlexDirection) const;
  125. void determine_intrinsic_size_of_flex_container();
  126. [[nodiscard]] float calculate_intrinsic_main_size_of_flex_container();
  127. [[nodiscard]] float calculate_intrinsic_cross_size_of_flex_container();
  128. [[nodiscard]] float calculate_cross_min_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const;
  129. [[nodiscard]] float calculate_cross_max_content_contribution(FlexItem const&, bool resolve_percentage_min_max_sizes) const;
  130. [[nodiscard]] float calculate_main_min_content_contribution(FlexItem const&) const;
  131. [[nodiscard]] float calculate_main_max_content_contribution(FlexItem const&) const;
  132. [[nodiscard]] float calculate_min_content_main_size(FlexItem const&) const;
  133. [[nodiscard]] float calculate_max_content_main_size(FlexItem const&) const;
  134. [[nodiscard]] float calculate_min_content_cross_size(FlexItem const&) const;
  135. [[nodiscard]] float calculate_max_content_cross_size(FlexItem const&) const;
  136. [[nodiscard]] float calculate_fit_content_main_size(FlexItem const&) const;
  137. [[nodiscard]] float calculate_fit_content_cross_size(FlexItem const&) const;
  138. virtual void parent_context_did_dimension_child_root_box() override;
  139. CSS::FlexBasisData used_flex_basis_for_item(FlexItem const&) const;
  140. LayoutState::UsedValues& m_flex_container_state;
  141. Vector<FlexLine> m_flex_lines;
  142. Vector<FlexItem> m_flex_items;
  143. CSS::FlexDirection m_flex_direction {};
  144. struct AxisAgnosticAvailableSpace {
  145. AvailableSize main;
  146. AvailableSize cross;
  147. AvailableSpace space;
  148. };
  149. Optional<AxisAgnosticAvailableSpace> m_available_space_for_items;
  150. Optional<AxisAgnosticAvailableSpace> m_available_space_for_flex_container;
  151. };
  152. }