Changeset 279544 in webkit


Ignore:
Timestamp:
Jul 3, 2021, 10:27:46 AM (4 years ago)
Author:
Alan Bujtas
Message:

REGRESSION (r278377): incorrect hit-testing with clip-path()
https://bugs.webkit.org/show_bug.cgi?id=227624
<rdar://problem/79845896>

Reviewed by Simon Fraser.

Source/WebCore:

Use the correct coordinate space for clip-path based hittesting.

  1. The hittest location is in the coordinate space of the painting root (hittesting is similar to painting in this context).
  2. RenderBox::hitTestClipPath's accumulatedOffset (as the name implies) should include the offset from the (paint) hittest root.
  3. The clip-path intersecting takes coordinates relative to the containing block.

Test: fast/clip/hit-test-with-clip-path.html

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::hitTestVisualOverflow const):
(WebCore::RenderBox::hitTestClipPath const): Make the hittest root coordinates relative to the containing block.
(WebCore::RenderBox::hitTestBorderRadius const):

  • rendering/RenderBox.h: Let's not use locationInContainer name as it is way too generic and misleading.
  • rendering/RenderLayer.cpp: Compute and pass in proper accumulated offset value.

(WebCore::RenderLayer::hitTestLayer):

LayoutTests:

  • fast/clip/hit-test-with-clip-path-expected.txt: Added.
  • fast/clip/hit-test-with-clip-path.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r279543 r279544  
     12021-07-03  Alan Bujtas  <zalan@apple.com>
     2
     3        REGRESSION (r278377): incorrect hit-testing with clip-path()
     4        https://bugs.webkit.org/show_bug.cgi?id=227624
     5        <rdar://problem/79845896>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/clip/hit-test-with-clip-path-expected.txt: Added.
     10        * fast/clip/hit-test-with-clip-path.html: Added.
     11
    1122021-07-03  Alan Bujtas  <zalan@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r279543 r279544  
     12021-07-03  Alan Bujtas  <zalan@apple.com>
     2
     3        REGRESSION (r278377): incorrect hit-testing with clip-path()
     4        https://bugs.webkit.org/show_bug.cgi?id=227624
     5        <rdar://problem/79845896>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Use the correct coordinate space for clip-path based hittesting.
     10
     11        1. The hittest location is in the coordinate space of the painting root (hittesting is similar to painting in this context).
     12        2. RenderBox::hitTestClipPath's accumulatedOffset (as the name implies) should include the offset from the (paint) hittest root.
     13        3. The clip-path intersecting takes coordinates relative to the containing block.
     14
     15        Test: fast/clip/hit-test-with-clip-path.html
     16
     17        * rendering/RenderBox.cpp:
     18        (WebCore::RenderBox::hitTestVisualOverflow const):
     19        (WebCore::RenderBox::hitTestClipPath const): Make the hittest root coordinates relative to the containing block.
     20        (WebCore::RenderBox::hitTestBorderRadius const):
     21        * rendering/RenderBox.h: Let's not use locationInContainer name as it is way too generic and misleading.
     22        * rendering/RenderLayer.cpp: Compute and pass in proper accumulated offset value.
     23        (WebCore::RenderLayer::hitTestLayer):
     24
    1252021-07-03  Alan Bujtas  <zalan@apple.com>
    226
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r279218 r279544  
    13621362
    13631363// Hit Testing
    1364 bool RenderBox::hitTestVisualOverflow(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
     1364bool RenderBox::hitTestVisualOverflow(const HitTestLocation& hitTestLocation, const LayoutPoint& accumulatedOffset) const
    13651365{
    13661366    if (isRenderView())
     
    13711371    flipForWritingMode(overflowBox);
    13721372    overflowBox.moveBy(adjustedLocation);
    1373     return locationInContainer.intersects(overflowBox);
    1374 }
    1375 
    1376 bool RenderBox::hitTestClipPath(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
     1373    return hitTestLocation.intersects(overflowBox);
     1374}
     1375
     1376bool RenderBox::hitTestClipPath(const HitTestLocation& hitTestLocation, const LayoutPoint& accumulatedOffset) const
    13771377{
    13781378    if (!style().clipPath())
    13791379        return true;
    13801380
    1381     LayoutPoint adjustedLocation = accumulatedOffset + location();
    1382     const LayoutSize localOffset = toLayoutSize(adjustedLocation);
    1383 
     1381    auto offsetFromHitTestRoot = toLayoutSize(accumulatedOffset + location());
     1382    auto hitTestLocationInLocalCoordinates = hitTestLocation.point() - offsetFromHitTestRoot;
    13841383    switch (style().clipPath()->type()) {
    13851384    case ClipPathOperation::Shape: {
    13861385        auto& clipPath = downcast<ShapeClipPathOperation>(*style().clipPath());
    13871386        auto referenceBoxRect = referenceBox(clipPath.referenceBox());
    1388         if (!clipPath.pathForReferenceRect(referenceBoxRect).contains(locationInContainer.point() - localOffset, clipPath.windRule()))
     1387        if (!clipPath.pathForReferenceRect(referenceBoxRect).contains(hitTestLocationInLocalCoordinates, clipPath.windRule()))
    13891388            return false;
    13901389        break;
     
    13981397            break;
    13991398        auto& clipper = downcast<RenderSVGResourceClipper>(*element->renderer());
    1400         if (!clipper.hitTestClipContent(FloatRect(borderBoxRect()), FloatPoint(locationInContainer.point() - localOffset)))
     1399        if (!clipper.hitTestClipContent(FloatRect(borderBoxRect()), FloatPoint { hitTestLocationInLocalCoordinates }))
    14011400            return false;
    14021401        break;
     
    14091408}
    14101409
    1411 bool RenderBox::hitTestBorderRadius(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
     1410bool RenderBox::hitTestBorderRadius(const HitTestLocation& hitTestLocation, const LayoutPoint& accumulatedOffset) const
    14121411{
    14131412    if (isRenderView() || !style().hasBorderRadius())
     
    14181417    borderRect.moveBy(adjustedLocation);
    14191418    RoundedRect border = style().getRoundedBorderFor(borderRect);
    1420     return locationInContainer.intersects(border);
     1419    return hitTestLocation.intersects(border);
    14211420}
    14221421
  • trunk/Source/WebCore/rendering/RenderBox.h

    r279278 r279544  
    306306
    307307    void layout() override;
    308     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
    309     bool hitTestVisualOverflow(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
    310     bool hitTestClipPath(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
    311     bool hitTestBorderRadius(const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
     308    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint& accumulatedOffset, HitTestAction) override;
     309    bool hitTestVisualOverflow(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
     310    bool hitTestClipPath(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
     311    bool hitTestBorderRadius(const HitTestLocation&, const LayoutPoint& accumulatedOffset) const;
    312312
    313313    LayoutUnit minPreferredLogicalWidth() const override;
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r279056 r279544  
    41124112#endif
    41134113
     4114    auto offsetFromRoot = offsetFromAncestor(rootLayer);
    41144115    // FIXME: We need to correctly hit test the clip-path when we have a RenderInline too.
    4115     if (renderer().hasClipPath() && is<RenderBox>(renderer()) && !downcast<RenderBox>(renderer()).hitTestClipPath(hitTestLocation, toLayoutPoint(location() - renderBoxLocation())))
     4116    if (auto* rendererBox = this->renderBox(); rendererBox && !rendererBox->hitTestClipPath(hitTestLocation, toLayoutPoint(offsetFromRoot - toLayoutSize(renderBoxLocation()))))
    41164117        return nullptr;
    41174118
     
    41364137    // Collect the fragments. This will compute the clip rectangles for each layer fragment.
    41374138    LayerFragments layerFragments;
    4138     collectFragments(layerFragments, rootLayer, hitTestRect, IncludeCompositedPaginatedLayers, RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip,
    4139         offsetFromAncestor(rootLayer));
     4139    collectFragments(layerFragments, rootLayer, hitTestRect, IncludeCompositedPaginatedLayers, RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, offsetFromRoot);
    41404140
    41414141    LayoutPoint localPoint;
Note: See TracChangeset for help on using the changeset viewer.