Title: [259830] trunk
Revision
259830
Author
commit-qu...@webkit.org
Date
2020-04-09 14:45:57 -0700 (Thu, 09 Apr 2020)

Log Message

REGRESSION: CSS animations inside an embedded SVG image do not animate
https://bugs.webkit.org/show_bug.cgi?id=209370

Patch by Said Abou-Hallawa <sabouhall...@apple.com> on 2020-04-09
Reviewed by Simon Fraser.

Source/WebCore:

If WebAnimation is enabled and the SVGImage includes CSS animations, the
DocumentTimeline is added to the SVGDocument of the embedded SVGImage.
Because the SVGImage has its own Page the RenderingUpdate is scheduled
and the updateRendering steps run in this Page.

The Page of the SVGImage is inactive such that scheduling RenderingUpdate
fails; therefore the updateRendering steps never run and the CSS animation
never advances.

The fix is:

1) Scheduling the RenderingUpdate: This has to happen in the Page which
   contains the renderer of the SVGImage. Because DocumentTimeline is
   added to SVGDocument, this scheduling will go through these hubs:
        - DocumentTimeline
        - Page
        - ChromeClient -> SVGImageChromeClient
        - SVGImage
        - ImageObserver -> CachedImageObserver
        - CachedImage
        - CachedImageClient -> RenderElement
        - Page

2) Running the updateRendering steps: Each document in the Page will
   enumerate its cached SVGImages. The updateRendering of the Page of
   each SVGImage will be called.

To make enumerating the cached SVGImages of a Document faster, the URL
of the cached SVGImage will be added to the cachedSVGImagesURLs of
CachedResourceLoader when notifyFinished() is called for associated
CachedImage.

Tests: svg/animations/css-animation-background-svg.html
       svg/animations/css-animation-embedded-svg.html
       svg/animations/css-animation-hover-svg.html

* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::scheduleAnimationResolution):
(WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
* html/ImageBitmap.cpp:
* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::hasSVGImage const):
(WebCore::CachedImage::CachedImageObserver::scheduleTimedRenderingUpdate):
(WebCore::CachedImage::scheduleTimedRenderingUpdate):
* loader/cache/CachedImage.h:
* loader/cache/CachedImageClient.h:
(WebCore::CachedImageClient::scheduleTimedRenderingUpdate):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::isSVGImageCachedResource):
(WebCore::cachedResourceSVGImage):
(WebCore::CachedResourceLoader::notifyFinished):
(WebCore:: const):
* loader/cache/CachedResourceLoader.h:
* page/ChromeClient.h:
(WebCore::ChromeClient::scheduleTimedRenderingUpdate):
* page/Page.cpp:
(WebCore::Page::scheduleTimedRenderingUpdate):
(WebCore::Page::updateRendering):
* page/Page.h:
* platform/graphics/ImageObserver.h:
* rendering/RenderElement.cpp:
(WebCore::RenderElement::notifyFinished):
(WebCore::RenderElement::scheduleTimedRenderingUpdate):
* rendering/RenderElement.h:
* rendering/RenderImage.cpp:
(WebCore::RenderImage::notifyFinished):
* svg/graphics/SVGImage.h:
* svg/graphics/SVGImageClients.h:

LayoutTests:

* svg/animations/css-animation-background-svg-expected.html: Added.
* svg/animations/css-animation-background-svg.html: Added.
* svg/animations/css-animation-embedded-svg-expected.html: Added.
* svg/animations/css-animation-embedded-svg.html: Added.
* svg/animations/css-animation-hover-svg-expected.html: Added.
* svg/animations/css-animation-hover-svg.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (259829 => 259830)


--- trunk/LayoutTests/ChangeLog	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/LayoutTests/ChangeLog	2020-04-09 21:45:57 UTC (rev 259830)
@@ -1,3 +1,17 @@
+2020-04-09  Said Abou-Hallawa  <sabouhall...@apple.com>
+
+        REGRESSION: CSS animations inside an embedded SVG image do not animate
+        https://bugs.webkit.org/show_bug.cgi?id=209370
+
+        Reviewed by Simon Fraser.
+
+        * svg/animations/css-animation-background-svg-expected.html: Added.
+        * svg/animations/css-animation-background-svg.html: Added.
+        * svg/animations/css-animation-embedded-svg-expected.html: Added.
+        * svg/animations/css-animation-embedded-svg.html: Added.
+        * svg/animations/css-animation-hover-svg-expected.html: Added.
+        * svg/animations/css-animation-hover-svg.html: Added.
+
 2020-04-09  Keith Miller  <keith_mil...@apple.com>
 
         Remove legacy X-WebKit-CSP header support

Added: trunk/LayoutTests/svg/animations/css-animation-background-svg-expected.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-background-svg-expected.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-background-svg-expected.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,11 @@
+<style>
+   	div {
+        width: 100px;
+        height: 100px;
+        display: inline-block;
+        background-color: green;
+    }
+</style>
+<body>
+	<div></div>
+</body>

Added: trunk/LayoutTests/svg/animations/css-animation-background-svg.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-background-svg.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-background-svg.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,39 @@
+<style>
+    .box {
+        width: 100px;
+        height: 100px;
+        background: url("data:image/svg+xml;utf8, \
+            %3Csvg xmlns='http://www.w3.org/2000/svg'%3E \
+                %3Cstyle%3E \
+                    @keyframes fadein { \
+                        from { opacity:0; } \
+                        to { opacity:1; } \
+                    } \
+                    #green { \
+                        animation: fadein 16ms; \
+                    } \
+                %3C/style%3E \
+                %3Crect width='100%' height='100%' fill='red'/%3E \
+                %3Crect id='green' width='100%' height='100%' fill='green'/%3E \
+            %3C/svg%3E");
+    }
+</style>
+<body>
+    <div class="box"></div>
+    <script>
+        window.addEventListener('load', (event) => {
+            if (window.testRunner)
+                testRunner.waitUntilDone();
+
+            var rAFCount = 0;
+            function animate(timestamp) {
+                if (++rAFCount < 10)
+                    window.requestAnimationFrame(animate);
+                else if (window.testRunner)
+                    testRunner.notifyDone();
+            }
+
+            window.requestAnimationFrame(animate);
+        });
+    </script>
+</body>

Added: trunk/LayoutTests/svg/animations/css-animation-embedded-svg-expected.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-embedded-svg-expected.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-embedded-svg-expected.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,11 @@
+<style>
+   	div {
+        width: 100px;
+        height: 100px;
+        display: inline-block;
+        background-color: green;
+    }
+</style>
+<body>
+	<div></div>
+</body>

Added: trunk/LayoutTests/svg/animations/css-animation-embedded-svg.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-embedded-svg.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-embedded-svg.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,38 @@
+<style>
+    img {
+        width: 100px;
+        height: 100px;
+    }
+</style>
+<body>
+    <img src=''>
+    <script>
+        window.addEventListener('load', (event) => {
+            if (window.testRunner)
+                testRunner.waitUntilDone();
+
+            var rAFCount = 0;
+            function animate(timestamp) {
+                if (++rAFCount < 10)
+                    window.requestAnimationFrame(animate);
+                else if (window.testRunner)
+                    testRunner.notifyDone();
+            }
+
+            window.requestAnimationFrame(animate);
+        });
+    </script>
+</body>

Added: trunk/LayoutTests/svg/animations/css-animation-hover-svg-expected.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-hover-svg-expected.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-hover-svg-expected.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,11 @@
+<style>
+   	div {
+        width: 100px;
+        height: 100px;
+        display: inline-block;
+        background-color: green;
+    }
+</style>
+<body>
+	<div></div>
+</body>

Added: trunk/LayoutTests/svg/animations/css-animation-hover-svg.html (0 => 259830)


--- trunk/LayoutTests/svg/animations/css-animation-hover-svg.html	                        (rev 0)
+++ trunk/LayoutTests/svg/animations/css-animation-hover-svg.html	2020-04-09 21:45:57 UTC (rev 259830)
@@ -0,0 +1,44 @@
+<style>
+    .box {
+        width: 100px;
+        height: 100px;
+        background-color: red;
+    }
+    .hover {
+        background: url("data:image/svg+xml;charset=utf8, \
+            %3Csvg xmlns='http://www.w3.org/2000/svg'%3E \
+                %3Cstyle%3E \
+                    @keyframes fadein { \
+                        from { opacity:0; } \
+                        to { opacity:1; } \
+                    } \
+                    #green { \
+                        animation: fadein 16ms; \
+                    } \
+                %3C/style%3E \
+                %3Crect width='100%' height='100%' fill='red'/%3E \
+                %3Crect id='green' width='100%' height='100%' fill='green'/%3E \
+            %3C/svg%3E");
+    }
+</style>
+<body>
+    <div class="box"></div>
+    <script>
+        window.addEventListener('load', (event) => {
+            if (window.testRunner)
+                testRunner.waitUntilDone();
+
+            var rAFCount = 0;
+            function animate(timestamp) {
+                if (++rAFCount < 10)
+                    window.requestAnimationFrame(animate);
+                else if (window.testRunner)
+                    testRunner.notifyDone();
+            }
+
+            var box = document.querySelector(".box");
+            box.classList.add('hover');
+            window.requestAnimationFrame(animate);
+        });
+    </script>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (259829 => 259830)


--- trunk/Source/WebCore/ChangeLog	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/ChangeLog	2020-04-09 21:45:57 UTC (rev 259830)
@@ -1,3 +1,79 @@
+2020-04-09  Said Abou-Hallawa  <sabouhall...@apple.com>
+
+        REGRESSION: CSS animations inside an embedded SVG image do not animate
+        https://bugs.webkit.org/show_bug.cgi?id=209370
+
+        Reviewed by Simon Fraser.
+
+        If WebAnimation is enabled and the SVGImage includes CSS animations, the
+        DocumentTimeline is added to the SVGDocument of the embedded SVGImage.
+        Because the SVGImage has its own Page the RenderingUpdate is scheduled
+        and the updateRendering steps run in this Page.
+
+        The Page of the SVGImage is inactive such that scheduling RenderingUpdate
+        fails; therefore the updateRendering steps never run and the CSS animation
+        never advances.
+
+        The fix is:
+
+        1) Scheduling the RenderingUpdate: This has to happen in the Page which
+           contains the renderer of the SVGImage. Because DocumentTimeline is
+           added to SVGDocument, this scheduling will go through these hubs:
+                - DocumentTimeline
+                - Page
+                - ChromeClient -> SVGImageChromeClient 
+                - SVGImage
+                - ImageObserver -> CachedImageObserver
+                - CachedImage
+                - CachedImageClient -> RenderElement
+                - Page
+
+        2) Running the updateRendering steps: Each document in the Page will
+           enumerate its cached SVGImages. The updateRendering of the Page of
+           each SVGImage will be called.
+
+        To make enumerating the cached SVGImages of a Document faster, the URL
+        of the cached SVGImage will be added to the cachedSVGImagesURLs of
+        CachedResourceLoader when notifyFinished() is called for associated
+        CachedImage.
+
+        Tests: svg/animations/css-animation-background-svg.html
+               svg/animations/css-animation-embedded-svg.html
+               svg/animations/css-animation-hover-svg.html
+
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::scheduleAnimationResolution):
+        (WebCore::DocumentTimeline::updateAnimationsAndSendEvents):
+        * html/ImageBitmap.cpp:
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::hasSVGImage const):
+        (WebCore::CachedImage::CachedImageObserver::scheduleTimedRenderingUpdate):
+        (WebCore::CachedImage::scheduleTimedRenderingUpdate):
+        * loader/cache/CachedImage.h:
+        * loader/cache/CachedImageClient.h:
+        (WebCore::CachedImageClient::scheduleTimedRenderingUpdate):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::isSVGImageCachedResource):
+        (WebCore::cachedResourceSVGImage):
+        (WebCore::CachedResourceLoader::notifyFinished):
+        (WebCore:: const):
+        * loader/cache/CachedResourceLoader.h:
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::scheduleTimedRenderingUpdate):
+        * page/Page.cpp:
+        (WebCore::Page::scheduleTimedRenderingUpdate):
+        (WebCore::Page::updateRendering):
+        * page/Page.h:
+        * platform/graphics/ImageObserver.h:
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::notifyFinished):
+        (WebCore::RenderElement::scheduleTimedRenderingUpdate):
+        * rendering/RenderElement.h:
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::notifyFinished):
+        * svg/graphics/SVGImage.h:
+        * svg/graphics/SVGImageClients.h:
+
 2020-04-09  Keith Miller  <keith_mil...@apple.com>
 
         Remove legacy X-WebKit-CSP header support

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (259829 => 259830)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -339,7 +339,7 @@
     if (!shouldRunUpdateAnimationsAndSendEventsIgnoringSuspensionState())
         return;
 
-    m_document->page()->renderingUpdateScheduler().scheduleTimedRenderingUpdate();
+    m_document->page()->scheduleTimedRenderingUpdate();
     m_animationResolutionScheduled = true;
 }
 
@@ -364,7 +364,6 @@
 
 void DocumentTimeline::updateAnimationsAndSendEvents()
 {
-
     // Updating animations and sending events may invalidate the timing of some animations, so we must set the m_animationResolutionScheduled
     // flag to false prior to running that procedure to allow animation with timing model updates to schedule updates.
     m_animationResolutionScheduled = false;

Modified: trunk/Source/WebCore/html/ImageBitmap.cpp (259829 => 259830)


--- trunk/Source/WebCore/html/ImageBitmap.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/html/ImageBitmap.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -528,6 +528,7 @@
     bool canDestroyDecodedData(const Image&) override { return true; }
     void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* = nullptr, DecodingStatus = DecodingStatus::Invalid) override { }
     void changedInRect(const Image&, const IntRect* = nullptr) override { }
+    void scheduleTimedRenderingUpdate(const Image&) override { }
 
 private:
     ImageBitmapImageObserver(String mimeType, long long expectedContentLength, const URL& sourceUrl)

Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (259829 => 259830)


--- trunk/Source/WebCore/loader/cache/CachedImage.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/loader/cache/CachedImage.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -268,6 +268,11 @@
     return m_image.get();
 }
 
+bool CachedImage::hasSVGImage() const
+{
+    return m_image && m_image->isSVGImage();
+}
+
 void CachedImage::setContainerContextForClient(const CachedImageClient& client, const LayoutSize& containerSize, float containerZoom, const URL& imageURL)
 {
     if (containerSize.isEmpty())
@@ -434,6 +439,12 @@
         cachedImage->changedInRect(image, rect);
 }
 
+void CachedImage::CachedImageObserver::scheduleTimedRenderingUpdate(const Image& image)
+{
+    for (auto cachedImage : m_cachedImages)
+        cachedImage->scheduleTimedRenderingUpdate(image);
+}
+
 inline void CachedImage::clearImage()
 {
     if (!m_image)
@@ -684,6 +695,16 @@
     notifyObservers(rect);
 }
 
+void CachedImage::scheduleTimedRenderingUpdate(const Image& image)
+{
+    if (&image != m_image)
+        return;
+
+    CachedResourceClientWalker<CachedImageClient> walker(m_clients);
+    while (auto* client = walker.next())
+        client->scheduleTimedRenderingUpdate();
+}
+
 bool CachedImage::currentFrameKnownToBeOpaque(const RenderElement* renderer)
 {
     Image* image = imageForRenderer(renderer);

Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (259829 => 259830)


--- trunk/Source/WebCore/loader/cache/CachedImage.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -56,6 +56,7 @@
     WEBCORE_EXPORT Image* image(); // Returns the nullImage() if the image is not available yet.
     WEBCORE_EXPORT Image* imageForRenderer(const RenderObject*); // Returns the nullImage() if the image is not available yet.
     bool hasImage() const { return m_image.get(); }
+    bool hasSVGImage() const;
     bool currentFrameKnownToBeOpaque(const RenderElement*);
 
     std::pair<Image*, float> brokenImage(float deviceScaleFactor) const; // Returns an image and the image's resolution scale factor.
@@ -152,6 +153,7 @@
         bool canDestroyDecodedData(const Image&) final;
         void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* changeRect = nullptr, DecodingStatus = DecodingStatus::Invalid) final;
         void changedInRect(const Image&, const IntRect*) final;
+        void scheduleTimedRenderingUpdate(const Image&) final;
 
         HashSet<CachedImage*> m_cachedImages;
     };
@@ -162,6 +164,7 @@
     bool canDestroyDecodedData(const Image&);
     void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* changeRect = nullptr, DecodingStatus = DecodingStatus::Invalid);
     void changedInRect(const Image&, const IntRect*);
+    void scheduleTimedRenderingUpdate(const Image&);
 
     void updateBufferInternal(SharedBuffer&);
 

Modified: trunk/Source/WebCore/loader/cache/CachedImageClient.h (259829 => 259830)


--- trunk/Source/WebCore/loader/cache/CachedImageClient.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/loader/cache/CachedImageClient.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -48,6 +48,8 @@
     virtual VisibleInViewportState imageFrameAvailable(CachedImage& image, ImageAnimatingState, const IntRect* changeRect) { imageChanged(&image, changeRect); return VisibleInViewportState::No; }
 
     virtual void didRemoveCachedImageClient(CachedImage&) { }
+
+    virtual void scheduleTimedRenderingUpdate() { }
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (259829 => 259830)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -69,6 +69,7 @@
 #include "ResourceTiming.h"
 #include "RuntimeApplicationChecks.h"
 #include "RuntimeEnabledFeatures.h"
+#include "SVGImage.h"
 #include "ScriptController.h"
 #include "SecurityOrigin.h"
 #include "SecurityPolicy.h"
@@ -788,6 +789,20 @@
     return FetchOptions::Destination::EmptyString;
 }
 
+static inline bool isSVGImageCachedResource(const CachedResource* resource)
+{
+    if (!resource || !is<CachedImage>(*resource))
+        return false;
+    return downcast<CachedImage>(*resource).hasSVGImage();
+}
+
+static inline SVGImage* cachedResourceSVGImage(CachedResource* resource)
+{
+    if (!isSVGImageCachedResource(resource))
+        return nullptr;
+    return downcast<SVGImage>(downcast<CachedImage>(*resource).image());
+}
+
 ResourceErrorOr<CachedResourceHandle<CachedResource>> CachedResourceLoader::requestResource(CachedResource::Type type, CachedResourceRequest&& request, ForPreload forPreload, ImageLoading imageLoading)
 {
     if (!frame() || !frame()->page()) {
@@ -1401,6 +1416,25 @@
     ASSERT(m_requestCount > -1);
 }
 
+void CachedResourceLoader::notifyFinished(const CachedResource& resource)
+{
+    if (isSVGImageCachedResource(&resource))
+        m_cachedSVGImagesURLs.add(resource.url());
+}
+
+Vector<Ref<SVGImage>> CachedResourceLoader::allCachedSVGImages() const
+{
+    Vector<Ref<SVGImage>> allCachedSVGImages;
+
+    for (auto& cachedSVGImageURL : m_cachedSVGImagesURLs) {
+        auto* resource = cachedResource(cachedSVGImageURL);
+        if (auto* image = cachedResourceSVGImage(resource))
+            allCachedSVGImages.append(*image);
+    }
+        
+    return allCachedSVGImages;
+}
+
 ResourceErrorOr<CachedResourceHandle<CachedResource>> CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest&& request)
 {
     if (InspectorInstrumentation::willInterceptRequest(frame(), request.resourceRequest()))

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.h (259829 => 259830)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -57,6 +57,7 @@
 class Frame;
 class ImageLoader;
 class Page;
+class SVGImage;
 class Settings;
 
 template <typename T>
@@ -116,6 +117,9 @@
     typedef HashMap<String, CachedResourceHandle<CachedResource>> DocumentResourceMap;
     const DocumentResourceMap& allCachedResources() const { return m_documentResources; }
 
+    void notifyFinished(const CachedResource&);
+    Vector<Ref<SVGImage>> allCachedSVGImages() const;
+
     bool autoLoadImages() const { return m_autoLoadImages; }
     void setAutoLoadImages(bool);
 
@@ -193,6 +197,7 @@
     bool canRequestInContentDispositionAttachmentSandbox(CachedResource::Type, const URL&) const;
 
     HashSet<String> m_validatedURLs;
+    HashSet<String> m_cachedSVGImagesURLs;
     mutable DocumentResourceMap m_documentResources;
     WeakPtr<Document> m_document;
     DocumentLoader* m_documentLoader;

Modified: trunk/Source/WebCore/page/ChromeClient.h (259829 => 259830)


--- trunk/Source/WebCore/page/ChromeClient.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/page/ChromeClient.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -316,6 +316,7 @@
     // Sets a flag to specify that the view needs to be updated, so we need
     // to do an eager layout before the drawing.
     virtual void scheduleRenderingUpdate() = 0;
+    virtual bool scheduleTimedRenderingUpdate() { return false; }
     virtual bool needsImmediateRenderingUpdate() const { return false; }
     // Returns whether or not the client can render the composited layer,
     // regardless of the settings.

Modified: trunk/Source/WebCore/page/Page.cpp (259829 => 259830)


--- trunk/Source/WebCore/page/Page.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/page/Page.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -29,6 +29,7 @@
 #include "BackForwardController.h"
 #include "CSSAnimationController.h"
 #include "CacheStorageProvider.h"
+#include "CachedResourceLoader.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
 #include "ConstantPropertyMap.h"
@@ -104,6 +105,7 @@
 #include "ResourceUsageOverlay.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGDocumentExtensions.h"
+#include "SVGImage.h"
 #include "ScriptController.h"
 #include "ScriptDisallowedScope.h"
 #include "ScriptedAnimationController.h"
@@ -1298,6 +1300,13 @@
     renderingUpdateScheduler().scheduleRenderingUpdate();
 }
 
+void Page::scheduleTimedRenderingUpdate()
+{
+    if (chrome().client().scheduleTimedRenderingUpdate())
+        return;
+    renderingUpdateScheduler().scheduleTimedRenderingUpdate();
+}
+
 // https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering
 void Page::updateRendering()
 {
@@ -1350,6 +1359,13 @@
     });
 #endif
 
+    forEachDocument([] (Document& document) {
+        for (auto& image : document.cachedResourceLoader().allCachedSVGImages()) {
+            if (auto* page = image->internalPage())
+                page->updateRendering();
+        }
+    });
+
     layoutIfNeeded();
     doAfterUpdateRendering();
 }

Modified: trunk/Source/WebCore/page/Page.h (259829 => 259830)


--- trunk/Source/WebCore/page/Page.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/page/Page.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -478,6 +478,7 @@
     WEBCORE_EXPORT void updateRendering();
     
     WEBCORE_EXPORT void scheduleRenderingUpdate();
+    void scheduleTimedRenderingUpdate();
 
     WEBCORE_EXPORT void suspendScriptedAnimations();
     WEBCORE_EXPORT void resumeScriptedAnimations();

Modified: trunk/Source/WebCore/platform/graphics/ImageObserver.h (259829 => 259830)


--- trunk/Source/WebCore/platform/graphics/ImageObserver.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/platform/graphics/ImageObserver.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -50,6 +50,7 @@
     virtual bool canDestroyDecodedData(const Image&) = 0;
     virtual void imageFrameAvailable(const Image&, ImageAnimatingState, const IntRect* changeRect = nullptr, DecodingStatus = DecodingStatus::Invalid) = 0;
     virtual void changedInRect(const Image&, const IntRect* changeRect = nullptr) = 0;
+    virtual void scheduleTimedRenderingUpdate(const Image&) = 0;
 };
 
 }

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (259829 => 259830)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -26,6 +26,7 @@
 #include "RenderElement.h"
 
 #include "AXObjectCache.h"
+#include "CachedResourceLoader.h"
 #if PLATFORM(IOS_FAMILY)
 #include "ContentChangeObserver.h"
 #endif
@@ -1324,6 +1325,11 @@
     return isVisible ? VisibleInViewportState::Yes : VisibleInViewportState::No;
 }
 
+void RenderElement::notifyFinished(CachedResource& resource)
+{
+    document().cachedResourceLoader().notifyFinished(resource);
+}
+
 void RenderElement::didRemoveCachedImageClient(CachedImage& cachedImage)
 {
     if (hasPausedImageAnimations())
@@ -1330,6 +1336,12 @@
         view().removeRendererWithPausedImageAnimations(*this, cachedImage);
 }
 
+void RenderElement::scheduleTimedRenderingUpdate()
+{
+    if (auto* page = document().page())
+        page->scheduleTimedRenderingUpdate();
+}
+
 bool RenderElement::repaintForPausedImageAnimationsIfNeeded(const IntRect& visibleRect, CachedImage& cachedImage)
 {
     ASSERT(m_hasPausedImageAnimations);

Modified: trunk/Source/WebCore/rendering/RenderElement.h (259829 => 259830)


--- trunk/Source/WebCore/rendering/RenderElement.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/rendering/RenderElement.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -263,6 +263,7 @@
     void insertedIntoTree() override;
     void willBeRemovedFromTree() override;
     void willBeDestroyed() override;
+    void notifyFinished(CachedResource&) override;
 
     void setRenderInlineAlwaysCreatesLineBoxes(bool b) { m_renderInlineAlwaysCreatesLineBoxes = b; }
     bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; }
@@ -320,6 +321,7 @@
     bool canDestroyDecodedData() final { return !isVisibleInViewport(); }
     VisibleInViewportState imageFrameAvailable(CachedImage&, ImageAnimatingState, const IntRect* changeRect) final;
     void didRemoveCachedImageClient(CachedImage&) final;
+    void scheduleTimedRenderingUpdate() final;
 
     bool getLeadingCorner(FloatPoint& output, bool& insideFixed) const;
     bool getTrailingCorner(FloatPoint& output, bool& insideFixed) const;

Modified: trunk/Source/WebCore/rendering/RenderImage.cpp (259829 => 259830)


--- trunk/Source/WebCore/rendering/RenderImage.cpp	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/rendering/RenderImage.cpp	2020-04-09 21:45:57 UTC (rev 259830)
@@ -418,6 +418,8 @@
 
     if (is<HTMLImageElement>(element()))
         page().didFinishLoadingImageForElement(downcast<HTMLImageElement>(*element()));
+
+    RenderReplaced::notifyFinished(newImage);
 }
 
 void RenderImage::setImageDevicePixelRatio(float factor)

Modified: trunk/Source/WebCore/svg/graphics/SVGImage.h (259829 => 259830)


--- trunk/Source/WebCore/svg/graphics/SVGImage.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/svg/graphics/SVGImage.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -68,6 +68,8 @@
 #if USE(DIRECT2D)
     NativeImagePtr nativeImage(const GraphicsContext* = nullptr) final;
 #endif
+    
+    Page* internalPage() { return m_page.get(); }
 
 private:
     friend class SVGImageChromeClient;

Modified: trunk/Source/WebCore/svg/graphics/SVGImageClients.h (259829 => 259830)


--- trunk/Source/WebCore/svg/graphics/SVGImageClients.h	2020-04-09 21:31:03 UTC (rev 259829)
+++ trunk/Source/WebCore/svg/graphics/SVGImageClients.h	2020-04-09 21:45:57 UTC (rev 259830)
@@ -62,7 +62,14 @@
 
         imageObserver->imageFrameAvailable(*m_image, m_image->isAnimating() ? ImageAnimatingState::Yes : ImageAnimatingState::No, &r);
     }
-    
+
+    bool scheduleTimedRenderingUpdate() final
+    {
+        if (m_image && m_image->imageObserver())
+            m_image->imageObserver()->scheduleTimedRenderingUpdate(*m_image);
+        return true;
+    }
+
     SVGImage* m_image;
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to