Title: [262795] trunk
Revision
262795
Author
[email protected]
Date
2020-06-09 08:59:29 -0700 (Tue, 09 Jun 2020)

Log Message

[LFC][TFC] Add support for empty table
https://bugs.webkit.org/show_bug.cgi?id=212971

Reviewed by Antti Koivisto.

Source/WebCore:

No need to run formatting context layout when the table box has no descendant.

Test: fast/layoutformattingcontext/empty-table-box.html

* layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp:
(WebCore::Layout::TableWrapperBlockFormattingContext::layoutTableBox):
(WebCore::Layout::TableWrapperBlockFormattingContext::computeBorderAndPaddingForTableBox):
(WebCore::Layout::TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox):
* layout/tableformatting/TableFormattingContext.cpp:
(WebCore::Layout::TableFormattingContext::ensureTableGrid):
* layout/tableformatting/TableGrid.h:
(WebCore::Layout::TableGrid::isEmpty const):

LayoutTests:

* fast/layoutformattingcontext/empty-table-box-expected.html: Added.
* fast/layoutformattingcontext/empty-table-box.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (262794 => 262795)


--- trunk/LayoutTests/ChangeLog	2020-06-09 15:45:17 UTC (rev 262794)
+++ trunk/LayoutTests/ChangeLog	2020-06-09 15:59:29 UTC (rev 262795)
@@ -1,3 +1,13 @@
+2020-06-09  Zalan Bujtas  <[email protected]>
+
+        [LFC][TFC] Add support for empty table
+        https://bugs.webkit.org/show_bug.cgi?id=212971
+
+        Reviewed by Antti Koivisto.
+
+        * fast/layoutformattingcontext/empty-table-box-expected.html: Added.
+        * fast/layoutformattingcontext/empty-table-box.html: Added.
+
 2020-06-09  Youenn Fablet  <[email protected]>
 
         Fix two MediaStream tests

Added: trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box-expected.html (0 => 262795)


--- trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box-expected.html	2020-06-09 15:59:29 UTC (rev 262795)
@@ -0,0 +1,9 @@
+<!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
+<style>
+div {
+    width: 100px;
+    height: 100px;
+}
+</style>
+<div style="background-color: green;"></div>
+<div style="background-color: blue; height: 10px; margin-top: -100px"></div>

Added: trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box.html (0 => 262795)


--- trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box.html	                        (rev 0)
+++ trunk/LayoutTests/fast/layoutformattingcontext/empty-table-box.html	2020-06-09 15:59:29 UTC (rev 262795)
@@ -0,0 +1,17 @@
+<!-- webkit-test-runner [ internal:LayoutFormattingContextEnabled=true internal:LayoutFormattingContextIntegrationEnabled=false ] -->
+<style>
+.container {
+    width: 100px;
+    height: 100px;
+    background: green;
+}
+.empty_table {
+    display: table;
+    width: 90px;
+    height: 50px;
+    border: 5px solid blue;
+}
+</style>
+<div class=container>
+  <div class=empty_table></div>
+</div>

Modified: trunk/Source/WebCore/ChangeLog (262794 => 262795)


--- trunk/Source/WebCore/ChangeLog	2020-06-09 15:45:17 UTC (rev 262794)
+++ trunk/Source/WebCore/ChangeLog	2020-06-09 15:59:29 UTC (rev 262795)
@@ -1,3 +1,23 @@
+2020-06-09  Zalan Bujtas  <[email protected]>
+
+        [LFC][TFC] Add support for empty table
+        https://bugs.webkit.org/show_bug.cgi?id=212971
+
+        Reviewed by Antti Koivisto.
+
+        No need to run formatting context layout when the table box has no descendant.
+
+        Test: fast/layoutformattingcontext/empty-table-box.html
+
+        * layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp:
+        (WebCore::Layout::TableWrapperBlockFormattingContext::layoutTableBox):
+        (WebCore::Layout::TableWrapperBlockFormattingContext::computeBorderAndPaddingForTableBox):
+        (WebCore::Layout::TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox):
+        * layout/tableformatting/TableFormattingContext.cpp:
+        (WebCore::Layout::TableFormattingContext::ensureTableGrid):
+        * layout/tableformatting/TableGrid.h:
+        (WebCore::Layout::TableGrid::isEmpty const):
+
 2020-06-09  Youenn Fablet  <[email protected]>
 
         Forward declare MediaKeys/MediaKeySession in Internals.h

Modified: trunk/Source/WebCore/layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp (262794 => 262795)


--- trunk/Source/WebCore/layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp	2020-06-09 15:45:17 UTC (rev 262794)
+++ trunk/Source/WebCore/layout/blockformatting/tablewrapper/TableWrapperBlockFormattingContext.cpp	2020-06-09 15:59:29 UTC (rev 262795)
@@ -73,8 +73,10 @@
     computeWidthAndMarginForTableBox(tableBox, constraints.horizontal);
     computeStaticHorizontalPosition(tableBox, constraints.horizontal);
 
-    auto invalidationState = InvalidationState { };
-    LayoutContext::createFormattingContext(tableBox, layoutState())->layoutInFlowContent(invalidationState, geometry().constraintsForInFlowContent(tableBox));
+    if (tableBox.hasChild()) {
+        auto invalidationState = InvalidationState { };
+        LayoutContext::createFormattingContext(tableBox, layoutState())->layoutInFlowContent(invalidationState, geometry().constraintsForInFlowContent(tableBox));
+    }
 
     computeHeightAndMarginForTableBox(tableBox, constraints);
 }
@@ -82,66 +84,75 @@
 void TableWrapperBlockFormattingContext::computeBorderAndPaddingForTableBox(const ContainerBox& tableBox, const HorizontalConstraints& horizontalConstraints)
 {
     ASSERT(tableBox.isTableBox());
-    if (tableBox.style().borderCollapse() == BorderCollapse::Collapse) {
-        // UAs must compute an initial left and right border width for the table by examining
-        // the first and last cells in the first row of the table.
-        // The left border width of the table is half of the first cell's collapsed left border,
-        // and the right border width of the table is half of the last cell's collapsed right border.
-        // The top border width of the table is computed by examining all cells who collapse their top
-        // borders with the top border of the table. The top border width of the table is equal to half of the
-        // maximum collapsed top border. The bottom border width is computed by examining all cells whose bottom borders collapse
-        // with the bottom of the table. The bottom border width is equal to half of the maximum collapsed bottom border.
-        auto& grid = layoutState().establishedTableFormattingState(tableBox).tableGrid();
-        auto tableBorder = geometry().computedBorder(tableBox);
+    if (!tableBox.hasChild() || tableBox.style().borderCollapse() == BorderCollapse::Separate) {
+        BlockFormattingContext::computeBorderAndPadding(tableBox, horizontalConstraints);
+        return;
+    }
+    // UAs must compute an initial left and right border width for the table by examining
+    // the first and last cells in the first row of the table.
+    // The left border width of the table is half of the first cell's collapsed left border,
+    // and the right border width of the table is half of the last cell's collapsed right border.
+    // The top border width of the table is computed by examining all cells who collapse their top
+    // borders with the top border of the table. The top border width of the table is equal to half of the
+    // maximum collapsed top border. The bottom border width is computed by examining all cells whose bottom borders collapse
+    // with the bottom of the table. The bottom border width is equal to half of the maximum collapsed bottom border.
+    auto& grid = layoutState().establishedTableFormattingState(tableBox).tableGrid();
+    auto tableBorder = geometry().computedBorder(tableBox);
 
-        auto& firstColumnFirstRowBox = grid.slot({ 0 , 0 })->cell().box();
-        auto leftBorder = std::max(tableBorder.horizontal.left, geometry().computedBorder(firstColumnFirstRowBox).horizontal.left);
+    auto& firstColumnFirstRowBox = grid.slot({ 0 , 0 })->cell().box();
+    auto leftBorder = std::max(tableBorder.horizontal.left, geometry().computedBorder(firstColumnFirstRowBox).horizontal.left);
 
-        auto& lastColumnFirstRow = grid.slot({ grid.columns().size() - 1, 0 })->cell().box();
-        auto rightBorder = std::max(tableBorder.horizontal.right, geometry().computedBorder(lastColumnFirstRow).horizontal.right);
+    auto& lastColumnFirstRow = grid.slot({ grid.columns().size() - 1, 0 })->cell().box();
+    auto rightBorder = std::max(tableBorder.horizontal.right, geometry().computedBorder(lastColumnFirstRow).horizontal.right);
 
-        auto topBorder = tableBorder.vertical.top;
-        auto bottomBorder = tableBorder.vertical.bottom;
-        auto lastRowIndex = grid.rows().size() - 1;
-        for (size_t columnIndex = 0; columnIndex < grid.columns().size(); ++columnIndex) {
-            auto& boxInFirstRox = grid.slot({ columnIndex, 0 })->cell().box();
-            auto& boxInLastRow = grid.slot({ columnIndex, lastRowIndex })->cell().box();
+    auto topBorder = tableBorder.vertical.top;
+    auto bottomBorder = tableBorder.vertical.bottom;
+    auto lastRowIndex = grid.rows().size() - 1;
+    for (size_t columnIndex = 0; columnIndex < grid.columns().size(); ++columnIndex) {
+        auto& boxInFirstRox = grid.slot({ columnIndex, 0 })->cell().box();
+        auto& boxInLastRow = grid.slot({ columnIndex, lastRowIndex })->cell().box();
 
-            topBorder = std::max(topBorder, geometry().computedBorder(boxInFirstRox).vertical.top);
-            bottomBorder = std::max(bottomBorder, geometry().computedBorder(boxInLastRow).vertical.bottom);
-        }
+        topBorder = std::max(topBorder, geometry().computedBorder(boxInFirstRox).vertical.top);
+        bottomBorder = std::max(bottomBorder, geometry().computedBorder(boxInLastRow).vertical.bottom);
+    }
 
-        topBorder = std::max(topBorder, geometry().computedBorder(*tableBox.firstChild()).vertical.top);
-        for (auto& section : childrenOfType<ContainerBox>(tableBox)) {
-            auto horiztonalBorder = geometry().computedBorder(section).horizontal;
-            leftBorder = std::max(leftBorder, horiztonalBorder.left);
-            rightBorder = std::max(rightBorder, horiztonalBorder.right);
-        }
-        bottomBorder = std::max(bottomBorder, geometry().computedBorder(*tableBox.lastChild()).vertical.bottom);
+    topBorder = std::max(topBorder, geometry().computedBorder(*tableBox.firstChild()).vertical.top);
+    for (auto& section : childrenOfType<ContainerBox>(tableBox)) {
+        auto horiztonalBorder = geometry().computedBorder(section).horizontal;
+        leftBorder = std::max(leftBorder, horiztonalBorder.left);
+        rightBorder = std::max(rightBorder, horiztonalBorder.right);
+    }
+    bottomBorder = std::max(bottomBorder, geometry().computedBorder(*tableBox.lastChild()).vertical.bottom);
 
-        auto& rows = grid.rows().list();
-        topBorder = std::max(topBorder, geometry().computedBorder(rows.first().box()).vertical.top);
-        for (auto& row : rows) {
-            auto horiztonalBorder = geometry().computedBorder(row.box()).horizontal;
-            leftBorder = std::max(leftBorder, horiztonalBorder.left);
-            rightBorder = std::max(rightBorder, horiztonalBorder.right);
-        }
-        bottomBorder = std::max(bottomBorder, geometry().computedBorder(rows.last().box()).vertical.bottom);
+    auto& rows = grid.rows().list();
+    topBorder = std::max(topBorder, geometry().computedBorder(rows.first().box()).vertical.top);
+    for (auto& row : rows) {
+        auto horiztonalBorder = geometry().computedBorder(row.box()).horizontal;
+        leftBorder = std::max(leftBorder, horiztonalBorder.left);
+        rightBorder = std::max(rightBorder, horiztonalBorder.right);
+    }
+    bottomBorder = std::max(bottomBorder, geometry().computedBorder(rows.last().box()).vertical.bottom);
 
-        auto collapsedBorder = Edges { { leftBorder, rightBorder }, { topBorder, bottomBorder } };
-        grid.setCollapsedBorder(collapsedBorder);
+    auto collapsedBorder = Edges { { leftBorder, rightBorder }, { topBorder, bottomBorder } };
+    grid.setCollapsedBorder(collapsedBorder);
 
-        auto& displayBox = formattingState().displayBox(tableBox);
-        displayBox.setBorder(collapsedBorder / 2);
-        displayBox.setPadding(geometry().computedPadding(tableBox, horizontalConstraints.logicalWidth));
-        return;
-    }
-    BlockFormattingContext::computeBorderAndPadding(tableBox, horizontalConstraints);
+    auto& displayBox = formattingState().displayBox(tableBox);
+    displayBox.setBorder(collapsedBorder / 2);
+    displayBox.setPadding(geometry().computedPadding(tableBox, horizontalConstraints.logicalWidth));
 }
 
 void TableWrapperBlockFormattingContext::computeWidthAndMarginForTableBox(const ContainerBox& tableBox, const HorizontalConstraints& horizontalConstraints)
 {
     ASSERT(tableBox.isTableBox());
+    if (!tableBox.hasChild()) {
+        auto contentWidthAndMargin = geometry().inFlowWidthAndMargin(tableBox, horizontalConstraints, { });
+        auto& displayBox = formattingState().displayBox(tableBox);
+        displayBox.setContentBoxWidth(contentWidthAndMargin.contentWidth);
+        displayBox.setHorizontalMargin(contentWidthAndMargin.usedMargin);
+        displayBox.setHorizontalComputedMargin(contentWidthAndMargin.computedMargin);
+        return;
+    }
+
     // This is a special table "fit-content size" behavior handling. Not in the spec though.
     // Table returns its final width as min/max. Use this final width value to computed horizontal margins etc.
     auto& formattingStateForTableBox = layoutState().establishedTableFormattingState(tableBox);

Modified: trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp (262794 => 262795)


--- trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp	2020-06-09 15:45:17 UTC (rev 262794)
+++ trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp	2020-06-09 15:59:29 UTC (rev 262795)
@@ -297,6 +297,11 @@
     tableGrid->setVerticalSpacing(LayoutUnit { shouldApplyBorderSpacing ? tableStyle.verticalBorderSpacing() : 0 });
 
     auto* firstChild = tableBox.firstChild();
+    if (!firstChild) {
+        // The rare case of empty table.
+        return tableGrid;
+    }
+
     const Box* tableCaption = nullptr;
     const Box* colgroup = nullptr;
     // Table caption is an optional element; if used, it is always the first child of a <table>.

Modified: trunk/Source/WebCore/layout/tableformatting/TableGrid.h (262794 => 262795)


--- trunk/Source/WebCore/layout/tableformatting/TableGrid.h	2020-06-09 15:45:17 UTC (rev 262794)
+++ trunk/Source/WebCore/layout/tableformatting/TableGrid.h	2020-06-09 15:59:29 UTC (rev 262795)
@@ -61,6 +61,7 @@
     void setWidthConstraints(FormattingContext::IntrinsicWidthConstraints intrinsicWidthConstraints) { m_intrinsicWidthConstraints = intrinsicWidthConstraints; }
     Optional<FormattingContext::IntrinsicWidthConstraints> widthConstraints() const { return m_intrinsicWidthConstraints; }
 
+    bool isEmpty() const { return m_slotMap.isEmpty(); }
     // Column represents a vertical set of slots in the grid. A column has horizontal position and width.
     class Column {
     public:
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to