<!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>[172348] 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/172348">172348</a></dd>
<dt>Author</dt> <dd>simon.fraser@apple.com</dd>
<dt>Date</dt> <dd>2014-08-08 11:55:51 -0700 (Fri, 08 Aug 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Clean up image subsampling code, make it less iOS-specific
https://bugs.webkit.org/show_bug.cgi?id=134916
Reviewed by Dean Jackson.
Compile the image subsampling code on both Mac and iOS, and make it more platform
neutral in general. Add a setting to allow it to be enabled on Mac for testing.
The most significant changes are in ImageSourceCG and BitmapImageCG. CG's ImageSource
is no longer stateful with respect to subsampling; its functions take a SubsamplingLevel
when appropriate. CG's BitmapImage now determines which level of subsampling to use
for a given frame, storing the subsampling level in the frame data. It can replace
an aggressively subsampled frame with a less subsampled frame if necessary.
To reduce the chances of subsampling affecting rendering, BitmapImage::size() now
always returns the non-subsampled size; subsampling is strictly internal to BitmapImage.
BitmapImage::draw() takes care of scaling the srcRect for subsampled images.
iOS had a code path that enabled caching of frame metadata in BitmapImage without
actually decoding the frame; make this cross-platform.
Fix a couple of issues in the original pathc: remove a log, and ImageSource::allowSubsamplingOfFrameAtIndex()
return false.
* WebCore.exp.in: Changed signature for GraphicsContext::drawNativeImage().
* WebCore.xcodeproj/project.pbxproj: Added ImageSource.cpp, which is not built
for Cocoa but useful for reference.
* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::imageSizeForRenderer): Remove iOS-specific subsampling code.
(WebCore::CachedImage::createImage): Call setAllowSubsampling() on the image if we
can get to Settings (m_loader is null for image documents).
(WebCore::CachedImage::currentFrameKnownToBeOpaque): This forced decode always
caused creation of the non-subsampled image, so remove it. There's no reason to
eagerly decode the frame here.
* loader/cache/CachedImage.h: Fix comment.
* page/Settings.cpp: Add defaultImageSubsamplingEnabled, true for iOS and false for Mac.
* page/Settings.in: Added imageSubsamplingEnabled.
* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::BitmapImage): Init some more things. Default m_allowSubsampling to
true for iOS to catch images created in code paths where we can't get to Settings.
(WebCore::BitmapImage::haveFrameAtIndex): Handy helper.
(WebCore::BitmapImage::cacheFrame): Now takes the subsampling level and whether to cache
just metadata, or also the frame.
(WebCore::BitmapImage::didDecodeProperties): No need to store originalSize.
(WebCore::BitmapImage::updateSize): When we get the size for the first time, call
determineMinimumSubsamplingLevel() to choose a reasonable subsampling level which takes
platform-specific limits into account.
(WebCore::BitmapImage::dataChanged): Comment.
(WebCore::BitmapImage::ensureFrameIsCached): Take ImageFrameCaching into account.
(WebCore::BitmapImage::frameAtIndex): Choose a subsampling level given the scale,
then determine if we can use the currently cached frame, or whether we should resample.
(WebCore::BitmapImage::frameIsCompleteAtIndex): Caching m_isComplete is now done when caching
frame metadata.
(WebCore::BitmapImage::frameDurationAtIndex):
(WebCore::BitmapImage::frameHasAlphaAtIndex): The 'true' return is the safe return value.
(WebCore::BitmapImage::frameOrientationAtIndex): Caching m_orientation is now done when caching
frame metadata.
(WebCore::BitmapImage::cacheFrameInfo): Deleted.
(WebCore::BitmapImage::originalSize): Deleted.
(WebCore::BitmapImage::originalSizeRespectingOrientation): Deleted.
(WebCore::BitmapImage::currentFrameSize): Deleted.
(WebCore::BitmapImage::ensureFrameInfoIsCached): Deleted.
* platform/graphics/BitmapImage.h:
(WebCore::FrameData::FrameData):
* platform/graphics/GraphicsContext.h: No need to pass a scale param now.
* platform/graphics/ImageSource.cpp: Non-Cocoa changes.
(WebCore::ImageSource::subsamplingLevelForScale):
(WebCore::ImageSource::allowSubsamplingOfFrameAtIndex):
(WebCore::ImageSource::size):
(WebCore::ImageSource::frameSizeAtIndex):
(WebCore::ImageSource::createFrameAtIndex):
(WebCore::ImageSource::frameBytesAtIndex):
* platform/graphics/ImageSource.h: No longer stores subsampling state.
(WebCore::ImageSource::isSubsampled): Deleted.
* platform/graphics/cairo/BitmapImageCairo.cpp:
(WebCore::BitmapImage::determineMinimumSubsamplingLevel):
* platform/graphics/cg/BitmapImageCG.cpp:
(WebCore::FrameData::clear):
(WebCore::BitmapImage::BitmapImage): Init more members.
(WebCore::BitmapImage::determineMinimumSubsamplingLevel): Choose a minimum subsampling
level for the platform (subsample until the image area falls under a threshold).
(WebCore::BitmapImage::checkForSolidColor): Don't bother decoding frames if the image
is not 1x1. Also take care not to decode a non-subsampled image.
(WebCore::BitmapImage::draw): The actual bug fix is here; remove logic that
computed srcRectForCurrentFrame from m_size and m_originalSize; for some callers
srcRect was computed using the pre-subsampled size, and for others it was the subsampled size.
Instead, scale srcRect by mapping between the non-subsampled size, and the size of the CGImageRef
which is affected by subsampling.
(WebCore::BitmapImage::copyUnscaledFrameAtIndex):
* platform/graphics/cg/GraphicsContext3DCG.cpp:
(WebCore::GraphicsContext3D::ImageExtractor::extractImage): Remove #ifdeffed code.
(WebCore::GraphicsContext3D::paintToCanvas):
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContext::drawNativeImage): No more weird scaling!
* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::ImageBuffer::draw):
* platform/graphics/cg/ImageSourceCG.cpp:
(WebCore::ImageSource::ImageSource):
(WebCore::createImageSourceOptions): Helper that always returns a new CFDictionaryRef.
(WebCore::imageSourceOptions): If not subsampling, return the cached CFDictionaryRef, otherwise
make a new options dict and return it.
(WebCore::ImageSource::subsamplingLevelForScale): Helper that returns a subsampling level
between 0 and 3 given a scale.
(WebCore::ImageSource::isSizeAvailable): SkipMetadata is a default value for the param now.
(WebCore::ImageSource::allowSubsamplingOfFrameAtIndex): We turn off subsampling for progressive
JPEGs because of a bug, so need this to know if a frame should be subsampled.
(WebCore::ImageSource::frameSizeAtIndex): The looping to find a subsampling level is now in BitmapImageCG.
(WebCore::ImageSource::orientationAtIndex):
(WebCore::ImageSource::size): Always use a subsampling level of 0 for size().
(WebCore::ImageSource::getHotSpot):
(WebCore::ImageSource::repetitionCount):
(WebCore::ImageSource::createFrameAtIndex): The caller mapped a scale to a level.
(WebCore::ImageSource::frameDurationAtIndex):
(WebCore::ImageSource::frameBytesAtIndex):
(WebCore::ImageSource::imageSourceOptions): Deleted.
(WebCore::ImageSource::originalSize): Deleted.
* platform/graphics/mac/ImageMac.mm:
(WebCore::BitmapImage::invalidatePlatformData): 0 -> nullptr
* platform/graphics/wince/ImageWinCE.cpp:
(WebCore::BitmapImage::determineMinimumSubsamplingLevel):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedImagecpp">trunk/Source/WebCore/loader/cache/CachedImage.cpp</a></li>
<li><a href="#trunkSourceWebCoreloadercacheCachedImageh">trunk/Source/WebCore/loader/cache/CachedImage.h</a></li>
<li><a href="#trunkSourceWebCorepageSettingscpp">trunk/Source/WebCore/page/Settings.cpp</a></li>
<li><a href="#trunkSourceWebCorepageSettingsin">trunk/Source/WebCore/page/Settings.in</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="#trunkSourceWebCoreplatformgraphicsGraphicsContexth">trunk/Source/WebCore/platform/graphics/GraphicsContext.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="#trunkSourceWebCoreplatformgraphicscairoBitmapImageCairocpp">trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgBitmapImageCGcpp">trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgGraphicsContext3DCGcpp">trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgGraphicsContextCGcpp">trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageBufferCGcpp">trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscgImageSourceCGcpp">trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsmacImageMacmm">trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicswinceImageWinCEcpp">trunk/Source/WebCore/platform/graphics/wince/ImageWinCE.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/ChangeLog        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -1,3 +1,126 @@
</span><ins>+2014-08-08 Simon Fraser <simon.fraser@apple.com>
+
+ Clean up image subsampling code, make it less iOS-specific
+ https://bugs.webkit.org/show_bug.cgi?id=134916
+
+ Reviewed by Dean Jackson.
+
+ Compile the image subsampling code on both Mac and iOS, and make it more platform
+ neutral in general. Add a setting to allow it to be enabled on Mac for testing.
+
+ The most significant changes are in ImageSourceCG and BitmapImageCG. CG's ImageSource
+ is no longer stateful with respect to subsampling; its functions take a SubsamplingLevel
+ when appropriate. CG's BitmapImage now determines which level of subsampling to use
+ for a given frame, storing the subsampling level in the frame data. It can replace
+ an aggressively subsampled frame with a less subsampled frame if necessary.
+
+ To reduce the chances of subsampling affecting rendering, BitmapImage::size() now
+ always returns the non-subsampled size; subsampling is strictly internal to BitmapImage.
+ BitmapImage::draw() takes care of scaling the srcRect for subsampled images.
+
+ iOS had a code path that enabled caching of frame metadata in BitmapImage without
+ actually decoding the frame; make this cross-platform.
+
+ Fix a couple of issues in the original pathc: remove a log, and ImageSource::allowSubsamplingOfFrameAtIndex()
+ return false.
+
+ * WebCore.exp.in: Changed signature for GraphicsContext::drawNativeImage().
+ * WebCore.xcodeproj/project.pbxproj: Added ImageSource.cpp, which is not built
+ for Cocoa but useful for reference.
+ * loader/cache/CachedImage.cpp:
+ (WebCore::CachedImage::imageSizeForRenderer): Remove iOS-specific subsampling code.
+ (WebCore::CachedImage::createImage): Call setAllowSubsampling() on the image if we
+ can get to Settings (m_loader is null for image documents).
+ (WebCore::CachedImage::currentFrameKnownToBeOpaque): This forced decode always
+ caused creation of the non-subsampled image, so remove it. There's no reason to
+ eagerly decode the frame here.
+ * loader/cache/CachedImage.h: Fix comment.
+ * page/Settings.cpp: Add defaultImageSubsamplingEnabled, true for iOS and false for Mac.
+ * page/Settings.in: Added imageSubsamplingEnabled.
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::BitmapImage): Init some more things. Default m_allowSubsampling to
+ true for iOS to catch images created in code paths where we can't get to Settings.
+ (WebCore::BitmapImage::haveFrameAtIndex): Handy helper.
+ (WebCore::BitmapImage::cacheFrame): Now takes the subsampling level and whether to cache
+ just metadata, or also the frame.
+ (WebCore::BitmapImage::didDecodeProperties): No need to store originalSize.
+ (WebCore::BitmapImage::updateSize): When we get the size for the first time, call
+ determineMinimumSubsamplingLevel() to choose a reasonable subsampling level which takes
+ platform-specific limits into account.
+ (WebCore::BitmapImage::dataChanged): Comment.
+ (WebCore::BitmapImage::ensureFrameIsCached): Take ImageFrameCaching into account.
+ (WebCore::BitmapImage::frameAtIndex): Choose a subsampling level given the scale,
+ then determine if we can use the currently cached frame, or whether we should resample.
+ (WebCore::BitmapImage::frameIsCompleteAtIndex): Caching m_isComplete is now done when caching
+ frame metadata.
+ (WebCore::BitmapImage::frameDurationAtIndex):
+ (WebCore::BitmapImage::frameHasAlphaAtIndex): The 'true' return is the safe return value.
+ (WebCore::BitmapImage::frameOrientationAtIndex): Caching m_orientation is now done when caching
+ frame metadata.
+ (WebCore::BitmapImage::cacheFrameInfo): Deleted.
+ (WebCore::BitmapImage::originalSize): Deleted.
+ (WebCore::BitmapImage::originalSizeRespectingOrientation): Deleted.
+ (WebCore::BitmapImage::currentFrameSize): Deleted.
+ (WebCore::BitmapImage::ensureFrameInfoIsCached): Deleted.
+ * platform/graphics/BitmapImage.h:
+ (WebCore::FrameData::FrameData):
+ * platform/graphics/GraphicsContext.h: No need to pass a scale param now.
+ * platform/graphics/ImageSource.cpp: Non-Cocoa changes.
+ (WebCore::ImageSource::subsamplingLevelForScale):
+ (WebCore::ImageSource::allowSubsamplingOfFrameAtIndex):
+ (WebCore::ImageSource::size):
+ (WebCore::ImageSource::frameSizeAtIndex):
+ (WebCore::ImageSource::createFrameAtIndex):
+ (WebCore::ImageSource::frameBytesAtIndex):
+ * platform/graphics/ImageSource.h: No longer stores subsampling state.
+ (WebCore::ImageSource::isSubsampled): Deleted.
+ * platform/graphics/cairo/BitmapImageCairo.cpp:
+ (WebCore::BitmapImage::determineMinimumSubsamplingLevel):
+ * platform/graphics/cg/BitmapImageCG.cpp:
+ (WebCore::FrameData::clear):
+ (WebCore::BitmapImage::BitmapImage): Init more members.
+ (WebCore::BitmapImage::determineMinimumSubsamplingLevel): Choose a minimum subsampling
+ level for the platform (subsample until the image area falls under a threshold).
+ (WebCore::BitmapImage::checkForSolidColor): Don't bother decoding frames if the image
+ is not 1x1. Also take care not to decode a non-subsampled image.
+ (WebCore::BitmapImage::draw): The actual bug fix is here; remove logic that
+ computed srcRectForCurrentFrame from m_size and m_originalSize; for some callers
+ srcRect was computed using the pre-subsampled size, and for others it was the subsampled size.
+ Instead, scale srcRect by mapping between the non-subsampled size, and the size of the CGImageRef
+ which is affected by subsampling.
+ (WebCore::BitmapImage::copyUnscaledFrameAtIndex):
+ * platform/graphics/cg/GraphicsContext3DCG.cpp:
+ (WebCore::GraphicsContext3D::ImageExtractor::extractImage): Remove #ifdeffed code.
+ (WebCore::GraphicsContext3D::paintToCanvas):
+ * platform/graphics/cg/GraphicsContextCG.cpp:
+ (WebCore::GraphicsContext::drawNativeImage): No more weird scaling!
+ * platform/graphics/cg/ImageBufferCG.cpp:
+ (WebCore::ImageBuffer::draw):
+ * platform/graphics/cg/ImageSourceCG.cpp:
+ (WebCore::ImageSource::ImageSource):
+ (WebCore::createImageSourceOptions): Helper that always returns a new CFDictionaryRef.
+ (WebCore::imageSourceOptions): If not subsampling, return the cached CFDictionaryRef, otherwise
+ make a new options dict and return it.
+ (WebCore::ImageSource::subsamplingLevelForScale): Helper that returns a subsampling level
+ between 0 and 3 given a scale.
+ (WebCore::ImageSource::isSizeAvailable): SkipMetadata is a default value for the param now.
+ (WebCore::ImageSource::allowSubsamplingOfFrameAtIndex): We turn off subsampling for progressive
+ JPEGs because of a bug, so need this to know if a frame should be subsampled.
+ (WebCore::ImageSource::frameSizeAtIndex): The looping to find a subsampling level is now in BitmapImageCG.
+ (WebCore::ImageSource::orientationAtIndex):
+ (WebCore::ImageSource::size): Always use a subsampling level of 0 for size().
+ (WebCore::ImageSource::getHotSpot):
+ (WebCore::ImageSource::repetitionCount):
+ (WebCore::ImageSource::createFrameAtIndex): The caller mapped a scale to a level.
+ (WebCore::ImageSource::frameDurationAtIndex):
+ (WebCore::ImageSource::frameBytesAtIndex):
+ (WebCore::ImageSource::imageSourceOptions): Deleted.
+ (WebCore::ImageSource::originalSize): Deleted.
+ * platform/graphics/mac/ImageMac.mm:
+ (WebCore::BitmapImage::invalidatePlatformData): 0 -> nullptr
+ * platform/graphics/wince/ImageWinCE.cpp:
+ (WebCore::BitmapImage::determineMinimumSubsamplingLevel):
+
</ins><span class="cx"> 2014-08-08 Alex Christensen <achristensen@webkit.org>
</span><span class="cx">
</span><span class="cx"> Progress towards using CMake on Mac.
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/WebCore.exp.in        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -521,6 +521,7 @@
</span><span class="cx"> __ZN7WebCore15GraphicsContext11clearShadowEv
</span><span class="cx"> __ZN7WebCore15GraphicsContext12setFillColorERKNS_5ColorENS_10ColorSpaceE
</span><span class="cx"> __ZN7WebCore15GraphicsContext14setStrokeColorERKNS_5ColorENS_10ColorSpaceE
</span><ins>+__ZN7WebCore15GraphicsContext15drawNativeImageEP7CGImageRKNS_9FloatSizeENS_10ColorSpaceERKNS_9FloatRectES9_NS_17CompositeOperatorENS_9BlendModeENS_16ImageOrientationE
</ins><span class="cx"> __ZN7WebCore15GraphicsContext15setFillGradientEN3WTF10PassRefPtrINS_8GradientEEE
</span><span class="cx"> __ZN7WebCore15GraphicsContext18setShouldAntialiasEb
</span><span class="cx"> __ZN7WebCore15GraphicsContext19setIsCALayerContextEb
</span><span class="lines">@@ -2240,7 +2241,6 @@
</span><span class="cx"> __ZN7WebCore13getRawCookiesERKNS_21NetworkStorageSessionERKNS_3URLES5_RN3WTF6VectorINS_6CookieELm0ENS6_15CrashOnOverflowEEE
</span><span class="cx"> __ZN7WebCore13toDeviceSpaceERKNS_9FloatRectEP8NSWindow
</span><span class="cx"> __ZN7WebCore14cookiesEnabledERKNS_21NetworkStorageSessionERKNS_3URLES5_
</span><del>-__ZN7WebCore15GraphicsContext15drawNativeImageEP7CGImageRKNS_9FloatSizeENS_10ColorSpaceERKNS_9FloatRectES9_fNS_17CompositeOperatorENS_9BlendModeENS_16ImageOrientationE
</del><span class="cx"> __ZN7WebCore15GraphicsContextC1EP9CGContext
</span><span class="cx"> __ZN7WebCore15ResourceRequest41updateFromDelegatePreservingOldPropertiesERKS0_
</span><span class="cx"> __ZN7WebCore16FontPlatformDataC1EP6NSFontfbbbNS_15FontOrientationENS_16FontWidthVariantE
</span><span class="lines">@@ -2591,7 +2591,6 @@
</span><span class="cx"> __ZN7WebCore15DatabaseTracker7trackerEv
</span><span class="cx"> __ZN7WebCore15GraphicsContext12drawBidiTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPointENS1_24CustomFontNotReadyActionEPNS_10BidiStatusEi
</span><span class="cx"> __ZN7WebCore15GraphicsContext15drawLineForTextERKNS_10FloatPointEfbb
</span><del>-__ZN7WebCore15GraphicsContext15drawNativeImageEP7CGImageRKNS_9FloatSizeENS_10ColorSpaceERKNS_9FloatRectES9_fNS_17CompositeOperatorENS_9BlendModeENS_16ImageOrientationE
</del><span class="cx"> __ZN7WebCore15GraphicsContext22setEmojiDrawingEnabledEb
</span><span class="cx"> __ZN7WebCore15GraphicsContext23setIsAcceleratedContextEb
</span><span class="cx"> __ZN7WebCore15GraphicsContextC1EP9CGContextb
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -473,6 +473,7 @@
</span><span class="cx">                 0F1774801378B772009DA76A /* ScrollAnimatorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F17747E1378B771009DA76A /* ScrollAnimatorIOS.h */; };
</span><span class="cx">                 0F1774811378B772009DA76A /* ScrollAnimatorIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F17747F1378B772009DA76A /* ScrollAnimatorIOS.mm */; };
</span><span class="cx">                 0F29C16E1300C2E2002D794E /* AccessibilityAllInOne.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F29C16D1300C2E2002D794E /* AccessibilityAllInOne.cpp */; };
</span><ins>+                0F3C725E1974874B00AEDD0C /* ImageSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3C725D1974874B00AEDD0C /* ImageSource.cpp */; };
</ins><span class="cx">                 0F3DD44F12F5EA1B000D9190 /* ShadowBlur.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3DD44D12F5EA1B000D9190 /* ShadowBlur.cpp */; };
</span><span class="cx">                 0F3DD45012F5EA1B000D9190 /* ShadowBlur.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3DD44E12F5EA1B000D9190 /* ShadowBlur.h */; };
</span><span class="cx">                 0F3F0E59157030C3006DA57F /* RenderGeometryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3F0E57157030C3006DA57F /* RenderGeometryMap.cpp */; };
</span><span class="lines">@@ -7407,6 +7408,7 @@
</span><span class="cx">                 0F17747E1378B771009DA76A /* ScrollAnimatorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScrollAnimatorIOS.h; path = ios/ScrollAnimatorIOS.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F17747F1378B772009DA76A /* ScrollAnimatorIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScrollAnimatorIOS.mm; path = ios/ScrollAnimatorIOS.mm; sourceTree = "<group>"; };
</span><span class="cx">                 0F29C16D1300C2E2002D794E /* AccessibilityAllInOne.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AccessibilityAllInOne.cpp; sourceTree = "<group>"; };
</span><ins>+                0F3C725D1974874B00AEDD0C /* ImageSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageSource.cpp; sourceTree = "<group>"; };
</ins><span class="cx">                 0F3DD44D12F5EA1B000D9190 /* ShadowBlur.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowBlur.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F3DD44E12F5EA1B000D9190 /* ShadowBlur.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowBlur.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F3F0E57157030C3006DA57F /* RenderGeometryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderGeometryMap.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -20459,6 +20461,7 @@
</span><span class="cx">                                 A8748D6612CC3763001FBA41 /* ImageOrientation.h */,
</span><span class="cx">                                 49291E4A134172C800E753DE /* ImageRenderingMode.h */,
</span><span class="cx">                                 B27535430B053814002CE64F /* ImageSource.h */,
</span><ins>+                                0F3C725D1974874B00AEDD0C /* ImageSource.cpp */,
</ins><span class="cx">                                 07941793166EA04E009416C2 /* InbandTextTrackPrivate.h */,
</span><span class="cx">                                 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */,
</span><span class="cx">                                 2D46F04D17B96FBD005647F0 /* IntPoint.cpp */,
</span><span class="lines">@@ -29402,6 +29405,7 @@
</span><span class="cx">                                 97BC6A441505F081001B74AC /* SQLResultSetRowList.cpp in Sources */,
</span><span class="cx">                                 97BC6A471505F081001B74AC /* SQLStatement.cpp in Sources */,
</span><span class="cx">                                 FE8A674716CDD19E00930BF8 /* SQLStatementBackend.cpp in Sources */,
</span><ins>+                                0F3C725E1974874B00AEDD0C /* ImageSource.cpp in Sources */,
</ins><span class="cx">                                 97BC6A4D1505F081001B74AC /* SQLStatementSync.cpp in Sources */,
</span><span class="cx">                                 97BC6A4F1505F081001B74AC /* SQLTransaction.cpp in Sources */,
</span><span class="cx">                                 FEE1811316C319E800084849 /* SQLTransactionBackend.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedImage.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/loader/cache/CachedImage.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -289,16 +289,7 @@
</span><span class="cx"> }
</span><span class="cx"> #else
</span><span class="cx"> if (m_image->isBitmapImage() && (renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation))
</span><del>-#if !PLATFORM(IOS)
</del><span class="cx"> imageSize = LayoutSize(toBitmapImage(m_image.get())->sizeRespectingOrientation());
</span><del>-#else
- {
- // On iOS, the image may have been subsampled to accommodate our size restrictions. However
- // we should tell the renderer what the original size was.
- imageSize = LayoutSize(toBitmapImage(m_image.get())->originalSizeRespectingOrientation());
- } else if (m_image->isBitmapImage())
- imageSize = LayoutSize(toBitmapImage(m_image.get())->originalSize());
-#endif // !PLATFORM(IOS)
</del><span class="cx"> #endif // ENABLE(CSS_IMAGE_ORIENTATION)
</span><span class="cx">
</span><span class="cx"> else if (m_image->isSVGImage() && sizeType == UsedSize) {
</span><span class="lines">@@ -352,6 +343,7 @@
</span><span class="cx"> // Create the image if it doesn't yet exist.
</span><span class="cx"> if (m_image)
</span><span class="cx"> return;
</span><ins>+
</ins><span class="cx"> #if USE(CG) && !USE(WEBKIT_IMAGE_DECODERS)
</span><span class="cx"> else if (m_response.mimeType() == "application/pdf")
</span><span class="cx"> m_image = PDFDocumentImage::create(this);
</span><span class="lines">@@ -360,8 +352,10 @@
</span><span class="cx"> RefPtr<SVGImage> svgImage = SVGImage::create(this);
</span><span class="cx"> m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.get());
</span><span class="cx"> m_image = svgImage.release();
</span><del>- } else
</del><ins>+ } else {
</ins><span class="cx"> m_image = BitmapImage::create(this);
</span><ins>+ toBitmapImage(m_image.get())->setAllowSubsampling(m_loader && m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled());
+ }
</ins><span class="cx">
</span><span class="cx"> if (m_image) {
</span><span class="cx"> // Send queued container size requests.
</span><span class="lines">@@ -518,8 +512,6 @@
</span><span class="cx"> bool CachedImage::currentFrameKnownToBeOpaque(const RenderElement* renderer)
</span><span class="cx"> {
</span><span class="cx"> Image* image = imageForRenderer(renderer);
</span><del>- if (image->isBitmapImage())
- image->nativeImageForCurrentFrame(); // force decode
</del><span class="cx"> return image->currentFrameKnownToBeOpaque();
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreloadercacheCachedImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/loader/cache/CachedImage.h        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx"> Image* image(); // Returns the nullImage() if the image is not available yet.
</span><span class="cx"> Image* imageForRenderer(const RenderObject*); // Returns the nullImage() if the image is not available yet.
</span><span class="cx"> bool hasImage() const { return m_image.get(); }
</span><del>- bool currentFrameKnownToBeOpaque(const RenderElement*); // Side effect: ensures decoded image is in cache, therefore should only be called when about to draw the image.
</del><ins>+ bool currentFrameKnownToBeOpaque(const RenderElement*);
</ins><span class="cx">
</span><span class="cx"> std::pair<Image*, float> brokenImage(float deviceScaleFactor) const; // Returns an image and the image's resolution scale factor.
</span><span class="cx"> bool willPaintBrokenImage() const;
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/page/Settings.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -127,6 +127,7 @@
</span><span class="cx"> static const bool defaultMediaPlaybackAllowsInline = false;
</span><span class="cx"> static const bool defaultMediaPlaybackRequiresUserGesture = true;
</span><span class="cx"> static const bool defaultShouldRespectImageOrientation = true;
</span><ins>+static const bool defaultImageSubsamplingEnabled = true;
</ins><span class="cx"> static const bool defaultScrollingTreeIncludesFrames = true;
</span><span class="cx"> #else
</span><span class="cx"> static const bool defaultFixedPositionCreatesStackingContext = false;
</span><span class="lines">@@ -135,6 +136,7 @@
</span><span class="cx"> static const bool defaultMediaPlaybackAllowsInline = true;
</span><span class="cx"> static const bool defaultMediaPlaybackRequiresUserGesture = false;
</span><span class="cx"> static const bool defaultShouldRespectImageOrientation = false;
</span><ins>+static const bool defaultImageSubsamplingEnabled = false;
</ins><span class="cx"> static const bool defaultScrollingTreeIncludesFrames = false;
</span><span class="cx"> #endif
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingsin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.in (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.in        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/page/Settings.in        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -141,6 +141,7 @@
</span><span class="cx"> needsIsLoadingInAPISenseQuirk initial=false
</span><span class="cx">
</span><span class="cx"> shouldRespectImageOrientation initial=defaultShouldRespectImageOrientation
</span><ins>+imageSubsamplingEnabled initial=defaultImageSubsamplingEnabled
</ins><span class="cx"> wantsBalancedSetDefersLoadingBehavior initial=false
</span><span class="cx"> requestAnimationFrameEnabled initial=true
</span><span class="cx"> deviceSupportsTouch initial=false
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsBitmapImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -44,12 +44,12 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-// FIXME: We should better integrate the iOS and non-iOS code in this class. Unlike other ports, the
-// iOS port caches the metadata for a frame without decoding the image.
</del><span class="cx"> BitmapImage::BitmapImage(ImageObserver* observer)
</span><span class="cx"> : Image(observer)
</span><ins>+ , m_minimumSubsamplingLevel(0)
+ , m_imageOrientation(OriginTopLeft)
+ , m_shouldRespectImageOrientation(false)
</ins><span class="cx"> , m_currentFrame(0)
</span><del>- , m_frames(0)
</del><span class="cx"> , m_repetitionCount(cAnimationNone)
</span><span class="cx"> , m_repetitionCountStatus(Unknown)
</span><span class="cx"> , m_repetitionsComplete(0)
</span><span class="lines">@@ -61,6 +61,9 @@
</span><span class="cx"> // FIXME: We should expose a setting to enable/disable progressive loading remove the PLATFORM(IOS)-guard.
</span><span class="cx"> , m_progressiveLoadChunkTime(0)
</span><span class="cx"> , m_progressiveLoadChunkCount(0)
</span><ins>+ , m_allowSubsampling(true)
+#else
+ , m_allowSubsampling(false)
</ins><span class="cx"> #endif
</span><span class="cx"> , m_isSolidColor(false)
</span><span class="cx"> , m_checkedForSolidColor(false)
</span><span class="lines">@@ -80,6 +83,17 @@
</span><span class="cx"> stopAnimation();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+bool BitmapImage::haveFrameAtIndex(size_t index)
+{
+ if (index >= frameCount())
+ return false;
+
+ if (index >= m_frames.size())
+ return false;
+
+ return m_frames[index].m_frame;
+}
+
</ins><span class="cx"> bool BitmapImage::hasSingleSecurityOrigin() const
</span><span class="cx"> {
</span><span class="cx"> return true;
</span><span class="lines">@@ -152,11 +166,7 @@
</span><span class="cx"> imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
-void BitmapImage::cacheFrame(size_t index, float scaleHint)
-#else
-void BitmapImage::cacheFrame(size_t index)
-#endif
</del><ins>+void BitmapImage::cacheFrame(size_t index, SubsamplingLevel subsamplingLevel, ImageFrameCaching frameCaching)
</ins><span class="cx"> {
</span><span class="cx"> size_t numFrames = frameCount();
</span><span class="cx"> ASSERT(m_decodedSize == 0 || numFrames > 1);
</span><span class="lines">@@ -164,26 +174,27 @@
</span><span class="cx"> if (m_frames.size() < numFrames)
</span><span class="cx"> m_frames.grow(numFrames);
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
- m_frames[index].m_frame = m_source.createFrameAtIndex(index, &scaleHint);
- m_frames[index].m_subsamplingScale = scaleHint;
-#else
- m_frames[index].m_frame = m_source.createFrameAtIndex(index);
-#endif
- if (numFrames == 1 && m_frames[index].m_frame)
- checkForSolidColor();
</del><ins>+ if (frameCaching == CacheMetadataAndFrame) {
+ m_frames[index].m_frame = m_source.createFrameAtIndex(index, subsamplingLevel);
+ m_frames[index].m_subsamplingLevel = subsamplingLevel;
+ if (numFrames == 1 && m_frames[index].m_frame)
+ checkForSolidColor();
+ }
</ins><span class="cx">
</span><span class="cx"> m_frames[index].m_orientation = m_source.orientationAtIndex(index);
</span><span class="cx"> m_frames[index].m_haveMetadata = true;
</span><span class="cx"> m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);
</span><ins>+
</ins><span class="cx"> if (repetitionCount(false) != cAnimationNone)
</span><span class="cx"> m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
</span><ins>+
</ins><span class="cx"> m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
</span><del>- m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index);
</del><ins>+ m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index, subsamplingLevel);
</ins><span class="cx">
</span><del>- const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
- if (frameSize != m_size)
</del><ins>+ const IntSize frameSize(index ? m_source.frameSizeAtIndex(index, subsamplingLevel) : m_size);
+ if (!subsamplingLevel && frameSize != m_size)
</ins><span class="cx"> m_hasUniformFrameSize = false;
</span><ins>+
</ins><span class="cx"> if (m_frames[index].m_frame) {
</span><span class="cx"> int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes);
</span><span class="cx"> m_decodedSize += deltaBytes;
</span><span class="lines">@@ -196,30 +207,15 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
-void BitmapImage::cacheFrameInfo(size_t index)
-{
- size_t numFrames = frameCount();
-
- if (m_frames.size() < numFrames)
- m_frames.resize(numFrames);
-
- ASSERT(!m_frames[index].m_haveInfo);
-
- if (shouldAnimate())
- m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
- m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
- m_frames[index].m_haveInfo = true;
-}
-#endif
-
</del><span class="cx"> void BitmapImage::didDecodeProperties() const
</span><span class="cx"> {
</span><span class="cx"> if (m_decodedSize)
</span><span class="cx"> return;
</span><ins>+
</ins><span class="cx"> size_t updatedSize = m_source.bytesDecodedToDetermineProperties();
</span><span class="cx"> if (m_decodedPropertiesSize == updatedSize)
</span><span class="cx"> return;
</span><ins>+
</ins><span class="cx"> int deltaBytes = updatedSize - m_decodedPropertiesSize;
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx"> bool overflow = updatedSize > m_decodedPropertiesSize && deltaBytes < 0;
</span><span class="lines">@@ -238,13 +234,13 @@
</span><span class="cx">
</span><span class="cx"> m_size = m_source.size(description);
</span><span class="cx"> m_sizeRespectingOrientation = m_source.size(ImageOrientationDescription(RespectImageOrientation, description.imageOrientation()));
</span><ins>+
</ins><span class="cx"> m_imageOrientation = static_cast<unsigned>(description.imageOrientation());
</span><span class="cx"> m_shouldRespectImageOrientation = static_cast<unsigned>(description.respectImageOrientation());
</span><del>-#if PLATFORM(IOS)
- m_originalSize = m_source.originalSize();
- m_originalSizeRespectingOrientation = m_source.originalSize(RespectImageOrientation);
-#endif
</del><ins>+
</ins><span class="cx"> m_haveSize = true;
</span><ins>+
+ determineMinimumSubsamplingLevel();
</ins><span class="cx"> didDecodeProperties();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -260,29 +256,6 @@
</span><span class="cx"> return m_sizeRespectingOrientation;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
-FloatSize BitmapImage::originalSize() const
-{
- updateSize();
- return m_originalSize;
-}
-
-IntSize BitmapImage::originalSizeRespectingOrientation() const
-{
- updateSize();
- return m_originalSizeRespectingOrientation;
-}
-#endif
-
-IntSize BitmapImage::currentFrameSize() const
-{
- if (!m_currentFrame || m_hasUniformFrameSize)
- return IntSize(size());
- IntSize frameSize = m_source.frameSizeAtIndex(m_currentFrame);
- didDecodeProperties();
- return frameSize;
-}
-
</del><span class="cx"> bool BitmapImage::getHotSpot(IntPoint& hotSpot) const
</span><span class="cx"> {
</span><span class="cx"> bool result = m_source.getHotSpot(hotSpot);
</span><span class="lines">@@ -323,6 +296,7 @@
</span><span class="cx"> }
</span><span class="cx"> destroyMetadataAndNotify(frameBytesCleared);
</span><span class="cx"> #else
</span><ins>+ // FIXME: why is this different for iOS?
</ins><span class="cx"> int deltaBytes = 0;
</span><span class="cx"> if (!m_frames.isEmpty()) {
</span><span class="cx"> int bytes = m_frames[m_frames.size() - 1].m_frameBytes;
</span><span class="lines">@@ -390,85 +364,58 @@
</span><span class="cx"> return m_sizeAvailable;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if !PLATFORM(IOS)
-bool BitmapImage::ensureFrameIsCached(size_t index)
</del><ins>+bool BitmapImage::ensureFrameIsCached(size_t index, ImageFrameCaching frameCaching)
</ins><span class="cx"> {
</span><span class="cx"> if (index >= frameCount())
</span><span class="cx"> return false;
</span><span class="cx">
</span><del>- if (index >= m_frames.size() || !m_frames[index].m_frame)
- cacheFrame(index);
- return true;
-}
-#else
-bool BitmapImage::ensureFrameInfoIsCached(size_t index)
-{
- if (index >= frameCount())
- return false;
</del><ins>+ if (index >= m_frames.size()
+ || (frameCaching == CacheMetadataAndFrame && !m_frames[index].m_frame)
+ || (frameCaching == CacheMetadataOnly && !m_frames[index].m_haveMetadata))
+ cacheFrame(index, 0, frameCaching);
</ins><span class="cx">
</span><del>- if (index >= m_frames.size() || !m_frames[index].m_haveInfo)
- cacheFrameInfo(index);
</del><span class="cx"> return true;
</span><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><del>-PassNativeImagePtr BitmapImage::frameAtIndex(size_t index)
</del><ins>+PassNativeImagePtr BitmapImage::frameAtIndex(size_t index, float presentationScaleHint)
</ins><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
- return frameAtIndex(index, 1.0f);
-#else
- if (!ensureFrameIsCached(index))
- return nullptr;
- return m_frames[index].m_frame;
-#endif
-}
-
-#if PLATFORM(IOS)
-PassNativeImagePtr BitmapImage::frameAtIndex(size_t index, float scaleHint)
-{
</del><span class="cx"> if (index >= frameCount())
</span><span class="cx"> return nullptr;
</span><span class="cx">
</span><del>- if (index >= m_frames.size() || !m_frames[index].m_frame)
- cacheFrame(index, scaleHint);
- else if (std::min(1.0f, scaleHint) > m_frames[index].m_subsamplingScale) {
</del><ins>+ SubsamplingLevel subsamplingLevel = std::min(m_source.subsamplingLevelForScale(presentationScaleHint), m_minimumSubsamplingLevel);
+
+ // 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 < m_frames.size() && m_frames[index].m_frame && subsamplingLevel < m_frames[index].m_subsamplingLevel) {
</ins><span class="cx"> // If the image is already cached, but at too small a size, re-decode a larger version.
</span><span class="cx"> int sizeChange = -m_frames[index].m_frameBytes;
</span><del>- ASSERT(static_cast<int>(m_decodedSize) + sizeChange >= 0);
</del><span class="cx"> m_frames[index].clear(true);
</span><span class="cx"> invalidatePlatformData();
</span><span class="cx"> m_decodedSize += sizeChange;
</span><span class="cx"> if (imageObserver())
</span><span class="cx"> imageObserver()->decodedSizeChanged(this, sizeChange);
</span><del>-
- cacheFrame(index, scaleHint);
</del><span class="cx"> }
</span><ins>+
+ // If we haven't fetched a frame yet, do so.
+ if (index >= m_frames.size() || !m_frames[index].m_frame)
+ cacheFrame(index, subsamplingLevel, CacheMetadataAndFrame);
+
</ins><span class="cx"> return m_frames[index].m_frame;
</span><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><span class="cx"> bool BitmapImage::frameIsCompleteAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
- // FIXME: cacheFrameInfo does not set m_isComplete. Should it?
- if (!ensureFrameInfoIsCached(index))
</del><ins>+ if (!ensureFrameIsCached(index, CacheMetadataOnly))
</ins><span class="cx"> return false;
</span><del>-#else
- if (!ensureFrameIsCached(index))
- return false;
-#endif
</del><ins>+
</ins><span class="cx"> return m_frames[index].m_isComplete;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> float BitmapImage::frameDurationAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
- if (!ensureFrameInfoIsCached(index))
</del><ins>+ if (!ensureFrameIsCached(index, CacheMetadataOnly))
</ins><span class="cx"> return 0;
</span><del>-#else
- if (!ensureFrameIsCached(index))
- return 0;
-#endif
</del><ins>+
</ins><span class="cx"> return m_frames[index].m_duration;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -479,13 +426,9 @@
</span><span class="cx">
</span><span class="cx"> bool BitmapImage::frameHasAlphaAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
- if (!ensureFrameInfoIsCached(index))
- return true; // FIXME: Why would an invalid index return true here?
-#else
- if (m_frames.size() <= index)
</del><ins>+ if (!ensureFrameIsCached(index, CacheMetadataOnly))
</ins><span class="cx"> return true;
</span><del>-#endif
</del><ins>+
</ins><span class="cx"> if (m_frames[index].m_haveMetadata)
</span><span class="cx"> return m_frames[index].m_hasAlpha;
</span><span class="cx">
</span><span class="lines">@@ -499,14 +442,8 @@
</span><span class="cx">
</span><span class="cx"> ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index)
</span><span class="cx"> {
</span><del>-#if PLATFORM(IOS)
- // FIXME: cacheFrameInfo does not set m_orientation. Should it?
- if (!ensureFrameInfoIsCached(index))
</del><ins>+ if (!ensureFrameIsCached(index, CacheMetadataOnly))
</ins><span class="cx"> return DefaultImageOrientation;
</span><del>-#else
- if (!ensureFrameIsCached(index))
- return DefaultImageOrientation;
-#endif
</del><span class="cx">
</span><span class="cx"> if (m_frames[index].m_haveMetadata)
</span><span class="cx"> return m_frames[index].m_orientation;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsBitmapImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/BitmapImage.h        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -70,10 +70,7 @@
</span><span class="cx"> FrameData()
</span><span class="cx"> : m_frame(0)
</span><span class="cx"> , m_orientation(DefaultImageOrientation)
</span><del>-#if PLATFORM(IOS)
- , m_subsamplingScale(0)
- , m_haveInfo(false)
-#endif
</del><ins>+ , m_subsamplingLevel(0)
</ins><span class="cx"> , m_duration(0)
</span><span class="cx"> , m_haveMetadata(false)
</span><span class="cx"> , m_isComplete(false)
</span><span class="lines">@@ -93,10 +90,7 @@
</span><span class="cx">
</span><span class="cx"> NativeImagePtr m_frame;
</span><span class="cx"> ImageOrientation m_orientation;
</span><del>-#if PLATFORM(IOS)
- float m_subsamplingScale;
- bool m_haveInfo;
-#endif
</del><ins>+ SubsamplingLevel m_subsamplingLevel;
</ins><span class="cx"> float m_duration;
</span><span class="cx"> bool m_haveMetadata : 1;
</span><span class="cx"> bool m_isComplete : 1;
</span><span class="lines">@@ -108,9 +102,6 @@
</span><span class="cx"> // BitmapImage Class
</span><span class="cx"> // =================================================
</span><span class="cx">
</span><del>-// FIXME: We should better integrate the iOS and non-iOS code in this class. Unlike other ports, the
-// iOS port caches the metadata for a frame without decoding the image.
-
</del><span class="cx"> class BitmapImage final : public Image {
</span><span class="cx"> friend class GeneratedImage;
</span><span class="cx"> friend class CrossfadeGeneratedImage;
</span><span class="lines">@@ -137,11 +128,7 @@
</span><span class="cx"> // FloatSize due to override.
</span><span class="cx"> virtual FloatSize size() const override;
</span><span class="cx"> IntSize sizeRespectingOrientation(ImageOrientationDescription = ImageOrientationDescription()) const;
</span><del>-#if PLATFORM(IOS)
- virtual FloatSize originalSize() const override;
- IntSize originalSizeRespectingOrientation() const;
-#endif
- IntSize currentFrameSize() const;
</del><ins>+
</ins><span class="cx"> virtual bool getHotSpot(IntPoint&) const override;
</span><span class="cx">
</span><span class="cx"> unsigned decodedSize() const { return m_decodedSize; }
</span><span class="lines">@@ -194,8 +181,12 @@
</span><span class="cx">
</span><span class="cx"> bool canAnimate();
</span><span class="cx">
</span><ins>+ bool allowSubsampling() const { return m_allowSubsampling; }
+ void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
+
</ins><span class="cx"> private:
</span><span class="cx"> void updateSize(ImageOrientationDescription = ImageOrientationDescription()) const;
</span><ins>+ void determineMinimumSubsamplingLevel() const;
</ins><span class="cx">
</span><span class="cx"> protected:
</span><span class="cx"> enum RepetitionCountStatus {
</span><span class="lines">@@ -218,30 +209,24 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> size_t currentFrame() const { return m_currentFrame; }
</span><del>-#if PLATFORM(IOS)
- PassNativeImagePtr frameAtIndex(size_t, float scaleHint);
- PassNativeImagePtr copyUnscaledFrameAtIndex(size_t);
-#endif
</del><span class="cx"> size_t frameCount();
</span><del>- PassNativeImagePtr frameAtIndex(size_t);
</del><ins>+
+ PassNativeImagePtr frameAtIndex(size_t, float presentationScaleHint = 1);
+ PassNativeImagePtr copyUnscaledFrameAtIndex(size_t);
+
+ bool haveFrameAtIndex(size_t);
+
</ins><span class="cx"> bool frameIsCompleteAtIndex(size_t);
</span><span class="cx"> float frameDurationAtIndex(size_t);
</span><span class="cx"> bool frameHasAlphaAtIndex(size_t);
</span><span class="cx"> ImageOrientation frameOrientationAtIndex(size_t);
</span><span class="cx">
</span><span class="cx"> // Decodes and caches a frame. Never accessed except internally.
</span><del>-#if PLATFORM(IOS)
- void cacheFrame(size_t index, float scaleHint);
</del><ins>+ enum ImageFrameCaching { CacheMetadataOnly, CacheMetadataAndFrame };
+ void cacheFrame(size_t index, SubsamplingLevel, ImageFrameCaching = CacheMetadataAndFrame);
</ins><span class="cx">
</span><del>- // Cache frame metadata without decoding image.
- void cacheFrameInfo(size_t index);
</del><span class="cx"> // Called before accessing m_frames[index] for info without decoding. Returns false on index out of bounds.
</span><del>- bool ensureFrameInfoIsCached(size_t index);
-#else
- void cacheFrame(size_t index);
- // Called before accessing m_frames[index]. Returns false on index out of bounds.
- bool ensureFrameIsCached(size_t index);
-#endif
</del><ins>+ bool ensureFrameIsCached(size_t index, ImageFrameCaching = CacheMetadataAndFrame);
</ins><span class="cx">
</span><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="lines">@@ -301,13 +286,12 @@
</span><span class="cx"> ImageSource m_source;
</span><span class="cx"> mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
</span><span class="cx"> mutable IntSize m_sizeRespectingOrientation;
</span><ins>+
+ mutable SubsamplingLevel m_minimumSubsamplingLevel;
+
</ins><span class="cx"> mutable unsigned m_imageOrientation : 4; // ImageOrientationEnum
</span><span class="cx"> mutable unsigned m_shouldRespectImageOrientation : 1; // RespectImageOrientationEnum
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
- mutable IntSize m_originalSize; // The size of the unsubsampled image.
- mutable IntSize m_originalSizeRespectingOrientation;
-#endif
</del><span class="cx"> size_t m_currentFrame; // The index of the current frame of animation.
</span><span class="cx"> Vector<FrameData, 1> m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.
</span><span class="cx">
</span><span class="lines">@@ -336,6 +320,7 @@
</span><span class="cx"> uint16_t m_progressiveLoadChunkCount;
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+ bool m_allowSubsampling : 1; // Whether we should attempt subsampling if this image is very large.
</ins><span class="cx"> bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image.
</span><span class="cx"> bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color.
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsGraphicsContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.h (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/GraphicsContext.h        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.h        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -283,7 +283,7 @@
</span><span class="cx"> void applyFillPattern();
</span><span class="cx"> void drawPath(const Path&);
</span><span class="cx">
</span><del>- void drawNativeImage(PassNativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, float scale = 1, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal, ImageOrientation = DefaultImageOrientation);
</del><ins>+ void drawNativeImage(PassNativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal, ImageOrientation = DefaultImageOrientation);
</ins><span class="cx">
</span><span class="cx"> // Allow font smoothing (LCD antialiasing). Not part of the graphics state.
</span><span class="cx"> void setAllowsFontSmoothing(bool);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageSourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -29,6 +29,8 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "ImageSource.h"
</span><span class="cx">
</span><ins>+#if !USE(CG)
+
</ins><span class="cx"> #include "ImageDecoder.h"
</span><span class="cx">
</span><span class="cx"> #include "ImageOrientation.h"
</span><span class="lines">@@ -94,6 +96,16 @@
</span><span class="cx"> return m_decoder ? m_decoder->filenameExtension() : String();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+SubsamplingLevel ImageSource::subsamplingLevelForScale(float) const
+{
+ return 0;
+}
+
+bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t) const
+{
+ return false;
+}
+
</ins><span class="cx"> bool ImageSource::isSizeAvailable()
</span><span class="cx"> {
</span><span class="cx"> return m_decoder && m_decoder->isSizeAvailable();
</span><span class="lines">@@ -101,10 +113,10 @@
</span><span class="cx">
</span><span class="cx"> IntSize ImageSource::size(ImageOrientationDescription description) const
</span><span class="cx"> {
</span><del>- return frameSizeAtIndex(0, description);
</del><ins>+ return frameSizeAtIndex(0, 0, description);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-IntSize ImageSource::frameSizeAtIndex(size_t index, ImageOrientationDescription description) const
</del><ins>+IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel, ImageOrientationDescription description) const
</ins><span class="cx"> {
</span><span class="cx"> if (!m_decoder)
</span><span class="cx"> return IntSize();
</span><span class="lines">@@ -136,10 +148,8 @@
</span><span class="cx"> return m_decoder ? m_decoder->frameCount() : 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-PassNativeImagePtr ImageSource::createFrameAtIndex(size_t index, float* scale)
</del><ins>+PassNativeImagePtr ImageSource::createFrameAtIndex(size_t index, SubsamplingLevel)
</ins><span class="cx"> {
</span><del>- UNUSED_PARAM(scale);
-
</del><span class="cx"> if (!m_decoder)
</span><span class="cx"> return 0;
</span><span class="cx">
</span><span class="lines">@@ -197,7 +207,7 @@
</span><span class="cx"> return buffer && buffer->status() == ImageFrame::FrameComplete;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-unsigned ImageSource::frameBytesAtIndex(size_t index) const
</del><ins>+unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel) const
</ins><span class="cx"> {
</span><span class="cx"> if (!m_decoder)
</span><span class="cx"> return 0;
</span><span class="lines">@@ -205,3 +215,5 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> }
</span><ins>+
+#endif // USE(CG)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsImageSourceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/ImageSource.h (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/ImageSource.h        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -77,6 +77,9 @@
</span><span class="cx"> const int cAnimationLoopInfinite = -1;
</span><span class="cx"> const int cAnimationNone = -2;
</span><span class="cx">
</span><ins>+// SubsamplingLevel. 0 is no subsampling, 1 is half dimensions on each axis etc.
+typedef short SubsamplingLevel;
+
</ins><span class="cx"> class ImageSource {
</span><span class="cx"> WTF_MAKE_NONCOPYABLE(ImageSource);
</span><span class="cx"> public:
</span><span class="lines">@@ -131,15 +134,15 @@
</span><span class="cx"> void setData(SharedBuffer* data, bool allDataReceived);
</span><span class="cx"> String filenameExtension() const;
</span><span class="cx">
</span><ins>+ SubsamplingLevel subsamplingLevelForScale(float) const;
+ bool allowSubsamplingOfFrameAtIndex(size_t) const;
+
</ins><span class="cx"> bool isSizeAvailable();
</span><ins>+ // Always original size, without subsampling.
</ins><span class="cx"> IntSize size(ImageOrientationDescription = ImageOrientationDescription()) const;
</span><del>- IntSize frameSizeAtIndex(size_t, ImageOrientationDescription = ImageOrientationDescription()) const;
</del><ins>+ // Size of optionally subsampled frame.
+ IntSize frameSizeAtIndex(size_t, SubsamplingLevel = 0, ImageOrientationDescription = ImageOrientationDescription()) const;
</ins><span class="cx">
</span><del>-#if PLATFORM(IOS)
- IntSize originalSize(RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
- bool isSubsampled() const { return m_baseSubsampling; }
-#endif
-
</del><span class="cx"> bool getHotSpot(IntPoint&) const;
</span><span class="cx">
</span><span class="cx"> size_t bytesDecodedToDetermineProperties() const;
</span><span class="lines">@@ -150,7 +153,7 @@
</span><span class="cx">
</span><span class="cx"> // Callers should not call this after calling clear() with a higher index;
</span><span class="cx"> // see comments on clear() above.
</span><del>- PassNativeImagePtr createFrameAtIndex(size_t, float* scale = 0);
</del><ins>+ PassNativeImagePtr createFrameAtIndex(size_t, SubsamplingLevel = 0);
</ins><span class="cx">
</span><span class="cx"> float frameDurationAtIndex(size_t);
</span><span class="cx"> bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
</span><span class="lines">@@ -159,7 +162,7 @@
</span><span class="cx">
</span><span class="cx"> // Return the number of bytes in the decoded frame. If the frame is not yet
</span><span class="cx"> // decoded then return 0.
</span><del>- unsigned frameBytesAtIndex(size_t) const;
</del><ins>+ unsigned frameBytesAtIndex(size_t, SubsamplingLevel = 0) const;
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
</span><span class="cx"> static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; }
</span><span class="lines">@@ -176,11 +179,6 @@
</span><span class="cx"> #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
</span><span class="cx"> static unsigned s_maxPixelsPerDecodedImage;
</span><span class="cx"> #endif
</span><del>-#if PLATFORM(IOS)
- mutable int m_baseSubsampling;
- mutable bool m_isProgressive;
- CFDictionaryRef imageSourceOptions(ShouldSkipMetadata, int subsampling = 0) const;
-#endif
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscairoBitmapImageCairocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -119,6 +119,11 @@
</span><span class="cx"> imageObserver()->didDraw(this);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void BitmapImage::determineMinimumSubsamplingLevel() const
+{
+ m_minimumSubsamplingLevel = 0;
+}
+
</ins><span class="cx"> void BitmapImage::checkForSolidColor()
</span><span class="cx"> {
</span><span class="cx"> m_isSolidColor = false;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgBitmapImageCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if USE(CG)
</span><span class="cx">
</span><span class="cx"> #include "FloatConversion.h"
</span><ins>+#include "GeometryUtilities.h"
</ins><span class="cx"> #include "GraphicsContextCG.h"
</span><span class="cx"> #include "ImageObserver.h"
</span><span class="cx"> #include "SubimageCacheWithTimer.h"
</span><span class="lines">@@ -58,13 +59,8 @@
</span><span class="cx"> m_haveMetadata = false;
</span><span class="cx">
</span><span class="cx"> m_orientation = DefaultImageOrientation;
</span><ins>+ m_subsamplingLevel = 0;
</ins><span class="cx">
</span><del>-#if PLATFORM(IOS)
- m_frameBytes = 0;
- m_subsamplingScale = 1;
- m_haveInfo = false;
-#endif
-
</del><span class="cx"> if (m_frame) {
</span><span class="cx"> #if CACHE_SUBIMAGES
</span><span class="cx"> subimageCache().clearImage(m_frame);
</span><span class="lines">@@ -78,8 +74,10 @@
</span><span class="cx">
</span><span class="cx"> BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
</span><span class="cx"> : Image(observer)
</span><ins>+ , m_minimumSubsamplingLevel(0)
+ , m_imageOrientation(OriginTopLeft)
+ , m_shouldRespectImageOrientation(false)
</ins><span class="cx"> , m_currentFrame(0)
</span><del>- , m_frames(0)
</del><span class="cx"> , m_repetitionCount(cAnimationNone)
</span><span class="cx"> , m_repetitionCountStatus(Unknown)
</span><span class="cx"> , m_repetitionsComplete(0)
</span><span class="lines">@@ -103,50 +101,62 @@
</span><span class="cx"> // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0.
</span><span class="cx"> m_sizeRespectingOrientation = m_size;
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
- m_originalSize = m_size;
- m_originalSizeRespectingOrientation = m_size;
-#endif
-
</del><span class="cx"> m_frames.grow(1);
</span><span class="cx"> m_frames[0].m_frame = CGImageRetain(cgImage);
</span><span class="cx"> m_frames[0].m_hasAlpha = true;
</span><span class="cx"> m_frames[0].m_haveMetadata = true;
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
- m_frames[0].m_subsamplingScale = 1;
-#endif
-
</del><span class="cx"> checkForSolidColor();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-// Drawing Routines
</del><ins>+void BitmapImage::determineMinimumSubsamplingLevel() const
+{
+ if (!m_allowSubsampling)
+ return;
</ins><span class="cx">
</span><ins>+ if (!m_source.allowSubsamplingOfFrameAtIndex(0))
+ return;
+
+ // Values chosen to be appropriate for iOS.
+ const int cMaximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
+ const SubsamplingLevel maxSubsamplingLevel = 3;
+
+ SubsamplingLevel currentLevel = 0;
+ for ( ; currentLevel <= maxSubsamplingLevel; ++currentLevel) {
+ IntSize frameSize = m_source.frameSizeAtIndex(0, currentLevel);
+ if (frameSize.area() < cMaximumImageAreaBeforeSubsampling)
+ break;
+ }
+
+ m_minimumSubsamplingLevel = currentLevel;
+}
+
</ins><span class="cx"> void BitmapImage::checkForSolidColor()
</span><span class="cx"> {
</span><span class="cx"> m_checkedForSolidColor = true;
</span><del>- if (frameCount() > 1) {
- m_isSolidColor = false;
</del><ins>+ m_isSolidColor = false;
+
+ if (frameCount() > 1)
</ins><span class="cx"> return;
</span><ins>+
+ if (!haveFrameAtIndex(0)) {
+ IntSize size = m_source.frameSizeAtIndex(0, 0);
+ if (size.width() != 1 || size.height() != 1)
+ return;
+
+ if (!ensureFrameIsCached(0))
+ return;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-#if !PLATFORM(IOS)
- CGImageRef image = frameAtIndex(0);
-#else
- // Note, checkForSolidColor() may be called from frameAtIndex(). On iOS frameAtIndex() gets passed a scaleHint
- // argument which it uses to tell CG to create a scaled down image. Since we don't know the scaleHint here, if
- // we call frameAtIndex() again, we would pass it the default scale of 1 and would end up recreating the image.
- // So we do a quick check and call frameAtIndex(0) only if we haven't yet created an image.
</del><span class="cx"> CGImageRef image = nullptr;
</span><span class="cx"> if (m_frames.size())
</span><span class="cx"> image = m_frames[0].m_frame;
</span><span class="cx">
</span><span class="cx"> if (!image)
</span><del>- image = frameAtIndex(0);
-#endif
</del><ins>+ return;
</ins><span class="cx">
</span><span class="cx"> // Currently we only check for solid color in the important special case of a 1x1 image.
</span><del>- if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
</del><ins>+ if (CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
</ins><span class="cx"> unsigned char pixel[4]; // RGBA
</span><span class="cx"> RetainPtr<CGContextRef> bitmapContext = adoptCF(CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), deviceRGBColorSpaceRef(),
</span><span class="cx"> kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
</span><span class="lines">@@ -198,30 +208,23 @@
</span><span class="cx">
</span><span class="cx"> void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode, ImageOrientationDescription description)
</span><span class="cx"> {
</span><del>- CGImageRef image;
- FloatRect srcRectForCurrentFrame = srcRect;
-
</del><span class="cx"> #if PLATFORM(IOS)
</span><del>- if (m_originalSize != m_size && !m_originalSize.isEmpty())
- srcRectForCurrentFrame.scale(m_size.width() / static_cast<float>(m_originalSize.width()), m_size.height() / static_cast<float>(m_originalSize.height()));
-
</del><span class="cx"> startAnimation(DoNotCatchUp);
</span><ins>+#else
+ startAnimation();
+#endif
</ins><span class="cx">
</span><del>- CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(ctxt->platformContext()));
- RetainPtr<CGImageRef> imagePossiblyCopied;
</del><ins>+ RetainPtr<CGImageRef> image;
</ins><span class="cx"> // Never use subsampled images for drawing into PDF contexts.
</span><del>- if (CGContextGetType(ctxt->platformContext()) == kCGContextTypePDF)
- imagePossiblyCopied = adoptCF(copyUnscaledFrameAtIndex(m_currentFrame));
- else
- imagePossiblyCopied = frameAtIndex(m_currentFrame, std::min<float>(1.0f, std::max(transformedDestinationRect.size.width / srcRectForCurrentFrame.width(), transformedDestinationRect.size.height / srcRectForCurrentFrame.height())));
</del><ins>+ if (wkCGContextIsPDFContext(ctxt->platformContext()))
+ image = adoptCF(copyUnscaledFrameAtIndex(m_currentFrame));
+ else {
+ CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(ctxt->platformContext()));
+ float subsamplingScale = std::min<float>(1, std::max(transformedDestinationRect.size.width / srcRect.width(), transformedDestinationRect.size.height / srcRect.height()));
</ins><span class="cx">
</span><del>- image = imagePossiblyCopied.get();
-#else
- startAnimation();
</del><ins>+ image = frameAtIndex(m_currentFrame, subsamplingScale);
+ }
</ins><span class="cx">
</span><del>- image = frameAtIndex(m_currentFrame);
-#endif
-
</del><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">@@ -230,37 +233,40 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- float scale = 1;
-#if PLATFORM(IOS)
- scale = m_frames[m_currentFrame].m_subsamplingScale;
-#endif
- FloatSize selfSize = currentFrameSize();
</del><ins>+ // Subsampling may have given us an image that is smaller than size().
+ IntSize imageSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get()));
+
+ // srcRect is in the coordinates of the unsubsampled image, so we have to map it to the subsampled image.
+ FloatRect scaledSrcRect = srcRect;
+ if (imageSize != m_size) {
+ FloatRect originalImageBounds(FloatPoint(), m_size);
+ FloatRect subsampledImageBounds(FloatPoint(), imageSize);
+ scaledSrcRect = mapRect(srcRect, originalImageBounds, subsampledImageBounds);
+ }
+
</ins><span class="cx"> ImageOrientation orientation;
</span><del>-
</del><span class="cx"> if (description.respectImageOrientation() == RespectImageOrientation)
</span><span class="cx"> orientation = frameOrientationAtIndex(m_currentFrame);
</span><span class="cx">
</span><del>- ctxt->drawNativeImage(image, selfSize, styleColorSpace, destRect, srcRectForCurrentFrame, scale, compositeOp, blendMode, orientation);
</del><ins>+ ctxt->drawNativeImage(image.get(), imageSize, styleColorSpace, destRect, scaledSrcRect, compositeOp, blendMode, orientation);
</ins><span class="cx">
</span><span class="cx"> if (imageObserver())
</span><span class="cx"> imageObserver()->didDraw(this);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
</del><span class="cx"> PassNativeImagePtr BitmapImage::copyUnscaledFrameAtIndex(size_t index)
</span><span class="cx"> {
</span><span class="cx"> if (index >= frameCount())
</span><span class="cx"> return nullptr;
</span><span class="cx">
</span><span class="cx"> if (index >= m_frames.size() || !m_frames[index].m_frame)
</span><del>- cacheFrame(index, 1);
</del><ins>+ cacheFrame(index, 0);
</ins><span class="cx">
</span><del>- if (m_frames[index].m_subsamplingScale == 1 && !m_source.isSubsampled())
</del><ins>+ if (!m_frames[index].m_subsamplingLevel)
</ins><span class="cx"> return CGImageRetain(m_frames[index].m_frame);
</span><span class="cx">
</span><span class="cx"> return m_source.createFrameAtIndex(index);
</span><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgGraphicsContext3DCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -332,17 +332,8 @@
</span><span class="cx"> decoder.setData(m_image->data(), true);
</span><span class="cx"> if (!decoder.frameCount())
</span><span class="cx"> return false;
</span><del>-#if PLATFORM(IOS)
- float scaleHint = 1;
- if (m_image->isBitmapImage()) {
- FloatSize originalSize = toBitmapImage(m_image)->originalSize();
- if (!originalSize.isEmpty())
- scaleHint = std::min<float>(1, std::max(m_image->size().width() / originalSize.width(), m_image->size().width() / originalSize.height()));
- }
- m_decodedImage = adoptCF(decoder.createFrameAtIndex(0, &scaleHint));
-#else
</del><ins>+
</ins><span class="cx"> m_decodedImage = adoptCF(decoder.createFrameAtIndex(0));
</span><del>-#endif
</del><span class="cx"> m_cgImage = m_decodedImage.get();
</span><span class="cx"> } else
</span><span class="cx"> m_cgImage = m_image->nativeImageForCurrentFrame();
</span><span class="lines">@@ -545,7 +536,7 @@
</span><span class="cx"> context->scale(FloatSize(1, -1));
</span><span class="cx"> context->translate(0, -imageHeight);
</span><span class="cx"> context->setImageInterpolationQuality(InterpolationNone);
</span><del>- context->drawNativeImage(cgImage.get(), imageSize, ColorSpaceDeviceRGB, canvasRect, FloatRect(FloatPoint(), imageSize), 1, CompositeCopy);
</del><ins>+ context->drawNativeImage(cgImage.get(), imageSize, ColorSpaceDeviceRGB, canvasRect, FloatRect(FloatPoint(), imageSize), CompositeCopy);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgGraphicsContextCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -169,18 +169,11 @@
</span><span class="cx"> m_data->m_userToDeviceTransformKnownToBeIdentity = false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void GraphicsContext::drawNativeImage(PassNativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, float scale, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
</del><ins>+void GraphicsContext::drawNativeImage(PassNativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, BlendMode blendMode, ImageOrientation orientation)
</ins><span class="cx"> {
</span><span class="cx"> RetainPtr<CGImageRef> image(imagePtr);
</span><span class="cx">
</span><span class="cx"> float currHeight = orientation.usesWidthAsHeight() ? CGImageGetWidth(image.get()) : CGImageGetHeight(image.get());
</span><del>-#if PLATFORM(IOS)
- // Unapply the scaling since we are getting this from a scaled bitmap.
- currHeight /= scale;
-#else
- UNUSED_PARAM(scale);
-#endif
-
</del><span class="cx"> if (currHeight <= srcRect.y())
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="lines">@@ -221,9 +214,6 @@
</span><span class="cx"> subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
</span><span class="cx"> adjustedDestRect.setHeight(subimageRect.height() / yScale);
</span><span class="cx">
</span><del>-#if PLATFORM(IOS)
- subimageRect.scale(scale, scale);
-#endif
</del><span class="cx"> #if CACHE_SUBIMAGES
</span><span class="cx"> image = subimageCache().getSubimage(image.get(), subimageRect);
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageBufferCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -301,7 +301,7 @@
</span><span class="cx">
</span><span class="cx"> FloatRect adjustedSrcRect = srcRect;
</span><span class="cx"> adjustedSrcRect.scale(m_resolutionScale, m_resolutionScale);
</span><del>- destContext->drawNativeImage(image.get(), m_data.m_backingStoreSize, colorSpace, destRect, adjustedSrcRect, 1, op, blendMode);
</del><ins>+ destContext->drawNativeImage(image.get(), m_data.m_backingStoreSize, colorSpace, destRect, adjustedSrcRect, op, blendMode);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscgImageSourceCGcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -38,12 +38,17 @@
</span><span class="cx"> #include <ApplicationServices/ApplicationServices.h>
</span><span class="cx"> #else
</span><span class="cx"> #include <CoreGraphics/CGImagePrivate.h>
</span><del>-#include <CoreGraphics/CoreGraphics.h>
-#include <ImageIO/CGImageSourcePrivate.h>
</del><span class="cx"> #include <ImageIO/ImageIO.h>
</span><ins>+#include <wtf/NeverDestroyed.h>
</ins><span class="cx"> #include <wtf/RetainPtr.h>
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#if __has_include(<ImageIO/CGImageSourcePrivate.h>)
+#import <ImageIO/CGImageSourcePrivate.h>
+#else
+const CFStringRef kCGImageSourceSubsampleFactor = CFSTR("kCGImageSourceSubsampleFactor");
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> const CFStringRef WebCoreCGImagePropertyAPNGUnclampedDelayTime = CFSTR("UnclampedDelayTime");
</span><span class="lines">@@ -76,10 +81,6 @@
</span><span class="cx">
</span><span class="cx"> ImageSource::ImageSource(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption)
</span><span class="cx"> : m_decoder(0)
</span><del>-#if PLATFORM(IOS)
- , m_baseSubsampling(0)
- , m_isProgressive(false)
-#endif
</del><span class="cx"> {
</span><span class="cx"> // FIXME: AlphaOption and GammaAndColorProfileOption are ignored.
</span><span class="cx"> }
</span><span class="lines">@@ -105,39 +106,35 @@
</span><span class="cx"> setData(data, allDataReceived);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-#if !PLATFORM(IOS)
-static CFDictionaryRef imageSourceOptions(ImageSource::ShouldSkipMetadata skipMetaData)
</del><ins>+static CFDictionaryRef createImageSourceOptions(ImageSource::ShouldSkipMetadata skipMetaData, SubsamplingLevel subsamplingLevel)
</ins><span class="cx"> {
</span><del>- static CFDictionaryRef options;
-
- if (!options) {
</del><ins>+ const CFBooleanRef imageSourceSkipMetadata = (skipMetaData == ImageSource::SkipMetadata) ? kCFBooleanTrue : kCFBooleanFalse;
+
+ if (!subsamplingLevel) {
</ins><span class="cx"> const unsigned numOptions = 3;
</span><del>- const CFBooleanRef imageSourceSkipMetadata = (skipMetaData == ImageSource::SkipMetadata) ? kCFBooleanTrue : kCFBooleanFalse;
</del><span class="cx"> const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata };
</span><span class="cx"> const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, imageSourceSkipMetadata };
</span><del>- options = CFDictionaryCreate(NULL, keys, values, numOptions,
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
</del><ins>+ return CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
</ins><span class="cx"> }
</span><del>- return options;
</del><ins>+
+ short constrainedSubsamplingLevel = std::min<short>(3, std::max<short>(0, subsamplingLevel));
+ int subsampleInt = 1 << constrainedSubsamplingLevel; // [0..3] => [1, 2, 4, 8]
+
+ RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &subsampleInt));
+ const CFIndex numOptions = 4;
+ const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata, kCGImageSourceSubsampleFactor };
+ const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, imageSourceSkipMetadata, subsampleNumber.get() };
+ return CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
</ins><span class="cx"> }
</span><del>-#else
-CFDictionaryRef ImageSource::imageSourceOptions(ShouldSkipMetadata skipMetaData, int requestedSubsampling) const
</del><ins>+
+static CFDictionaryRef imageSourceOptions(ImageSource::ShouldSkipMetadata skipMetadata = ImageSource::SkipMetadata, SubsamplingLevel subsamplingLevel = 0)
</ins><span class="cx"> {
</span><del>- static CFDictionaryRef options[4] = {nullptr, nullptr, nullptr, nullptr};
- int subsampling = std::min(3, m_isProgressive || requestedSubsampling < 0 ? 0 : (requestedSubsampling + m_baseSubsampling));
</del><ins>+ if (subsamplingLevel)
+ return createImageSourceOptions(skipMetadata, subsamplingLevel);
</ins><span class="cx">
</span><del>- if (!options[subsampling]) {
- int subsampleInt = 1 << subsampling; // [0..3] => [1, 2, 4, 8]
- RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &subsampleInt));
- const CFIndex numOptions = 4;
- const CFBooleanRef imageSourceSkipMetaData = (skipMetaData == ImageSource::SkipMetadata) ? kCFBooleanTrue : kCFBooleanFalse;
- const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSubsampleFactor, kCGImageSourceSkipMetadata };
- const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, subsampleNumber.get(), imageSourceSkipMetaData };
- options[subsampling] = CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- }
- return options[subsampling];
</del><ins>+ static CFDictionaryRef options = createImageSourceOptions(skipMetadata, 0);
+ return options;
</ins><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><span class="cx"> bool ImageSource::initialized() const
</span><span class="cx"> {
</span><span class="lines">@@ -182,6 +179,15 @@
</span><span class="cx"> return WebCore::preferredExtensionForImageSourceType(imageSourceType);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale) const
+{
+ // There are four subsampling levels: 0 = 1x, 1 = 0.5x, 2 = 0.25x, 3 = 0.125x.
+ float clampedScale = std::max<float>(0.125, std::min<float>(1, scale));
+ int result = ceilf(log2f(1 / clampedScale));
+ ASSERT(result >=0 && result <= 3);
+ return result;
+}
+
</ins><span class="cx"> bool ImageSource::isSizeAvailable()
</span><span class="cx"> {
</span><span class="cx"> bool result = false;
</span><span class="lines">@@ -189,7 +195,7 @@
</span><span class="cx">
</span><span class="cx"> // Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
</span><span class="cx"> if (imageSourceStatus >= kCGImageStatusIncomplete) {
</span><del>- RetainPtr<CFDictionaryRef> image0Properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata)));
</del><ins>+ RetainPtr<CFDictionaryRef> image0Properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions()));
</ins><span class="cx"> if (image0Properties) {
</span><span class="cx"> CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelWidth);
</span><span class="cx"> CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelHeight);
</span><span class="lines">@@ -212,101 +218,67 @@
</span><span class="cx"> return ImageOrientation::fromEXIFValue(exifValue);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-IntSize ImageSource::frameSizeAtIndex(size_t index, ImageOrientationDescription description) const
</del><ins>+bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t) const
</ins><span class="cx"> {
</span><del>- RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
-
</del><ins>+ RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions()));
</ins><span class="cx"> if (!properties)
</span><del>- return IntSize();
</del><ins>+ return false;
</ins><span class="cx">
</span><del>- int w = 0, h = 0;
- CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
- if (num)
- CFNumberGetValue(num, kCFNumberIntType, &w);
- num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
- if (num)
- CFNumberGetValue(num, kCFNumberIntType, &h);
-
-#if PLATFORM(IOS)
- if (!m_isProgressive) {
- CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary));
- if (jfifProperties) {
- CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive));
- if (isProgCFBool)
- m_isProgressive = CFBooleanGetValue(isProgCFBool);
</del><ins>+ CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary));
+ if (jfifProperties) {
+ CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive));
+ if (isProgCFBool) {
+ bool isProgressive = CFBooleanGetValue(isProgCFBool);
</ins><span class="cx"> // Workaround for <rdar://problem/5184655> - Hang rendering very large progressive JPEG. Decoding progressive
</span><span class="cx"> // images hangs for a very long time right now. Until this is fixed, don't sub-sample progressive images. This
</span><span class="cx"> // will cause them to fail our large image check and they won't be decoded.
</span><span class="cx"> // FIXME: Remove once underlying issue is fixed (<rdar://problem/5191418>)
</span><ins>+ return !isProgressive;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if ((m_baseSubsampling == 0) && !m_isProgressive) {
- IntSize subsampledSize(w, h);
- const int cMaximumImageSizeBeforeSubsampling = 5 * 1024 * 1024;
- while ((m_baseSubsampling < 3) && subsampledSize.width() * subsampledSize.height() > cMaximumImageSizeBeforeSubsampling) {
- // We know the size, but the actual image is very large and should be sub-sampled.
- // Increase the base subsampling and ask for the size again. If the image can be subsampled, the size will be
- // greatly reduced. 4x sub-sampling will make us support up to 320MP (5MP * 4^3) images, which should be plenty.
- // There's no callback from ImageIO when the size is available, so we do the check when we happen
- // to check the size and its non - zero.
- // Note: Some clients of this class don't call isSizeAvailable() so we can't rely on that.
- ++m_baseSubsampling;
- subsampledSize = frameSizeAtIndex(index, description.respectImageOrientation());
- }
- w = subsampledSize.width();
- h = subsampledSize.height();
- }
-#endif
-
- if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight())
- return IntSize(h, w);
-
- return IntSize(w, h);
</del><ins>+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-ImageOrientation ImageSource::orientationAtIndex(size_t index) const
</del><ins>+IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageOrientationDescription description) const
</ins><span class="cx"> {
</span><del>- RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
- if (!properties)
- return DefaultImageOrientation;
</del><ins>+ RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata, subsamplingLevel)));
</ins><span class="cx">
</span><del>- return orientationFromProperties(properties.get());
-}
-
-#if PLATFORM(IOS)
-IntSize ImageSource::originalSize(RespectImageOrientationEnum shouldRespectOrientation) const
-{
- frameSizeAtIndex(0, shouldRespectOrientation);
- RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata, -1)));
-
</del><span class="cx"> if (!properties)
</span><span class="cx"> return IntSize();
</span><span class="cx">
</span><span class="cx"> int width = 0;
</span><span class="cx"> int height = 0;
</span><del>- CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
- if (number)
- CFNumberGetValue(number, kCFNumberIntType, &width);
- number = static_cast<CFNumberRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight));
- if (number)
- CFNumberGetValue(number, kCFNumberIntType, &height);
</del><ins>+ CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &width);
+ num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &height);
</ins><span class="cx">
</span><del>- if ((shouldRespectOrientation == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight())
</del><ins>+ if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight())
</ins><span class="cx"> return IntSize(height, width);
</span><span class="cx">
</span><span class="cx"> return IntSize(width, height);
</span><span class="cx"> }
</span><del>-#endif
</del><span class="cx">
</span><ins>+ImageOrientation ImageSource::orientationAtIndex(size_t index) const
+{
+ RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions()));
+ if (!properties)
+ return DefaultImageOrientation;
+
+ return orientationFromProperties(properties.get());
+}
+
</ins><span class="cx"> IntSize ImageSource::size(ImageOrientationDescription description) const
</span><span class="cx"> {
</span><del>- return frameSizeAtIndex(0, description);
</del><ins>+ return frameSizeAtIndex(0, 0, description);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool ImageSource::getHotSpot(IntPoint& hotSpot) const
</span><span class="cx"> {
</span><del>- RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata)));
</del><ins>+ RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions()));
</ins><span class="cx"> if (!properties)
</span><span class="cx"> return false;
</span><span class="cx">
</span><span class="lines">@@ -342,7 +314,7 @@
</span><span class="cx"> if (!initialized())
</span><span class="cx"> return cAnimationLoopOnce;
</span><span class="cx">
</span><del>- RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_decoder, imageSourceOptions(SkipMetadata)));
</del><ins>+ RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_decoder, imageSourceOptions()));
</ins><span class="cx"> if (!properties)
</span><span class="cx"> return cAnimationLoopOnce;
</span><span class="cx">
</span><span class="lines">@@ -381,22 +353,14 @@
</span><span class="cx"> return m_decoder ? CGImageSourceGetCount(m_decoder) : 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-CGImageRef ImageSource::createFrameAtIndex(size_t index, float* scale)
</del><ins>+CGImageRef ImageSource::createFrameAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
</ins><span class="cx"> {
</span><del>- UNUSED_PARAM(scale);
-
</del><span class="cx"> if (!initialized())
</span><span class="cx"> return 0;
</span><span class="cx">
</span><del>-#if !PLATFORM(IOS)
- UNUSED_PARAM(scale);
- RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata)));
-#else
- // Subsampling can be 1, 2 or 3, which means quarter-, sixteenth- and sixty-fourth-size, respectively.
- // A zero or negative value means no subsampling.
- int subsampling = scale ? static_cast<int>(log2f(1.0f / std::max(0.1f, std::min(1.0f, *scale)))) : -1;
- RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata, subsampling)));
</del><ins>+ RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata, subsamplingLevel)));
</ins><span class="cx">
</span><ins>+#if PLATFORM(IOS)
</ins><span class="cx"> // <rdar://problem/7371198> - CoreGraphics changed the default caching behaviour in iOS 4.0 to kCGImageCachingTransient
</span><span class="cx"> // which caused a performance regression for us since the images had to be resampled/recreated every time we called
</span><span class="cx"> // CGContextDrawImage. We now tell CG to cache the drawn images. See also <rdar://problem/14366755> -
</span><span class="lines">@@ -409,15 +373,8 @@
</span><span class="cx"> #if COMPILER(CLANG)
</span><span class="cx"> #pragma clang diagnostic pop
</span><span class="cx"> #endif
</span><del>- if (scale) {
- if (subsampling > 0)
- *scale = static_cast<float>(CGImageGetWidth(image.get())) / size(DoNotRespectImageOrientation).width();
- else {
- ASSERT(static_cast<int>(CGImageGetWidth(image.get())) == size(DoNotRespectImageOrientation).width());
- *scale = 1;
- }
- }
</del><span class="cx"> #endif // !PLATFORM(IOS)
</span><ins>+
</ins><span class="cx"> CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
</span><span class="cx"> static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
</span><span class="cx"> if (!imageUTI || !CFEqual(imageUTI, xbmUTI))
</span><span class="lines">@@ -485,7 +442,7 @@
</span><span class="cx"> // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
</span><span class="cx"> // for more information.
</span><span class="cx"> if (duration < 0.011f)
</span><del>- return 0.100f;
</del><ins>+ return 0.1f;
</ins><span class="cx"> return duration;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -510,9 +467,9 @@
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-unsigned ImageSource::frameBytesAtIndex(size_t index) const
</del><ins>+unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
</ins><span class="cx"> {
</span><del>- IntSize frameSize = frameSizeAtIndex(index, ImageOrientationDescription(RespectImageOrientation));
</del><ins>+ IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel, ImageOrientationDescription(RespectImageOrientation));
</ins><span class="cx"> return frameSize.width() * frameSize.height() * 4;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsmacImageMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/mac/ImageMac.mm        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -57,9 +57,9 @@
</span><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> #if USE(APPKIT)
</span><del>- m_nsImage = 0;
</del><ins>+ m_nsImage = nullptr;
</ins><span class="cx"> #endif
</span><del>- m_tiffRep = 0;
</del><ins>+ m_tiffRep = nullptr;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> PassRefPtr<Image> Image::loadPlatformResource(const char *name)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicswinceImageWinCEcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/wince/ImageWinCE.cpp (172347 => 172348)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/wince/ImageWinCE.cpp        2014-08-08 18:28:55 UTC (rev 172347)
+++ trunk/Source/WebCore/platform/graphics/wince/ImageWinCE.cpp        2014-08-08 18:55:51 UTC (rev 172348)
</span><span class="lines">@@ -148,6 +148,11 @@
</span><span class="cx"> bmp->drawPattern(ctxt, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, m_source.size());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void BitmapImage::determineMinimumSubsamplingLevel() const
+{
+ m_minimumSubsamplingLevel = 0;
+}
+
</ins><span class="cx"> void BitmapImage::checkForSolidColor()
</span><span class="cx"> {
</span><span class="cx"> if (m_checkedForSolidColor)
</span></span></pre>
</div>
</div>
</body>
</html>