Changeset 243674 in webkit


Ignore:
Timestamp:
Mar 30, 2019 1:28:07 AM (5 years ago)
Author:
Antti Koivisto
Message:

Hit-testing of boxes over scrollers should account for border-radius
https://bugs.webkit.org/show_bug.cgi?id=195374
<rdar://problem/48649993>

Reviewed by Simon Fraser.

Source/WebCore:

Test: fast/scrolling/ios/border-radious-event-region.html

  • page/Frame.h:
  • platform/graphics/GraphicsLayer.cpp:

(WebCore::GraphicsLayer::dumpProperties const):

Testing support.

  • platform/graphics/GraphicsLayerClient.h:
  • platform/graphics/RoundedRect.cpp:

(WebCore::approximateAsRegion):

Add a function to approximate RoundedRects as Regions.
It cuts away rectangles from the corners following the corner shapes.
More rectangles are cut for larger radii.

  • platform/graphics/RoundedRect.h:
  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::paintObject):

Use the new interface to get rounded corners right.
In rectangle case this takes optimized paths.

  • rendering/RenderLayerCompositor.cpp:

(WebCore::RenderLayerCompositor::layerTreeAsText):

  • testing/Internals.cpp:

(WebCore::toLayerTreeFlags):

  • testing/Internals.h:
  • testing/Internals.idl:

LayoutTests:

  • fast/scrolling/ios/border-radius-event-region-expected.txt: Added.
  • fast/scrolling/ios/border-radius-event-region.html: Added.
  • fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt:
Location:
trunk
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r243673 r243674  
     12019-03-30  Antti Koivisto  <antti@apple.com>
     2
     3        Hit-testing of boxes over scrollers should account for border-radius
     4        https://bugs.webkit.org/show_bug.cgi?id=195374
     5        <rdar://problem/48649993>
     6
     7        Reviewed by Simon Fraser.
     8
     9        * fast/scrolling/ios/border-radius-event-region-expected.txt: Added.
     10        * fast/scrolling/ios/border-radius-event-region.html: Added.
     11        * fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt:
     12
    1132019-03-29  Zalan Bujtas  <zalan@apple.com>
    214
  • trunk/LayoutTests/fast/scrolling/ios/overflow-scroll-overlap-2-expected.txt

    r243134 r243674  
    55case 3: Scrollable 3
    66case 4: Scrollable 4
    7 case 5:
     7case 5: Scrollable 5
    88
  • trunk/Source/WebCore/ChangeLog

    r243673 r243674  
     12019-03-30  Antti Koivisto  <antti@apple.com>
     2
     3        Hit-testing of boxes over scrollers should account for border-radius
     4        https://bugs.webkit.org/show_bug.cgi?id=195374
     5        <rdar://problem/48649993>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Test: fast/scrolling/ios/border-radious-event-region.html
     10
     11        * page/Frame.h:
     12        * platform/graphics/GraphicsLayer.cpp:
     13        (WebCore::GraphicsLayer::dumpProperties const):
     14
     15        Testing support.
     16
     17        * platform/graphics/GraphicsLayerClient.h:
     18        * platform/graphics/RoundedRect.cpp:
     19        (WebCore::approximateAsRegion):
     20
     21        Add a function to approximate RoundedRects as Regions.
     22        It cuts away rectangles from the corners following the corner shapes.
     23        More rectangles are cut for larger radii.
     24
     25        * platform/graphics/RoundedRect.h:
     26        * rendering/RenderBlock.cpp:
     27        (WebCore::RenderBlock::paintObject):
     28
     29        Use the new interface to get rounded corners right.
     30        In rectangle case this takes optimized paths.
     31
     32        * rendering/RenderLayerCompositor.cpp:
     33        (WebCore::RenderLayerCompositor::layerTreeAsText):
     34        * testing/Internals.cpp:
     35        (WebCore::toLayerTreeFlags):
     36        * testing/Internals.h:
     37        * testing/Internals.idl:
     38
    1392019-03-29  Zalan Bujtas  <zalan@apple.com>
    240
  • trunk/Source/WebCore/page/Frame.h

    r242082 r243674  
    107107
    108108enum {
    109     LayerTreeFlagsIncludeDebugInfo = 1 << 0,
    110     LayerTreeFlagsIncludeVisibleRects = 1 << 1,
    111     LayerTreeFlagsIncludeTileCaches = 1 << 2,
    112     LayerTreeFlagsIncludeRepaintRects = 1 << 3,
    113     LayerTreeFlagsIncludePaintingPhases = 1 << 4,
    114     LayerTreeFlagsIncludeContentLayers = 1 << 5,
    115     LayerTreeFlagsIncludeAcceleratesDrawing = 1 << 6,
    116     LayerTreeFlagsIncludeBackingStoreAttached = 1 << 7,
    117     LayerTreeFlagsIncludeRootLayerProperties = 1 << 8,
     109    LayerTreeFlagsIncludeDebugInfo              = 1 << 0,
     110    LayerTreeFlagsIncludeVisibleRects           = 1 << 1,
     111    LayerTreeFlagsIncludeTileCaches             = 1 << 2,
     112    LayerTreeFlagsIncludeRepaintRects           = 1 << 3,
     113    LayerTreeFlagsIncludePaintingPhases         = 1 << 4,
     114    LayerTreeFlagsIncludeContentLayers          = 1 << 5,
     115    LayerTreeFlagsIncludeAcceleratesDrawing     = 1 << 6,
     116    LayerTreeFlagsIncludeBackingStoreAttached   = 1 << 7,
     117    LayerTreeFlagsIncludeRootLayerProperties    = 1 << 8,
     118    LayerTreeFlagsIncludeEventRegion            = 1 << 9,
    118119};
    119120typedef unsigned LayerTreeFlags;
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp

    r243007 r243674  
    927927    }
    928928
     929    if (behavior & LayerTreeAsTextIncludeEventRegion && !m_eventRegion.isEmpty())
     930        ts << indent << "(event region" << m_eventRegion << ")\n";
     931
    929932    if (behavior & LayerTreeAsTextIncludePaintingPhases && paintingPhase()) {
    930933        ts << indent << "(paintingPhases\n";
  • trunk/Source/WebCore/platform/graphics/GraphicsLayerClient.h

    r241788 r243674  
    7474    LayerTreeAsTextIncludeBackingStoreAttached  = 1 << 8,
    7575    LayerTreeAsTextIncludeRootLayerProperties   = 1 << 9,
     76    LayerTreeAsTextIncludeEventRegion           = 1 << 10,
    7677    LayerTreeAsTextShowAll                      = 0xFFFF
    7778};
  • trunk/Source/WebCore/platform/graphics/Region.cpp

    r242995 r243674  
    651651}
    652652
     653TextStream& operator<<(TextStream& ts, const Region& region)
     654{
     655    ts << "\n";
     656    {
     657        TextStream::IndentScope indentScope(ts);
     658        for (auto& rect : region.rects())
     659            ts << indent << "(rect " << rect << ")\n";
     660    }
     661    ts << indent;
     662
     663    return ts;
     664}
    653665
    654666} // namespace WebCore
  • trunk/Source/WebCore/platform/graphics/Region.h

    r242998 r243674  
    209209}
    210210
     211WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const Region&);
     212
    211213template<class Encoder>
    212214void Region::Span::encode(Encoder& encoder) const
  • trunk/Source/WebCore/platform/graphics/RoundedRect.cpp

    r222245 r243674  
    3333#include "LayoutRect.h"
    3434#include "LayoutUnit.h"
     35#include "Region.h"
    3536
    3637#include <algorithm>
     
    306307}
    307308
     309Region approximateAsRegion(const RoundedRect& roundedRect, unsigned stepLength)
     310{
     311    Region region;
     312
     313    auto& rect = roundedRect.rect();
     314    region.unite(enclosingIntRect(rect));
     315
     316    if (!roundedRect.isRounded())
     317        return region;
     318
     319    auto& radii = roundedRect.radii();
     320
     321    auto makeIntRect = [] (LayoutPoint a, LayoutPoint b) {
     322        return enclosingIntRect(LayoutRect {
     323            LayoutPoint { std::min(a.x(), b.x()), std::min(a.y(), b.y()) },
     324            LayoutPoint { std::max(a.x(), b.x()), std::max(a.y(), b.y()) }
     325        });
     326    };
     327
     328    auto subtractCornerRects = [&] (LayoutPoint corner, LayoutPoint ellipsisCenter, LayoutSize axes, double fromAngle) {
     329        double toAngle = fromAngle + M_PI / 2;
     330
     331        // Substract more rects for longer, more rounded arcs.
     332        auto arcLengthFactor = roundToInt(std::min(axes.width(), axes.height()));
     333        auto count = (arcLengthFactor + (stepLength / 2)) / stepLength;
     334
     335        for (auto i = 0u; i < count; ++i) {
     336            auto angle = fromAngle + (i + 1) * (toAngle - fromAngle) / (count + 1);
     337            auto ellipsisPoint = LayoutPoint { axes.width() * cos(angle), axes.height() * sin(angle) };
     338            auto cornerRect = makeIntRect(corner, ellipsisCenter + ellipsisPoint);
     339            region.subtract(cornerRect);
     340        }
     341    };
     342
     343    {
     344        auto corner = rect.maxXMaxYCorner();
     345        auto axes = radii.bottomRight();
     346        auto ellipsisCenter = LayoutPoint(corner.x() - axes.width(), corner.y() - axes.height());
     347        subtractCornerRects(corner, ellipsisCenter, axes, 0);
     348    }
     349
     350    {
     351        auto corner = rect.minXMaxYCorner();
     352        auto axes = radii.bottomLeft();
     353        auto ellipsisCenter = LayoutPoint(corner.x() + axes.width(), corner.y() - axes.height());
     354        subtractCornerRects(corner, ellipsisCenter, axes, M_PI / 2);
     355    }
     356
     357    {
     358        auto corner = rect.minXMinYCorner();
     359        auto axes = radii.topLeft();
     360        auto ellipsisCenter = LayoutPoint(corner.x() + axes.width(), corner.y() + axes.height());
     361        subtractCornerRects(corner, ellipsisCenter, axes, M_PI);
     362    }
     363
     364    {
     365        auto corner = rect.maxXMinYCorner();
     366        auto axes = radii.topRight();
     367        auto ellipsisCenter = LayoutPoint(corner.x() - axes.width(), corner.y() + axes.height());
     368        subtractCornerRects(corner, ellipsisCenter, axes, M_PI * 3 / 2);
     369    }
     370
     371    return region;
     372}
     373
    308374} // namespace WebCore
  • trunk/Source/WebCore/platform/graphics/RoundedRect.h

    r222245 r243674  
    3636class FloatRoundedRect;
    3737class LayoutUnit;
     38class Region;
    3839
    3940class RoundedRect {
     
    7980    };
    8081
    81     explicit RoundedRect(const LayoutRect&, const Radii& = Radii());
     82    WEBCORE_EXPORT explicit RoundedRect(const LayoutRect&, const Radii& = Radii());
    8283    RoundedRect(const LayoutUnit&, const LayoutUnit&, const LayoutUnit& width, const LayoutUnit& height);
    8384    WEBCORE_EXPORT RoundedRect(const LayoutRect&, const LayoutSize& topLeft, const LayoutSize& topRight, const LayoutSize& bottomLeft, const LayoutSize& bottomRight);
     
    128129}
    129130
     131// Snip away rectangles from corners, roughly one per step length of arc.
     132WEBCORE_EXPORT Region approximateAsRegion(const RoundedRect&, unsigned stepLength = 20);
    130133
    131134} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r243134 r243674  
    12421242
    12431243    if (paintPhase == PaintPhase::EventRegion) {
    1244         // FIXME: Handle inlines, lineboxes, SVG too.
    1245         // FIXME: Transforms?
    1246         if (visibleToHitTesting())
    1247             paintInfo.eventRegion->unite(enclosingIntRect(LayoutRect(paintOffset, size())));
     1244        auto borderRect = LayoutRect(paintOffset, size());
     1245
     1246        if (visibleToHitTesting()) {
     1247            auto borderRegion = approximateAsRegion(style().getRoundedBorderFor(borderRect));
     1248            paintInfo.eventRegion->unite(borderRegion);
     1249        }
    12481250
    12491251        // No need to check descendants if we don't have overflow.
  • trunk/Source/WebCore/rendering/RenderLayerCompositor.cpp

    r243513 r243674  
    19441944    if (flags & LayerTreeFlagsIncludeRootLayerProperties)
    19451945        layerTreeBehavior |= LayerTreeAsTextIncludeRootLayerProperties;
     1946    if (flags & LayerTreeFlagsIncludeEventRegion)
     1947        layerTreeBehavior |= LayerTreeAsTextIncludeEventRegion;
    19461948
    19471949    // We skip dumping the scroll and clip layers to keep layerTreeAsText output
  • trunk/Source/WebCore/testing/Internals.cpp

    r243671 r243674  
    25192519    if (flags & Internals::LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES)
    25202520        layerTreeFlags |= LayerTreeFlagsIncludeRootLayerProperties;
     2521    if (flags & Internals::LAYER_TREE_INCLUDES_EVENT_REGION)
     2522        layerTreeFlags |= LayerTreeFlagsIncludeEventRegion;
    25212523
    25222524    return layerTreeFlags;
  • trunk/Source/WebCore/testing/Internals.h

    r243482 r243674  
    348348        LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED = 64,
    349349        LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES = 128,
     350        LAYER_TREE_INCLUDES_EVENT_REGION = 256,
    350351    };
    351352    ExceptionOr<String> layerTreeAsText(Document&, unsigned short flags) const;
  • trunk/Source/WebCore/testing/Internals.idl

    r243482 r243674  
    373373    const unsigned short LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED = 64;
    374374    const unsigned short LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES = 128;
     375    const unsigned short LAYER_TREE_INCLUDES_EVENT_REGION = 256;
    375376    [MayThrowException] DOMString layerTreeAsText(Document document, optional unsigned short flags = 0);
    376377
Note: See TracChangeset for help on using the changeset viewer.