Changeset 282463 in webkit


Ignore:
Timestamp:
Sep 15, 2021 11:06:47 AM (10 months ago)
Author:
Ziran Sun
Message:

[css-grid] Overflow should be computed with the actual logical bottom
https://bugs.webkit.org/show_bug.cgi?id=226981

Reviewed by Javier Fernandez.

When computing the overflow area in the grid container, we need to obtain the result of ClientLogicalBottom
function. This value should be retrieved after computing the actual logical height rather than before.

For grid, width/height of the overflow rect should be the width/height of the grid area of the items rather than
the width/height of the container block. As per https://github.com/w3c/csswg-drafts/issues/3653, child's margins
along with padding should contribute to the scrollable overflow area.

Test: imported/w3c/web-platform-tests/css/css-grid/alignment/grid-content-alignment-overflow-002.html

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::clientLogicalBottomAfterRepositioning):
(WebCore::RenderBlock::computeOverflow):

  • rendering/RenderBlock.h:

(WebCore::RenderBlock::logicalLeftForChild const):

  • rendering/RenderFlexibleBox.cpp:

(WebCore::RenderFlexibleBox::clientLogicalBottomAfterRepositioning): Deleted.

  • rendering/RenderFlexibleBox.h:
  • rendering/RenderGrid.cpp:

(WebCore::RenderGrid::layoutBlock):

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-grid/alignment/grid-content-alignment-overflow-002-expected.txt

    r279269 r282463  
    4242
    4343
    44 FAIL .grid 1 assert_equals:
    45 <div class="container" style="margin-bottom: 50px; margin-right: 25px;">
    46   <div class="grid overflowWidth contentCenter" data-expected-width="60" data-expected-height="300" data-expected-scroll-width="110" data-expected-scroll-height="300">
    47     <div class="firstRowFirstColumn" data-offset-x="-20" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
    48     <div class="secondRowFirstColumn" data-offset-x="-20" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
    49     <div class="firstRowSecondColumn" data-offset-x="30" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
    50     <div class="secondRowSecondColumn" data-offset-x="30" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
    51   </div>
    52 </div>
    53 scrollWidth expected 110 but got 80
    54 FAIL .grid 2 assert_equals:
    55 <div class="container" style="margin-bottom: 50px; margin-right: 25px;">
    56   <div class="grid overflowHeight contentCenterUnsafe" data-expected-width="200" data-expected-height="150" data-expected-scroll-width="200" data-expected-scroll-height="205">
    57     <div class="firstRowFirstColumn" data-offset-x="50" data-offset-y="-25" data-expected-width="50" data-expected-height="100"></div>
    58     <div class="secondRowFirstColumn" data-offset-x="50" data-offset-y="75" data-expected-width="50" data-expected-height="100"></div>
    59     <div class="firstRowSecondColumn" data-offset-x="100" data-offset-y="-25" data-expected-width="50" data-expected-height="100"></div>
    60     <div class="secondRowSecondColumn" data-offset-x="100" data-offset-y="75" data-expected-width="50" data-expected-height="100"></div>
    61   </div>
    62 </div>
    63 scrollHeight expected 205 but got 260
    64 FAIL .grid 3 assert_equals:
    65 <div class="container" style="margin-bottom: 50px; margin-right: 25px;">
    66   <div class="grid overflowWidth contentCenterSafe" data-expected-width="60" data-expected-height="300" data-expected-scroll-width="160" data-expected-scroll-height="300">
    67     <div class="firstRowFirstColumn" data-offset-x="30" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
    68     <div class="secondRowFirstColumn" data-offset-x="30" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
    69     <div class="firstRowSecondColumn" data-offset-x="80" data-offset-y="50" data-expected-width="50" data-expected-height="100"></div>
    70     <div class="secondRowSecondColumn" data-offset-x="80" data-offset-y="150" data-expected-width="50" data-expected-height="100"></div>
    71   </div>
    72 </div>
    73 scrollWidth expected 160 but got 130
     44PASS .grid 1
     45PASS .grid 2
     46PASS .grid 3
    7447PASS .grid 4
    7548PASS .grid 5
    76 FAIL .grid 6 assert_equals:
    77 <div class="container" style="margin-bottom: 50px; margin-right: 25px;">
    78   <div class="grid overflowHeight contentEndUnsafe" data-expected-width="200" data-expected-height="150" data-expected-scroll-width="200" data-expected-scroll-height="150">
    79     <div class="firstRowFirstColumn" data-offset-x="70" data-offset-y="-80" data-expected-width="50" data-expected-height="100"></div>
    80     <div class="secondRowFirstColumn" data-offset-x="70" data-offset-y="20" data-expected-width="50" data-expected-height="100"></div>
    81     <div class="firstRowSecondColumn" data-offset-x="120" data-offset-y="-80" data-expected-width="50" data-expected-height="100"></div>
    82     <div class="secondRowSecondColumn" data-offset-x="120" data-offset-y="20" data-expected-width="50" data-expected-height="100"></div>
    83   </div>
    84 </div>
    85 scrollHeight expected 150 but got 260
    86 FAIL .grid 7 assert_equals:
    87 <div class="container" style="margin-bottom: 50px; margin-right: 25px;">
    88   <div class="grid overflowWidth contentEndSafe" data-expected-width="60" data-expected-height="300" data-expected-scroll-width="160" data-expected-scroll-height="300">
    89     <div class="firstRowFirstColumn" data-offset-x="30" data-offset-y="70" data-expected-width="50" data-expected-height="100"></div>
    90     <div class="secondRowFirstColumn" data-offset-x="30" data-offset-y="170" data-expected-width="50" data-expected-height="100"></div>
    91     <div class="firstRowSecondColumn" data-offset-x="80" data-offset-y="70" data-expected-width="50" data-expected-height="100"></div>
    92     <div class="secondRowSecondColumn" data-offset-x="80" data-offset-y="170" data-expected-width="50" data-expected-height="100"></div>
    93   </div>
    94 </div>
    95 scrollWidth expected 160 but got 130
     49PASS .grid 6
     50PASS .grid 7
    9651PASS .grid 8
    9752PASS .grid 9
    9853PASS .grid 10
    99 FAIL .grid 11 assert_equals:
    100 <div class="container" style="margin-bottom: 100px; margin-right: 25px;">
    101   <div class="grid contentSizedTracks fit-content maxSize contentEndUnsafe" data-expected-width="100" data-expected-height="100" data-expected-scroll-width="100" data-expected-scroll-height="100">
    102     <div class="item1 firstRowSecondColumn" data-offset-x="20" data-offset-y="-180" data-expected-width="50" data-expected-height="150"></div>
    103     <div class="item2 secondRowFirstColumn" data-offset-x="-130" data-offset-y="-30" data-expected-width="150" data-expected-height="100"></div>
    104   </div>
    105 </div>
    106 scrollHeight expected 100 but got 310
    107 FAIL .grid 12 assert_equals:
    108 <div class="container" style="margin-bottom: 100px; margin-right: 75px;">
    109   <div class="grid contentSizedTracks fit-content maxSize contentCenterUnsafe" data-expected-width="100" data-expected-height="100" data-expected-scroll-width="180" data-expected-scroll-height="205">
    110     <div class="item1 firstRowSecondColumn" data-offset-x="100" data-offset-y="-75" data-expected-width="50" data-expected-height="150"></div>
    111     <div class="item2 secondRowFirstColumn" data-offset-x="-50" data-offset-y="75" data-expected-width="150" data-expected-height="100"></div>
    112   </div>
    113 </div>
    114 scrollWidth expected 180 but got 150
     54PASS .grid 11
     55PASS .grid 12
    11556PASS .grid 13
    11657PASS .grid 14
  • trunk/Source/WebCore/ChangeLog

    r282459 r282463  
     12021-09-15  Ziran Sun  <zsun@igalia.com>
     2
     3        [css-grid] Overflow should be computed with the actual logical bottom
     4        https://bugs.webkit.org/show_bug.cgi?id=226981
     5
     6        Reviewed by Javier Fernandez.
     7
     8        When computing the overflow area in the grid container, we need to obtain the result of ClientLogicalBottom
     9        function. This value should be retrieved after computing the actual logical height rather than before.
     10
     11        For grid, width/height of the overflow rect should be the width/height of the grid area of the items rather than
     12        the width/height of the container block. As per https://github.com/w3c/csswg-drafts/issues/3653, child's margins
     13        along with padding should contribute to the scrollable overflow area.
     14
     15        Test: imported/w3c/web-platform-tests/css/css-grid/alignment/grid-content-alignment-overflow-002.html
     16        * rendering/RenderBlock.cpp:
     17        (WebCore::RenderBlock::clientLogicalBottomAfterRepositioning):
     18        (WebCore::RenderBlock::computeOverflow):
     19        * rendering/RenderBlock.h:
     20        (WebCore::RenderBlock::logicalLeftForChild const):
     21        * rendering/RenderFlexibleBox.cpp:
     22        (WebCore::RenderFlexibleBox::clientLogicalBottomAfterRepositioning): Deleted.
     23        * rendering/RenderFlexibleBox.h:
     24        * rendering/RenderGrid.cpp:
     25        (WebCore::RenderGrid::layoutBlock):
     26
    1272021-09-15  Youenn Fablet  <youenn@apple.com>
    228
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r282085 r282463  
    661661}
    662662
     663LayoutSize RenderBlock::clientLogicalRightAndBottomAfterRepositioning() const
     664{
     665    LayoutUnit maxChildLogicalRight;
     666    LayoutUnit maxChildLogicalBottom;
     667    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
     668        if (child->isOutOfFlowPositioned())
     669            continue;
     670        LayoutUnit childLogicalRight = logicalLeftForChild(*child) + logicalWidthForChild(*child) + marginEndForChild(*child);
     671        LayoutUnit childLogicalBottom = logicalTopForChild(*child) + logicalHeightForChild(*child) + marginAfterForChild(*child);
     672        maxChildLogicalRight = std::max(maxChildLogicalRight, childLogicalRight);
     673        maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
     674
     675    }
     676    return LayoutSize(maxChildLogicalRight + paddingRight(), std::max(clientLogicalBottom(), maxChildLogicalBottom + paddingAfter()));
     677}
     678
     679
    663680// Overflow is always relative to the border-box of the element in question.
    664681// Therefore, if the element has a vertical scrollbar placed on the left, an overflow rect at x=2px would conceptually intersect the scrollbar.
     
    671688
    672689    if (hasNonVisibleOverflow()) {
     690        // Set the axis we don't care about to be 1, since we want this overflow to always be considered reachable.
     691        LayoutUnit rectWidth = 1_lu;
     692        // For grid, width of the overflow rect should be the width of the grid area of the items rather than the container block.
     693        // As per https://github.com/w3c/csswg-drafts/issues/3653, child's margins along with padding should contribute to the
     694        // scrollable overflow area.
     695        if (this->isRenderGrid())
     696            rectWidth = clientLogicalRightAndBottomAfterRepositioning().width();
     697
    673698        // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
    674         // and bottom padding.  Set the axis we don't care about to be 1, since we want this overflow to always
    675         // be considered reachable.
     699        // and bottom padding.
    676700        LayoutRect clientRect(flippedClientBoxRect());
    677701        LayoutRect rectToApply;
    678702        if (isHorizontalWritingMode())
    679             rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1_lu, std::max(0_lu, oldClientAfterEdge - clientRect.y()));
     703            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), rectWidth, std::max(0_lu, oldClientAfterEdge - clientRect.y()));
    680704        else
    681             rectToApply = LayoutRect(clientRect.x(), clientRect.y(), std::max(0_lu, oldClientAfterEdge - clientRect.x()), 1_lu);
     705            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), std::max(0_lu, oldClientAfterEdge - clientRect.x()), rectWidth);
    682706        addLayoutOverflow(rectToApply);
    683707        if (hasRenderOverflow())
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r279268 r282463  
    233233    void paintExcludedChildrenInBorder(PaintInfo&, const LayoutPoint&);
    234234   
     235    LayoutSize clientLogicalRightAndBottomAfterRepositioning() const;
    235236    // Accessors for logical width/height and margins in the containing block's block-flow direction.
    236237    enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
     
    239240    LayoutSize logicalSizeForChild(const RenderBox& child) const { return isHorizontalWritingMode() ? child.size() : child.size().transposedSize(); }
    240241    LayoutUnit logicalTopForChild(const RenderBox& child) const { return isHorizontalWritingMode() ? child.y() : child.x(); }
     242    LayoutUnit logicalLeftForChild(const RenderBox& child) const { return isHorizontalWritingMode() ? child.x() : child.y(); }
    241243    void setLogicalLeftForChild(RenderBox& child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
    242244    void setLogicalTopForChild(RenderBox& child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp

    r282267 r282463  
    391391        repaintChildrenDuringLayoutIfMoved(oldChildRects);
    392392        // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
    393         computeOverflow(clientLogicalBottomAfterRepositioning());
     393        computeOverflow(clientLogicalRightAndBottomAfterRepositioning().height());
    394394    }
    395395    updateLayerTransform();
     
    461461    // flipped.
    462462    flipForRightToLeftColumn(lineContexts);
    463 }
    464 
    465 LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
    466 {
    467     LayoutUnit maxChildLogicalBottom;
    468     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    469         if (child->isOutOfFlowPositioned())
    470             continue;
    471         LayoutUnit childLogicalBottom = logicalTopForChild(*child) + logicalHeightForChild(*child) + marginAfterForChild(*child);
    472         maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
    473     }
    474     return std::max(clientLogicalBottom(), maxChildLogicalBottom + paddingAfter());
    475463}
    476464
  • trunk/Source/WebCore/rendering/RenderFlexibleBox.h

    r281840 r282463  
    171171    bool updateAutoMarginsInCrossAxis(RenderBox& child, LayoutUnit availableAlignmentSpace);
    172172    void repositionLogicalHeightDependentFlexItems(Vector<LineContext>&, LayoutUnit gapBetweenLines);
    173     LayoutUnit clientLogicalBottomAfterRepositioning();
    174173   
    175174    LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, const RenderBox& child);
  • trunk/Source/WebCore/rendering/RenderGrid.cpp

    r282340 r282463  
    264264        setLogicalHeight(trackBasedLogicalHeight);
    265265
    266         LayoutUnit oldClientAfterEdge = clientLogicalBottom();
    267266        updateLogicalHeight();
    268267
     
    301300        layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
    302301
    303         computeOverflow(oldClientAfterEdge);
     302        computeOverflow(clientLogicalRightAndBottomAfterRepositioning().height());
    304303    }
    305304
Note: See TracChangeset for help on using the changeset viewer.