Added: trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution-expected.txt (0 => 261676)
--- trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution-expected.txt 2020-05-14 05:03:14 UTC (rev 261676)
@@ -0,0 +1,30 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x263
+ RenderBlock {HTML} at (0,0) size 800x263
+ RenderBody {BODY} at (8,8) size 784x247
+ RenderTable {TABLE} at (0,0) size 153x130 [border: (10px solid #008000)]
+ RenderTableSection {TBODY} at (40,40) size 73x50
+ RenderTableRow {TR} at (0,0) size 73x28
+ RenderTableCell {TD} at (0,13) size 33x2 [r=0 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (32,0) size 41x28 [r=0 c=1 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 23x26
+ text run at (1,1) width 23: "iiiiiiii"
+ text run at (1,14) width 23: "iiiiiiii"
+ RenderTableRow {TR} at (0,28) size 73x22
+ RenderTableCell {TD} at (0,38) size 33x2 [r=1 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (32,31) size 41x16 [r=1 c=1 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 23x14
+ text run at (1,2) width 23: "iiiiiiii"
+ RenderTable {TABLE} at (0,130) size 153x117 [border: (10px solid #008000)]
+ RenderTableSection {TBODY} at (40,40) size 73x37
+ RenderTableRow {TR} at (0,0) size 73x15
+ RenderTableCell {TD} at (0,6) size 24x3 [r=0 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (24,0) size 49x15 [r=0 c=1 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 47x13
+ text run at (1,1) width 47: "iiiiiiii iiiiiiii"
+ RenderTableRow {TR} at (0,15) size 73x22
+ RenderTableCell {TD} at (0,25) size 24x2 [r=1 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (24,18) size 49x16 [r=1 c=1 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 23x14
+ text run at (1,2) width 23: "iiiiiiii"
Modified: trunk/Source/WebCore/ChangeLog (261675 => 261676)
--- trunk/Source/WebCore/ChangeLog 2020-05-14 04:55:18 UTC (rev 261675)
+++ trunk/Source/WebCore/ChangeLog 2020-05-14 05:03:14 UTC (rev 261676)
@@ -1,5 +1,44 @@
2020-05-13 Zalan Bujtas <za...@apple.com>
+ [LFC][TFC] Add support for cases when the balancing is not based on the initial width
+ https://bugs.webkit.org/show_bug.cgi?id=211878
+
+ Reviewed by Antti Koivisto.
+
+ This patch adds support for the cases when the table stretches all the way to the maximum content size,
+ and we still choose the minimum width as the initial width and the maximum width as the base for balancing the extra space.
+
+ Consider the following 2 tables:
+
+ <table>
+ <tr><td style="width: 20px"></td><td>some long long long content</td></tr>
+ <tr><td style="width: 20px"></td><td>22px width content</td></tr>
+ </table>
+
+ <table>
+ <tr><td style="width: 20px"></td><td>some long long long content</td></tr>
+ <tr><td style="width: 20px"></td><td id=fixed_width style="width: 22px;">22px width content</td></tr>
+ </table>
+
+ These tables have the same maximum widths and they both stretch to that size.
+ However the second table will end up with a wider first and narrower second column because of the
+ width property on the [fixed_width] cell.
+ While the first table applies the maximum width for each columns, the second table uses the minimum width as the
+ initial width and balances the extra space using the maximum width (as the distribution ratio).
+ This produces a very different layout where the first table has no line wrapping, while
+ the second table wraps the "some long long long content" text (even though the used max widths are the same for each cells).
+
+ Test: fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html
+
+ * layout/tableformatting/TableFormattingContext.cpp:
+ (WebCore::Layout::ColumnSpan::spacing):
+ (WebCore::Layout::RowSpan::spacing):
+ (WebCore::Layout::distributeAvailableSpace):
+ (WebCore::Layout::TableFormattingContext::computeAndDistributeExtraHorizontalSpace):
+ (WebCore::Layout::TableFormattingContext::computeAndDistributeExtraVerticalSpace):
+
+2020-05-13 Zalan Bujtas <za...@apple.com>
+
Do not clear selection/repaint when the renderer gets moved during tree normalization.
https://bugs.webkit.org/show_bug.cgi?id=211865
<rdar://problem/62849044>
Modified: trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp (261675 => 261676)
--- trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp 2020-05-14 04:55:18 UTC (rev 261675)
+++ trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp 2020-05-14 05:03:14 UTC (rev 261676)
@@ -361,7 +361,7 @@
static size_t index(size_t columnIndex, size_t /*rowIndex*/) { return columnIndex; }
static size_t size(const TableGrid& grid) { return grid.columns().size(); }
- static LayoutUnit spacing(const TableGrid& grid, const TableGrid::Cell& cell) { return (cell.columnSpan() - 1) * grid.horizontalSpacing(); }
+ static LayoutUnit spacing(const TableGrid& grid) { return grid.horizontalSpacing(); }
};
struct RowSpan {
@@ -375,7 +375,7 @@
static size_t index(size_t /*columnIndex*/, size_t rowIndex) { return rowIndex; }
static size_t size(const TableGrid& grid) { return grid.rows().size(); }
- static LayoutUnit spacing(const TableGrid& grid, const TableGrid::Cell& cell) { return (cell.rowSpan() - 1) * grid.verticalSpacing(); }
+ static LayoutUnit spacing(const TableGrid& grid) { return grid.verticalSpacing(); }
};
struct GridSpace {
@@ -420,7 +420,7 @@
using DistributedSpaces = Vector<float>;
template <typename SpanType>
-static DistributedSpaces distributeAvailableSpace(const TableGrid& grid, float spaceToDistribute, const WTF::Function<GridSpace(const TableGrid::Slot&, size_t)>& slotSpace)
+static DistributedSpaces distributeAvailableSpace(const TableGrid& grid, LayoutUnit availableSpace, const WTF::Function<GridSpace(const TableGrid::Slot&, size_t)>& slotSpace)
{
struct ResolvedItem {
GridSpace slotSpace;
@@ -505,7 +505,7 @@
// The spanning cell fits the spanned columns/rows just fine. Nothing to distribute.
continue;
}
- auto spacing = SpanType::spacing(grid, cell);
+ auto spacing = SpanType::spacing(grid) * (SpanType::spanCount(cell) - 1);
auto spaceToDistribute = unresolvedSpanningSpace - GridSpace { spacing, spacing } - resolvedSpanningSpace;
if (!spaceToDistribute.isEmpty()) {
auto distributionRatio = spaceToDistribute.distributionBase / resolvedSpanningSpace.distributionBase;
@@ -529,6 +529,9 @@
}
DistributedSpaces distributedSpaces(resolvedItems.size());
+ float spaceToDistribute = availableSpace - adjustabledSpace.value - ((resolvedItems.size() + 1) * SpanType::spacing(grid));
+ // Essentially the remaining space to distribute should never be negative. LayoutUnit::epsilon() is required to compensate for LayoutUnit's low precision.
+ ASSERT(spaceToDistribute >= -LayoutUnit::epsilon() * resolvedItems.size());
// Distribute the extra space based on the resolved spaces.
auto distributionRatio = spaceToDistribute / adjustabledSpace.distributionBase;
for (size_t index = 0; index < resolvedItems.size(); ++index) {
@@ -537,7 +540,7 @@
distributedSpaces[index] = slotSpace;
if (!needsSpaceDistribution)
continue;
- distributedSpaces[index] += slotSpace * distributionRatio;
+ distributedSpaces[index] += resolvedItems[index]->slotSpace.distributionBase * distributionRatio;
}
return distributedSpaces;
}
@@ -552,11 +555,19 @@
auto computeColumnWidths = [&] (auto columnWidthBalancingBase, auto extraHorizontalSpace) {
auto distributedSpaces = distributeAvailableSpace<ColumnSpan>(grid, extraHorizontalSpace, [&] (const TableGrid::Slot& slot, size_t columnIndex) {
auto& column = columns.list()[columnIndex];
- auto columnFixedWidth = column.box() ? column.box()->columnWidth() : WTF::nullopt;
- auto slotWidth = std::max<float>(columnWidthBalancingBase == ColumnWidthBalancingBase::MinimumWidth ? slot.widthConstraints().minimum : slot.widthConstraints().maximum, columnFixedWidth.valueOr(0_lu));
- return GridSpace { slotWidth, slotWidth };
+ auto columnBoxFixedWidth = column.box() ? column.box()->columnWidth().valueOr(0_lu) : 0_lu;
+ if (columnWidthBalancingBase == ColumnWidthBalancingBase::MinimumWidth) {
+ auto minimumWidth = std::max<float>(slot.widthConstraints().minimum, columnBoxFixedWidth);
+ return GridSpace { minimumWidth, minimumWidth };
+ }
+ // When the column has a fixed width cell, the maximum width balancing is based on the minimum width.
+ auto minimumWidth = std::max<float>(slot.widthConstraints().minimum, columnBoxFixedWidth);
+ auto maximumWidth = std::max<float>(slot.widthConstraints().maximum, columnBoxFixedWidth);
+ if (column.isFixedWidth())
+ return GridSpace { minimumWidth, maximumWidth };
+ return GridSpace { maximumWidth, maximumWidth };
});
- // Set finial horizontal position and width.
+ // Set final horizontal position and width.
auto columnLogicalLeft = grid.horizontalSpacing();
for (size_t columnIndex = 0; columnIndex < columns.size(); ++columnIndex) {
auto& column = columns.list()[columnIndex];
@@ -567,16 +578,8 @@
columnLogicalLeft += columnWidth + grid.horizontalSpacing();
}
};
-
- auto needsExtraSpaceDistribution = availableHorizontalSpace != tableWidthConstraints.minimum && availableHorizontalSpace != tableWidthConstraints.maximum;
- if (!needsExtraSpaceDistribution) {
- auto columnWidthBalancingBase = availableHorizontalSpace == tableWidthConstraints.maximum ? ColumnWidthBalancingBase::MaximumWidth : ColumnWidthBalancingBase::MinimumWidth;
- computeColumnWidths(columnWidthBalancingBase, LayoutUnit { });
- return;
- }
- auto horizontalSpaceToDistribute = availableHorizontalSpace - tableWidthConstraints.minimum;
- ASSERT(horizontalSpaceToDistribute > 0);
- computeColumnWidths(ColumnWidthBalancingBase::MinimumWidth, horizontalSpaceToDistribute);
+ auto columnWidthBalancingBase = availableHorizontalSpace == tableWidthConstraints.maximum ? ColumnWidthBalancingBase::MaximumWidth : ColumnWidthBalancingBase::MinimumWidth;
+ computeColumnWidths(columnWidthBalancingBase, availableHorizontalSpace);
}
void TableFormattingContext::computeAndDistributeExtraVerticalSpace(LayoutUnit availableHorizontalSpace, Optional<LayoutUnit> availableVerticalSpace)
@@ -593,7 +596,7 @@
};
Vector<RowHeight> rowHeight(rows.size());
Vector<SlotPosition> spanningRowPositionList;
- float tableUsedHeight = 0;
+ LayoutUnit tableUsedHeight;
// 1. Collect initial, basline aligned row heights.
for (size_t rowIndex = 0; rowIndex < rows.size(); ++rowIndex) {
auto maximumColumnAscent = InlineLayoutUnit { };
@@ -620,10 +623,9 @@
// FIXME: Collect spanning row maximum heights.
// Distribute extra space if the table is supposed to be taller than the sum of the row heights.
- float spaceToDistribute = 0;
- if (availableVerticalSpace)
- spaceToDistribute = std::max(0.0f, *availableVerticalSpace - ((rows.size() + 1) * grid.verticalSpacing()) - tableUsedHeight);
- auto distributedSpaces = distributeAvailableSpace<RowSpan>(grid, spaceToDistribute, [&] (const TableGrid::Slot& slot, size_t rowIndex) {
+ tableUsedHeight += (rows.size() + 1) * grid.verticalSpacing();
+ auto availableSpace = std::max(availableVerticalSpace.valueOr(0_lu), tableUsedHeight);
+ auto distributedSpaces = distributeAvailableSpace<RowSpan>(grid, availableSpace, [&] (const TableGrid::Slot& slot, size_t rowIndex) {
if (slot.hasRowSpan())
return GridSpace { geometryForBox(slot.cell().box()).height(), geometryForBox(slot.cell().box()).height() };
auto computedRowHeight = geometry().computedHeight(rows.list()[rowIndex].box(), { });