Changeset 278605 in webkit
- Timestamp:
- Jun 8, 2021, 7:02:56 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 5 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/layoutformattingcontext/table-with-percent-columns-only-no-content-expected.html (added)
-
LayoutTests/fast/layoutformattingcontext/table-with-percent-columns-only-no-content.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/layout/formattingContexts/table/TableFormattingContext.cpp (modified) (5 diffs)
-
Source/WebCore/layout/formattingContexts/table/TableGrid.h (modified) (3 diffs)
-
Source/WebCore/layout/formattingContexts/table/TableLayout.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r278604 r278605 1 2021-06-08 Alan Bujtas <zalan@apple.com> 2 3 [LFC][TFC] Add initial percent value support for columns 4 https://bugs.webkit.org/show_bug.cgi?id=226751 5 6 Reviewed by Simon Fraser. 7 8 * fast/layoutformattingcontext/table-with-percent-columns-only-no-content-expected.html: Added. 9 * fast/layoutformattingcontext/table-with-percent-columns-only-no-content.html: Added. 10 1 11 2021-06-08 Diego Pino Garcia <dpino@igalia.com> 2 12 -
trunk/Source/WebCore/ChangeLog
r278603 r278605 1 2021-06-08 Alan Bujtas <zalan@apple.com> 2 3 [LFC][TFC] Add initial percent value support for columns 4 https://bugs.webkit.org/show_bug.cgi?id=226751 5 6 Reviewed by Simon Fraser. 7 8 This patch adds the initial support for content like this: 9 <table> 10 <tr> 11 <td style="width: 10%"></td><td style="width: 90%"></td> 12 </tr> 13 </table> 14 15 Percent values work in mysterious ways in cases when the table has no fixed width. 16 17 1. The smaller the percent value is, the wider the table may become. 18 19 Percent values are resolved against the cell's border box (so essentially they are resolved 20 against their own content as opposed to the table/containing block) and the formula is slightly different. 21 22 <td style="padding: 5px; width: 20%;"></td> : produces a 10px wide border box (horizontal border: 0px, padding: 10px, content: 0px). 23 The maximum constraint is resolved to 50px (width / percent * 100) 24 <td style="padding: 5px; width: 100%;"></td> : produces a 10px wide border box and the maximum constraint is resolved to 10px. 25 26 This maximum constraint value turns into the available width for the table content and becomes the final table width. 27 28 2. With multiple rows, we pick the highest _percent_ value for each column (as opposed to the resolved values). 29 30 <tr><td style="width: 20%"></td></tr> (assum same 5px padding on both sides) 31 <tr><td style="width: 80%"></td></tr> 32 33 While the second row's cell has a higher maximum constraint value (50px see #1) since we only look at the raw percent values, 34 this content only produces a 12.5px wide table. 35 36 3. The percent values do not accumulate across columns but instead we pick the largest one to represent the entire table's max constraint width. 37 38 <tr><td style="width: 60%"></td><td style="width: 40%"></td></tr> 39 40 60% resolves to 16.6px 41 40% resolves to 25px and we use the 25px value as the width for the entire table (and not 16.6px + 25px). 42 43 4. Since we pick the highest percent values across rows for each columns, we may end up with > 100%. 44 In such cases we start dropping percent values for subsequent columns: 45 46 <tr><td style="width: 20%;"></td><td style="width: 80%;"></td></tr> 47 <tr><td style="width: 60%;"></td><td style="width: 10%;"></td></tr> 48 49 First column width is max(20%, 60%) -> 60% 50 Second column width is max(80%, 10%) -> 80% 51 As we limit the accumulated percent value to 100%, the final column percent values are 60% and 40% (and not 80%). 52 Now the 60% is resolved to 16.6px and the 40% is resolved to 25px and since we don't accumulate these values (see #3) 53 the final table width is 25px (based on a percent value which is not even in the markup). 54 55 5. While the smaller percent values produce wider tables (see #1), during the available space distribution 56 columns with smaller percent values get assigned less space. 57 58 <tr><td style="width: 1%"></td><td style="width: 99%"></td></tr> 59 60 This content produces a 1000px wide table due to the small (1%) percent value (see #1 #2 and #3). 61 When we distribute the available space (1000px), the first cell gets only 10px (1%) while the second cell ends up with 990px (99%). 62 63 (and this is the cherry on top (not included in this patch): 64 Imagine the following scenario: 65 1. the accumulated column percent value > 100% (let's say 80% and 30%) 66 2. as we reach the 100% while walking the columns one by one (see #4), the remaining percent value becomes 0%. 67 3. In order to avoid division by 0, we pick a very small epsilon value to run the formula. 68 4. Now this very small percent value produces a large resolved value (see #2) which means 69 70 <tr><td style="width: 100%"></td></tr> 71 72 produces a 10px wide table 73 74 <tr><td style="width: 100%"></td><td style="width: 1%"></td></tr> <- note the 1% 75 76 produces a very very very wide table. 77 ) 78 79 Test: fast/layoutformattingcontext/table-with-percent-columns-only-no-content.html 80 81 * layout/formattingContexts/table/TableFormattingContext.cpp: 82 (WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints): 83 (WebCore::Layout::TableFormattingContext::computedPreferredWidthForColumns): 84 * layout/formattingContexts/table/TableGrid.h: 85 (WebCore::Layout::TableGrid::Column::percent const): 86 (WebCore::Layout::TableGrid::Column::setFixedWidth): 87 (WebCore::Layout::TableGrid::Column::setPercent): 88 * layout/formattingContexts/table/TableLayout.cpp: 89 (WebCore::Layout::TableFormattingContext::TableLayout::distributedHorizontalSpace): 90 1 91 2021-06-08 Jean-Yves Avenard <jya@apple.com> 2 92 -
trunk/Source/WebCore/layout/formattingContexts/table/TableFormattingContext.cpp
r278537 r278605 297 297 { 298 298 ASSERT(!root().isSizeContainmentBox()); 299 // Tables have a slight y different concept of shrink to fit. It's really only different with non-auto "width" values, where299 // Tables have a slightly different concept of shrink to fit. It's really only different with non-auto "width" values, where 300 300 // a generic shrink-to fit block level box like a float box would be just sized to the computed value of "width", tables 301 // can actually be stre ched way over.301 // can actually be stretched way over. 302 302 auto& grid = formattingState().tableGrid(); 303 303 if (auto computedWidthConstraints = grid.widthConstraints()) … … 329 329 auto* columnBox = column.box(); 330 330 if (!columnBox) { 331 // Ano ynmous columns don't have associated layout boxes and can't have fixed col size.331 // Anonymous columns don't have associated layout boxes and can't have fixed col size. 332 332 return { }; 333 333 } … … 340 340 } 341 341 342 Vector<std::optional<float>> columnPercentList(columnList.size()); 342 343 for (auto& cell : grid.cells()) { 343 344 auto& cellBox = cell->box(); … … 360 361 *fixedWidth += horizontalBorderAndPaddingWidth; 361 362 columnList[cellPosition.column].setFixedWidth(std::max(*fixedWidth, columnList[cellPosition.column].fixedWidth().value_or(0))); 363 } 364 // Collect the percent values so that we can compute the maximum values per column. 365 auto& cellLogicalWidth = cellBox.style().logicalWidth(); 366 if (cellLogicalWidth.isPercent()) { 367 // FIXME: Add support for column spanning distribution. 368 columnPercentList[cellPosition.column] = std::max(cellLogicalWidth.percent(), columnPercentList[cellPosition.column].value_or(0.0f)); 362 369 } 363 370 } … … 412 419 } 413 420 414 // 5. The final table min/max widths is just the accumulated column constraints. 421 // 5. Resolve the percent values. 422 auto remainingPercent = 100.0f; 423 auto percentMaximumConstraint = LayoutUnit { }; 424 for (size_t columnIndex = 0; columnIndex < columnList.size(); ++columnIndex) { 425 auto percent = columnPercentList[columnIndex]; 426 // FIXME: Add support for mixed content with and without percent values. 427 if (!percent) 428 continue; 429 ASSERT(*percent > 0); 430 columnList[columnIndex].setPercent(std::min(remainingPercent, *percent)); 431 percentMaximumConstraint = std::max(percentMaximumConstraint, LayoutUnit { columnIntrinsicWidths[columnIndex].maximum * 100.0f / *columnList[columnIndex].percent() }); 432 remainingPercent -= *columnList[columnIndex].percent(); 433 } 434 435 // 6. The final table min/max widths is just the accumulated column constraints. 415 436 auto tableWidthConstraints = IntrinsicWidthConstraints { }; 416 437 for (auto& columnIntrinsicWidth : columnIntrinsicWidths) 417 438 tableWidthConstraints += columnIntrinsicWidth; 418 // Exapand the preferred width with leading and trailing cell spacing (note that column spanners count as one cell). 439 tableWidthConstraints.maximum = std::max(tableWidthConstraints.maximum, percentMaximumConstraint); 440 // Expand the preferred width with leading and trailing cell spacing (note that column spanners count as one cell). 419 441 tableWidthConstraints += (numberOfActualColumns + 1) * grid.horizontalSpacing(); 420 442 return tableWidthConstraints; -
trunk/Source/WebCore/layout/formattingContexts/table/TableGrid.h
r278537 r278605 74 74 LayoutUnit logicalWidth() const; 75 75 76 void setFixedWidth(LayoutUnit fixedValue) { m_fixedWidth = fixedValue; }76 void setFixedWidth(LayoutUnit fixedValue); 77 77 std::optional<LayoutUnit> fixedWidth() const { return m_fixedWidth; } 78 79 void setPercent(float); 80 std::optional<float> percent() const { return m_percent; } 78 81 79 82 const ContainerBox* box() const { return m_layoutBox.get(); } … … 83 86 LayoutUnit m_computedLogicalLeft; 84 87 std::optional<LayoutUnit> m_fixedWidth; 88 std::optional<float> m_percent; 85 89 WeakPtr<const ContainerBox> m_layoutBox; 86 90 … … 231 235 }; 232 236 237 238 inline void TableGrid::Column::setFixedWidth(LayoutUnit fixedValue) 239 { 240 ASSERT(!m_percent); 241 m_fixedWidth = fixedValue; 242 } 243 244 inline void TableGrid::Column::setPercent(float percent) 245 { 246 ASSERT(!m_fixedWidth); 247 m_percent = percent; 248 } 249 233 250 } 234 251 } -
trunk/Source/WebCore/layout/formattingContexts/table/TableLayout.cpp
r278537 r278605 248 248 float maximumWidth = slot.widthConstraints().maximum; 249 249 250 if (auto fixedWidth = m_grid.columns().list()[columnIndex].fixedWidth()) 250 auto& column = m_grid.columns().list()[columnIndex]; 251 if (auto fixedWidth = column.fixedWidth()) 251 252 maximumWidth = std::max<float>(minimumWidth, *fixedWidth); 253 else if (auto percent = column.percent()) 254 maximumWidth = std::max(minimumWidth, *percent * availableHorizontalSpace / 100.0f); 252 255 253 256 if (columnWidthBalancingBase == ColumnWidthBalancingBase::MinimumWidth) {
Note:
See TracChangeset
for help on using the changeset viewer.