Changeset 248834 in webkit
- Timestamp:
- Aug 18, 2019 3:16:52 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r248831 r248834 1 2019-08-18 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][TFC] Compute column min/max widths and table width. 4 https://bugs.webkit.org/show_bug.cgi?id=200757 5 <rdar://problem/54333148> 6 7 Reviewed by Antti Koivisto. 8 9 For each column, determine a maximum and minimum column width from the cells that span only that column. 10 The minimum is that required by the cell with the largest minimum cell width (or the column 'width', whichever is larger). 11 The maximum is that required by the cell with the largest maximum cell width (or the column 'width', whichever is larger). 12 13 * layout/tableformatting/TableFormattingContext.cpp: 14 (WebCore::Layout::TableFormattingContext::computePreferredWidthForColumns const): 15 * layout/tableformatting/TableGrid.cpp: 16 (WebCore::Layout::TableGrid::appendCell): 17 * layout/tableformatting/TableGrid.h: 18 (WebCore::Layout::TableGrid::columns): 19 (WebCore::Layout::TableGrid::rows): 20 1 21 2019-08-17 Darin Adler <darin@apple.com> 2 22 -
trunk/Source/WebCore/layout/FormattingContext.h
r248365 r248834 55 55 struct IntrinsicWidthConstraints { 56 56 void expand(LayoutUnit horizontalValue); 57 IntrinsicWidthConstraints& operator+=(const IntrinsicWidthConstraints&); 57 58 58 59 LayoutUnit minimum; … … 148 149 } 149 150 151 inline FormattingContext::IntrinsicWidthConstraints& FormattingContext::IntrinsicWidthConstraints::operator+=(const IntrinsicWidthConstraints& other) 152 { 153 minimum += other.minimum; 154 maximum += other.maximum; 155 return *this; 156 } 157 150 158 } 151 159 } -
trunk/Source/WebCore/layout/displaytree/DisplayBox.h
r248262 r248834 45 45 class InlineFormattingContext; 46 46 class LayoutState; 47 class TableFormattingContext; 47 48 } 48 49 … … 59 60 friend class Layout::InlineFormattingContext; 60 61 friend class Layout::LayoutState; 62 friend class Layout::TableFormattingContext; 61 63 62 64 Box(const RenderStyle&); -
trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp
r248671 r248834 54 54 // 3. Compute the width of the table. 55 55 computeTableWidth(); 56 // 4. Distribute the width of the table among columns. 57 distributeAvailabeWidth(); 58 // 5. Compute the height of the table. 56 // 4. Compute the height of the table. 59 57 computeTableHeight(); 60 // 6. Distribute the height of the table among rows.58 // 5. Distribute the height of the table among rows. 61 59 distributeAvailableHeight(); 62 60 } … … 105 103 grid.slot({ initialPosition.x() + i, initialPosition.y() })->widthConstraints = slotIntrinsicWidth; 106 104 } 105 // 2. For each column, determine a maximum and minimum column width from the cells that span only that column. 106 // The minimum is that required by the cell with the largest minimum cell width (or the column 'width', whichever is larger). 107 // The maximum is that required by the cell with the largest maximum cell width (or the column 'width', whichever is larger). 108 auto& columns = grid.columnsContext().columns(); 109 int numberOfRows = grid.rows().size(); 110 int numberOfColumns = columns.size(); 111 for (int columnIndex = 0; columnIndex < numberOfColumns; ++columnIndex) { 112 auto columnIntrinsicWidths = FormattingContext::IntrinsicWidthConstraints { }; 113 for (int rowIndex = 0; rowIndex < numberOfRows; ++rowIndex) { 114 auto* slot = grid.slot({ columnIndex, rowIndex }); 115 columnIntrinsicWidths.minimum = std::max(slot->widthConstraints.minimum, columnIntrinsicWidths.minimum); 116 columnIntrinsicWidths.maximum = std::max(slot->widthConstraints.maximum, columnIntrinsicWidths.maximum); 117 } 118 columns[columnIndex].setWidthConstraints(columnIntrinsicWidths); 119 } 120 // FIXME: Take column group elements into account. 107 121 } 108 122 109 123 void TableFormattingContext::computeTableWidth() const 110 124 { 125 // Column and caption widths influence the final table width as follows: 126 // If the 'table' or 'inline-table' element's 'width' property has a computed value (W) other than 'auto', the used width is the greater of 127 // W, CAPMIN, and the minimum width required by all the columns plus cell spacing or borders (MIN). 128 // If the used width is greater than MIN, the extra width should be distributed over the columns. 129 // If the 'table' or 'inline-table' element has 'width: auto', the used width is the greater of the table's containing block width, 130 // CAPMIN, and MIN. However, if either CAPMIN or the maximum width required by the columns plus cell spacing or borders (MAX) is 131 // less than that of the containing block, use max(MAX, CAPMIN). 132 133 // FIXME: This kind of code usually lives in *FormattingContextGeometry class. 134 auto& tableWrapperBox = root(); 135 auto& style = tableWrapperBox.style(); 136 auto& containingBlock = *tableWrapperBox.containingBlock(); 137 auto& containingBlockDisplayBox = layoutState().displayBoxForLayoutBox(containingBlock); 138 auto containingBlockWidth = containingBlockDisplayBox.contentBoxWidth(); 139 140 auto& grid = formattingState().tableGrid(); 141 auto& columnsContext = grid.columnsContext(); 142 auto tableWidthConstraints = grid.widthConstraints(); 143 144 auto width = Geometry::computedValueIfNotAuto(style.width(), containingBlockWidth); 145 LayoutUnit usedWidth; 146 if (width) { 147 if (*width > tableWidthConstraints.minimum) { 148 distributeAvailableWidth(*width - tableWidthConstraints.minimum); 149 usedWidth = *width; 150 } else { 151 usedWidth = tableWidthConstraints.minimum; 152 columnsContext.useAsLogicalWidth(TableGrid::ColumnsContext::WidthConstraintsType::Minimum); 153 } 154 } else { 155 if (tableWidthConstraints.minimum > containingBlockWidth) { 156 usedWidth = tableWidthConstraints.minimum; 157 columnsContext.useAsLogicalWidth(TableGrid::ColumnsContext::WidthConstraintsType::Minimum); 158 } else if (tableWidthConstraints.maximum < containingBlockWidth) { 159 usedWidth = tableWidthConstraints.maximum; 160 columnsContext.useAsLogicalWidth(TableGrid::ColumnsContext::WidthConstraintsType::Maximum); 161 } else { 162 usedWidth = containingBlockWidth; 163 distributeAvailableWidth(*width - tableWidthConstraints.minimum); 164 } 165 } 166 167 auto& tableDisplayBox = layoutState().displayBoxForLayoutBox(tableWrapperBox); 168 tableDisplayBox.setContentBoxWidth(usedWidth); 111 169 } 112 170 113 void TableFormattingContext::distributeAvailab eWidth() const171 void TableFormattingContext::distributeAvailableWidth(LayoutUnit extraHorizontalSpace) const 114 172 { 173 // FIXME: Right now just distribute the extra space equaly among the columns. 174 auto& columns = formattingState().tableGrid().columnsContext().columns(); 175 ASSERT(!columns.isEmpty()); 176 177 auto columnExtraSpace = extraHorizontalSpace / columns.size(); 178 for (auto& column : columns) 179 column.setLogicalWidth(column.widthConstraints().minimum + columnExtraSpace); 115 180 } 116 181 -
trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.h
r248596 r248834 49 49 void computePreferredWidthForColumns() const; 50 50 void computeTableWidth() const; 51 void distributeAvailab eWidth() const;51 void distributeAvailableWidth(LayoutUnit extraHorizontalSpace) const; 52 52 void computeTableHeight() const; 53 53 void distributeAvailableHeight() const; -
trunk/Source/WebCore/layout/tableformatting/TableGrid.cpp
r248671 r248834 36 36 WTF_MAKE_ISO_ALLOCATED_IMPL(TableGrid); 37 37 38 void TableGrid::Column::setWidthConstraints(FormattingContext::IntrinsicWidthConstraints widthConstraints) 39 { 40 #ifndef NDEBUG 41 m_hasWidthConstraints = true; 42 #endif 43 m_widthConstraints = widthConstraints; 44 } 45 46 FormattingContext::IntrinsicWidthConstraints TableGrid::Column::widthConstraints() const 47 { 48 ASSERT(m_hasWidthConstraints); 49 return m_widthConstraints; 50 } 51 52 void TableGrid::Column::setLogicalWidth(LayoutUnit computedLogicalWidth) 53 { 54 #ifndef NDEBUG 55 m_hasComputedWidth = true; 56 #endif 57 m_computedLogicalWidth = computedLogicalWidth; 58 } 59 60 LayoutUnit TableGrid::Column::logicalWidth() const 61 { 62 ASSERT(m_hasComputedWidth); 63 return m_computedLogicalWidth; 64 } 65 66 void TableGrid::ColumnsContext::addColumn() 67 { 68 m_columns.append({ }); 69 } 70 71 void TableGrid::ColumnsContext::useAsLogicalWidth(WidthConstraintsType type) 72 { 73 for (auto& column : m_columns) 74 column.setLogicalWidth(type == WidthConstraintsType::Minimum ? column.widthConstraints().minimum : column.widthConstraints().maximum); 75 } 76 38 77 TableGrid::CellInfo::CellInfo(const Box& tableCellBox, SlotPosition position, CellSize size) 39 78 : tableCellBox(tableCellBox) … … 61 100 int rowSpan = tableCellBox.rowSpan(); 62 101 int columnSpan = tableCellBox.columnSpan(); 102 auto isInNewRow = !tableCellBox.previousSibling(); 63 103 auto initialSlotPosition = SlotPosition { }; 64 104 … … 67 107 auto lastSlotPosition = lastCell->position; 68 108 // First table cell in this row? 69 if ( !tableCellBox.previousSibling())109 if (isInNewRow) 70 110 initialSlotPosition = SlotPosition { 0, lastSlotPosition.y() + 1 }; 71 111 else … … 88 128 } 89 129 } 130 // Initialize columns/rows if needed. 131 auto missingNumberOfColumns = std::max<unsigned>(0, (initialSlotPosition.x() + columnSpan) - m_columnsContext.columns().size()); 132 for (unsigned column = 0; column < missingNumberOfColumns; ++column) 133 m_columnsContext.addColumn(); 134 135 if (isInNewRow) 136 m_rows.append({ }); 137 90 138 m_cellList.add(WTFMove(cellInfo)); 91 139 } … … 102 150 } 103 151 152 FormattingContext::IntrinsicWidthConstraints TableGrid::widthConstraints() const 153 { 154 // FIXME: We should probably cache this value. 155 auto widthConstraints = FormattingContext::IntrinsicWidthConstraints { }; 156 for (auto& column : m_columnsContext.columns()) 157 widthConstraints += column.widthConstraints(); 158 return widthConstraints; 159 } 160 104 161 } 105 162 } -
trunk/Source/WebCore/layout/tableformatting/TableGrid.h
r248762 r248834 48 48 49 49 using SlotPosition = IntPoint; 50 51 // Cell represents a <td> or <th>. It can span multiple slots in the grid. 50 52 using CellSize = IntSize; 51 53 struct CellInfo : public CanMakeWeakPtr<CellInfo> { … … 60 62 CellList& cells() { return m_cellList; } 61 63 62 using SlotLogicalSize = LayoutSize; 64 // Column represents a vertical set of slots in the grid. A column has min/max and final width. 65 class ColumnsContext; 66 class Column { 67 public: 68 void setWidthConstraints(FormattingContext::IntrinsicWidthConstraints); 69 FormattingContext::IntrinsicWidthConstraints widthConstraints() const; 70 71 void setLogicalWidth(LayoutUnit); 72 LayoutUnit logicalWidth() const; 73 74 private: 75 friend class ColumnsContext; 76 Column() = default; 77 78 FormattingContext::IntrinsicWidthConstraints m_widthConstraints; 79 LayoutUnit m_computedLogicalWidth; 80 #ifndef NDEBUG 81 bool m_hasWidthConstraints { false }; 82 bool m_hasComputedWidth { false }; 83 #endif 84 }; 85 86 class ColumnsContext { 87 public: 88 using ColumnList = Vector<Column>; 89 ColumnList& columns() { return m_columns; } 90 const ColumnList& columns() const { return m_columns; } 91 92 enum class WidthConstraintsType { Minimum, Maximum }; 93 void useAsLogicalWidth(WidthConstraintsType); 94 95 private: 96 friend class TableGrid; 97 void addColumn(); 98 99 ColumnList m_columns; 100 }; 101 ColumnsContext& columnsContext() { return m_columnsContext; } 102 103 struct Row { 104 LayoutUnit height; 105 }; 106 using RowList = WTF::Vector<Row>; 107 RowList& rows() { return m_rows; } 108 63 109 struct SlotInfo { 64 110 WTF_MAKE_STRUCT_FAST_ALLOCATED; … … 68 114 WeakPtr<CellInfo> cell; 69 115 FormattingContext::IntrinsicWidthConstraints widthConstraints; 70 SlotLogicalSize size;71 116 }; 72 117 SlotInfo* slot(SlotPosition); 73 118 119 FormattingContext::IntrinsicWidthConstraints widthConstraints() const; 120 74 121 private: 75 122 using SlotMap = WTF::HashMap<SlotPosition, std::unique_ptr<SlotInfo>>; 123 76 124 SlotMap m_slotMap; 77 125 CellList m_cellList; 126 ColumnsContext m_columnsContext; 127 RowList m_rows; 78 128 }; 79 129
Note: See TracChangeset
for help on using the changeset viewer.