diff options
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.cc | 105 |
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. |