LayoutTableDetails.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * This source file is part of RmlUi, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://github.com/mikke89/RmlUi
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. * Copyright (c) 2019 The RmlUi Team, and contributors
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. */
  28. #ifndef RMLUI_CORE_LAYOUTTABLEDETAILS_H
  29. #define RMLUI_CORE_LAYOUTTABLEDETAILS_H
  30. #include "../../Include/RmlUi/Core/Types.h"
  31. #include "../../Include/RmlUi/Core/ComputedValues.h"
  32. #include <float.h>
  33. namespace Rml {
  34. /*
  35. TableGrid builds the structure of the table, that is a list of rows, columns, and cells, taking
  36. spanning attributes into account to position cells.
  37. */
  38. class TableGrid
  39. {
  40. public:
  41. // Build a list of columns, rows, and cells in this table.
  42. bool Build(Element* element_table);
  43. struct Column {
  44. Element* element_column = nullptr; // The '<col>' element which begins at this column, or nullptr if there is no such element or if the column is spanned from a previous column.
  45. Element* element_group = nullptr; // The '<colgroup>' element which begins at this column, otherwise nullptr.
  46. Element* element_cell = nullptr; // The '<td>' element of the first row which begins at this column, otherwise nullptr.
  47. int column_span = 0; // The span of the '<col>' element.
  48. int group_span = 0; // The span of the '<colgroup>' element.
  49. int cell_span = 0; // The colspan of the '<td>' element.
  50. };
  51. struct Row {
  52. Element* element_row = nullptr; // The '<tr>' element which begins at this column, or nullptr if there is no such element or if the column is spanned from a previous column.
  53. Element* element_group = nullptr; // The '<tbody>' element which begins at this column, otherwise nullptr.
  54. int group_span = 0; // The span of the '<tbody>' element.
  55. };
  56. struct Cell {
  57. Element* element_cell = nullptr; // The <td> element.
  58. int row_begin = 0, row_last = 0; // The first and last rows the cell spans.
  59. int column_begin = 0, column_last = 0; // The first and last columns the cell spans.
  60. };
  61. using ColumnList = Vector<Column>;
  62. using RowList = Vector<Row>;
  63. using CellList = Vector<Cell>;
  64. ColumnList columns;
  65. RowList rows;
  66. CellList cells;
  67. private:
  68. void PushColumn(Element* element_column, int column_span);
  69. void PushColumnGroup(Element* element_column_group);
  70. void PushOrMergeColumnsFromFirstRow(Element* element_cell, int column_begin, int span);
  71. void PushRow(Element* element_row, ElementList cell_elements);
  72. CellList open_cells;
  73. };
  74. /*
  75. ComputedTrackSize is an abstraction for computed size properties of rows and column elements alike which
  76. allows them to use the same algorithms. Here, 'a' means left or top, 'b' means right or bottom.
  77. */
  78. struct ComputedTrackSize {
  79. Style::LengthPercentageAuto size;
  80. Style::LengthPercentage min_size, max_size;
  81. Style::Padding padding_a, padding_b;
  82. Style::Margin margin_a, margin_b;
  83. float border_a, border_b;
  84. Style::BoxSizing box_sizing;
  85. };
  86. ComputedTrackSize BuildComputedColumnSize(const ComputedValues& computed);
  87. ComputedTrackSize BuildComputedRowSize(const ComputedValues& computed);
  88. enum class TrackSizingMode { Auto, Fixed, Flexible };
  89. /*
  90. TrackMetric describes the size and the edges of a given track (row or column) in the table.
  91. */
  92. struct TrackMetric {
  93. // All sizes are defined in terms of the border size of cells in the row or column.
  94. TrackSizingMode sizing_mode = TrackSizingMode::Auto;
  95. float fixed_size = 0;
  96. float flex_size = 0;
  97. float min_size = 0;
  98. float max_size = FLT_MAX;
  99. // The following are used for row/column elements.
  100. float column_padding_border_a = 0;
  101. float column_padding_border_b = 0;
  102. // The following are used for group elements.
  103. float group_padding_border_a = 0;
  104. float group_padding_border_b = 0;
  105. // The margins are the sum of the margins from all cells, tracks, and group elements.
  106. float sum_margin_a = 0;
  107. float sum_margin_b = 0;
  108. };
  109. using TrackMetricList = Vector<TrackMetric>;
  110. /*
  111. TracksSizing is a helper class for building the track metrics, with methods applicable to both rows and columns sizing.
  112. */
  113. class TracksSizing {
  114. public:
  115. TracksSizing(TrackMetricList& metrics, float table_initial_content_size, float table_gap) : metrics(metrics), table_initial_content_size(table_initial_content_size), table_gap(table_gap)
  116. {}
  117. // Apply group element. This sets the initial size of edges.
  118. void ApplyGroupElement(const int index, const int span, const ComputedTrackSize& computed);
  119. // Apply track element. This merges its edges, and sets the initial content size.
  120. void ApplyTrackElement(const int index, const int span, const ComputedTrackSize& computed);
  121. // Apply cell element for column sizing. This merges its content size and margins.
  122. void ApplyCellElement(const int index, const int span, const ComputedTrackSize& computed);
  123. // Convert flexible size to fixed size for all tracks.
  124. void ResolveFlexibleSize();
  125. private:
  126. void GetEdgeSizes(float& margin_a, float& margin_b, float& padding_border_a, float& padding_border_b, const ComputedTrackSize& computed) const;
  127. // Fill the track metric with fixed, flexible and min/max size, based on the element's computed values.
  128. void InitializeSize(TrackMetric& metric, float& margin_a, float& margin_b, float& padding_border_a,
  129. float& padding_border_b, const ComputedTrackSize& computed, const int span, const Style::BoxSizing target_box) const;
  130. TrackMetricList& metrics;
  131. const float table_initial_content_size;
  132. const float table_gap;
  133. };
  134. /*
  135. TrackBox represents the size and offset of any given track (row or column).
  136. Rows: Sizes == Heights. Offsets along vertical axis.
  137. Columns: Sizes == Widths. Offsets along horizontal axis.
  138. */
  139. struct TrackBox {
  140. float cell_size = 0; // The *border* size of cells in this track, does not account for spanning cells.
  141. float cell_offset = 0; // Offset from the table content box to the border box of cells in this track.
  142. float track_size = 0; // The *content* size of the row/column element, which may span multiple tracks.
  143. float track_offset = 0; // Offset from the table content box to the border box of the row/column element.
  144. float group_size = 0; // The *content* size of the group element, which may span multiple tracks.
  145. float group_offset = 0; // Offset from the table content box to the border box of the group element.
  146. };
  147. using TrackBoxList = Vector<TrackBox>;
  148. // Build a list of column boxes from the provided metrics.
  149. // @return The accumulated width of all columns.
  150. float BuildColumnBoxes(TrackBoxList& column_boxes, const TrackMetricList& column_metrics, const TableGrid::ColumnList& grid_columns, float table_gap_x);
  151. // Build a list of row boxes from the provided metrics.
  152. // @return The accumulated height of all rows.
  153. float BuildRowBoxes(TrackBoxList& row_boxes, const TrackMetricList& row_metrics, const TableGrid::RowList& grid_rows, float table_gap_y);
  154. // Return the border size of a cell spanning one or multiple tracks.
  155. inline float GetSpanningCellBorderSize(const TrackBoxList& boxes, const int index, const int index_last_span)
  156. {
  157. RMLUI_ASSERT(index < (int)boxes.size() && index_last_span < (int)boxes.size());
  158. return boxes[index_last_span].cell_size + (boxes[index_last_span].cell_offset - boxes[index].cell_offset);
  159. }
  160. } // namespace Rml
  161. #endif