Index: Source/core/layout/svg/LayoutSVGEllipse.cpp |
diff --git a/Source/core/layout/svg/LayoutSVGEllipse.cpp b/Source/core/layout/svg/LayoutSVGEllipse.cpp |
index 8809a19effc56498f07bce318b1f8db40dee533e..3c14eb186daec78597a50a6efc3720218c6b85f7 100644 |
--- a/Source/core/layout/svg/LayoutSVGEllipse.cpp |
+++ b/Source/core/layout/svg/LayoutSVGEllipse.cpp |
@@ -45,38 +45,44 @@ LayoutSVGEllipse::~LayoutSVGEllipse() |
{ |
} |
+void LayoutSVGEllipse::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) |
+{ |
+ if (diff.needsFullLayout() && oldStyle) { |
+ const SVGComputedStyle& oldSvgStyle = oldStyle->svgStyle(); |
+ const SVGComputedStyle& svgStyle = style()->svgStyle(); |
+ |
+ bool radiusChanged; |
+ if (isSVGCircleElement(*element())) |
+ radiusChanged = oldSvgStyle.r() != svgStyle.r(); |
+ else |
+ radiusChanged = (oldSvgStyle.rx() != svgStyle.rx()) || (oldSvgStyle.ry() != svgStyle.ry()); |
+ |
+ if (oldSvgStyle.cx() != svgStyle.cx() |
+ || oldSvgStyle.cy() != svgStyle.cy() |
+ || radiusChanged |
+ || oldSvgStyle.vectorEffect() != svgStyle.vectorEffect() |
+ || hasContinuousStroke(oldSvgStyle) != hasContinuousStroke(svgStyle)) |
+ setNeedsShapeUpdate(); |
+ } |
+ |
+ // Superclass will take care of calling clientStyleChanged. |
+ LayoutSVGShape::styleDidChange(diff, oldStyle); |
+} |
+ |
void LayoutSVGEllipse::updateShapeFromElement() |
{ |
- // Before creating a new object we need to clear the cached bounding box |
- // to avoid using garbage. |
- m_fillBoundingBox = FloatRect(); |
- m_strokeBoundingBox = FloatRect(); |
- m_center = FloatPoint(); |
- m_radii = FloatSize(); |
m_usePathFallback = false; |
- |
calculateRadiiAndCenter(); |
- // Spec: "A negative value is an error. A value of zero disables rendering of the element." |
- if (m_radii.width() < 0 || m_radii.height() < 0) |
+ // Fall back to LayoutSVGShape and path-based hit detection if the ellipse |
+ // has a non-scaling or discontinuous stroke. |
+ if (hasNonScalingStroke() || !hasContinuousStroke(style()->svgStyle())) { |
+ LayoutSVGShape::updateShapeFromElement(); |
+ m_usePathFallback = true; |
return; |
- |
- if (!m_radii.isEmpty()) { |
- // Fall back to LayoutSVGShape and path-based hit detection if the ellipse |
- // has a non-scaling or discontinuous stroke. |
- if (hasNonScalingStroke() || !hasContinuousStroke()) { |
- LayoutSVGShape::updateShapeFromElement(); |
- m_usePathFallback = true; |
- return; |
- } |
} |
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_strokeBoundingBox = m_fillBoundingBox; |
- if (style()->svgStyle().hasStroke()) |
- m_strokeBoundingBox.inflate(strokeWidth() / 2); |
} |
void LayoutSVGEllipse::calculateRadiiAndCenter() |
@@ -97,15 +103,41 @@ void LayoutSVGEllipse::calculateRadiiAndCenter() |
} |
} |
+void LayoutSVGEllipse::updateStrokeAndFillBoundingBoxes() |
+{ |
+ // Spec: "A negative value is an error." |
+ if (m_radii.width() < 0 || m_radii.height() < 0) { |
+ m_fillBoundingBox = FloatRect(); |
+ m_strokeBoundingBox = FloatRect(); |
+ return; |
+ } |
+ |
+ if (m_usePathFallback) { |
+ // Spec: "A value of zero disables rendering of the element." so we can skip |
+ // the path fallback and rely on the existing bounding box calculation. |
+ if (!m_radii.isEmpty()) { |
+ LayoutSVGShape::updateStrokeAndFillBoundingBoxes(); |
+ return; |
+ } |
+ m_usePathFallback = false; |
+ 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_strokeBoundingBox = m_fillBoundingBox; |
+ if (style()->svgStyle().hasStroke()) |
+ m_strokeBoundingBox.inflate(strokeWidth() / 2); |
+} |
+ |
bool LayoutSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point) |
{ |
// The optimized check below for circles does not support non-scaling or |
// discontinuous strokes. |
if (m_usePathFallback |
- || !hasContinuousStroke() |
+ || !hasContinuousStroke(style()->svgStyle()) |
|| m_radii.width() != m_radii.height()) { |
- if (!hasPath()) |
- createPath(); |
+ if (!m_usePathFallback) |
+ LayoutSVGShape::updateShapeFromElement(); |
return LayoutSVGShape::shapeDependentStrokeContains(point); |
} |
@@ -126,9 +158,8 @@ bool LayoutSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const |
return xrX * xrX + yrY * yrY <= 1.0; |
} |
-bool LayoutSVGEllipse::hasContinuousStroke() const |
+bool LayoutSVGEllipse::hasContinuousStroke(const SVGComputedStyle& svgStyle) const |
{ |
- const SVGComputedStyle& svgStyle = style()->svgStyle(); |
return svgStyle.strokeDashArray()->isEmpty(); |
} |