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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "core/dom/IntersectionObservation.h"
7
8 #include "core/dom/ElementRareData.h"
9 #include "core/dom/IntersectionObserver.h"
10 #include "core/frame/FrameView.h"
11 #include "core/layout/LayoutBox.h"
12 #include "core/layout/LayoutText.h"
13 #include "core/layout/LayoutView.h"
14 #include "core/paint/PaintLayer.h"
15
16 namespace blink {
17
18 IntersectionObservation::IntersectionObservation(IntersectionObserver& observer, Element& target, bool shouldReportRootBounds)
19 : m_observer(observer)
20 , m_target(target.intersectionObserverData().createWeakPtr(&target))
21 , m_active(1)
esprehn 2015/12/17 01:40:28 true
szager1 2015/12/17 20:27:25 Done.
22 , m_shouldReportRootBounds(shouldReportRootBounds ? 1 : 0)
esprehn 2015/12/17 01:40:28 ditto, just assign
szager1 2015/12/17 20:27:25 Done.
23 , m_lastThresholdIndex(0)
24 {
25 target.intersectionObserverData().addObservation(*this);
26 }
27
28 void IntersectionObservation::initializeGeometry(IntersectionGeometry& geometry)
29 {
30 LayoutObject* targetLayoutObject = m_target->layoutObject();
31 if (targetLayoutObject->isBoxModelObject())
32 geometry.targetRect = toLayoutBoxModelObject(targetLayoutObject)->visual OverflowRect();
33 else
34 geometry.targetRect = toLayoutText(targetLayoutObject)->visualOverflowRe ct();
35 geometry.intersectionRect = geometry.targetRect;
36 }
37
38 void IntersectionObservation::clipToRoot(LayoutRect& rect)
39 {
40 // Map and clip rect into root element coordinates.
41 LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
42 LayoutObject* targetLayoutObject = m_target->layoutObject();
43 targetLayoutObject->mapToVisibleRectInContainerSpace(toLayoutBoxModelObject( rootLayoutObject), rect, nullptr);
44 if (rootLayoutObject->hasOverflowClip()) {
45 LayoutBox* rootLayoutBox = toLayoutBox(rootLayoutObject);
46 LayoutRect clipRect(LayoutPoint(), LayoutSize(rootLayoutBox->layer()->si ze()));
47 m_observer->applyRootMargin(clipRect);
48 rootLayoutBox->flipForWritingMode(rect);
49 rect.intersect(clipRect);
50 rootLayoutBox->flipForWritingMode(rect);
51 }
52 }
53
54 void IntersectionObservation::clipToFrameView(IntersectionGeometry& geometry)
55 {
56 Element* rootElement = m_observer->root();
57 bool rootIsDocumentElement = (rootElement == rootElement->document().documen tElement());
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.
58 LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
59 if (rootIsDocumentElement) {
60 geometry.rootRect = LayoutRect(rootElement->document().view()->visibleCo ntentRect());
61 m_observer->applyRootMargin(geometry.rootRect);
62 geometry.intersectionRect.intersect(geometry.rootRect);
63 } else {
64 if (rootLayoutObject->isBox())
65 geometry.rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->absolu teContentBox());
66 else
67 geometry.rootRect = LayoutRect(rootLayoutObject->absoluteBoundingBox Rect());
68 m_observer->applyRootMargin(geometry.rootRect);
69 }
70
71 LayoutPoint scrollPosition(rootElement->document().view()->scrollPosition()) ;
72 geometry.targetRect.moveBy(-scrollPosition);
73 geometry.intersectionRect.moveBy(-scrollPosition);
74 geometry.rootRect.moveBy(-scrollPosition);
75 }
76
77 static void mapRectToDocumentCoordinates(LayoutObject* layoutObject, LayoutRect& rect)
78 {
79 rect = LayoutRect(layoutObject->localToAbsoluteQuad(FloatQuad(FloatRect(rect )), UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries).boundingBox ());
80 }
81
82 bool IntersectionObservation::computeGeometry(IntersectionGeometry& geometry)
83 {
84 LayoutObject* rootLayoutObject = m_observer->rootLayoutObject();
85 LayoutObject* targetLayoutObject = m_target->layoutObject();
86 if (!rootLayoutObject->isBoxModelObject())
87 return false;
88 if (!targetLayoutObject->isBoxModelObject() && !targetLayoutObject->isText() )
89 return false;
90
91 // Initialize targetRect and intersectionRect to bounds of target, in target 's coordinate space.
92 initializeGeometry(geometry);
93
94 // TODO: Support intersection observations for zero-area targets. For now, we just
95 // punt on the observation.
96 if (!geometry.targetRect.size().width() || !geometry.targetRect.size().heigh t())
97 return false;
98
99 // Clip intersectionRect to the root, and map it to root coordinates.
100 clipToRoot(geometry.intersectionRect);
101
102 // Map targetRect into document coordinates.
esprehn 2015/12/17 01:40:28 soooooo much better as steps, great!
103 mapRectToDocumentCoordinates(targetLayoutObject, geometry.targetRect);
104
105 // Map intersectionRect into document coordinates.
106 mapRectToDocumentCoordinates(rootLayoutObject, geometry.intersectionRect);
107
108 // Clip intersectionRect to FrameView visible area if necessary, and map all geometry to frame coordinates.
109 clipToFrameView(geometry);
110
111 if (geometry.intersectionRect.size().isZero())
112 geometry.intersectionRect = LayoutRect();
113 if (!m_shouldReportRootBounds)
114 geometry.rootRect = LayoutRect();
115
116 return true;
117 }
118
119 void IntersectionObservation::computeIntersectionObservations(double timestamp)
120 {
121 Element* targetElement = target();
122 if (!targetElement || !isActive())
123 return;
124 LayoutObject* targetLayoutObject = targetElement->layoutObject();
125 // TODO: Support SVG
126 if (!targetLayoutObject || (!targetLayoutObject->isBox() && !targetLayoutObj ect->isInline()))
127 return;
128
129 IntersectionGeometry geometry;
130 if (!computeGeometry(geometry))
131 return;
132
133 float intersectionArea = geometry.intersectionRect.size().width().toFloat() * geometry.intersectionRect.size().height().toFloat();
134 float targetArea = geometry.targetRect.size().width().toFloat() * geometry.t argetRect.size().height().toFloat();
135 if (!targetArea)
136 return;
137 float newVisibleRatio = intersectionArea / targetArea;
138 unsigned newThresholdIndex = observer()->firstThresholdGreaterThan(newVisibl eRatio);
139 if (m_lastThresholdIndex != newThresholdIndex) {
140 IntersectionObserverEntry* newEntry = new IntersectionObserverEntry(
141 timestamp / 1000.0,
142 pixelSnappedIntRect(geometry.targetRect),
143 pixelSnappedIntRect(geometry.rootRect),
144 pixelSnappedIntRect(geometry.intersectionRect),
145 targetElement);
146 observer()->enqueueIntersectionObserverEntry(*newEntry);
147 }
148 setLastThresholdIndex(newThresholdIndex);
149 }
150
151 void IntersectionObservation::disconnect()
152 {
153 observer()->disconnect(*this);
154 if (m_target)
155 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
156 }
157
158 DEFINE_TRACE(IntersectionObservation)
159 {
160 visitor->trace(m_observer);
161 visitor->trace(m_target);
162 }
163
164 } // namespace blink {
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698