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(