Diff
Modified: trunk/LayoutTests/ChangeLog (221804 => 221805)
--- trunk/LayoutTests/ChangeLog 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/LayoutTests/ChangeLog 2017-09-09 03:09:09 UTC (rev 221805)
@@ -1,3 +1,21 @@
+2017-09-08 Said Abou-Hallawa <sabouhall...@apple.com>
+
+ Implement HTMLImageElement.decoode() method
+ https://bugs.webkit.org/show_bug.cgi?id=176016
+
+ Reviewed by Simon Fraser.
+
+ * fast/images/decode-animated-image-expected.html: Added.
+ * fast/images/decode-animated-image.html: Added.
+ * fast/images/decode-render-animated-image-expected.html: Added.
+ * fast/images/decode-render-animated-image.html: Added.
+ * fast/images/decode-render-static-image-expected.html: Added.
+ * fast/images/decode-render-static-image.html: Added.
+ * fast/images/decode-static-image-reject-expected.txt: Added.
+ * fast/images/decode-static-image-reject.html: Added.
+ * fast/images/decode-static-image-resolve-expected.html: Added.
+ * fast/images/decode-static-image-resolve.html: Added.
+
2017-09-08 Joseph Pecoraro <pecor...@apple.com>
Fetch's Response.statusText is unexpectedly the full http status line for HTTP/2 responses
Added: trunk/LayoutTests/fast/images/decode-animated-image-expected.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-animated-image-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-animated-image-expected.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,11 @@
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+</style>
+<body>
+ <p>This tests calling decode() multiple times for an animated image.</p>
+ <div></div>
+</body>
\ No newline at end of file
Added: trunk/LayoutTests/fast/images/decode-animated-image.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-animated-image.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-animated-image.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,27 @@
+<style>
+ canvas {
+ width: 100px;
+ height: 100px;
+ }
+</style>
+<body>
+ <p>This tests calling decode() multiple times for an animated image.</p>
+ <canvas></canvas>
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+ var image = new Image;
+ image.src = ""
+ // First decode() will decode the red frame.
+ image.decode().then(() => {
+ // Second decode() will decode the green frame.
+ image.decode().then(() => {
+ let canvas = document.querySelector("canvas");
+ let context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
+ if (window.testRunner)
+ testRunner.notifyDone();
+ });
+ });
+ </script>
+</body>
Added: trunk/LayoutTests/fast/images/decode-render-animated-image-expected.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-render-animated-image-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-render-animated-image-expected.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,11 @@
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: blue;
+ }
+</style>
+<body>
+ <p>This tests calling decode() for a animated image which is also an element in the DOM tree.</p>
+ <div></div>
+</body>
Added: trunk/LayoutTests/fast/images/decode-render-animated-image.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-render-animated-image.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-render-animated-image.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,55 @@
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ }
+ canvas {
+ width: 100px;
+ height: 100px;
+ background-color: black;
+ }
+ img {
+ max-width: 100%;
+ max-height: 100%;
+ }
+</style>
+<body>
+ <p>This tests calling decode() for a animated image which is also an element in the DOM tree.</p>
+ <canvas></canvas>
+ <div></div>
+ <script>
+ if (window.internals && window.testRunner) {
+ internals.clearMemoryCache();
+ internals.settings.setWebkitImageReadyEventEnabled(true);
+ testRunner.waitUntilDone();
+ }
+
+ var image = new Image;
+ var parent = document.querySelector("div");
+ parent.appendChild(image);
+
+ image._onload_ = (() => {
+ if (window.internals && window.testRunner) {
+ // Force layout and display so the image gets drawn. The image will draw its red frame.
+ document.body.offsetHeight;
+ testRunner.display();
+
+ // Wait till decoding the next (green) frame finishes and the animation advances to it.
+ image.addEventListener("webkitImageFrameReady", function() {
+ setTimeout(function() {
+ // Request decoding the next (blue) frame. Wait till decoding finishes and the
+ // animation advances to it.
+ image.decode().then(() => {
+ var canvas = document.querySelector("canvas");
+ var context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
+ parent.remove();
+ testRunner.notifyDone();
+ });
+ }, 0);
+ });
+ }
+ });
+ image.src = ""
+ </script>
+</body>
Added: trunk/LayoutTests/fast/images/decode-render-static-image-expected.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-render-static-image-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-render-static-image-expected.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,11 @@
+<style>
+ div {
+ width: 200px;
+ height: 200px;
+ background-color: green;
+ }
+</style>
+<body>
+ <p>This tests calling decode() for a static image which is also an element in the DOM tree.</p>
+ <div></div>
+</body>
Added: trunk/LayoutTests/fast/images/decode-render-static-image.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-render-static-image.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-render-static-image.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,56 @@
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ }
+ img {
+ max-width: 100%;
+ max-height: 100%;
+ }
+</style>
+<body>
+ <p>This tests calling decode() for a static image which is also an element in the DOM tree.</p>
+ <div></div>
+ <script>
+ if (window.internals && window.testRunner) {
+ internals.clearMemoryCache();
+ internals.settings.setWebkitImageReadyEventEnabled(true);
+ internals.settings.setLargeImageAsyncDecodingEnabled(true);
+ testRunner.waitUntilDone();
+ }
+
+ var image = new Image;
+ var parent = document.querySelector("div");
+ parent.appendChild(image);
+
+ image._onload_ = (() => {
+ if (window.internals && window.testRunner) {
+ // Force async image decoding for this image.
+ internals.setLargeImageAsyncDecodingEnabledForTesting(image, true);
+
+ // Force layout and display so the image gets drawn.
+ document.body.offsetHeight;
+ testRunner.display();
+
+ // testRunner.display() requests an async image decoding. Wait till it finishes.
+ image.addEventListener("webkitImageFrameReady", function() {
+ // Execute this code in the next loop run.
+ setTimeout(function() {
+ testRunner.display();
+ // The image frame was decoded for the renderer which is (100x100). This
+ // decode() will request a new decoding with the native size which is (400x400).
+ image.decode().then(() => {
+ parent.style.width = "200px";
+ parent.style.height = "200px";
+ // No extra decoding is required to display the image after changing its size.
+ // The image frame was decoded with the native size which is the maximum size
+ // that an image can be decoded with.
+ testRunner.notifyDone();
+ });
+ }, 0);
+ });
+ }
+ });
+ image.src = ""
+ </script>
+</body>
Added: trunk/LayoutTests/fast/images/decode-static-image-reject-expected.txt (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-static-image-reject-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/images/decode-static-image-reject-expected.txt 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,12 @@
+Test rejecting the decode() promise when loading the image fails.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Failed to decode image with no source. Result is: EncodingError: Missing source URL.
+Failed to decode image with non-existent source. Result is: EncodingError: Loading error.
+Failed to decode image with unsupported image format. Result is: EncodingError: Loading error.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/images/decode-static-image-reject.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-static-image-reject.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-static-image-reject.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,28 @@
+<head>
+ <script src=""
+</head>
+<body>
+ <div></div>
+ <script>
+ description("Test rejecting the decode() promise when loading the image fails.");
+ jsTestIsAsync = true;
+
+ var image = new Image;
+ image.decode()
+ .catch(reason => {
+ debug("Failed to decode image with no source. Result is: " + reason);
+ image.src = ""
+ return image.decode();
+ })
+ .catch(reason => {
+ debug("Failed to decode image with non-existent source. Result is: " + reason);
+ image.src = ""
+ return image.decode();
+ })
+ .catch(reason => {
+ debug("Failed to decode image with unsupported image format. Result is: " + reason);
+ finishJSTest();
+ });
+ </script>
+ <script src=""
+</body>
Added: trunk/LayoutTests/fast/images/decode-static-image-resolve-expected.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-static-image-resolve-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-static-image-resolve-expected.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,11 @@
+<style>
+ div {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ }
+</style>
+<body>
+ <p>This tests resolving the decode() promise when loading and decoding a static image succeeds.</p>
+ <div></div>
+</body>
\ No newline at end of file
Added: trunk/LayoutTests/fast/images/decode-static-image-resolve.html (0 => 221805)
--- trunk/LayoutTests/fast/images/decode-static-image-resolve.html (rev 0)
+++ trunk/LayoutTests/fast/images/decode-static-image-resolve.html 2017-09-09 03:09:09 UTC (rev 221805)
@@ -0,0 +1,24 @@
+<style>
+ canvas {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+</style>
+<body>
+ <p>This tests resolving the decode() promise when loading and decoding a static image succeeds.</p>
+ <canvas></canvas>
+ <script>
+ if (window.testRunner)
+ testRunner.waitUntilDone();
+ var image = new Image;
+ image.src = ""
+ image.decode().then(() => {
+ let canvas = document.querySelector("canvas");
+ let context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, canvas.width, canvas.height);
+ if (window.testRunner)
+ testRunner.notifyDone();
+ });
+ </script>
+</body>
Modified: trunk/Source/WebCore/ChangeLog (221804 => 221805)
--- trunk/Source/WebCore/ChangeLog 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/ChangeLog 2017-09-09 03:09:09 UTC (rev 221805)
@@ -1,3 +1,48 @@
+2017-09-08 Said Abou-Hallawa <sabouhall...@apple.com>
+
+ Implement HTMLImageElement.decoode() method
+ https://bugs.webkit.org/show_bug.cgi?id=176016
+
+ Reviewed by Simon Fraser.
+
+ The specs is:
+ https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode.
+
+ -- img.decode() waits till loading the image finishes. Otherwise it starts
+ decoding the image immediately.
+ -- If the image frame is already decoded, the promise will be resolved
+ before return.
+ -- If an error happens in loading the image or decoding the image frame,
+ the promise will be rejected with 'EncodingError' exception.
+ -- Animated image resolves the promise when the next frame is decoded and
+ the animation is advanced it. If the image is not displayed, decode() will
+ request the decoding the first frame and start animating the image.
+
+ Tests: fast/images/decode-animated-image.html
+ fast/images/decode-render-animated-image.html
+ fast/images/decode-render-static-image.html
+ fast/images/decode-static-image-reject.html
+ fast/images/decode-static-image-resolve.html
+
+ * html/HTMLImageElement.cpp:
+ (WebCore::HTMLImageElement::decode):
+ * html/HTMLImageElement.h:
+ * html/HTMLImageElement.idl:
+ * loader/ImageLoader.cpp:
+ (WebCore::ImageLoader::notifyFinished):
+ (WebCore::ImageLoader::decode):
+ (WebCore::ImageLoader::decodeError):
+ * loader/ImageLoader.h:
+ (WebCore::ImageLoader::hasPendingDecodePromise const):
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::internalStartAnimation):
+ (WebCore::BitmapImage::internalAdvanceAnimation):
+ (WebCore::BitmapImage::decode):
+ (WebCore::BitmapImage::imageFrameAvailableAtIndex):
+ * platform/graphics/BitmapImage.h:
+ * platform/graphics/Image.h:
+ (WebCore::Image::decode):
+
2017-09-08 Joseph Pecoraro <pecor...@apple.com>
Fetch's Response.statusText is unexpectedly the full http status line for HTTP/2 responses
Modified: trunk/Source/WebCore/html/HTMLImageElement.cpp (221804 => 221805)
--- trunk/Source/WebCore/html/HTMLImageElement.cpp 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/html/HTMLImageElement.cpp 2017-09-09 03:09:09 UTC (rev 221805)
@@ -538,6 +538,11 @@
return m_imageLoader.imageComplete();
}
+void HTMLImageElement::decode(Ref<DeferredPromise>&& promise)
+{
+ return m_imageLoader.decode(WTFMove(promise));
+}
+
void HTMLImageElement::addSubresourceAttributeURLs(ListHashSet<URL>& urls) const
{
HTMLElement::addSubresourceAttributeURLs(urls);
Modified: trunk/Source/WebCore/html/HTMLImageElement.h (221804 => 221805)
--- trunk/Source/WebCore/html/HTMLImageElement.h 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/html/HTMLImageElement.h 2017-09-09 03:09:09 UTC (rev 221805)
@@ -79,6 +79,8 @@
WEBCORE_EXPORT bool complete() const;
+ WEBCORE_EXPORT void decode(Ref<DeferredPromise>&&);
+
#if PLATFORM(IOS)
bool willRespondToMouseClickEvents() override;
#endif
Modified: trunk/Source/WebCore/html/HTMLImageElement.idl (221804 => 221805)
--- trunk/Source/WebCore/html/HTMLImageElement.idl 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/html/HTMLImageElement.idl 2017-09-09 03:09:09 UTC (rev 221805)
@@ -49,5 +49,7 @@
readonly attribute long naturalWidth;
readonly attribute long x;
readonly attribute long y;
+
+ Promise<void> decode();
};
Modified: trunk/Source/WebCore/loader/ImageLoader.cpp (221804 => 221805)
--- trunk/Source/WebCore/loader/ImageLoader.cpp 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/loader/ImageLoader.cpp 2017-09-09 03:09:09 UTC (rev 221805)
@@ -291,6 +291,9 @@
static NeverDestroyed<String> consoleMessage(MAKE_STATIC_STRING_IMPL("Cross-origin image load denied by Cross-Origin Resource Sharing policy."));
element().document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage);
+ if (hasPendingDecodePromises())
+ decodeError("Access control error.");
+
ASSERT(!m_hasPendingLoadEvent);
// Only consider updating the protection ref-count of the Element immediately before returning
@@ -300,6 +303,8 @@
}
if (m_image->wasCanceled()) {
+ if (hasPendingDecodePromises())
+ decodeError("Loading was canceled.");
m_hasPendingLoadEvent = false;
// Only consider updating the protection ref-count of the Element immediately before returning
// from this function as doing so might result in the destruction of this ImageLoader.
@@ -307,6 +312,8 @@
return;
}
+ if (hasPendingDecodePromises())
+ decode();
loadEventSender().dispatchEventSoon(*this);
}
@@ -369,6 +376,59 @@
}
}
+void ImageLoader::decode(Ref<DeferredPromise>&& promise)
+{
+ m_decodingPromises.append(WTFMove(promise));
+
+ if (!element().document().domWindow()) {
+ decodeError("Inactive document.");
+ return;
+ }
+
+ AtomicString attr = element().imageSourceURL();
+ if (attr.isNull() || stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) {
+ decodeError("Missing source URL.");
+ return;
+ }
+
+ if (m_imageComplete)
+ decode();
+}
+
+void ImageLoader::decodeError(String&& message)
+{
+ ASSERT(hasPendingDecodePromises());
+ for (auto& promise : m_decodingPromises)
+ promise->reject(Exception { EncodingError, WTFMove(message) });
+ m_decodingPromises.clear();
+}
+
+void ImageLoader::decode()
+{
+ ASSERT(hasPendingDecodePromises());
+
+ if (!element().document().domWindow()) {
+ decodeError("Inactive document.");
+ return;
+ }
+
+ Image* image = m_image->image();
+ if (!image || m_image->errorOccurred()) {
+ decodeError("Loading error.");
+ return;
+ }
+
+ if (!image->isBitmapImage()) {
+ decodeError("Invalid image type.");
+ return;
+ }
+
+ image->decode([promises = WTFMove(m_decodingPromises)]() mutable {
+ for (auto& promise : promises)
+ promise->resolve();
+ });
+}
+
void ImageLoader::timerFired()
{
m_protectedElement = nullptr;
Modified: trunk/Source/WebCore/loader/ImageLoader.h (221804 => 221805)
--- trunk/Source/WebCore/loader/ImageLoader.h 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/loader/ImageLoader.h 2017-09-09 03:09:09 UTC (rev 221805)
@@ -24,7 +24,9 @@
#include "CachedImageClient.h"
#include "CachedResourceHandle.h"
+#include "JSDOMPromiseDeferred.h"
#include "Timer.h"
+#include <wtf/Vector.h>
#include <wtf/text/AtomicString.h>
namespace WebCore {
@@ -58,6 +60,8 @@
CachedImage* image() const { return m_image.get(); }
void clearImage(); // Cancels pending beforeload and load events, and doesn't dispatch new ones.
+
+ void decode(Ref<DeferredPromise>&&);
void setLoadManually(bool loadManually) { m_loadManually = loadManually; }
@@ -90,6 +94,10 @@
void clearImageWithoutConsideringPendingLoadEvent();
void clearFailedLoadURL();
+ bool hasPendingDecodePromises() const { return !m_decodingPromises.isEmpty(); }
+ void decodeError(String&&);
+ void decode();
+
void timerFired();
Element& m_element;
@@ -97,6 +105,7 @@
Timer m_derefElementTimer;
RefPtr<Element> m_protectedElement;
AtomicString m_failedLoadURL;
+ Vector<RefPtr<DeferredPromise>, 1> m_decodingPromises;
bool m_hasPendingBeforeLoadEvent : 1;
bool m_hasPendingLoadEvent : 1;
bool m_hasPendingErrorEvent : 1;
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (221804 => 221805)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2017-09-09 03:09:09 UTC (rev 221805)
@@ -464,7 +464,9 @@
DecodingStatus decodingStatus = frameDecodingStatusAtIndex(m_currentFrame);
setCurrentFrameDecodingStatusIfNecessary(decodingStatus);
-
+
+ callDecodingCallbacks();
+
if (imageObserver())
imageObserver()->imageFrameAvailable(*this, ImageAnimatingState::Yes, nullptr, decodingStatus);
@@ -497,6 +499,47 @@
destroyDecodedDataIfNecessary(true);
}
+void BitmapImage::decode(WTF::Function<void()>&& callback)
+{
+ m_decodingCallbacks.append(WTFMove(callback));
+
+ if (canAnimate()) {
+ if (m_desiredFrameStartTime) {
+ internalStartAnimation();
+ return;
+ }
+
+ // The animated image has not been displayed. In this case, either the first frame has not been decoded yet or the animation has not started yet.
+ bool frameIsCompatible = frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, std::optional<IntSize>());
+ bool frameIsBeingDecoded = frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, std::optional<IntSize>());
+
+ if (frameIsCompatible)
+ internalStartAnimation();
+ else if (!frameIsBeingDecoded) {
+ m_source.requestFrameAsyncDecodingAtIndex(m_currentFrame, m_currentSubsamplingLevel, std::optional<IntSize>());
+ m_currentFrameDecodingStatus = DecodingStatus::Decoding;
+ }
+ return;
+ }
+
+ bool frameIsCompatible = frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, std::optional<IntSize>());
+ bool frameIsBeingDecoded = frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, std::optional<IntSize>());
+
+ if (frameIsCompatible)
+ callDecodingCallbacks();
+ else if (!frameIsBeingDecoded) {
+ m_source.requestFrameAsyncDecodingAtIndex(m_currentFrame, m_currentSubsamplingLevel, std::optional<IntSize>());
+ m_currentFrameDecodingStatus = DecodingStatus::Decoding;
+ }
+}
+
+void BitmapImage::callDecodingCallbacks()
+{
+ for (auto& decodingCallback : m_decodingCallbacks)
+ decodingCallback();
+ m_decodingCallbacks.clear();
+}
+
void BitmapImage::imageFrameAvailableAtIndex(size_t index)
{
LOG(Images, "BitmapImage::%s - %p - url: %s [requested frame %ld is now available]", __FUNCTION__, this, sourceURL().string().utf8().data(), index);
@@ -524,10 +567,14 @@
DecodingStatus decodingStatus = frameDecodingStatusAtIndex(m_currentFrame);
setCurrentFrameDecodingStatusIfNecessary(decodingStatus);
-
+
if (m_currentFrameDecodingStatus == DecodingStatus::Complete)
++m_decodeCountForTesting;
+ // Call m_decodingCallbacks only if the image frame was decoded with the native size.
+ if (frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, std::optional<IntSize>()))
+ callDecodingCallbacks();
+
if (imageObserver())
imageObserver()->imageFrameAvailable(*this, ImageAnimatingState::No, nullptr, decodingStatus);
}
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (221804 => 221805)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.h 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h 2017-09-09 03:09:09 UTC (rev 221805)
@@ -178,8 +178,7 @@
// automatically pause once all observers no longer want to render the image anywhere.
void stopAnimation() override;
void resetAnimation() override;
- void imageFrameAvailableAtIndex(size_t) override;
-
+
// Handle platform-specific data
void invalidatePlatformData();
@@ -197,6 +196,9 @@
bool canDestroyDecodedData();
void setCurrentFrameDecodingStatusIfNecessary(DecodingStatus);
bool isBitmapImage() const override { return true; }
+ void decode(WTF::Function<void()>&&) override;
+ void callDecodingCallbacks();
+ void imageFrameAvailableAtIndex(size_t) override;
void dump(WTF::TextStream&) const override;
// Animated images over a certain size are considered large enough that we'll only hang on to one frame at a time.
@@ -211,6 +213,7 @@
RepetitionCount m_repetitionsComplete { RepetitionCountNone }; // How many repetitions we've finished.
MonotonicTime m_desiredFrameStartTime; // The system time at which we hope to see the next call to startAnimation().
+ Vector<Function<void()>, 1> m_decodingCallbacks;
Seconds m_frameDecodingDurationForTesting;
MonotonicTime m_desiredFrameDecodeTimeForTesting;
Modified: trunk/Source/WebCore/platform/graphics/Image.h (221804 => 221805)
--- trunk/Source/WebCore/platform/graphics/Image.h 2017-09-09 00:33:44 UTC (rev 221804)
+++ trunk/Source/WebCore/platform/graphics/Image.h 2017-09-09 03:09:09 UTC (rev 221805)
@@ -133,10 +133,12 @@
void startAnimationAsynchronously();
virtual void stopAnimation() {}
virtual void resetAnimation() {}
- virtual void imageFrameAvailableAtIndex(size_t) { }
virtual bool isAnimating() const { return false; }
bool animationPending() const { return m_animationStartTimer.isActive(); }
-
+
+ virtual void decode(WTF::Function<void()>&&) { }
+ virtual void imageFrameAvailableAtIndex(size_t) { }
+
// Typically the CachedImage that owns us.
ImageObserver* imageObserver() const { return m_imageObserver; }
void setImageObserver(ImageObserver* observer) { m_imageObserver = observer; }