Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Unified Diff: Source/core/rendering/svg/RenderSVGEllipse.cpp

Issue 877553002: Fix ellipse hit testing in the non-circle case (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Lazily create the path Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « LayoutTests/svg/hittest/ellipse-hittest-expected.txt ('k') | Source/core/rendering/svg/RenderSVGShape.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/svg/RenderSVGEllipse.cpp
diff --git a/Source/core/rendering/svg/RenderSVGEllipse.cpp b/Source/core/rendering/svg/RenderSVGEllipse.cpp
index 3d8f8c0cc1a3d359c2b5d29dfafd7c1d8e1779b1..2371c9a3e72d73c06be2c7cce3c64e51ea27681d 100644
--- a/Source/core/rendering/svg/RenderSVGEllipse.cpp
+++ b/Source/core/rendering/svg/RenderSVGEllipse.cpp
@@ -31,6 +31,8 @@
#include "core/svg/SVGCircleElement.h"
#include "core/svg/SVGEllipseElement.h"
+#include <cmath>
+
namespace blink {
RenderSVGEllipse::RenderSVGEllipse(SVGGraphicsElement* node)
@@ -61,7 +63,7 @@ void RenderSVGEllipse::updateShapeFromElement()
return;
if (!m_radii.isEmpty()) {
- // Fallback to RenderSVGShape and path-based hit detection if the ellipse
+ // Fall back to RenderSVGShape and path-based hit detection if the ellipse
// has a non-scaling or discontinuous stroke.
if (hasNonScalingStroke() || !hasContinuousStroke()) {
RenderSVGShape::updateShapeFromElement();
@@ -70,6 +72,8 @@ void RenderSVGEllipse::updateShapeFromElement()
}
}
+ clearPath();
+
m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
m_hitTestStrokeBoundingBox = m_fillBoundingBox;
m_hitTestStrokeBoundingBox.inflate(strokeWidth() / 2);
@@ -98,40 +102,30 @@ void RenderSVGEllipse::calculateRadiiAndCenter()
bool RenderSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point)
{
- // The optimized code below does not support discontinuous strokes so we need
- // to fall back to RenderSVGShape::shapeDependentStrokeContains in these cases.
- if (m_usePathFallback || !hasContinuousStroke()) {
+ // The optimized check below for circles does not support non-scaling or
+ // discontinuous strokes.
+ if (m_usePathFallback
+ || !hasContinuousStroke()
+ || m_radii.width() != m_radii.height()) {
if (!hasPath())
RenderSVGShape::updateShapeFromElement();
return RenderSVGShape::shapeDependentStrokeContains(point);
}
- float halfStrokeWidth = strokeWidth() / 2;
- FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
-
- // This works by checking if the point satisfies the ellipse equation,
- // (x/rX)^2 + (y/rY)^2 <= 1, for the outer but not the inner stroke.
- float xrXOuter = center.x() / (m_radii.width() + halfStrokeWidth);
- float yrYOuter = center.y() / (m_radii.height() + halfStrokeWidth);
- if (xrXOuter * xrXOuter + yrYOuter * yrYOuter > 1.0)
- return false;
-
- float xrXInner = center.x() / (m_radii.width() - halfStrokeWidth);
- float yrYInner = center.y() / (m_radii.height() - halfStrokeWidth);
- return xrXInner * xrXInner + yrYInner * yrYInner >= 1.0;
+ const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+ const float halfStrokeWidth = strokeWidth() / 2;
+ const float r = m_radii.width();
+ return std::abs(center.length() - r) <= halfStrokeWidth;
}
bool RenderSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
{
- if (m_usePathFallback)
- return RenderSVGShape::shapeDependentFillContains(point, fillRule);
-
- FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+ const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
// This works by checking if the point satisfies the ellipse equation.
// (x/rX)^2 + (y/rY)^2 <= 1
- float xrX = center.x() / m_radii.width();
- float yrY = center.y() / m_radii.height();
+ const float xrX = center.x() / m_radii.width();
+ const float yrY = center.y() / m_radii.height();
return xrX * xrX + yrY * yrY <= 1.0;
}
« no previous file with comments | « LayoutTests/svg/hittest/ellipse-hittest-expected.txt ('k') | Source/core/rendering/svg/RenderSVGShape.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698