[SVG] Cached filter results are not invalidated on repaint rect change
[WebKit-https.git] / Source / WebCore / rendering / svg / SVGRenderingContext.cpp
index e2adb30..e275932 100644 (file)
@@ -27,6 +27,7 @@
 #if ENABLE(SVG)
 #include "SVGRenderingContext.h"
 
+#include "BasicShapes.h"
 #include "Frame.h"
 #include "FrameView.h"
 #include "RenderSVGResource.h"
@@ -60,6 +61,7 @@ SVGRenderingContext::~SVGRenderingContext()
         ASSERT(m_filter);
         m_filter->postApplyResource(static_cast<RenderSVGShape*>(m_object), m_paintInfo->context, ApplyToDefaultMode, 0, 0);
         m_paintInfo->context = m_savedContext;
+        m_paintInfo->rect = m_savedPaintRect;
     }
 #endif
 
@@ -122,6 +124,12 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
         }
     }
 
+    ClipPathOperation* clipPathOperation = style->clipPath();
+    if (clipPathOperation && clipPathOperation->getOperationType() == ClipPathOperation::SHAPE) {
+        ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(clipPathOperation);
+        m_paintInfo->context->clipPath(clipPath->path(object->objectBoundingBox()), clipPath->windRule());
+    }
+
     SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(m_object);
     if (!resources) {
 #if ENABLE(FILTERS)
@@ -139,7 +147,8 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
         }
     }
 
-    if (RenderSVGResourceClipper* clipper = resources->clipper()) {
+    RenderSVGResourceClipper* clipper = resources->clipper();
+    if (!clipPathOperation && clipper) {
         if (!clipper->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
             return;
     }
@@ -149,11 +158,18 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintI
         m_filter = resources->filter();
         if (m_filter) {
             m_savedContext = m_paintInfo->context;
+            m_savedPaintRect = m_paintInfo->rect;
             // Return with false here may mean that we don't need to draw the content
             // (because it was either drawn before or empty) but we still need to apply the filter.
             m_renderingFlags |= EndFilterLayer;
             if (!m_filter->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
                 return;
+
+            // Since we're caching the resulting bitmap and do not invalidate it on repaint rect
+            // changes, we need to paint the whole filter region. Otherwise, elements not visible
+            // at the time of the initial paint (due to scrolling, window size, etc.) will never
+            // be drawn.
+            m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_object));
         }
     }
 #endif
@@ -205,14 +221,10 @@ bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const A
     GraphicsContext* imageContext = image->context();
     ASSERT(imageContext);
 
-    // This is done in absolute coordinates.
-    imageContext->translate(-paintRect.x(), -paintRect.y());
-
-    imageContext->concatCTM(absoluteTransform);
-
-    // This happens in local coordinates.
     imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
                                   static_cast<float>(clampedSize.height()) / paintRect.height()));
+    imageContext->translate(-paintRect.x(), -paintRect.y());
+    imageContext->concatCTM(absoluteTransform);
 
     imageBuffer = image.release();
     return true;
@@ -247,7 +259,7 @@ void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderO
     ASSERT(image);
     ASSERT(image->context());
 
-    PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0, 0);
+    PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal);
 
     AffineTransform& contentTransformation = currentContentTransformation();
     AffineTransform savedContentTransformation = contentTransformation;