Title: [261676] trunk
Revision
261676
Author
za...@apple.com
Date
2020-05-13 22:03:14 -0700 (Wed, 13 May 2020)

Log Message

[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.

Source/WebCore:

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):

LayoutTests:

* fast/layoutformattingcontext/table-fixed-width-with-max-distribution-expected.txt: Added.
* fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (261675 => 261676)


--- trunk/LayoutTests/ChangeLog	2020-05-14 04:55:18 UTC (rev 261675)
+++ trunk/LayoutTests/ChangeLog	2020-05-14 05:03:14 UTC (rev 261676)
@@ -1,5 +1,15 @@
 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.
+
+        * fast/layoutformattingcontext/table-fixed-width-with-max-distribution-expected.txt: Added.
+        * fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html: Added.
+
+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>

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"

Added: trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html (0 => 261676)


--- trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html	                        (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html	2020-05-14 05:03:14 UTC (rev 261676)
@@ -0,0 +1,23 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
+<style>
+table {
+    font-size: 10px;
+    border-spacing: 0px;
+    padding: 30px;
+    border: 10px solid green;
+}
+
+td {
+    outline: 1px solid red;
+}
+</style>
+<table>
+<tr><td style="width: 22px"></td><td>iiiiiiii iiiiiiii</td></tr>
+<tr><td style="width: 22px"></td><td style="width: 22px; height: 20px;">iiiiiiii</td></tr>
+</table>
+
+</style>
+<table>
+<tr><td style="width: 22px"></td><td>iiiiiiii iiiiiiii</td></tr>
+<tr><td style="width: 22px"></td><td style="height: 20px;">iiiiiiii</td></tr>
+</table>

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(), { });
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to