Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / rendering / svg / RenderSVGResourceGradient.cpp
index 22433cf..a16c909 100644 (file)
  */
 
 #include "config.h"
-
-#if ENABLE(SVG)
 #include "RenderSVGResourceGradient.h"
 
 #include "GradientAttributes.h"
 #include "GraphicsContext.h"
-#include "RenderSVGShape.h"
 #include "RenderSVGText.h"
-#include "SVGImageBufferTools.h"
-#include "SVGRenderSupport.h"
-#include <wtf/UnusedParam.h>
+#include "SVGRenderingContext.h"
 
 namespace WebCore {
 
-RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node)
-    : RenderSVGResourceContainer(node)
+RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement& node, Ref<RenderStyle>&& style)
+    : RenderSVGResourceContainer(node, WTFMove(style))
     , m_shouldCollectGradientAttributes(true)
 #if USE(CG)
     , m_savedContext(0)
@@ -44,89 +39,50 @@ RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node)
 {
 }
 
-RenderSVGResourceGradient::~RenderSVGResourceGradient()
-{
-    if (m_gradient.isEmpty())
-        return;
-
-    deleteAllValues(m_gradient);
-    m_gradient.clear();
-}
-
 void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation)
 {
-    if (!m_gradient.isEmpty()) {
-        deleteAllValues(m_gradient);
-        m_gradient.clear();
-    }
-
+    m_gradientMap.clear();
     m_shouldCollectGradientAttributes = true;
     markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
 }
 
-void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+void RenderSVGResourceGradient::removeClientFromCache(RenderElement& client, bool markForInvalidation)
 {
-    ASSERT(client);
-
-    if (m_gradient.contains(client))
-        delete m_gradient.take(client);
-
+    m_gradientMap.remove(&client);
     markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
 }
 
 #if USE(CG)
-static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context,
-                                                           GraphicsContext*& savedContext,
-                                                           OwnPtr<ImageBuffer>& imageBuffer,
-                                                           RenderObject* object)
+static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context, GraphicsContext*& savedContext, std::unique_ptr<ImageBuffer>& imageBuffer, RenderObject* object)
 {
-    RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object);
+    auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
     ASSERT(textRootBlock);
 
-    AffineTransform absoluteTransform;
-    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
-
-    FloatRect absoluteTargetRect = absoluteTransform.mapRect(textRootBlock->repaintRectInLocalCoordinates());
-    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
-    if (clampedAbsoluteTargetRect.isEmpty())
-        return false;
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
+    FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates();
 
-    OwnPtr<ImageBuffer> maskImage;
-    if (!SVGImageBufferTools::createImageBuffer(absoluteTargetRect, clampedAbsoluteTargetRect, maskImage, ColorSpaceDeviceRGB))
+    auto maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceSRGB, context->renderingMode());
+    if (!maskImage)
         return false;
 
-    GraphicsContext* maskImageContext = maskImage->context();
-    ASSERT(maskImageContext);
-
-    maskImageContext->translate(-clampedAbsoluteTargetRect.x(), -clampedAbsoluteTargetRect.y());
-    maskImageContext->concatCTM(absoluteTransform);
-
+    GraphicsContext& maskImageContext = maskImage->context();
     ASSERT(maskImage);
     savedContext = context;
-    context = maskImageContext;
-    imageBuffer = maskImage.release();
+    context = &maskImageContext;
+    imageBuffer = WTFMove(maskImage);
     return true;
 }
 
-static inline AffineTransform clipToTextMask(GraphicsContext* context,
-                                             OwnPtr<ImageBuffer>& imageBuffer,
-                                             FloatRect& targetRect,
-                                             RenderObject* object,
-                                             bool boundingBoxMode,
-                                             const AffineTransform& gradientTransform)
+static inline AffineTransform clipToTextMask(GraphicsContext& context, std::unique_ptr<ImageBuffer>& imageBuffer, FloatRect& targetRect, RenderObject* object, bool boundingBoxMode, const AffineTransform& gradientTransform)
 {
-    RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(object);
+    auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
     ASSERT(textRootBlock);
 
-    targetRect = textRootBlock->repaintRectInLocalCoordinates();
-
-    AffineTransform absoluteTransform;
-    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(textRootBlock, absoluteTransform);
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
 
-    FloatRect absoluteTargetRect = absoluteTransform.mapRect(targetRect);
-    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
+    targetRect = textRootBlock->repaintRectInLocalCoordinates();
 
-    SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, imageBuffer);
+    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false);
 
     AffineTransform matrix;
     if (boundingBoxMode) {
@@ -139,10 +95,8 @@ static inline AffineTransform clipToTextMask(GraphicsContext* context,
 }
 #endif
 
-bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
+bool RenderSVGResourceGradient::applyResource(RenderElement& renderer, const RenderStyle& style, GraphicsContext*& context, unsigned short resourceMode)
 {
-    ASSERT(object);
-    ASSERT(style);
     ASSERT(context);
     ASSERT(resourceMode != ApplyToDefaultMode);
 
@@ -150,13 +104,9 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
     // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
     // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our
     // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
-    SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node());
-    if (!gradientElement)
-        return false;
-
     if (m_shouldCollectGradientAttributes) {
-        gradientElement->updateAnimatedSVGAttribute(anyQName());
-        if (!collectGradientAttributes(gradientElement))
+        gradientElement().synchronizeAnimatedSVGAttribute(anyQName());
+        if (!collectGradientAttributes())
             return false;
 
         m_shouldCollectGradientAttributes = false;
@@ -164,27 +114,27 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
 
     // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
     // then the given effect (e.g. a gradient or a filter) will be ignored.
-    FloatRect objectBoundingBox = object->objectBoundingBox();
-    if (boundingBoxMode() && objectBoundingBox.isEmpty())
+    FloatRect objectBoundingBox = renderer.objectBoundingBox();
+    if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
         return false;
 
-    if (!m_gradient.contains(object))
-        m_gradient.set(object, new GradientData);
+    auto& gradientData = m_gradientMap.add(&renderer, nullptr).iterator->value;
+    if (!gradientData)
+        gradientData = std::make_unique<GradientData>();
 
-    GradientData* gradientData = m_gradient.get(object);
     bool isPaintingText = resourceMode & ApplyToTextMode;
 
     // Create gradient object
     if (!gradientData->gradient) {
-        buildGradient(gradientData, gradientElement);
+        buildGradient(gradientData.get());
 
         // CG platforms will handle the gradient space transform for text after applying the
         // resource, so don't apply it here. For non-CG platforms, we want the text bounding
         // box applied to the gradient space transform now, so the gradient shader can use it.
 #if USE(CG)
-        if (boundingBoxMode() && !objectBoundingBox.isEmpty() && !isPaintingText) {
+        if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty() && !isPaintingText) {
 #else
-        if (boundingBoxMode() && !objectBoundingBox.isEmpty()) {
+        if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty()) {
 #endif
             gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y());
             gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
@@ -194,6 +144,13 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
         calculateGradientTransform(gradientTransform);
 
         gradientData->userspaceTransform *= gradientTransform;
+        if (isPaintingText) {
+            // Depending on font scaling factor, we may need to rescale the gradient here since
+            // text painting removes the scale factor from the context.
+            AffineTransform additionalTextTransform;
+            if (shouldTransformOnTextPainting(renderer, additionalTextTransform))
+                gradientData->userspaceTransform *= additionalTextTransform;
+        }
         gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
     }
 
@@ -205,7 +162,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
 
     if (isPaintingText) {
 #if USE(CG)
-        if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) {
+        if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, &renderer)) {
             context->restore();
             return false;
         }
@@ -214,25 +171,24 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
         context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke);
     }
 
-    const SVGRenderStyle* svgStyle = style->svgStyle();
-    ASSERT(svgStyle);
+    const SVGRenderStyle& svgStyle = style.svgStyle();
 
     if (resourceMode & ApplyToFillMode) {
-        context->setAlpha(svgStyle->fillOpacity());
-        context->setFillGradient(gradientData->gradient);
-        context->setFillRule(svgStyle->fillRule());
+        context->setAlpha(svgStyle.fillOpacity());
+        context->setFillGradient(*gradientData->gradient);
+        context->setFillRule(svgStyle.fillRule());
     } else if (resourceMode & ApplyToStrokeMode) {
-        if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
-            gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(object, gradientData->userspaceTransform));
-        context->setAlpha(svgStyle->strokeOpacity());
-        context->setStrokeGradient(gradientData->gradient);
-        SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
+        if (svgStyle.vectorEffect() == VE_NON_SCALING_STROKE)
+            gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(&renderer, gradientData->userspaceTransform));
+        context->setAlpha(svgStyle.strokeOpacity());
+        context->setStrokeGradient(*gradientData->gradient);
+        SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer);
     }
 
     return true;
 }
 
-void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path* path, const RenderSVGShape* shape)
+void RenderSVGResourceGradient::postApplyResource(RenderElement& renderer, GraphicsContext*& context, unsigned short resourceMode, const Path* path, const RenderSVGShape* shape)
 {
     ASSERT(context);
     ASSERT(resourceMode != ApplyToDefaultMode);
@@ -240,9 +196,8 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
     if (resourceMode & ApplyToTextMode) {
 #if USE(CG)
         // CG requires special handling for gradient on text
-        if (m_savedContext && m_gradient.contains(object)) {
-            GradientData* gradientData = m_gradient.get(object);
-
+        GradientData* gradientData;
+        if (m_savedContext && (gradientData = m_gradientMap.get(&renderer))) {
             // Restore on-screen drawing context
             context = m_savedContext;
             m_savedContext = 0;
@@ -251,27 +206,27 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
             calculateGradientTransform(gradientTransform);
 
             FloatRect targetRect;
-            gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, targetRect, object, boundingBoxMode(), gradientTransform));
-            context->setFillGradient(gradientData->gradient);
+            gradientData->gradient->setGradientSpaceTransform(clipToTextMask(*context, m_imageBuffer, targetRect, &renderer, gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, gradientTransform));
+            context->setFillGradient(*gradientData->gradient);
 
             context->fillRect(targetRect);
-            m_imageBuffer.clear();
+            m_imageBuffer.reset();
         }
 #else
-        UNUSED_PARAM(object);
+        UNUSED_PARAM(renderer);
 #endif
     } else {
         if (resourceMode & ApplyToFillMode) {
             if (path)
                 context->fillPath(*path);
             else if (shape)
-                shape->fillShape(context);
+                shape->fillShape(*context);
         }
         if (resourceMode & ApplyToStrokeMode) {
             if (path)
                 context->strokePath(*path);
             else if (shape)
-                shape->strokeShape(context);
+                shape->strokeShape(*context);
         }
     }
 
@@ -304,5 +259,3 @@ GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(
 }
 
 }
-
-#endif