Index: Source/core/layout/svg/LayoutSVGRect.cpp |
diff --git a/Source/core/layout/svg/LayoutSVGRect.cpp b/Source/core/layout/svg/LayoutSVGRect.cpp |
index 18b0ccd737b67602e2f4f40fe69236ed49f814fe..d5890dcc06eb45aad4afea34bc4dfaa9973e1542 100644 |
--- a/Source/core/layout/svg/LayoutSVGRect.cpp |
+++ b/Source/core/layout/svg/LayoutSVGRect.cpp |
@@ -43,37 +43,64 @@ LayoutSVGRect::~LayoutSVGRect() |
{ |
} |
+void LayoutSVGRect::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) |
+{ |
+ if (diff.needsFullLayout() && oldStyle) { |
+ const SVGComputedStyle& oldSvgStyle = oldStyle->svgStyle(); |
+ const SVGComputedStyle& svgStyle = style()->svgStyle(); |
+ if (oldSvgStyle.rx() != svgStyle.rx() |
+ || oldSvgStyle.ry() != svgStyle.ry() |
+ || oldSvgStyle.vectorEffect() != svgStyle.vectorEffect() |
+ || definitelyHasSimpleStroke(oldSvgStyle) != definitelyHasSimpleStroke(svgStyle)) |
+ setNeedsShapeUpdate(); |
+ } |
+ |
+ // Superclass will take care of calling clientStyleChanged. |
+ LayoutSVGShape::styleDidChange(diff, oldStyle); |
+} |
+ |
void LayoutSVGRect::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_usePathFallback = false; |
- SVGRectElement* rect = toSVGRectElement(element()); |
- ASSERT(rect); |
- SVGLengthContext lengthContext(rect); |
+ // Fallback to LayoutSVGShape and path-based hit detection if the rect |
+ // has rounded corners or a non-scaling or non-simple stroke. |
+ SVGLengthContext lengthContext(toSVGRectElement(element())); |
+ if (lengthContext.valueForLength(styleRef().svgStyle().rx(), styleRef(), SVGLengthMode::Width) > 0 |
+ || lengthContext.valueForLength(styleRef().svgStyle().ry(), styleRef(), SVGLengthMode::Height) > 0 |
+ || hasNonScalingStroke() |
+ || !definitelyHasSimpleStroke(style()->svgStyle())) { |
+ LayoutSVGShape::updateShapeFromElement(); |
+ m_usePathFallback = true; |
+ return; |
+ } |
+ |
+ clearPath(); |
+} |
+ |
+void LayoutSVGRect::updateStrokeAndFillBoundingBoxes() |
+{ |
+ SVGLengthContext lengthContext(toSVGRectElement(element())); |
FloatSize boundingBoxSize( |
lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMode::Width), |
lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthMode::Height)); |
// Spec: "A negative value is an error." |
- if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) |
+ if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) { |
+ m_fillBoundingBox = FloatRect(); |
+ m_strokeBoundingBox = FloatRect(); |
return; |
+ } |
- // Spec: "A value of zero disables rendering of the element." |
- if (!boundingBoxSize.isEmpty()) { |
- // Fallback to LayoutSVGShape and path-based hit detection if the rect |
- // has rounded corners or a non-scaling or non-simple stroke. |
- if (lengthContext.valueForLength(styleRef().svgStyle().rx(), styleRef(), SVGLengthMode::Width) > 0 |
- || lengthContext.valueForLength(styleRef().svgStyle().ry(), styleRef(), SVGLengthMode::Height) > 0 |
- || hasNonScalingStroke() |
- || !definitelyHasSimpleStroke()) { |
- LayoutSVGShape::updateShapeFromElement(); |
- m_usePathFallback = true; |
+ 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 (!boundingBoxSize.isEmpty()) { |
+ LayoutSVGShape::updateStrokeAndFillBoundingBoxes(); |
return; |
} |
+ m_usePathFallback = false; |
+ clearPath(); |
} |
m_fillBoundingBox = FloatRect( |
@@ -90,8 +117,8 @@ bool LayoutSVGRect::shapeDependentStrokeContains(const FloatPoint& point) |
{ |
// The optimized code below does not support non-simple strokes so we need |
// to fall back to LayoutSVGShape::shapeDependentStrokeContains in these cases. |
- if (m_usePathFallback || !definitelyHasSimpleStroke()) { |
- if (!hasPath()) |
+ if (m_usePathFallback || !definitelyHasSimpleStroke(style()->svgStyle())) { |
+ if (!m_usePathFallback) |
LayoutSVGShape::updateShapeFromElement(); |
return LayoutSVGShape::shapeDependentStrokeContains(point); |
} |
@@ -119,10 +146,8 @@ bool LayoutSVGRect::shapeDependentFillContains(const FloatPoint& point, const Wi |
} |
// Returns true if the stroke is continuous and definitely uses miter joins. |
-bool LayoutSVGRect::definitelyHasSimpleStroke() const |
+bool LayoutSVGRect::definitelyHasSimpleStroke(const SVGComputedStyle& svgStyle) const |
{ |
- const SVGComputedStyle& svgStyle = style()->svgStyle(); |
- |
// The four angles of a rect are 90 degrees. Using the formula at: |
// http://www.w3.org/TR/SVG/painting.html#StrokeMiterlimitProperty |
// when the join style of the rect is "miter", the ratio of the miterLength |