FlexFormattingContext.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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(FormattingState&, Box const& flex_container, FormattingContext* parent);
  13. ~FlexFormattingContext();
  14. virtual bool inhibits_floating() const override { return true; }
  15. virtual void run(Box const&, LayoutMode) override;
  16. Box const& flex_container() const { return context_box(); }
  17. private:
  18. struct DirectionAgnosticMargins {
  19. float main_before { 0 };
  20. float main_after { 0 };
  21. float cross_before { 0 };
  22. float cross_after { 0 };
  23. };
  24. struct FlexItem {
  25. Box& box;
  26. float flex_base_size { 0 };
  27. float hypothetical_main_size { 0 };
  28. float hypothetical_cross_size { 0 };
  29. float hypothetical_cross_size_with_margins() { return hypothetical_cross_size + margins.cross_before + margins.cross_after; }
  30. float target_main_size { 0 };
  31. bool frozen { false };
  32. Optional<float> flex_factor {};
  33. float scaled_flex_shrink_factor { 0 };
  34. float max_content_flex_fraction { 0 };
  35. float main_size { 0 };
  36. float cross_size { 0 };
  37. float main_offset { 0 };
  38. float cross_offset { 0 };
  39. DirectionAgnosticMargins margins {};
  40. bool is_min_violation { false };
  41. bool is_max_violation { false };
  42. };
  43. struct FlexLine {
  44. Vector<FlexItem*> items;
  45. float cross_size { 0 };
  46. };
  47. bool has_definite_main_size(Box const&) const;
  48. bool has_definite_cross_size(Box const&) const;
  49. float specified_main_size(Box const&) const;
  50. float specified_cross_size(Box const&) const;
  51. bool has_main_min_size(Box const&) const;
  52. bool has_cross_min_size(Box const&) const;
  53. bool cross_size_is_absolute_or_resolved_nicely(NodeWithStyle const&) const;
  54. float specified_main_max_size(Box const&) const;
  55. float specified_cross_max_size(Box const&) const;
  56. float calculated_main_size(Box const&) const;
  57. bool is_cross_auto(Box const&) const;
  58. bool is_main_axis_margin_first_auto(Box const&) const;
  59. bool is_main_axis_margin_second_auto(Box const&) const;
  60. float specified_main_size_of_child_box(Box const& child_box) const;
  61. float specified_main_min_size(Box const&) const;
  62. float specified_cross_min_size(Box const&) const;
  63. bool has_main_max_size(Box const&) const;
  64. bool has_cross_max_size(Box const&) const;
  65. float sum_of_margin_padding_border_in_main_axis(Box const&) const;
  66. void set_main_size(Box const&, float size);
  67. void set_cross_size(Box const&, float size);
  68. void set_offset(Box const&, float main_offset, float cross_offset);
  69. void set_main_axis_first_margin(Box const&, float margin);
  70. void set_main_axis_second_margin(Box const&, float margin);
  71. void generate_anonymous_flex_items();
  72. struct AvailableSpace {
  73. float main { 0 };
  74. float cross { 0 };
  75. };
  76. AvailableSpace determine_available_main_and_cross_space(bool& main_size_is_infinite, bool& main_is_constrained, bool& cross_is_constrained, float& main_min_size, float& main_max_size, float& cross_min_size, float& cross_max_size) const;
  77. float layout_for_maximum_main_size(Box const&);
  78. void determine_flex_base_size_and_hypothetical_main_size(FlexItem&);
  79. void determine_main_size_of_flex_container(bool main_is_constrained, bool main_size_is_infinite, float& main_available_size, float main_min_size, float main_max_size);
  80. void collect_flex_items_into_flex_lines(float main_available_size);
  81. void resolve_flexible_lengths(float main_available_size);
  82. float determine_hypothetical_cross_size_of_item(Box const&);
  83. void calculate_cross_size_of_each_flex_line(float cross_min_size, float cross_max_size);
  84. void determine_used_cross_size_of_each_flex_item();
  85. void distribute_any_remaining_free_space(float main_available_size);
  86. void align_all_flex_items_along_the_cross_axis();
  87. void determine_flex_container_used_cross_size(float cross_min_size, float cross_max_size);
  88. void align_all_flex_lines();
  89. bool is_row_layout() const { return m_flex_direction == CSS::FlexDirection::Row || m_flex_direction == CSS::FlexDirection::RowReverse; }
  90. bool is_single_line() const { return flex_container().computed_values().flex_wrap() == CSS::FlexWrap::Nowrap; }
  91. void populate_specified_margins(FlexItem&, CSS::FlexDirection) const;
  92. FormattingState::NodeState& m_flex_container_state;
  93. Vector<FlexLine> m_flex_lines;
  94. Vector<FlexItem> m_flex_items;
  95. CSS::FlexDirection m_flex_direction {};
  96. };
  97. }