TableFormattingContext.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Forward.h>
  8. #include <LibWeb/Layout/FormattingContext.h>
  9. #include <LibWeb/Layout/TableWrapper.h>
  10. namespace Web::Layout {
  11. enum class TableDimension {
  12. Row,
  13. Column
  14. };
  15. class TableFormattingContext final : public FormattingContext {
  16. public:
  17. explicit TableFormattingContext(LayoutState&, Box const&, FormattingContext* parent);
  18. ~TableFormattingContext();
  19. virtual void run(Box const&, LayoutMode, AvailableSpace const&) override;
  20. virtual CSSPixels automatic_content_width() const override;
  21. virtual CSSPixels automatic_content_height() const override;
  22. Box const& table_box() const { return context_box(); }
  23. TableWrapper const& table_wrapper() const
  24. {
  25. return verify_cast<TableWrapper>(*table_box().containing_block());
  26. }
  27. static bool border_is_less_specific(const CSS::BorderData& a, const CSS::BorderData& b);
  28. private:
  29. CSSPixels run_caption_layout(LayoutMode, CSS::CaptionSide);
  30. CSSPixels compute_capmin();
  31. void calculate_row_column_grid(Box const&);
  32. void compute_constrainedness();
  33. void compute_cell_measures(AvailableSpace const& available_space);
  34. void compute_outer_content_sizes();
  35. template<class RowOrColumn>
  36. void initialize_table_measures();
  37. template<class RowOrColumn>
  38. void compute_table_measures();
  39. template<class RowOrColumn>
  40. void compute_intrinsic_percentage(size_t max_cell_span);
  41. void compute_table_width();
  42. void distribute_width_to_columns();
  43. void distribute_excess_width_to_columns(CSSPixels available_width);
  44. void distribute_excess_width_to_columns_fixed_mode(CSSPixels excess_width);
  45. void compute_table_height(LayoutMode layout_mode);
  46. void distribute_height_to_rows();
  47. void position_row_boxes();
  48. void position_cell_boxes();
  49. void border_conflict_resolution();
  50. CSSPixels border_spacing_horizontal() const;
  51. CSSPixels border_spacing_vertical() const;
  52. CSSPixels compute_columns_total_used_width() const;
  53. void commit_candidate_column_widths(Vector<CSSPixels> const& candidate_widths);
  54. void assign_columns_width_linear_combination(Vector<CSSPixels> const& candidate_widths, CSSPixels available_width);
  55. template<class ColumnFilter, class BaseWidthGetter>
  56. bool distribute_excess_width_proportionally_to_base_width(CSSPixels excess_width, ColumnFilter column_filter, BaseWidthGetter base_width_getter);
  57. template<class ColumnFilter>
  58. bool distribute_excess_width_equally(CSSPixels excess_width, ColumnFilter column_filter);
  59. template<class ColumnFilter>
  60. bool distribute_excess_width_by_intrinsic_percentage(CSSPixels excess_width, ColumnFilter column_filter);
  61. bool use_fixed_mode_layout() const;
  62. CSSPixels m_table_height { 0 };
  63. CSSPixels m_automatic_content_height { 0 };
  64. Optional<AvailableSpace> m_available_space;
  65. struct Column {
  66. CSSPixels left_offset { 0 };
  67. CSSPixels min_size { 0 };
  68. CSSPixels max_size { 0 };
  69. CSSPixels used_width { 0 };
  70. bool has_intrinsic_percentage { false };
  71. double intrinsic_percentage { 0 };
  72. // Store whether the column is constrained: https://www.w3.org/TR/css-tables-3/#constrainedness
  73. bool is_constrained { false };
  74. // Store whether the column has originating cells, defined in https://www.w3.org/TR/css-tables-3/#terminology.
  75. bool has_originating_cells { false };
  76. };
  77. struct Row {
  78. JS::NonnullGCPtr<Box const> box;
  79. CSSPixels base_height { 0 };
  80. CSSPixels reference_height { 0 };
  81. CSSPixels final_height { 0 };
  82. CSSPixels baseline { 0 };
  83. CSSPixels min_size { 0 };
  84. CSSPixels max_size { 0 };
  85. bool has_intrinsic_percentage { false };
  86. double intrinsic_percentage { 0 };
  87. // Store whether the row is constrained: https://www.w3.org/TR/css-tables-3/#constrainedness
  88. bool is_constrained { false };
  89. };
  90. struct Cell {
  91. JS::NonnullGCPtr<Box const> box;
  92. size_t column_index;
  93. size_t row_index;
  94. size_t column_span;
  95. size_t row_span;
  96. CSSPixels baseline { 0 };
  97. CSSPixels outer_min_width { 0 };
  98. CSSPixels outer_max_width { 0 };
  99. CSSPixels outer_min_height { 0 };
  100. CSSPixels outer_max_height { 0 };
  101. };
  102. // Accessors to enable direction-agnostic table measurement.
  103. template<class RowOrColumn>
  104. static size_t cell_span(Cell const& cell);
  105. template<class RowOrColumn>
  106. static size_t cell_index(Cell const& cell);
  107. template<class RowOrColumn>
  108. static CSSPixels cell_min_size(Cell const& cell);
  109. template<class RowOrColumn>
  110. static CSSPixels cell_max_size(Cell const& cell);
  111. template<class RowOrColumn>
  112. static double cell_percentage_contribution(Cell const& cell);
  113. template<class RowOrColumn>
  114. static bool cell_has_intrinsic_percentage(Cell const& cell);
  115. template<class RowOrColumn>
  116. void initialize_intrinsic_percentages_from_rows_or_columns();
  117. template<class RowOrColumn>
  118. void initialize_intrinsic_percentages_from_cells();
  119. template<class RowOrColumn>
  120. CSSPixels border_spacing();
  121. template<class RowOrColumn>
  122. Vector<RowOrColumn>& table_rows_or_columns();
  123. CSSPixels compute_row_content_height(Cell const& cell) const;
  124. enum class ConflictingSide {
  125. Top,
  126. Bottom,
  127. Left,
  128. Right,
  129. };
  130. struct ConflictingEdge {
  131. Node const* element;
  132. Painting::PaintableBox::ConflictingElementKind element_kind;
  133. ConflictingSide side;
  134. Optional<size_t> row;
  135. Optional<size_t> column;
  136. };
  137. static TableFormattingContext::ConflictingEdge const& winning_conflicting_edge(TableFormattingContext::ConflictingEdge const& a, TableFormattingContext::ConflictingEdge const& b);
  138. static const CSS::BorderData& border_data_conflicting_edge(ConflictingEdge const& conflicting_edge);
  139. static const Painting::PaintableBox::BorderDataWithElementKind border_data_with_element_kind_from_conflicting_edge(ConflictingEdge const& conflicting_edge);
  140. class BorderConflictFinder {
  141. public:
  142. BorderConflictFinder(TableFormattingContext const* context);
  143. Vector<ConflictingEdge> conflicting_edges(Cell const&, ConflictingSide) const;
  144. private:
  145. void collect_conflicting_col_elements();
  146. void collect_conflicting_row_group_elements();
  147. void collect_cell_conflicting_edges(Vector<ConflictingEdge>&, Cell const&, ConflictingSide) const;
  148. void collect_row_conflicting_edges(Vector<ConflictingEdge>&, Cell const&, ConflictingSide) const;
  149. void collect_row_group_conflicting_edges(Vector<ConflictingEdge>&, Cell const&, ConflictingSide) const;
  150. void collect_column_group_conflicting_edges(Vector<ConflictingEdge>&, Cell const&, ConflictingSide) const;
  151. void collect_table_box_conflicting_edges(Vector<ConflictingEdge>&, Cell const&, ConflictingSide) const;
  152. struct RowGroupInfo {
  153. Node const* row_group;
  154. size_t start_index;
  155. size_t row_count;
  156. };
  157. Vector<Node const*> m_col_elements_by_index;
  158. Vector<Optional<RowGroupInfo>> m_row_group_elements_by_index;
  159. TableFormattingContext const* m_context;
  160. };
  161. Vector<Cell> m_cells;
  162. Vector<Vector<Optional<Cell const&>>> m_cells_by_coordinate;
  163. Vector<Column> m_columns;
  164. Vector<Row> m_rows;
  165. };
  166. }