Commit 80f26da6 authored by szager's avatar szager Committed by Commit bot

Refactor IntersectionGeometry class and move it to core/layout.

IntersectionGeometry is an ephemeral object, so make it stack
allocated, let it use raw pointers to LayoutObject, and move it to
core/layout.

Also, be explicit about the implicit root by introducing
rootIsImplicit.

R=ojan@chromium.org,xjz@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2553103004
Cr-Commit-Position: refs/heads/master@{#437949}
parent 0cfffd46
...@@ -155,8 +155,6 @@ blink_core_sources("dom") { ...@@ -155,8 +155,6 @@ blink_core_sources("dom") {
"IgnoreDestructiveWriteCountIncrementer.h", "IgnoreDestructiveWriteCountIncrementer.h",
"IncrementLoadEventDelayCount.cpp", "IncrementLoadEventDelayCount.cpp",
"IncrementLoadEventDelayCount.h", "IncrementLoadEventDelayCount.h",
"IntersectionGeometry.cpp",
"IntersectionGeometry.h",
"IntersectionObservation.cpp", "IntersectionObservation.cpp",
"IntersectionObservation.h", "IntersectionObservation.h",
"IntersectionObserver.cpp", "IntersectionObserver.cpp",
......
...@@ -6,18 +6,16 @@ ...@@ -6,18 +6,16 @@
#include "core/dom/ElementRareData.h" #include "core/dom/ElementRareData.h"
#include "core/dom/IntersectionObserver.h" #include "core/dom/IntersectionObserver.h"
#include "core/layout/IntersectionGeometry.h"
namespace blink { namespace blink {
IntersectionObservation::IntersectionObservation( IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
IntersectionObserver& observer, Element& target,
Element& target, bool shouldReportRootBounds)
IntersectionGeometry::ReportRootBounds shouldReportRootBounds)
: m_observer(observer), : m_observer(observer),
m_target(&target), m_target(&target),
m_shouldReportRootBounds( m_shouldReportRootBounds(shouldReportRootBounds),
shouldReportRootBounds ==
IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds),
m_lastThresholdIndex(0) {} m_lastThresholdIndex(0) {}
void IntersectionObservation::computeIntersectionObservations( void IntersectionObservation::computeIntersectionObservations(
...@@ -29,11 +27,10 @@ void IntersectionObservation::computeIntersectionObservations( ...@@ -29,11 +27,10 @@ void IntersectionObservation::computeIntersectionObservations(
rootMargin[1] = m_observer->rightMargin(); rootMargin[1] = m_observer->rightMargin();
rootMargin[2] = m_observer->bottomMargin(); rootMargin[2] = m_observer->bottomMargin();
rootMargin[3] = m_observer->leftMargin(); rootMargin[3] = m_observer->leftMargin();
Node* rootNode = m_observer->rootNode();
IntersectionGeometry geometry( IntersectionGeometry geometry(
m_observer->rootNode(), target(), rootMargin, rootNode && !rootNode->isDocumentNode() ? toElement(rootNode) : nullptr,
m_shouldReportRootBounds *target(), rootMargin, m_shouldReportRootBounds);
? IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds
: IntersectionGeometry::ReportRootBounds::kShouldNotReportRootBounds);
geometry.computeGeometry(); geometry.computeGeometry();
// Some corner cases for threshold index: // Some corner cases for threshold index:
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#define IntersectionObservation_h #define IntersectionObservation_h
#include "core/dom/DOMHighResTimeStamp.h" #include "core/dom/DOMHighResTimeStamp.h"
#include "core/dom/IntersectionGeometry.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
namespace blink { namespace blink {
...@@ -17,10 +16,9 @@ class IntersectionObserver; ...@@ -17,10 +16,9 @@ class IntersectionObserver;
class IntersectionObservation final class IntersectionObservation final
: public GarbageCollected<IntersectionObservation> { : public GarbageCollected<IntersectionObservation> {
public: public:
IntersectionObservation( IntersectionObservation(IntersectionObserver&,
IntersectionObserver&, Element&,
Element&, bool shouldReportRootBounds);
IntersectionGeometry::ReportRootBounds shouldReportRootBounds);
IntersectionObserver& observer() const { return *m_observer; } IntersectionObserver& observer() const { return *m_observer; }
Element* target() const { return m_target; } Element* target() const { return m_target; }
......
...@@ -270,11 +270,8 @@ void IntersectionObserver::observe(Element* target, ...@@ -270,11 +270,8 @@ void IntersectionObserver::observe(Element* target,
isDOMDescendant = (targetFrame->tree().top() == rootFrame); isDOMDescendant = (targetFrame->tree().top() == rootFrame);
} }
IntersectionObservation* observation = new IntersectionObservation( IntersectionObservation* observation =
*this, *target, new IntersectionObservation(*this, *target, shouldReportRootBounds);
shouldReportRootBounds
? IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds
: IntersectionGeometry::ReportRootBounds::kShouldNotReportRootBounds);
target->ensureIntersectionObserverData().addObservation(*observation); target->ensureIntersectionObserverData().addObservation(*observation);
m_observations.add(observation); m_observations.add(observation);
......
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
#include "core/dom/ElementTraversal.h" #include "core/dom/ElementTraversal.h"
#include "core/dom/ElementVisibilityObserver.h" #include "core/dom/ElementVisibilityObserver.h"
#include "core/dom/Fullscreen.h" #include "core/dom/Fullscreen.h"
#include "core/dom/IntersectionGeometry.h"
#include "core/dom/TaskRunnerHelper.h" #include "core/dom/TaskRunnerHelper.h"
#include "core/dom/shadow/ShadowRoot.h" #include "core/dom/shadow/ShadowRoot.h"
#include "core/events/Event.h" #include "core/events/Event.h"
...@@ -66,6 +65,7 @@ ...@@ -66,6 +65,7 @@
#include "core/html/track/VideoTrack.h" #include "core/html/track/VideoTrack.h"
#include "core/html/track/VideoTrackList.h" #include "core/html/track/VideoTrackList.h"
#include "core/inspector/ConsoleMessage.h" #include "core/inspector/ConsoleMessage.h"
#include "core/layout/IntersectionGeometry.h"
#include "core/layout/LayoutMedia.h" #include "core/layout/LayoutMedia.h"
#include "core/layout/api/LayoutViewItem.h" #include "core/layout/api/LayoutViewItem.h"
#include "core/layout/compositing/PaintLayerCompositor.h" #include "core/layout/compositing/PaintLayerCompositor.h"
...@@ -4069,9 +4069,9 @@ DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) { ...@@ -4069,9 +4069,9 @@ DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) {
void HTMLMediaElement::checkViewportIntersectionChanged() { void HTMLMediaElement::checkViewportIntersectionChanged() {
// TODO(xjz): Early return if we not in tab mirroring. // TODO(xjz): Early return if we not in tab mirroring.
IntersectionGeometry geometry( bool shouldReportRootBounds = true;
document().frame()->localFrameRoot()->document(), this, Vector<Length>(), IntersectionGeometry geometry(nullptr, *this, Vector<Length>(),
IntersectionGeometry::ReportRootBounds::kShouldReportRootBounds); shouldReportRootBounds);
geometry.computeGeometry(); geometry.computeGeometry();
IntRect intersectRect = geometry.intersectionIntRect(); IntRect intersectRect = geometry.intersectionIntRect();
if (m_currentIntersectRect == intersectRect) if (m_currentIntersectRect == intersectRect)
......
...@@ -39,6 +39,8 @@ blink_core_sources("layout") { ...@@ -39,6 +39,8 @@ blink_core_sources("layout") {
"HitTestingTransformState.h", "HitTestingTransformState.h",
"ImageQualityController.cpp", "ImageQualityController.cpp",
"ImageQualityController.h", "ImageQualityController.h",
"IntersectionGeometry.cpp",
"IntersectionGeometry.h",
"LayoutAnalyzer.cpp", "LayoutAnalyzer.cpp",
"LayoutAnalyzer.h", "LayoutAnalyzer.h",
"LayoutBR.cpp", "LayoutBR.cpp",
......
...@@ -2,12 +2,11 @@ ...@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "core/dom/IntersectionGeometry.h" #include "core/layout/IntersectionGeometry.h"
#include "core/dom/Element.h"
#include "core/dom/ElementRareData.h"
#include "core/frame/FrameView.h" #include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h" #include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/LayoutBox.h" #include "core/layout/LayoutBox.h"
#include "core/layout/LayoutView.h" #include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutAPIShim.h" #include "core/layout/api/LayoutAPIShim.h"
...@@ -22,10 +21,6 @@ bool isContainingBlockChainDescendant(LayoutObject* descendant, ...@@ -22,10 +21,6 @@ bool isContainingBlockChainDescendant(LayoutObject* descendant,
LayoutObject* ancestor) { LayoutObject* ancestor) {
LocalFrame* ancestorFrame = ancestor->document().frame(); LocalFrame* ancestorFrame = ancestor->document().frame();
LocalFrame* descendantFrame = descendant->document().frame(); LocalFrame* descendantFrame = descendant->document().frame();
if (ancestor->isLayoutView())
return descendantFrame && descendantFrame->tree().top() == ancestorFrame;
if (ancestorFrame != descendantFrame) if (ancestorFrame != descendantFrame)
return false; return false;
...@@ -35,18 +30,19 @@ bool isContainingBlockChainDescendant(LayoutObject* descendant, ...@@ -35,18 +30,19 @@ bool isContainingBlockChainDescendant(LayoutObject* descendant,
} }
void mapRectUpToDocument(LayoutRect& rect, void mapRectUpToDocument(LayoutRect& rect,
const LayoutObject& layoutObject, const LayoutObject& descendant,
const Document& document) { const Document& document) {
FloatQuad mappedQuad = layoutObject.localToAbsoluteQuad( FloatQuad mappedQuad = descendant.localToAncestorQuad(
FloatQuad(FloatRect(rect)), UseTransforms | ApplyContainerFlip); FloatQuad(FloatRect(rect)), document.layoutView(),
UseTransforms | ApplyContainerFlip);
rect = LayoutRect(mappedQuad.boundingBox()); rect = LayoutRect(mappedQuad.boundingBox());
} }
void mapRectDownToDocument(LayoutRect& rect, void mapRectDownToDocument(LayoutRect& rect,
LayoutBoxModelObject& layoutObject, LayoutBoxModelObject* ancestor,
const Document& document) { const Document& document) {
FloatQuad mappedQuad = document.layoutView()->ancestorToLocalQuad( FloatQuad mappedQuad = document.layoutView()->ancestorToLocalQuad(
&layoutObject, FloatQuad(FloatRect(rect)), ancestor, FloatQuad(FloatRect(rect)),
UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries); UseTransforms | ApplyContainerFlip | TraverseDocumentBoundaries);
rect = LayoutRect(mappedQuad.boundingBox()); rect = LayoutRect(mappedQuad.boundingBox());
} }
...@@ -60,62 +56,71 @@ LayoutUnit computeMargin(const Length& length, LayoutUnit referenceLength) { ...@@ -60,62 +56,71 @@ LayoutUnit computeMargin(const Length& length, LayoutUnit referenceLength) {
return LayoutUnit(length.intValue()); return LayoutUnit(length.intValue());
} }
LayoutView* localRootView(Element& element) {
LocalFrame* frame = element.document().frame();
LocalFrame* frameRoot = frame ? frame->localFrameRoot() : nullptr;
return frameRoot ? frameRoot->contentLayoutObject() : nullptr;
}
} // namespace } // namespace
IntersectionGeometry::IntersectionGeometry( IntersectionGeometry::IntersectionGeometry(Element* root,
Node* root, Element& target,
Element* target, const Vector<Length>& rootMargin,
const Vector<Length>& rootMargin, bool shouldReportRootBounds)
ReportRootBounds shouldReportRootBounds) : m_root(root ? root->layoutObject() : localRootView(target)),
: m_root(root), m_target(target.layoutObject()),
m_target(target),
m_rootMargin(rootMargin), m_rootMargin(rootMargin),
m_shouldReportRootBounds(shouldReportRootBounds) { m_doesIntersect(0),
DCHECK(m_target); m_shouldReportRootBounds(shouldReportRootBounds),
DCHECK(rootMargin.isEmpty() || rootMargin.size() == 4); m_rootIsImplicit(!root),
m_canComputeGeometry(initializeCanComputeGeometry(root, target)) {
if (m_canComputeGeometry)
initializeGeometry();
} }
IntersectionGeometry::~IntersectionGeometry() {} IntersectionGeometry::~IntersectionGeometry() {}
Element* IntersectionGeometry::root() const { bool IntersectionGeometry::initializeCanComputeGeometry(Element* root,
if (m_root && !m_root->isDocumentNode()) Element& target) const {
return toElement(m_root); DCHECK(m_rootMargin.isEmpty() || m_rootMargin.size() == 4);
return nullptr; if (root && !root->isConnected())
} return false;
if (!m_root || !m_root->isBox())
LayoutObject* IntersectionGeometry::getRootLayoutObject() const { return false;
DCHECK(m_root); if (!target.isConnected())
if (m_root->isDocumentNode()) { return false;
return LayoutAPIShim::layoutObjectFrom( if (!m_target || (!m_target->isBoxModelObject() && !m_target->isText()))
toDocument(m_root)->layoutViewItem()); return false;
} if (root && !isContainingBlockChainDescendant(m_target, m_root))
return toElement(m_root)->layoutObject(); return false;
return true;
} }
void IntersectionGeometry::initializeGeometry() { void IntersectionGeometry::initializeGeometry() {
initializeTargetRect(); initializeTargetRect();
m_intersectionRect = m_targetRect; m_intersectionRect = m_targetRect;
initializeRootRect(); initializeRootRect();
m_doesIntersect = true;
} }
void IntersectionGeometry::initializeTargetRect() { void IntersectionGeometry::initializeTargetRect() {
LayoutObject* targetLayoutObject = m_target->layoutObject(); m_targetRect =
DCHECK(targetLayoutObject && targetLayoutObject->isBoxModelObject()); LayoutRect(toLayoutBoxModelObject(target())->borderBoundingBox());
m_targetRect = LayoutRect(
toLayoutBoxModelObject(targetLayoutObject)->borderBoundingBox());
} }
void IntersectionGeometry::initializeRootRect() { void IntersectionGeometry::initializeRootRect() {
LayoutObject* rootLayoutObject = getRootLayoutObject(); // TODO(szager): In OOPIF, m_root will be the LayoutView of the
if (rootLayoutObject->isLayoutView()) { // localFrameRoot(). Once viewport intersection support lands,
m_rootRect = LayoutRect( // add a call to mapToVisualRectInAncestorSpace to map the rect up to
toLayoutView(rootLayoutObject)->frameView()->visibleContentRect()); // top-level frame coordinates.
} else if (rootLayoutObject->isBox() && rootLayoutObject->hasOverflowClip()) { if (m_root->isLayoutView()) {
m_rootRect = LayoutRect(toLayoutBox(rootLayoutObject)->contentBoxRect()); m_rootRect =
LayoutRect(toLayoutView(m_root)->frameView()->visibleContentRect());
} else if (m_root->isBox() && m_root->hasOverflowClip()) {
m_rootRect = LayoutRect(toLayoutBox(m_root)->contentBoxRect());
} else { } else {
m_rootRect = LayoutRect( m_rootRect =
toLayoutBoxModelObject(rootLayoutObject)->borderBoundingBox()); LayoutRect(toLayoutBoxModelObject(m_root)->borderBoundingBox());
} }
applyRootMargin(); applyRootMargin();
} }
...@@ -140,102 +145,71 @@ void IntersectionGeometry::applyRootMargin() { ...@@ -140,102 +145,71 @@ void IntersectionGeometry::applyRootMargin() {
void IntersectionGeometry::clipToRoot() { void IntersectionGeometry::clipToRoot() {
// Map and clip rect into root element coordinates. // Map and clip rect into root element coordinates.
// TODO(szager): the writing mode flipping needs a test. // TODO(szager): the writing mode flipping needs a test.
LayoutBox* rootLayoutObject = toLayoutBox(getRootLayoutObject()); // TODO(szager): Once the OOPIF viewport intersection code lands,
LayoutObject* targetLayoutObject = m_target->layoutObject(); // use nullptr for ancestor to map to the top frame.
LayoutBox* ancestor = toLayoutBox(m_root);
m_doesIntersect = targetLayoutObject->mapToVisualRectInAncestorSpace( m_doesIntersect = m_target->mapToVisualRectInAncestorSpace(
rootLayoutObject, m_intersectionRect, EdgeInclusive); ancestor, m_intersectionRect, EdgeInclusive);
if (rootLayoutObject->hasOverflowClip()) if (ancestor && ancestor->hasOverflowClip())
m_intersectionRect.move(-rootLayoutObject->scrolledContentOffset()); m_intersectionRect.move(-ancestor->scrolledContentOffset());
if (!m_doesIntersect) if (!m_doesIntersect)
return; return;
LayoutRect rootClipRect(m_rootRect); LayoutRect rootClipRect(m_rootRect);
rootLayoutObject->flipForWritingMode(rootClipRect); if (ancestor)
ancestor->flipForWritingMode(rootClipRect);
m_doesIntersect &= m_intersectionRect.inclusiveIntersect(rootClipRect); m_doesIntersect &= m_intersectionRect.inclusiveIntersect(rootClipRect);
} }
void IntersectionGeometry::mapTargetRectToTargetFrameCoordinates() { void IntersectionGeometry::mapTargetRectToTargetFrameCoordinates() {
LayoutObject& targetLayoutObject = *m_target->layoutObject();
Document& targetDocument = m_target->document(); Document& targetDocument = m_target->document();
LayoutSize scrollPosition = LayoutSize scrollPosition =
LayoutSize(targetDocument.view()->getScrollOffset()); LayoutSize(targetDocument.view()->getScrollOffset());
mapRectUpToDocument(m_targetRect, targetLayoutObject, targetDocument); mapRectUpToDocument(m_targetRect, *m_target, targetDocument);
m_targetRect.move(-scrollPosition); m_targetRect.move(-scrollPosition);
} }
void IntersectionGeometry::mapRootRectToRootFrameCoordinates() { void IntersectionGeometry::mapRootRectToRootFrameCoordinates() {
LayoutObject& rootLayoutObject = *getRootLayoutObject(); Document& rootDocument = m_root->document();
Document& rootDocument = rootLayoutObject.document(); if (!rootIsImplicit())
mapRectUpToDocument(m_rootRect, *m_root, rootDocument);
// TODO(szager): When OOPIF support lands, this scroll offset adjustment
// will probably be wrong.
LayoutSize scrollPosition = LayoutSize scrollPosition =
LayoutSize(rootDocument.view()->getScrollOffset()); LayoutSize(rootDocument.view()->getScrollOffset());
mapRectUpToDocument(m_rootRect, rootLayoutObject,
rootLayoutObject.document());
m_rootRect.move(-scrollPosition); m_rootRect.move(-scrollPosition);
} }
void IntersectionGeometry::mapRootRectToTargetFrameCoordinates() { void IntersectionGeometry::mapIntersectionRectToTargetFrameCoordinates() {
LayoutObject& rootLayoutObject = *getRootLayoutObject();
Document& targetDocument = m_target->document(); Document& targetDocument = m_target->document();
LayoutSize scrollPosition = if (rootIsImplicit()) {
LayoutSize(targetDocument.view()->getScrollOffset()); LocalFrame* targetFrame = targetDocument.frame();
Frame* rootFrame = targetFrame->tree().top();
if (&targetDocument == &rootLayoutObject.document()) { LayoutSize scrollPosition =
mapRectUpToDocument(m_intersectionRect, rootLayoutObject, targetDocument); LayoutSize(targetDocument.view()->getScrollOffset());
if (targetFrame != rootFrame)
mapRectDownToDocument(m_intersectionRect, nullptr, targetDocument);
m_intersectionRect.move(-scrollPosition);
} else { } else {
mapRectDownToDocument(m_intersectionRect, LayoutSize scrollPosition =
toLayoutBoxModelObject(rootLayoutObject), LayoutSize(targetDocument.view()->getScrollOffset());
targetDocument); mapRectUpToDocument(m_intersectionRect, *m_root, m_root->document());
m_intersectionRect.move(-scrollPosition);
} }
m_intersectionRect.move(-scrollPosition);
} }
void IntersectionGeometry::computeGeometry() { void IntersectionGeometry::computeGeometry() {
// In the first few lines here, before initializeGeometry is called, "return if (!canComputeGeometry())
// true" effectively means "if the previous observed state was that root and
// target were intersecting, then generate a notification indicating that they
// are no longer intersecting." This happens, for example, when root or
// target is removed from the DOM tree and not reinserted before the next
// frame is generated, or display:none is set on the root or target.
if (!m_target->isConnected())
return;
Element* rootElement = root();
if (rootElement && !rootElement->isConnected())
return;
LayoutObject* rootLayoutObject = getRootLayoutObject();
if (!rootLayoutObject || !rootLayoutObject->isBoxModelObject())
return;
// TODO(szager): Support SVG
LayoutObject* targetLayoutObject = m_target->layoutObject();
if (!targetLayoutObject)
return;
if (!targetLayoutObject->isBoxModelObject() && !targetLayoutObject->isText())
return;
if (!isContainingBlockChainDescendant(targetLayoutObject, rootLayoutObject))
return; return;
initializeGeometry();
clipToRoot(); clipToRoot();
mapTargetRectToTargetFrameCoordinates(); mapTargetRectToTargetFrameCoordinates();
if (m_doesIntersect) if (m_doesIntersect)
mapRootRectToTargetFrameCoordinates(); mapIntersectionRectToTargetFrameCoordinates();
else else
m_intersectionRect = LayoutRect(); m_intersectionRect = LayoutRect();
// Small optimization: if we're not going to report root bounds, don't bother // Small optimization: if we're not going to report root bounds, don't bother
// transforming them to the frame. // transforming them to the frame.
if (m_shouldReportRootBounds == ReportRootBounds::kShouldReportRootBounds) if (shouldReportRootBounds())
mapRootRectToRootFrameCoordinates(); mapRootRectToRootFrameCoordinates();
} }
DEFINE_TRACE(IntersectionGeometry) {
visitor->trace(m_root);
visitor->trace(m_target);
}
} // namespace blink } // namespace blink
...@@ -12,28 +12,38 @@ ...@@ -12,28 +12,38 @@
namespace blink { namespace blink {
class Node;
class Element; class Element;
class LayoutObject; class LayoutObject;
class IntersectionGeometry final // Computes the intersection between an ancestor (root) element and a
: public GarbageCollectedFinalized<IntersectionGeometry> { // descendant (target) element, with overflow and CSS clipping applied, but not
// paint occlusion.
//
// If the root argument to the constructor is null, computes the intersection
// of the target with the top-level frame viewport (AKA the "implicit root").
class IntersectionGeometry {
STACK_ALLOCATED()
public: public:
enum ReportRootBounds { IntersectionGeometry(Element* root,
kShouldReportRootBounds, Element& target,
kShouldNotReportRootBounds,
};
IntersectionGeometry(Node* root,
Element* target,
const Vector<Length>& rootMargin, const Vector<Length>& rootMargin,
ReportRootBounds shouldReportRootBounds); bool shouldReportRootBounds);
~IntersectionGeometry(); ~IntersectionGeometry();
void computeGeometry(); void computeGeometry();
LayoutObject* root() const { return m_root; }
LayoutObject* target() const { return m_target; }
// Client rect in the coordinate system of the frame containing target.
LayoutRect targetRect() const { return m_targetRect; } LayoutRect targetRect() const { return m_targetRect; }
// Client rect in the coordinate system of the frame containing target.
LayoutRect intersectionRect() const { return m_intersectionRect; } LayoutRect intersectionRect() const { return m_intersectionRect; }
// Client rect in the coordinate system of the frame containing root.
LayoutRect rootRect() const { return m_rootRect; } LayoutRect rootRect() const { return m_rootRect; }
bool doesIntersect() const { return m_doesIntersect; } bool doesIntersect() const { return m_doesIntersect; }
IntRect intersectionIntRect() const { IntRect intersectionIntRect() const {
...@@ -44,28 +54,33 @@ class IntersectionGeometry final ...@@ -44,28 +54,33 @@ class IntersectionGeometry final
IntRect rootIntRect() const { return pixelSnappedIntRect(m_rootRect); } IntRect rootIntRect() const { return pixelSnappedIntRect(m_rootRect); }
DECLARE_TRACE();
private: private:
bool initializeCanComputeGeometry(Element* root, Element& target) const;
void initializeGeometry(); void initializeGeometry();
void initializeTargetRect(); void initializeTargetRect();
void initializeRootRect(); void initializeRootRect();
void clipToRoot(); void clipToRoot();
void mapTargetRectToTargetFrameCoordinates(); void mapTargetRectToTargetFrameCoordinates();
void mapRootRectToRootFrameCoordinates(); void mapRootRectToRootFrameCoordinates();
void mapRootRectToTargetFrameCoordinates(); void mapIntersectionRectToTargetFrameCoordinates();
Element* root() const;
LayoutObject* getRootLayoutObject() const;
void applyRootMargin(); void applyRootMargin();
Member<Node> m_root; // Returns true iff it's possible to compute an intersection between root
Member<Element> m_target; // and target.
bool canComputeGeometry() const { return m_canComputeGeometry; }
bool rootIsImplicit() const { return m_rootIsImplicit; }
bool shouldReportRootBounds() const { return m_shouldReportRootBounds; }
LayoutObject* m_root;
LayoutObject* m_target;
const Vector<Length> m_rootMargin; const Vector<Length> m_rootMargin;
const ReportRootBounds m_shouldReportRootBounds;
LayoutRect m_targetRect; LayoutRect m_targetRect;
LayoutRect m_intersectionRect; LayoutRect m_intersectionRect;
LayoutRect m_rootRect; LayoutRect m_rootRect;
bool m_doesIntersect = false; unsigned m_doesIntersect : 1;
const unsigned m_shouldReportRootBounds : 1;
const unsigned m_rootIsImplicit : 1;
const unsigned m_canComputeGeometry : 1;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment