<!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>[206481] trunk/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/206481">206481</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-09-27 18:06:57 -0700 (Tue, 27 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move caching the ImageFrame from BitmapImage to ImageSource
https://bugs.webkit.org/show_bug.cgi?id=155498

Patch by Said Abou-Hallawa &lt;sabouhallawa@apple.com&gt; on 2016-09-27
Reviewed by Simon Fraser.

BitmapImage has two modes of operation regarding its image decoding state.
The first mode happens when a remote image is loaded as encoded data and
which requires an ImageDecoder to generate the image metadata and the
the ImageFrames. The second mode happens when a BitmapImage is created
with a NativeImagePtr. In this case, no ImageDecoder is needed.

To remove this burden from the BitmapImage the member 'm_frames' is removed
from BitmapImage. A new member named 'm_frameCache' of type ImageFrameCache
is added to ImageSource. This class handles caching and recaching the image
metadata and the ImageFrames if the image needs decoding. When the BitmapImage
is initialized with a memory image, the ImageFrameCache initializes its
metadata and ImageFrames directly from the NativeImagePtr.

The plan for ImageFrameCache is to be extended for the asynchronous image
decoding and also to be used by the non CG image decoders which cache
other copies of the ImageFrames. This double caching should be removed.

When the BitmapImage is replying to the ImageFrame queries, it will ask the
ImageSource which will pass the query the ImageFrameCache. ImageFrameCache
will ensure the requested ImageFrame is cached and is valid for the requested
SubSamplingLevel before accessing the data members of this ImageFrame.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
Add and ImageFrameCache.cpp to the WebCore project.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::BitmapImage): Move initializing the image metadata to
ImageSource. Add initializers for the remaining members in the class declaration.

(WebCore::BitmapImage::destroyDecodedData): Move most of the logic of this
function to ImageFrameCache::destroyDecodedData(). The only part which can't
be moved is the call invalidatePlatformData().

(WebCore::BitmapImage::destroyDecodedDataIfNecessary): Move the logic of this
function to ImageFrameCache::destroyDecodedDataIfNecessary().

(WebCore::BitmapImage::dataChanged): Move the logic of this function to
ImageSource::dataChanged().

(WebCore::BitmapImage::frameImageAtIndex): Move most of the logic of this
function to ImageFrameCache::frameImageAtIndex(). The only part which can't
be moved is the call invalidatePlatformData() if the required subsampling
level is different from the subsampling level for the cached frame image.

(WebCore::BitmapImage::draw): Replace the BitmapImage  cached metadata with
the corresponding ImageSource cached metadata.
(WebCore::BitmapImage::drawPattern): Ditto.
(WebCore::BitmapImage::shouldAnimate): Ditto.
(WebCore::BitmapImage::startAnimation): Ditto.
(WebCore::BitmapImage::internalAdvanceAnimation): Ditto.

(WebCore::BitmapImage::dump): Call ImageSource::dump() to dump the image
cached metadata.

(WebCore::BitmapImage::haveFrameImageAtIndex): Deleted.
(WebCore::BitmapImage::destroyMetadataAndNotify): Deleted.
(WebCore::BitmapImage::cacheFrame): Deleted.
(WebCore::BitmapImage::didDecodeProperties): Deleted.
(WebCore::BitmapImage::updateSize): Deleted.
(WebCore::BitmapImage::size): Deleted.
(WebCore::BitmapImage::sizeRespectingOrientation): Deleted.
(WebCore::BitmapImage::hotSpot): Deleted.
(WebCore::BitmapImage::frameCount): Deleted.
(WebCore::BitmapImage::isSizeAvailable): Deleted.
(WebCore::BitmapImage::ensureFrameAtIndexIsCached): Deleted.
(WebCore::BitmapImage::frameIsCompleteAtIndex): Deleted.
(WebCore::BitmapImage::frameDurationAtIndex): Deleted.
(WebCore::BitmapImage::frameHasAlphaAtIndex): Deleted.
(WebCore::BitmapImage::currentFrameKnownToBeOpaque): Deleted.
(WebCore::BitmapImage::frameOrientationAtIndex): Deleted.
(WebCore::BitmapImage::singlePixelSolidColor): Deleted.
(WebCore::BitmapImage::repetitionCount): Deleted.
* platform/graphics/BitmapImage.h:
Managing the ImageFrames caching is moved to ImageFrameCache. Caching the
image metadata is now moved to the ImageSource.

* platform/graphics/GeneratedImage.h:
* platform/graphics/Image.h:
(WebCore::Image::orientationForCurrentFrame):
(WebCore::Image::singlePixelSolidColor):
Change currentFrameKnownToBeOpaque(), orientationForCurrentFrame() and
singlePixelSolidColor() to be const.

* platform/graphics/ImageFrame.cpp:
(WebCore::ImageFrame::defaultFrame): Returns an empty ImageFrame to get the default ImageFrame metadata.
(WebCore::ImageFrame::fillMetadata): Deleted. Moved to ImageFrameCache.
(WebCore::ImageFrame::initialize): Deleted. Ditto.

* platform/graphics/ImageFrame.h:
(WebCore::ImageFrame::setDuration): Change the type of the argument to float instead of unsigned.
(WebCore::ImageFrame::hasAlpha): Protect the unset m_hasAlpha by checking hasMetadata() first.

* platform/graphics/ImageFrameCache.cpp: Added.
(WebCore::ImageFrameCache::ImageFrameCache): Two constructors similar to what we do for ImageSource and BitmapImage.
(WebCore::ImageFrameCache::destroyDecodedData): Moved from BitmapImage.cpp.
(WebCore::ImageFrameCache::destroyDecodedDataIfNecessary): Ditto.
(WebCore::ImageFrameCache::destroyIncompleteDecodedData): Ditto.
(WebCore::ImageFrameCache::decodedSizeChanged): Ditto.
(WebCore::ImageFrameCache::decodedSizeIncremented): Ditto.
(WebCore::ImageFrameCache::decodedSizeDecremented): Ditto.
(WebCore::ImageFrameCache::decodedSizeReset): Ditto.
(WebCore::ImageFrameCache::didDecodeProperties): Ditto.
(WebCore::ImageFrameCache::growFrames): Grows the size of m_frames if necessary.
(WebCore::ImageFrameCache::setNativeImage): Initializes the ImageFrame metadata directly from the NativeImagePtr.
(WebCore::ImageFrameCache::setFrameNativeImage): Initializes the ImageFrame image and the metadata.
(WebCore::ImageFrameCache::setFrameMetadata): Initializes the ImageFrame metadata from the ImageDecoder.
(WebCore::ImageFrameCache::frameAtIndex): Returns an ImageFrame given its index. Cache or recache the requested ImageFrame if necessary.
(WebCore::ImageFrameCache::clearMetadata): Invalidates the cached image metadata.
(WebCore::ImageFrameCache::metadata): A template function which returns an image metadata property.
(WebCore::ImageFrameCache::frameMetadataAtIndex): A template function which returns an ImageFrame metadata property.
(WebCore::ImageFrameCache::isSizeAvailable): An image metadata property.
(WebCore::ImageFrameCache::frameCount): Ditto.
(WebCore::ImageFrameCache::repetitionCount): Ditto.
(WebCore::ImageFrameCache::filenameExtension): Ditto.
(WebCore::ImageFrameCache::hotSpot): Ditto.
(WebCore::ImageFrameCache::size): An image metadata property but we get it from the first ImageFrame.
(WebCore::ImageFrameCache::sizeRespectingOrientation): Ditto.
(WebCore::ImageFrameCache::singlePixelSolidColor): Ditto.
(WebCore::ImageFrameCache::frameIsCompleteAtIndex): An ImageFrame metadata property.
(WebCore::ImageFrameCache::frameHasAlphaAtIndex): Ditto.
(WebCore::ImageFrameCache::frameHasImageAtIndex): Ditto.
(WebCore::ImageFrameCache::frameHasInvalidNativeImageAtIndex): Ditto.
(WebCore::ImageFrameCache::frameSubsamplingLevelAtIndex): Ditto.
(WebCore::ImageFrameCache::frameSizeAtIndex): Ditto.
(WebCore::ImageFrameCache::frameBytesAtIndex): Ditto.
(WebCore::ImageFrameCache::frameDurationAtIndex): Ditto.
(WebCore::ImageFrameCache::frameOrientationAtIndex): Ditto.
(WebCore::ImageFrameCache::frameImageAtIndex): Ditto.

* platform/graphics/ImageFrameCache.h: Added.
(WebCore::ImageFrameCache::setDecoder): Sets the current ImageDecoder which is owned by the ImageSource.
(WebCore::ImageFrameCache::decodedSize): Returns the size of the cached NativeImages.
(WebCore::ImageFrameCache::isDecoderAvailable): Returns whether an ImageDecoder is available.

* platform/graphics/ImageSource.cpp:
(WebCore::ImageSource::ImageSource): Initializes the ImageFrameCache based on the image decoding state.
(WebCore::ImageSource::clearFrameBufferCache): Replace initialized() with isDecoderAvailable().
(WebCore::ImageSource::clear): Clears the ImageDecoder of the ImageFrameCache.
(WebCore::ImageSource::destroyDecodedData): Moved from BitmapImage.cpp.
(WebCore::ImageSource::destroyDecodedDataIfNecessary): Ditto.
(WebCore::ImageSource::ensureDecoderAvailable): Creates an ImageDecoder if necessary and sets it in ImageFrameCache.
(WebCore::ImageSource::setData):
(WebCore::ImageSource::dataChanged): Moved from BitmapImage.cpp.
(WebCore::ImageSource::isAllDataReceived):
(WebCore::ImageSource::maximumSubsamplingLevel): Rename calculateMaximumSubsamplingLevel() to maximumSubsamplingLevel().
(WebCore::ImageSource::subsamplingLevelForScale):
(WebCore::ImageSource::createFrameImageAtIndex):
(WebCore::ImageSource::dump):
(WebCore::ImageSource::calculateMaximumSubsamplingLevel): Deleted. Renamed to maximumSubsamplingLevel().
(WebCore::ImageSource::updateMetadata): Deleted. Not needed. Caching the image metadata is the responsibility of ImageFrameCache.
(WebCore::ImageSource::bytesDecodedToDetermineProperties): Deleted. Not needed.
(WebCore::ImageSource::isSizeAvailable): Deleted. Moved to ImageSource.h.
(WebCore::ImageSource::size): Deleted. Ditto.
(WebCore::ImageSource::sizeRespectingOrientation): Deleted. Ditto.
(WebCore::ImageSource::frameCount): Deleted. Ditto.
(WebCore::ImageSource::repetitionCount): Deleted. Ditto.
(WebCore::ImageSource::filenameExtension): Deleted. Ditto.
(WebCore::ImageSource::hotSpot): Deleted. Ditto.
(WebCore::ImageSource::frameIsCompleteAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameHasAlphaAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameAllowSubsamplingAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameSizeAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameBytesAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameDurationAtIndex): Deleted. Ditto.
(WebCore::ImageSource::frameOrientationAtIndex): Deleted. Ditto.

* platform/graphics/ImageSource.h:
(WebCore::ImageSource::isDecoderAvailable): initialized() was renamed to isDecoderAvailable().
(WebCore::ImageSource::decodedSize): Send the query to ImageFrameCache.
(WebCore::ImageSource::isSizeAvailable): Ditto.
(WebCore::ImageSource::frameCount): Ditto.
(WebCore::ImageSource::repetitionCount): Ditto.
(WebCore::ImageSource::filenameExtension): Ditto.
(WebCore::ImageSource::hotSpot): Ditto.
(WebCore::ImageSource::size): Ditto.
(WebCore::ImageSource::sizeRespectingOrientation): Ditto.
(WebCore::ImageSource::singlePixelSolidColor): Ditto.
(WebCore::ImageSource::frameIsCompleteAtIndex): Ditto.
(WebCore::ImageSource::frameHasAlphaAtIndex): Ditto.
(WebCore::ImageSource::frameHasImageAtIndex): Ditto.
(WebCore::ImageSource::frameHasInvalidNativeImageAtIndex): Ditto.
(WebCore::ImageSource::frameSubsamplingLevelAtIndex): Ditto.
(WebCore::ImageSource::frameSizeAtIndex): Ditto.
(WebCore::ImageSource::frameBytesAtIndex): Ditto.
(WebCore::ImageSource::frameDurationAtIndex): Ditto.
(WebCore::ImageSource::frameOrientationAtIndex): Ditto.
(WebCore::ImageSource::frameImageAtIndex): Ditto.
(WebCore::ImageSource::decoder): Deleted. Not needed.
(WebCore::ImageSource::initialized): Deleted. Was renamed to isDecoderAvailable().
(WebCore::ImageSource::setNeedsUpdateMetadata): Deleted. Not needed.

* platform/graphics/cairo/GraphicsContext3DCairo.cpp:
(WebCore::GraphicsContext3D::ImageExtractor::extractImage): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/graphics/cg/GraphicsContext3DCG.cpp:
(WebCore::GraphicsContext3D::ImageExtractor::extractImage): Ditto.

* platform/graphics/cg/ImageDecoderCG.cpp:
(WebCore::ImageDecoder::ImageDecoder): Make the constructor of ImageDecoder be the same for all ports.
(WebCore::ImageDecoder::setData): Removed unused overloaded function.
(WebCore::ImageDecoder::size): Deleted.  Removed unused function.

* platform/graphics/cg/ImageDecoderCG.h:
(WebCore::ImageDecoder::create): Make the constructor of CG ImageDecoder be like the other ports.
(WebCore::ImageDecoder::isAllDataReceived): Make this property owned by ImageDecoder.

* platform/graphics/cg/PDFDocumentImage.h: Change currentFrameKnownToBeOpaque() to be const.

* platform/graphics/efl/GraphicsContext3DEfl.cpp:
(WebCore::GraphicsContext3D::ImageExtractor::extractImage): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.

* platform/graphics/mac/ImageMac.mm:
(WebCore::BitmapImage::invalidatePlatformData): m_frames is owned by ImageFrameCache. ImageFrameCache::frameCount() has to
be equal to ImageFrame::m_frames.size().

* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::create): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/image-decoders/ImageDecoder.h:
(WebCore::ImageDecoder::ImageDecoder): Ditto.
(WebCore::ImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
* platform/image-decoders/bmp/BMPImageDecoder.cpp:
(WebCore::BMPImageDecoder::BMPImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/image-decoders/bmp/BMPImageDecoder.h:
* platform/image-decoders/gif/GIFImageDecoder.cpp:
(WebCore::GIFImageDecoder::GIFImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
(WebCore::GIFImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
* platform/image-decoders/gif/GIFImageDecoder.h:
* platform/image-decoders/gif/GIFImageReader.cpp:
* platform/image-decoders/gif/GIFImageReader.h:
* platform/image-decoders/ico/ICOImageDecoder.cpp:
(WebCore::ICOImageDecoder::ICOImageDecoder):
(WebCore::ICOImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
(WebCore::ICOImageDecoder::decode): Move resizing the m_frameBufferCache from ICOImageDecoder::frameCount() to ICOImageDecoder::decode().
(WebCore::ICOImageDecoder::decodeAtIndex): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/image-decoders/ico/ICOImageDecoder.h:
* platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
(WebCore::JPEGImageDecoder::JPEGImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/image-decoders/jpeg/JPEGImageDecoder.h:
* platform/image-decoders/png/PNGImageDecoder.cpp:
(WebCore::PNGImageDecoder::PNGImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
* platform/image-decoders/png/PNGImageDecoder.h:
(WebCore::PNGImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
* platform/image-decoders/webp/WEBPImageDecoder.cpp:
(WebCore::WEBPImageDecoder::WEBPImageDecoder):
* platform/image-decoders/webp/WEBPImageDecoder.h:

* svg/graphics/SVGImage.h: Make currentFrameKnownToBeOpaque() be const.
* svg/graphics/SVGImageForContainer.h: Ditto.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsBitmapImagecpp">trunk/Source/WebCore/platform/graphics/BitmapImage.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsBitmapImageh">trunk/Source/WebCore/platform/graphics/BitmapImage.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsGeneratedImageh">trunk/Source/WebCore/platform/graphics/GeneratedImage.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageh">trunk/Source/WebCore/platform/graphics/Image.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageFramecpp">trunk/Source/WebCore/platform/graphics/ImageFrame.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageFrameh">trunk/Source/WebCore/platform/graphics/ImageFrame.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageSourcecpp">trunk/Source/WebCore/platform/graphics/ImageSource.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageSourceh">trunk/Source/WebCore/platform/graphics/ImageSource.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscairoGraphicsContext3DCairocpp">trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgGraphicsContext3DCGcpp">trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageDecoderCGcpp">trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageDecoderCGh">trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgPDFDocumentImageh">trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicseflGraphicsContext3DEflcpp">trunk/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacImageMacmm">trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersImageDecoderh">trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersbmpBMPImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersbmpBMPImageDecoderh">trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersgifGIFImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersgifGIFImageDecoderh">trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersgifGIFImageReadercpp">trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersgifGIFImageReaderh">trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersicoICOImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersicoICOImageDecoderh">trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersjpegJPEGImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecodersjpegJPEGImageDecoderh">trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecoderspngPNGImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecoderspngPNGImageDecoderh">trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecoderswebpWEBPImageDecodercpp">trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformimagedecoderswebpWEBPImageDecoderh">trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsSVGImageh">trunk/Source/WebCore/svg/graphics/SVGImage.h</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsSVGImageForContainerh">trunk/Source/WebCore/svg/graphics/SVGImageForContainer.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageFrameCachecpp">trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsImageFrameCacheh">trunk/Source/WebCore/platform/graphics/ImageFrameCache.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/CMakeLists.txt        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -2221,6 +2221,7 @@
</span><span class="cx">     platform/graphics/Image.cpp
</span><span class="cx">     platform/graphics/ImageBuffer.cpp
</span><span class="cx">     platform/graphics/ImageFrame.cpp
</span><ins>+    platform/graphics/ImageFrameCache.cpp
</ins><span class="cx">     platform/graphics/ImageOrientation.cpp
</span><span class="cx">     platform/graphics/ImageSource.cpp
</span><span class="cx">     platform/graphics/IntPoint.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/ChangeLog        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -1,3 +1,259 @@
</span><ins>+2016-09-27  Said Abou-Hallawa  &lt;sabouhallawa@apple.com&gt;
+
+        Move caching the ImageFrame from BitmapImage to ImageSource
+        https://bugs.webkit.org/show_bug.cgi?id=155498
+
+        Reviewed by Simon Fraser.
+
+        BitmapImage has two modes of operation regarding its image decoding state.
+        The first mode happens when a remote image is loaded as encoded data and
+        which requires an ImageDecoder to generate the image metadata and the
+        the ImageFrames. The second mode happens when a BitmapImage is created
+        with a NativeImagePtr. In this case, no ImageDecoder is needed.
+
+        To remove this burden from the BitmapImage the member 'm_frames' is removed
+        from BitmapImage. A new member named 'm_frameCache' of type ImageFrameCache
+        is added to ImageSource. This class handles caching and recaching the image
+        metadata and the ImageFrames if the image needs decoding. When the BitmapImage
+        is initialized with a memory image, the ImageFrameCache initializes its
+        metadata and ImageFrames directly from the NativeImagePtr.
+
+        The plan for ImageFrameCache is to be extended for the asynchronous image
+        decoding and also to be used by the non CG image decoders which cache
+        other copies of the ImageFrames. This double caching should be removed.
+
+        When the BitmapImage is replying to the ImageFrame queries, it will ask the
+        ImageSource which will pass the query the ImageFrameCache. ImageFrameCache
+        will ensure the requested ImageFrame is cached and is valid for the requested
+        SubSamplingLevel before accessing the data members of this ImageFrame.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Add and ImageFrameCache.cpp to the WebCore project.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::BitmapImage): Move initializing the image metadata to
+        ImageSource. Add initializers for the remaining members in the class declaration.
+
+        (WebCore::BitmapImage::destroyDecodedData): Move most of the logic of this
+        function to ImageFrameCache::destroyDecodedData(). The only part which can't
+        be moved is the call invalidatePlatformData().
+
+        (WebCore::BitmapImage::destroyDecodedDataIfNecessary): Move the logic of this
+        function to ImageFrameCache::destroyDecodedDataIfNecessary().
+
+        (WebCore::BitmapImage::dataChanged): Move the logic of this function to
+        ImageSource::dataChanged().
+
+        (WebCore::BitmapImage::frameImageAtIndex): Move most of the logic of this
+        function to ImageFrameCache::frameImageAtIndex(). The only part which can't
+        be moved is the call invalidatePlatformData() if the required subsampling
+        level is different from the subsampling level for the cached frame image.
+
+        (WebCore::BitmapImage::draw): Replace the BitmapImage  cached metadata with
+        the corresponding ImageSource cached metadata.
+        (WebCore::BitmapImage::drawPattern): Ditto.
+        (WebCore::BitmapImage::shouldAnimate): Ditto.
+        (WebCore::BitmapImage::startAnimation): Ditto.
+        (WebCore::BitmapImage::internalAdvanceAnimation): Ditto.
+
+        (WebCore::BitmapImage::dump): Call ImageSource::dump() to dump the image
+        cached metadata.
+
+        (WebCore::BitmapImage::haveFrameImageAtIndex): Deleted.
+        (WebCore::BitmapImage::destroyMetadataAndNotify): Deleted.
+        (WebCore::BitmapImage::cacheFrame): Deleted.
+        (WebCore::BitmapImage::didDecodeProperties): Deleted.
+        (WebCore::BitmapImage::updateSize): Deleted.
+        (WebCore::BitmapImage::size): Deleted.
+        (WebCore::BitmapImage::sizeRespectingOrientation): Deleted.
+        (WebCore::BitmapImage::hotSpot): Deleted.
+        (WebCore::BitmapImage::frameCount): Deleted.
+        (WebCore::BitmapImage::isSizeAvailable): Deleted.
+        (WebCore::BitmapImage::ensureFrameAtIndexIsCached): Deleted.
+        (WebCore::BitmapImage::frameIsCompleteAtIndex): Deleted.
+        (WebCore::BitmapImage::frameDurationAtIndex): Deleted.
+        (WebCore::BitmapImage::frameHasAlphaAtIndex): Deleted.
+        (WebCore::BitmapImage::currentFrameKnownToBeOpaque): Deleted.
+        (WebCore::BitmapImage::frameOrientationAtIndex): Deleted.
+        (WebCore::BitmapImage::singlePixelSolidColor): Deleted.
+        (WebCore::BitmapImage::repetitionCount): Deleted.
+        * platform/graphics/BitmapImage.h:
+        Managing the ImageFrames caching is moved to ImageFrameCache. Caching the
+        image metadata is now moved to the ImageSource.
+        
+        * platform/graphics/GeneratedImage.h:
+        * platform/graphics/Image.h:
+        (WebCore::Image::orientationForCurrentFrame):
+        (WebCore::Image::singlePixelSolidColor):
+        Change currentFrameKnownToBeOpaque(), orientationForCurrentFrame() and
+        singlePixelSolidColor() to be const.
+        
+        * platform/graphics/ImageFrame.cpp:
+        (WebCore::ImageFrame::defaultFrame): Returns an empty ImageFrame to get the default ImageFrame metadata.
+        (WebCore::ImageFrame::fillMetadata): Deleted. Moved to ImageFrameCache.
+        (WebCore::ImageFrame::initialize): Deleted. Ditto.
+        
+        * platform/graphics/ImageFrame.h:
+        (WebCore::ImageFrame::setDuration): Change the type of the argument to float instead of unsigned.
+        (WebCore::ImageFrame::hasAlpha): Protect the unset m_hasAlpha by checking hasMetadata() first.
+
+        * platform/graphics/ImageFrameCache.cpp: Added.
+        (WebCore::ImageFrameCache::ImageFrameCache): Two constructors similar to what we do for ImageSource and BitmapImage.
+        (WebCore::ImageFrameCache::destroyDecodedData): Moved from BitmapImage.cpp.
+        (WebCore::ImageFrameCache::destroyDecodedDataIfNecessary): Ditto.
+        (WebCore::ImageFrameCache::destroyIncompleteDecodedData): Ditto.
+        (WebCore::ImageFrameCache::decodedSizeChanged): Ditto.
+        (WebCore::ImageFrameCache::decodedSizeIncremented): Ditto.
+        (WebCore::ImageFrameCache::decodedSizeDecremented): Ditto.
+        (WebCore::ImageFrameCache::decodedSizeReset): Ditto.
+        (WebCore::ImageFrameCache::didDecodeProperties): Ditto.
+        (WebCore::ImageFrameCache::growFrames): Grows the size of m_frames if necessary.
+        (WebCore::ImageFrameCache::setNativeImage): Initializes the ImageFrame metadata directly from the NativeImagePtr. 
+        (WebCore::ImageFrameCache::setFrameNativeImage): Initializes the ImageFrame image and the metadata.
+        (WebCore::ImageFrameCache::setFrameMetadata): Initializes the ImageFrame metadata from the ImageDecoder.
+        (WebCore::ImageFrameCache::frameAtIndex): Returns an ImageFrame given its index. Cache or recache the requested ImageFrame if necessary.
+        (WebCore::ImageFrameCache::clearMetadata): Invalidates the cached image metadata.
+        (WebCore::ImageFrameCache::metadata): A template function which returns an image metadata property.
+        (WebCore::ImageFrameCache::frameMetadataAtIndex): A template function which returns an ImageFrame metadata property.
+        (WebCore::ImageFrameCache::isSizeAvailable): An image metadata property.
+        (WebCore::ImageFrameCache::frameCount): Ditto.
+        (WebCore::ImageFrameCache::repetitionCount): Ditto.
+        (WebCore::ImageFrameCache::filenameExtension): Ditto.
+        (WebCore::ImageFrameCache::hotSpot): Ditto.
+        (WebCore::ImageFrameCache::size): An image metadata property but we get it from the first ImageFrame.
+        (WebCore::ImageFrameCache::sizeRespectingOrientation): Ditto.
+        (WebCore::ImageFrameCache::singlePixelSolidColor): Ditto.
+        (WebCore::ImageFrameCache::frameIsCompleteAtIndex): An ImageFrame metadata property.
+        (WebCore::ImageFrameCache::frameHasAlphaAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameHasImageAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameHasInvalidNativeImageAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameSubsamplingLevelAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameSizeAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameBytesAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameDurationAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameOrientationAtIndex): Ditto.
+        (WebCore::ImageFrameCache::frameImageAtIndex): Ditto.
+
+        * platform/graphics/ImageFrameCache.h: Added.
+        (WebCore::ImageFrameCache::setDecoder): Sets the current ImageDecoder which is owned by the ImageSource.
+        (WebCore::ImageFrameCache::decodedSize): Returns the size of the cached NativeImages.
+        (WebCore::ImageFrameCache::isDecoderAvailable): Returns whether an ImageDecoder is available.
+
+        * platform/graphics/ImageSource.cpp:
+        (WebCore::ImageSource::ImageSource): Initializes the ImageFrameCache based on the image decoding state.
+        (WebCore::ImageSource::clearFrameBufferCache): Replace initialized() with isDecoderAvailable().
+        (WebCore::ImageSource::clear): Clears the ImageDecoder of the ImageFrameCache.
+        (WebCore::ImageSource::destroyDecodedData): Moved from BitmapImage.cpp.
+        (WebCore::ImageSource::destroyDecodedDataIfNecessary): Ditto.
+        (WebCore::ImageSource::ensureDecoderAvailable): Creates an ImageDecoder if necessary and sets it in ImageFrameCache.
+        (WebCore::ImageSource::setData):
+        (WebCore::ImageSource::dataChanged): Moved from BitmapImage.cpp.
+        (WebCore::ImageSource::isAllDataReceived):
+        (WebCore::ImageSource::maximumSubsamplingLevel): Rename calculateMaximumSubsamplingLevel() to maximumSubsamplingLevel().
+        (WebCore::ImageSource::subsamplingLevelForScale):
+        (WebCore::ImageSource::createFrameImageAtIndex):
+        (WebCore::ImageSource::dump):
+        (WebCore::ImageSource::calculateMaximumSubsamplingLevel): Deleted. Renamed to maximumSubsamplingLevel().
+        (WebCore::ImageSource::updateMetadata): Deleted. Not needed. Caching the image metadata is the responsibility of ImageFrameCache. 
+        (WebCore::ImageSource::bytesDecodedToDetermineProperties): Deleted. Not needed.
+        (WebCore::ImageSource::isSizeAvailable): Deleted. Moved to ImageSource.h. 
+        (WebCore::ImageSource::size): Deleted. Ditto.
+        (WebCore::ImageSource::sizeRespectingOrientation): Deleted. Ditto.
+        (WebCore::ImageSource::frameCount): Deleted. Ditto.
+        (WebCore::ImageSource::repetitionCount): Deleted. Ditto.
+        (WebCore::ImageSource::filenameExtension): Deleted. Ditto.
+        (WebCore::ImageSource::hotSpot): Deleted. Ditto.
+        (WebCore::ImageSource::frameIsCompleteAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameHasAlphaAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameAllowSubsamplingAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameSizeAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameBytesAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameDurationAtIndex): Deleted. Ditto.
+        (WebCore::ImageSource::frameOrientationAtIndex): Deleted. Ditto.
+
+        * platform/graphics/ImageSource.h:
+        (WebCore::ImageSource::isDecoderAvailable): initialized() was renamed to isDecoderAvailable().
+        (WebCore::ImageSource::decodedSize): Send the query to ImageFrameCache.
+        (WebCore::ImageSource::isSizeAvailable): Ditto.
+        (WebCore::ImageSource::frameCount): Ditto.
+        (WebCore::ImageSource::repetitionCount): Ditto.
+        (WebCore::ImageSource::filenameExtension): Ditto.
+        (WebCore::ImageSource::hotSpot): Ditto.
+        (WebCore::ImageSource::size): Ditto.
+        (WebCore::ImageSource::sizeRespectingOrientation): Ditto.
+        (WebCore::ImageSource::singlePixelSolidColor): Ditto.
+        (WebCore::ImageSource::frameIsCompleteAtIndex): Ditto.
+        (WebCore::ImageSource::frameHasAlphaAtIndex): Ditto.
+        (WebCore::ImageSource::frameHasImageAtIndex): Ditto.
+        (WebCore::ImageSource::frameHasInvalidNativeImageAtIndex): Ditto.
+        (WebCore::ImageSource::frameSubsamplingLevelAtIndex): Ditto.
+        (WebCore::ImageSource::frameSizeAtIndex): Ditto.
+        (WebCore::ImageSource::frameBytesAtIndex): Ditto.
+        (WebCore::ImageSource::frameDurationAtIndex): Ditto.
+        (WebCore::ImageSource::frameOrientationAtIndex): Ditto.
+        (WebCore::ImageSource::frameImageAtIndex): Ditto.
+        (WebCore::ImageSource::decoder): Deleted. Not needed.
+        (WebCore::ImageSource::initialized): Deleted. Was renamed to isDecoderAvailable().
+        (WebCore::ImageSource::setNeedsUpdateMetadata): Deleted. Not needed.
+
+        * platform/graphics/cairo/GraphicsContext3DCairo.cpp:
+        (WebCore::GraphicsContext3D::ImageExtractor::extractImage): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/graphics/cg/GraphicsContext3DCG.cpp:
+        (WebCore::GraphicsContext3D::ImageExtractor::extractImage): Ditto.
+        
+        * platform/graphics/cg/ImageDecoderCG.cpp:
+        (WebCore::ImageDecoder::ImageDecoder): Make the constructor of ImageDecoder be the same for all ports. 
+        (WebCore::ImageDecoder::setData): Removed unused overloaded function.
+        (WebCore::ImageDecoder::size): Deleted.  Removed unused function.
+
+        * platform/graphics/cg/ImageDecoderCG.h:
+        (WebCore::ImageDecoder::create): Make the constructor of CG ImageDecoder be like the other ports.
+        (WebCore::ImageDecoder::isAllDataReceived): Make this property owned by ImageDecoder.
+
+        * platform/graphics/cg/PDFDocumentImage.h: Change currentFrameKnownToBeOpaque() to be const.
+
+        * platform/graphics/efl/GraphicsContext3DEfl.cpp:
+        (WebCore::GraphicsContext3D::ImageExtractor::extractImage): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        
+        * platform/graphics/mac/ImageMac.mm:
+        (WebCore::BitmapImage::invalidatePlatformData): m_frames is owned by ImageFrameCache. ImageFrameCache::frameCount() has to 
+        be equal to ImageFrame::m_frames.size().
+
+        * platform/image-decoders/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::create): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/image-decoders/ImageDecoder.h:
+        (WebCore::ImageDecoder::ImageDecoder): Ditto.
+        (WebCore::ImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
+        * platform/image-decoders/bmp/BMPImageDecoder.cpp:
+        (WebCore::BMPImageDecoder::BMPImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/image-decoders/bmp/BMPImageDecoder.h:
+        * platform/image-decoders/gif/GIFImageDecoder.cpp:
+        (WebCore::GIFImageDecoder::GIFImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        (WebCore::GIFImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
+        * platform/image-decoders/gif/GIFImageDecoder.h:
+        * platform/image-decoders/gif/GIFImageReader.cpp:
+        * platform/image-decoders/gif/GIFImageReader.h:
+        * platform/image-decoders/ico/ICOImageDecoder.cpp:
+        (WebCore::ICOImageDecoder::ICOImageDecoder): 
+        (WebCore::ICOImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
+        (WebCore::ICOImageDecoder::decode): Move resizing the m_frameBufferCache from ICOImageDecoder::frameCount() to ICOImageDecoder::decode().
+        (WebCore::ICOImageDecoder::decodeAtIndex): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/image-decoders/ico/ICOImageDecoder.h:
+        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
+        (WebCore::JPEGImageDecoder::JPEGImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/image-decoders/jpeg/JPEGImageDecoder.h:
+        * platform/image-decoders/png/PNGImageDecoder.cpp:
+        (WebCore::PNGImageDecoder::PNGImageDecoder): AlphaOption and GammaAndColorProfileOption are moved out of ImageSource.
+        * platform/image-decoders/png/PNGImageDecoder.h:
+        (WebCore::PNGImageDecoder::frameCount): Make frameCount const so it can be passed to the template function ImageFrameCache::metadata().
+        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
+        (WebCore::WEBPImageDecoder::WEBPImageDecoder):
+        * platform/image-decoders/webp/WEBPImageDecoder.h:
+
+        * svg/graphics/SVGImage.h: Make currentFrameKnownToBeOpaque() be const.
+        * svg/graphics/SVGImageForContainer.h: Ditto.
+
</ins><span class="cx"> 2016-09-27  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Correctly parse URLs with the first tab in the fragment
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -2271,6 +2271,8 @@
</span><span class="cx">                 555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
</span><span class="cx">                 5576A5641D88A70800CCC04C /* ImageFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5576A5621D88A70800CCC04C /* ImageFrame.cpp */; };
</span><span class="cx">                 5576A5651D88A70800CCC04C /* ImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 5576A5631D88A70800CCC04C /* ImageFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                5597F8261D91C3130066BC21 /* ImageFrameCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5597F8241D91C3130066BC21 /* ImageFrameCache.cpp */; };
+                5597F8271D91C3130066BC21 /* ImageFrameCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 5597F8251D91C3130066BC21 /* ImageFrameCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 55A336F71D8209F40022C4C7 /* NativeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F61D8209F40022C4C7 /* NativeImage.h */; };
</span><span class="cx">                 55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 5709E8CD1D413D47003244AC /* WebKitSubtleCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5709E8CA1D413CE3003244AC /* WebKitSubtleCrypto.cpp */; };
</span><span class="lines">@@ -9300,6 +9302,8 @@
</span><span class="cx">                 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5576A5621D88A70800CCC04C /* ImageFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrame.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 5576A5631D88A70800CCC04C /* ImageFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrame.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                5597F8241D91C3130066BC21 /* ImageFrameCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageFrameCache.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                5597F8251D91C3130066BC21 /* ImageFrameCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageFrameCache.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 55A336F61D8209F40022C4C7 /* NativeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeImage.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBackingStore.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 55D408F71A7C631800C78450 /* SVGImageClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageClients.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -20718,6 +20722,8 @@
</span><span class="cx">                                 22BD9F7D1353625C009BD102 /* ImageBufferData.h */,
</span><span class="cx">                                 5576A5621D88A70800CCC04C /* ImageFrame.cpp */,
</span><span class="cx">                                 5576A5631D88A70800CCC04C /* ImageFrame.h */,
</span><ins>+                                5597F8241D91C3130066BC21 /* ImageFrameCache.cpp */,
+                                5597F8251D91C3130066BC21 /* ImageFrameCache.h */,
</ins><span class="cx">                                 BC7F44A70B9E324E00A9D081 /* ImageObserver.h */,
</span><span class="cx">                                 A8748D7412CC3F89001FBA41 /* ImageOrientation.cpp */,
</span><span class="cx">                                 A8748D6612CC3763001FBA41 /* ImageOrientation.h */,
</span><span class="lines">@@ -24495,6 +24501,7 @@
</span><span class="cx">                                 0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */,
</span><span class="cx">                                 B275356B0B053814002CE64F /* FloatRect.h in Headers */,
</span><span class="cx">                                 6E0E569C183BFFE600E0E8D5 /* FloatRoundedRect.h in Headers */,
</span><ins>+                                5597F8271D91C3130066BC21 /* ImageFrameCache.h in Headers */,
</ins><span class="cx">                                 B275356D0B053814002CE64F /* FloatSize.h in Headers */,
</span><span class="cx">                                 58CD35CB18EB4C3900B9F3AC /* FloatSizeHash.h in Headers */,
</span><span class="cx">                                 D72F6D7A153159A3001EE44E /* FlowThreadController.h in Headers */,
</span><span class="lines">@@ -27617,6 +27624,7 @@
</span><span class="cx">                                 514C764D0CE9234E007EF3CD /* AuthenticationMac.mm in Sources */,
</span><span class="cx">                                 E461D65D1BB0C7F000CB5645 /* AuthorStyleSheets.cpp in Sources */,
</span><span class="cx">                                 A5F6E16B132ED46E008EDAE3 /* Autocapitalize.cpp in Sources */,
</span><ins>+                                5597F8261D91C3130066BC21 /* ImageFrameCache.cpp in Sources */,
</ins><span class="cx">                                 7C1843FD1C8B7283002EB973 /* Autofill.cpp in Sources */,
</span><span class="cx">                                 7C1E97271A9F9834007BF0FB /* AutoFillButtonElement.cpp in Sources */,
</span><span class="cx">                                 45830D4D1679B4F800ACF8C3 /* AutoscrollController.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsBitmapImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -21,7 +21,7 @@
</span><span class="cx">  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
</span><span class="cx">  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
</span><span class="cx">  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
</span><del>- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</del><ins>+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="lines">@@ -48,32 +48,14 @@
</span><span class="cx"> 
</span><span class="cx"> BitmapImage::BitmapImage(ImageObserver* observer)
</span><span class="cx">     : Image(observer)
</span><del>-    , m_animationFinished(false)
-    , m_allDataReceived(false)
-    , m_haveSize(false)
-    , m_sizeAvailable(false)
-    , m_haveFrameCount(false)
-    , m_animationFinishedWhenCatchingUp(false)
</del><ins>+    , m_source(this)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> BitmapImage::BitmapImage(NativeImagePtr&amp;&amp; image, ImageObserver* observer)
</span><span class="cx">     : Image(observer)
</span><del>-    , m_source(image)
-    , m_frameCount(1)
-    , m_animationFinished(true)
-    , m_allDataReceived(true)
-    , m_haveSize(true)
-    , m_sizeAvailable(true)
-    , m_haveFrameCount(true)
-    , m_animationFinishedWhenCatchingUp(false)
</del><ins>+    , m_source(WTFMove(image))
</ins><span class="cx"> {
</span><del>-    m_frames.grow(1);
-    m_frames[0].initialize(WTFMove(image));
-
-    m_size = m_frames[0].size();
-    m_sizeRespectingOrientation = m_size;
-    m_decodedSize = m_size.area() * 4;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> BitmapImage::~BitmapImage()
</span><span class="lines">@@ -82,294 +64,32 @@
</span><span class="cx">     stopAnimation();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool BitmapImage::haveFrameImageAtIndex(size_t index)
-{
-    if (index &gt;= frameCount())
-        return false;
-
-    if (index &gt;= m_frames.size())
-        return false;
-
-    return m_frames[index].hasNativeImage();
-}
-
</del><span class="cx"> void BitmapImage::destroyDecodedData(bool destroyAll)
</span><span class="cx"> {
</span><del>-    unsigned frameBytesCleared = 0;
-    const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame;
-
-    // Because we can advance frames without always needing to decode the actual
-    // bitmap data, |m_currentFrame| may be larger than m_frames.size();
-    // make sure not to walk off the end of the container in this case.
-    for (size_t i = 0; i &lt;  std::min(clearBeforeFrame, m_frames.size()); ++i) {
-        // The underlying frame isn't actually changing (we're just trying to
-        // save the memory for the framebuffer data), so we don't need to clear
-        // the metadata.
-        frameBytesCleared += m_frames[i].clearImage();
-    }
-
-    m_source.clear(destroyAll, clearBeforeFrame, data(), m_allDataReceived);
-    destroyMetadataAndNotify(frameBytesCleared, ClearedSource::Yes);
</del><ins>+    m_source.destroyDecodedData(data(), destroyAll, m_currentFrame);
+    invalidatePlatformData();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
</span><span class="cx"> {
</span><del>-    // Animated images over a certain size are considered large enough that we'll only hang on
-    // to one frame at a time.
-#if PLATFORM(IOS)
-    const unsigned largeAnimationCutoff = 2097152;
-#else
-    const unsigned largeAnimationCutoff = 5242880;
-#endif
-
-    // If we have decoded frames but there is no encoded data, we shouldn't destroy
-    // the decoded image since we won't be able to reconstruct it later.
-    if (!data() &amp;&amp; m_frames.size())
-        return;
-
-    unsigned allFrameBytes = 0;
-    for (auto&amp; frame : m_frames)
-        allFrameBytes += frame.frameBytes();
-
-    if (allFrameBytes &gt; largeAnimationCutoff) {
-        LOG(Images, &quot;BitmapImage %p destroyDecodedDataIfNecessary destroyingData: allFrameBytes=%u cutoff=%u&quot;, this, allFrameBytes, largeAnimationCutoff);
-        destroyDecodedData(destroyAll);
-    }
</del><ins>+    m_source.destroyDecodedDataIfNecessary(data(), destroyAll, m_currentFrame);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared, ClearedSource clearedSource)
-{
-    m_solidColor = Nullopt;
-    invalidatePlatformData();
-
-    ASSERT(m_decodedSize &gt;= frameBytesCleared);
-    m_decodedSize -= frameBytesCleared;
-
-    // Clearing the ImageSource destroys the extra decoded data used for determining image properties.
-    if (clearedSource == ClearedSource::Yes) {
-        frameBytesCleared += m_decodedPropertiesSize;
-        m_decodedPropertiesSize = 0;
-    }
-
-    if (frameBytesCleared &amp;&amp; imageObserver())
-        imageObserver()-&gt;decodedSizeChanged(this, -safeCast&lt;int&gt;(frameBytesCleared));
-}
-
-void BitmapImage::cacheFrame(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching)
-{
-    size_t numFrames = frameCount();
-    ASSERT(m_decodedSize == 0 || numFrames &gt; 1);
-    
-    if (m_frames.size() &lt; numFrames)
-        m_frames.grow(numFrames);
-
-    if (caching == ImageFrame::Caching::MetadataAndImage) {
-        NativeImagePtr image = m_source.createFrameImageAtIndex(index, subsamplingLevel);
-        m_frames[index].initialize(WTFMove(image), *m_source.decoder(), index, subsamplingLevel, repetitionCount(false));
-    } else
-        m_frames[index].initialize(nullptr, *m_source.decoder(), index, subsamplingLevel, repetitionCount(false));
-
-    LOG(Images, &quot;BitmapImage %p cacheFrame %lu (%s%u bytes, complete %d)&quot;, this, index, caching == ImageFrame::Caching::Metadata ? &quot;metadata only, &quot; : &quot;&quot;, m_frames[index].frameBytes(), m_frames[index].isComplete());
-
-    if (m_frames[index].hasNativeImage()) {
-        int deltaBytes = safeCast&lt;int&gt;(m_frames[index].frameBytes());
-        m_decodedSize += deltaBytes;
-        // The fully-decoded frame will subsume the partially decoded data used
-        // to determine image properties.
-        deltaBytes -= m_decodedPropertiesSize;
-        m_decodedPropertiesSize = 0;
-        if (imageObserver())
-            imageObserver()-&gt;decodedSizeChanged(this, deltaBytes);
-    }
-}
-
-void BitmapImage::didDecodeProperties() const
-{
-    if (m_decodedSize)
-        return;
-
-    size_t updatedSize = m_source.bytesDecodedToDetermineProperties();
-    if (m_decodedPropertiesSize == updatedSize)
-        return;
-
-    int deltaBytes = updatedSize - m_decodedPropertiesSize;
-#if !ASSERT_DISABLED
-    bool overflow = updatedSize &gt; m_decodedPropertiesSize &amp;&amp; deltaBytes &lt; 0;
-    bool underflow = updatedSize &lt; m_decodedPropertiesSize &amp;&amp; deltaBytes &gt; 0;
-    ASSERT(!overflow &amp;&amp; !underflow);
-#endif
-    m_decodedPropertiesSize = updatedSize;
-    if (imageObserver())
-        imageObserver()-&gt;decodedSizeChanged(this, deltaBytes);
-}
-
-void BitmapImage::updateSize() const
-{
-    if (!m_sizeAvailable || m_haveSize)
-        return;
-
-    m_size = m_source.size();
-    m_sizeRespectingOrientation = m_source.sizeRespectingOrientation();
-
-    m_haveSize = true;
-    didDecodeProperties();
-}
-
-FloatSize BitmapImage::size() const
-{
-    updateSize();
-    return m_size;
-}
-
-IntSize BitmapImage::sizeRespectingOrientation() const
-{
-    updateSize();
-    return m_sizeRespectingOrientation;
-}
-
-Optional&lt;IntPoint&gt; BitmapImage::hotSpot() const
-{
-    auto result = m_source.hotSpot();
-    didDecodeProperties();
-    return result;
-}
-
</del><span class="cx"> bool BitmapImage::dataChanged(bool allDataReceived)
</span><span class="cx"> {
</span><del>-    // Because we're modifying the current frame, clear its (now possibly
-    // inaccurate) metadata as well.
-#if !PLATFORM(IOS)
-    // Clear all partially-decoded frames. For most image formats, there is only
-    // one frame, but at least GIF and ICO can have more. With GIFs, the frames
-    // come in order and we ask to decode them in order, waiting to request a
-    // subsequent frame until the prior one is complete. Given that we clear
-    // incomplete frames here, this means there is at most one incomplete frame
-    // (even if we use destroyDecodedData() -- since it doesn't reset the
-    // metadata), and it is after all the complete frames.
-    //
-    // With ICOs, on the other hand, we may ask for arbitrary frames at
-    // different times (e.g. because we're displaying a higher-resolution image
-    // in the content area and using a lower-resolution one for the favicon),
-    // and the frames aren't even guaranteed to appear in the file in the same
-    // order as in the directory, so an arbitrary number of the frames might be
-    // incomplete (if we ask for frames for which we've not yet reached the
-    // start of the frame data), and any or none of them might be the particular
-    // frame affected by appending new data here. Thus we have to clear all the
-    // incomplete frames to be safe.
-    unsigned frameBytesCleared = 0;
-    for (auto&amp; frame : m_frames) {
-        // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to
-        // decode any uncached (i.e. never-decoded or
-        // cleared-on-a-previous-pass) frames!
-        if (frame.hasMetadata() &amp;&amp; !frame.isComplete())
-            frameBytesCleared += frame.clear();
-    }
-    destroyMetadataAndNotify(frameBytesCleared, ClearedSource::No);
-#else
-    // FIXME: why is this different for iOS?
-    int deltaBytes = 0;
-    if (!m_frames.isEmpty()) {
-        if (int bytes = m_frames[m_frames.size() - 1].clear()) {
-            deltaBytes += bytes;
-            deltaBytes += m_decodedPropertiesSize;
-            m_decodedPropertiesSize = 0;
-        }
-    }
-    destroyMetadataAndNotify(deltaBytes, ClearedSource::No);
-#endif
-    
-    // Feed all the data we've seen so far to the image decoder.
-    m_allDataReceived = allDataReceived;
-#if PLATFORM(IOS)
-    // FIXME: We should expose a setting to enable/disable progressive loading and make this
-    // code conditional on it. Then we can remove the PLATFORM(IOS)-guard.
-    static const double chunkLoadIntervals[] = {0, 1, 3, 6, 15};
-    double interval = chunkLoadIntervals[std::min(m_progressiveLoadChunkCount, static_cast&lt;uint16_t&gt;(4))];
-
-    bool needsUpdate = false;
-    if (currentTime() - m_progressiveLoadChunkTime &gt; interval) { // The first time through, the chunk time will be 0 and the image will get an update.
-        needsUpdate = true;
-        m_progressiveLoadChunkTime = currentTime();
-        ASSERT(m_progressiveLoadChunkCount &lt;= std::numeric_limits&lt;uint16_t&gt;::max());
-        ++m_progressiveLoadChunkCount;
-    }
-    if (needsUpdate || allDataReceived)
-        m_source.setData(data(), allDataReceived);
-#else
-    m_source.setData(data(), allDataReceived);
-#endif
-
-    m_haveFrameCount = false;
-    m_source.setNeedsUpdateMetadata();
-    return isSizeAvailable();
</del><ins>+    return m_source.dataChanged(data(), allDataReceived);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t BitmapImage::frameCount()
</del><ins>+NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</ins><span class="cx"> {
</span><del>-    if (!m_haveFrameCount) {
-        m_frameCount = m_source.frameCount();
-        // If decoder is not initialized yet, m_source.frameCount() returns 0.
-        if (m_frameCount) {
-            didDecodeProperties();
-            m_haveFrameCount = true;
-        }
</del><ins>+    if (frameHasInvalidNativeImageAtIndex(index, subsamplingLevel)) {
+        LOG(Images, &quot;BitmapImage %p frameImageAtIndex - subsamplingLevel was %d, resampling&quot;, this, static_cast&lt;int&gt;(frameSubsamplingLevelAtIndex(index)));
+        invalidatePlatformData();
</ins><span class="cx">     }
</span><del>-    return m_frameCount;
-}
</del><span class="cx"> 
</span><del>-bool BitmapImage::isSizeAvailable()
-{
-    if (m_sizeAvailable)
-        return true;
-
-    m_sizeAvailable = m_source.isSizeAvailable();
-    didDecodeProperties();
-
-    return m_sizeAvailable;
</del><ins>+    return m_source.frameImageAtIndex(index, subsamplingLevel);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool BitmapImage::ensureFrameAtIndexIsCached(size_t index, ImageFrame::Caching caching)
-{
-    if (index &gt;= frameCount())
-        return false;
-
-    if (index &gt;= m_frames.size()
-        || (caching == ImageFrame::Caching::MetadataAndImage &amp;&amp; !m_frames[index].hasNativeImage())
-        || (caching == ImageFrame::Caching::Metadata &amp;&amp; !m_frames[index].hasMetadata()))
-        cacheFrame(index, SubsamplingLevel::Default, caching);
-
-    return true;
-}
-
-NativeImagePtr BitmapImage::frameImageAtIndex(size_t index, float presentationScaleHint)
-{
-    if (index &gt;= frameCount())
-        return nullptr;
-
-    SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(presentationScaleHint);
-    
-    LOG(Images, &quot;BitmapImage %p frameImageAtIndex - subsamplingLevel %d at scale %.4f&quot;, this, static_cast&lt;int&gt;(subsamplingLevel), presentationScaleHint);
-
-    // We may have cached a frame with a higher subsampling level, in which case we need to
-    // re-decode with a lower level.
-    if (index &lt; m_frames.size() &amp;&amp; m_frames[index].hasInvalidNativeImage(subsamplingLevel)) {
-        LOG(Images, &quot;  subsamplingLevel was %d, resampling&quot;, static_cast&lt;int&gt;(m_frames[index].subsamplingLevel()));
-
-        // If the image is already cached, but at too small a size, re-decode a larger version.
-        int sizeChange = -m_frames[index].clear();
-        invalidatePlatformData();
-        m_decodedSize += sizeChange;
-        if (imageObserver())
-            imageObserver()-&gt;decodedSizeChanged(this, sizeChange);
-    }
-
-    // If we haven't fetched a frame yet, do so.
-    if (index &gt;= m_frames.size() || !m_frames[index].hasNativeImage())
-        cacheFrame(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
-
-    return m_frames[index].nativeImage();
-}
-    
</del><span class="cx"> NativeImagePtr BitmapImage::nativeImage()
</span><span class="cx"> {
</span><span class="cx">     return frameImageAtIndex(0);
</span><span class="lines">@@ -379,105 +99,36 @@
</span><span class="cx"> {
</span><span class="cx">     return frameImageAtIndex(m_currentFrame);
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> #if USE(CG)
</span><span class="cx"> NativeImagePtr BitmapImage::nativeImageOfSize(const IntSize&amp; size)
</span><span class="cx"> {
</span><span class="cx">     size_t count = frameCount();
</span><del>-    
</del><ins>+
</ins><span class="cx">     for (size_t i = 0; i &lt; count; ++i) {
</span><span class="cx">         auto image = frameImageAtIndex(i);
</span><span class="cx">         if (image &amp;&amp; nativeImageSize(image) == size)
</span><span class="cx">             return image;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Fallback to the first frame image if we can't find the right size
</span><span class="cx">     return frameImageAtIndex(0);
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> Vector&lt;NativeImagePtr&gt; BitmapImage::framesNativeImages()
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;NativeImagePtr&gt; images;
</span><span class="cx">     size_t count = frameCount();
</span><del>-    
</del><ins>+
</ins><span class="cx">     for (size_t i = 0; i &lt; count; ++i) {
</span><span class="cx">         if (auto image = frameImageAtIndex(i))
</span><span class="cx">             images.append(image);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     return images;
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-bool BitmapImage::frameIsCompleteAtIndex(size_t index)
-{
-    if (!ensureFrameAtIndexIsCached(index, ImageFrame::Caching::Metadata))
-        return false;
-
-    return m_frames[index].isComplete();
-}
-
-float BitmapImage::frameDurationAtIndex(size_t index)
-{
-    if (!ensureFrameAtIndexIsCached(index, ImageFrame::Caching::Metadata))
-        return 0;
-
-    return m_frames[index].duration();
-}
-
-bool BitmapImage::frameHasAlphaAtIndex(size_t index)
-{
-    if (!ensureFrameAtIndexIsCached(index, ImageFrame::Caching::Metadata))
-        return true;
-
-    if (m_frames[index].hasMetadata())
-        return m_frames[index].hasAlpha();
-
-    return m_source.frameHasAlphaAtIndex(index);
-}
-
-bool BitmapImage::currentFrameKnownToBeOpaque()
-{
-    return !frameHasAlphaAtIndex(currentFrame());
-}
-
-ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index)
-{
-    if (!ensureFrameAtIndexIsCached(index, ImageFrame::Caching::Metadata))
-        return ImageOrientation();
-
-    if (m_frames[index].hasMetadata())
-        return m_frames[index].orientation();
-
-    return m_source.frameOrientationAtIndex(index);
-}
-
-Color BitmapImage::singlePixelSolidColor()
-{
-    // If the image size is not available yet or if the image will be animating don't use the solid color optimization.
-    if (frameCount() != 1)
-        return Color();
-
-    if (m_solidColor)
-        return m_solidColor.value();
-
-    // If the frame image is not loaded, first use the decoder to get the size of the image.
-    if (!haveFrameImageAtIndex(0) &amp;&amp; m_source.frameSizeAtIndex(0) != IntSize(1, 1)) {
-        m_solidColor = Color();
-        return m_solidColor.value();
-    }
-
-    // Cache the frame image. The size will be calculated from the NativeImagePtr.
-    if (!ensureFrameAtIndexIsCached(0))
-        return Color();
-
-    ASSERT(m_frames.size());
-    m_solidColor = nativeImageSinglePixelSolidColor(m_frames[0].nativeImage());
-    
-    ASSERT(m_solidColor);
-    return m_solidColor.value();
-}
-
</del><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> bool BitmapImage::notSolidColor()
</span><span class="cx"> {
</span><span class="lines">@@ -485,20 +136,6 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-RepetitionCount BitmapImage::repetitionCount(bool imageKnownToBeComplete)
-{
-    if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Uncertain) &amp;&amp; imageKnownToBeComplete)) {
-        // Snag the repetition count. If |imageKnownToBeComplete| is false, the
-        // repetition count may not be accurate yet for GIFs; in this case the
-        // decoder will default to RepetitionCountOnce, and we'll try and read
-        // the count again once the whole image is decoded.
-        m_repetitionCount = m_source.repetitionCount();
-        didDecodeProperties();
-        m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount == RepetitionCountNone) ? Certain : Uncertain;
-    }
-    return m_repetitionCount;
-}
-
</del><span class="cx"> void BitmapImage::draw(GraphicsContext&amp; context, const FloatRect&amp; destRect, const FloatRect&amp; srcRect, CompositeOperator op, BlendMode mode, ImageOrientationDescription description)
</span><span class="cx"> {
</span><span class="cx">     if (destRect.isEmpty() || srcRect.isEmpty())
</span><span class="lines">@@ -516,7 +153,11 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    auto image = frameImageAtIndex(m_currentFrame, subsamplingScale(context, destRect, srcRect));
</del><ins>+    float scale = subsamplingScale(context, destRect, srcRect);
+    SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(scale);
+    LOG(Images, &quot;BitmapImage %p draw - subsamplingLevel %d at scale %.4f&quot;, this, subsamplingLevel, scale);
+
+    auto image = frameImageAtIndex(m_currentFrame, subsamplingLevel);
</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">@@ -524,12 +165,12 @@
</span><span class="cx">     if (description.respectImageOrientation() == RespectImageOrientation)
</span><span class="cx">         orientation = frameOrientationAtIndex(m_currentFrame);
</span><span class="cx"> 
</span><del>-    drawNativeImage(image, context, destRect, srcRect, m_size, op, mode, orientation);
</del><ins>+    drawNativeImage(image, context, destRect, srcRect, IntSize(size()), op, mode, orientation);
</ins><span class="cx"> 
</span><span class="cx">     if (imageObserver())
</span><span class="cx">         imageObserver()-&gt;didDraw(this);
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> void BitmapImage::drawPattern(GraphicsContext&amp; ctxt, const FloatRect&amp; tileRect, const AffineTransform&amp; transform, const FloatPoint&amp; phase, const FloatSize&amp; spacing, CompositeOperator op, const FloatRect&amp; destRect, BlendMode blendMode)
</span><span class="cx"> {
</span><span class="cx">     if (tileRect.isEmpty())
</span><span class="lines">@@ -559,7 +200,7 @@
</span><span class="cx">         if (!m_cachedImage)
</span><span class="cx">             return;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     ctxt.setDrawLuminanceMask(false);
</span><span class="cx">     m_cachedImage-&gt;drawPattern(ctxt, tileRect, transform, phase, spacing, op, destRect, blendMode);
</span><span class="cx"> }
</span><span class="lines">@@ -566,7 +207,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool BitmapImage::shouldAnimate()
</span><span class="cx"> {
</span><del>-    return repetitionCount(false) &amp;&amp; !m_animationFinished &amp;&amp; imageObserver();
</del><ins>+    return repetitionCount() &amp;&amp; !m_animationFinished &amp;&amp; imageObserver();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BitmapImage::canAnimate()
</span><span class="lines">@@ -598,7 +239,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Don't advance the animation to an incomplete frame.
</span><span class="cx">     size_t nextFrame = (m_currentFrame + 1) % frameCount();
</span><del>-    if (!m_allDataReceived &amp;&amp; !frameIsCompleteAtIndex(nextFrame))
</del><ins>+    if (!m_source.isAllDataReceived() &amp;&amp; !frameIsCompleteAtIndex(nextFrame))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // Don't advance past the last frame if we haven't decoded the whole image
</span><span class="lines">@@ -605,7 +246,7 @@
</span><span class="cx">     // yet and our repetition count is potentially unset. The repetition count
</span><span class="cx">     // in a GIF can potentially come after all the rest of the image data, so
</span><span class="cx">     // wait on it.
</span><del>-    if (!m_allDataReceived &amp;&amp; repetitionCount(false) == RepetitionCountOnce &amp;&amp; m_currentFrame &gt;= (frameCount() - 1))
</del><ins>+    if (!m_source.isAllDataReceived() &amp;&amp; repetitionCount() == RepetitionCountOnce &amp;&amp; m_currentFrame &gt;= (frameCount() - 1))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // Determine time for next frame to start. By ignoring paint and timer lag
</span><span class="lines">@@ -656,7 +297,7 @@
</span><span class="cx"> #if !LOG_DISABLED
</span><span class="cx">     size_t startCatchupFrameIndex = nextFrame;
</span><span class="cx"> #endif
</span><del>-    
</del><ins>+
</ins><span class="cx">     for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsCompleteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) {
</span><span class="cx">         // Should we skip the next frame?
</span><span class="cx">         double frameAfterNextStartTime = m_desiredFrameStartTime + frameDurationAtIndex(nextFrame);
</span><span class="lines">@@ -700,7 +341,7 @@
</span><span class="cx">         m_animationFinishedWhenCatchingUp = false;
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     ++m_currentFrame;
</span><span class="cx">     bool advancedAnimation = true;
</span><span class="cx">     bool destroyAll = false;
</span><span class="lines">@@ -710,7 +351,7 @@
</span><span class="cx">         // Get the repetition count again. If we weren't able to get a
</span><span class="cx">         // repetition count before, we should have decoded the whole image by
</span><span class="cx">         // now, so it should now be available.
</span><del>-        if (repetitionCount(true) != RepetitionCountInfinite &amp;&amp; m_repetitionsComplete &gt; m_repetitionCount) {
</del><ins>+        if (repetitionCount() != RepetitionCountInfinite &amp;&amp; m_repetitionsComplete &gt; repetitionCount()) {
</ins><span class="cx">             m_animationFinished = true;
</span><span class="cx">             m_desiredFrameStartTime = 0;
</span><span class="cx">             --m_currentFrame;
</span><span class="lines">@@ -752,18 +393,10 @@
</span><span class="cx"> void BitmapImage::dump(TextStream&amp; ts) const
</span><span class="cx"> {
</span><span class="cx">     Image::dump(ts);
</span><del>-
-    ts.dumpProperty(&quot;type&quot;, m_source.filenameExtension());
-
-    if (isAnimated()) {
-        ts.dumpProperty(&quot;frame-count&quot;, m_frameCount);
-        ts.dumpProperty(&quot;repetitions&quot;, m_repetitionCount);
</del><ins>+    
+    if (isAnimated())
</ins><span class="cx">         ts.dumpProperty(&quot;current-frame&quot;, m_currentFrame);
</span><del>-    }
</del><span class="cx">     
</span><del>-    if (m_solidColor)
-        ts.dumpProperty(&quot;solid-color&quot;, m_solidColor.value());
-    
</del><span class="cx">     m_source.dump(ts);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsBitmapImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/BitmapImage.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -25,8 +25,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef BitmapImage_h
-#define BitmapImage_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;Image.h&quot;
</span><span class="cx"> #include &quot;Color.h&quot;
</span><span class="lines">@@ -67,28 +66,35 @@
</span><span class="cx">     
</span><span class="cx">     bool hasSingleSecurityOrigin() const override { return true; }
</span><span class="cx"> 
</span><ins>+    bool dataChanged(bool allDataReceived) override;
+    unsigned decodedSize() const { return m_source.decodedSize(); }
+
+    bool isSizeAvailable() const { return m_source.isSizeAvailable(); }
+    size_t frameCount() const { return m_source.frameCount(); }
+    RepetitionCount repetitionCount() const { return m_source.repetitionCount(); }
+    String filenameExtension() const override { return m_source.filenameExtension(); }
+    Optional&lt;IntPoint&gt; hotSpot() const override { return m_source.hotSpot(); }
+
</ins><span class="cx">     // FloatSize due to override.
</span><del>-    FloatSize size() const override;
-    IntSize sizeRespectingOrientation() const;
</del><ins>+    FloatSize size() const override { return m_source.size(); }
+    IntSize sizeRespectingOrientation() const { return m_source.sizeRespectingOrientation(); }
+    Color singlePixelSolidColor() const override { return m_source.singlePixelSolidColor(); }
</ins><span class="cx"> 
</span><del>-    Optional&lt;IntPoint&gt; hotSpot() const override;
</del><ins>+    void setAllowSubsampling(bool allowSubsampling) { m_source.setAllowSubsampling(allowSubsampling); }
</ins><span class="cx"> 
</span><del>-    unsigned decodedSize() const { return m_decodedSize; }
</del><ins>+    bool frameIsCompleteAtIndex(size_t index) const { return m_source.frameIsCompleteAtIndex(index); }
+    bool frameHasAlphaAtIndex(size_t index) const { return m_source.frameHasAlphaAtIndex(index); }
+    bool frameHasInvalidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const { return m_source.frameHasInvalidNativeImageAtIndex(index, subsamplingLevel); }
+    SubsamplingLevel frameSubsamplingLevelAtIndex(size_t index) const { return m_source.frameSubsamplingLevelAtIndex(index); }
</ins><span class="cx"> 
</span><del>-    bool dataChanged(bool allDataReceived) override;
-    String filenameExtension() const override { return m_source.filenameExtension(); }
</del><ins>+    float frameDurationAtIndex(size_t index) const { return m_source.frameDurationAtIndex(index); }
+    ImageOrientation frameOrientationAtIndex(size_t index) const { return m_source.frameOrientationAtIndex(index); }
</ins><span class="cx"> 
</span><del>-    // It may look unusual that there is no start animation call as public API. This is because
-    // we start and stop animating lazily. Animation begins whenever someone draws the image. It will
-    // automatically pause once all observers no longer want to render the image anywhere.
-    void stopAnimation() override;
-    void resetAnimation() override;
</del><ins>+    size_t currentFrame() const { return m_currentFrame; }
+    bool currentFrameKnownToBeOpaque() const override { return !frameHasAlphaAtIndex(currentFrame()); }
+    ImageOrientation orientationForCurrentFrame() const override { return frameOrientationAtIndex(currentFrame()); }
</ins><span class="cx"> 
</span><del>-    void drawPattern(GraphicsContext&amp;, const FloatRect&amp; srcRect, const AffineTransform&amp; patternTransform,
-        const FloatPoint&amp; phase, const FloatSize&amp; spacing, CompositeOperator, const FloatRect&amp; destRect, BlendMode = BlendModeNormal) override;
-
</del><span class="cx">     // Accessors for native image formats.
</span><del>-
</del><span class="cx"> #if USE(APPKIT)
</span><span class="cx">     NSImage* getNSImage() override;
</span><span class="cx"> #endif
</span><span class="lines">@@ -116,60 +122,13 @@
</span><span class="cx">     NativeImagePtr nativeImageOfSize(const IntSize&amp;) override;
</span><span class="cx">     Vector&lt;NativeImagePtr&gt; framesNativeImages() override;
</span><span class="cx"> #endif
</span><del>-    ImageOrientation orientationForCurrentFrame() override { return frameOrientationAtIndex(currentFrame()); }
</del><span class="cx"> 
</span><del>-    bool currentFrameKnownToBeOpaque() override;
-
-    bool isAnimated() const override { return m_frameCount &gt; 1; }
-    
-    bool canAnimate();
-
-    void setAllowSubsampling(bool allowSubsampling) { m_source.setAllowSubsampling(allowSubsampling); }
-
-    size_t currentFrame() const { return m_currentFrame; }
-    
-private:
-    bool isBitmapImage() const override { return true; }
-
-    void updateSize() const;
-
</del><span class="cx"> protected:
</span><del>-    enum RepetitionCountStatus {
-      Unknown,    // We haven't checked the source's repetition count.
-      Uncertain,  // We have a repetition count, but it might be wrong (some GIFs have a count after the image data, and will report &quot;loop once&quot; until all data has been decoded).
-      Certain     // The repetition count is known to be correct.
-    };
-
</del><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>-#if PLATFORM(WIN)
-    void drawFrameMatchingSourceSize(GraphicsContext&amp;, const FloatRect&amp; dstRect, const IntSize&amp; srcSize, CompositeOperator) override;
-#endif
-    void draw(GraphicsContext&amp;, const FloatRect&amp; dstRect, const FloatRect&amp; srcRect, CompositeOperator, BlendMode, ImageOrientationDescription) override;
</del><ins>+    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
</ins><span class="cx"> 
</span><del>-#if USE(WINGDI)
-    virtual void drawPattern(GraphicsContext&amp;, const FloatRect&amp; srcRect, const AffineTransform&amp; patternTransform,
-        const FloatPoint&amp; phase, const FloatSize&amp; spacing, CompositeOperator, const FloatRect&amp; destRect);
-#endif
-
-    size_t frameCount();
-
-    NativeImagePtr frameImageAtIndex(size_t, float presentationScaleHint = 1);
-
-    bool haveFrameImageAtIndex(size_t);
-
-    bool frameIsCompleteAtIndex(size_t);
-    float frameDurationAtIndex(size_t);
-    bool frameHasAlphaAtIndex(size_t);
-    ImageOrientation frameOrientationAtIndex(size_t);
-
-    // Decodes and caches a frame. Never accessed except internally.
-    void cacheFrame(size_t index, SubsamplingLevel, ImageFrame::Caching = ImageFrame::Caching::MetadataAndImage);
-
-    // Called before accessing m_frames[index] for info without decoding. Returns false on index out of bounds.
-    bool ensureFrameAtIndexIsCached(size_t index, ImageFrame::Caching = ImageFrame::Caching::MetadataAndImage);
-
</del><span class="cx">     // Called to invalidate cached data. When |destroyAll| is true, we wipe out
</span><span class="cx">     // the entire frame buffer cache and tell the image source to destroy
</span><span class="cx">     // everything; this is used when e.g. we want to free some room in the image
</span><span class="lines">@@ -180,26 +139,18 @@
</span><span class="cx"> 
</span><span class="cx">     // If the image is large enough, calls destroyDecodedData() and passes
</span><span class="cx">     // |destroyAll| along.
</span><del>-    void destroyDecodedDataIfNecessary(bool destroyAll);
</del><ins>+    void destroyDecodedDataIfNecessary(bool destroyAll = true);
</ins><span class="cx"> 
</span><del>-    // Generally called by destroyDecodedData(), destroys whole-image metadata
-    // and notifies observers that the memory footprint has (hopefully)
-    // decreased by |frameBytesCleared|.
-    enum class ClearedSource { No, Yes };
-    void destroyMetadataAndNotify(unsigned frameBytesCleared, ClearedSource);
</del><ins>+    void draw(GraphicsContext&amp;, const FloatRect&amp; dstRect, const FloatRect&amp; srcRect, CompositeOperator, BlendMode, ImageOrientationDescription) override;
+    void drawPattern(GraphicsContext&amp;, const FloatRect&amp; srcRect, const AffineTransform&amp; patternTransform, const FloatPoint&amp; phase, const FloatSize&amp; spacing, CompositeOperator, const FloatRect&amp; destRect, BlendMode = BlendModeNormal) override;
+#if PLATFORM(WIN)
+    void drawFrameMatchingSourceSize(GraphicsContext&amp;, const FloatRect&amp; dstRect, const IntSize&amp; srcSize, CompositeOperator) override;
+#endif
</ins><span class="cx"> 
</span><del>-    // Whether or not size is available yet.
-    bool isSizeAvailable();
-
-    // Called after asking the source for any information that may require
-    // decoding part of the image (e.g., the image size). We need to report
-    // the partially decoded data to our observer so it has an accurate
-    // account of the BitmapImage's memory usage.
-    void didDecodeProperties() const;
-
</del><span class="cx">     // Animation.
</span><del>-    RepetitionCount repetitionCount(bool imageKnownToBeComplete); // |imageKnownToBeComplete| should be set if the caller knows the entire image has been decoded.
</del><ins>+    bool isAnimated() const override { return m_source.frameCount() &gt; 1; }
</ins><span class="cx">     bool shouldAnimate();
</span><ins>+    bool canAnimate();
</ins><span class="cx">     void startAnimation(CatchUpAnimation = CatchUp) override;
</span><span class="cx">     void advanceAnimation();
</span><span class="cx"> 
</span><span class="lines">@@ -211,11 +162,15 @@
</span><span class="cx">     enum AnimationAdvancement { Normal, SkippingFramesToCatchUp };
</span><span class="cx">     bool internalAdvanceAnimation(AnimationAdvancement = Normal);
</span><span class="cx"> 
</span><ins>+    // It may look unusual that there is no start animation call as public API. This is because
+    // we start and stop animating lazily. Animation begins whenever someone draws the image. It will
+    // automatically pause once all observers no longer want to render the image anywhere.
+    void stopAnimation() override;
+    void resetAnimation() override;
+
</ins><span class="cx">     // Handle platform-specific data
</span><span class="cx">     void invalidatePlatformData();
</span><span class="cx"> 
</span><del>-    Color singlePixelSolidColor() override;
-
</del><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     bool notSolidColor() override;
</span><span class="cx"> #endif
</span><span class="lines">@@ -223,21 +178,17 @@
</span><span class="cx"> private:
</span><span class="cx">     void clearTimer();
</span><span class="cx">     void startTimer(double delay);
</span><del>-
</del><ins>+    bool isBitmapImage() const override { return true; }
</ins><span class="cx">     void dump(TextStream&amp;) const override;
</span><span class="cx"> 
</span><del>-    ImageSource m_source;
-    mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
-    mutable IntSize m_sizeRespectingOrientation;
</del><ins>+    mutable ImageSource m_source;
</ins><span class="cx"> 
</span><span class="cx">     size_t m_currentFrame { 0 }; // The index of the current frame of animation.
</span><del>-    Vector&lt;ImageFrame, 1&gt; m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.
-
</del><span class="cx">     std::unique_ptr&lt;Timer&gt; m_frameTimer;
</span><del>-    RepetitionCount m_repetitionCount { RepetitionCountNone }; // How many total animation loops we should do. This will be cAnimationNone if this image type is incapable of animation.
-    RepetitionCountStatus m_repetitionCountStatus { Unknown };
</del><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><ins>+    bool m_animationFinished { false };
+    bool m_animationFinishedWhenCatchingUp { false };
</ins><span class="cx"> 
</span><span class="cx"> #if USE(APPKIT)
</span><span class="cx">     mutable RetainPtr&lt;NSImage&gt; m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one.
</span><span class="lines">@@ -245,29 +196,6 @@
</span><span class="cx"> #if USE(CG)
</span><span class="cx">     mutable RetainPtr&lt;CFDataRef&gt; m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one.
</span><span class="cx"> #endif
</span><del>-
-    // The value of this data member is a missing value if we haven’t analyzed to check for a solid color or not, but an invalid
-    // color if we have analyzed and decided it’s not a solid color, and a valid color if we have analyzed and decide that the
-    // solid color optimization applies. The analysis, we do, handles only the case of 1x1 solid color images.
-    Optional&lt;Color&gt; m_solidColor;
-
-    unsigned m_decodedSize { 0 }; // The current size of all decoded frames.
-    mutable unsigned m_decodedPropertiesSize { 0 }; // The size of data decoded by the source to determine image properties (e.g. size, frame count, etc).
-    size_t m_frameCount;
-
-#if PLATFORM(IOS)
-    // FIXME: We should expose a setting to enable/disable progressive loading remove the PLATFORM(IOS)-guard.
-    double m_progressiveLoadChunkTime { 0 };
-    uint16_t m_progressiveLoadChunkCount { 0 };
-#endif
-    bool m_animationFinished : 1; // Whether or not we've completed the entire animation.
-
-    bool m_allDataReceived : 1; // Whether or not we've received all our data.
-    mutable bool m_haveSize : 1; // Whether or not our |m_size| member variable has the final overall image size yet.
-    bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
-    mutable bool m_haveFrameCount : 1;
-    bool m_animationFinishedWhenCatchingUp : 1;
-
</del><span class="cx">     RefPtr&lt;Image&gt; m_cachedImage;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -274,5 +202,3 @@
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> SPECIALIZE_TYPE_TRAITS_IMAGE(BitmapImage)
</span><del>-
-#endif // BitmapImage_h
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGeneratedImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GeneratedImage.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GeneratedImage.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/GeneratedImage.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">         const FloatPoint&amp; phase, const FloatSize&amp; spacing, CompositeOperator, const FloatRect&amp; destRect, BlendMode) override = 0;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Implement this to be less conservative.
</span><del>-    bool currentFrameKnownToBeOpaque() override { return false; }
</del><ins>+    bool currentFrameKnownToBeOpaque() const override { return false; }
</ins><span class="cx"> 
</span><span class="cx">     GeneratedImage() { }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/Image.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/Image.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/Image.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">     virtual bool isSVGImage() const { return false; }
</span><span class="cx">     virtual bool isPDFDocumentImage() const { return false; }
</span><span class="cx"> 
</span><del>-    virtual bool currentFrameKnownToBeOpaque() = 0;
</del><ins>+    virtual bool currentFrameKnownToBeOpaque() const = 0;
</ins><span class="cx">     virtual bool isAnimated() const { return false; }
</span><span class="cx"> 
</span><span class="cx">     // Derived classes should override this if they can assure that 
</span><span class="lines">@@ -140,7 +140,7 @@
</span><span class="cx">     virtual NativeImagePtr nativeImage() { return nullptr; }
</span><span class="cx">     virtual NativeImagePtr nativeImageOfSize(const IntSize&amp;) { return nullptr; }
</span><span class="cx">     virtual NativeImagePtr nativeImageForCurrentFrame() { return nullptr; }
</span><del>-    virtual ImageOrientation orientationForCurrentFrame() { return ImageOrientation(); }
</del><ins>+    virtual ImageOrientation orientationForCurrentFrame() const { return ImageOrientation(); }
</ins><span class="cx">     virtual Vector&lt;NativeImagePtr&gt; framesNativeImages() { return { }; }
</span><span class="cx"> 
</span><span class="cx">     // Accessors for native image formats.
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">     void drawTiled(GraphicsContext&amp;, const FloatRect&amp; dstRect, const FloatRect&amp; srcRect, const FloatSize&amp; tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator);
</span><span class="cx"> 
</span><span class="cx">     // Supporting tiled drawing
</span><del>-    virtual Color singlePixelSolidColor() { return Color(); }
</del><ins>+    virtual Color singlePixelSolidColor() const { return Color(); }
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     RefPtr&lt;SharedBuffer&gt; m_encodedImageData;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageFrame.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageFrame.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/ImageFrame.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -26,11 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;ImageFrame.h&quot;
</span><span class="cx"> 
</span><del>-#if USE(CG)
-#include &quot;ImageDecoderCG.h&quot;
-#else
-#include &quot;ImageDecoder.h&quot;
-#endif
</del><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -43,6 +39,12 @@
</span><span class="cx">     clearImage();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const ImageFrame&amp; ImageFrame::defaultFrame()
+{
+    static NeverDestroyed&lt;ImageFrame&gt; sharedInstance;
+    return sharedInstance;
+}
+
</ins><span class="cx"> ImageFrame&amp; ImageFrame::operator=(const ImageFrame&amp; other)
</span><span class="cx"> {
</span><span class="cx">     if (this == &amp;other)
</span><span class="lines">@@ -68,19 +70,6 @@
</span><span class="cx">     return *this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrame::fillMetadata(ImageDecoder&amp; decoder, size_t index, SubsamplingLevel subsamplingLevel, bool animating)
-{
-    m_decoding = decoder.frameIsCompleteAtIndex(index) ? Decoding::Complete : Decoding::Partial;
-    m_size = decoder.frameSizeAtIndex(index, subsamplingLevel);
-
-    m_subsamplingLevel = subsamplingLevel;
-
-    m_orientation = decoder.frameOrientationAtIndex(index);
-    if (animating)
-        m_duration = decoder.frameDurationAtIndex(index);
-    m_hasAlpha = decoder.frameHasAlphaAtIndex(index);
-}
-
</del><span class="cx"> unsigned ImageFrame::clearImage()
</span><span class="cx"> {
</span><span class="cx"> #if !USE(CG)
</span><span class="lines">@@ -106,25 +95,6 @@
</span><span class="cx">     return frameBytes;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageFrame::initialize(NativeImagePtr&amp;&amp; nativeImage, ImageDecoder&amp; decoder, size_t index, SubsamplingLevel subsamplingLevel, bool animating)
-{
-    m_nativeImage = WTFMove(nativeImage);
-
-    if (!hasMetadata())
-        fillMetadata(decoder, index, subsamplingLevel, animating);
-    else if (!isComplete())
-        m_decoding = decoder.frameIsCompleteAtIndex(index) ? Decoding::Complete : Decoding::Partial;
-}
-
-void ImageFrame::initialize(NativeImagePtr&amp;&amp; nativeImage)
-{
-    m_nativeImage = WTFMove(nativeImage);
-
-    m_decoding = Decoding::Complete;
-    m_size = nativeImageSize(m_nativeImage);
-    m_hasAlpha = nativeImageHasAlpha(m_nativeImage);
-}
-
</del><span class="cx"> #if !USE(CG)
</span><span class="cx"> bool ImageFrame::initialize(const ImageBackingStore&amp; backingStore)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageFrame.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageFrame.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/ImageFrame.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -34,7 +34,6 @@
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class Color;
</span><del>-class ImageDecoder;
</del><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><span class="lines">@@ -64,27 +63,34 @@
</span><span class="cx">     RepetitionCountInfinite = -1,
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum class AlphaOption {
+    Premultiplied,
+    NotPremultiplied
+};
+
+enum class GammaAndColorProfileOption {
+    Applied,
+    Ignored
+};
+
</ins><span class="cx"> class ImageFrame {
</span><ins>+    friend class ImageFrameCache;
</ins><span class="cx"> public:
</span><span class="cx">     enum class Caching { Empty, Metadata, MetadataAndImage };
</span><span class="cx">     enum class Decoding { Empty, Partial, Complete };
</span><span class="cx"> 
</span><span class="cx">     ImageFrame();
</span><del>-    ImageFrame(NativeImagePtr&amp;&amp;);
</del><span class="cx">     ImageFrame(const ImageFrame&amp; other) { operator=(other); }
</span><span class="cx"> 
</span><span class="cx">     ~ImageFrame();
</span><span class="cx"> 
</span><ins>+    static const ImageFrame&amp; defaultFrame();
+
</ins><span class="cx">     ImageFrame&amp; operator=(const ImageFrame&amp; other);
</span><span class="cx"> 
</span><span class="cx">     unsigned clearImage();
</span><span class="cx">     unsigned clear();
</span><span class="cx"> 
</span><del>-    // FIXME: Calling ImageDecoder::repetitionCount() is expensive to be done for every frame.
-    // Remove the 'animating' flag from this function when calling repetitionCount() is cheap
-    // because it will be cached by ImageDecoder or a sub-class of it.
-    void initialize(NativeImagePtr&amp;&amp;, ImageDecoder&amp;, size_t, SubsamplingLevel, bool animating);
-    void initialize(NativeImagePtr&amp;&amp;);
</del><span class="cx"> #if !USE(CG)
</span><span class="cx">     bool initialize(const ImageBackingStore&amp;);
</span><span class="cx">     bool initialize(const IntSize&amp;, bool premultiplyAlpha);
</span><span class="lines">@@ -112,11 +118,11 @@
</span><span class="cx">     void setOrientation(ImageOrientation orientation) { m_orientation = orientation; };
</span><span class="cx">     ImageOrientation orientation() const { return m_orientation; }
</span><span class="cx"> 
</span><del>-    void setDuration(unsigned duration) { m_duration = duration; }
</del><ins>+    void setDuration(float duration) { m_duration = duration; }
</ins><span class="cx">     float duration() const { return m_duration; }
</span><span class="cx"> 
</span><span class="cx">     void setHasAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; }
</span><del>-    bool hasAlpha() const { return m_hasAlpha; }
</del><ins>+    bool hasAlpha() const { return !hasMetadata() || m_hasAlpha; }
</ins><span class="cx"> 
</span><span class="cx">     bool hasNativeImage() const { return m_nativeImage; }
</span><span class="cx">     bool hasInvalidNativeImage(SubsamplingLevel subsamplingLevel) const { return hasNativeImage() &amp;&amp; subsamplingLevel &lt; m_subsamplingLevel; }
</span><span class="lines">@@ -130,8 +136,6 @@
</span><span class="cx">     Color singlePixelSolidColor() const;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void fillMetadata(ImageDecoder&amp;, size_t, SubsamplingLevel, bool animating);
-
</del><span class="cx">     Decoding m_decoding { Decoding::Empty };
</span><span class="cx">     IntSize m_size;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageFrameCachecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp (0 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -0,0 +1,370 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;ImageFrameCache.h&quot;
+
+#include &quot;Image.h&quot;
+#include &quot;ImageObserver.h&quot;
+
+#if USE(CG)
+#include &quot;ImageDecoderCG.h&quot;
+#else
+#include &quot;ImageDecoder.h&quot;
+#endif
+
+namespace WebCore {
+
+ImageFrameCache::ImageFrameCache(Image* image)
+    : m_image(image)
+{
+}
+
+ImageFrameCache::ImageFrameCache(NativeImagePtr&amp;&amp; nativeImage)
+{
+    m_frameCount = 1;
+    m_isSizeAvailable = true;
+    growFrames();
+
+    setNativeImage(WTFMove(nativeImage));
+
+    m_decodedSize = m_frames[0].frameBytes();
+
+    // The assumption is the memory image will be displayed with the default
+    // orientation. So set m_sizeRespectingOrientation to be the same as m_size.
+    m_size = m_frames[0].size();
+    m_sizeRespectingOrientation = m_size;
+}
+
+void ImageFrameCache::destroyDecodedData(bool destroyAll, size_t count)
+{
+    if (destroyAll)
+        count = m_frames.size();
+    
+    unsigned decodedSize = 0;
+    for (size_t i = 0; i &lt;  count; ++i)
+        decodedSize += m_frames[i].clearImage();
+    
+    decodedSizeReset(decodedSize);
+}
+
+bool ImageFrameCache::destroyDecodedDataIfNecessary(bool destroyAll, size_t count)
+{
+    unsigned decodedSize = 0;
+    for (auto&amp; frame : m_frames)
+        decodedSize += frame.frameBytes();
+    
+    if (decodedSize &lt; LargeAnimationCutoff)
+        return false;
+    
+    destroyDecodedData(destroyAll, count);
+    return true;
+}
+
+void ImageFrameCache::destroyIncompleteDecodedData()
+{
+    unsigned decodedSize = 0;
+    
+    for (auto&amp; frame : m_frames) {
+        if (!frame.hasMetadata() || frame.isComplete())
+            continue;
+        
+        decodedSize += frame.clear();
+    }
+    
+    decodedSizeDecremented(decodedSize);
+}
+
+
+void ImageFrameCache::decodedSizeChanged(int decodedSize)
+{
+    if (!decodedSize || !m_image || !m_image-&gt;imageObserver())
+        return;
+    
+    m_image-&gt;imageObserver()-&gt;decodedSizeChanged(m_image, decodedSize);
+}
+
+void ImageFrameCache::decodedSizeIncremented(unsigned decodedSize)
+{
+    if (!decodedSize)
+        return;
+    
+    m_decodedSize += decodedSize;
+    
+    // The fully-decoded frame will subsume the partially decoded data used
+    // to determine image properties.
+    int changeSize = decodedSize - m_decodedPropertiesSize;
+    m_decodedPropertiesSize = 0;
+    decodedSizeChanged(changeSize);
+}
+
+void ImageFrameCache::decodedSizeDecremented(unsigned decodedSize)
+{
+    if (!decodedSize)
+        return;
+    
+    ASSERT(m_decodedSize &gt;= decodedSize);
+    m_decodedSize -= decodedSize;
+    decodedSizeChanged(-safeCast&lt;int&gt;(decodedSize));
+}
+
+void ImageFrameCache::decodedSizeReset(unsigned decodedSize)
+{
+    ASSERT(m_decodedSize &gt;= decodedSize);
+    m_decodedSize -= decodedSize;
+    
+    // Clearing the ImageSource destroys the extra decoded data used for
+    // determining image properties.
+    decodedSize += m_decodedPropertiesSize;
+    m_decodedPropertiesSize = 0;
+    decodedSizeChanged(-safeCast&lt;int&gt;(decodedSize));
+}
+
+void ImageFrameCache::didDecodeProperties(unsigned decodedPropertiesSize)
+{
+    if (m_decodedSize)
+        return;
+    
+    int decodedSize = decodedPropertiesSize - m_decodedPropertiesSize;
+    m_decodedPropertiesSize = decodedPropertiesSize;
+    decodedSizeChanged(decodedSize);
+}
+
+void ImageFrameCache::growFrames()
+{
+    ASSERT(isSizeAvailable());
+    ASSERT(m_frames.size() &lt;= frameCount());
+    m_frames.grow(frameCount());
+}
+
+void ImageFrameCache::setNativeImage(NativeImagePtr&amp;&amp; nativeImage)
+{
+    ASSERT(m_frames.size() == 1);
+    ImageFrame&amp; frame = m_frames[0];
+
+    ASSERT(!isDecoderAvailable());
+
+    frame.m_nativeImage = WTFMove(nativeImage);
+
+    frame.m_decoding = ImageFrame::Decoding::Complete;
+    frame.m_size = nativeImageSize(frame.m_nativeImage);
+    frame.m_hasAlpha = nativeImageHasAlpha(frame.m_nativeImage);
+}
+
+void ImageFrameCache::setFrameNativeImage(NativeImagePtr&amp;&amp; nativeImage, size_t index, SubsamplingLevel subsamplingLevel)
+{
+    ASSERT(index &lt; m_frames.size());
+    ImageFrame&amp; frame = m_frames[index];
+
+    ASSERT(isDecoderAvailable());
+
+    frame.m_nativeImage = WTFMove(nativeImage);
+    setFrameMetadata(index, subsamplingLevel);
+}
+
+void ImageFrameCache::setFrameMetadata(size_t index, SubsamplingLevel subsamplingLevel)
+{
+    ASSERT(index &lt; m_frames.size());
+    ImageFrame&amp; frame = m_frames[index];
+
+    ASSERT(isDecoderAvailable());
+    frame.m_decoding = m_decoder-&gt;frameIsCompleteAtIndex(index) ? ImageFrame::Decoding::Complete : ImageFrame::Decoding::Partial;
+    if (frame.hasMetadata())
+        return;
+    
+    frame.m_subsamplingLevel = subsamplingLevel;
+    frame.m_size = m_decoder-&gt;frameSizeAtIndex(index, subsamplingLevel);
+    frame.m_orientation = m_decoder-&gt;frameOrientationAtIndex(index);
+    frame.m_hasAlpha = m_decoder-&gt;frameHasAlphaAtIndex(index);
+    
+    if (repetitionCount())
+        frame.m_duration = m_decoder-&gt;frameDurationAtIndex(index);
+}
+
+const ImageFrame&amp; ImageFrameCache::frameAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching)
+{
+    ASSERT(index &lt; m_frames.size());
+    ImageFrame&amp; frame = m_frames[index];
+    if (!isDecoderAvailable() || caching == ImageFrame::Caching::Empty)
+        return frame;
+    
+    if (subsamplingLevel == SubsamplingLevel::Undefinded)
+        subsamplingLevel = frame.subsamplingLevel();
+    
+    if (frame.hasInvalidNativeImage(subsamplingLevel)) {
+        unsigned decodedSize = frame.clear();
+        decodedSizeDecremented(decodedSize);
+    }
+    
+    if (!frame.isComplete() &amp;&amp; caching == ImageFrame::Caching::Metadata)
+        setFrameMetadata(index, subsamplingLevel);
+    
+    if (!frame.hasNativeImage() &amp;&amp; caching == ImageFrame::Caching::MetadataAndImage) {
+        setFrameNativeImage(m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevel), index, subsamplingLevel);
+        decodedSizeIncremented(frame.frameBytes());
+    }
+    
+    return frame;
+}
+
+void ImageFrameCache::clearMetadata()
+{
+    m_frameCount = Nullopt;
+    m_singlePixelSolidColor = Nullopt;
+    m_maximumSubsamplingLevel = Nullopt;
+}
+
+template&lt;typename T, T (ImageDecoder::*functor)() const&gt;
+T ImageFrameCache::metadata(const T&amp; defaultValue, Optional&lt;T&gt;* cachedValue)
+{
+    if (cachedValue &amp;&amp; *cachedValue)
+        return cachedValue-&gt;value();
+
+    if (!isDecoderAvailable() || !m_decoder-&gt;isSizeAvailable())
+        return defaultValue;
+
+    if (!cachedValue)
+        return (m_decoder-&gt;*functor)();
+
+    *cachedValue = (m_decoder-&gt;*functor)();
+    didDecodeProperties(m_decoder-&gt;bytesDecodedToDetermineProperties());
+    return cachedValue-&gt;value();
+}
+
+template&lt;typename T, T (ImageFrame::*functor)() const&gt;
+T ImageFrameCache::frameMetadataAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageFrame::Caching caching, Optional&lt;T&gt;* cachedValue)
+{
+    if (cachedValue &amp;&amp; *cachedValue)
+        return cachedValue-&gt;value();
+    
+    const ImageFrame&amp; frame = index &lt; m_frames.size() ? frameAtIndex(index, subsamplingLevel, caching) : ImageFrame::defaultFrame();
+
+    // Don't cache any unavailable frame metadata.
+    if (!frame.hasMetadata() || !cachedValue)
+        return (frame.*functor)();
+    
+    *cachedValue = (frame.*functor)();
+    return cachedValue-&gt;value();
+}
+
+bool ImageFrameCache::isSizeAvailable()
+{
+    if (m_isSizeAvailable)
+        return m_isSizeAvailable.value();
+    
+    if (!isDecoderAvailable() || !m_decoder-&gt;isSizeAvailable())
+        return false;
+    
+    m_isSizeAvailable = true;
+    didDecodeProperties(m_decoder-&gt;bytesDecodedToDetermineProperties());
+    return true;
+}
+
+size_t ImageFrameCache::frameCount()
+{
+    return metadata&lt;size_t, (&amp;ImageDecoder::frameCount)&gt;(m_frames.size(), &amp;m_frameCount);
+}
+
+RepetitionCount ImageFrameCache::repetitionCount()
+{
+    return metadata&lt;RepetitionCount, (&amp;ImageDecoder::repetitionCount)&gt;(RepetitionCountNone, &amp;m_repetitionCount);
+}
+
+String ImageFrameCache::filenameExtension()
+{
+    return metadata&lt;String, (&amp;ImageDecoder::filenameExtension)&gt;(String(), &amp;m_filenameExtension);
+}
+
+Optional&lt;IntPoint&gt; ImageFrameCache::hotSpot()
+{
+    return metadata&lt;Optional&lt;IntPoint&gt;, (&amp;ImageDecoder::hotSpot)&gt;(Nullopt, &amp;m_hotSpot);
+}
+
+IntSize ImageFrameCache::size()
+{
+    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::size)&gt;(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &amp;m_size);
+}
+
+IntSize ImageFrameCache::sizeRespectingOrientation()
+{
+    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::sizeRespectingOrientation)&gt;(0, SubsamplingLevel::Default, ImageFrame::Caching::Metadata, &amp;m_sizeRespectingOrientation);
+}
+
+Color ImageFrameCache::singlePixelSolidColor()
+{
+    return frameCount() == 1 ? frameMetadataAtIndex&lt;Color, (&amp;ImageFrame::singlePixelSolidColor)&gt;(0, SubsamplingLevel::Undefinded, ImageFrame::Caching::MetadataAndImage, &amp;m_singlePixelSolidColor) : Color();
+}
+
+bool ImageFrameCache::frameIsCompleteAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::isComplete)&gt;(index);
+}
+
+bool ImageFrameCache::frameHasAlphaAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::hasAlpha)&gt;(index);
+}
+
+bool ImageFrameCache::frameHasImageAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;bool, (&amp;ImageFrame::hasNativeImage)&gt;(index);
+}
+
+bool ImageFrameCache::frameHasInvalidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+    return frameHasImageAtIndex(index) &amp;&amp; subsamplingLevel &lt; frameSubsamplingLevelAtIndex(index);
+}
+
+SubsamplingLevel ImageFrameCache::frameSubsamplingLevelAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;SubsamplingLevel, (&amp;ImageFrame::subsamplingLevel)&gt;(index);
+}
+
+IntSize ImageFrameCache::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+    return frameMetadataAtIndex&lt;IntSize, (&amp;ImageFrame::size)&gt;(index, subsamplingLevel, ImageFrame::Caching::Metadata);
+}
+
+unsigned ImageFrameCache::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+    return frameMetadataAtIndex&lt;unsigned, (&amp;ImageFrame::frameBytes)&gt;(index, subsamplingLevel, ImageFrame::Caching::Metadata);
+}
+
+float ImageFrameCache::frameDurationAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;float, (&amp;ImageFrame::duration)&gt;(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
+}
+
+ImageOrientation ImageFrameCache::frameOrientationAtIndex(size_t index)
+{
+    return frameMetadataAtIndex&lt;ImageOrientation, (&amp;ImageFrame::orientation)&gt;(index, SubsamplingLevel::Undefinded, ImageFrame::Caching::Metadata);
+}
+
+NativeImagePtr ImageFrameCache::frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
+{
+    return frameMetadataAtIndex&lt;NativeImagePtr, (&amp;ImageFrame::nativeImage)&gt;(index, subsamplingLevel, ImageFrame::Caching::MetadataAndImage);
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageFrameCacheh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/graphics/ImageFrameCache.h (0 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageFrameCache.h                                (rev 0)
+++ trunk/Source/WebCore/platform/graphics/ImageFrameCache.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -0,0 +1,129 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;ImageFrame.h&quot;
+#include &quot;TextStream.h&quot;
+
+#include &lt;wtf/Forward.h&gt;
+#include &lt;wtf/Optional.h&gt;
+
+namespace WebCore {
+
+class Image;
+class ImageDecoder;
+
+class ImageFrameCache {
+    friend class ImageSource;
+public:
+    ImageFrameCache(Image*);
+    ImageFrameCache(NativeImagePtr&amp;&amp;);
+
+    void setDecoder(ImageDecoder* decoder) { m_decoder = decoder; }
+    unsigned decodedSize() const { return m_decodedSize; }
+    void destroyDecodedData(bool destroyAll = true, size_t count = 0);
+    bool destroyDecodedDataIfNecessary(bool destroyAll = true, size_t count = 0);
+    void destroyIncompleteDecodedData();
+
+    void growFrames();
+    void clearMetadata();
+
+    // Image metadata which is calculated either by the ImageDecoder or directly
+    // from the NativeImage if this class was created for a memory image.
+    bool isSizeAvailable();
+    size_t frameCount();
+    RepetitionCount repetitionCount();
+    String filenameExtension();
+    Optional&lt;IntPoint&gt; hotSpot();
+    
+    // Image metadata which is calculated from the first ImageFrame.
+    IntSize size();
+    IntSize sizeRespectingOrientation();
+
+    Color singlePixelSolidColor();
+
+    // ImageFrame metadata which does not require caching the ImageFrame.
+    bool frameIsCompleteAtIndex(size_t);
+    bool frameHasAlphaAtIndex(size_t);
+    bool frameHasImageAtIndex(size_t);
+    bool frameHasInvalidNativeImageAtIndex(size_t, SubsamplingLevel);
+    SubsamplingLevel frameSubsamplingLevelAtIndex(size_t);
+    
+    // ImageFrame metadata which forces caching or re-caching the ImageFrame.
+    IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+    float frameDurationAtIndex(size_t);
+    ImageOrientation frameOrientationAtIndex(size_t);
+    NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
+
+private:
+    template&lt;typename T, T (ImageDecoder::*functor)() const&gt;
+    T metadata(const T&amp; defaultValue, Optional&lt;T&gt;* cachedValue = nullptr);
+
+    template&lt;typename T, T (ImageFrame::*functor)() const&gt;
+    T frameMetadataAtIndex(size_t index, SubsamplingLevel = SubsamplingLevel::Undefinded, ImageFrame::Caching = ImageFrame::Caching::Empty, Optional&lt;T&gt;* = nullptr);
+
+    bool isDecoderAvailable() const { return m_decoder; }
+    void decodedSizeChanged(int decodedSize);
+    void didDecodeProperties(unsigned decodedPropertiesSize);
+    void decodedSizeIncremented(unsigned decodedSize);
+    void decodedSizeDecremented(unsigned decodedSize);
+    void decodedSizeReset(unsigned decodedSize);
+
+    void setNativeImage(NativeImagePtr&amp;&amp;);
+    void setFrameNativeImage(NativeImagePtr&amp;&amp;, size_t, SubsamplingLevel);
+    void setFrameMetadata(size_t, SubsamplingLevel);
+    const ImageFrame&amp; frameAtIndex(size_t, SubsamplingLevel, ImageFrame::Caching);
+
+    // Animated images over a certain size are considered large enough that we'll only hang on to one frame at a time.
+#if !PLATFORM(IOS)
+    static const unsigned LargeAnimationCutoff = 5242880;
+#else
+    static const unsigned LargeAnimationCutoff = 2097152;
+#endif
+
+    Image* m_image { nullptr };
+    ImageDecoder* m_decoder { nullptr };
+    unsigned m_decodedSize { 0 };
+    unsigned m_decodedPropertiesSize { 0 };
+
+    Vector&lt;ImageFrame, 1&gt; m_frames;
+
+    // Image metadata.
+    Optional&lt;bool&gt; m_isSizeAvailable;
+    Optional&lt;size_t&gt; m_frameCount;
+    Optional&lt;RepetitionCount&gt; m_repetitionCount;
+    Optional&lt;String&gt; m_filenameExtension;
+    Optional&lt;Optional&lt;IntPoint&gt;&gt; m_hotSpot;
+
+    // Image metadata which is calculated from the first ImageFrame.
+    Optional&lt;IntSize&gt; m_size;
+    Optional&lt;IntSize&gt; m_sizeRespectingOrientation;
+    Optional&lt;SubsamplingLevel&gt; m_maximumSubsamplingLevel;
+    Optional&lt;Color&gt; m_singlePixelSolidColor;
+};
+    
+}
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -37,15 +37,17 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ImageOrientation.h&quot;
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/CurrentTime.h&gt;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-ImageSource::ImageSource(const NativeImagePtr&amp;)
</del><ins>+ImageSource::ImageSource(NativeImagePtr&amp;&amp; nativeImage)
+    : m_frameCache(WTFMove(nativeImage))
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
-    : m_needsUpdateMetadata(true)
-    , m_maximumSubsamplingLevel(Nullopt)
</del><ins>+ImageSource::ImageSource(Image* image, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
+    : m_frameCache(image)
</ins><span class="cx">     , m_alphaOption(alphaOption)
</span><span class="cx">     , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
</span><span class="cx"> {
</span><span class="lines">@@ -57,176 +59,150 @@
</span><span class="cx"> 
</span><span class="cx"> void ImageSource::clearFrameBufferCache(size_t clearBeforeFrame)
</span><span class="cx"> {
</span><del>-    if (!initialized())
</del><ins>+    if (!isDecoderAvailable())
</ins><span class="cx">         return;
</span><span class="cx">     m_decoder-&gt;clearFrameBufferCache(clearBeforeFrame);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageSource::clear(bool destroyAllFrames, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
</del><ins>+void ImageSource::clear(bool destroyAll, size_t count, SharedBuffer* data)
</ins><span class="cx"> {
</span><span class="cx">     // There's no need to throw away the decoder unless we're explicitly asked
</span><span class="cx">     // to destroy all of the frames.
</span><del>-    if (!destroyAllFrames) {
-        clearFrameBufferCache(clearBeforeFrame);
</del><ins>+    if (!destroyAll) {
+        clearFrameBufferCache(count);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_decoder = nullptr;
</span><ins>+    m_frameCache.setDecoder(nullptr);
+    setData(data, isAllDataReceived());
+}
</ins><span class="cx"> 
</span><del>-    if (data)
-        setData(data, allDataReceived);
</del><ins>+void ImageSource::destroyDecodedData(SharedBuffer* data, bool destroyAll, size_t count)
+{
+    ASSERT(isDecoderAvailable());
+    m_frameCache.destroyDecodedData(destroyAll, count);
+    clear(destroyAll, count, data);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
</del><ins>+bool ImageSource::destroyDecodedDataIfNecessary(SharedBuffer* data, bool destroyAll, size_t count)
</ins><span class="cx"> {
</span><del>-    if (!data)
-        return;
</del><ins>+    // If we have decoded frames but there is no encoded data, we shouldn't destroy
+    // the decoded image since we won't be able to reconstruct it later.
+    if (!data &amp;&amp; m_frameCache.frameCount())
+        return false;
</ins><span class="cx"> 
</span><del>-    if (!initialized()) {
-        m_decoder = ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption);
-        if (!m_decoder)
-            return;
-    }
</del><ins>+    if (!m_frameCache.destroyDecodedDataIfNecessary(destroyAll, count))
+        return false;
</ins><span class="cx"> 
</span><del>-    m_decoder-&gt;setData(*data, allDataReceived);
</del><ins>+    clear(destroyAll, count, data);
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-SubsamplingLevel ImageSource::calculateMaximumSubsamplingLevel() const
</del><ins>+bool ImageSource::ensureDecoderAvailable(SharedBuffer* data)
</ins><span class="cx"> {
</span><del>-    if (!m_allowSubsampling || !frameAllowSubsamplingAtIndex(0))
-        return SubsamplingLevel::Default;
-    
-    // FIXME: this value was chosen to be appropriate for iOS since the image
-    // subsampling is only enabled by default on iOS. Choose a different value
-    // if image subsampling is enabled on other platform.
-    const int maximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
</del><ins>+    if (!data || isDecoderAvailable())
+        return true;
</ins><span class="cx"> 
</span><del>-    for (SubsamplingLevel level = SubsamplingLevel::First; level &lt;= SubsamplingLevel::Last; ++level) {
-        if (frameSizeAtIndex(0, level).area() &lt; maximumImageAreaBeforeSubsampling)
-            return level;
-    }
-    
-    return SubsamplingLevel::Last;
</del><ins>+    m_decoder = ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption);
+    if (!isDecoderAvailable())
+        return false;
+
+    m_frameCache.setDecoder(m_decoder.get());
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageSource::updateMetadata()
</del><ins>+void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
</ins><span class="cx"> {
</span><del>-    if (!(m_needsUpdateMetadata &amp;&amp; isSizeAvailable()))
</del><ins>+    if (!data || !ensureDecoderAvailable(data))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    m_frameCount = m_decoder-&gt;frameCount();
-    if (!m_maximumSubsamplingLevel)
-        m_maximumSubsamplingLevel = calculateMaximumSubsamplingLevel();
-
-    m_needsUpdateMetadata = false;
</del><ins>+    m_decoder-&gt;setData(*data, allDataReceived);
</ins><span class="cx"> }
</span><del>-    
-SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale)
-{
-    if (!(scale &gt; 0 &amp;&amp; scale &lt;= 1))
-        return SubsamplingLevel::Default;
</del><span class="cx"> 
</span><del>-    updateMetadata();
-    if (!m_maximumSubsamplingLevel)
-        return SubsamplingLevel::Default;
-
-    int result = std::ceil(std::log2(1 / scale));
-    return static_cast&lt;SubsamplingLevel&gt;(std::min(result, static_cast&lt;int&gt;(m_maximumSubsamplingLevel.value())));
-}
-
-size_t ImageSource::bytesDecodedToDetermineProperties()
</del><ins>+bool ImageSource::dataChanged(SharedBuffer* data, bool allDataReceived)
</ins><span class="cx"> {
</span><del>-    return ImageDecoder::bytesDecodedToDetermineProperties();
-}
</del><ins>+    m_frameCache.destroyIncompleteDecodedData();
</ins><span class="cx"> 
</span><del>-bool ImageSource::isSizeAvailable() const
-{
-    return initialized() &amp;&amp; m_decoder-&gt;isSizeAvailable();
-}
</del><ins>+#if PLATFORM(IOS)
+    // FIXME: We should expose a setting to enable/disable progressive loading and make this
+    // code conditional on it. Then we can remove the PLATFORM(IOS)-guard.
+    static const double chunkLoadIntervals[] = {0, 1, 3, 6, 15};
+    double interval = chunkLoadIntervals[std::min(m_progressiveLoadChunkCount, static_cast&lt;uint16_t&gt;(4))];
</ins><span class="cx"> 
</span><del>-IntSize ImageSource::size() const
-{
-    return frameSizeAtIndex(0, SubsamplingLevel::Default);
-}
</del><ins>+    bool needsUpdate = false;
</ins><span class="cx"> 
</span><del>-IntSize ImageSource::sizeRespectingOrientation() const
-{
-    return frameSizeAtIndex(0, SubsamplingLevel::Default, RespectImageOrientation);
-}
</del><ins>+    // The first time through, the chunk time will be 0 and the image will get an update.
+    if (currentTime() - m_progressiveLoadChunkTime &gt; interval) {
+        needsUpdate = true;
+        m_progressiveLoadChunkTime = currentTime();
+        ASSERT(m_progressiveLoadChunkCount &lt;= std::numeric_limits&lt;uint16_t&gt;::max());
+        ++m_progressiveLoadChunkCount;
+    }
</ins><span class="cx"> 
</span><del>-size_t ImageSource::frameCount()
-{
-    updateMetadata();
-    return m_frameCount;
-}
</del><ins>+    if (needsUpdate || allDataReceived)
+        setData(data, allDataReceived);
+#else
+    setData(data, allDataReceived);
+#endif
</ins><span class="cx"> 
</span><del>-RepetitionCount ImageSource::repetitionCount()
-{
-    return initialized() ? m_decoder-&gt;repetitionCount() : RepetitionCountNone;
-}
</del><ins>+    m_frameCache.clearMetadata();
+    if (!isSizeAvailable())
+        return false;
</ins><span class="cx"> 
</span><del>-String ImageSource::filenameExtension() const
-{
-    return initialized() ? m_decoder-&gt;filenameExtension() : String();
</del><ins>+    m_frameCache.growFrames();
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-Optional&lt;IntPoint&gt; ImageSource::hotSpot() const
</del><ins>+bool ImageSource::isAllDataReceived()
</ins><span class="cx"> {
</span><del>-    return initialized() ? m_decoder-&gt;hotSpot() : Nullopt;
</del><ins>+    return isDecoderAvailable() ? m_decoder-&gt;isAllDataReceived() : m_frameCache.frameCount();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ImageSource::frameIsCompleteAtIndex(size_t index)
</del><ins>+SubsamplingLevel ImageSource::maximumSubsamplingLevel()
</ins><span class="cx"> {
</span><del>-    return initialized() &amp;&amp; m_decoder-&gt;frameIsCompleteAtIndex(index);
-}
</del><ins>+    if (m_maximumSubsamplingLevel)
+        return m_maximumSubsamplingLevel.value();
</ins><span class="cx"> 
</span><del>-bool ImageSource::frameHasAlphaAtIndex(size_t index)
-{
-    return !initialized() || m_decoder-&gt;frameHasAlphaAtIndex(index);
-}
</del><ins>+    if (!m_allowSubsampling || !isDecoderAvailable() || !m_decoder-&gt;frameAllowSubsamplingAtIndex(0))
+        return SubsamplingLevel::Default;
</ins><span class="cx"> 
</span><del>-bool ImageSource::frameAllowSubsamplingAtIndex(size_t index) const
-{
-    return initialized() &amp;&amp; m_decoder-&gt;frameAllowSubsamplingAtIndex(index);
-}
</del><ins>+    // FIXME: this value was chosen to be appropriate for iOS since the image
+    // subsampling is only enabled by default on iOS. Choose a different value
+    // if image subsampling is enabled on other platform.
+    const int maximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
+    SubsamplingLevel level = SubsamplingLevel::First;
</ins><span class="cx"> 
</span><del>-IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
-{
-    if (!initialized())
-        return { };
</del><ins>+    for (; level &lt; SubsamplingLevel::Last; ++level) {
+        if (frameSizeAtIndex(0, level).area() &lt; maximumImageAreaBeforeSubsampling)
+            break;
+    }
</ins><span class="cx"> 
</span><del>-    IntSize size = m_decoder-&gt;frameSizeAtIndex(index, subsamplingLevel);
-    if (shouldRespectImageOrientation != RespectImageOrientation)
-        return size;
-
-    return frameOrientationAtIndex(index).usesWidthAsHeight() ? size.transposedSize() : size;
</del><ins>+    m_maximumSubsamplingLevel = level;
+    return m_maximumSubsamplingLevel.value();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
</del><ins>+SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale)
</ins><span class="cx"> {
</span><del>-    return frameSizeAtIndex(index, subsamplingLevel).area() * 4;
-}
</del><ins>+    if (!(scale &gt; 0 &amp;&amp; scale &lt;= 1))
+        return SubsamplingLevel::Default;
</ins><span class="cx"> 
</span><del>-float ImageSource::frameDurationAtIndex(size_t index)
-{
-    return initialized() ? m_decoder-&gt;frameDurationAtIndex(index) : 0;
</del><ins>+    int result = std::ceil(std::log2(1 / scale));
+    return static_cast&lt;SubsamplingLevel&gt;(std::min(result, static_cast&lt;int&gt;(maximumSubsamplingLevel())));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ImageOrientation ImageSource::frameOrientationAtIndex(size_t index) const
-{
-    return initialized() ? m_decoder-&gt;frameOrientationAtIndex(index) : ImageOrientation();
-}
-    
</del><span class="cx"> NativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</span><span class="cx"> {
</span><del>-    return initialized() ? m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
</del><ins>+    return isDecoderAvailable() ? m_decoder-&gt;createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageSource::dump(TextStream&amp; ts) const
</del><ins>+void ImageSource::dump(TextStream&amp; ts)
</ins><span class="cx"> {
</span><del>-    if (m_allowSubsampling)
-        ts.dumpProperty(&quot;allow-subsampling&quot;, m_allowSubsampling);
-    
</del><ins>+    ts.dumpProperty(&quot;type&quot;, filenameExtension());
+    ts.dumpProperty(&quot;frame-count&quot;, frameCount());
+    ts.dumpProperty(&quot;repetitions&quot;, repetitionCount());
+    ts.dumpProperty(&quot;solid-color&quot;, singlePixelSolidColor());
+
</ins><span class="cx">     ImageOrientation orientation = frameOrientationAtIndex(0);
</span><span class="cx">     if (orientation != OriginTopLeft)
</span><span class="cx">         ts.dumpProperty(&quot;orientation&quot;, orientation);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageSource.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageSource.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -24,10 +24,10 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef ImageSource_h
-#define ImageSource_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageFrame.h&quot;
</span><ins>+#include &quot;ImageFrameCache.h&quot;
</ins><span class="cx"> #include &quot;ImageOrientation.h&quot;
</span><span class="cx"> #include &quot;IntPoint.h&quot;
</span><span class="cx"> #include &quot;NativeImage.h&quot;
</span><span class="lines">@@ -38,105 +38,73 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+class ImageDecoder;
</ins><span class="cx"> class ImageOrientation;
</span><span class="cx"> class IntPoint;
</span><span class="cx"> class IntSize;
</span><span class="cx"> class SharedBuffer;
</span><del>-class ImageDecoder;
</del><span class="cx"> 
</span><span class="cx"> class ImageSource {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(ImageSource);
</span><span class="cx">     friend class BitmapImage;
</span><span class="cx"> public:
</span><del>-    enum AlphaOption {
-        AlphaPremultiplied,
-        AlphaNotPremultiplied
-    };
-
-    enum GammaAndColorProfileOption {
-        GammaAndColorProfileApplied,
-        GammaAndColorProfileIgnored
-    };
-
-    ImageSource(const NativeImagePtr&amp;);
-    ImageSource(AlphaOption = AlphaPremultiplied, GammaAndColorProfileOption = GammaAndColorProfileApplied);
</del><ins>+    ImageSource(NativeImagePtr&amp;&amp;);
+    ImageSource(Image*, AlphaOption = AlphaOption::Premultiplied, GammaAndColorProfileOption = GammaAndColorProfileOption::Applied);
</ins><span class="cx">     ~ImageSource();
</span><span class="cx"> 
</span><del>-    // Tells the ImageSource that the Image no longer cares about decoded frame
-    // data -- at all (if |destroyAll| is true), or before frame
-    // |clearBeforeFrame| (if |destroyAll| is false).  The ImageSource should
-    // delete cached decoded data for these frames where possible to keep memory
-    // usage low.  When |destroyAll| is true, the ImageSource should also reset
-    // any local state so that decoding can begin again.
-    //
-    // Implementations that delete less than what's specified above waste
-    // memory.  Implementations that delete more may burn CPU re-decoding frames
-    // that could otherwise have been cached, or encounter errors if they're
-    // asked to decode frames they can't decode due to the loss of previous
-    // decoded frames.
-    //
-    // Callers should not call clear(false, n) and subsequently call
-    // createFrameImageAtIndex(m) with m &lt; n, unless they first call clear(true).
-    // This ensures that stateful ImageSources/decoders will work properly.
-    //
-    // The |data| and |allDataReceived| parameters should be supplied by callers
-    // who set |destroyAll| to true if they wish to be able to continue using
-    // the ImageSource.  This way implementations which choose to destroy their
-    // decoders in some cases can reconstruct them correctly.
-    void clear(bool destroyAll, size_t clearBeforeFrame = 0, SharedBuffer* data = nullptr, bool allDataReceived = false);
</del><ins>+    void destroyDecodedData(SharedBuffer* data, bool destroyAll = true, size_t count = 0);
+    bool destroyDecodedDataIfNecessary(SharedBuffer* data, bool destroyAll = true, size_t count = 0);
</ins><span class="cx"> 
</span><del>-    // FIXME: Remove the decoder() function from this class when caching the ImageFrame is moved outside BitmapImage.
-    ImageDecoder* decoder() const { return m_decoder.get(); }
-    bool initialized() const { return m_decoder.get(); }
</del><ins>+    bool ensureDecoderAvailable(SharedBuffer*);
+    bool isDecoderAvailable() const { return m_decoder.get(); }
</ins><span class="cx"> 
</span><span class="cx">     void setData(SharedBuffer* data, bool allDataReceived);
</span><del>-    
-    void setNeedsUpdateMetadata() { m_needsUpdateMetadata = true; }
</del><ins>+    bool dataChanged(SharedBuffer* data, bool allDataReceived);
</ins><span class="cx"> 
</span><ins>+    unsigned decodedSize() const { return m_frameCache.decodedSize(); }
+    bool isAllDataReceived();
+
+    // Image metadata which is calculated by the decoder or can deduced by the case of the memory NativeImage.
+    bool isSizeAvailable() { return m_frameCache.isSizeAvailable(); }
+    size_t frameCount() { return m_frameCache.frameCount(); }
+    RepetitionCount repetitionCount() { return m_frameCache.repetitionCount(); }
+    String filenameExtension() { return m_frameCache.filenameExtension(); }
+    Optional&lt;IntPoint&gt; hotSpot() { return m_frameCache.hotSpot(); }
+
+    // Image metadata which is calculated from the first ImageFrame.
+    IntSize size() { return m_frameCache.size(); }
+    IntSize sizeRespectingOrientation() { return m_frameCache.sizeRespectingOrientation(); }
+    Color singlePixelSolidColor() { return m_frameCache.singlePixelSolidColor(); }
+
+    // ImageFrame metadata which does not require caching the ImageFrame.
+    bool frameIsCompleteAtIndex(size_t index) { return m_frameCache.frameIsCompleteAtIndex(index); }
+    bool frameHasAlphaAtIndex(size_t index) { return m_frameCache.frameHasAlphaAtIndex(index); }
+    bool frameHasImageAtIndex(size_t index) { return m_frameCache.frameHasImageAtIndex(index); }
+    bool frameHasInvalidNativeImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { return m_frameCache.frameHasInvalidNativeImageAtIndex(index, subsamplingLevel); }
+    SubsamplingLevel frameSubsamplingLevelAtIndex(size_t index) { return m_frameCache.frameSubsamplingLevelAtIndex(index); }
+
+    // ImageFrame metadata which forces caching or re-caching the ImageFrame.
+    IntSize frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache.frameSizeAtIndex(index, subsamplingLevel); }
+    unsigned frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache.frameBytesAtIndex(index, subsamplingLevel); }
+    float frameDurationAtIndex(size_t index) { return m_frameCache.frameDurationAtIndex(index); }
+    ImageOrientation frameOrientationAtIndex(size_t index) { return m_frameCache.frameOrientationAtIndex(index); }
+    NativeImagePtr frameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel = SubsamplingLevel::Default) { return m_frameCache.frameImageAtIndex(index, subsamplingLevel); }
+
+    SubsamplingLevel maximumSubsamplingLevel();
</ins><span class="cx">     SubsamplingLevel subsamplingLevelForScale(float);
</span><span class="cx">     void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
</span><del>-    static size_t bytesDecodedToDetermineProperties();
-    
-    bool isSizeAvailable() const;
-    // Always original size, without subsampling.
-    IntSize size() const;
-    IntSize sizeRespectingOrientation() const;
</del><ins>+    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
</ins><span class="cx"> 
</span><del>-    size_t frameCount();
-    RepetitionCount repetitionCount();
-    String filenameExtension() const;
-    Optional&lt;IntPoint&gt; hotSpot() const;
-
-    bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
-    bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
-    bool frameAllowSubsamplingAtIndex(size_t) const;
-    
-    // Size of optionally subsampled frame.
-    IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
-    
-    // Return the number of bytes in the decoded frame. If the frame is not yet
-    // decoded then return 0.
-    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
-    
-    float frameDurationAtIndex(size_t);
-    ImageOrientation frameOrientationAtIndex(size_t) const; // EXIF image orientation
-    
-    // Callers should not call this after calling clear() with a higher index;
-    // see comments on clear() above.
-    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default);
-    
</del><span class="cx"> private:
</span><span class="cx">     void clearFrameBufferCache(size_t);
</span><del>-    SubsamplingLevel calculateMaximumSubsamplingLevel() const;
-    void updateMetadata();
-    void dump(TextStream&amp;) const;
</del><ins>+    void clear(bool destroyAll, size_t count, SharedBuffer* data);
+    void dump(TextStream&amp;);
</ins><span class="cx">     
</span><ins>+    ImageFrameCache m_frameCache;
</ins><span class="cx">     std::unique_ptr&lt;ImageDecoder&gt; m_decoder;
</span><del>-    
-    bool m_needsUpdateMetadata { false };
-    size_t m_frameCount { 0 };
-    Optional&lt;SubsamplingLevel&gt; m_maximumSubsamplingLevel { SubsamplingLevel::Default };
</del><span class="cx"> 
</span><ins>+    Optional&lt;SubsamplingLevel&gt; m_maximumSubsamplingLevel;
+
</ins><span class="cx">     // The default value of m_allowSubsampling should be the same as defaultImageSubsamplingEnabled in Settings.cpp
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     bool m_allowSubsampling { true };
</span><span class="lines">@@ -144,10 +112,14 @@
</span><span class="cx">     bool m_allowSubsampling { false };
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    AlphaOption m_alphaOption { AlphaPremultiplied };
-    GammaAndColorProfileOption m_gammaAndColorProfileOption { GammaAndColorProfileApplied };
</del><ins>+#if PLATFORM(IOS)
+    // FIXME: We should expose a setting to enable/disable progressive loading so that we can remove the PLATFORM(IOS)-guard.
+    double m_progressiveLoadChunkTime { 0 };
+    uint16_t m_progressiveLoadChunkCount { 0 };
+#endif
+
+    AlphaOption m_alphaOption { AlphaOption::Premultiplied };
+    GammaAndColorProfileOption m_gammaAndColorProfileOption { GammaAndColorProfileOption::Applied };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscairoGraphicsContext3DCairocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -211,12 +211,16 @@
</span><span class="cx">     if (!m_image)
</span><span class="cx">         return false;
</span><span class="cx">     // We need this to stay in scope because the native image is just a shallow copy of the data.
</span><del>-    m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
</del><ins>+    AlphaOption alphaOption = premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied;
+    GammaAndColorProfileOption gammaAndColorProfileOption = ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied;
+    m_decoder = new ImageSource(nullptr, alphaOption, gammaAndColorProfileOption);
+    
</ins><span class="cx">     if (!m_decoder)
</span><span class="cx">         return false;
</span><ins>+
</ins><span class="cx">     ImageSource&amp; decoder = *m_decoder;
</span><ins>+    m_alphaOp = AlphaDoNothing;
</ins><span class="cx"> 
</span><del>-    m_alphaOp = AlphaDoNothing;
</del><span class="cx">     if (m_image-&gt;data()) {
</span><span class="cx">         decoder.setData(m_image-&gt;data(), true);
</span><span class="cx">         if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgGraphicsContext3DCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -327,8 +327,7 @@
</span><span class="cx">         return false;
</span><span class="cx">     bool hasAlpha = !m_image-&gt;currentFrameKnownToBeOpaque();
</span><span class="cx">     if ((ignoreGammaAndColorProfile || (hasAlpha &amp;&amp; !premultiplyAlpha)) &amp;&amp; m_image-&gt;data()) {
</span><del>-        ImageSource decoder(ImageSource::AlphaNotPremultiplied,
-                            ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
</del><ins>+        ImageSource decoder(nullptr, AlphaOption::NotPremultiplied, ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied);
</ins><span class="cx">         decoder.setData(m_image-&gt;data(), true);
</span><span class="cx">         if (!decoder.frameCount())
</span><span class="cx">             return false;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageDecoderCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-ImageDecoder::ImageDecoder()
</del><ins>+ImageDecoder::ImageDecoder(AlphaOption, GammaAndColorProfileOption)
</ins><span class="cx"> {
</span><span class="cx">     m_nativeDecoder = adoptCF(CGImageSourceCreateIncremental(nullptr));
</span><span class="cx"> }
</span><span class="lines">@@ -154,13 +154,6 @@
</span><span class="cx">     &amp;&amp; CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelHeight);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-IntSize ImageDecoder::size() const
-{
-    if (m_size.isEmpty())
-        m_size = frameSizeAtIndex(0);
-    return m_size;
-}
-
</del><span class="cx"> size_t ImageDecoder::frameCount() const
</span><span class="cx"> {
</span><span class="cx">     return CGImageSourceGetCount(m_nativeDecoder.get());
</span><span class="lines">@@ -374,18 +367,15 @@
</span><span class="cx">     return maskedImage ? maskedImage : image;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ImageDecoder::setData(CFDataRef data, bool allDataReceived)
</del><ins>+void ImageDecoder::setData(SharedBuffer&amp; data, bool allDataReceived)
</ins><span class="cx"> {
</span><del>-    CGImageSourceUpdateData(m_nativeDecoder.get(), data, allDataReceived);
-}
</del><ins>+    m_isAllDataReceived = allDataReceived;
</ins><span class="cx"> 
</span><del>-void ImageDecoder::setData(SharedBuffer&amp; data, bool allDataReceived)
-{
</del><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge.
</span><span class="cx">     // We use SharedBuffer's ability to wrap itself inside CFData to get around this, ensuring that ImageIO is
</span><span class="cx">     // really looking at the SharedBuffer.
</span><del>-    setData(data.createCFData().get(), allDataReceived);
</del><ins>+    CGImageSourceUpdateData(m_nativeDecoder.get(), data.createCFData().get(), allDataReceived);
</ins><span class="cx"> #else
</span><span class="cx">     // Create a CGDataProvider to wrap the SharedBuffer.
</span><span class="cx">     data.ref();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageDecoderCGh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageDecoderCG.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -23,8 +23,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef ImageDecoderCG_h
-#define ImageDecoderCG_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageSourceCG.h&quot;
</span><span class="cx"> #include &quot;IntSize.h&quot;
</span><span class="lines">@@ -39,25 +38,21 @@
</span><span class="cx"> class ImageDecoder {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    ImageDecoder();
-    
-    static std::unique_ptr&lt;ImageDecoder&gt; create(const SharedBuffer&amp;, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption)
</del><ins>+    ImageDecoder(AlphaOption, GammaAndColorProfileOption);
+
+    static std::unique_ptr&lt;ImageDecoder&gt; create(const SharedBuffer&amp;, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     {
</span><del>-        return std::make_unique&lt;ImageDecoder&gt;();
</del><ins>+        return std::make_unique&lt;ImageDecoder&gt;(alphaOption, gammaAndColorProfileOption);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     static size_t bytesDecodedToDetermineProperties();
</span><del>-    
-    String filenameExtension() const;
</del><ins>+
</ins><span class="cx">     bool isSizeAvailable() const;
</span><del>-    
-    // Always original size, without subsampling.
-    IntSize size() const;
</del><span class="cx">     size_t frameCount() const;
</span><del>-
</del><span class="cx">     RepetitionCount repetitionCount() const;
</span><ins>+    String filenameExtension() const;
</ins><span class="cx">     Optional&lt;IntPoint&gt; hotSpot() const;
</span><del>-    
</del><ins>+
</ins><span class="cx">     IntSize frameSizeAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
</span><span class="cx">     bool frameIsCompleteAtIndex(size_t) const;
</span><span class="cx">     ImageOrientation frameOrientationAtIndex(size_t) const;
</span><span class="lines">@@ -69,16 +64,13 @@
</span><span class="cx">     
</span><span class="cx">     NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default) const;
</span><span class="cx">     
</span><del>-    void setData(CFDataRef, bool allDataReceived);
</del><span class="cx">     void setData(SharedBuffer&amp;, bool allDataReceived);
</span><del>-    
</del><ins>+    bool isAllDataReceived() const { return m_isAllDataReceived; }
</ins><span class="cx">     void clearFrameBufferCache(size_t) { }
</span><span class="cx">     
</span><span class="cx"> protected:
</span><del>-    mutable IntSize m_size;
</del><ins>+    bool m_isAllDataReceived { false };
</ins><span class="cx">     RetainPtr&lt;CGImageSourceRef&gt; m_nativeDecoder;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span><del>-
-#endif // ImageDecoderCG_h
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgPDFDocumentImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/cg/PDFDocumentImage.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">     void draw(GraphicsContext&amp;, const FloatRect&amp; dstRect, const FloatRect&amp; srcRect, CompositeOperator, BlendMode, ImageOrientationDescription) override;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Implement this to be less conservative.
</span><del>-    bool currentFrameKnownToBeOpaque() override { return false; }
</del><ins>+    bool currentFrameKnownToBeOpaque() const override { return false; }
</ins><span class="cx"> 
</span><span class="cx">     void dump(TextStream&amp;) const override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicseflGraphicsContext3DEflcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -249,7 +249,9 @@
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     // We need this to stay in scope because the native image is just a shallow copy of the data.
</span><del>-    m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
</del><ins>+    AlphaOption alphaOption = premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied;
+    GammaAndColorProfileOption gammaAndColorProfileOption = ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied;
+    m_decoder = new ImageSource(nullptr, alphaOption, gammaAndColorProfileOption);
</ins><span class="cx"> 
</span><span class="cx">     if (!m_decoder)
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacImageMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> void BitmapImage::invalidatePlatformData()
</span><span class="cx"> {
</span><del>-    if (m_frames.size() != 1)
</del><ins>+    if (frameCount() != 1)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx"> #if USE(APPKIT)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-std::unique_ptr&lt;ImageDecoder&gt; ImageDecoder::create(const SharedBuffer&amp; data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+std::unique_ptr&lt;ImageDecoder&gt; ImageDecoder::create(const SharedBuffer&amp; data, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx"> {
</span><span class="cx">     static const unsigned lengthOfLongestSignature = 14; // To wit: &quot;RIFF????WEBPVP&quot;
</span><span class="cx">     char contents[lengthOfLongestSignature];
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -28,8 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include &quot;ImageBackingStore.h&quot;
-#include &quot;ImageSource.h&quot;
</del><ins>+#include &quot;ImageFrame.h&quot;
</ins><span class="cx"> #include &quot;IntRect.h&quot;
</span><span class="cx"> #include &quot;IntSize.h&quot;
</span><span class="cx"> #include &quot;PlatformScreen.h&quot;
</span><span class="lines">@@ -42,8 +41,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-using ColorProfile = Vector&lt;char&gt;;
-
</del><span class="cx">     // ImageDecoder is a base for all format-specific decoders
</span><span class="cx">     // (e.g. JPEGImageDecoder).  This base manages the ImageFrame cache.
</span><span class="cx">     //
</span><span class="lines">@@ -53,9 +50,9 @@
</span><span class="cx">     class ImageDecoder {
</span><span class="cx">         WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">     public:
</span><del>-        ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
-            : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
-            , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
</del><ins>+        ImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
+            : m_premultiplyAlpha(alphaOption == AlphaOption::Premultiplied)
+            , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == GammaAndColorProfileOption::Ignored)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -66,7 +63,7 @@
</span><span class="cx">         // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
</span><span class="cx">         // we can't sniff a supported type from the provided data (possibly
</span><span class="cx">         // because there isn't enough data yet).
</span><del>-        static std::unique_ptr&lt;ImageDecoder&gt; create(const SharedBuffer&amp; data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        static std::unique_ptr&lt;ImageDecoder&gt; create(const SharedBuffer&amp; data, AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx"> 
</span><span class="cx">         virtual String filenameExtension() const = 0;
</span><span class="cx">         
</span><span class="lines">@@ -122,7 +119,7 @@
</span><span class="cx">         // possible), without decoding the individual frames.
</span><span class="cx">         // FIXME: Right now that has to be done by each subclass; factor the
</span><span class="cx">         // decode call out and use it here.
</span><del>-        virtual size_t frameCount() { return 1; }
</del><ins>+        virtual size_t frameCount() const { return 1; }
</ins><span class="cx"> 
</span><span class="cx">         virtual RepetitionCount repetitionCount() const { return RepetitionCountNone; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersbmpBMPImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -40,8 +40,7 @@
</span><span class="cx"> // don't pack).
</span><span class="cx"> static const size_t sizeOfFileHeader = 14;
</span><span class="cx"> 
</span><del>-BMPImageDecoder::BMPImageDecoder(ImageSource::AlphaOption alphaOption,
-                                 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+BMPImageDecoder::BMPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx">     , m_decodedOffset(0)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersbmpBMPImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -28,8 +28,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef BMPImageDecoder_h
-#define BMPImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;BMPImageReader.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -38,7 +37,7 @@
</span><span class="cx">     // This class decodes the BMP image format.
</span><span class="cx">     class BMPImageDecoder final : public ImageDecoder {
</span><span class="cx">     public:
</span><del>-        BMPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        BMPImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx"> 
</span><span class="cx">         // ImageDecoder
</span><span class="cx">         String filenameExtension() const override { return &quot;bmp&quot;; }
</span><span class="lines">@@ -80,5 +79,3 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersgifGIFImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-GIFImageDecoder::GIFImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+GIFImageDecoder::GIFImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -70,9 +70,9 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t GIFImageDecoder::frameCount()
</del><ins>+size_t GIFImageDecoder::frameCount() const
</ins><span class="cx"> {
</span><del>-    decode(std::numeric_limits&lt;unsigned&gt;::max(), GIFFrameCountQuery);
</del><ins>+    const_cast&lt;GIFImageDecoder*&gt;(this)-&gt;decode(std::numeric_limits&lt;unsigned&gt;::max(), GIFFrameCountQuery);
</ins><span class="cx">     return m_frameBufferCache.size();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersgifGIFImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -23,8 +23,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef GIFImageDecoder_h
-#define GIFImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageDecoder.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -35,7 +34,7 @@
</span><span class="cx">     // This class decodes the GIF image format.
</span><span class="cx">     class GIFImageDecoder final : public ImageDecoder {
</span><span class="cx">     public:
</span><del>-        GIFImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        GIFImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx">         virtual ~GIFImageDecoder();
</span><span class="cx"> 
</span><span class="cx">         enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
</span><span class="lines">@@ -45,7 +44,7 @@
</span><span class="cx">         void setData(SharedBuffer&amp; data, bool allDataReceived) override;
</span><span class="cx">         bool isSizeAvailable() override;
</span><span class="cx">         bool setSize(const IntSize&amp;) override;
</span><del>-        size_t frameCount() override;
</del><ins>+        size_t frameCount() const override;
</ins><span class="cx">         RepetitionCount repetitionCount() const override;
</span><span class="cx">         ImageFrame* frameBufferAtIndex(size_t index) override;
</span><span class="cx">         // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
</span><span class="lines">@@ -77,5 +76,3 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersgifGIFImageReadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -77,7 +77,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;string.h&gt;
</span><span class="cx"> #include &quot;GIFImageDecoder.h&quot;
</span><del>-#include &quot;ImageSource.h&quot;
</del><span class="cx"> 
</span><span class="cx"> using WebCore::GIFImageDecoder;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersgifGIFImageReaderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -35,8 +35,7 @@
</span><span class="cx">  *
</span><span class="cx">  * ***** END LICENSE BLOCK ***** */
</span><span class="cx"> 
</span><del>-#ifndef GIFImageReader_h
-#define GIFImageReader_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> // Define ourselves as the clientPtr.  Mozilla just hacked their C++ callback class into this old C decoder,
</span><span class="cx"> // so we will too.
</span><span class="lines">@@ -323,5 +322,3 @@
</span><span class="cx">     RefPtr&lt;WebCore::SharedBuffer&gt; m_data;
</span><span class="cx">     bool m_parseCompleted;
</span><span class="cx"> };
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersicoICOImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -44,8 +44,7 @@
</span><span class="cx"> static const size_t sizeOfDirectory = 6;
</span><span class="cx"> static const size_t sizeOfDirEntry = 16;
</span><span class="cx"> 
</span><del>-ICOImageDecoder::ICOImageDecoder(ImageSource::AlphaOption alphaOption,
-                                 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+ICOImageDecoder::ICOImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx">     , m_decodedOffset(0)
</span><span class="cx"> {
</span><span class="lines">@@ -95,14 +94,9 @@
</span><span class="cx">     return m_frameSize.isEmpty() ? ImageDecoder::setSize(size) : ((size == m_frameSize) || setFailed());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-size_t ICOImageDecoder::frameCount()
</del><ins>+size_t ICOImageDecoder::frameCount() const
</ins><span class="cx"> {
</span><del>-    decode(0, true);
-    if (m_frameBufferCache.isEmpty())
-        m_frameBufferCache.resize(m_dirEntries.size());
-    // CAUTION: We must not resize m_frameBufferCache again after this, as
-    // decodeAtIndex() may give a BMPImageReader a pointer to one of the
-    // entries.
</del><ins>+    const_cast&lt;ICOImageDecoder*&gt;(this)-&gt;decode(0, true);
</ins><span class="cx">     return m_frameBufferCache.size();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -180,6 +174,12 @@
</span><span class="cx">         m_bmpReaders[index] = nullptr;
</span><span class="cx">         m_pngDecoders[index] = nullptr;
</span><span class="cx">     }
</span><ins>+    
+    if (m_frameBufferCache.isEmpty())
+        m_frameBufferCache.resize(m_dirEntries.size());
+    // CAUTION: We must not resize m_frameBufferCache again after this, as
+    // decodeAtIndex() may give a BMPImageReader a pointer to one of the
+    // entries.
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ICOImageDecoder::decodeDirectory()
</span><span class="lines">@@ -217,8 +217,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (!m_pngDecoders[index]) {
</span><span class="cx">         m_pngDecoders[index] = std::make_unique&lt;
</span><del>-            PNGImageDecoder&gt;(m_premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied,
-                m_ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
</del><ins>+            PNGImageDecoder&gt;(m_premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied,
+                m_ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied);
</ins><span class="cx">         setDataForPNGDecoderAtIndex(index);
</span><span class="cx">     }
</span><span class="cx">     // Fail if the size the PNGImageDecoder calculated does not match the size
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersicoICOImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -28,8 +28,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef ICOImageDecoder_h
-#define ICOImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;BMPImageReader.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -40,7 +39,7 @@
</span><span class="cx">     // This class decodes the ICO and CUR image formats.
</span><span class="cx">     class ICOImageDecoder final : public ImageDecoder {
</span><span class="cx">     public:
</span><del>-        ICOImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        ICOImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx">         virtual ~ICOImageDecoder();
</span><span class="cx"> 
</span><span class="cx">         // ImageDecoder
</span><span class="lines">@@ -50,7 +49,7 @@
</span><span class="cx">         IntSize size() override;
</span><span class="cx">         IntSize frameSizeAtIndex(size_t, SubsamplingLevel) override;
</span><span class="cx">         bool setSize(const IntSize&amp;) override;
</span><del>-        size_t frameCount() override;
</del><ins>+        size_t frameCount() const override;
</ins><span class="cx">         ImageFrame* frameBufferAtIndex(size_t) override;
</span><span class="cx">         // CAUTION: setFailed() deletes all readers and decoders.  Be careful to
</span><span class="cx">         // avoid accessing deleted memory, especially when calling this from
</span><span class="lines">@@ -151,5 +150,3 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersjpegJPEGImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -501,8 +501,7 @@
</span><span class="cx">     src-&gt;decoder-&gt;decoder()-&gt;jpegComplete();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption,
-                                   ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecodersjpegJPEGImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -24,8 +24,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef JPEGImageDecoder_h
-#define JPEGImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageDecoder.h&quot;
</span><span class="cx"> #include &lt;stdio.h&gt; // Needed by jpeglib.h for FILE.
</span><span class="lines">@@ -44,7 +43,7 @@
</span><span class="cx">     // This class decodes the JPEG image format.
</span><span class="cx">     class JPEGImageDecoder final : public ImageDecoder {
</span><span class="cx">     public:
</span><del>-        JPEGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        JPEGImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx">         virtual ~JPEGImageDecoder();
</span><span class="cx"> 
</span><span class="cx">         // ImageDecoder
</span><span class="lines">@@ -84,5 +83,3 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecoderspngPNGImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -193,7 +193,7 @@
</span><span class="cx">     png_bytep m_interlaceBuffer;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-PNGImageDecoder::PNGImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+PNGImageDecoder::PNGImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx">     , m_doNothingOnFailure(false)
</span><span class="cx">     , m_currentFrame(0)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecoderspngPNGImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -23,8 +23,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef PNGImageDecoder_h
-#define PNGImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageDecoder.h&quot;
</span><span class="cx"> #if ENABLE(APNG)
</span><span class="lines">@@ -38,13 +37,13 @@
</span><span class="cx">     // This class decodes the PNG image format.
</span><span class="cx">     class PNGImageDecoder final : public ImageDecoder {
</span><span class="cx">     public:
</span><del>-        PNGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+        PNGImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx">         virtual ~PNGImageDecoder();
</span><span class="cx"> 
</span><span class="cx">         // ImageDecoder
</span><span class="cx">         String filenameExtension() const override { return &quot;png&quot;; }
</span><span class="cx"> #if ENABLE(APNG)
</span><del>-        size_t frameCount() override { return m_frameCount; }
</del><ins>+        size_t frameCount() const override { return m_frameCount; }
</ins><span class="cx">         RepetitionCount repetitionCount() const override { return m_playCount-1; }
</span><span class="cx"> #endif
</span><span class="cx">         bool isSizeAvailable() override;
</span><span class="lines">@@ -130,5 +129,3 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecoderswebpWEBPImageDecodercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -45,8 +45,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption,
-                                   ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
</del><ins>+WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
</ins><span class="cx">     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
</span><span class="cx">     , m_decoder(0)
</span><span class="cx">     , m_hasAlpha(false)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformimagedecoderswebpWEBPImageDecoderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -26,8 +26,7 @@
</span><span class="cx">  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef WEBPImageDecoder_h
-#define WEBPImageDecoder_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;ImageDecoder.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -39,7 +38,7 @@
</span><span class="cx"> 
</span><span class="cx"> class WEBPImageDecoder final : public ImageDecoder {
</span><span class="cx"> public:
</span><del>-    WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
</del><ins>+    WEBPImageDecoder(AlphaOption, GammaAndColorProfileOption);
</ins><span class="cx">     virtual ~WEBPImageDecoder();
</span><span class="cx"> 
</span><span class="cx">     String filenameExtension() const override { return &quot;webp&quot;; }
</span><span class="lines">@@ -59,5 +58,3 @@
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><del>-
-#endif
</del></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsSVGImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/SVGImage.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/SVGImage.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/svg/graphics/SVGImage.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">     void destroyDecodedData(bool) final { }
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Implement this to be less conservative.
</span><del>-    bool currentFrameKnownToBeOpaque() final { return false; }
</del><ins>+    bool currentFrameKnownToBeOpaque() const final { return false; }
</ins><span class="cx"> 
</span><span class="cx">     void dump(TextStream&amp;) const final;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsSVGImageForContainerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/SVGImageForContainer.h (206480 => 206481)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/SVGImageForContainer.h        2016-09-28 01:02:00 UTC (rev 206480)
+++ trunk/Source/WebCore/svg/graphics/SVGImageForContainer.h        2016-09-28 01:06:57 UTC (rev 206481)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">     void drawPattern(GraphicsContext&amp;, const FloatRect&amp;, const AffineTransform&amp;, const FloatPoint&amp;, const FloatSize&amp;, CompositeOperator, const FloatRect&amp;, BlendMode) final;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Implement this to be less conservative.
</span><del>-    bool currentFrameKnownToBeOpaque() final { return false; }
</del><ins>+    bool currentFrameKnownToBeOpaque() const final { return false; }
</ins><span class="cx"> 
</span><span class="cx">     NativeImagePtr nativeImageForCurrentFrame() final;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>