Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/IntersectionObservation.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp |
| index 8a35d27e6dcdd306ff4eb6c895ac4dc6d1438b10..621234815b3a11faae5237197a39c1bb9ac7fe3c 100644 |
| --- a/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp |
| +++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp |
| @@ -34,19 +34,20 @@ void IntersectionObservation::applyRootMargin(LayoutRect& rect) const |
| m_observer->applyRootMargin(rect); |
| } |
| +void IntersectionObservation::initializeGeometry(IntersectionGeometry& geometry) const |
| +{ |
| + initializeTargetRect(geometry.targetRect); |
| + geometry.intersectionRect = geometry.targetRect; |
| + initializeRootRect(geometry.rootRect); |
| + geometry.doesIntersect = true; |
| +} |
| + |
| void IntersectionObservation::initializeTargetRect(LayoutRect& rect) const |
| { |
| ASSERT(m_target); |
| LayoutObject* targetLayoutObject = target()->layoutObject(); |
| ASSERT(targetLayoutObject && targetLayoutObject->isBoxModelObject()); |
| rect = toLayoutBoxModelObject(targetLayoutObject)->visualOverflowRect(); |
| - |
| - // TODO(szager): Properly support intersection observations for zero-area targets |
| - // by using edge-inclusive geometry. |
| - if (!rect.size().width()) |
| - rect.setWidth(LayoutUnit(1)); |
| - if (!rect.size().height()) |
| - rect.setHeight(LayoutUnit(1)); |
| } |
| void IntersectionObservation::initializeRootRect(LayoutRect& rect) const |
| @@ -62,7 +63,7 @@ void IntersectionObservation::initializeRootRect(LayoutRect& rect) const |
| applyRootMargin(rect); |
| } |
| -void IntersectionObservation::clipToRoot(LayoutRect& rect, const LayoutRect& rootRect) const |
| +void IntersectionObservation::clipToRoot(IntersectionGeometry& geometry) const |
| { |
| // Map and clip rect into root element coordinates. |
| // TODO(szager): the writing mode flipping needs a test. |
| @@ -70,10 +71,12 @@ void IntersectionObservation::clipToRoot(LayoutRect& rect, const LayoutRect& roo |
| LayoutObject* rootLayoutObject = m_observer->rootLayoutObject(); |
| LayoutObject* targetLayoutObject = target()->layoutObject(); |
| - targetLayoutObject->mapToVisibleRectInAncestorSpace(toLayoutBoxModelObject(rootLayoutObject), rect, nullptr); |
| - LayoutRect rootClipRect(rootRect); |
| + geometry.doesIntersect = targetLayoutObject->mapToVisibleRectInAncestorSpace(toLayoutBoxModelObject(rootLayoutObject), geometry.intersectionRect, nullptr, EdgeInclusive); |
| + if (!geometry.doesIntersect) |
| + return; |
| + LayoutRect rootClipRect(geometry.rootRect); |
| toLayoutBox(rootLayoutObject)->flipForWritingMode(rootClipRect); |
| - rect.intersect(rootClipRect); |
| + geometry.doesIntersect &= geometry.intersectionRect.inclusiveIntersect(rootClipRect); |
| } |
| static void mapRectUpToDocument(LayoutRect& rect, const LayoutObject& layoutObject, const Document& document) |
| @@ -164,22 +167,22 @@ bool IntersectionObservation::computeGeometry(IntersectionGeometry& geometry) co |
| if (!isContainingBlockChainDescendant(targetLayoutObject, rootLayoutObject)) |
| return false; |
| - initializeTargetRect(geometry.targetRect); |
| - geometry.intersectionRect = geometry.targetRect; |
| - initializeRootRect(geometry.rootRect); |
| + initializeGeometry(geometry); |
| - clipToRoot(geometry.intersectionRect, geometry.rootRect); |
| + clipToRoot(geometry); |
| - // TODO(szager): there are some simple optimizations that can be done here: |
| - // - Don't transform rootRect if it's not going to be reported |
| - // - Don't transform intersectionRect if it's empty |
| mapTargetRectToTargetFrameCoordinates(geometry.targetRect); |
| - mapRootRectToTargetFrameCoordinates(geometry.intersectionRect); |
| - mapRootRectToRootFrameCoordinates(geometry.rootRect); |
| - if (geometry.intersectionRect.size().isZero()) |
| + if (geometry.doesIntersect) |
| + mapRootRectToTargetFrameCoordinates(geometry.intersectionRect); |
| + else |
| geometry.intersectionRect = LayoutRect(); |
| + if (m_shouldReportRootBounds) |
| + mapRootRectToRootFrameCoordinates(geometry.rootRect); |
| + else |
| + geometry.rootRect = LayoutRect(); |
|
chrishtr
2016/03/24 23:35:29
Might as well kill this else clause.
szager1
2016/03/25 08:02:39
Done.
|
| + |
| return true; |
| } |
| @@ -189,15 +192,30 @@ void IntersectionObservation::computeIntersectionObservations(DOMHighResTimeStam |
| if (!computeGeometry(geometry)) |
| return; |
| - float intersectionArea = geometry.intersectionRect.size().width().toFloat() * geometry.intersectionRect.size().height().toFloat(); |
| - float targetArea = geometry.targetRect.size().width().toFloat() * geometry.targetRect.size().height().toFloat(); |
| - if (!targetArea) |
| - return; |
| - float newVisibleRatio = intersectionArea / targetArea; |
| - unsigned newThresholdIndex = observer().firstThresholdGreaterThan(newVisibleRatio); |
| - IntRect snappedRootBounds = pixelSnappedIntRect(geometry.rootRect); |
| - IntRect* rootBoundsPointer = m_shouldReportRootBounds ? &snappedRootBounds : nullptr; |
|
szager1
2016/03/24 23:33:09
Here.
chrishtr
2016/03/24 23:35:29
ah
|
| + // Some corner cases for threshold index: |
| + // - If target rect is zero area, only two states are recognized: |
|
chrishtr
2016/03/24 23:33:11
Good to mention that zero-area means either width
szager1
2016/03/25 08:02:39
Done.
|
| + // - 0 means not intersecting. |
| + // - 1 means intersecting. |
|
chrishtr
2016/03/24 23:33:11
Change to an enum.
szager1
2016/03/25 08:02:38
OK, although it seems weird to use an enum when, i
|
| + // No other threshold crossings are possible. |
| + // - Otherwise: |
| + // - If root and target do not intersect, the threshold index is 0. |
| + // - If root and target intersect but the intersection has zero-area (i.e., they |
| + // have a coincident edge or corner), we consider the intersection to have |
| + // "crossed" a zero threshold, but not crossed any non-zero threshold. |
| + unsigned newThresholdIndex; |
| + if (!geometry.doesIntersect) { |
| + newThresholdIndex = 0; |
| + } else if (geometry.targetRect.isEmpty()) { |
| + newThresholdIndex = 1; |
| + } else { |
| + float intersectionArea = geometry.intersectionRect.size().width().toFloat() * geometry.intersectionRect.size().height().toFloat(); |
| + float targetArea = geometry.targetRect.size().width().toFloat() * geometry.targetRect.size().height().toFloat(); |
| + float newVisibleRatio = intersectionArea / targetArea; |
| + newThresholdIndex = observer().firstThresholdGreaterThan(newVisibleRatio); |
| + } |
| if (m_lastThresholdIndex != newThresholdIndex) { |
| + IntRect snappedRootBounds = pixelSnappedIntRect(geometry.rootRect); |
| + IntRect* rootBoundsPointer = m_shouldReportRootBounds ? &snappedRootBounds : nullptr; |
| IntersectionObserverEntry* newEntry = new IntersectionObserverEntry( |
| timestamp, |
| pixelSnappedIntRect(geometry.targetRect), |