summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc105
1 files changed, 61 insertions, 44 deletions
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
index eef6e1da665..b54140b258b 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_geometry.cc
@@ -51,34 +51,72 @@ LayoutUnit ComputeMargin(const Length& length,
}
// Expand rect by the given margin values.
-void ApplyRootMargin(PhysicalRect& rect,
- const Vector<Length>& margin,
- float zoom) {
+void ApplyMargin(
+ PhysicalRect& expand_rect,
+ const Vector<Length>& margin,
+ float zoom,
+ const base::Optional<PhysicalRect>& resolution_rect = base::nullopt) {
if (margin.IsEmpty())
return;
// TODO(szager): Make sure the spec is clear that left/right margins are
// resolved against width and not height.
+ const PhysicalRect& rect = resolution_rect.value_or(expand_rect);
LayoutRectOutsets outsets(ComputeMargin(margin[0], rect.Height(), zoom),
ComputeMargin(margin[1], rect.Width(), zoom),
ComputeMargin(margin[2], rect.Height(), zoom),
ComputeMargin(margin[3], rect.Width(), zoom));
- rect.Expand(outsets);
+ expand_rect.Expand(outsets);
+}
+
+// Returns the root intersect rect for the given root object, with the given
+// margins applied, in the coordinate system of the root object.
+//
+// https://w3c.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
+PhysicalRect InitializeRootRect(const LayoutObject* root,
+ const Vector<Length>& margin) {
+ DCHECK(margin.IsEmpty() || margin.size() == 4);
+ PhysicalRect result;
+ auto* layout_view = DynamicTo<LayoutView>(root);
+ if (layout_view && root->GetDocument().IsInMainFrame()) {
+ // The main frame is a bit special as the scrolling viewport can differ in
+ // size from the LayoutView itself. There's two situations this occurs in:
+ // 1) The ForceZeroLayoutHeight quirk setting is used in Android WebView for
+ // compatibility and sets the initial-containing-block's (a.k.a.
+ // LayoutView) height to 0. Thus, we can't use its size for intersection
+ // testing. Use the FrameView geometry instead.
+ // 2) An element wider than the ICB can cause us to resize the FrameView so
+ // we can zoom out to fit the entire element width.
+ result = layout_view->OverflowClipRect(PhysicalOffset());
+ } else if (root->IsBox() && root->HasOverflowClip()) {
+ result = ToLayoutBox(root)->PhysicalContentBoxRect();
+ } else {
+ result = PhysicalRect(ToLayoutBoxModelObject(root)->BorderBoundingBox());
+ }
+ ApplyMargin(result, margin, root->StyleRef().EffectiveZoom());
+ return result;
}
// Return the bounding box of target in target's own coordinate system
-PhysicalRect InitializeTargetRect(const LayoutObject* target, unsigned flags) {
+PhysicalRect InitializeTargetRect(const LayoutObject* target,
+ unsigned flags,
+ const Vector<Length>& margin,
+ const LayoutObject* root) {
+ PhysicalRect result;
if ((flags & IntersectionGeometry::kShouldUseReplacedContentRect) &&
target->IsLayoutEmbeddedContent()) {
- return ToLayoutEmbeddedContent(target)->ReplacedContentRect();
- }
- if (target->IsBox())
- return PhysicalRect(ToLayoutBoxModelObject(target)->BorderBoundingBox());
- if (target->IsLayoutInline()) {
- return target->AbsoluteToLocalRect(
+ result = ToLayoutEmbeddedContent(target)->ReplacedContentRect();
+ } else if (target->IsBox()) {
+ result = PhysicalRect(ToLayoutBoxModelObject(target)->BorderBoundingBox());
+ } else if (target->IsLayoutInline()) {
+ result = target->AbsoluteToLocalRect(
PhysicalRect::EnclosingRect(target->AbsoluteBoundingBoxFloatRect()));
+ } else {
+ result = ToLayoutText(target)->PhysicalLinesBoundingBox();
}
- return ToLayoutText(target)->PhysicalLinesBoundingBox();
+ ApplyMargin(result, margin, root->StyleRef().EffectiveZoom(),
+ InitializeRootRect(root, {} /* margin */));
+ return result;
}
// Return the local frame root for a given object
@@ -93,7 +131,6 @@ LayoutView* LocalRootView(const LayoutObject& object) {
//
// https://w3c.github.io/IntersectionObserver/v2/#calculate-visibility-algo
bool ComputeIsVisible(const LayoutObject* target, const PhysicalRect& rect) {
- DCHECK(RuntimeEnabledFeatures::IntersectionObserverV2Enabled());
if (target->GetDocument().GetFrame()->LocalFrameRoot().GetOcclusionState() !=
FrameOcclusionState::kGuaranteedNotOccluded) {
return false;
@@ -114,34 +151,6 @@ bool ComputeIsVisible(const LayoutObject* target, const PhysicalRect& rect) {
return false;
}
-// Returns the root intersect rect for the given root object, with the given
-// margins applied, in the coordinate system of the root object.
-//
-// https://w3c.github.io/IntersectionObserver/#intersectionobserver-root-intersection-rectangle
-PhysicalRect InitializeRootRect(const LayoutObject* root,
- const Vector<Length>& margin) {
- DCHECK(margin.IsEmpty() || margin.size() == 4);
- PhysicalRect result;
- auto* layout_view = DynamicTo<LayoutView>(root);
- if (layout_view && root->GetDocument().IsInMainFrame()) {
- // The main frame is a bit special as the scrolling viewport can differ in
- // size from the LayoutView itself. There's two situations this occurs in:
- // 1) The ForceZeroLayoutHeight quirk setting is used in Android WebView for
- // compatibility and sets the initial-containing-block's (a.k.a.
- // LayoutView) height to 0. Thus, we can't use its size for intersection
- // testing. Use the FrameView geometry instead.
- // 2) An element wider than the ICB can cause us to resize the FrameView so
- // we can zoom out to fit the entire element width.
- result = layout_view->OverflowClipRect(PhysicalOffset());
- } else if (root->IsBox() && root->HasOverflowClip()) {
- result = ToLayoutBox(root)->PhysicalContentBoxRect();
- } else {
- result = PhysicalRect(ToLayoutBoxModelObject(root)->BorderBoundingBox());
- }
- ApplyRootMargin(result, margin, root->StyleRef().EffectiveZoom());
- return result;
-}
-
// Validates the given target element and returns its LayoutObject
LayoutObject* GetTargetLayoutObject(const Element& target_element) {
if (!target_element.isConnected())
@@ -224,11 +233,15 @@ IntersectionGeometry::IntersectionGeometry(const Node* root_node,
const Element& target_element,
const Vector<Length>& root_margin,
const Vector<float>& thresholds,
+ const Vector<Length>& target_margin,
unsigned flags,
CachedRects* cached_rects)
: flags_(flags & kConstructorFlagsMask),
intersection_ratio_(0),
threshold_index_(0) {
+ // Only one of root_margin or target_margin can be specified.
+ DCHECK(root_margin.IsEmpty() || target_margin.IsEmpty());
+
if (cached_rects)
cached_rects->valid = false;
if (!root_node)
@@ -241,13 +254,15 @@ IntersectionGeometry::IntersectionGeometry(const Node* root_node,
if (!root)
return;
RootGeometry root_geometry(root, root_margin);
- ComputeGeometry(root_geometry, root, target, thresholds, cached_rects);
+ ComputeGeometry(root_geometry, root, target, thresholds, target_margin,
+ cached_rects);
}
IntersectionGeometry::IntersectionGeometry(const RootGeometry& root_geometry,
const Node& explicit_root,
const Element& target_element,
const Vector<float>& thresholds,
+ const Vector<Length>& target_margin,
unsigned flags,
CachedRects* cached_rects)
: flags_(flags & kConstructorFlagsMask),
@@ -262,13 +277,15 @@ IntersectionGeometry::IntersectionGeometry(const RootGeometry& root_geometry,
&explicit_root, target, !ShouldUseCachedRects());
if (!root)
return;
- ComputeGeometry(root_geometry, root, target, thresholds, cached_rects);
+ ComputeGeometry(root_geometry, root, target, thresholds, target_margin,
+ cached_rects);
}
void IntersectionGeometry::ComputeGeometry(const RootGeometry& root_geometry,
const LayoutObject* root,
const LayoutObject* target,
const Vector<float>& thresholds,
+ const Vector<Length>& target_margin,
CachedRects* cached_rects) {
DCHECK(cached_rects || !ShouldUseCachedRects());
// Initially:
@@ -284,7 +301,7 @@ void IntersectionGeometry::ComputeGeometry(const RootGeometry& root_geometry,
unclipped_intersection_rect_ =
cached_rects->unscrolled_unclipped_intersection_rect;
} else {
- target_rect_ = InitializeTargetRect(target, flags_);
+ target_rect_ = InitializeTargetRect(target, flags_, target_margin, root);
// We have to map/clip target_rect_ up to the root, so we begin with the
// intersection rect in target's coordinate system. After ClipToRoot, it
// will be in root's coordinate system.