Changeset 260808 in webkit


Ignore:
Timestamp:
Apr 27, 2020 11:22:55 PM (4 years ago)
Author:
Simon Fraser
Message:

Do correct clipping of composited replaced elements with border-radius
https://bugs.webkit.org/show_bug.cgi?id=211114

Reviewed by Zalan Bujtas.
Source/WebCore:

For replaced elements with composited content (video, WebGL), RenderLayerBacking
incorrectly used the rounded inner border rect to clip the contents. This doesn't match
painted replaced elements, which clip to the inside of the padding box.

Fix by implementing RenderReplaced::roundedContentBoxRect() and calling it from compositing
code. Also add a helper to get the rounded border box rect, and call it in various places.

Test: compositing/clipping/border-radius-on-webgl.html

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::roundedBorderBoxRect const):

  • rendering/RenderBox.h:
  • rendering/RenderLayerBacking.cpp:

(WebCore::RenderLayerBacking::updateBackdropFiltersGeometry):
(WebCore::RenderLayerBacking::updateConfiguration):
(WebCore::RenderLayerBacking::updateGeometry):
(WebCore::RenderLayerBacking::updateContentsRects):
(WebCore::RenderLayerBacking::resetContentsRect):
(WebCore::RenderLayerBacking::updateChildClippingStrategy):
(WebCore::RenderLayerBacking::updateDirectlyCompositedBackgroundImage):
(WebCore::RenderLayerBacking::updateImageContents):
(WebCore::backgroundRectForBox):

  • rendering/RenderLayerBacking.h:
  • rendering/RenderReplaced.cpp:

(WebCore::RenderReplaced::roundedContentBoxRect const):

  • rendering/RenderReplaced.h:

LayoutTests:

This test clips out everything but the rounded padding area. None of the red
canvas should show.

  • compositing/clipping/border-radius-on-webgl-expected.html: Added.
  • compositing/clipping/border-radius-on-webgl.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r260807 r260808  
     12020-04-27  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Do correct clipping of composited replaced elements with border-radius
     4        https://bugs.webkit.org/show_bug.cgi?id=211114
     5
     6        Reviewed by Zalan Bujtas.
     7       
     8        This test clips out everything but the rounded padding area. None of the red
     9        canvas should show.
     10
     11        * compositing/clipping/border-radius-on-webgl-expected.html: Added.
     12        * compositing/clipping/border-radius-on-webgl.html: Added.
     13
    1142020-04-27  Devin Rousso  <drousso@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r260800 r260808  
     12020-04-27  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Do correct clipping of composited replaced elements with border-radius
     4        https://bugs.webkit.org/show_bug.cgi?id=211114
     5
     6        Reviewed by Zalan Bujtas.
     7
     8        For replaced elements with composited content (video, WebGL), RenderLayerBacking
     9        incorrectly used the rounded inner border rect to clip the contents. This doesn't match
     10        painted replaced elements, which clip to the inside of the padding box.
     11
     12        Fix by implementing RenderReplaced::roundedContentBoxRect() and calling it from compositing
     13        code. Also add a helper to get the rounded border box rect, and call it in various places.
     14
     15        Test: compositing/clipping/border-radius-on-webgl.html
     16
     17        * rendering/RenderBox.cpp:
     18        (WebCore::RenderBox::roundedBorderBoxRect const):
     19        * rendering/RenderBox.h:
     20        * rendering/RenderLayerBacking.cpp:
     21        (WebCore::RenderLayerBacking::updateBackdropFiltersGeometry):
     22        (WebCore::RenderLayerBacking::updateConfiguration):
     23        (WebCore::RenderLayerBacking::updateGeometry):
     24        (WebCore::RenderLayerBacking::updateContentsRects):
     25        (WebCore::RenderLayerBacking::resetContentsRect):
     26        (WebCore::RenderLayerBacking::updateChildClippingStrategy):
     27        (WebCore::RenderLayerBacking::updateDirectlyCompositedBackgroundImage):
     28        (WebCore::RenderLayerBacking::updateImageContents):
     29        (WebCore::backgroundRectForBox):
     30        * rendering/RenderLayerBacking.h:
     31        * rendering/RenderReplaced.cpp:
     32        (WebCore::RenderReplaced::roundedContentBoxRect const):
     33        * rendering/RenderReplaced.h:
     34
    1352020-04-27  Said Abou-Hallawa  <sabouhallawa@apple.com>
    236
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r260482 r260808  
    673673}
    674674
     675RoundedRect RenderBox::roundedBorderBoxRect() const
     676{
     677    return style().getRoundedInnerBorderFor(borderBoxRect());
     678}
     679
    675680LayoutRect RenderBox::paddingBoxRect() const
    676681{
  • trunk/Source/WebCore/rendering/RenderBox.h

    r260482 r260808  
    155155
    156156    WEBCORE_EXPORT RoundedRect::Radii borderRadii() const;
     157    RoundedRect roundedBorderBoxRect() const;
    157158
    158159    // The content area of the box (excludes padding - and intrinsic padding for table cells, etc... - and border).
  • trunk/Source/WebCore/rendering/RenderLayerBacking.cpp

    r260774 r260808  
    637637        return;
    638638
    639     auto& renderer = downcast<RenderBox>(this->renderer());
    640     LayoutRect boxRect = renderer.borderBoxRect();
    641     if (renderer.hasClip())
    642         boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
     639    auto& renderBox = downcast<RenderBox>(this->renderer());
     640    LayoutRect boxRect = renderBox.borderBoxRect();
     641    if (renderBox.hasClip())
     642        boxRect.intersect(renderBox.clipRect(LayoutPoint(), nullptr));
    643643    boxRect.move(contentOffsetInCompositingLayer());
    644644
    645645    FloatRoundedRect backdropFiltersRect;
    646     if (renderer.style().hasBorderRadius() && !renderer.hasClip())
    647         backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
     646    if (renderBox.style().hasBorderRadius() && !renderBox.hasClip())
     647        backdropFiltersRect = renderBox.roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    648648    else
    649649        backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor()));
     
    880880    if (usesCompositedScrolling) {
    881881        // If it's scrollable, it has to be a box.
    882         auto& renderBox = downcast<RenderBox>(renderer());
    883         FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(renderBox.borderBoxRect()).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
     882        FloatRoundedRect contentsClippingRect = downcast<RenderBox>(renderer()).roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    884883        needsDescendantsClippingLayer = contentsClippingRect.isRounded();
    885884    } else
     
    949948        auto* mediaElement = downcast<HTMLMediaElement>(renderer().element());
    950949        m_graphicsLayer->setContentsToPlatformLayer(mediaElement->platformLayer(), GraphicsLayer::ContentsLayerPurpose::Media);
    951         // Requires layout.
    952         resetContentsRect();
     950        updateContentsRects();
    953951    }
    954952#endif
     
    12721270
    12731271        if ((renderer().style().clipPath() || renderer().style().hasBorderRadius()) && !m_childClippingMaskLayer) {
    1274             LayoutRect boxRect({ }, renderBox.size());
    1275             FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
     1272            FloatRoundedRect contentsClippingRect = renderBox.roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    12761273            contentsClippingRect.move(LayoutSize(-clipLayer->offsetFromRenderer()));
    12771274            clipLayer->setMasksToBoundsRect(contentsClippingRect);
     
    15861583}
    15871584
     1585void RenderLayerBacking::updateContentsRects()
     1586{
     1587    m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
     1588   
     1589    if (is<RenderReplaced>(renderer())) {
     1590        FloatRoundedRect contentsClippingRect = downcast<RenderReplaced>(renderer()).roundedContentBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
     1591        contentsClippingRect.move(contentOffsetInCompositingLayer());
     1592        m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
     1593    }
     1594}
     1595
    15881596void RenderLayerBacking::resetContentsRect()
    15891597{
    1590     m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
    1591    
    1592     if (is<RenderBox>(renderer())) {
    1593         LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
    1594         boxRect.move(contentOffsetInCompositingLayer());
    1595         FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    1596         m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
    1597     }
    1598 
     1598    updateContentsRects();
    15991599    m_graphicsLayer->setContentsTileSize(IntSize());
    16001600    m_graphicsLayer->setContentsTilePhase(IntSize());
     
    20412041        if (is<RenderBox>(renderer()) && (renderer().style().clipPath() || renderer().style().hasBorderRadius())) {
    20422042            auto* clipLayer = clippingLayer();
    2043             LayoutRect boxRect(LayoutPoint(), downcast<RenderBox>(renderer()).size());
    2044             FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
     2043            FloatRoundedRect contentsClippingRect = downcast<RenderBox>(renderer()).roundedBorderBoxRect().pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    20452044            contentsClippingRect.move(LayoutSize(-clipLayer->offsetFromRenderer()));
    20462045            // Note that we have to set this rounded rect again during the geometry update (clipLayer->offsetFromRenderer() may be stale here).
     
    23242323    auto& style = renderer().style();
    23252324    if (!contentsInfo.isSimpleContainer() || !style.hasBackgroundImage()) {
    2326         m_graphicsLayer->setContentsToImage(0);
     2325        m_graphicsLayer->setContentsToImage(nullptr);
    23272326        return;
    23282327    }
     
    26882687        return;
    26892688
    2690     // This is a no-op if the layer doesn't have an inner layer for the image.
    2691     m_graphicsLayer->setContentsRect(snapRectToDevicePixels(contentsBox(), deviceScaleFactor()));
    2692 
    2693     LayoutRect boxRect(LayoutPoint(), imageRenderer.size());
    2694     boxRect.move(contentOffsetInCompositingLayer());
    2695     FloatRoundedRect contentsClippingRect = renderer().style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
    2696     m_graphicsLayer->setContentsClippingRect(contentsClippingRect);
    2697 
     2689    updateContentsRects();
    26982690    m_graphicsLayer->setContentsToImage(image);
    26992691   
     
    27612753
    27622754    ASSERT_NOT_REACHED();
    2763     return LayoutRect();
     2755    return { };
    27642756}
    27652757
  • trunk/Source/WebCore/rendering/RenderLayerBacking.h

    r260403 r260808  
    364364
    365365    void resetContentsRect();
     366    void updateContentsRects();
    366367
    367368    bool isPaintDestinationForDescendantLayers(RenderLayer::PaintedContentRequest&) const;
  • trunk/Source/WebCore/rendering/RenderReplaced.cpp

    r260367 r260808  
    427427}
    428428
     429RoundedRect RenderReplaced::roundedContentBoxRect() const
     430{
     431    return style().getRoundedInnerBorderFor(borderBoxRect(),
     432        borderTop() + paddingTop(), borderBottom() + paddingBottom(),
     433        borderLeft() + paddingLeft(), borderRight() + paddingRight());
     434}
     435
    429436void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
    430437{
  • trunk/Source/WebCore/rendering/RenderReplaced.h

    r256196 r260808  
    4242
    4343    LayoutSize intrinsicSize() const final { return m_intrinsicSize; }
     44   
     45    RoundedRect roundedContentBoxRect() const;
    4446
    4547protected:
Note: See TracChangeset for help on using the changeset viewer.