Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: third_party/WebKit/Source/core/dom/IntersectionObservation.cpp

Issue 1449623002: IntersectionObserver: second cut. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Added dispose() methods for expicit cleanup Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
new file mode 100644
index 0000000000000000000000000000000000000000..e0433765e0b67e71933192bc66f6354b51ab72ee
--- /dev/null
+++ b/third_party/WebKit/Source/core/dom/IntersectionObservation.cpp
@@ -0,0 +1,164 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/dom/IntersectionObservation.h"
+
+#include "core/dom/ElementRareData.h"
+#include "core/dom/IntersectionObserver.h"
+#include "core/frame/FrameView.h"
+#include "core/layout/LayoutBox.h"
+#include "core/layout/LayoutText.h"
+#include "core/layout/LayoutView.h"
+#include "core/paint/PaintLayer.h"
+
+namespace blink {
+
+IntersectionObservation::IntersectionObservation(IntersectionObserver& observer, Element& target, bool shouldReportRootBounds)
+ : m_observer(observer)
+ , m_target(target.intersectionObserverData().createWeakPtr(&target))
+ , m_active(1)
esprehn 2015/12/17 01:40:28 true
szager1 2015/12/17 20:27:25 Done.
+ , m_shouldReportRootBounds(shouldReportRootBounds ? 1 : 0)
esprehn 2015/12/17 01:40:28 ditto, just assign
szager1 2015/12/17 20:27:25 Done.
+ , m_lastThresholdIndex(0)
+{
+ target.intersectionObserverData().addObservation(*this);
+}
+
+void IntersectionObservation::initializeGeometry(IntersectionGeometry& geometry)
+{
+ LayoutObject* targetLayoutObject = m_target->layoutObject();
+ if (targetLayoutObject->isBoxModelObject())
+ geometry.targetRect = toLayoutBoxModelObject(targetLayoutObject)->visualOverflowRect();
+ else
+ geometry.targetRect = toLayoutText(targetLayoutObject)->visualOverflowRect();
+ geometry.intersectionRect = geometry.targetRect;
+}
+
+void IntersectionObservation::clipToRoot(LayoutRect& rect)
+{
+ // Map and clip rect into root element coordinates.
+ LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
+ LayoutObject* targetLayoutObject = m_target->layoutObject();
+ targetLayoutObject->mapToVisibleRectInContainerSpace(toLayoutBoxModelObject(rootLayoutObject), rect, nullptr);
+ if (rootLayoutObject->hasOverflowClip()) {
+ LayoutBox* rootLayoutBox = toLayoutBox(rootLayoutObject);
+ LayoutRect clipRect(LayoutPoint(), LayoutSize(rootLayoutBox->layer()->size()));
+ m_observer->applyRootMargin(clipRect);
+ rootLayoutBox->flipForWritingMode(rect);
+ rect.intersect(clipRect);
+ rootLayoutBox->flipForWritingMode(rect);
+ }
+}
+
+void IntersectionObservation::clipToFrameView(IntersectionGeometry& geometry)
+{
+ Element* rootElement = m_observer->root();
+ bool rootIsDocumentElement = (rootElement == rootElement->document().documentElement());
esprehn 2015/12/17 01:40:28 I would just inline this into the if () below, the
szager1 2015/12/17 20:27:25 Done.
+ LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
+ if (rootIsDocumentElement) {
+ geometry.rootRect = LayoutRect(rootElement->document().view()->visibleContentRect());
+ m_observer->applyRootMargin(geometry.rootRect);
+ geometry.intersectionRect.intersect(geometry.rootRect);
+ } else {
+ if (rootLayoutObject->isBox())
+ geometry.rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->absoluteContentBox());
+ else
+ geometry.rootRect = LayoutRect(rootLayoutObject->absoluteBoundingBoxRect());
+ m_observer->applyRootMargin(geometry.rootRect);
+ }
+
+ LayoutPoint scrollPosition(rootElement->document().view()->scrollPosition());
+ geometry.targetRect.moveBy(-scrollPosition);
+ geometry.intersectionRect.moveBy(-scrollPosition);
+ geometry.rootRect.moveBy(-scrollPosition);
+}
+
+static void mapRectToDocumentCoordinates(LayoutObject* layoutObject, LayoutRect& rect)
+{
+ rect = LayoutRect(layoutObject->localToAbsoluteQuad(FloatQuad(FloatRect(rect)), UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries).boundingBox());
+}
+
+bool IntersectionObservation::computeGeometry(IntersectionGeometry& geometry)
+{
+ LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
+ LayoutObject* targetLayoutObject = m_target->layoutObject();
+ if (!rootLayoutObject->isBoxModelObject())
+ return false;
+ if (!targetLayoutObject->isBoxModelObject() && !targetLayoutObject->isText())
+ return false;
+
+ // Initialize targetRect and intersectionRect to bounds of target, in target's coordinate space.
+ initializeGeometry(geometry);
+
+ // TODO: Support intersection observations for zero-area targets. For now, we just
+ // punt on the observation.
+ if (!geometry.targetRect.size().width() || !geometry.targetRect.size().height())
+ return false;
+
+ // Clip intersectionRect to the root, and map it to root coordinates.
+ clipToRoot(geometry.intersectionRect);
+
+ // Map targetRect into document coordinates.
esprehn 2015/12/17 01:40:28 soooooo much better as steps, great!
+ mapRectToDocumentCoordinates(targetLayoutObject, geometry.targetRect);
+
+ // Map intersectionRect into document coordinates.
+ mapRectToDocumentCoordinates(rootLayoutObject, geometry.intersectionRect);
+
+ // Clip intersectionRect to FrameView visible area if necessary, and map all geometry to frame coordinates.
+ clipToFrameView(geometry);
+
+ if (geometry.intersectionRect.size().isZero())
+ geometry.intersectionRect = LayoutRect();
+ if (!m_shouldReportRootBounds)
+ geometry.rootRect = LayoutRect();
+
+ return true;
+}
+
+void IntersectionObservation::computeIntersectionObservations(double timestamp)
+{
+ Element* targetElement = target();
+ if (!targetElement || !isActive())
+ return;
+ LayoutObject* targetLayoutObject = targetElement->layoutObject();
+ // TODO: Support SVG
+ if (!targetLayoutObject || (!targetLayoutObject->isBox() && !targetLayoutObject->isInline()))
+ return;
+
+ IntersectionGeometry geometry;
+ 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);
+ if (m_lastThresholdIndex != newThresholdIndex) {
+ IntersectionObserverEntry* newEntry = new IntersectionObserverEntry(
+ timestamp / 1000.0,
+ pixelSnappedIntRect(geometry.targetRect),
+ pixelSnappedIntRect(geometry.rootRect),
+ pixelSnappedIntRect(geometry.intersectionRect),
+ targetElement);
+ observer()->enqueueIntersectionObserverEntry(*newEntry);
+ }
+ setLastThresholdIndex(newThresholdIndex);
+}
+
+void IntersectionObservation::disconnect()
+{
+ observer()->disconnect(*this);
+ if (m_target)
+ m_target->intersectionObserverData().removeObservation(*this->observer());
esprehn 2015/12/17 01:40:28 if you clear the sets in the dispose method you ca
szager1 2015/12/17 20:27:25 Acknowledged, added a TODO in IntersectionObserver
+}
+
+DEFINE_TRACE(IntersectionObservation)
+{
+ visitor->trace(m_observer);
+ visitor->trace(m_target);
+}
+
+} // namespace blink {

Powered by Google App Engine
This is Rietveld 408576698