Title: [237284] trunk
Revision
237284
Author
[email protected]
Date
2018-10-19 06:47:25 -0700 (Fri, 19 Oct 2018)

Log Message

[IntersectionObserver] Handle zero-area intersections
https://bugs.webkit.org/show_bug.cgi?id=189624

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

Rebaseline expectations for tests that now pass.

* web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt:
* web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt:
* web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt:
* web-platform-tests/intersection-observer/text-target-expected.txt:
* web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt:

Source/WebCore:

Use edge-inclusive intersection when applying clips and intersecting with the
root, so that two rects that touch each other are considered intersecting even
if the area of their intersection is 0.

Covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.

* dom/Document.cpp:
(WebCore::computeIntersectionState):
(WebCore::Document::updateIntersectionObservations):
(WebCore::computeIntersectionRects): Deleted.

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,3 +1,18 @@
+2018-10-19  Ali Juma  <[email protected]>
+
+        [IntersectionObserver] Handle zero-area intersections
+        https://bugs.webkit.org/show_bug.cgi?id=189624
+
+        Reviewed by Simon Fraser.
+
+        Rebaseline expectations for tests that now pass.
+
+        * web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt:
+        * web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt:
+        * web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt:
+        * web-platform-tests/intersection-observer/text-target-expected.txt:
+        * web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt:
+
 2018-10-18  Yusuke Suzuki  <[email protected]>
 
         [JSC] JSC should have "parseFunction" to optimize Function constructor

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/edge-inclusive-intersection-expected.txt	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,7 +1,7 @@
 
 PASS IntersectionObserver should detect and report edge-adjacent and zero-area intersections. 
 PASS First rAF. 
-FAIL Set transform=translateY(200px) on target. assert_equals: entries.length expected 2 but got 1
-FAIL Set transform=translateY(201px) on target. assert_equals: entries.length expected 3 but got 1
-FAIL Set transform=translateY(185px) on target. assert_equals: entries.length expected 4 but got 1
+PASS Set transform=translateY(200px) on target. 
+PASS Set transform=translateY(201px) on target. 
+PASS Set transform=translateY(185px) on target. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/isIntersecting-change-events-expected.txt	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,4 +1,7 @@
 
 PASS isIntersecting changes should trigger notifications. 
-FAIL Rects in initial notifications should report initial positions. assert_equals: entries[2].target.isIntersecting equals true expected true but got false
+PASS Rects in initial notifications should report initial positions. 
+PASS Set scrollTop=100 and check for no new notifications. 
+PASS Add 4th target. 
+PASS Set scrollTop=100 and check for one new notification. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/same-document-zero-size-target-expected.txt	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,6 +1,6 @@
 
 PASS Observing a zero-area target. 
 PASS First rAF 
-FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
-FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+PASS document.scrollingElement.scrollTop = 300 
+PASS document.scrollingElement.scrollTop = 100 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/text-target-expected.txt	2018-10-19 13:47:25 UTC (rev 237284)
@@ -2,6 +2,6 @@
 
 PASS IntersectionObserver observing a br element. 
 PASS First rAF. 
-FAIL document.scrollingElement.scrollTop = 300 assert_equals: entries.length expected 2 but got 1
-FAIL document.scrollingElement.scrollTop = 100 assert_equals: entries.length expected 3 but got 1
+PASS document.scrollingElement.scrollTop = 300 
+PASS document.scrollingElement.scrollTop = 100 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt (237283 => 237284)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/intersection-observer/zero-area-element-visible-expected.txt	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,4 +1,4 @@
 
 PASS Ensure that a zero-area target intersecting root generates a notification with intersectionRatio == 1 
-FAIL First rAF should generate a notification. assert_equals: intersectionRatio == 1 expected 1 but got 0
+PASS First rAF should generate a notification. 
 

Modified: trunk/Source/WebCore/ChangeLog (237283 => 237284)


--- trunk/Source/WebCore/ChangeLog	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/Source/WebCore/ChangeLog	2018-10-19 13:47:25 UTC (rev 237284)
@@ -1,3 +1,21 @@
+2018-10-19  Ali Juma  <[email protected]>
+
+        [IntersectionObserver] Handle zero-area intersections
+        https://bugs.webkit.org/show_bug.cgi?id=189624
+
+        Reviewed by Simon Fraser.
+
+        Use edge-inclusive intersection when applying clips and intersecting with the
+        root, so that two rects that touch each other are considered intersecting even
+        if the area of their intersection is 0.
+
+        Covered by rebased tests in imported/w3c/web-platform-tests/intersection-observer.
+
+        * dom/Document.cpp:
+        (WebCore::computeIntersectionState):
+        (WebCore::Document::updateIntersectionObservations):
+        (WebCore::computeIntersectionRects): Deleted.
+
 2018-10-18  Eric Carlson  <[email protected]>
 
         [MediaStream] Allow ports to optionally do screen capture in the UI process

Modified: trunk/Source/WebCore/dom/Document.cpp (237283 => 237284)


--- trunk/Source/WebCore/dom/Document.cpp	2018-10-19 13:39:32 UTC (rev 237283)
+++ trunk/Source/WebCore/dom/Document.cpp	2018-10-19 13:47:25 UTC (rev 237284)
@@ -7592,25 +7592,32 @@
     localRootBounds.expand(rootMarginFloatBox);
 }
 
-static void computeIntersectionRects(FrameView& frameView, IntersectionObserver& observer, Element& target, FloatRect& absTargetRect, FloatRect& absIntersectionRect, FloatRect& absRootBounds)
+struct IntersectionObservationState {
+    FloatRect absoluteTargetRect;
+    FloatRect absoluteRootBounds;
+    FloatRect absoluteIntersectionRect;
+    bool isIntersecting { false };
+};
+
+static std::optional<IntersectionObservationState> computeIntersectionState(FrameView& frameView, const IntersectionObserver& observer, Element& target)
 {
     // FIXME: Implement intersection computation for the cross-document case.
     if (observer.trackingDocument() != &target.document())
-        return;
+        return std::nullopt;
 
     auto* targetRenderer = target.renderer();
     if (!targetRenderer)
-        return;
+        return std::nullopt;
 
     FloatRect localRootBounds;
     RenderBlock* rootRenderer;
     if (observer.root()) {
         if (!observer.root()->renderer() || !is<RenderBlock>(observer.root()->renderer()))
-            return;
+            return std::nullopt;
 
         rootRenderer = downcast<RenderBlock>(observer.root()->renderer());
         if (!rootRenderer->isContainingBlockAncestorFor(*targetRenderer))
-            return;
+            return std::nullopt;
 
         if (rootRenderer->hasOverflowClip())
             localRootBounds = rootRenderer->contentBoxRect();
@@ -7632,14 +7639,19 @@
     else if (is<RenderLineBreak>(targetRenderer))
         localTargetBounds = downcast<RenderLineBreak>(targetRenderer)->linesBoundingBox();
 
-    FloatRect rootLocalIntersectionRect = targetRenderer->computeRectForRepaint(localTargetBounds, rootRenderer);
-    rootLocalIntersectionRect.intersect(localRootBounds);
+    OptionSet<RenderObject::VisibleRectContextOption> visibleRectOptions = { RenderObject::VisibleRectContextOption::UseEdgeInclusiveIntersection, RenderObject::VisibleRectContextOption::ApplyCompositedClips, RenderObject::VisibleRectContextOption::ApplyCompositedContainerScrolls };
+    std::optional<LayoutRect> rootLocalTargetRect = targetRenderer->computeVisibleRectInContainer(localTargetBounds, rootRenderer, { false /* hasPositionFixedDescendant */, false /* dirtyRectIsFlipped */, visibleRectOptions });
+    FloatRect rootLocalIntersectionRect = localRootBounds;
 
-    if (!rootLocalIntersectionRect.isEmpty())
-        absIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+    IntersectionObservationState intersectionState;
+    intersectionState.isIntersecting = rootLocalTargetRect && rootLocalIntersectionRect.edgeInclusiveIntersect(*rootLocalTargetRect);
 
-    absTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
-    absRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
+    if (intersectionState.isIntersecting)
+        intersectionState.absoluteIntersectionRect = rootRenderer->localToAbsoluteQuad(rootLocalIntersectionRect).boundingBox();
+
+    intersectionState.absoluteTargetRect = targetRenderer->localToAbsoluteQuad(FloatRect(localTargetBounds)).boundingBox();
+    intersectionState.absoluteRootBounds = rootRenderer->localToAbsoluteQuad(localRootBounds).boundingBox();
+    return intersectionState;
 }
 
 void Document::updateIntersectionObservations()
@@ -7667,28 +7679,38 @@
             ASSERT(index != notFound);
             auto& registration = targetRegistrations[index];
 
-            FloatRect absTargetRect;
-            FloatRect absIntersectionRect;
-            FloatRect absRootBounds;
-            computeIntersectionRects(*frameView, *observer, *target, absTargetRect, absIntersectionRect, absRootBounds);
+            auto intersectionState = computeIntersectionState(*frameView, *observer, *target);
 
-            // FIXME: Handle zero-area intersections (e.g., intersections involving zero-area targets).
-            bool isIntersecting = absIntersectionRect.area();
-            float intersectionRatio = isIntersecting ? absIntersectionRect.area() / absTargetRect.area() : 0;
+            float intersectionRatio = 0;
             size_t thresholdIndex = 0;
-            if (isIntersecting) {
-                auto& thresholds = observer->thresholds();
-                while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
-                    ++thresholdIndex;
+            if (intersectionState) {
+                if (intersectionState->isIntersecting) {
+                    float absTargetArea = intersectionState->absoluteTargetRect.area();
+                    if (absTargetArea)
+                        intersectionRatio = intersectionState->absoluteIntersectionRect.area() / absTargetArea;
+                    else
+                        intersectionRatio = 1;
+
+                    auto& thresholds = observer->thresholds();
+                    while (thresholdIndex < thresholds.size() && thresholds[thresholdIndex] <= intersectionRatio)
+                        ++thresholdIndex;
+                }
             }
 
+
             if (!registration.previousThresholdIndex || thresholdIndex != registration.previousThresholdIndex) {
-                FloatRect targetBoundingClientRect = frameView->absoluteToClientRect(absTargetRect);
-                FloatRect clientIntersectionRect = isIntersecting ? frameView->absoluteToClientRect(absIntersectionRect) : FloatRect();
+                FloatRect targetBoundingClientRect;
+                FloatRect clientIntersectionRect;
+                FloatRect clientRootBounds;
+                if (intersectionState) {
+                    targetBoundingClientRect = frameView->absoluteToClientRect(intersectionState->absoluteTargetRect);
+                    clientRootBounds = frameView->absoluteToClientRect(intersectionState->absoluteRootBounds);
+                    if (intersectionState->isIntersecting)
+                        clientIntersectionRect = frameView->absoluteToClientRect(intersectionState->absoluteIntersectionRect);
+                }
 
                 // FIXME: Once cross-document observation is implemented, only report root bounds if the target document and
                 // the root document are similar-origin.
-                FloatRect clientRootBounds = frameView->absoluteToClientRect(absRootBounds);
                 std::optional<DOMRectInit> reportedRootBounds = DOMRectInit({
                     clientRootBounds.x(),
                     clientRootBounds.y(),
@@ -7703,7 +7725,7 @@
                     { clientIntersectionRect.x(), clientIntersectionRect.y(), clientIntersectionRect.width(), clientIntersectionRect.height() },
                     intersectionRatio,
                     target,
-                    isIntersecting,
+                    intersectionState? intersectionState->isIntersecting : false,
                 }));
                 needNotify = true;
                 registration.previousThresholdIndex = thresholdIndex;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to