Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / rendering / svg / RenderSVGRect.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 8d585c5..abc9fd3
  */
 
 #include "config.h"
-
-#if ENABLE(SVG)
 #include "RenderSVGRect.h"
 
 #include "SVGNames.h"
-#include "SVGRectElement.h"
-#include <wtf/Platform.h>
 
 namespace WebCore {
 
-RenderSVGRect::RenderSVGRect(SVGRectElement* node)
-    : RenderSVGShape(node)
+RenderSVGRect::RenderSVGRect(SVGRectElement& element, Ref<RenderStyle>&& style)
+    : RenderSVGShape(element, WTFMove(style))
+    , m_usePathFallback(false)
 {
 }
 
@@ -45,99 +42,121 @@ RenderSVGRect::~RenderSVGRect()
 {
 }
 
-void RenderSVGRect::createShape()
+SVGRectElement& RenderSVGRect::rectElement() const
+{
+    return downcast<SVGRectElement>(RenderSVGShape::graphicsElement());
+}
+
+void RenderSVGRect::updateShapeFromElement()
 {
     // Before creating a new object we need to clear the cached bounding box
     // to avoid using garbage.
-    m_boundingBox = FloatRect();
+    m_fillBoundingBox = FloatRect();
     m_innerStrokeRect = FloatRect();
     m_outerStrokeRect = FloatRect();
-    SVGRectElement* rect = static_cast<SVGRectElement*>(node());
-    ASSERT(rect);
-
-    bool nonScalingStroke = style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
-    // Fallback to RenderSVGShape if rect has rounded corners.
-    if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || nonScalingStroke) {
-       RenderSVGShape::createShape();
-       setIsPaintingFallback(true);
-       return;
-    }
 
-    SVGLengthContext lengthContext(rect);
-    FloatSize boundingBoxSize(rect->width().value(lengthContext), rect->height().value(lengthContext));
-    if (boundingBoxSize.isEmpty())
+    SVGLengthContext lengthContext(&rectElement());
+    FloatSize boundingBoxSize(lengthContext.valueForLength(style().width(), LengthModeWidth), lengthContext.valueForLength(style().height(), LengthModeHeight));
+
+    // Element is invalid if either dimension is negative.
+    if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0)
         return;
 
-    m_boundingBox = FloatRect(FloatPoint(rect->x().value(lengthContext), rect->y().value(lengthContext)), boundingBoxSize);
+    // Rendering enabled? Spec: "A value of zero disables rendering of the element."
+    if (!boundingBoxSize.isEmpty()) {
+        if (rectElement().rx().value(lengthContext) > 0 || rectElement().ry().value(lengthContext) > 0 || hasNonScalingStroke()) {
+            // Fall back to RenderSVGShape
+            RenderSVGShape::updateShapeFromElement();
+            m_usePathFallback = true;
+            return;
+        }
+        m_usePathFallback = false;
+    }
+
+    m_fillBoundingBox = FloatRect(FloatPoint(lengthContext.valueForLength(style().svgStyle().x(), LengthModeWidth),
+        lengthContext.valueForLength(style().svgStyle().y(), LengthModeHeight)),
+        boundingBoxSize);
 
     // To decide if the stroke contains a point we create two rects which represent the inner and
     // the outer stroke borders. A stroke contains the point, if the point is between them.
-    m_innerStrokeRect = m_boundingBox;
-    m_outerStrokeRect = m_boundingBox;
+    m_innerStrokeRect = m_fillBoundingBox;
+    m_outerStrokeRect = m_fillBoundingBox;
 
-    if (style()->svgStyle()->hasStroke()) {
+    if (style().svgStyle().hasStroke()) {
         float strokeWidth = this->strokeWidth();
         m_innerStrokeRect.inflate(-strokeWidth / 2);
         m_outerStrokeRect.inflate(strokeWidth / 2);
     }
-}
 
-FloatRect RenderSVGRect::objectBoundingBox() const
-{
-    if (isPaintingFallback())
-        return RenderSVGShape::objectBoundingBox();
-    return m_boundingBox;
-}
+    m_strokeBoundingBox = m_outerStrokeRect;
 
-FloatRect RenderSVGRect::strokeBoundingBox() const
-{
-    if (isPaintingFallback())
-        return RenderSVGShape::strokeBoundingBox();
-    return m_outerStrokeRect;
+#if USE(CG)
+    // CoreGraphics can inflate the stroke by 1px when drawing a rectangle with antialiasing disabled at non-integer coordinates, we need to compensate.
+    if (style().svgStyle().shapeRendering() == SR_CRISPEDGES)
+        m_strokeBoundingBox.inflate(1);
+#endif
 }
 
-void RenderSVGRect::fillShape(GraphicsContext* context) const
+void RenderSVGRect::fillShape(GraphicsContext& context) const
 {
-    if (!isPaintingFallback()) {
-#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(MAC_OS_X))
-        // FIXME: CG implementation of GraphicsContextCG::fillRect has an own
-        // shadow drawing method, which draws an extra shadow.
-        // This is a workaround for switching off the extra shadow.
-        // https://bugs.webkit.org/show_bug.cgi?id=68899
-        if (context->hasShadow()) {
-            GraphicsContextStateSaver stateSaver(*context);
-            context->clearShadow();
-            context->fillRect(m_boundingBox);
-            return;
-        }
-#endif
-        context->fillRect(m_boundingBox);
+    if (m_usePathFallback) {
+        RenderSVGShape::fillShape(context);
+        return;
+    }
+
+#if USE(CG)
+    // FIXME: CG implementation of GraphicsContextCG::fillRect has an own
+    // shadow drawing method, which draws an extra shadow.
+    // This is a workaround for switching off the extra shadow.
+    // https://bugs.webkit.org/show_bug.cgi?id=68899
+    if (context.hasShadow()) {
+        GraphicsContextStateSaver stateSaver(context);
+        context.clearShadow();
+        context.fillRect(m_fillBoundingBox);
         return;
     }
-    RenderSVGShape::fillShape(context);
+#endif
+
+    context.fillRect(m_fillBoundingBox);
 }
 
-void RenderSVGRect::strokeShape(GraphicsContext* context) const
+void RenderSVGRect::strokeShape(GraphicsContext& context) const
 {
-    if (!isPaintingFallback()) {
-        context->strokeRect(m_boundingBox, strokeWidth());
+    if (!style().svgStyle().hasVisibleStroke())
+        return;
+
+    if (m_usePathFallback) {
+        RenderSVGShape::strokeShape(context);
         return;
     }
-    RenderSVGShape::strokeShape(context);
+
+    context.strokeRect(m_fillBoundingBox, strokeWidth());
 }
 
-bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point) const
+bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point)
 {
+    // The optimized contains code below does not support non-smooth strokes so we need
+    // to fall back to RenderSVGShape::shapeDependentStrokeContains in these cases.
+    if (m_usePathFallback || !hasSmoothStroke()) {
+        if (!hasPath())
+            RenderSVGShape::updateShapeFromElement();
+        return RenderSVGShape::shapeDependentStrokeContains(point);
+    }
+
     return m_outerStrokeRect.contains(point, FloatRect::InsideOrOnStroke) && !m_innerStrokeRect.contains(point, FloatRect::InsideButNotOnStroke);
 }
 
 bool RenderSVGRect::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
 {
-    if (isPaintingFallback())
+    if (m_usePathFallback)
         return RenderSVGShape::shapeDependentFillContains(point, fillRule);
-    return m_boundingBox.contains(point.x(), point.y());
+    return m_fillBoundingBox.contains(point.x(), point.y());
 }
 
+bool RenderSVGRect::isRenderingDisabled() const
+{
+    // A width or height of zero disables rendering for the element, and results in an empty bounding box.
+    return m_fillBoundingBox.isEmpty();
 }
 
-#endif // ENABLE(SVG)
+}