COMMIT_MESSAGE

 1Remove redundant logical right computation for grid items in RenderBlock::computeOverflow
 2https://bugs.webkit.org/show_bug.cgi?id=241689
 3
 4Reviewed by NOBODY (OOPS!).
 5
 6If the grid content produces layout overflow, we should not need to re-compute it again by looping through the grid items.
 7
 81. Decouple "include padding end" and "include child's margin end" logic
 92. Decouple "include padding after" and "include padding end" logic.
 103. Restore RenderFlexibleBox and RenderGrid computeOverflow calls to pre-r282463 (when clientLogicalRightAndBottomAfterRepositioning was introduced)
 11
 12* LayoutTests/fast/overflow/grid-horizontal-overflow-with-padding-end-expected.html: Added.
 13* LayoutTests/fast/overflow/grid-horizontal-overflow-with-padding-end.html: Added.
 14* Source/WebCore/rendering/RenderBlock.cpp:
 15(WebCore::RenderBlock::computeOverflow):
 16(WebCore::RenderBlock::layoutOverflowLogicalBottom):
 17(WebCore::RenderBlock::clientLogicalRightAndBottomAfterRepositioning const): Deleted.
 18* Source/WebCore/rendering/RenderBlock.h:
 19* Source/WebCore/rendering/RenderBox.cpp:
 20(WebCore::RenderBox::layoutOverflowRectForPropagation const):
 21* Source/WebCore/rendering/RenderFlexibleBox.cpp:
 22(WebCore::RenderFlexibleBox::layoutBlock):
 23* Source/WebCore/rendering/RenderGrid.cpp:
 24(WebCore::RenderGrid::layoutBlock):

Source/WebCore/rendering/RenderBlock.cpp

@@void RenderBlock::addOverflowFromChildren()
681681 }
682682}
683683
684 LayoutSize RenderBlock::clientLogicalRightAndBottomAfterRepositioning() const
685 {
686  LayoutUnit maxChildLogicalRight;
687  LayoutUnit maxChildLogicalBottom;
688  for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
689  if (child->isOutOfFlowPositioned())
690  continue;
691  LayoutUnit childLogicalRight = logicalLeftForChild(*child) + logicalWidthForChild(*child) + marginEndForChild(*child);
692  LayoutUnit childLogicalBottom = logicalTopForChild(*child) + logicalHeightForChild(*child) + marginAfterForChild(*child);
693  maxChildLogicalRight = std::max(maxChildLogicalRight, childLogicalRight);
694  maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
695 
696  }
697  return LayoutSize(maxChildLogicalRight + paddingRight(), std::max(clientLogicalBottom(), maxChildLogicalBottom + paddingAfter()));
698 }
699 
700 
701684// Overflow is always relative to the border-box of the element in question.
702685// Therefore, if the element has a vertical scrollbar placed on the left, an overflow rect at x=2px would conceptually intersect the scrollbar.
703686void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool)

@@void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool)
708691 addOverflowFromPositionedObjects();
709692
710693 if (hasNonVisibleOverflow()) {
711  // Set the axis we don't care about to be 1, since we want this overflow to always be considered reachable.
712  LayoutUnit rectWidth = 1_lu;
713  // For grid, width of the overflow rect should be the width of the grid area of the items rather than the container block.
714  // As per https://github.com/w3c/csswg-drafts/issues/3653, child's margins along with padding should contribute to the
715  // scrollable overflow area.
716  if (this->isRenderGrid())
717  rectWidth = clientLogicalRightAndBottomAfterRepositioning().width();
718 
719  // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
720  // and bottom padding.
721  LayoutRect clientRect(flippedClientBoxRect());
722  LayoutRect rectToApply;
723  if (isHorizontalWritingMode())
724  rectToApply = LayoutRect(clientRect.x(), clientRect.y(), rectWidth, std::max(0_lu, oldClientAfterEdge - clientRect.y()));
725  else
726  rectToApply = LayoutRect(clientRect.x(), clientRect.y(), std::max(0_lu, oldClientAfterEdge - clientRect.x()), rectWidth);
727  addLayoutOverflow(rectToApply);
 694 auto includePaddingEnd = [&] {
 695 // As per https://github.com/w3c/csswg-drafts/issues/3653 padding should contribute to the scrollable overflow area.
 696 if (!paddingEnd())
 697 return;
 698 // FIXME: Expand it to non-grid cases when applicable.
 699 if (!is<RenderGrid>(*this))
 700 return;
 701
 702 auto layoutOverflowRect = this->layoutOverflowRect();
 703 auto layoutOverflowLogicalWidthIncludingPaddingEnd = [&] {
 704 if (hasHorizontalLayoutOverflow())
 705 return (isHorizontalWritingMode() ? layoutOverflowRect.width() : layoutOverflowRect.height()) + paddingEnd();
 706
 707 // FIXME: This is not sufficient for BFC layout (missing non-formatting-context root descendants).
 708 auto contentLogicalRight = LayoutUnit { };
 709 for (auto& child : childrenOfType<RenderBox>(*this)) {
 710 if (child.isOutOfFlowPositioned())
 711 continue;
 712 auto childLogicalRight = logicalLeftForChild(child) + logicalWidthForChild(child) + marginEndForChild(child);
 713 contentLogicalRight = std::max(contentLogicalRight, childLogicalRight);
 714 }
 715 auto logicalRightWithPaddingEnd = contentLogicalRight + paddingEnd();
 716 // Use padding box as the reference box.
 717 return logicalRightWithPaddingEnd - (isHorizontalWritingMode() ? borderLeft() : borderTop());
 718 };
 719
 720 if (isHorizontalWritingMode())
 721 layoutOverflowRect.setWidth(layoutOverflowLogicalWidthIncludingPaddingEnd());
 722 else
 723 layoutOverflowRect.setHeight(layoutOverflowLogicalWidthIncludingPaddingEnd());
 724 addLayoutOverflow(layoutOverflowRect);
 725 };
 726 includePaddingEnd();
 727
 728 auto includePaddingAfter = [&] {
 729 // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins and bottom padding.
 730 auto clientRect = flippedClientBoxRect();
 731 auto rectToApply = clientRect;
 732 // Set the axis we don't care about to be 1, since we want this overflow to always be considered reachable.
 733 if (isHorizontalWritingMode()) {
 734 rectToApply.setWidth(1);
 735 rectToApply.setHeight(std::max(0_lu, oldClientAfterEdge - clientRect.y()));
 736 } else {
 737 rectToApply.setWidth(std::max(0_lu, oldClientAfterEdge - clientRect.x()));
 738 rectToApply.setHeight(1);
 739 }
 740 addLayoutOverflow(rectToApply);
 741 };
 742 includePaddingAfter();
728743 if (hasRenderOverflow())
729744 m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
730745 }

@@String RenderBlock::updateSecurityDiscCharacters(const RenderStyle& style, Strin
35103525 return makeStringByReplacingAll(string, discCharacterToReplace, textSecurityDiscPUACodePoint);
35113526#endif
35123527}
3513 
 3528
 3529LayoutUnit RenderBlock::layoutOverflowLogicalBottom(const RenderBlock& renderer)
 3530{
 3531 ASSERT(is<RenderGrid>(renderer) || is<RenderFlexibleBox>(renderer));
 3532 auto maxChildLogicalBottom = LayoutUnit { };
 3533 for (auto& child : childrenOfType<RenderBox>(renderer)) {
 3534 if (child.isOutOfFlowPositioned())
 3535 continue;
 3536 auto childLogicalBottom = renderer.logicalTopForChild(child) + renderer.logicalHeightForChild(child) + renderer.marginAfterForChild(child);
 3537 maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
 3538 }
 3539 return std::max(renderer.clientLogicalBottom(), maxChildLogicalBottom + renderer.paddingAfter());
 3540}
 3541
35143542} // namespace WebCore

Source/WebCore/rendering/RenderBlock.h

@@public:
231231 LayoutUnit adjustIntrinsicLogicalHeightForBoxSizing(LayoutUnit height) const override;
232232 void paintExcludedChildrenInBorder(PaintInfo&, const LayoutPoint&);
233233
234  LayoutSize clientLogicalRightAndBottomAfterRepositioning() const;
235234 // Accessors for logical width/height and margins in the containing block's block-flow direction.
236235 enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
237236 LayoutUnit logicalWidthForChild(const RenderBox& child) const { return isHorizontalWritingMode() ? child.width() : child.height(); }

@@protected:
378377
379378 bool childBoxIsUnsplittableForFragmentation(const RenderBox& child) const;
380379
 380 static LayoutUnit layoutOverflowLogicalBottom(const RenderBlock&);
 381
381382public:
382383 virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
383384 void clearLayoutOverflow();

Source/WebCore/rendering/RenderBox.cpp

@@LayoutRect RenderBox::logicalLayoutOverflowRectForPropagation(const RenderStyle*
52335233LayoutRect RenderBox::layoutOverflowRectForPropagation(const RenderStyle* parentStyle) const
52345234{
52355235 // Only propagate interior layout overflow if we don't completely clip it.
5236  LayoutRect rect = borderBoxRect();
 5236 auto rect = borderBoxRect();
 5237 if (isGridItem()) {
 5238 // As per https://github.com/w3c/csswg-drafts/issues/3653, child's margins should contribute to the scrollable overflow area.
 5239 // FIXME: Expand it to non-grid cases when applicable.
 5240 rect.setWidth(rect.width() + std::max(0_lu, marginEnd()));
 5241 }
52375242 if (!shouldApplyLayoutContainment()) {
52385243 if (style().overflowX() == Overflow::Clip && style().overflowY() == Overflow::Visible) {
52395244 LayoutRect clippedOverflowRect = layoutOverflowRect();

Source/WebCore/rendering/RenderFlexibleBox.cpp

@@void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
407407
408408 repaintChildrenDuringLayoutIfMoved(oldChildRects);
409409 // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
410  computeOverflow(clientLogicalRightAndBottomAfterRepositioning().height());
 410 computeOverflow(layoutOverflowLogicalBottom(*this));
411411 }
412412 updateLayerTransform();
413413

Source/WebCore/rendering/RenderGrid.cpp

@@void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
369369 layoutPositionedObjects(relayoutChildren || isDocumentElementRenderer());
370370 m_trackSizingAlgorithm.reset();
371371
372  computeOverflow(clientLogicalRightAndBottomAfterRepositioning().height());
 372 computeOverflow(layoutOverflowLogicalBottom(*this));
373373 }
374374
375375 updateLayerTransform();

LayoutTests/fast/overflow/grid-horizontal-overflow-with-padding-end-expected.html

 1<style>
 2.container {
 3 box-sizing: border-box;
 4 width: 320px;
 5 height: 188px;
 6 overflow-x: scroll;
 7 border: 50px solid blue;
 8 background-color: cyan;
 9}
 10
 11.container > div {
 12 margin-left: 10px;
 13 width: 20px;
 14 height: 20px;
 15 background-color: green;
 16}
 17
 18#overflow {
 19 background-color: transparent;
 20 width: 211px;
 21 height: 10px;
 22}
 23</style>
 24<div class=container><div></div></div>
 25<div class=container><div style="width: 21px"></div><div id=overflow></div></div>
 26<script>
 27let scrollers = document.body.getElementsByClassName("container");
 28for (let scroller of scrollers)
 29 scroller.scrollTo(100, 0);
 30</script>

LayoutTests/fast/overflow/grid-horizontal-overflow-with-padding-end.html

 1<style>
 2.container {
 3 box-sizing: border-box;
 4 width: 320px;
 5 height: 188px;
 6 overflow-x: scroll;
 7 padding-left: 10px;
 8 padding-right: 190px;
 9 border: 50px solid blue;
 10 background-color: cyan;
 11 display: grid;
 12}
 13
 14.container > div {
 15 width: 20px;
 16 height: 20px;
 17 background-color: green;
 18}
 19</style>
 20<div class=container><div></div></div>
 21<div class=container><div style="width: 21px"></div></div>
 22<script>
 23let scrollers = document.body.getElementsByClassName("container");
 24for (let scroller of scrollers)
 25 scroller.scrollTo(100, 0);
 26</script>