Infinite repaint loop with SVGImageCache and deferred repaint timers
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Feb 2012 19:41:12 +0000 (19:41 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 24 Feb 2012 19:41:12 +0000 (19:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=78315
<rdar://problem/10651634>

Reviewed by Dean Jackson.

Only defer image redraw on a timer if we're in layout. This breaks
the repaint loop while still preventing us from drawing inside layout.

No new tests, as the problem only occurs in a nonstandard configuration.

* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::draw):
(WebCore::SVGImage::frameView):
(WebCore):
* svg/graphics/SVGImage.h:
(WebCore):
* svg/graphics/SVGImageCache.cpp:
(WebCore::SVGImageCache::imageContentChanged):
(WebCore::SVGImageCache::redraw):
(WebCore::SVGImageCache::redrawTimerFired):
(WebCore):
* svg/graphics/SVGImageCache.h:
(SVGImageCache):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@108834 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImage.h
Source/WebCore/svg/graphics/SVGImageCache.cpp
Source/WebCore/svg/graphics/SVGImageCache.h

index 015ad1a..25ccee0 100644 (file)
@@ -1,5 +1,32 @@
 2012-02-24  Tim Horton  <timothy_horton@apple.com>
 
 2012-02-24  Tim Horton  <timothy_horton@apple.com>
 
+        Infinite repaint loop with SVGImageCache and deferred repaint timers
+        https://bugs.webkit.org/show_bug.cgi?id=78315
+        <rdar://problem/10651634>
+
+        Reviewed by Dean Jackson.
+
+        Only defer image redraw on a timer if we're in layout. This breaks
+        the repaint loop while still preventing us from drawing inside layout.
+
+        No new tests, as the problem only occurs in a nonstandard configuration.
+
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::draw):
+        (WebCore::SVGImage::frameView):
+        (WebCore):
+        * svg/graphics/SVGImage.h:
+        (WebCore):
+        * svg/graphics/SVGImageCache.cpp:
+        (WebCore::SVGImageCache::imageContentChanged):
+        (WebCore::SVGImageCache::redraw):
+        (WebCore::SVGImageCache::redrawTimerFired):
+        (WebCore):
+        * svg/graphics/SVGImageCache.h:
+        (SVGImageCache):
+
+2012-02-24  Tim Horton  <timothy_horton@apple.com>
+
         SVG should be supported in Dashboard compatibility mode
         https://bugs.webkit.org/show_bug.cgi?id=78322
         <rdar://problem/5861278>
         SVG should be supported in Dashboard compatibility mode
         https://bugs.webkit.org/show_bug.cgi?id=78322
         <rdar://problem/5861278>
index 7e1ce28..603974d 100644 (file)
@@ -210,7 +210,7 @@ void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const Fl
     if (!m_page)
         return;
 
     if (!m_page)
         return;
 
-    FrameView* view = m_page->mainFrame()->view();
+    FrameView* view = frameView();
 
     GraphicsContextStateSaver stateSaver(*context);
     context->setCompositeOperation(compositeOp);
 
     GraphicsContextStateSaver stateSaver(*context);
     context->setCompositeOperation(compositeOp);
@@ -255,6 +255,14 @@ RenderBox* SVGImage::embeddedContentBox() const
     return toRenderBox(rootElement->renderer());
 }
 
     return toRenderBox(rootElement->renderer());
 }
 
+FrameView* SVGImage::frameView() const
+{
+    if (!m_page)
+        return 0;
+
+    return m_page->mainFrame()->view();
+}
+
 bool SVGImage::hasRelativeWidth() const
 {
     if (!m_page)
 bool SVGImage::hasRelativeWidth() const
 {
     if (!m_page)
index 7e16049..0fe7b69 100644 (file)
@@ -34,6 +34,7 @@
 
 namespace WebCore {
 
 
 namespace WebCore {
 
+class FrameView;
 class ImageBuffer;
 class Page;
 class RenderBox;
 class ImageBuffer;
 class Page;
 class RenderBox;
@@ -53,6 +54,7 @@ public:
 
     void drawSVGToImageBuffer(ImageBuffer*, const IntSize&, float zoom, ShouldClearBuffer);
     RenderBox* embeddedContentBox() const;
 
     void drawSVGToImageBuffer(ImageBuffer*, const IntSize&, float zoom, ShouldClearBuffer);
     RenderBox* embeddedContentBox() const;
+    FrameView* frameView() const;
 
     virtual bool isSVGImage() const { return true; }
     virtual IntSize size() const;
 
     virtual bool isSVGImage() const { return true; }
     virtual IntSize size() const;
index cd901f4..74add2b 100644 (file)
@@ -21,6 +21,7 @@
 #include "SVGImageCache.h"
 
 #if ENABLE(SVG)
 #include "SVGImageCache.h"
 
 #if ENABLE(SVG)
+#include "FrameView.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "RenderSVGRoot.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "RenderSVGRoot.h"
@@ -81,13 +82,18 @@ void SVGImageCache::imageContentChanged()
     for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it)
         it->second.imageNeedsUpdate = true;
 
     for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it)
         it->second.imageNeedsUpdate = true;
 
-    // Start redrawing dirty images with a timer, as imageContentChanged() may be called
-    // by the FrameView of the SVGImage which is currently in FrameView::layout().
-    if (!m_redrawTimer.isActive())
-        m_redrawTimer.startOneShot(0);
+    // If we're in the middle of layout, start redrawing dirty
+    // images on a timer; otherwise it's safe to draw immediately.
+    
+    FrameView* frameView = m_svgImage->frameView();
+    if (frameView && frameView->needsLayout()) {
+        if (!m_redrawTimer.isActive())
+            m_redrawTimer.startOneShot(0);
+    } else
+        redraw();
 }
 
 }
 
-void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
+void SVGImageCache::redraw()
 {
     ImageDataMap::iterator end = m_imageDataMap.end();
     for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
 {
     ImageDataMap::iterator end = m_imageDataMap.end();
     for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
@@ -105,6 +111,11 @@ void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
     m_svgImage->imageObserver()->animationAdvanced(m_svgImage);
 }
 
     m_svgImage->imageObserver()->animationAdvanced(m_svgImage);
 }
 
+void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
+{
+    redraw();
+}
+
 Image* SVGImageCache::lookupOrCreateBitmapImageForRenderer(const RenderObject* renderer)
 {
     ASSERT(renderer);
 Image* SVGImageCache::lookupOrCreateBitmapImageForRenderer(const RenderObject* renderer)
 {
     ASSERT(renderer);
index 53d2161..46b7093 100644 (file)
@@ -70,6 +70,7 @@ public:
 
 private:
     SVGImageCache(SVGImage*);
 
 private:
     SVGImageCache(SVGImage*);
+    void redraw();
     void redrawTimerFired(Timer<SVGImageCache>*);
 
     struct ImageData {
     void redrawTimerFired(Timer<SVGImageCache>*);
 
     struct ImageData {