Changeset 251281 in webkit


Ignore:
Timestamp:
Oct 18, 2019 9:09:41 AM (5 years ago)
Author:
Alan Bujtas
Message:

[LFC][BFC] TableFormattingContext::computedIntrinsicWidthConstraints should not expect a valid containing block's width
https://bugs.webkit.org/show_bug.cgi?id=203131
<rdar://problem/56394676>

Reviewed by Antti Koivisto.

When TableFormattingContext::computedIntrinsicWidthConstraints is called by the preferred width computation (<div style="float: left"><table>)
the containing block's width is not yet set (it gets computed based on the preferred width) so computedIntrinsicWidthConstraints should not be relying
on it. Let's move that logic out to TableFormattingContext::layoutInFlowContent() where it belongs.

  • layout/blockformatting/BlockFormattingContextGeometry.cpp:

(WebCore::Layout::BlockFormattingContext::Geometry::inFlowWidthAndMargin):

  • layout/tableformatting/TableFormattingContext.cpp:

(WebCore::Layout::TableFormattingContext::layoutInFlowContent):
(WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints):
(WebCore::Layout::TableFormattingContext::ensureTableGrid):
(WebCore::Layout::TableFormattingContext::computeAndDistributeExtraHorizontalSpace):
(WebCore::Layout::TableFormattingContext::computedTableWidth): Deleted.
(WebCore::Layout::TableFormattingContext::distributeExtraHorizontalSpace): Deleted.

  • layout/tableformatting/TableFormattingContext.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r251280 r251281  
     12019-10-18  Zalan Bujtas  <zalan@apple.com>
     2
     3        [LFC][BFC] TableFormattingContext::computedIntrinsicWidthConstraints should not expect a valid containing block's width
     4        https://bugs.webkit.org/show_bug.cgi?id=203131
     5        <rdar://problem/56394676>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        When TableFormattingContext::computedIntrinsicWidthConstraints is called by the preferred width computation (<div style="float: left"><table>)
     10        the containing block's width is not yet set (it gets computed based on the preferred width) so computedIntrinsicWidthConstraints should not be relying
     11        on it. Let's move that logic out to TableFormattingContext::layoutInFlowContent() where it belongs.
     12
     13        * layout/blockformatting/BlockFormattingContextGeometry.cpp:
     14        (WebCore::Layout::BlockFormattingContext::Geometry::inFlowWidthAndMargin):
     15        * layout/tableformatting/TableFormattingContext.cpp:
     16        (WebCore::Layout::TableFormattingContext::layoutInFlowContent):
     17        (WebCore::Layout::TableFormattingContext::computedIntrinsicWidthConstraints):
     18        (WebCore::Layout::TableFormattingContext::ensureTableGrid):
     19        (WebCore::Layout::TableFormattingContext::computeAndDistributeExtraHorizontalSpace):
     20        (WebCore::Layout::TableFormattingContext::computedTableWidth): Deleted.
     21        (WebCore::Layout::TableFormattingContext::distributeExtraHorizontalSpace): Deleted.
     22        * layout/tableformatting/TableFormattingContext.h:
     23
    1242019-10-18  Zalan Bujtas  <zalan@apple.com>
    225
  • trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp

    r251280 r251281  
    283283            // This is a special table "fit-content size" behavior handling. Not in the spec though.
    284284            // Table returns its final width as min/max. Use this final width value to computed horizontal margins etc.
    285             usedHorizontalValues.width = shrinkToFitWidth(layoutBox, usedHorizontalValues.constraints.width);
     285            usedHorizontalValues.width = usedHorizontalValues.width ? usedHorizontalValues.width : shrinkToFitWidth(layoutBox, usedHorizontalValues.constraints.width);
    286286        }
    287287        return inFlowNonReplacedWidthAndMargin(layoutBox, usedHorizontalValues);
  • trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.cpp

    r251243 r251281  
    6161{
    6262    auto& grid = formattingState().tableGrid();
     63    auto& columnsContext = grid.columnsContext();
     64
     65    computeAndDistributeExtraHorizontalSpace();
     66    // 1. Position each column.
     67    // FIXME: This should also deal with collapsing borders etc.
     68    auto horizontalSpacing = grid.horizontalSpacing();
     69    auto columnLogicalLeft = horizontalSpacing;
     70    for (auto& column : columnsContext.columns()) {
     71        column.setLogicalLeft(columnLogicalLeft);
     72        columnLogicalLeft += (column.logicalWidth() + horizontalSpacing);
     73    }
     74
     75    // 2. Layout each table cell (and compute row height as well).
     76    auto& columnList = columnsContext.columns();
    6377    auto& cellList = grid.cells();
    64     auto& columnList = grid.columnsContext().columns();
    6578    ASSERT(!cellList.isEmpty());
    66     // Layout and position each table cell (and compute row height as well).
    6779    for (auto& cell : cellList) {
    6880        auto& cellLayoutBox = cell->tableCellBox;
     
    7991    }
    8092
    81     // Finalize size and position.
     93    // 3. Finalize size and position.
    8294    positionTableCells();
    8395    setComputedGeometryForSections();
     
    153165    // 1. Ensure each cell slot is occupied by at least one cell.
    154166    ensureTableGrid();
    155     // 2. Compute the minimum width of each column.
     167    // 2. Compute the minimum/maximum width of each column.
    156168    computePreferredWidthForColumns();
    157     // 3. Compute the width of the table.
    158     auto width = computedTableWidth();
    159     // This is the actual computed table width that we want to present as min/max width.
    160     formattingState().setIntrinsicWidthConstraints({ width, width });
    161     return { width, width };
     169    // 3. Compute the minimum/maximum width of the table box.
     170    auto& grid = formattingState().tableGrid();
     171    auto tableWidthConstraints = grid.widthConstraints();
     172    tableWidthConstraints.expand(grid.totalHorizontalSpacing());
     173    return tableWidthConstraints;
    162174}
    163175
    164176void TableFormattingContext::ensureTableGrid()
    165177{
    166     auto& tableWrapperBox = root();
     178    auto& tableBox = root();
    167179    auto& tableGrid = formattingState().tableGrid();
    168     tableGrid.setHorizontalSpacing(LayoutUnit { tableWrapperBox.style().horizontalBorderSpacing() });
    169     tableGrid.setVerticalSpacing(LayoutUnit { tableWrapperBox.style().verticalBorderSpacing() });
    170 
    171     auto* firstChild = tableWrapperBox.firstChild();
     180    tableGrid.setHorizontalSpacing(LayoutUnit { tableBox.style().horizontalBorderSpacing() });
     181    tableGrid.setVerticalSpacing(LayoutUnit { tableBox.style().verticalBorderSpacing() });
     182
     183    auto* firstChild = tableBox.firstChild();
    172184    const Box* tableCaption = nullptr;
    173185    const Box* colgroup = nullptr;
     
    261273}
    262274
    263 LayoutUnit TableFormattingContext::computedTableWidth()
    264 {
     275void TableFormattingContext::computeAndDistributeExtraHorizontalSpace()
     276{
     277    auto& grid = formattingState().tableGrid();
     278    auto tableWidthConstraints = grid.widthConstraints();
     279    auto tableMinimumContentWidth = tableWidthConstraints.minimum - grid.totalHorizontalSpacing();
     280
    265281    // Column and caption widths influence the final table width as follows:
    266282    // 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
     
    270286    // CAPMIN, and MIN. However, if either CAPMIN or the maximum width required by the columns plus cell spacing or borders (MAX) is
    271287    // less than that of the containing block, use max(MAX, CAPMIN).
    272 
    273     // FIXME: This kind of code usually lives in *FormattingContextGeometry class.
    274     auto& tableWrapperBox = root();
    275     auto& style = tableWrapperBox.style();
    276     auto& containingBlock = *tableWrapperBox.containingBlock();
    277     auto containingBlockWidth = geometryForBox(containingBlock, EscapeType::TableFormattingContextAccessParentTableWrapperBlockFormattingContext).contentBoxWidth();
    278 
    279     auto& grid = formattingState().tableGrid();
    280     auto& columnsContext = grid.columnsContext();
    281     auto tableWidthConstraints = grid.widthConstraints();
    282     auto totalHorizontalSpacing = grid.totalHorizontalSpacing();
    283 
    284     auto width = geometry().computedValueIfNotAuto(style.width(), containingBlockWidth);
    285     LayoutUnit usedWidth;
     288    auto distributeExtraHorizontalSpace = [&](auto extraHorizontalSpace) {
     289        auto& columns = grid.columnsContext().columns();
     290        ASSERT(!columns.isEmpty());
     291
     292        auto adjustabledHorizontalSpace = tableMinimumContentWidth;
     293        auto numberOfColumns = columns.size();
     294        // Fixed width columns don't participate in available space distribution.
     295        for (auto& column : columns) {
     296            if (!column.hasFixedWidth())
     297                continue;
     298            auto columnFixedWidth = *column.columnBox()->columnWidth();
     299            column.setLogicalWidth(columnFixedWidth);
     300
     301            --numberOfColumns;
     302            adjustabledHorizontalSpace -= columnFixedWidth;
     303        }
     304        if (!numberOfColumns || !adjustabledHorizontalSpace)
     305            return;
     306        // FIXME: Right now just distribute the extra space equaly among the columns using the minimum width.
     307        ASSERT(adjustabledHorizontalSpace > 0);
     308        for (auto& column : columns) {
     309            if (column.hasFixedWidth())
     310                continue;
     311            auto columnExtraSpace = extraHorizontalSpace / adjustabledHorizontalSpace * column.widthConstraints().minimum;
     312            column.setLogicalWidth(column.widthConstraints().minimum + columnExtraSpace);
     313        }
     314    };
     315
     316    auto containingBlockWidth = geometryForBox(*root().containingBlock(), EscapeType::TableFormattingContextAccessParentTableWrapperBlockFormattingContext).contentBoxWidth();
     317    auto width = geometry().computedValueIfNotAuto(root().style().width(), containingBlockWidth);
    286318    if (width) {
    287         if (*width > tableWidthConstraints.minimum) {
    288             distributeExtraHorizontalSpace(*width - totalHorizontalSpacing, tableWidthConstraints.minimum - totalHorizontalSpacing);
    289             usedWidth = *width;
    290         } else {
    291             usedWidth = tableWidthConstraints.minimum;
     319        if (*width > tableMinimumContentWidth)
     320            distributeExtraHorizontalSpace(*width - tableMinimumContentWidth);
     321        else
    292322            useAsContentLogicalWidth(WidthConstraintsType::Minimum);
    293         }
    294323    } else {
    295         if (tableWidthConstraints.minimum > containingBlockWidth) {
    296             usedWidth = tableWidthConstraints.minimum;
     324        if (tableMinimumContentWidth > containingBlockWidth)
    297325            useAsContentLogicalWidth(WidthConstraintsType::Minimum);
    298         } else if (tableWidthConstraints.maximum < containingBlockWidth) {
    299             usedWidth = tableWidthConstraints.maximum;
     326        else if (tableWidthConstraints.maximum < containingBlockWidth)
    300327            useAsContentLogicalWidth(WidthConstraintsType::Maximum);
    301         } else {
    302             usedWidth = containingBlockWidth;
    303             distributeExtraHorizontalSpace(usedWidth - totalHorizontalSpacing, tableWidthConstraints.minimum - totalHorizontalSpacing);
    304         }
    305     }
    306     // FIXME: This should also deal with collapsing borders etc.
    307     auto horizontalSpacing = grid.horizontalSpacing();
    308     auto columnLogicalLeft = horizontalSpacing;
    309     for (auto& column : columnsContext.columns()) {
    310         column.setLogicalLeft(columnLogicalLeft);
    311         columnLogicalLeft += (column.logicalWidth() + horizontalSpacing);
    312     }
    313     return usedWidth;
    314 }
    315 
    316 void TableFormattingContext::distributeExtraHorizontalSpace(LayoutUnit availableContentWidth, LayoutUnit tableMinimumContentWidth)
    317 {
    318     ASSERT(availableContentWidth >= tableMinimumContentWidth);
    319     auto& grid = formattingState().tableGrid();
    320     auto& columns = grid.columnsContext().columns();
    321     ASSERT(!columns.isEmpty());
    322 
    323     auto extraHorizontalSpace = availableContentWidth - tableMinimumContentWidth;
    324     auto adjustabledHorizontalSpace = tableMinimumContentWidth;
    325     auto numberOfColumns = columns.size();
    326     // Fixed width columns don't participate in available space distribution.
    327     for (auto& column : columns) {
    328         if (!column.hasFixedWidth())
    329             continue;
    330         auto columnFixedWidth = *column.columnBox()->columnWidth();
    331         column.setLogicalWidth(columnFixedWidth);
    332 
    333         --numberOfColumns;
    334         adjustabledHorizontalSpace -= columnFixedWidth;
    335     }
    336     if (!numberOfColumns || !adjustabledHorizontalSpace)
    337         return;
    338     // FIXME: Right now just distribute the extra space equaly among the columns using the minimum width.
    339     ASSERT(adjustabledHorizontalSpace > 0);
    340     for (auto& column : columns) {
    341         if (column.hasFixedWidth())
    342             continue;
    343         auto columnExtraSpace = extraHorizontalSpace / adjustabledHorizontalSpace * column.widthConstraints().minimum;
    344         column.setLogicalWidth(column.widthConstraints().minimum + columnExtraSpace);
     328        else
     329            distributeExtraHorizontalSpace(containingBlockWidth - tableMinimumContentWidth);
    345330    }
    346331}
  • trunk/Source/WebCore/layout/tableformatting/TableFormattingContext.h

    r251186 r251281  
    5959
    6060    IntrinsicWidthConstraints computedIntrinsicWidthConstraints() override;
    61     LayoutUnit computedTableWidth();
    6261    void layoutTableCellBox(const Box& cellLayoutBox, const TableGrid::Column&);
    6362    void positionTableCells();
     
    6766    void ensureTableGrid();
    6867    void computePreferredWidthForColumns();
    69     void distributeExtraHorizontalSpace(LayoutUnit availableContentWidth, LayoutUnit tableMinimumContentWidth);
     68    void computeAndDistributeExtraHorizontalSpace();
    7069    enum class WidthConstraintsType { Minimum, Maximum };
    7170    void useAsContentLogicalWidth(WidthConstraintsType);
Note: See TracChangeset for help on using the changeset viewer.