<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[213830] releases/WebKitGTK/webkit-2.16/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/213830">213830</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-13 04:44:26 -0700 (Mon, 13 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/213563">r213563</a> - Asynchronous image decoding should consider the drawing size if it is smaller than the size of the image
https://bugs.webkit.org/show_bug.cgi?id=168814

Patch by Said Abou-Hallawa &lt;sabouhallawa@apple.com&gt; on 2017-03-07
Reviewed by Simon Fraser.

If the image destinationRect.size() is smaller than the imageSourceSize
(e.g. 3000x3000 pixels), CGImageSourceCreateThumbnailAtIndex() is slower
than CGImageSourceCreateImageAtIndex() in decoding this image. To overcome
this problem, the entry (kCGImageSourceThumbnailMaxPixelSize,
max(destinationRect.width, destinationRect.height)) is added to the options
dictionary when calling CGImageSourceCreateThumbnailAtIndex(). This will
avoid copying a large block of memory for the unscaled bitmap image.

An argument named 'sizeForDrawing' of type std::optional&lt;IntSize&gt; will be passed
all the way from BitmapImage to ImageDecoder. If bool(sizeForDrawing) equals
true that means we want async image decoding. Otherwise the image will be decoded
synchronously.

The subsamplingLevel argument will be passed as std::optional&lt;SubsamplingLevel&gt;.
to ImageFrame query functions. When combined with sizeForDrawing, the meaning of
these two arguments will be the following:
-- !bool(subsamplingLevel): No caching is required. return what is stored in ImageFrameCache.
-- bool(subsamplingLevel) &amp;&amp; !bool(sizeForDrawing): Match subsamplingLevel only. Recache if it's different.
-- bool(subsamplingLevel) &amp;&amp; bool(sizeForDrawing): Match both both. . Recache if one of them is different.

We are going to allow decoding the same ImageFrame for different sizeForDrawings.
The rule is a new decoding is allowed only if the maxPixelSize(sizeForDrawing) of
the last requested image decoding is less than the new request sizeForDrawing.

* loader/cache/CachedImage.h: Add a helper function which returns the URL of a CachedImage.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::frameImageAtIndex): Add a new argument for sizeForDrawing.
(WebCore::BitmapImage::nativeImage): Pass an empty sizeForDrawing to frameImageAtIndex(). We an image with the native size.
(WebCore::BitmapImage::nativeImageForCurrentFrame): Ditto.
(WebCore::BitmapImage::nativeImageOfSize): Ditto.
(WebCore::BitmapImage::draw): Pass the destRect.size() to internalStartAnimation().
(WebCore::BitmapImage::isAsyncDecodingRequired): A helper function to answer the question
whether the async image decoding is required. It takes into account the animated images, the
large image, and the image size.
(WebCore::BitmapImage::internalStartAnimation):  If async image decoding is requested for this frame m_sizeForDraw
will be set. If internalStartAnimation() is called from startAnimation(), sizeForDraw will be empty. In this
case no async image decoding will be requested. This happens only when startAnimation() is called from outside
BitmapImage::draw().
(WebCore::BitmapImage::advanceAnimation): Change the log message.
(WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): Ditto.
* platform/graphics/BitmapImage.h:

* platform/graphics/ImageFrame.cpp:
(WebCore::ImageFrame::operator=):  Include m_sizeForDraw in the properties of ImageFrame.
(WebCore::maxPixelSize): Returns the maximum of the width() and the height of an IntSize.
(WebCore::ImageFrame::isBeingDecoded): Returns true if the ImageFrame is currently being decoded for a specific sizeForDrawing.
(WebCore::ImageFrame::hasValidNativeImage): Ditto.
* platform/graphics/ImageFrame.h:
(WebCore::ImageFrame::enqueueSizeForDecoding): Adds a new sizeForDrawing; this sets the ImageFrame is being decoded for this sizeForDrawing.
(WebCore::ImageFrame::dequeueSizeForDecoding): Removes the first sizeForDrawing was enqueued; this marks this ImageFrame has finished decoding for this sizeForDrawing.
(WebCore::ImageFrame::clearSizeForDecoding): Clears the sizeForDecoding queue. Marks the ImageFrame for not being decoded.
(WebCore::ImageFrame::isEmpty): Replace Decoding::Empty by Decoding::None.
(WebCore::ImageFrame::sizeForDrawing): Returns the ImageFrame sizeForDraw.
(WebCore::ImageFrame::hasDecodedNativeImage): Returns true if the ImageFrame doesn't need decoding before drawing.
(WebCore::ImageFrame::hasValidNativeImage): Deleted. Moved to the source file.

* platform/graphics/ImageFrameCache.cpp:
(WebCore::ImageFrameCache::setFrameNativeImageAtIndex): Take a new argument for sizeForDraw.
(WebCore::ImageFrameCache::setFrameMetadataAtIndex):  When sizeForDraw is set, use the decoder to get the image
frame size. Otherwise, get the size of the nativeImage.
(WebCore::ImageFrameCache::replaceFrameNativeImageAtIndex): Take a new argument for sizeForDraw.
(WebCore::ImageFrameCache::cacheFrameNativeImageAtIndex): Ditto.
(WebCore::ImageFrameCache::startAsyncDecodingQueue): Pass the sizeForDraw as a new property of the ImageFrame.
(WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Store sizeForDraw in ImageFrameRequest. Delete unneeded check.
This function always receives a valid subsamplingLevel.
(WebCore::ImageFrameCache::stopAsyncDecodingQueue): Marks all the queued ImageFrames for not being decoded.
(WebCore::ImageFrameCache::frameAtIndexCacheIfNeeded): Take a new argument for sizeForDraw. If this function fixes the
properties of ImageFrame properties, keep the old sizeForDraw and/or subsamplingLevel. If a new frame is
decoded, no async image decoding will be done in this code path. So pass an empty std::optional&lt;IntSize&gt; to
ImageDecoder::createFrameImageAtIndex() and store std::optional&lt;IntSize&gt; in ImageFrame.
(WebCore::ImageFrameCache::frameMetadataAtIndex): A new helper function which takes a variable number of arguments which
will be passed to the (ImageFrame::*functor).
(WebCore::ImageFrameCache::frameMetadataAtIndexCacheIfNeeded): Make this function takes a variable number of arguments which
will be passed to the frameAtIndexCacheIfNeeded().
(WebCore::ImageFrameCache::size): Pass an Metadata, valid SubsamplingLevel and empty sizeForDraw to frameMetadataAtIndexCacheIfNeeded().
(WebCore::ImageFrameCache::sizeRespectingOrientation): Ditto.
(WebCore::ImageFrameCache::singlePixelSolidColor): Pass MetadataAndImage, empty SubsamplingLevel and empty sizeForDraw to
frameMetadataAtIndexCacheIfNeeded(); we can use the current frame image regardless of its size.
(WebCore::ImageFrameCache::frameIsBeingDecodedAtIndex): Pass the ImageFrame method as a function argument instead of
passing it as a template argument.
(WebCore::ImageFrameCache::frameIsCompleteAtIndex): Ditto.
(WebCore::ImageFrameCache::frameHasAlphaAtIndex): Ditto.
(WebCore::ImageFrameCache::frameHasImageAtIndex): Ditto.
(WebCore::ImageFrameCache::frameHasValidNativeImageAtIndex): Pass subsamplingLevel and sizeForDrawing to frameMetadataAtIndex().
(WebCore::ImageFrameCache::frameHasDecodedNativeImage): New helper function to answer the question whether an ImageFrame will need
decoding when drawing or not.
(WebCore::ImageFrameCache::frameSubsamplingLevelAtIndex):  Pass the ImageFrame method as a function argument instead of
passing it as a template argument.
(WebCore::ImageFrameCache::frameSizeAtIndex): Ditto.
(WebCore::ImageFrameCache::frameBytesAtIndex): Ditto.
(WebCore::ImageFrameCache::frameDurationAtIndex): Ditto.
(WebCore::ImageFrameCache::frameOrientationAtIndex):
(WebCore::ImageFrameCache::frameImageAtIndex): Ditto.
(WebCore::ImageFrameCache::frameAtIndex): Deleted. Renamed to frameAtIndexCacheIfNeeded().
* platform/graphics/ImageFrameCache.h:
(WebCore::ImageFrameCache::frameAtIndexCacheIfNeeded):

* platform/graphics/ImageObserver.h: Define a virtual function for image sourceUrl().

* platform/graphics/ImageSource.cpp:
(WebCore::ImageSource::frameImageAtIndex): Take a new argument for sizeForDrawing.
* platform/graphics/ImageSource.h:
(WebCore::ImageSource::requestFrameAsyncDecodingAtIndex): Take a new argument for sizeForDrawing.
(WebCore::ImageSource::frameHasValidNativeImageAtIndex): Ditto.
(WebCore::ImageSource::frameHasDecodedNativeImage): New helper function.
(WebCore::ImageSource::frameImageAtIndex): Ditto.

* platform/graphics/cg/ImageDecoderCG.cpp:
(WebCore::createImageSourceOptions): Create a dictionary with the basic image decoding options.
(WebCore::createImageSourceAsyncOptions): Create a dictionary with the basic asynchronous image decoding options.
(WebCore::appendImageSourceOption): Append the SubsamplingLevel or the MaxPixelSize option to an CGImageSource options dictionary.
(WebCore::appendImageSourceOptions): Append the SubsamplingLevel and the MaxPixelSize option to an CGImageSource options dictionary.
(WebCore::imageSourceOptions): Creates a dictionary for the synchronous image decoding options.
(WebCore::imageSourceAsyncOptions): Creates a dictionary for the asynchronous image decoding options.
(WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
* platform/graphics/cg/ImageDecoderCG.h: Change a prototype.

* platform/graphics/win/ImageDecoderDirect2D.cpp:
(WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
* platform/graphics/win/ImageDecoderDirect2D.h: Change a prototype.

* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
* platform/image-decoders/ImageDecoder.h: Change a prototype.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreChangeLog">releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreloadercacheCachedImageh">releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/cache/CachedImage.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsBitmapImagecpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsBitmapImageh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFramecpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameCachecpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameCacheh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageObserverh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageObserver.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageSourcecpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageSourceh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicscgImageDecoderCGcpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicscgImageDecoderCGh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicswinImageDecoderDirect2Dcpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicswinImageDecoderDirect2Dh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformimagedecodersImageDecodercpp">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit216SourceWebCoreplatformimagedecodersImageDecoderh">releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit216SourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/ChangeLog        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -1,3 +1,136 @@
</span><ins>+2017-03-07  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        Asynchronous image decoding should consider the drawing size if it is smaller than the size of the image
+        https://bugs.webkit.org/show_bug.cgi?id=168814
+
+        Reviewed by Simon Fraser.
+
+        If the image destinationRect.size() is smaller than the imageSourceSize
+        (e.g. 3000x3000 pixels), CGImageSourceCreateThumbnailAtIndex() is slower
+        than CGImageSourceCreateImageAtIndex() in decoding this image. To overcome
+        this problem, the entry (kCGImageSourceThumbnailMaxPixelSize,
+        max(destinationRect.width, destinationRect.height)) is added to the options
+        dictionary when calling CGImageSourceCreateThumbnailAtIndex(). This will
+        avoid copying a large block of memory for the unscaled bitmap image.
+
+        An argument named 'sizeForDrawing' of type std::optional&lt;IntSize&gt; will be passed
+        all the way from BitmapImage to ImageDecoder. If bool(sizeForDrawing) equals
+        true that means we want async image decoding. Otherwise the image will be decoded
+        synchronously.
+
+        The subsamplingLevel argument will be passed as std::optional&lt;SubsamplingLevel&gt;.
+        to ImageFrame query functions. When combined with sizeForDrawing, the meaning of
+        these two arguments will be the following:
+        -- !bool(subsamplingLevel): No caching is required. return what is stored in ImageFrameCache.
+        -- bool(subsamplingLevel) &amp;&amp; !bool(sizeForDrawing): Match subsamplingLevel only. Recache if it's different.
+        -- bool(subsamplingLevel) &amp;&amp; bool(sizeForDrawing): Match both both. . Recache if one of them is different.
+
+        We are going to allow decoding the same ImageFrame for different sizeForDrawings.
+        The rule is a new decoding is allowed only if the maxPixelSize(sizeForDrawing) of
+        the last requested image decoding is less than the new request sizeForDrawing.
+
+        * loader/cache/CachedImage.h: Add a helper function which returns the URL of a CachedImage.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::frameImageAtIndex): Add a new argument for sizeForDrawing.
+        (WebCore::BitmapImage::nativeImage): Pass an empty sizeForDrawing to frameImageAtIndex(). We an image with the native size.
+        (WebCore::BitmapImage::nativeImageForCurrentFrame): Ditto.
+        (WebCore::BitmapImage::nativeImageOfSize): Ditto.
+        (WebCore::BitmapImage::draw): Pass the destRect.size() to internalStartAnimation().
+        (WebCore::BitmapImage::isAsyncDecodingRequired): A helper function to answer the question
+        whether the async image decoding is required. It takes into account the animated images, the
+        large image, and the image size.
+        (WebCore::BitmapImage::internalStartAnimation):  If async image decoding is requested for this frame m_sizeForDraw
+        will be set. If internalStartAnimation() is called from startAnimation(), sizeForDraw will be empty. In this
+        case no async image decoding will be requested. This happens only when startAnimation() is called from outside
+        BitmapImage::draw().
+        (WebCore::BitmapImage::advanceAnimation): Change the log message.
+        (WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): Ditto.
+        * platform/graphics/BitmapImage.h:
+
+        * platform/graphics/ImageFrame.cpp:
+        (WebCore::ImageFrame::operator=):  Include m_sizeForDraw in the properties of ImageFrame.
+        (WebCore::maxPixelSize): Returns the maximum of the width() and the height of an IntSize.
+        (WebCore::ImageFrame::isBeingDecoded): Returns true if the ImageFrame is currently being decoded for a specific sizeForDrawing.
+        (WebCore::ImageFrame::hasValidNativeImage): Ditto.
+        * platform/graphics/ImageFrame.h:
+        (WebCore::ImageFrame::enqueueSizeForDecoding): Adds a new sizeForDrawing; this sets the ImageFrame is being decoded for this sizeForDrawing.
+        (WebCore::ImageFrame::dequeueSizeForDecoding): Removes the first sizeForDrawing was enqueued; this marks this ImageFrame has finished decoding for this sizeForDrawing.
+        (WebCore::ImageFrame::clearSizeForDecoding): Clears the sizeForDecoding queue. Marks the ImageFrame for not being decoded.
+        (WebCore::ImageFrame::isEmpty): Replace Decoding::Empty by Decoding::None.
+        (WebCore::ImageFrame::sizeForDrawing): Returns the ImageFrame sizeForDraw.
+        (WebCore::ImageFrame::hasDecodedNativeImage): Returns true if the ImageFrame doesn't need decoding before drawing.
+        (WebCore::ImageFrame::hasValidNativeImage): Deleted. Moved to the source file.
+
+        * platform/graphics/ImageFrameCache.cpp:
+        (WebCore::ImageFrameCache::setFrameNativeImageAtIndex): Take a new argument for sizeForDraw.
+        (WebCore::ImageFrameCache::setFrameMetadataAtIndex):  When sizeForDraw is set, use the decoder to get the image
+        frame size. Otherwise, get the size of the nativeImage.
+        (WebCore::ImageFrameCache::replaceFrameNativeImageAtIndex): Take a new argument for sizeForDraw.
+        (WebCore::ImageFrameCache::cacheFrameNativeImageAtIndex): Ditto.
+        (WebCore::ImageFrameCache::startAsyncDecodingQueue): Pass the sizeForDraw as a new property of the ImageFrame.
+        (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Store sizeForDraw in ImageFrameRequest. Delete unneeded check.
+        This function always receives a valid subsamplingLevel. 
+        (WebCore::ImageFrameCache::stopAsyncDecodingQueue): Marks all the queued ImageFrames for not being decoded.
+        (WebCore::ImageFrameCache::frameAtIndexCacheIfNeeded): Take a new argument for sizeForDraw. If this function fixes the
+        properties of ImageFrame properties, keep the old sizeForDraw and/or subsamplingLevel. If a new frame is 
+        decoded, no async image decoding will be done in this code path. So pass an empty std::optional&lt;IntSize&gt; to 
+        ImageDecoder::createFrameImageAtIndex() and store std::optional&lt;IntSize&gt; in ImageFrame.
+        (WebCore::ImageFrameCache::frameMetadataAtIndex): A new helper function which takes a variable number of arguments which
+        will be passed to the (ImageFrame::*functor).
+        (WebCore::ImageFrameCache::frameMetadataAtIndexCacheIfNeeded): Make this function takes a variable number of arguments which
+        will be passed to the frameAtIndexCacheIfNeeded().
+        (WebCore::ImageFrameCache::size): Pass an Metadata, valid SubsamplingLevel and empty sizeForDraw to frameMetadataAtIndexCacheIfNeeded().
+        (WebCore::ImageFrameCache::sizeRespectingOrientation): Ditto.
+        (WebCore::ImageFrameCache::singlePixelSolidColor): Pass MetadataAndImage, empty SubsamplingLevel and empty sizeForDraw to
+        frameMetadataAtIndexCacheIfNeeded(); we can use the current frame image regardless of its size.
+        (WebCore::ImageFrameCache::frameIsBeingDecodedAtIndex): Pass the ImageFrame method as a function argument instead of 
+        passing it as a template argument.
+        (WebCore::ImageFrameCache::frameIsCompleteAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameHasAlphaAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameHasImageAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameHasValidNativeImageAtIndex): Pass subsamplingLevel and sizeForDrawing to frameMetadataAtIndex().
+        (WebCore::ImageFrameCache::frameHasDecodedNativeImage): New helper function to answer the question whether an ImageFrame will need
+        decoding when drawing or not.
+        (WebCore::ImageFrameCache::frameSubsamplingLevelAtIndex):  Pass the ImageFrame method as a function argument instead of 
+        passing it as a template argument.
+        (WebCore::ImageFrameCache::frameSizeAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameBytesAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameDurationAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameOrientationAtIndex):
+        (WebCore::ImageFrameCache::frameImageAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameAtIndex): Deleted. Renamed to frameAtIndexCacheIfNeeded().
+        * platform/graphics/ImageFrameCache.h:
+        (WebCore::ImageFrameCache::frameAtIndexCacheIfNeeded):
+
+        * platform/graphics/ImageObserver.h: Define a virtual function for image sourceUrl().
+
+        * platform/graphics/ImageSource.cpp:
+        (WebCore::ImageSource::frameImageAtIndex): Take a new argument for sizeForDrawing.
+        * platform/graphics/ImageSource.h:
+        (WebCore::ImageSource::requestFrameAsyncDecodingAtIndex): Take a new argument for sizeForDrawing.
+        (WebCore::ImageSource::frameHasValidNativeImageAtIndex): Ditto.
+        (WebCore::ImageSource::frameHasDecodedNativeImage): New helper function.
+        (WebCore::ImageSource::frameImageAtIndex): Ditto.
+
+        * platform/graphics/cg/ImageDecoderCG.cpp:
+        (WebCore::createImageSourceOptions): Create a dictionary with the basic image decoding options.
+        (WebCore::createImageSourceAsyncOptions): Create a dictionary with the basic asynchronous image decoding options.
+        (WebCore::appendImageSourceOption): Append the SubsamplingLevel or the MaxPixelSize option to an CGImageSource options dictionary.
+        (WebCore::appendImageSourceOptions): Append the SubsamplingLevel and the MaxPixelSize option to an CGImageSource options dictionary.
+        (WebCore::imageSourceOptions): Creates a dictionary for the synchronous image decoding options.
+        (WebCore::imageSourceAsyncOptions): Creates a dictionary for the asynchronous image decoding options.
+        (WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
+        * platform/graphics/cg/ImageDecoderCG.h: Change a prototype.
+
+        * platform/graphics/win/ImageDecoderDirect2D.cpp: 
+        (WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
+        * platform/graphics/win/ImageDecoderDirect2D.h: Change a prototype.
+
+        * platform/image-decoders/ImageDecoder.cpp: 
+        (WebCore::ImageDecoder::createFrameImageAtIndex): Replace the DecodingMode argument by an std::optional&lt;IntSize&gt;.
+        * platform/image-decoders/ImageDecoder.h: Change a prototype.
+
</ins><span class="cx"> 2017-03-07  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         [URLParser] Fix file URLs that are just file:// and a Windows drive letter
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreloadercacheCachedImageh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/cache/CachedImage.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/cache/CachedImage.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/loader/cache/CachedImage.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -126,6 +126,7 @@
</span><span class="cx">         explicit CachedImageObserver(CachedImage&amp;);
</span><span class="cx"> 
</span><span class="cx">         // ImageObserver API
</span><ins>+        URL sourceUrl() const override { return m_cachedImages[0]-&gt;url(); }
</ins><span class="cx">         bool allowSubsampling() const final { return m_allowSubsampling; }
</span><span class="cx">         bool allowLargeImageAsyncDecoding() const override { return m_allowLargeImageAsyncDecoding; }
</span><span class="cx">         bool allowAnimatedImageAsyncDecoding() const override { return m_allowAnimatedImageAsyncDecoding; }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsBitmapImagecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -100,24 +100,24 @@
</span><span class="cx">     return m_source.dataChanged(data(), allDataReceived);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
</del><ins>+NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing, const GraphicsContext* targetContext)
</ins><span class="cx"> {
</span><del>-    if (!frameHasValidNativeImageAtIndex(index, subsamplingLevel)) {
-        LOG(Images, &quot;BitmapImage %p %s - subsamplingLevel was %d, resampling&quot;, this, __FUNCTION__, static_cast&lt;int&gt;(frameSubsamplingLevelAtIndex(index)));
</del><ins>+    if (!frameHasValidNativeImageAtIndex(index, subsamplingLevel, sizeForDrawing)) {
+        LOG(Images, &quot;BitmapImage::%s - %p - url: %s [subsamplingLevel was %d, resampling]&quot;, __FUNCTION__, this, sourceURL().characters8(), static_cast&lt;int&gt;(frameSubsamplingLevelAtIndex(index)));
</ins><span class="cx">         invalidatePlatformData();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    return m_source.frameImageAtIndex(index, subsamplingLevel, targetContext);
</del><ins>+    return m_source.frameImageAtIndex(index, subsamplingLevel, sizeForDrawing, targetContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> NativeImagePtr BitmapImage::nativeImage(const GraphicsContext* targetContext)
</span><span class="cx"> {
</span><del>-    return frameImageAtIndex(0, SubsamplingLevel::Default, targetContext);
</del><ins>+    return frameImageAtIndex(0, SubsamplingLevel::Default, { }, targetContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> NativeImagePtr BitmapImage::nativeImageForCurrentFrame(const GraphicsContext* targetContext)
</span><span class="cx"> {
</span><del>-    return frameImageAtIndex(m_currentFrame, SubsamplingLevel::Default, targetContext);
</del><ins>+    return frameImageAtIndex(m_currentFrame, SubsamplingLevel::Default, { }, targetContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(CG)
</span><span class="lines">@@ -126,13 +126,13 @@
</span><span class="cx">     size_t count = frameCount();
</span><span class="cx"> 
</span><span class="cx">     for (size_t i = 0; i &lt; count; ++i) {
</span><del>-        auto image = frameImageAtIndex(i, SubsamplingLevel::Default, targetContext);
</del><ins>+        auto image = frameImageAtIndex(i, SubsamplingLevel::Default, { }, targetContext);
</ins><span class="cx">         if (image &amp;&amp; nativeImageSize(image) == size)
</span><span class="cx">             return image;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Fallback to the first frame image if we can't find the right size
</span><del>-    return frameImageAtIndex(0, SubsamplingLevel::Default, targetContext);
</del><ins>+    return frameImageAtIndex(0, SubsamplingLevel::Default, { }, targetContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Vector&lt;NativeImagePtr&gt; BitmapImage::framesNativeImages()
</span><span class="lines">@@ -161,6 +161,7 @@
</span><span class="cx">     if (destRect.isEmpty() || srcRect.isEmpty())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    m_sizeForDrawing = enclosingIntRect(destRect).size();
</ins><span class="cx">     StartAnimationResult result = internalStartAnimation();
</span><span class="cx"> 
</span><span class="cx">     Color color;
</span><span class="lines">@@ -176,10 +177,10 @@
</span><span class="cx"> 
</span><span class="cx">     float scale = subsamplingScale(context, destRect, srcRect);
</span><span class="cx">     m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default;
</span><del>-    LOG(Images, &quot;BitmapImage %p draw - subsamplingLevel %d at scale %.4f&quot;, this, static_cast&lt;int&gt;(m_currentSubsamplingLevel), scale);
</del><ins>+    LOG(Images, &quot;BitmapImage::%s - %p - url: %s [m_currentFrame = %ld subsamplingLevel = %d scale = %.4f]&quot;, __FUNCTION__, this, sourceURL().characters8(), m_currentFrame, static_cast&lt;int&gt;(m_currentSubsamplingLevel), scale);
</ins><span class="cx"> 
</span><del>-    ASSERT_IMPLIES(result == StartAnimationResult::DecodingActive, m_source.frameHasValidNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel));
-    auto image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, &amp;context);
</del><ins>+    ASSERT_IMPLIES(result == StartAnimationResult::DecodingActive, m_source.frameHasValidNativeImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing));
+    auto image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, m_sizeForDrawing, &amp;context);
</ins><span class="cx">     if (!image) // If it's too early we won't have an image yet.
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="lines">@@ -237,6 +238,16 @@
</span><span class="cx">     return shouldAnimate() &amp;&amp; frameCount() &gt; 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool BitmapImage::isLargeImageAsyncDecodingRequired()
+{
+    return !canAnimate() &amp;&amp; allowLargeImageAsyncDecoding() &amp;&amp; (isAsyncDecodingForcedForTesting() || m_source.isAsyncDecodingRequired());
+}
+
+bool BitmapImage::isAnimatedImageAsyncDecodingRequired()
+{
+    return canAnimate() &amp;&amp; allowAnimatedImageAsyncDecoding() &amp;&amp; (isAsyncDecodingForcedForTesting() || m_source.isAsyncDecodingRequired());
+}
+
</ins><span class="cx"> void BitmapImage::clearTimer()
</span><span class="cx"> {
</span><span class="cx">     m_frameTimer = nullptr;
</span><span class="lines">@@ -259,8 +270,10 @@
</span><span class="cx">     
</span><span class="cx">     // Don't start a new animation until we draw the frame that is currently being decoded.
</span><span class="cx">     size_t nextFrame = (m_currentFrame + 1) % frameCount();
</span><del>-    if (frameIsBeingDecodedAtIndex(nextFrame))
</del><ins>+    if (frameIsBeingDecodedAtIndex(nextFrame, m_sizeForDrawing)) {
+        LOG(Images, &quot;BitmapImage::%s - %p - url: %s [nextFrame = %ld is being decoded]&quot;, __FUNCTION__, this, sourceURL().characters8(), nextFrame);
</ins><span class="cx">         return StartAnimationResult::DecodingActive;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     if (m_currentFrame &gt;= frameCount() - 1) {
</span><span class="cx">         // Don't advance past the last frame if we haven't decoded the whole image
</span><span class="lines">@@ -299,9 +312,18 @@
</span><span class="cx">     // it will be decoded on a separate work queue. When decoding nextFrame finishes, we will be notified
</span><span class="cx">     // through the callback newFrameNativeImageAvailableAtIndex(). Otherwise, advanceAnimation() will be called
</span><span class="cx">     // when the timer fires and m_currentFrame will be advanced to nextFrame since it is not being decoded.
</span><del>-    if ((allowAnimatedImageAsyncDecoding() &amp;&amp; m_source.isAsyncDecodingRequired()) || isAsyncDecodingForcedForTesting()) {
-        if (!m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel))
-            LOG(Images, &quot;BitmapImage %p %s - cachedFrameCount %ld nextFrame %ld&quot;, this, __FUNCTION__, ++m_cachedFrameCount, nextFrame);
</del><ins>+    if (m_sizeForDrawing &amp;&amp; isAnimatedImageAsyncDecodingRequired()) {
+        bool isAsyncDecode = m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel, *m_sizeForDrawing);
+
+#if !LOG_DISABLED
+        if (isAsyncDecode)
+            LOG(Images, &quot;BitmapImage::%s - %p - url: %s [requesting async decoding for nextFrame = %ld]&quot;, __FUNCTION__, this, sourceURL().characters8(), nextFrame);
+        else
+            LOG(Images, &quot;BitmapImage::%s - %p - url: %s [cachedFrameCount = %ld nextFrame = %ld]&quot;, __FUNCTION__, this, sourceURL().characters8(), ++m_cachedFrameCount, nextFrame);
+#else
+        UNUSED_PARAM(isAsyncDecode);
+#endif
+
</ins><span class="cx">         m_desiredFrameDecodeTimeForTesting = time + std::max(m_frameDecodingDurationForTesting, 0.0f);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -327,13 +349,13 @@
</span><span class="cx">     
</span><span class="cx">     // Don't advance to nextFrame unless its decoding has finished or was not required.
</span><span class="cx">     size_t nextFrame = (m_currentFrame + 1) % frameCount();
</span><del>-    if (!frameIsBeingDecodedAtIndex(nextFrame))
</del><ins>+    if (!frameIsBeingDecodedAtIndex(nextFrame, m_sizeForDrawing))
</ins><span class="cx">         internalAdvanceAnimation();
</span><span class="cx">     else {
</span><span class="cx">         // Force repaint if showDebugBackground() is on.
</span><span class="cx">         if (showDebugBackground())
</span><span class="cx">             imageObserver()-&gt;changedInRect(this);
</span><del>-        LOG(Images, &quot;BitmapImage %p %s - lateFrameCount %ld nextFrame %ld&quot;, this, __FUNCTION__, ++m_lateFrameCount, nextFrame);
</del><ins>+        LOG(Images, &quot;BitmapImage::%s - %p - url: %s [lateFrameCount = %ld nextFrame = %ld]&quot;, __FUNCTION__, this, sourceURL().characters8(), ++m_lateFrameCount, nextFrame);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -340,12 +362,14 @@
</span><span class="cx"> void BitmapImage::internalAdvanceAnimation()
</span><span class="cx"> {
</span><span class="cx">     m_currentFrame = (m_currentFrame + 1) % frameCount();
</span><del>-    ASSERT(!frameIsBeingDecodedAtIndex(m_currentFrame));
</del><ins>+    ASSERT(!frameIsBeingDecodedAtIndex(m_currentFrame, m_sizeForDrawing));
</ins><span class="cx"> 
</span><span class="cx">     destroyDecodedDataIfNecessary(false);
</span><span class="cx"> 
</span><span class="cx">     if (imageObserver())
</span><span class="cx">         imageObserver()-&gt;animationAdvanced(this);
</span><ins>+
+    LOG(Images, &quot;BitmapImage::%s - %p - url: %s [m_currentFrame = %ld]&quot;, __FUNCTION__, this, sourceURL().characters8(), m_currentFrame);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BitmapImage::stopAnimation()
</span><span class="lines">@@ -377,7 +401,7 @@
</span><span class="cx">     if (canAnimate() &amp;&amp; !m_frameTimer)
</span><span class="cx">         internalAdvanceAnimation();
</span><span class="cx">     else
</span><del>-        LOG(Images, &quot;BitmapImage %p %s - earlyFrameCount %ld nextFrame %ld&quot;, this, __FUNCTION__, ++m_earlyFrameCount, index);
</del><ins>+        LOG(Images, &quot;BitmapImage::%s - %p - url: %s [earlyFrameCount = %ld nextFrame = %ld]&quot;, __FUNCTION__, this, sourceURL().characters8(), ++m_earlyFrameCount, index);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BitmapImage::dump(TextStream&amp; ts) const
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsBitmapImageh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/BitmapImage.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;ImageOrientation.h&quot;
</span><span class="cx"> #include &quot;ImageSource.h&quot;
</span><span class="cx"> #include &quot;IntSize.h&quot;
</span><ins>+#include &quot;URL.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if USE(CG) || USE(APPKIT)
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="lines">@@ -81,10 +82,11 @@
</span><span class="cx">     IntSize sizeRespectingOrientation() const { return m_source.sizeRespectingOrientation(); }
</span><span class="cx">     Color singlePixelSolidColor() const override { return m_source.singlePixelSolidColor(); }
</span><span class="cx"> 
</span><del>-    bool frameIsBeingDecodedAtIndex(size_t index) const { return m_source.frameIsBeingDecodedAtIndex(index); }
</del><ins>+    bool frameIsBeingDecodedAtIndex(size_t index, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const { return m_source.frameIsBeingDecodedAtIndex(index, sizeForDrawing); }
+    bool frameHasDecodedNativeImage(size_t index) const { return m_source.frameHasDecodedNativeImage(index); }
</ins><span class="cx">     bool frameIsCompleteAtIndex(size_t index) const { return m_source.frameIsCompleteAtIndex(index); }
</span><span class="cx">     bool frameHasAlphaAtIndex(size_t index) const { return m_source.frameHasAlphaAtIndex(index); }
</span><del>-    bool frameHasValidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const { return m_source.frameHasValidNativeImageAtIndex(index, subsamplingLevel); }
</del><ins>+    bool frameHasValidNativeImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const { return m_source.frameHasValidNativeImageAtIndex(index, subsamplingLevel, sizeForDrawing); }
</ins><span class="cx">     SubsamplingLevel frameSubsamplingLevelAtIndex(size_t index) const { return m_source.frameSubsamplingLevelAtIndex(index); }
</span><span class="cx"> 
</span><span class="cx">     float frameDurationAtIndex(size_t index) const { return m_source.frameDurationAtIndex(index); }
</span><span class="lines">@@ -96,6 +98,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool isAsyncDecodingForcedForTesting() const { return m_frameDecodingDurationForTesting &gt; 0; }
</span><span class="cx">     void setFrameDecodingDurationForTesting(float duration) { m_frameDecodingDurationForTesting = duration; }
</span><ins>+    bool isLargeImageAsyncDecodingRequired();
+    bool isAnimatedImageAsyncDecodingRequired();
</ins><span class="cx"> 
</span><span class="cx">     // Accessors for native image formats.
</span><span class="cx"> #if USE(APPKIT)
</span><span class="lines">@@ -127,8 +131,9 @@
</span><span class="cx">     WEBCORE_EXPORT BitmapImage(NativeImagePtr&amp;&amp;, ImageObserver* = nullptr);
</span><span class="cx">     WEBCORE_EXPORT BitmapImage(ImageObserver* = nullptr);
</span><span class="cx"> 
</span><del>-    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* = nullptr);
</del><ins>+    NativeImagePtr frameImageAtIndex(size_t, const std::optional&lt;SubsamplingLevel&gt;&amp; = { }, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { }, const GraphicsContext* = nullptr);
</ins><span class="cx"> 
</span><ins>+    String sourceURL() const { return imageObserver() ? imageObserver()-&gt;sourceUrl().string() : emptyString(); }
</ins><span class="cx">     bool allowSubsampling() const { return imageObserver() &amp;&amp; imageObserver()-&gt;allowSubsampling(); }
</span><span class="cx">     bool allowLargeImageAsyncDecoding() const { return imageObserver() &amp;&amp; imageObserver()-&gt;allowLargeImageAsyncDecoding(); }
</span><span class="cx">     bool allowAnimatedImageAsyncDecoding() const { return imageObserver() &amp;&amp; imageObserver()-&gt;allowAnimatedImageAsyncDecoding(); }
</span><span class="lines">@@ -197,6 +202,7 @@
</span><span class="cx"> 
</span><span class="cx">     size_t m_currentFrame { 0 }; // The index of the current frame of animation.
</span><span class="cx">     SubsamplingLevel m_currentSubsamplingLevel { SubsamplingLevel::Default };
</span><ins>+    std::optional&lt;IntSize&gt; m_sizeForDrawing;
</ins><span class="cx">     std::unique_ptr&lt;Timer&gt; m_frameTimer;
</span><span class="cx">     RepetitionCount m_repetitionsComplete { RepetitionCountNone }; // How many repetitions we've finished.
</span><span class="cx">     double m_desiredFrameStartTime { 0 }; // The system time at which we hope to see the next call to startAnimation().
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFramecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -63,6 +63,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_nativeImage = other.m_nativeImage;
</span><span class="cx">     m_subsamplingLevel = other.m_subsamplingLevel;
</span><ins>+    m_sizeForDrawing = other.m_sizeForDrawing;
</ins><span class="cx"> 
</span><span class="cx">     m_orientation = other.m_orientation;
</span><span class="cx">     m_duration = other.m_duration;
</span><span class="lines">@@ -123,7 +124,46 @@
</span><span class="cx"> #endif
</span><span class="cx">     return m_size;
</span><span class="cx"> }
</span><ins>+    
+static int maxDimension(const IntSize&amp; size)
+{
+    return std::max(size.width(), size.height());
+}
</ins><span class="cx"> 
</span><ins>+bool ImageFrame::isBeingDecoded(const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const
+{
+    if (!m_sizeForDecoding.size())
+        return false;
+    
+    if (!sizeForDrawing)
+        return true;
+
+    // Return true if the ImageFrame will be decoded eventually with a suitable sizeForDecoding.
+    return maxDimension(m_sizeForDecoding.last()) &gt;= maxDimension(*sizeForDrawing);
+}
+    
+bool ImageFrame::hasValidNativeImage(const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const
+{
+    ASSERT_IMPLIES(!subsamplingLevel, !sizeForDrawing);
+
+    if (!hasNativeImage())
+        return false;
+
+    // The caller does not care about subsamplingLevel or sizeForDrawing. The current NativeImage is fine.
+    if (!subsamplingLevel)
+        return true;
+
+    if (*subsamplingLevel &lt; m_subsamplingLevel)
+        return false;
+
+    // The NativeImage was decoded with the native size. So it is valid for any size.
+    if (!m_sizeForDrawing)
+        return true;
+
+    // The NativeImage was decoded for a specific size. The two sizeForDrawings have to match.
+    return sizeForDrawing &amp;&amp; maxDimension(*m_sizeForDrawing) &gt;= maxDimension(*sizeForDrawing);
+}
+
</ins><span class="cx"> Color ImageFrame::singlePixelSolidColor() const
</span><span class="cx"> {
</span><span class="cx">     if (!hasNativeImage() || m_size != IntSize(1, 1))
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrame.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;ImageOrientation.h&quot;
</span><span class="cx"> #include &quot;IntSize.h&quot;
</span><span class="cx"> #include &quot;NativeImage.h&quot;
</span><ins>+#include &lt;wtf/Deque.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -37,7 +38,6 @@
</span><span class="cx"> 
</span><span class="cx"> // There are four subsampling levels: 0 = 1x, 1 = 0.5x, 2 = 0.25x, 3 = 0.125x.
</span><span class="cx"> enum class SubsamplingLevel {
</span><del>-    Undefinded = -1,
</del><span class="cx">     First = 0,
</span><span class="cx">     Default = First,
</span><span class="cx">     Level0 = First,
</span><span class="lines">@@ -73,16 +73,11 @@
</span><span class="cx">     Ignored
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-enum class DecodingMode {
-    OnDemand,
-    Immediate
-};
-
</del><span class="cx"> class ImageFrame {
</span><span class="cx">     friend class ImageFrameCache;
</span><span class="cx"> public:
</span><del>-    enum class Caching { Empty, Metadata, MetadataAndImage };
-    enum class Decoding { Empty, BeingDecoded, Partial, Complete };
</del><ins>+    enum class Caching { Metadata, MetadataAndImage };
+    enum class Decoding { None, Partial, Complete };
</ins><span class="cx"> 
</span><span class="cx">     ImageFrame();
</span><span class="cx">     ImageFrame(const ImageFrame&amp; other) { operator=(other); }
</span><span class="lines">@@ -103,8 +98,12 @@
</span><span class="cx"> 
</span><span class="cx">     void setDecoding(Decoding decoding) { m_decoding = decoding; }
</span><span class="cx">     Decoding decoding() const { return m_decoding; }
</span><del>-    bool isEmpty() const { return m_decoding == Decoding::Empty; }
-    bool isBeingDecoded() const { return m_decoding == Decoding::BeingDecoded; }
</del><ins>+    void enqueueSizeForDecoding(const IntSize&amp; sizeForDecoding) { m_sizeForDecoding.append(sizeForDecoding); }
+    void dequeueSizeForDecoding() { m_sizeForDecoding.removeFirst(); }
+    void clearSizeForDecoding() { m_sizeForDecoding.clear(); }
+
+    bool isEmpty() const { return m_decoding == Decoding::None; }
+    bool isBeingDecoded(const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { }) const;
</ins><span class="cx">     bool isPartial() const { return m_decoding == Decoding::Partial; }
</span><span class="cx">     bool isComplete() const { return m_decoding == Decoding::Complete; }
</span><span class="cx"> 
</span><span class="lines">@@ -112,6 +111,7 @@
</span><span class="cx">     IntSize sizeRespectingOrientation() const { return !m_orientation.usesWidthAsHeight() ? size() : size().transposedSize(); }
</span><span class="cx">     unsigned frameBytes() const { return hasNativeImage() ? (size().area() * sizeof(RGBA32)).unsafeGet() : 0; }
</span><span class="cx">     SubsamplingLevel subsamplingLevel() const { return m_subsamplingLevel; }
</span><ins>+    std::optional&lt;IntSize&gt; sizeForDrawing() const { return m_sizeForDrawing; }
</ins><span class="cx"> 
</span><span class="cx"> #if !USE(CG)
</span><span class="cx">     enum class DisposalMethod { Unspecified, DoNotDispose, RestoreToBackground, RestoreToPrevious };
</span><span class="lines">@@ -131,7 +131,8 @@
</span><span class="cx">     bool hasAlpha() const { return !hasMetadata() || m_hasAlpha; }
</span><span class="cx"> 
</span><span class="cx">     bool hasNativeImage() const { return m_nativeImage; }
</span><del>-    bool hasValidNativeImage(SubsamplingLevel subsamplingLevel) const { return hasNativeImage() &amp;&amp; subsamplingLevel &gt;= m_subsamplingLevel; }
</del><ins>+    bool hasValidNativeImage(const std::optional&lt;SubsamplingLevel&gt;&amp;, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const;
+    bool hasDecodedNativeImage() const { return hasNativeImage() &amp;&amp; sizeForDrawing(); }
</ins><span class="cx">     bool hasMetadata() const { return !size().isEmpty(); }
</span><span class="cx"> 
</span><span class="cx"> #if !USE(CG)
</span><span class="lines">@@ -142,7 +143,7 @@
</span><span class="cx">     Color singlePixelSolidColor() const;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    Decoding m_decoding { Decoding::Empty };
</del><ins>+    Decoding m_decoding { Decoding::None };
</ins><span class="cx">     IntSize m_size;
</span><span class="cx"> 
</span><span class="cx"> #if !USE(CG)
</span><span class="lines">@@ -152,6 +153,8 @@
</span><span class="cx"> 
</span><span class="cx">     NativeImagePtr m_nativeImage;
</span><span class="cx">     SubsamplingLevel m_subsamplingLevel { SubsamplingLevel::Default };
</span><ins>+    std::optional&lt;IntSize&gt; m_sizeForDrawing;
+    Deque&lt;IntSize, 4&gt; m_sizeForDecoding;
</ins><span class="cx"> 
</span><span class="cx">     ImageOrientation m_orientation { DefaultImageOrientation };
</span><span class="cx">     float m_duration { 0 };
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameCachecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -174,7 +174,7 @@
</span><span class="cx">     frame.m_hasAlpha = nativeImageHasAlpha(frame.m_nativeImage);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrameCache::setFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+void ImageFrameCache::setFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><span class="cx">     ImageFrame&amp; frame = m_frames[index];
</span><span class="lines">@@ -182,10 +182,10 @@
</span><span class="cx">     ASSERT(isDecoderAvailable());
</span><span class="cx"> 
</span><span class="cx">     frame.m_nativeImage = WTFMove(nativeImage);
</span><del>-    setFrameMetadataAtIndex(index, subsamplingLevel);
</del><ins>+    setFrameMetadataAtIndex(index, subsamplingLevel, sizeForDrawing);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrameCache::setFrameMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+void ImageFrameCache::setFrameMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><span class="cx">     ImageFrame&amp; frame = m_frames[index];
</span><span class="lines">@@ -196,20 +196,29 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     frame.m_subsamplingLevel = subsamplingLevel;
</span><del>-    frame.m_size = m_decoder-&gt;frameSizeAtIndex(index, subsamplingLevel);
</del><ins>+
+    if (!sizeForDrawing) {
+        frame.m_size = m_decoder-&gt;frameSizeAtIndex(index, frame.m_subsamplingLevel);
+        frame.m_sizeForDrawing = { };
+    } else {
+        ASSERT(frame.nativeImage());
+        frame.m_size = nativeImageSize(frame.nativeImage());
+        frame.m_sizeForDrawing = sizeForDrawing;
+    }
+
</ins><span class="cx">     frame.m_orientation = m_decoder-&gt;frameOrientationAtIndex(index);
</span><span class="cx">     frame.m_hasAlpha = m_decoder-&gt;frameHasAlphaAtIndex(index);
</span><del>-    
</del><ins>+
</ins><span class="cx">     if (repetitionCount())
</span><span class="cx">         frame.m_duration = m_decoder-&gt;frameDurationAtIndex(index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrameCache::replaceFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+void ImageFrameCache::replaceFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><span class="cx">     ImageFrame&amp; frame = m_frames[index];
</span><span class="cx"> 
</span><del>-    if (!frame.hasValidNativeImage(subsamplingLevel)) {
</del><ins>+    if (!frame.hasValidNativeImage(subsamplingLevel, sizeForDrawing)) {
</ins><span class="cx">         // Clear the current image frame and update the observer with this clearance.
</span><span class="cx">         unsigned decodedSize = frame.clear();
</span><span class="cx">         decodedSizeDecreased(decodedSize);
</span><span class="lines">@@ -221,22 +230,23 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // Copy the new image to the cache.
</span><del>-    setFrameNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel);
</del><ins>+    setFrameNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel, sizeForDrawing);
</ins><span class="cx"> 
</span><span class="cx">     // Update the observer with the new image frame bytes.
</span><span class="cx">     decodedSizeIncreased(frame.frameBytes());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrameCache::cacheFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+void ImageFrameCache::cacheFrameNativeImageAtIndex(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel, const IntSize&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     if (!isDecoderAvailable())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><del>-    ASSERT(m_frames[index].isBeingDecoded());
</del><ins>+    ASSERT(m_frames[index].isBeingDecoded(sizeForDrawing));
</ins><span class="cx"> 
</span><span class="cx">     // Clean the old native image and set a new one
</span><del>-    replaceFrameNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel);
</del><ins>+    replaceFrameNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel, sizeForDrawing);
+    m_frames[index].dequeueSizeForDecoding();
</ins><span class="cx"> 
</span><span class="cx">     // Notify the image with the readiness of the new frame NativeImage.
</span><span class="cx">     if (m_image)
</span><span class="lines">@@ -267,26 +277,23 @@
</span><span class="cx"> 
</span><span class="cx">         while (m_frameRequestQueue.dequeue(frameRequest)) {
</span><span class="cx">             // Get the frame NativeImage on the decoding thread.
</span><del>-            NativeImagePtr nativeImage = m_decoder-&gt;createFrameImageAtIndex(frameRequest.index, frameRequest.subsamplingLevel, DecodingMode::Immediate);
</del><ins>+            NativeImagePtr nativeImage = m_decoder-&gt;createFrameImageAtIndex(frameRequest.index, frameRequest.subsamplingLevel, frameRequest.sizeForDrawing);
</ins><span class="cx"> 
</span><span class="cx">             // Update the cached frames on the main thread to avoid updating the MemoryCache from a different thread.
</span><span class="cx">             callOnMainThread([this, protectedQueue = protectedQueue.copyRef(), nativeImage, frameRequest] () mutable {
</span><span class="cx">                 // The queue may be closed if after we got the frame NativeImage, stopAsyncDecodingQueue() was called
</span><span class="cx">                 if (protectedQueue.ptr() == m_decodingQueue)
</span><del>-                    cacheFrameNativeImageAtIndex(WTFMove(nativeImage), frameRequest.index, frameRequest.subsamplingLevel);
</del><ins>+                    cacheFrameNativeImageAtIndex(WTFMove(nativeImage), frameRequest.index, frameRequest.subsamplingLevel, frameRequest.sizeForDrawing);
</ins><span class="cx">             });
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+bool ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const IntSize&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     if (!isDecoderAvailable())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    if (!hasDecodingQueue())
-        startAsyncDecodingQueue();
-
</del><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><span class="cx">     ImageFrame&amp; frame = m_frames[index];
</span><span class="cx"> 
</span><span class="lines">@@ -293,17 +300,17 @@
</span><span class="cx">     // We need to coalesce multiple requests for decoding the same ImageFrame while it
</span><span class="cx">     // is still being decoded. This may happen if the image rectangle is repainted
</span><span class="cx">     // multiple times while the ImageFrame has not finished decoding.
</span><del>-    if (frame.isBeingDecoded())
</del><ins>+    if (frame.isBeingDecoded(sizeForDrawing))
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    if (subsamplingLevel == SubsamplingLevel::Undefinded)
-        subsamplingLevel = frame.subsamplingLevel();
-
-    if (frame.hasValidNativeImage(subsamplingLevel))
</del><ins>+    if (frame.hasValidNativeImage(subsamplingLevel, sizeForDrawing))
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><del>-    frame.setDecoding(ImageFrame::Decoding::BeingDecoded);
-    m_frameRequestQueue.enqueue({ index, subsamplingLevel });
</del><ins>+    if (!hasDecodingQueue())
+        startAsyncDecodingQueue();
+    
+    frame.enqueueSizeForDecoding(sizeForDrawing);
+    m_frameRequestQueue.enqueue({ index, subsamplingLevel, sizeForDrawing });
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -316,25 +323,39 @@
</span><span class="cx">     m_decodingQueue = nullptr;
</span><span class="cx"> 
</span><span class="cx">     for (ImageFrame&amp; frame : m_frames) {
</span><del>-        if (frame.isBeingDecoded())
</del><ins>+        if (frame.isBeingDecoded()) {
+            frame.clearSizeForDecoding();
</ins><span class="cx">             frame.clear();
</span><ins>+        }
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-const ImageFrame&amp; ImageFrameCache::frameAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching)
</del><ins>+const ImageFrame&amp; ImageFrameCache::frameAtIndexCacheIfNeeded(size_t index, ImageFrame::Caching caching, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(index &lt; m_frames.size());
</span><span class="cx">     ImageFrame&amp; frame = m_frames[index];
</span><del>-    if (!isDecoderAvailable() || frame.isBeingDecoded() || caching == ImageFrame::Caching::Empty)
</del><ins>+    if (!isDecoderAvailable() || frame.isBeingDecoded(sizeForDrawing))
</ins><span class="cx">         return frame;
</span><span class="cx">     
</span><del>-    if (subsamplingLevel == SubsamplingLevel::Undefinded)
-        subsamplingLevel = frame.subsamplingLevel();
</del><ins>+    SubsamplingLevel subsamplingLevelValue = subsamplingLevel ? subsamplingLevel.value() : frame.subsamplingLevel();
</ins><span class="cx"> 
</span><del>-    if (!frame.isComplete() &amp;&amp; caching == ImageFrame::Caching::Metadata)
-        setFrameMetadataAtIndex(index, subsamplingLevel);
-    else if (!frame.hasValidNativeImage(subsamplingLevel) &amp;&amp; caching == ImageFrame::Caching::MetadataAndImage)
-        replaceFrameNativeImageAtIndex(m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevel), index, subsamplingLevel);
</del><ins>+    switch (caching) {
+    case ImageFrame::Caching::Metadata:
+        // Retrieve the metadata from ImageDecoder if the ImageFrame isn't complete.
+        if (frame.isComplete())
+            break;
+        setFrameMetadataAtIndex(index, subsamplingLevelValue, frame.sizeForDrawing());
+        break;
+            
+    case ImageFrame::Caching::MetadataAndImage:
+        // Cache the image and retrieve the metadata from ImageDecoder only if there was not valid image stored.
+        if (frame.hasValidNativeImage(subsamplingLevel, sizeForDrawing))
+            break;
+        // We have to perform synchronous image decoding in this code path regardless of the sizeForDrawing value.
+        // So pass an empty sizeForDrawing to create an ImageFrame with the native size.
+        replaceFrameNativeImageAtIndex(m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevelValue, { }), index, subsamplingLevelValue, { });
+        break;
+    }
</ins><span class="cx"> 
</span><span class="cx">     return frame;
</span><span class="cx"> }
</span><span class="lines">@@ -362,18 +383,25 @@
</span><span class="cx">     return cachedValue-&gt;value();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T, T (ImageFrame::*functor)() const&gt;
-T ImageFrameCache::frameMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching, std::optional&lt;T&gt;* cachedValue)
</del><ins>+template&lt;typename T, typename... Args&gt;
+T ImageFrameCache::frameMetadataAtIndex(size_t index, T (ImageFrame::*functor)(Args...) const, Args&amp;&amp;... args)
</ins><span class="cx"> {
</span><ins>+    const ImageFrame&amp; frame = index &lt; m_frames.size() ? m_frames[index] : ImageFrame::defaultFrame();
+    return (frame.*functor)(std::forward&lt;Args&gt;(args)...);
+}
+
+template&lt;typename T, typename... Args&gt;
+T ImageFrameCache::frameMetadataAtIndexCacheIfNeeded(size_t index, T (ImageFrame::*functor)() const, std::optional&lt;T&gt;* cachedValue, Args&amp;&amp;... args)
+{
</ins><span class="cx">     if (cachedValue &amp;&amp; *cachedValue)
</span><span class="cx">         return cachedValue-&gt;value();
</span><del>-    
-    const ImageFrame&amp; frame = index &lt; m_frames.size() ? frameAtIndex(index, subsamplingLevel, caching) : ImageFrame::defaultFrame();
</del><span class="cx"> 
</span><ins>+    const ImageFrame&amp; frame = index &lt; m_frames.size() ? frameAtIndexCacheIfNeeded(index, std::forward&lt;Args&gt;(args)...) : ImageFrame::defaultFrame();
+
</ins><span class="cx">     // Don't cache any unavailable frame metadata.
</span><span class="cx">     if (!frame.hasMetadata() || !cachedValue)
</span><span class="cx">         return (frame.*functor)();
</span><del>-    
</del><ins>+
</ins><span class="cx">     *cachedValue = (frame.*functor)();
</span><span class="cx">     return cachedValue-&gt;value();
</span><span class="cx"> }
</span><span class="lines">@@ -413,72 +441,77 @@
</span><span class="cx"> 
</span><span class="cx"> IntSize ImageFrameCache::size()
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::size)&gt;(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &amp;m_size);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;IntSize&gt;(0, (&amp;ImageFrame::size), &amp;m_size, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IntSize ImageFrameCache::sizeRespectingOrientation()
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::sizeRespectingOrientation)&gt;(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &amp;m_sizeRespectingOrientation);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;IntSize&gt;(0, (&amp;ImageFrame::sizeRespectingOrientation), &amp;m_sizeRespectingOrientation, ImageFrame::Caching::Metadata, SubsamplingLevel::Default);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Color ImageFrameCache::singlePixelSolidColor()
</span><span class="cx"> {
</span><del>-    return frameCount() == 1 ? frameMetadataAtIndex&lt;Color, (&amp;ImageFrame::singlePixelSolidColor)&gt;(0, SubsamplingLevel::Undefinded, ImageFrame::Caching::MetadataAndImage, &amp;m_singlePixelSolidColor) : Color();
</del><ins>+    return frameCount() == 1 ? frameMetadataAtIndexCacheIfNeeded&lt;Color&gt;(0, (&amp;ImageFrame::singlePixelSolidColor), &amp;m_singlePixelSolidColor, ImageFrame::Caching::MetadataAndImage) : Color();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ImageFrameCache::frameIsBeingDecodedAtIndex(size_t index)
</del><ins>+bool ImageFrameCache::frameIsBeingDecodedAtIndex(size_t index, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::isBeingDecoded)&gt;(index);
</del><ins>+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::isBeingDecoded), sizeForDrawing);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ImageFrameCache::frameIsCompleteAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::isComplete)&gt;(index);
</del><ins>+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::isComplete));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ImageFrameCache::frameHasAlphaAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::hasAlpha)&gt;(index);
</del><ins>+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::hasAlpha));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ImageFrameCache::frameHasImageAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::hasNativeImage)&gt;(index);
</del><ins>+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::hasNativeImage));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ImageFrameCache::frameHasValidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+bool ImageFrameCache::frameHasValidNativeImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><del>-    return frameHasImageAtIndex(index) &amp;&amp; subsamplingLevel &gt;= frameSubsamplingLevelAtIndex(index);
</del><ins>+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::hasValidNativeImage), subsamplingLevel, sizeForDrawing);
</ins><span class="cx"> }
</span><ins>+    
+bool ImageFrameCache::frameHasDecodedNativeImage(size_t index)
+{
+    return frameMetadataAtIndex&lt;bool&gt;(index, (&amp;ImageFrame::hasDecodedNativeImage));
+}
</ins><span class="cx"> 
</span><span class="cx"> SubsamplingLevel ImageFrameCache::frameSubsamplingLevelAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;SubsamplingLevel, (&amp;ImageFrame::subsamplingLevel)&gt;(index);
</del><ins>+    return frameMetadataAtIndex&lt;SubsamplingLevel&gt;(index, (&amp;ImageFrame::subsamplingLevel));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IntSize ImageFrameCache::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::size)&gt;(index, subsamplingLevel, ImageFrame::Caching::Metadata);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;IntSize&gt;(index, (&amp;ImageFrame::size), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> unsigned ImageFrameCache::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;unsigned, (&amp;ImageFrame::frameBytes)&gt;(index, subsamplingLevel, ImageFrame::Caching::Metadata);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;unsigned&gt;(index, (&amp;ImageFrame::frameBytes), nullptr, ImageFrame::Caching::Metadata, subsamplingLevel);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> float ImageFrameCache::frameDurationAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;float, (&amp;ImageFrame::duration)&gt;(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;float&gt;(index, (&amp;ImageFrame::duration), nullptr, ImageFrame::Caching::Metadata);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ImageOrientation ImageFrameCache::frameOrientationAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;ImageOrientation, (&amp;ImageFrame::orientation)&gt;(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;ImageOrientation&gt;(index, (&amp;ImageFrame::orientation), nullptr, ImageFrame::Caching::Metadata);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</del><ins>+NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
</ins><span class="cx"> {
</span><del>-    return frameMetadataAtIndex&lt;NativeImagePtr, (&amp;ImageFrame::nativeImage)&gt;(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
</del><ins>+    return frameMetadataAtIndexCacheIfNeeded&lt;NativeImagePtr&gt;(index, (&amp;ImageFrame::nativeImage), nullptr, ImageFrame::Caching::MetadataAndImage, subsamplingLevel, sizeForDrawing);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageFrameCacheh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageFrameCache.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     
</span><span class="cx">     // Asynchronous image decoding
</span><span class="cx">     void startAsyncDecodingQueue();
</span><del>-    bool requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel);
</del><ins>+    bool requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel, const IntSize&amp;);
</ins><span class="cx">     void stopAsyncDecodingQueue();
</span><span class="cx">     bool hasDecodingQueue() { return m_decodingQueue; }
</span><span class="cx"> 
</span><span class="lines">@@ -88,11 +88,12 @@
</span><span class="cx">     Color singlePixelSolidColor();
</span><span class="cx"> 
</span><span class="cx">     // ImageFrame metadata which does not require caching the ImageFrame.
</span><del>-    bool frameIsBeingDecodedAtIndex(size_t);
</del><ins>+    bool frameIsBeingDecodedAtIndex(size_t, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
</ins><span class="cx">     bool frameIsCompleteAtIndex(size_t);
</span><span class="cx">     bool frameHasAlphaAtIndex(size_t);
</span><span class="cx">     bool frameHasImageAtIndex(size_t);
</span><del>-    bool frameHasValidNativeImageAtIndex(size_t, SubsamplingLevel);
</del><ins>+    bool frameHasValidNativeImageAtIndex(size_t, const std::optional&lt;SubsamplingLevel&gt;&amp;, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
+    bool frameHasDecodedNativeImage(size_t);
</ins><span class="cx">     SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
</span><span class="cx">     
</span><span class="cx">     // ImageFrame metadata which forces caching or re-caching the ImageFrame.
</span><span class="lines">@@ -100,7 +101,7 @@
</span><span class="cx">     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
</span><span class="cx">     float frameDurationAtIndex(size_t);
</span><span class="cx">     ImageOrientation frameOrientationAtIndex(size_t);
</span><del>-    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
</del><ins>+    NativeImagePtr frameImageAtIndex(size_t, const std::optional&lt;SubsamplingLevel&gt;&amp;, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ImageFrameCache(Image*);
</span><span class="lines">@@ -109,9 +110,12 @@
</span><span class="cx">     template&lt;typename T, T (ImageDecoder::*functor)() const&gt;
</span><span class="cx">     T metadata(const T&amp; defaultValue, std::optional&lt;T&gt;* cachedValue = nullptr);
</span><span class="cx"> 
</span><del>-    template&lt;typename T, T (ImageFrame::*functor)() const&gt;
-    T frameMetadataAtIndex(size_t index, SubsamplingLevel = SubsamplingLevel::Undefinded, ImageFrame::Caching = ImageFrame::Caching::Empty, std::optional&lt;T&gt;* = nullptr);
-
</del><ins>+    template&lt;typename T, typename... Args&gt;
+    T frameMetadataAtIndex(size_t, T (ImageFrame::*functor)(Args...) const, Args&amp;&amp;...);
+    
+    template&lt;typename T, typename... Args&gt;
+    T frameMetadataAtIndexCacheIfNeeded(size_t, T (ImageFrame::*functor)() const,  std::optional&lt;T&gt;* cachedValue, Args&amp;&amp;...);
+    
</ins><span class="cx">     bool isDecoderAvailable() const { return m_decoder; }
</span><span class="cx">     void destroyDecodedData(size_t frameCount, size_t excludeFrame);
</span><span class="cx">     void decodedSizeChanged(long long decodedSize);
</span><span class="lines">@@ -121,14 +125,14 @@
</span><span class="cx">     void decodedSizeReset(unsigned decodedSize);
</span><span class="cx"> 
</span><span class="cx">     void setNativeImage(NativeImagePtr&amp;&amp;);
</span><del>-    void setFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel);
-    void setFrameMetadataAtIndex(size_t, SubsamplingLevel);
-    void replaceFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel);
-    void cacheFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel);
</del><ins>+    void setFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
+    void setFrameMetadataAtIndex(size_t, SubsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
+    void replaceFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing);
+    void cacheFrameNativeImageAtIndex(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel, const IntSize&amp; sizeForDrawing);
</ins><span class="cx"> 
</span><span class="cx">     Ref&lt;WorkQueue&gt; decodingQueue();
</span><span class="cx"> 
</span><del>-    const ImageFrame&amp; frameAtIndex(size_t, SubsamplingLevel, ImageFrame::Caching);
</del><ins>+    const ImageFrame&amp; frameAtIndexCacheIfNeeded(size_t, ImageFrame::Caching, const std::optional&lt;SubsamplingLevel&gt;&amp; = { }, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { });
</ins><span class="cx"> 
</span><span class="cx">     Image* m_image { nullptr };
</span><span class="cx">     ImageDecoder* m_decoder { nullptr };
</span><span class="lines">@@ -141,6 +145,7 @@
</span><span class="cx">     struct ImageFrameRequest {
</span><span class="cx">         size_t index;
</span><span class="cx">         SubsamplingLevel subsamplingLevel;
</span><ins>+        IntSize sizeForDrawing;
</ins><span class="cx">     };
</span><span class="cx">     static const int BufferSize = 8;
</span><span class="cx">     using FrameRequestQueue = SynchronizedFixedQueue&lt;ImageFrameRequest, BufferSize&gt;;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageObserverh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageObserver.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageObserver.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageObserver.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> class Image;
</span><span class="cx"> class IntRect;
</span><ins>+class URL;
</ins><span class="cx"> 
</span><span class="cx"> // Interface for notification about changes to an image, including decoding,
</span><span class="cx"> // drawing, and animating.
</span><span class="lines">@@ -37,6 +38,7 @@
</span><span class="cx"> protected:
</span><span class="cx">     virtual ~ImageObserver() {}
</span><span class="cx"> public:
</span><ins>+    virtual URL sourceUrl() const = 0;
</ins><span class="cx">     virtual bool allowSubsampling() const = 0;
</span><span class="cx">     virtual bool allowLargeImageAsyncDecoding() const = 0;
</span><span class="cx">     virtual bool allowAnimatedImageAsyncDecoding() const = 0;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageSourcecpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -191,11 +191,10 @@
</span><span class="cx">     return isDecoderAvailable() ? m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr ImageSource::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const GraphicsContext* targetContext)
</del><ins>+NativeImagePtr ImageSource::frameImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing, const GraphicsContext* targetContext)
</ins><span class="cx"> {
</span><span class="cx">     setDecoderTargetContext(targetContext);
</span><del>-
-    return m_frameCache-&gt;frameImageAtIndex(index, subsamplingLevel);
</del><ins>+    return m_frameCache-&gt;frameImageAtIndex(index, subsamplingLevel, sizeForDrawing);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ImageSource::dump(TextStream&amp; ts)
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicsImageSourceh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/ImageSource.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     bool isAllDataReceived();
</span><span class="cx"> 
</span><span class="cx">     bool isAsyncDecodingRequired();
</span><del>-    bool requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { return m_frameCache-&gt;requestFrameAsyncDecodingAtIndex(index, subsamplingLevel); }
</del><ins>+    bool requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const IntSize&amp; sizeForDrawing) { return m_frameCache-&gt;requestFrameAsyncDecodingAtIndex(index, subsamplingLevel, sizeForDrawing); }
</ins><span class="cx">     bool hasDecodingQueue() const { return m_frameCache-&gt;hasDecodingQueue(); }
</span><span class="cx">     void stopAsyncDecodingQueue() { m_frameCache-&gt;stopAsyncDecodingQueue(); }
</span><span class="cx"> 
</span><span class="lines">@@ -86,11 +86,12 @@
</span><span class="cx">     Color singlePixelSolidColor() { return m_frameCache-&gt;singlePixelSolidColor(); }
</span><span class="cx"> 
</span><span class="cx">     // ImageFrame metadata which does not require caching the ImageFrame.
</span><del>-    bool frameIsBeingDecodedAtIndex(size_t index) { return m_frameCache-&gt;frameIsBeingDecodedAtIndex(index); }
</del><ins>+    bool frameIsBeingDecodedAtIndex(size_t index, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) { return m_frameCache-&gt;frameIsBeingDecodedAtIndex(index, sizeForDrawing); }
</ins><span class="cx">     bool frameIsCompleteAtIndex(size_t index) { return m_frameCache-&gt;frameIsCompleteAtIndex(index); }
</span><span class="cx">     bool frameHasAlphaAtIndex(size_t index) { return m_frameCache-&gt;frameHasAlphaAtIndex(index); }
</span><span class="cx">     bool frameHasImageAtIndex(size_t index) { return m_frameCache-&gt;frameHasImageAtIndex(index); }
</span><del>-    bool frameHasValidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { return m_frameCache-&gt;frameHasValidNativeImageAtIndex(index, subsamplingLevel); }
</del><ins>+    bool frameHasValidNativeImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) { return m_frameCache-&gt;frameHasValidNativeImageAtIndex(index, subsamplingLevel, sizeForDrawing); }
+    bool frameHasDecodedNativeImage(size_t index) { return m_frameCache-&gt;frameHasDecodedNativeImage(index); }
</ins><span class="cx">     SubsamplingLevel frameSubsamplingLevelAtIndex(size_t index) { return m_frameCache-&gt;frameSubsamplingLevelAtIndex(index); }
</span><span class="cx"> 
</span><span class="cx">     // ImageFrame metadata which forces caching or re-caching the ImageFrame.
</span><span class="lines">@@ -98,7 +99,7 @@
</span><span class="cx">     unsigned frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache-&gt;frameBytesAtIndex(index, subsamplingLevel); }
</span><span class="cx">     float frameDurationAtIndex(size_t index) { return m_frameCache-&gt;frameDurationAtIndex(index); }
</span><span class="cx">     ImageOrientation frameOrientationAtIndex(size_t index) { return m_frameCache-&gt;frameOrientationAtIndex(index); }
</span><del>-    NativeImagePtr frameImageAtIndex(size_t index, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* targetContext = nullptr);
</del><ins>+    NativeImagePtr frameImageAtIndex(size_t index, const std::optional&lt;SubsamplingLevel&gt;&amp; = { }, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { }, const GraphicsContext* targetContext = nullptr);
</ins><span class="cx"> 
</span><span class="cx">     SubsamplingLevel maximumSubsamplingLevel();
</span><span class="cx">     SubsamplingLevel subsamplingLevelForScale(float);
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicscgImageDecoderCGcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -58,41 +58,68 @@
</span><span class="cx"> const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR(&quot;kCGImageSourceShouldPreferRGB32&quot;);
</span><span class="cx"> const CFStringRef kCGImageSourceSkipMetadata = CFSTR(&quot;kCGImageSourceSkipMetadata&quot;);
</span><span class="cx"> 
</span><del>-static RetainPtr&lt;CFDictionaryRef&gt; createImageSourceOptions(SubsamplingLevel subsamplingLevel, DecodingMode decodingMode)
</del><ins>+static RetainPtr&lt;CFMutableDictionaryRef&gt; createImageSourceOptions()
</ins><span class="cx"> {
</span><span class="cx">     RetainPtr&lt;CFMutableDictionaryRef&gt; options = adoptCF(CFDictionaryCreateMutable(nullptr, 0, &amp;kCFTypeDictionaryKeyCallBacks, &amp;kCFTypeDictionaryValueCallBacks));
</span><del>-
</del><span class="cx">     CFDictionarySetValue(options.get(), kCGImageSourceShouldCache, kCFBooleanTrue);
</span><span class="cx">     CFDictionarySetValue(options.get(), kCGImageSourceShouldPreferRGB32, kCFBooleanTrue);
</span><span class="cx">     CFDictionarySetValue(options.get(), kCGImageSourceSkipMetadata, kCFBooleanTrue);
</span><del>-
-    if (subsamplingLevel &gt; SubsamplingLevel::First) {
-        RetainPtr&lt;CFNumberRef&gt; subsampleNumber;
-        subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
-        int subsampleInt = 1 &lt;&lt; static_cast&lt;int&gt;(subsamplingLevel); // [0..3] =&gt; [1, 2, 4, 8]
-        subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &amp;subsampleInt));
-        CFDictionarySetValue(options.get(), kCGImageSourceSubsampleFactor, subsampleNumber.get());
-    }
-
-    if (decodingMode == DecodingMode::Immediate) {
-        CFDictionarySetValue(options.get(), kCGImageSourceShouldCacheImmediately, kCFBooleanTrue);
-        CFDictionarySetValue(options.get(), kCGImageSourceCreateThumbnailFromImageAlways, kCFBooleanTrue);
-    }
-
</del><span class="cx">     return options;
</span><span class="cx"> }
</span><ins>+    
+static RetainPtr&lt;CFMutableDictionaryRef&gt; createImageSourceAsyncOptions()
+{
+    RetainPtr&lt;CFMutableDictionaryRef&gt; options = createImageSourceOptions();
+    CFDictionarySetValue(options.get(), kCGImageSourceShouldCacheImmediately, kCFBooleanTrue);
+    CFDictionarySetValue(options.get(), kCGImageSourceCreateThumbnailFromImageAlways, kCFBooleanTrue);
+    return options;
+}
</ins><span class="cx"> 
</span><del>-static RetainPtr&lt;CFDictionaryRef&gt; imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default, DecodingMode decodingMode = DecodingMode::OnDemand)
</del><ins>+static RetainPtr&lt;CFMutableDictionaryRef&gt; appendImageSourceOption(RetainPtr&lt;CFMutableDictionaryRef&gt;&amp;&amp; options, SubsamplingLevel subsamplingLevel)
</ins><span class="cx"> {
</span><del>-    if (subsamplingLevel &gt; SubsamplingLevel::First)
-        return createImageSourceOptions(subsamplingLevel, decodingMode);
</del><ins>+    RetainPtr&lt;CFNumberRef&gt; subsampleNumber;
+    subsamplingLevel = std::min(SubsamplingLevel::Last, std::max(SubsamplingLevel::First, subsamplingLevel));
+    int subsampleInt = 1 &lt;&lt; static_cast&lt;int&gt;(subsamplingLevel); // [0..3] =&gt; [1, 2, 4, 8]
+    subsampleNumber = adoptCF(CFNumberCreate(nullptr,  kCFNumberIntType,  &amp;subsampleInt));
+    CFDictionarySetValue(options.get(), kCGImageSourceSubsampleFactor, subsampleNumber.get());
+    return WTFMove(options);
+}
</ins><span class="cx"> 
</span><del>-    static NeverDestroyed&lt;RetainPtr&lt;CFDictionaryRef&gt;&gt; optionsOnDemand = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::OnDemand);
-    static NeverDestroyed&lt;RetainPtr&lt;CFDictionaryRef&gt;&gt; optionsImmediate = createImageSourceOptions(SubsamplingLevel::First, DecodingMode::Immediate);
</del><ins>+static RetainPtr&lt;CFMutableDictionaryRef&gt; appendImageSourceOption(RetainPtr&lt;CFMutableDictionaryRef&gt;&amp;&amp; options, const IntSize&amp; sizeForDrawing)
+{
+    unsigned maxPixelSize = std::max(sizeForDrawing.width(), sizeForDrawing.height());
+    RetainPtr&lt;CFNumberRef&gt; maxPixelSizeNumber = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &amp;maxPixelSize));
+    CFDictionarySetValue(options.get(), kCGImageSourceThumbnailMaxPixelSize, maxPixelSizeNumber.get());
+    return WTFMove(options);
+}
+    
+static RetainPtr&lt;CFMutableDictionaryRef&gt; appendImageSourceOptions(RetainPtr&lt;CFMutableDictionaryRef&gt;&amp;&amp; options, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing)
+{
+    if (subsamplingLevel != SubsamplingLevel::Default)
+        options = appendImageSourceOption(WTFMove(options), subsamplingLevel);
+    
+    if (sizeForDrawing)
+        options = appendImageSourceOption(WTFMove(options), sizeForDrawing.value());
</ins><span class="cx"> 
</span><del>-    return decodingMode == DecodingMode::OnDemand ? optionsOnDemand : optionsImmediate;
</del><ins>+    return WTFMove(options);
</ins><span class="cx"> }
</span><ins>+    
+static RetainPtr&lt;CFDictionaryRef&gt; imageSourceOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default)
+{
+    static NeverDestroyed&lt;RetainPtr&lt;CFMutableDictionaryRef&gt;&gt; options = createImageSourceOptions();
+    if (subsamplingLevel == SubsamplingLevel::Default)
+        return options.get();
+    return appendImageSourceOption(adoptCF(CFDictionaryCreateMutableCopy(nullptr, 0, options.get().get())), subsamplingLevel);
+}
</ins><span class="cx"> 
</span><ins>+static RetainPtr&lt;CFDictionaryRef&gt; imageSourceAsyncOptions(SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { })
+{
+    static NeverDestroyed&lt;RetainPtr&lt;CFMutableDictionaryRef&gt;&gt; options = createImageSourceAsyncOptions();
+    if (subsamplingLevel == SubsamplingLevel::Default &amp;&amp; !sizeForDrawing)
+        return options.get();
+    return appendImageSourceOptions(adoptCF(CFDictionaryCreateMutableCopy(nullptr, 0, options.get().get())), subsamplingLevel, sizeForDrawing);
+}
+    
</ins><span class="cx"> static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(imageProperties);
</span><span class="lines">@@ -339,17 +366,29 @@
</span><span class="cx">     return (frameSize.area() * 4).unsafeGet();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode decodingMode) const
</del><ins>+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing) const
</ins><span class="cx"> {
</span><span class="cx">     LOG(Images, &quot;ImageDecoder %p createFrameImageAtIndex %lu&quot;, this, index);
</span><del>-
-    RetainPtr&lt;CFDictionaryRef&gt; options = imageSourceOptions(subsamplingLevel, decodingMode);
</del><ins>+    RetainPtr&lt;CFDictionaryRef&gt; options;
</ins><span class="cx">     RetainPtr&lt;CGImageRef&gt; image;
</span><span class="cx"> 
</span><del>-    if (decodingMode == DecodingMode::OnDemand)
</del><ins>+    if (!sizeForDrawing) {
+        // Decode an image synchronously for its native size.
+        options = imageSourceOptions(subsamplingLevel);
</ins><span class="cx">         image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, options.get()));
</span><del>-    else
</del><ins>+    } else {
+        IntSize size = frameSizeAtIndex(index, subsamplingLevel);
+
+        if (size.unclampedArea() &lt; sizeForDrawing.value().unclampedArea()) {
+            // Decode an image asynchronously for its native size.
+            options = imageSourceAsyncOptions(subsamplingLevel);
+        } else {
+            // Decode an image asynchronously for sizeForDrawing since it is smaller than the image native size.
+            options = imageSourceAsyncOptions(subsamplingLevel, sizeForDrawing);
+        }
+        
</ins><span class="cx">         image = adoptCF(CGImageSourceCreateThumbnailAtIndex(m_nativeDecoder.get(), index, options.get()));
</span><ins>+    }
</ins><span class="cx">     
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     // &lt;rdar://problem/7371198&gt; - CoreGraphics changed the default caching behaviour in iOS 4.0 to kCGImageCachingTransient
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicscgImageDecoderCGh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">     bool frameAllowSubsamplingAtIndex(size_t) const;
</span><span class="cx">     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
</span><span class="cx">     
</span><del>-    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
</del><ins>+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const std::optional&lt;IntSize&gt;&amp; sizeForDrawing = { }) const;
</ins><span class="cx">     
</span><span class="cx">     void setData(SharedBuffer&amp;, bool allDataReceived);
</span><span class="cx">     bool isAllDataReceived() const { return m_isAllDataReceived; }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicswinImageDecoderDirect2Dcpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -180,7 +180,7 @@
</span><span class="cx">     m_renderTarget = renderTarget;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodingMode) const
</del><ins>+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, const std::optional&lt;IntSize&gt;&amp;) const
</ins><span class="cx"> {
</span><span class="cx">     if (!m_nativeDecoder || !m_renderTarget)
</span><span class="cx">         return nullptr;
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformgraphicswinImageDecoderDirect2Dh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/graphics/win/ImageDecoderDirect2D.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx">     bool frameAllowSubsamplingAtIndex(size_t) const;
</span><span class="cx">     unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
</span><span class="cx">     
</span><del>-    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand) const;
</del><ins>+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const std::optional&lt;IntSize&gt;&amp; sizeForDraw = { }) const;
</ins><span class="cx">     
</span><span class="cx">     void setData(SharedBuffer&amp;, bool allDataReceived);
</span><span class="cx">     bool isAllDataReceived() const { return m_isAllDataReceived; }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformimagedecodersImageDecodercpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.cpp        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.cpp        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -207,7 +207,7 @@
</span><span class="cx">     return duration;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel, DecodingMode)
</del><ins>+NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel, const std::optional&lt;IntSize&gt;&amp;)
</ins><span class="cx"> {
</span><span class="cx">     // Zero-height images can cause problems for some ports. If we have an empty image dimension, just bail.
</span><span class="cx">     if (size().isEmpty())
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit216SourceWebCoreplatformimagedecodersImageDecoderh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.h (213829 => 213830)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.h        2017-03-13 11:40:37 UTC (rev 213829)
+++ releases/WebKitGTK/webkit-2.16/Source/WebCore/platform/image-decoders/ImageDecoder.h        2017-03-13 11:44:26 UTC (rev 213830)
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx">         
</span><span class="cx">         float frameDurationAtIndex(size_t);
</span><span class="cx">         
</span><del>-        NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, DecodingMode = DecodingMode::OnDemand);
</del><ins>+        NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const std::optional&lt;IntSize&gt;&amp; sizeForDraw = { });
</ins><span class="cx"> 
</span><span class="cx">         void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
</span><span class="cx">         bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
</span></span></pre>
</div>
</div>

</body>
</html>