Plumb HitTestLocation further in LayoutSVG*

Plumb HitTestLocation into clip-path handling and
LayoutSVGShape::*Contains.

Change-Id: Ibd4e433e868ac427e637f906ff3d778fd33e1a80
Reviewed-on: https://chromium-review.googlesource.com/c/1291409
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#601413}
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
index 0e78210..93a6b90 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
@@ -99,15 +99,17 @@
   }
 }
 
-bool LayoutSVGEllipse::ShapeDependentStrokeContains(const FloatPoint& point) {
+bool LayoutSVGEllipse::ShapeDependentStrokeContains(
+    const HitTestLocation& location) {
   if (radii_.Width() < 0 || radii_.Height() < 0)
     return false;
 
   // The optimized check below for circles does not support non-circular and
   // the cases that we set use_path_fallback_ in UpdateShapeFromElement().
   if (use_path_fallback_ || radii_.Width() != radii_.Height())
-    return LayoutSVGShape::ShapeDependentStrokeContains(point);
+    return LayoutSVGShape::ShapeDependentStrokeContains(location);
 
+  const FloatPoint& point = location.TransformedPoint();
   const FloatPoint center =
       FloatPoint(center_.X() - point.X(), center_.Y() - point.Y());
   const float half_stroke_width = StrokeWidth() / 2;
@@ -116,8 +118,9 @@
 }
 
 bool LayoutSVGEllipse::ShapeDependentFillContains(
-    const FloatPoint& point,
+    const HitTestLocation& location,
     const WindRule fill_rule) const {
+  const FloatPoint& point = location.TransformedPoint();
   const FloatPoint center =
       FloatPoint(center_.X() - point.X(), center_.Y() - point.Y());
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h
index 1cc039d..9672a40b 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h
@@ -48,8 +48,8 @@
     return use_path_fallback_ ? LayoutSVGShape::IsShapeEmpty()
                               : fill_bounding_box_.IsEmpty();
   }
-  bool ShapeDependentStrokeContains(const FloatPoint&) override;
-  bool ShapeDependentFillContains(const FloatPoint&,
+  bool ShapeDependentStrokeContains(const HitTestLocation&) override;
+  bool ShapeDependentFillContains(const HitTestLocation&,
                                   const WindRule) const override;
   void CalculateRadiiAndCenter();
   bool HasContinuousStroke() const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
index 464555c..f895585 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
@@ -80,12 +80,14 @@
   stroke_bounding_box_ = CalculateStrokeBoundingBox();
 }
 
-bool LayoutSVGRect::ShapeDependentStrokeContains(const FloatPoint& point) {
+bool LayoutSVGRect::ShapeDependentStrokeContains(
+    const HitTestLocation& location) {
   // The optimized code below does not support the cases that we set
   // use_path_fallback_ in UpdateShapeFromElement().
   if (use_path_fallback_)
-    return LayoutSVGShape::ShapeDependentStrokeContains(point);
+    return LayoutSVGShape::ShapeDependentStrokeContains(location);
 
+  const FloatPoint& point = location.TransformedPoint();
   const float half_stroke_width = StrokeWidth() / 2;
   const float half_width = fill_bounding_box_.Width() / 2;
   const float half_height = fill_bounding_box_.Height() / 2;
@@ -104,10 +106,11 @@
          (half_height - half_stroke_width <= abs_delta_y);
 }
 
-bool LayoutSVGRect::ShapeDependentFillContains(const FloatPoint& point,
+bool LayoutSVGRect::ShapeDependentFillContains(const HitTestLocation& location,
                                                const WindRule fill_rule) const {
   if (use_path_fallback_)
-    return LayoutSVGShape::ShapeDependentFillContains(point, fill_rule);
+    return LayoutSVGShape::ShapeDependentFillContains(location, fill_rule);
+  const FloatPoint& point = location.TransformedPoint();
   return fill_bounding_box_.Contains(point.X(), point.Y());
 }
 
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h
index a2352f9..9dc9c764 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h
@@ -49,8 +49,8 @@
     return use_path_fallback_ ? LayoutSVGShape::IsShapeEmpty()
                               : fill_bounding_box_.IsEmpty();
   }
-  bool ShapeDependentStrokeContains(const FloatPoint&) override;
-  bool ShapeDependentFillContains(const FloatPoint&,
+  bool ShapeDependentStrokeContains(const HitTestLocation&) override;
+  bool ShapeDependentFillContains(const HitTestLocation&,
                                   const WindRule) const override;
   bool DefinitelyHasSimpleStroke() const;
 
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 7c12555..f1169d2f 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
@@ -26,6 +26,7 @@
 #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/layout/svg/transformed_hit_test_location.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/svg/svg_clip_path_element.h"
 #include "third_party/blink/renderer/core/svg/svg_geometry_element.h"
@@ -236,30 +237,26 @@
 
 bool LayoutSVGResourceClipper::HitTestClipContent(
     const FloatRect& object_bounding_box,
-    const FloatPoint& node_at_point) {
-  FloatPoint point = node_at_point;
-  if (!SVGLayoutSupport::IntersectsClipPath(*this, point))
+    const HitTestLocation& location) const {
+  if (!SVGLayoutSupport::IntersectsClipPath(*this, location))
     return false;
 
-  AffineTransform user_space_transform =
-      CalculateClipTransform(object_bounding_box);
-  if (!user_space_transform.IsInvertible())
+  TransformedHitTestLocation local_location(
+      location, CalculateClipTransform(object_bounding_box));
+  if (!local_location)
     return false;
 
-  point = user_space_transform.Inverse().MapPoint(point);
-
+  HitTestResult result(HitTestRequest::kSVGClipContent, *local_location);
   for (const SVGElement& child_element :
        Traversal<SVGElement>::ChildrenOf(*GetElement())) {
     if (!ContributesToClip(child_element))
       continue;
-    HitTestLocation location(point);
-    HitTestResult result(HitTestRequest::kSVGClipContent, location);
     LayoutObject* layout_object = child_element.GetLayoutObject();
 
     DCHECK(!layout_object->IsBoxModelObject() ||
            !ToLayoutBoxModelObject(layout_object)->HasSelfPaintingLayer());
 
-    if (layout_object->NodeAtPoint(result, location, LayoutPoint(),
+    if (layout_object->NodeAtPoint(result, *local_location, LayoutPoint(),
                                    kHitTestForeground))
       return true;
   }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h
index b7913ab..b8f71fb 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h
@@ -42,7 +42,7 @@
   static const LayoutSVGResourceType kResourceType = kClipperResourceType;
   LayoutSVGResourceType ResourceType() const override { return kResourceType; }
 
-  bool HitTestClipContent(const FloatRect&, const FloatPoint&);
+  bool HitTestClipContent(const FloatRect&, const HitTestLocation&) const;
 
   SVGUnitTypes::SVGUnitType ClipPathUnits() const;
   AffineTransform CalculateClipTransform(const FloatRect& reference_box) const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
index b8f1e08..366de43 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -146,7 +146,8 @@
   return ApproximateStrokeBoundingBox();
 }
 
-bool LayoutSVGShape::ShapeDependentStrokeContains(const FloatPoint& point) {
+bool LayoutSVGShape::ShapeDependentStrokeContains(
+    const HitTestLocation& location) {
   // In case the subclass didn't create path during UpdateShapeFromElement()
   // for optimization but still calls this method.
   if (!HasPath())
@@ -161,50 +162,50 @@
     if (!rare_data_)
       UpdateNonScalingStrokeData();
     return NonScalingStrokePath().StrokeContains(
-        NonScalingStrokeTransform().MapPoint(point), stroke_data);
+        NonScalingStrokeTransform().MapPoint(location.TransformedPoint()),
+        stroke_data);
   }
-
-  return path_->StrokeContains(point, stroke_data);
+  return path_->StrokeContains(location.TransformedPoint(), stroke_data);
 }
 
 bool LayoutSVGShape::ShapeDependentFillContains(
-    const FloatPoint& point,
+    const HitTestLocation& location,
     const WindRule fill_rule) const {
-  return GetPath().Contains(point, fill_rule);
+  return GetPath().Contains(location.TransformedPoint(), fill_rule);
 }
 
-bool LayoutSVGShape::FillContains(const FloatPoint& point,
+bool LayoutSVGShape::FillContains(const HitTestLocation& location,
                                   bool requires_fill,
                                   const WindRule fill_rule) {
-  if (!fill_bounding_box_.Contains(point))
+  if (!fill_bounding_box_.Contains(location.TransformedPoint()))
     return false;
 
   if (requires_fill && !SVGPaintServer::ExistsForLayoutObject(*this, StyleRef(),
                                                               kApplyToFillMode))
     return false;
 
-  return ShapeDependentFillContains(point, fill_rule);
+  return ShapeDependentFillContains(location, fill_rule);
 }
 
-bool LayoutSVGShape::StrokeContains(const FloatPoint& point,
+bool LayoutSVGShape::StrokeContains(const HitTestLocation& location,
                                     bool requires_stroke) {
   // "A zero value causes no stroke to be painted."
   if (StyleRef().SvgStyle().StrokeWidth().IsZero())
     return false;
 
   if (requires_stroke) {
-    if (!StrokeBoundingBox().Contains(point))
+    if (!StrokeBoundingBox().Contains(location.TransformedPoint()))
       return false;
 
     if (!SVGPaintServer::ExistsForLayoutObject(*this, StyleRef(),
                                                kApplyToStrokeMode))
       return false;
   } else {
-    if (!HitTestStrokeBoundingBox().Contains(point))
+    if (!HitTestStrokeBoundingBox().Contains(location.TransformedPoint()))
       return false;
   }
 
-  return ShapeDependentStrokeContains(point);
+  return ShapeDependentStrokeContains(location);
 }
 
 static inline bool TransformOriginIsFixed(const ComputedStyle& style) {
@@ -384,16 +385,14 @@
   const SVGComputedStyle& svg_style = style.SvgStyle();
   if (hit_rules.can_hit_stroke &&
       (svg_style.HasStroke() || !hit_rules.require_stroke) &&
-      StrokeContains(local_location.TransformedPoint(),
-                     hit_rules.require_stroke))
+      StrokeContains(local_location, hit_rules.require_stroke))
     return true;
   WindRule fill_rule = svg_style.FillRule();
   if (request.SvgClipContent())
     fill_rule = svg_style.ClipRule();
   if (hit_rules.can_hit_fill &&
       (svg_style.HasFill() || !hit_rules.require_fill) &&
-      FillContains(local_location.TransformedPoint(), hit_rules.require_fill,
-                   fill_rule))
+      FillContains(local_location, hit_rules.require_fill, fill_rule))
     return true;
   return false;
 }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
index 6c3aa6c..8818c80f 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -36,7 +36,6 @@
 
 namespace blink {
 
-class FloatPoint;
 class PointerEventsHitRules;
 class SVGGeometryElement;
 
@@ -140,8 +139,8 @@
   // Update (cached) shape data and the (object) bounding box.
   virtual void UpdateShapeFromElement();
   FloatRect CalculateStrokeBoundingBox() const;
-  virtual bool ShapeDependentStrokeContains(const FloatPoint&);
-  virtual bool ShapeDependentFillContains(const FloatPoint&,
+  virtual bool ShapeDependentStrokeContains(const HitTestLocation&);
+  virtual bool ShapeDependentFillContains(const HitTestLocation&,
                                           const WindRule) const;
 
   FloatRect fill_bounding_box_;
@@ -151,10 +150,10 @@
 
  private:
   // Hit-detection separated for the fill and the stroke
-  bool FillContains(const FloatPoint&,
+  bool FillContains(const HitTestLocation&,
                     bool requires_fill = true,
                     const WindRule fill_rule = RULE_NONZERO);
-  bool StrokeContains(const FloatPoint&, bool requires_stroke = true);
+  bool StrokeContains(const HitTestLocation&, bool requires_stroke = true);
 
   bool IsOfType(LayoutObjectType type) const override {
     return type == kLayoutObjectSVGShape ||
@@ -166,7 +165,7 @@
   bool NodeAtPoint(HitTestResult&,
                    const HitTestLocation& location_in_parent,
                    const LayoutPoint& accumulated_offset,
-                   HitTestAction) override;
+                   HitTestAction) final;
 
   FloatRect StrokeBoundingBox() const final { return stroke_bounding_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 4cd2fcc..24ca9c1 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
@@ -413,26 +413,22 @@
 
 bool SVGLayoutSupport::IntersectsClipPath(const LayoutObject& object,
                                           const HitTestLocation& location) {
-  return IntersectsClipPath(object, location.TransformedPoint());
-}
-
-bool SVGLayoutSupport::IntersectsClipPath(const LayoutObject& object,
-                                          const FloatPoint& point) {
   ClipPathOperation* clip_path_operation = object.StyleRef().ClipPath();
   if (!clip_path_operation)
     return true;
+  const FloatRect& reference_box = object.ObjectBoundingBox();
   if (clip_path_operation->GetType() == ClipPathOperation::SHAPE) {
     ShapeClipPathOperation& clip_path =
         ToShapeClipPathOperation(*clip_path_operation);
-    return clip_path.GetPath(object.ObjectBoundingBox()).Contains(point);
+    return clip_path.GetPath(reference_box)
+        .Contains(location.TransformedPoint());
   }
   DCHECK_EQ(clip_path_operation->GetType(), ClipPathOperation::REFERENCE);
   SVGResources* resources =
       SVGResourcesCache::CachedResourcesForLayoutObject(object);
   if (!resources || !resources->Clipper())
     return true;
-  return resources->Clipper()->HitTestClipContent(object.ObjectBoundingBox(),
-                                                  point);
+  return resources->Clipper()->HitTestClipContent(reference_box, location);
 }
 
 bool SVGLayoutSupport::HitTestChildren(LayoutObject* last_child,
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 e683dddc..5486a30 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
@@ -73,8 +73,7 @@
   // Determine if the LayoutObject references a filter resource object.
   static bool HasFilterResource(const LayoutObject&);
 
-  // Determine whether the passed point intersects the clip path of |object|.
-  static bool IntersectsClipPath(const LayoutObject&, const FloatPoint&);
+  // Determine whether the passed location intersects the clip path of |object|.
   static bool IntersectsClipPath(const LayoutObject&, const HitTestLocation&);
 
   // Shared child hit-testing code between LayoutSVGRoot/LayoutSVGContainer.
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index d7b3d2a..95eb73e 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -2501,7 +2501,8 @@
   float inverse_zoom = 1 / GetLayoutObject().StyleRef().EffectiveZoom();
   point.Scale(inverse_zoom, inverse_zoom);
   reference_box.Scale(inverse_zoom);
-  return !clipper->HitTestClipContent(reference_box, point);
+  HitTestLocation location(point);
+  return !clipper->HitTestClipContent(reference_box, location);
 }
 
 bool PaintLayer::IntersectsDamageRect(