From b19cea8da334391dc1a51e2d386b10b25e354a69 Mon Sep 17 00:00:00 2001 From: Chris Harrelson Date: Sat, 14 Apr 2018 00:19:40 +0000 Subject: [PATCH] [SPv175] Fix hittesting of under non-identity SVG-related transform If the SVG to border box transform or any other transform in SVG above is non-identity, then hit testing of the and content below it is incorrect, because it does not take into account such transforms. Before SPv175 + as stacking context, content underneath the did not paint with the correct sizing either, which hid this bug to some extent. To make this work requires a little bit of special-casing of foreignObject, because of the quirk that its location offset is applied *after* transform, not before. Bug: 820482,831591 Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2 Change-Id: Ided2b46f2ea12dd61c254892f5fbabb821f6229e Reviewed-on: https://chromium-review.googlesource.com/974568 Reviewed-by: Philip Rogers Commit-Queue: Chris Harrelson Cr-Commit-Position: refs/heads/master@{#550825} --- .../svg/transform-foreign-object-expected.txt | 4 +- .../svg/transform-foreign-object-expected.txt | 4 +- .../renderer/core/layout/layout_object.cc | 8 ++ .../renderer/core/layout/layout_object.h | 13 ++- .../core/layout/svg/layout_svg_container.cc | 4 + .../layout/svg/layout_svg_foreign_object.cc | 20 +++- .../layout/svg/layout_svg_foreign_object.h | 8 ++ .../svg/layout_svg_foreign_object_test.cc | 97 ++++++++++++++++++- .../layout/svg/layout_svg_resource_clipper.cc | 6 ++ .../core/layout/svg/layout_svg_root.cc | 3 + .../core/layout/svg/svg_layout_support.cc | 2 +- .../core/layout/svg/svg_layout_support.h | 4 + .../blink/renderer/core/paint/paint_layer.cc | 43 ++++++-- .../blink/renderer/core/paint/paint_layer.h | 1 + .../core/paint/svg_foreign_object_painter.cc | 12 ++- 15 files changed, 196 insertions(+), 33 deletions(-) diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/transform-foreign-object-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/transform-foreign-object-expected.txt index 027be0738ae2e..724e1420d8906 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/transform-foreign-object-expected.txt +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/svg/transform-foreign-object-expected.txt @@ -9,12 +9,12 @@ { "object": "LayoutSVGForeignObject foreignObject", "rect": [108, 8, 100, 100], - "reason": "appeared" + "reason": "paint property change" }, { "object": "LayoutSVGForeignObject foreignObject", "rect": [8, 8, 100, 100], - "reason": "disappeared" + "reason": "paint property change" } ] } diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/svg/transform-foreign-object-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/svg/transform-foreign-object-expected.txt index 4cc12b425055a..c0ae671e50167 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/svg/transform-foreign-object-expected.txt +++ b/third_party/WebKit/LayoutTests/paint/invalidation/svg/transform-foreign-object-expected.txt @@ -20,12 +20,12 @@ { "object": "LayoutSVGForeignObject foreignObject", "rect": [108, 8, 100, 100], - "reason": "appeared" + "reason": "paint property change" }, { "object": "LayoutSVGForeignObject foreignObject", "rect": [8, 8, 100, 100], - "reason": "disappeared" + "reason": "paint property change" } ] } diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 543819dec5d07..aab408d90d31d 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc @@ -2598,6 +2598,14 @@ void LayoutObject::GetTransformFromContainer( if (layer && layer->Transform()) transform.Multiply(layer->CurrentTransform()); + GetTransformFromContainerInternal(container_object, offset_in_container, + transform); +} + +void LayoutObject::GetTransformFromContainerInternal( + const LayoutObject* container_object, + const LayoutSize& offset_in_container, + TransformationMatrix& transform) const { transform.PostTranslate(offset_in_container.Width().ToFloat(), offset_in_container.Height().ToFloat()); diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 2358af94fb41a..704f3c6bc20de 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h @@ -1621,10 +1621,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver, const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap&) const; - bool ShouldUseTransformFromContainer(const LayoutObject* container) const; - void GetTransformFromContainer(const LayoutObject* container, - const LayoutSize& offset_in_container, - TransformationMatrix&) const; + virtual bool ShouldUseTransformFromContainer( + const LayoutObject* container) const; + virtual void GetTransformFromContainer(const LayoutObject* container, + const LayoutSize& offset_in_container, + TransformationMatrix&) const; bool CreatesGroup() const { return IsTransparent() || HasMask() || HasClipPath() || @@ -2054,6 +2055,10 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver, // changes at all). virtual bool AnonymousHasStylePropagationOverride() { return false; } + void GetTransformFromContainerInternal(const LayoutObject* container, + const LayoutSize& offset_in_container, + TransformationMatrix&) const; + // A fast path for MapToVisualRectInAncestorSpace for when GeometryMapper // can be used. bool MapToVisualRectInAncestorSpaceInternalFastPath( diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc index fa11a5a80209a..8b27cbe5ea596 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc @@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "third_party/blink/renderer/core/layout/layout_analyzer.h" +#include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h" @@ -191,6 +192,9 @@ bool LayoutSVGContainer::NodeAtFloatPoint(HitTestResult& result, for (LayoutObject* child = LastChild(); child; child = child->PreviousSibling()) { + if (child->IsBoxModelObject() && + ToLayoutBoxModelObject(child)->HasSelfPaintingLayer()) + continue; if (child->NodeAtFloatPoint(result, local_point, hit_test_action)) { const LayoutPoint& local_layout_point = LayoutPoint(local_point); UpdateHitTestResult(result, local_layout_point); diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc index 2ffeab0ad6671..6c83ce379a7f7 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc @@ -127,10 +127,10 @@ void LayoutSVGForeignObject::UpdateLayout() { bool LayoutSVGForeignObject::NodeAtFloatPoint(HitTestResult& result, const FloatPoint& point_in_parent, HitTestAction hit_test_action) { - // Embedded content is drawn in the foreground phase. - if (hit_test_action != kHitTestForeground) + if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + NOTREACHED(); return false; - + } AffineTransform local_transform = LocalSVGTransform(); if (!local_transform.IsInvertible()) return false; @@ -152,14 +152,24 @@ bool LayoutSVGForeignObject::NodeAtFloatPoint(HitTestResult& result, kHitTestChildBlockBackgrounds); } +void LayoutSVGForeignObject::GetTransformFromContainer( + const LayoutObject* container, + const LayoutSize& offset_in_container, + TransformationMatrix& matrix) const { + AffineTransform to_svg_root_transform; + SVGLayoutSupport::ComputeTransformToSVGRoot(*this, to_svg_root_transform); + matrix = to_svg_root_transform; + GetTransformFromContainerInternal(container, offset_in_container, matrix); +} + bool LayoutSVGForeignObject::NodeAtPoint( HitTestResult& result, const HitTestLocation& location_in_parent, const LayoutPoint& accumulated_offset, HitTestAction hit_test_action) { if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { - return NodeAtFloatPoint(result, FloatPoint(accumulated_offset), - hit_test_action); + return LayoutBlock::NodeAtPoint(result, location_in_parent, + accumulated_offset, hit_test_action); } NOTREACHED(); return false; diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h index 76ce9cdfd5fe7..78d8f07e3fb8a 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h @@ -60,6 +60,14 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock { return ObjectBoundingBox(); } + bool ShouldUseTransformFromContainer( + const LayoutObject* container) const override { + return true; + } + void GetTransformFromContainer(const LayoutObject* container, + const LayoutSize& offset_in_container, + TransformationMatrix&) const override; + bool NodeAtPoint(HitTestResult&, const HitTestLocation&, const LayoutPoint&, diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc index f3a6ac507e509..f0a03fbfc16a1 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc @@ -34,6 +34,7 @@ TEST_F(LayoutSVGForeignObjectTest, DivInForeignObject) { )HTML"); const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); const auto& foreign_object = *GetLayoutObjectByElementId("foreign"); const auto& div = *GetLayoutObjectByElementId("div"); @@ -69,10 +70,12 @@ TEST_F(LayoutSVGForeignObjectTest, DivInForeignObject) { rgm.MapToAncestor(FloatRect(0, 0, 1, 2), nullptr)); // Hit testing - EXPECT_EQ(svg, HitTest(149, 149)); + EXPECT_EQ(svg, HitTest(1, 1)); + EXPECT_EQ(foreign, HitTest(149, 149)); EXPECT_EQ(div.GetNode(), HitTest(150, 150)); EXPECT_EQ(div.GetNode(), HitTest(349, 249)); - EXPECT_EQ(svg, HitTest(350, 250)); + EXPECT_EQ(foreign, HitTest(350, 250)); + EXPECT_EQ(svg, HitTest(450, 350)); } TEST_F(LayoutSVGForeignObjectTest, IframeInForeignObject) { @@ -95,6 +98,7 @@ TEST_F(LayoutSVGForeignObjectTest, IframeInForeignObject) { GetDocument().View()->UpdateAllLifecyclePhases(); const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); const auto& foreign_object = *GetLayoutObjectByElementId("foreign"); const auto& div = *ChildDocument().getElementById("div")->GetLayoutObject(); @@ -130,14 +134,99 @@ TEST_F(LayoutSVGForeignObjectTest, IframeInForeignObject) { rgm.MapToAncestor(FloatRect(0, 0, 1, 2), nullptr)); // Hit testing - EXPECT_EQ(svg, HitTest(129, 129)); + EXPECT_EQ(svg, HitTest(90, 90)); + EXPECT_EQ(foreign, HitTest(129, 129)); EXPECT_EQ(ChildDocument().documentElement(), HitTest(130, 130)); EXPECT_EQ(ChildDocument().documentElement(), HitTest(199, 199)); EXPECT_EQ(div.GetNode(), HitTest(200, 200)); EXPECT_EQ(div.GetNode(), HitTest(299, 249)); EXPECT_EQ(ChildDocument().documentElement(), HitTest(300, 250)); EXPECT_EQ(ChildDocument().documentElement(), HitTest(369, 319)); - EXPECT_EQ(svg, HitTest(370, 320)); + EXPECT_EQ(foreign, HitTest(370, 320)); + EXPECT_EQ(svg, HitTest(450, 400)); +} + +TEST_F(LayoutSVGForeignObjectTest, HitTestZoomedForeignObject) { + SetBodyInnerHTML(R"HTML( + + + +
+
+
+
+ )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); + const auto& foreign_object = *GetLayoutObjectByElementId("foreign"); + const auto& div = *GetDocument().getElementById("div"); + + EXPECT_EQ(FloatRect(10, 10, 100, 150), foreign_object.ObjectBoundingBox()); + EXPECT_EQ(AffineTransform(), foreign_object.LocalSVGTransform()); + EXPECT_EQ(AffineTransform(), foreign_object.LocalToSVGParentTransform()); + + // mapToVisualRectInAncestorSpace + LayoutRect div_rect(0, 0, 100, 50); + EXPECT_TRUE(div.GetLayoutObject()->MapToVisualRectInAncestorSpace( + &GetLayoutView(), div_rect)); + EXPECT_EQ(LayoutRect(286, 286, 339, 170), div_rect); + + // mapLocalToAncestor + TransformState transform_state(TransformState::kApplyTransformDirection, + FloatPoint()); + div.GetLayoutObject()->MapLocalToAncestor(&GetLayoutView(), transform_state, + kTraverseDocumentBoundaries); + transform_state.Flatten(); + EXPECT_EQ(FloatPoint(286.875, 286.875), transform_state.LastPlanarPoint()); + + // mapAncestorToLocal + TransformState transform_state1( + TransformState::kUnapplyInverseTransformDirection, + FloatPoint(286.875, 286.875)); + div.GetLayoutObject()->MapAncestorToLocal(&GetLayoutView(), transform_state1, + kTraverseDocumentBoundaries); + transform_state1.Flatten(); + EXPECT_EQ(FloatPoint(), transform_state1.LastPlanarPoint()); + + EXPECT_EQ(svg, HitTest(20, 20)); + EXPECT_EQ(foreign, HitTest(280, 280)); + EXPECT_EQ(div, HitTest(290, 290)); +} + +TEST_F(LayoutSVGForeignObjectTest, HitTestViewBoxForeignObject) { + SetBodyInnerHTML(R"HTML( + + +
+
+
+
+ )HTML"); + + const auto& svg = *GetDocument().getElementById("svg"); + const auto& foreign = *GetDocument().getElementById("foreign"); + const auto& div = *GetDocument().getElementById("div"); + + // mapLocalToAncestor + TransformState transform_state(TransformState::kApplyTransformDirection, + FloatPoint()); + div.GetLayoutObject()->MapLocalToAncestor(&GetLayoutView(), transform_state, + kTraverseDocumentBoundaries); + transform_state.Flatten(); + EXPECT_EQ(FloatPoint(128, 128), transform_state.LastPlanarPoint()); + + // mapAncestorToLocal + TransformState transform_state1( + TransformState::kUnapplyInverseTransformDirection, FloatPoint(128, 128)); + div.GetLayoutObject()->MapAncestorToLocal(&GetLayoutView(), transform_state1, + kTraverseDocumentBoundaries); + transform_state1.Flatten(); + EXPECT_EQ(FloatPoint(), transform_state1.LastPlanarPoint()); + + EXPECT_EQ(svg, HitTest(20, 20)); + EXPECT_EQ(foreign, HitTest(120, 110)); + EXPECT_EQ(div, HitTest(160, 160)); } } // namespace blink diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc index 1a0eeaf7eab08..9e361f0ccacee 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc @@ -24,6 +24,7 @@ #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/layout/hit_test_result.h" +#include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h" #include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/svg/svg_geometry_element.h" @@ -243,6 +244,11 @@ bool LayoutSVGResourceClipper::HitTestClipContent( IntPoint hit_point; HitTestResult result(HitTestRequest::kSVGClipContent, hit_point); LayoutObject* layout_object = child_element.GetLayoutObject(); + + if (layout_object->IsBoxModelObject() && + ToLayoutBoxModelObject(layout_object)->HasSelfPaintingLayer()) + continue; + if (layout_object->NodeAtFloatPoint(result, point, kHitTestForeground)) return true; } diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index f35b4a16e3600..057c364d35f1a 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc @@ -513,6 +513,9 @@ bool LayoutSVGRoot::NodeAtPoint(HitTestResult& result, for (LayoutObject* child = LastChild(); child; child = child->PreviousSibling()) { + if (child->IsBoxModelObject() && + ToLayoutBoxModelObject(child)->HasSelfPaintingLayer()) + continue; // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet. if (child->NodeAtFloatPoint(result, local_point, hit_test_action)) { UpdateHitTestResult(result, point_in_border_box); diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc index 10e7e46daad78..b37d9a1e270a2 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc +++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc @@ -94,7 +94,7 @@ LayoutRect SVGLayoutSupport::TransformVisualRect( return LayoutRect(EnclosingIntRect(adjusted_rect)); } -static const LayoutSVGRoot& ComputeTransformToSVGRoot( +const LayoutSVGRoot& SVGLayoutSupport::ComputeTransformToSVGRoot( const LayoutObject& object, AffineTransform& root_border_box_transform) { DCHECK(object.IsSVGChild()); diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h index dbc43c74fee32..b055793af1f01 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_layout_support.h +++ b/third_party/blink/renderer/core/layout/svg/svg_layout_support.h @@ -153,6 +153,10 @@ class CORE_EXPORT SVGLayoutSupport { static LayoutObject* FindClosestLayoutSVGText(const LayoutObject*, const FloatPoint&); + static const LayoutSVGRoot& ComputeTransformToSVGRoot( + const LayoutObject& object, + AffineTransform& root_border_box_transform); + private: static void UpdateObjectBoundingBox(FloatRect& object_bounding_box, bool& object_bounding_box_valid, diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index c71636c1530b2..d476b10481d26 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc @@ -1851,6 +1851,16 @@ scoped_refptr PaintLayer::CreateLocalTransformState( ConvertToLayerCoords(root_layer, offset); } offset.MoveBy(translation_offset); + // The location of a foreignObject element is added *after* transform, not + // before (all SVG child elements have this behavior). Therefore, remove + // the offset here to avoid applying it before the transform. It will be + // added later. + // TODO(chrishtr): this ugliness can be removed if we change the code to + // to be based on PaintOffset rather than PaintLayer offsets, like the + // paint code does. This is a larger effort though, that involves using + // property trees to drive hit testing coordinate spaces. + if (GetLayoutObject().IsSVGForeignObject()) + offset.MoveBy(-LayoutBoxLocation()); LayoutObject* container_layout_object = container_layer ? &container_layer->GetLayoutObject() : nullptr; @@ -1928,8 +1938,14 @@ PaintLayer* PaintLayer::HitTestLayer( if (result.GetHitTestRequest().IgnoreClipping()) clip_behavior = kIgnoreOverflowClip; + // Always send foreignObject PaintLayers through the "transform" code path, + // even if they have no transform. This is in order to collect any ancestor + // SVG transforms, including the SVG root to border box transform, which + // are represented outside of the PaintLayer tree. + bool use_transform = Transform() || GetLayoutObject().IsSVGForeignObject(); + // Apply a transform if we have one. - if (Transform() && !applied_transform) { + if (use_transform && !applied_transform) { if (EnclosingPaginationLayer()) { return HitTestTransformedLayerInFragments( root_layer, container_layer, result, hit_test_rect, hit_test_location, @@ -2065,6 +2081,12 @@ PaintLayer* PaintLayer::HitTestLayer( return this; } + LayoutPoint offset = -LayoutBoxLocation(); + // See comment in CreateLocalTransformState. The code here is + // where we re-add the location. + if (root_layer->GetLayoutObject().IsSVGForeignObject()) + offset.MoveBy(root_layer->LayoutBoxLocation()); + // Next we want to see if the mouse pos is inside the child LayoutObjects of // the layer. Check every fragment in reverse order. if (IsSelfPaintingLayer()) { @@ -2073,7 +2095,8 @@ PaintLayer* PaintLayer::HitTestLayer( HitTestResult temp_result(result.GetHitTestRequest(), result.GetHitTestLocation()); bool inside_fragment_foreground_rect = false; - if (HitTestContentsForFragments(layer_fragments, temp_result, + + if (HitTestContentsForFragments(layer_fragments, offset, temp_result, hit_test_location, kHitTestDescendants, inside_fragment_foreground_rect) && IsHitCandidate(this, false, z_offset_for_contents_ptr, @@ -2114,7 +2137,7 @@ PaintLayer* PaintLayer::HitTestLayer( HitTestResult temp_result(result.GetHitTestRequest(), result.GetHitTestLocation()); bool inside_fragment_background_rect = false; - if (HitTestContentsForFragments(layer_fragments, temp_result, + if (HitTestContentsForFragments(layer_fragments, offset, temp_result, hit_test_location, kHitTestSelf, inside_fragment_background_rect) && IsHitCandidate(this, false, z_offset_for_contents_ptr, @@ -2135,6 +2158,7 @@ PaintLayer* PaintLayer::HitTestLayer( bool PaintLayer::HitTestContentsForFragments( const PaintLayerFragments& layer_fragments, + const LayoutPoint& offset, HitTestResult& result, const HitTestLocation& hit_test_location, HitTestFilter hit_test_filter, @@ -2150,8 +2174,10 @@ bool PaintLayer::HitTestContentsForFragments( !fragment.foreground_rect.Intersects(hit_test_location))) continue; inside_clip_rect = true; - if (HitTestContents(result, fragment.layer_bounds.Location(), - hit_test_location, hit_test_filter)) + LayoutPoint fragment_offset = offset; + fragment_offset.MoveBy(fragment.layer_bounds.Location()); + if (HitTestContents(result, fragment_offset, hit_test_location, + hit_test_filter)) return true; } @@ -2238,11 +2264,8 @@ bool PaintLayer::HitTestContents(HitTestResult& result, const HitTestLocation& hit_test_location, HitTestFilter hit_test_filter) const { DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant()); - - if (!GetLayoutObject().HitTestAllPhases( - result, hit_test_location, - ToLayoutPoint(fragment_offset - LayoutBoxLocation()), - hit_test_filter)) { + if (!GetLayoutObject().HitTestAllPhases(result, hit_test_location, + fragment_offset, hit_test_filter)) { // It's wrong to set innerNode, but then claim that you didn't hit anything, // unless it is a rect-based test. DCHECK(!result.InnerNode() || (result.GetHitTestRequest().ListBased() && diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 708a399543c72..4960ea71606ad 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h @@ -1086,6 +1086,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient { const HitTestLocation&, HitTestFilter) const; bool HitTestContentsForFragments(const PaintLayerFragments&, + const LayoutPoint& offset, HitTestResult&, const HitTestLocation&, HitTestFilter, diff --git a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc index 3a1d18fc069c6..3e8cc8eb07b37 100644 --- a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc @@ -42,13 +42,15 @@ void SVGForeignObjectPainter::Paint(const PaintInfo& paint_info) { } PaintInfo paint_info_before_filtering(paint_info); - paint_info_before_filtering.UpdateCullRect( - layout_svg_foreign_object_.LocalSVGTransform()); - SVGTransformContext transform_context( - paint_info_before_filtering, layout_svg_foreign_object_, - layout_svg_foreign_object_.LocalSVGTransform()); + Optional transform_context; if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + paint_info_before_filtering.UpdateCullRect( + layout_svg_foreign_object_.LocalSVGTransform()); + transform_context.emplace(paint_info_before_filtering, + layout_svg_foreign_object_, + layout_svg_foreign_object_.LocalSVGTransform()); + // In theory we should just let BlockPainter::paint() handle the clip, but // for now we don't allow normal overflow clip for LayoutSVGBlock, so we // have to apply clip manually. See LayoutSVGBlock::allowsOverflowClip() for