If an image appears more than once on a page, decoding for painting one instance...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 1 Jul 2017 06:23:31 +0000 (06:23 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 1 Jul 2017 06:23:31 +0000 (06:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169944

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2017-06-30
Reviewed by Simon Fraser.

Source/WebCore:

Make the Image::draw*() and GraphicsContext::draw*() functions return an
ImageDrawResult which indicates whether the image is drawn or has requested
an asynchronous image decoding.

If the image requested an asynchronous image decoding, the issuer of the
Image::draw(), which is of type CachedImageClient, will add itself to a
set of m_pendingImageDrawingClients, which owned by CachedImage.

When receiving the imageFrameAvailable() notification for a lrage image
from the decoding thread, CachedImage will loop through the clients that
are only in m_pendingImageDrawingClients to ask them to repaint their
rectangles.

Test: fast/images/async-image-multiple-clients-repaint.html

* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::didRemoveClient):
(WebCore::CachedImage::addPendingImageDrawingClient):
(WebCore::CachedImage::allClientsRemoved):
(WebCore::CachedImage::clear):
(WebCore::CachedImage::imageFrameAvailable):
* loader/cache/CachedImage.h:
* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::draw):
* platform/graphics/BitmapImage.h:
* platform/graphics/CrossfadeGeneratedImage.cpp:
(WebCore::CrossfadeGeneratedImage::draw):
* platform/graphics/CrossfadeGeneratedImage.h:
* platform/graphics/GeneratedImage.h:
* platform/graphics/GradientImage.cpp:
(WebCore::GradientImage::draw):
* platform/graphics/GradientImage.h:
* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::drawImage):
(WebCore::GraphicsContext::drawTiledImage):
* platform/graphics/GraphicsContext.h:
* platform/graphics/Image.cpp:
(WebCore::Image::drawTiled):
* platform/graphics/Image.h:
* platform/graphics/ImageTypes.h:
* platform/graphics/NamedImageGeneratedImage.cpp:
(WebCore::NamedImageGeneratedImage::draw):
* platform/graphics/NamedImageGeneratedImage.h:
* platform/graphics/cg/PDFDocumentImage.cpp:
(WebCore::PDFDocumentImage::draw):
* platform/graphics/cg/PDFDocumentImage.h:
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintFillLayerExtended):
* rendering/RenderImage.cpp:
(WebCore::RenderImage::paintIntoRect):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::drawForContainer):
(WebCore::SVGImage::draw):
* svg/graphics/SVGImage.h:
* svg/graphics/SVGImageForContainer.cpp:
(WebCore::SVGImageForContainer::draw):
* svg/graphics/SVGImageForContainer.h:

LayoutTests:

* fast/images/async-image-multiple-clients-repaint-expected.txt: Added.
* fast/images/async-image-multiple-clients-repaint.html: Added.
* platform/ios-simulator/fast/images: Added.
* platform/ios-simulator/fast/images/async-image-multiple-clients-repaint-expected.txt: Added.

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

29 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/images/async-image-multiple-clients-repaint-expected.txt [new file with mode: 0644]
LayoutTests/fast/images/async-image-multiple-clients-repaint.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator/fast/images/async-image-multiple-clients-repaint-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/cache/CachedImage.cpp
Source/WebCore/loader/cache/CachedImage.h
Source/WebCore/platform/graphics/BitmapImage.cpp
Source/WebCore/platform/graphics/BitmapImage.h
Source/WebCore/platform/graphics/CrossfadeGeneratedImage.cpp
Source/WebCore/platform/graphics/CrossfadeGeneratedImage.h
Source/WebCore/platform/graphics/GeneratedImage.h
Source/WebCore/platform/graphics/GradientImage.cpp
Source/WebCore/platform/graphics/GradientImage.h
Source/WebCore/platform/graphics/GraphicsContext.cpp
Source/WebCore/platform/graphics/GraphicsContext.h
Source/WebCore/platform/graphics/Image.cpp
Source/WebCore/platform/graphics/Image.h
Source/WebCore/platform/graphics/ImageTypes.h
Source/WebCore/platform/graphics/NamedImageGeneratedImage.cpp
Source/WebCore/platform/graphics/NamedImageGeneratedImage.h
Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
Source/WebCore/platform/graphics/cg/PDFDocumentImage.h
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImage.h
Source/WebCore/svg/graphics/SVGImageForContainer.cpp
Source/WebCore/svg/graphics/SVGImageForContainer.h

index b12e5a6..7979727 100644 (file)
@@ -1,3 +1,15 @@
+2017-06-30  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        If an image appears more than once on a page, decoding for painting one instance repaints them all
+        https://bugs.webkit.org/show_bug.cgi?id=169944
+
+        Reviewed by Simon Fraser.
+
+        * fast/images/async-image-multiple-clients-repaint-expected.txt: Added.
+        * fast/images/async-image-multiple-clients-repaint.html: Added.
+        * platform/ios-simulator/fast/images: Added.
+        * platform/ios-simulator/fast/images/async-image-multiple-clients-repaint-expected.txt: Added.
+
 2017-06-30  Jonathan Bedard  <jbedard@apple.com>
 
         Run webgl tests on iOS ports
diff --git a/LayoutTests/fast/images/async-image-multiple-clients-repaint-expected.txt b/LayoutTests/fast/images/async-image-multiple-clients-repaint-expected.txt
new file mode 100644 (file)
index 0000000..96d9311
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+(repaint rects
+  (rect 8 344 200 100)
+  (rect 8 344 200 100)
+  (rect 8 344 200 100)
+  (rect 8 344 200 100)
+  (rect 8 344 200 100)
+)
+
diff --git a/LayoutTests/fast/images/async-image-multiple-clients-repaint.html b/LayoutTests/fast/images/async-image-multiple-clients-repaint.html
new file mode 100644 (file)
index 0000000..3a8f4a6
--- /dev/null
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+    .box {
+        image-rendering: crisp-edges;
+    }
+    .small-box {
+        height: 50px;
+        width: 100px;
+        background-position: -50px -16500px;
+        background-size: 200px 33100px;
+    }
+    .large-box {
+        height: 100px;
+        width: 200px;
+        background-position: -100px -33000px;
+        background-size: 400px 66200px;
+    }
+    .vertical-space {
+        height: 250px;
+        width: 250px;
+    }
+    .image-background {
+    }
+</style>
+</head>
+<body>
+    <div class="box small-box image-background"></div>
+    <br>
+    <div class="vertical-space"></div>
+    <br>
+    <div class="box large-box image-background"></div>
+    <script>
+        function setElementImageBackground(element, image) {
+            return new Promise((resolve) => {
+                element.style.backgroundImage = 'url(' + image.src + ')';
+
+                // Force layout and display so the image frame starts decoding
+                document.body.offsetHeight;
+                testRunner.display();
+                element.addEventListener("webkitImageFrameReady", function() {
+                    resolve();
+                }, false);
+            });
+        }
+
+        function recordAndStopTrackingRepaints() {
+            var repaintRects = window.internals.repaintRectsAsText();
+            internals.stopTrackingRepaints()
+            var pre = document.createElement('pre');
+            document.body.appendChild(pre);
+            pre.innerHTML = repaintRects;
+        }
+
+        (function() {
+            if (window.internals && window.testRunner) {
+                internals.clearMemoryCache();
+                internals.settings.setWebkitImageReadyEventEnabled(true);
+                internals.settings.setLargeImageAsyncDecodingEnabled(true);
+                testRunner.dumpAsText(true);
+                testRunner.waitUntilDone();
+            }
+
+            var image = new Image();
+            image.onload = function() {
+                if (window.internals && window.testRunner) {
+                    setElementImageBackground(document.querySelector(".small-box"), image).then(() => {
+                        // Call the next setElementImageBackground() asynchronously, using setTimeout(, 0),
+                        // to avoid calling testRunner.display() while the webkitImageFrameReady callback of
+                        // the previous setElementImageBackground() still in the call stack.
+                        setTimeout(function() {
+                            internals.startTrackingRepaints();
+                            setElementImageBackground(document.querySelector(".large-box"), image).then(() => {
+                                recordAndStopTrackingRepaints();
+                                testRunner.notifyDone();
+                            });
+                        }, 0);
+                    });
+                } else {
+                    document.querySelector(".small-box").style.backgroundImage = 'url(' + image.src + ')';
+                    document.querySelector(".large-box").style.backgroundImage = 'url(' + image.src + ')';
+                }
+            }
+            image.src = "resources/sprite-sheet-red-green-blue.png";
+        })();
+    </script>
+</body>
+</html>
diff --git a/LayoutTests/platform/ios-simulator/fast/images/async-image-multiple-clients-repaint-expected.txt b/LayoutTests/platform/ios-simulator/fast/images/async-image-multiple-clients-repaint-expected.txt
new file mode 100644 (file)
index 0000000..0c236d5
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+(repaint rects
+  (rect 8 348 200 100)
+  (rect 8 348 200 100)
+  (rect 8 348 200 100)
+  (rect 8 348 200 100)
+  (rect 8 348 200 100)
+)
+
index 4ffdc04..35e2d78 100644 (file)
@@ -1,3 +1,68 @@
+2017-06-30  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        If an image appears more than once on a page, decoding for painting one instance repaints them all
+        https://bugs.webkit.org/show_bug.cgi?id=169944
+
+        Reviewed by Simon Fraser.
+
+        Make the Image::draw*() and GraphicsContext::draw*() functions return an
+        ImageDrawResult which indicates whether the image is drawn or has requested
+        an asynchronous image decoding.
+
+        If the image requested an asynchronous image decoding, the issuer of the
+        Image::draw(), which is of type CachedImageClient, will add itself to a
+        set of m_pendingImageDrawingClients, which owned by CachedImage.
+
+        When receiving the imageFrameAvailable() notification for a lrage image 
+        from the decoding thread, CachedImage will loop through the clients that
+        are only in m_pendingImageDrawingClients to ask them to repaint their
+        rectangles.
+
+        Test: fast/images/async-image-multiple-clients-repaint.html
+
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::didRemoveClient):
+        (WebCore::CachedImage::addPendingImageDrawingClient):
+        (WebCore::CachedImage::allClientsRemoved):
+        (WebCore::CachedImage::clear):
+        (WebCore::CachedImage::imageFrameAvailable):
+        * loader/cache/CachedImage.h:
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::draw):
+        * platform/graphics/BitmapImage.h:
+        * platform/graphics/CrossfadeGeneratedImage.cpp:
+        (WebCore::CrossfadeGeneratedImage::draw):
+        * platform/graphics/CrossfadeGeneratedImage.h:
+        * platform/graphics/GeneratedImage.h:
+        * platform/graphics/GradientImage.cpp:
+        (WebCore::GradientImage::draw):
+        * platform/graphics/GradientImage.h:
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawImage):
+        (WebCore::GraphicsContext::drawTiledImage):
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::drawTiled):
+        * platform/graphics/Image.h:
+        * platform/graphics/ImageTypes.h:
+        * platform/graphics/NamedImageGeneratedImage.cpp:
+        (WebCore::NamedImageGeneratedImage::draw):
+        * platform/graphics/NamedImageGeneratedImage.h:
+        * platform/graphics/cg/PDFDocumentImage.cpp:
+        (WebCore::PDFDocumentImage::draw):
+        * platform/graphics/cg/PDFDocumentImage.h:
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::paintIntoRect):
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::drawForContainer):
+        (WebCore::SVGImage::draw):
+        * svg/graphics/SVGImage.h:
+        * svg/graphics/SVGImageForContainer.cpp:
+        (WebCore::SVGImageForContainer::draw):
+        * svg/graphics/SVGImageForContainer.h:
+
 2017-06-30  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION(r214194): Safari leaves a popup window open opened during before unload
index b2f83a8..236ba8e 100644 (file)
@@ -129,6 +129,7 @@ void CachedImage::didRemoveClient(CachedResourceClient& client)
     ASSERT(client.resourceClientType() == CachedImageClient::expectedType());
 
     m_pendingContainerSizeRequests.remove(&static_cast<CachedImageClient&>(client));
+    m_pendingImageDrawingClients.remove(&static_cast<CachedImageClient&>(client));
 
     if (m_svgImageCache)
         m_svgImageCache->removeClientFromCache(&static_cast<CachedImageClient&>(client));
@@ -138,6 +139,12 @@ void CachedImage::didRemoveClient(CachedResourceClient& client)
     static_cast<CachedImageClient&>(client).didRemoveCachedImageClient(*this);
 }
 
+void CachedImage::addPendingImageDrawingClient(CachedImageClient& client)
+{
+    ASSERT(client.resourceClientType() == CachedImageClient::expectedType());
+    m_pendingImageDrawingClients.add(&client);
+}
+
 void CachedImage::switchClientsToRevalidatedResource()
 {
     ASSERT(is<CachedImage>(resourceToRevalidate()));
@@ -160,6 +167,7 @@ void CachedImage::switchClientsToRevalidatedResource()
 void CachedImage::allClientsRemoved()
 {
     m_pendingContainerSizeRequests.clear();
+    m_pendingImageDrawingClients.clear();
     if (m_image && !errorOccurred())
         m_image->resetAnimation();
 }
@@ -292,6 +300,7 @@ void CachedImage::clear()
     destroyDecodedData();
     clearImage();
     m_pendingContainerSizeRequests.clear();
+    m_pendingImageDrawingClients.clear();
     setEncodedSize(0);
 }
 
@@ -321,6 +330,7 @@ inline void CachedImage::createImage()
                 setContainerSizeForRenderer(request.key, request.value.first, request.value.second);
         }
         m_pendingContainerSizeRequests.clear();
+        m_pendingImageDrawingClients.clear();
     }
 }
 
@@ -540,12 +550,17 @@ void CachedImage::imageFrameAvailable(const Image& image, ImageAnimatingState an
     VisibleInViewportState visibleState = VisibleInViewportState::No;
 
     while (CachedImageClient* client = clientWalker.next()) {
+        // All the clients of animated images have to be notified. The new frame has to be drawn in all of them.
+        if (animatingState == ImageAnimatingState::No && !m_pendingImageDrawingClients.contains(client))
+            continue;
         if (client->imageFrameAvailable(*this, animatingState, changeRect) == VisibleInViewportState::Yes)
             visibleState = VisibleInViewportState::Yes;
     }
 
     if (visibleState == VisibleInViewportState::No && animatingState == ImageAnimatingState::Yes)
         m_image->stopAnimation();
+
+    m_pendingImageDrawingClients.clear();
 }
 
 void CachedImage::changedInRect(const Image& image, const IntRect* rect)
index 336f16e..f095ac2 100644 (file)
@@ -85,6 +85,8 @@ public:
 
     bool isOriginClean(SecurityOrigin*);
 
+    void addPendingImageDrawingClient(CachedImageClient&);
+
 private:
     void clear();
 
@@ -152,6 +154,8 @@ private:
     typedef HashMap<const CachedImageClient*, SizeAndZoom> ContainerSizeRequests;
     ContainerSizeRequests m_pendingContainerSizeRequests;
 
+    HashSet<CachedImageClient*> m_pendingImageDrawingClients;
+
     RefPtr<CachedImageObserver> m_imageObserver;
     RefPtr<Image> m_image;
     std::unique_ptr<SVGImageCache> m_svgImageCache;
index 494144a..546e03d 100644 (file)
@@ -178,13 +178,14 @@ bool BitmapImage::notSolidColor()
 }
 #endif
 
-void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode mode, DecodingMode decodingMode, ImageOrientationDescription description)
+ImageDrawResult BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode mode, DecodingMode decodingMode, ImageOrientationDescription description)
 {
     if (destRect.isEmpty() || srcRect.isEmpty())
-        return;
+        return ImageDrawResult::DidNothing;
 
     FloatSize scaleFactorForDrawing = context.scaleFactorForDrawing(destRect, srcRect);
     IntSize sizeForDrawing = expandedIntSize(size() * scaleFactorForDrawing);
+    ImageDrawResult result = ImageDrawResult::DidDraw;
 
     m_currentSubsamplingLevel = m_allowSubsampling ? m_source.subsamplingLevelForScaleFactor(context, scaleFactorForDrawing) : SubsamplingLevel::Default;
     LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scaleFactorForDrawing = (%.4f, %.4f)]", __FUNCTION__, this, sourceURL().string().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), scaleFactorForDrawing.width(), scaleFactorForDrawing.height());
@@ -205,10 +206,13 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
             m_currentFrameDecodingStatus = ImageFrame::DecodingStatus::Decoding;
         }
 
+        if (m_currentFrameDecodingStatus == ImageFrame::DecodingStatus::Decoding)
+            result = ImageDrawResult::DidRequestDecoding;
+
         if (!frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingMode::Asynchronous)) {
             if (m_showDebugBackground)
                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
-            return;
+            return result;
         }
 
         image = frameImageAtIndex(m_currentFrame);
@@ -219,21 +223,21 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
 
         if (status == StartAnimationStatus::DecodingActive && m_showDebugBackground) {
             fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
-            return;
+            return result;
         }
 
         if (frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingMode::Asynchronous)) {
-            // FIXME: instead of showing the yellow rectangle and returning we need to wait for this the frame to finish decoding.
+            // FIXME: instead of showing the yellow rectangle and returning we need to wait for this frame to finish decoding.
             if (m_showDebugBackground) {
                 fillWithSolidColor(context, destRect, Color(Color::yellow).colorWithAlpha(0.5), op);
                 LOG(Images, "BitmapImage::%s - %p - url: %s [waiting for async decoding to finish]", __FUNCTION__, this, sourceURL().string().utf8().data());
             }
-            return;
+            return ImageDrawResult::DidRequestDecoding;
         }
 
         image = frameImageAtIndexCacheIfNeeded(m_currentFrame, m_currentSubsamplingLevel, &context);
         if (!image) // If it's too early we won't have an image yet.
-            return;
+            return ImageDrawResult::DidNothing;
 
         if (m_currentFrameDecodingStatus != ImageFrame::DecodingStatus::Complete)
             ++m_decodeCountForTesting;
@@ -243,7 +247,7 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
     Color color = singlePixelSolidColor();
     if (color.isValid()) {
         fillWithSolidColor(context, destRect, color, op);
-        return;
+        return result;
     }
 
     ImageOrientation orientation(description.imageOrientation());
@@ -255,6 +259,8 @@ void BitmapImage::draw(GraphicsContext& context, const FloatRect& destRect, cons
 
     if (imageObserver())
         imageObserver()->didDraw(*this);
+
+    return result;
 }
 
 void BitmapImage::drawPattern(GraphicsContext& ctxt, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& transform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
index 33fc29e..c760162 100644 (file)
@@ -154,7 +154,7 @@ protected:
     // |destroyAll| along.
     void destroyDecodedDataIfNecessary(bool destroyAll = true);
 
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
     void drawPattern(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode = BlendModeNormal) override;
 #if PLATFORM(WIN)
     void drawFrameMatchingSourceSize(GraphicsContext&, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) override;
index 3d05264..d9489ab 100644 (file)
@@ -86,7 +86,7 @@ void CrossfadeGeneratedImage::drawCrossfade(GraphicsContext& context)
     context.endTransparencyLayer();
 }
 
-void CrossfadeGeneratedImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
+ImageDrawResult CrossfadeGeneratedImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
 {
     GraphicsContextStateSaver stateSaver(context);
     context.setCompositeOperation(compositeOp, blendMode);
@@ -97,6 +97,7 @@ void CrossfadeGeneratedImage::draw(GraphicsContext& context, const FloatRect& ds
     context.translate(-srcRect.x(), -srcRect.y());
     
     drawCrossfade(context);
+    return ImageDrawResult::DidDraw;
 }
 
 void CrossfadeGeneratedImage::drawPattern(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator compositeOp, BlendMode blendMode)
index ba98ad2..4f85cf3 100644 (file)
@@ -48,7 +48,7 @@ public:
     FloatSize size() const override { return m_crossfadeSize; }
 
 protected:
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
     void drawPattern(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode) override;
 
     CrossfadeGeneratedImage(Image& fromImage, Image& toImage, float percentage, const FloatSize& crossfadeSize, const FloatSize&);
index 3ef7e5f..d5f5b71 100644 (file)
@@ -47,7 +47,7 @@ public:
     void destroyDecodedData(bool /*destroyAll*/ = true) override { }
 
 protected:
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override = 0;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override = 0;
     void drawPattern(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform,
         const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode) override = 0;
 
index 8251440..43f4ff2 100644 (file)
@@ -41,7 +41,7 @@ GradientImage::~GradientImage()
 {
 }
 
-void GradientImage::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
+ImageDrawResult GradientImage::draw(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
 {
     GraphicsContextStateSaver stateSaver(destContext);
     destContext.setCompositeOperation(compositeOp, blendMode);
@@ -51,6 +51,7 @@ void GradientImage::draw(GraphicsContext& destContext, const FloatRect& destRect
         destContext.scale(FloatSize(destRect.width() / srcRect.width(), destRect.height() / srcRect.height()));
     destContext.translate(-srcRect.x(), -srcRect.y());
     destContext.fillRect(FloatRect(FloatPoint(), size()), m_gradient.get());
+    return ImageDrawResult::DidDraw;
 }
 
 void GradientImage::drawPattern(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform,
index 4b925d1..b2226fb 100644 (file)
@@ -44,7 +44,7 @@ public:
 private:
     GradientImage(Gradient&, const FloatSize&);
 
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
     void drawPattern(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode) final;
     bool isGradientImage() const final { return true; }
     void dump(TextStream&) const final;
index 2f73f0f..dff54ff 100644 (file)
@@ -701,12 +701,12 @@ void GraphicsContext::drawBidiText(const FontCascade& font, const TextRun& run,
     bidiRuns.clear();
 }
 
-void GraphicsContext::drawImage(Image& image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
+ImageDrawResult GraphicsContext::drawImage(Image& image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
 {
-    drawImage(image, FloatRect(destination, image.size()), FloatRect(FloatPoint(), image.size()), imagePaintingOptions);
+    return drawImage(image, FloatRect(destination, image.size()), FloatRect(FloatPoint(), image.size()), imagePaintingOptions);
 }
 
-void GraphicsContext::drawImage(Image& image, const FloatRect& destination, const ImagePaintingOptions& imagePaintingOptions)
+ImageDrawResult GraphicsContext::drawImage(Image& image, const FloatRect& destination, const ImagePaintingOptions& imagePaintingOptions)
 {
 #if PLATFORM(IOS)
     FloatRect srcRect(FloatPoint(), image.originalSize());
@@ -714,56 +714,55 @@ void GraphicsContext::drawImage(Image& image, const FloatRect& destination, cons
     FloatRect srcRect(FloatPoint(), image.size());
 #endif
         
-    drawImage(image, destination, srcRect, imagePaintingOptions);
+    return drawImage(image, destination, srcRect, imagePaintingOptions);
 }
 
-void GraphicsContext::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
+ImageDrawResult GraphicsContext::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
 {
     if (paintingDisabled())
-        return;
+        return ImageDrawResult::DidNothing;
 
     if (isRecording()) {
         m_displayListRecorder->drawImage(image, destination, source, imagePaintingOptions);
-        return;
+        return ImageDrawResult::DidRecord;
     }
 
     InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
-    image.draw(*this, destination, source, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_decodingMode, imagePaintingOptions.m_orientationDescription);
+    return image.draw(*this, destination, source, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_decodingMode, imagePaintingOptions.m_orientationDescription);
 }
 
-void GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
+ImageDrawResult GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
 {
     if (paintingDisabled())
-        return;
+        return ImageDrawResult::DidNothing;
 
     if (isRecording()) {
         m_displayListRecorder->drawTiledImage(image, destination, source, tileSize, spacing, imagePaintingOptions);
-        return;
+        return ImageDrawResult::DidRecord;
     }
 
     InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
-    image.drawTiled(*this, destination, source, tileSize, spacing, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_decodingMode);
+    return image.drawTiled(*this, destination, source, tileSize, spacing, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_decodingMode);
 }
 
-void GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor,
+ImageDrawResult GraphicsContext::drawTiledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor,
     Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
 {
     if (paintingDisabled())
-        return;
+        return ImageDrawResult::DidNothing;
 
     if (isRecording()) {
         m_displayListRecorder->drawTiledImage(image, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions);
-        return;
+        return ImageDrawResult::DidRecord;
     }
 
     if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
         // Just do a scale.
-        drawImage(image, destination, source, imagePaintingOptions);
-        return;
+        return drawImage(image, destination, source, imagePaintingOptions);
     }
 
     InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality);
-    image.drawTiled(*this, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions.m_compositeOperator);
+    return image.drawTiled(*this, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions.m_compositeOperator);
 }
 
 void GraphicsContext::drawImageBuffer(ImageBuffer& image, const FloatPoint& destination, const ImagePaintingOptions& imagePaintingOptions)
index 52f7de2..1fc042a 100644 (file)
@@ -358,12 +358,12 @@ public:
 
     WEBCORE_EXPORT void strokeRect(const FloatRect&, float lineWidth);
 
-    WEBCORE_EXPORT void drawImage(Image&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions());
-    WEBCORE_EXPORT void drawImage(Image&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions());
-    void drawImage(Image&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions());
+    WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions());
+    WEBCORE_EXPORT ImageDrawResult drawImage(Image&, const FloatRect& destination, const ImagePaintingOptions& = ImagePaintingOptions());
+    ImageDrawResult drawImage(Image&, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& = ImagePaintingOptions());
 
-    void drawTiledImage(Image&, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& = ImagePaintingOptions());
-    void drawTiledImage(Image&, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor,
+    ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& = ImagePaintingOptions());
+    ImageDrawResult drawTiledImage(Image&, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor,
         Image::TileRule, Image::TileRule, const ImagePaintingOptions& = ImagePaintingOptions());
 
     WEBCORE_EXPORT void drawImageBuffer(ImageBuffer&, const FloatPoint& destination, const ImagePaintingOptions& = ImagePaintingOptions());
index 8ed56b0..b586bfe 100644 (file)
@@ -95,12 +95,12 @@ void Image::fillWithSolidColor(GraphicsContext& ctxt, const FloatRect& dstRect,
     ctxt.setCompositeOperation(previousOperator);
 }
 
-void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode, DecodingMode decodingMode)
+ImageDrawResult Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode, DecodingMode decodingMode)
 {
     Color color = singlePixelSolidColor();
     if (color.isValid()) {
         fillWithSolidColor(ctxt, destRect, color, op);
-        return;
+        return ImageDrawResult::DidDraw;
     }
 
     ASSERT(!isBitmapImage() || notSolidColor());
@@ -131,8 +131,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const Fl
         visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
         visibleSrcRect.setWidth(destRect.width() / scale.width());
         visibleSrcRect.setHeight(destRect.height() / scale.height());
-        draw(ctxt, destRect, visibleSrcRect, op, blendMode, decodingMode, ImageOrientationDescription());
-        return;
+        return draw(ctxt, destRect, visibleSrcRect, op, blendMode, decodingMode, ImageOrientationDescription());
     }
 
 #if PLATFORM(IOS)
@@ -144,8 +143,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const Fl
             visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
             visibleSrcRect.setWidth(1);
             visibleSrcRect.setHeight(destRect.height() / scale.height());
-            draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
-            return;
+            return draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
         }
         if (size().height() == 1 && intersection(oneTileRect, destRect).width() == destRect.width()) {
             FloatRect visibleSrcRect;
@@ -153,8 +151,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const Fl
             visibleSrcRect.setY(0);
             visibleSrcRect.setWidth(destRect.width() / scale.width());
             visibleSrcRect.setHeight(1);
-            draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
-            return;
+            return draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
         }
     }
 #endif
@@ -177,6 +174,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const Fl
 
         currentTileRect.shiftYEdgeTo(destRect.y());
         float toY = currentTileRect.y();
+        ImageDrawResult result = ImageDrawResult::DidNothing;
         while (toY < destRect.maxY()) {
             currentTileRect.shiftXEdgeTo(destRect.x());
             float toX = currentTileRect.x();
@@ -185,30 +183,32 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const Fl
                 FloatRect fromRect(toFloatPoint(currentTileRect.location() - oneTileRect.location()), currentTileRect.size());
                 fromRect.scale(1 / scale.width(), 1 / scale.height());
 
-                draw(ctxt, toRect, fromRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
+                result = draw(ctxt, toRect, fromRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription());
+                if (result == ImageDrawResult::DidRequestDecoding)
+                    return result;
                 toX += currentTileRect.width();
                 currentTileRect.shiftXEdgeTo(oneTileRect.x());
             }
             toY += currentTileRect.height();
             currentTileRect.shiftYEdgeTo(oneTileRect.y());
         }
-        return;
+        return result;
     }
 
     AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height());
     FloatRect tileRect(FloatPoint(), intrinsicTileSize);
     drawPattern(ctxt, destRect, tileRect, patternTransform, oneTileRect.location(), spacing, op, blendMode);
     startAnimation();
+    return ImageDrawResult::DidDraw;
 }
 
 // FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
-void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
-    const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
+ImageDrawResult Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
 {    
     Color color = singlePixelSolidColor();
     if (color.isValid()) {
         fillWithSolidColor(ctxt, dstRect, color, op);
-        return;
+        return ImageDrawResult::DidDraw;
     }
     
     FloatSize tileScale = tileScaleFactor;
@@ -226,7 +226,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const Flo
     case SpaceTile: {
         int numItems = floorf(dstRect.width() / srcRect.width());
         if (!numItems)
-            return;
+            return ImageDrawResult::DidNothing;
         spacing.setWidth((dstRect.width() - srcRect.width() * numItems) / (numItems + 1));
         tileScale.setWidth(1);
         centerOnGapHorizonally = !(numItems & 1);
@@ -246,7 +246,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const Flo
     case SpaceTile: {
         int numItems = floorf(dstRect.height() / srcRect.height());
         if (!numItems)
-            return;
+            return ImageDrawResult::DidNothing;
         spacing.setHeight((dstRect.height() - srcRect.height() * numItems) / (numItems + 1));
         tileScale.setHeight(1);
         centerOnGapVertically = !(numItems & 1);
@@ -279,6 +279,7 @@ void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const Flo
     FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
     drawPattern(ctxt, dstRect, srcRect, patternTransform, patternPhase, spacing, op);
     startAnimation();
+    return ImageDrawResult::DidDraw;
 }
 
 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
index 3b5c5da..af514db 100644 (file)
@@ -191,9 +191,9 @@ protected:
 #if PLATFORM(WIN)
     virtual void drawFrameMatchingSourceSize(GraphicsContext&, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) { }
 #endif
-    virtual void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) = 0;
-    void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, const FloatSize& spacing, CompositeOperator, BlendMode, DecodingMode);
-    void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator);
+    virtual ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) = 0;
+    ImageDrawResult drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, const FloatSize& spacing, CompositeOperator, BlendMode, DecodingMode);
+    ImageDrawResult drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator);
 
     // Supporting tiled drawing
     virtual Color singlePixelSolidColor() const { return Color(); }
index db61212..ba7b254 100644 (file)
@@ -78,4 +78,11 @@ enum class EncodedDataStatus {
     Complete
 };
 
+enum class ImageDrawResult {
+    DidNothing,
+    DidRequestDecoding,
+    DidRecord,
+    DidDraw
+};
+
 }
index 7a56b5a..a300e0f 100644 (file)
@@ -40,7 +40,7 @@ NamedImageGeneratedImage::NamedImageGeneratedImage(String name, const FloatSize&
     setContainerSize(size);
 }
 
-void NamedImageGeneratedImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
+ImageDrawResult NamedImageGeneratedImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
 {
 #if USE(NEW_THEME) || PLATFORM(IOS)
     GraphicsContextStateSaver stateSaver(context);
@@ -52,12 +52,14 @@ void NamedImageGeneratedImage::draw(GraphicsContext& context, const FloatRect& d
     context.translate(-srcRect.x(), -srcRect.y());
 
     platformTheme()->drawNamedImage(m_name, context, dstRect);
+    return ImageDrawResult::DidDraw;
 #else
     UNUSED_PARAM(context);
     UNUSED_PARAM(dstRect);
     UNUSED_PARAM(srcRect);
     UNUSED_PARAM(compositeOp);
     UNUSED_PARAM(blendMode);
+    return ImageDrawResult::DidNothing;
 #endif
 }
 
index 4858d52..129a7bb 100644 (file)
@@ -40,7 +40,7 @@ public:
     }
 
 protected:
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
     void drawPattern(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, CompositeOperator, BlendMode) override;
 
     NamedImageGeneratedImage(String name, const FloatSize&);
index 96d1800..7efee4d 100644 (file)
@@ -263,10 +263,10 @@ void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext& context, const
     decodedSizeChanged(internalSize.unclampedArea() * 4);
 }
 
-void PDFDocumentImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op, BlendMode, DecodingMode, ImageOrientationDescription)
+ImageDrawResult PDFDocumentImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op, BlendMode, DecodingMode, ImageOrientationDescription)
 {
     if (!m_document || !m_hasPage)
-        return;
+        return ImageDrawResult::DidNothing;
 
     updateCachedImageIfNeeded(context, dstRect, srcRect);
 
@@ -289,6 +289,8 @@ void PDFDocumentImage::draw(GraphicsContext& context, const FloatRect& dstRect,
 
     if (imageObserver())
         imageObserver()->didDraw(*this);
+
+    return ImageDrawResult::DidDraw;
 }
 
 void PDFDocumentImage::destroyDecodedData(bool)
index 96eb83c..b1c9528 100644 (file)
@@ -72,7 +72,7 @@ private:
     void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) override;
     FloatSize size() const override;
 
-    void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) override;
 
     // FIXME: Implement this to be less conservative.
     bool currentFrameKnownToBeOpaque() const override { return false; }
index 5eb511c..8bbf0a4 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "BitmapImage.h"
 #include "BorderEdge.h"
+#include "CachedImage.h"
 #include "FloatRoundedRect.h"
 #include "Frame.h"
 #include "FrameView.h"
@@ -883,7 +884,11 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
 
             auto interpolation = chooseInterpolationQuality(context, *image, &bgLayer, geometry.tileSize());
             auto decodingMode = (paintInfo.paintBehavior & (PaintBehaviorFlattenCompositingLayers | PaintBehaviorSnapshotting)) ? DecodingMode::Synchronous : DecodingMode::Asynchronous;
-            context.drawTiledImage(*image, geometry.destRect(), toLayoutPoint(geometry.relativePhase()), geometry.tileSize(), geometry.spaceSize(), ImagePaintingOptions(compositeOp, bgLayer.blendMode(), decodingMode, ImageOrientationDescription(), interpolation));
+            auto drawResult = context.drawTiledImage(*image, geometry.destRect(), toLayoutPoint(geometry.relativePhase()), geometry.tileSize(), geometry.spaceSize(), ImagePaintingOptions(compositeOp, bgLayer.blendMode(), decodingMode, ImageOrientationDescription(), interpolation));
+            if (drawResult == ImageDrawResult::DidRequestDecoding) {
+                ASSERT(bgImage->isCachedImage());
+                bgImage->cachedImage()->addPendingImageDrawingClient(*this);
+            }
         }
     }
 
index 733c9e7..b84617d 100644 (file)
@@ -586,7 +586,9 @@ void RenderImage::paintIntoRect(PaintInfo& paintInfo, const FloatRect& rect)
     ImageOrientationDescription orientationDescription(shouldRespectImageOrientation(), style().imageOrientation());
 
     auto decodingMode = (paintInfo.paintBehavior & (PaintBehaviorFlattenCompositingLayers | PaintBehaviorSnapshotting)) ? DecodingMode::Synchronous : DecodingMode::Asynchronous;
-    paintInfo.context().drawImage(*img, rect, ImagePaintingOptions(compositeOperator, BlendModeNormal, decodingMode, orientationDescription, interpolation));
+    auto drawResult = paintInfo.context().drawImage(*img, rect, ImagePaintingOptions(compositeOperator, BlendModeNormal, decodingMode, orientationDescription, interpolation));
+    if (drawResult == ImageDrawResult::DidRequestDecoding)
+        imageResource().cachedImage()->addPendingImageDrawingClient(*this);
 }
 
 bool RenderImage::boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
index b3897e2..364bd97 100644 (file)
@@ -165,11 +165,11 @@ IntSize SVGImage::containerSize() const
     return IntSize(300, 150);
 }
 
-void SVGImage::drawForContainer(GraphicsContext& context, const FloatSize containerSize, float zoom, const FloatRect& dstRect,
+ImageDrawResult SVGImage::drawForContainer(GraphicsContext& context, const FloatSize containerSize, float zoom, const FloatRect& dstRect,
     const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode)
 {
     if (!m_page)
-        return;
+        return ImageDrawResult::DidNothing;
 
     ImageObserver* observer = imageObserver();
     ASSERT(observer);
@@ -188,9 +188,10 @@ void SVGImage::drawForContainer(GraphicsContext& context, const FloatSize contai
     adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height());
     scaledSrc.setSize(adjustedSrcSize);
 
-    draw(context, dstRect, scaledSrc, compositeOp, blendMode, DecodingMode::Synchronous, ImageOrientationDescription());
+    ImageDrawResult result = draw(context, dstRect, scaledSrc, compositeOp, blendMode, DecodingMode::Synchronous, ImageOrientationDescription());
 
     setImageObserver(observer);
+    return result;
 }
 
 #if USE(CAIRO)
@@ -276,10 +277,10 @@ void SVGImage::drawPatternForContainer(GraphicsContext& context, const FloatSize
     image->drawPattern(context, dstRect, scaledSrcRect, unscaledPatternTransform, phase, spacing, compositeOp, blendMode);
 }
 
-void SVGImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
+ImageDrawResult SVGImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
 {
     if (!m_page)
-        return;
+        return ImageDrawResult::DidNothing;
 
     FrameView* view = frameView();
     ASSERT(view);
@@ -322,6 +323,8 @@ void SVGImage::draw(GraphicsContext& context, const FloatRect& dstRect, const Fl
 
     if (imageObserver())
         imageObserver()->didDraw(*this);
+
+    return ImageDrawResult::DidDraw;
 }
 
 RenderBox* SVGImage::embeddedContentBox() const
index 4648508..0eb5f93 100644 (file)
@@ -97,8 +97,8 @@ private:
     void dump(TextStream&) const final;
 
     SVGImage(ImageObserver&, const URL&);
-    void draw(GraphicsContext&, const FloatRect& fromRect, const FloatRect& toRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
-    void drawForContainer(GraphicsContext&, const FloatSize, float, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode);
+    ImageDrawResult draw(GraphicsContext&, const FloatRect& fromRect, const FloatRect& toRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
+    ImageDrawResult drawForContainer(GraphicsContext&, const FloatSize, float, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode);
     void drawPatternForContainer(GraphicsContext&, const FloatSize& containerSize, float zoom, const FloatRect& srcRect, const AffineTransform&, const FloatPoint& phase, const FloatSize& spacing,
         CompositeOperator, const FloatRect&, BlendMode);
 
index 4fb1bff..7cbfbe7 100644 (file)
@@ -34,10 +34,10 @@ FloatSize SVGImageForContainer::size() const
     return FloatSize(roundedIntSize(scaledContainerSize));
 }
 
-void SVGImageForContainer::draw(GraphicsContext& context, const FloatRect& dstRect,
+ImageDrawResult SVGImageForContainer::draw(GraphicsContext& context, const FloatRect& dstRect,
     const FloatRect& srcRect, CompositeOperator compositeOp, BlendMode blendMode, DecodingMode, ImageOrientationDescription)
 {
-    m_image->drawForContainer(context, m_containerSize, m_zoom, dstRect, srcRect, compositeOp, blendMode);
+    return m_image->drawForContainer(context, m_containerSize, m_zoom, dstRect, srcRect, compositeOp, blendMode);
 }
 
 void SVGImageForContainer::drawPattern(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, const AffineTransform& patternTransform,
index 83c1e25..cf8bbdd 100644 (file)
@@ -55,7 +55,7 @@ public:
         m_image->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
     }
 
-    void draw(GraphicsContext&, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
+    ImageDrawResult draw(GraphicsContext&, const FloatRect&, const FloatRect&, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) final;
 
     void drawPattern(GraphicsContext&, const FloatRect&, const FloatRect&, const AffineTransform&, const FloatPoint&, const FloatSize&, CompositeOperator, BlendMode) final;