<!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" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { 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 #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#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>
<title>[20009] trunk/WebCore</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/20009">20009</a></dd>
<dt>Author</dt> <dd>hyatt</dd>
<dt>Date</dt> <dd>2007-03-06 23:42:45 -0800 (Tue, 06 Mar 2007)</dd>
</dl>
<h3>Log Message</h3>
<pre> This patch reworks the WebCore memory cache to significantly reduce the amount of memory consumed by
images in the cache and to enhance the accuracy of the cache size as an absolute bound for the objects
contained within it. WebCore's memory use over time should significantly improve as a result of these
changes.
Cached resources now have both an encoded size (the original data stream) and a decoded size (an estimate of
the amount of memory consumed by an expanded version of that resource, e.g., the decoded frames of an image).
Both sizes now count towards the total size of the object and towards the allowed memory cache total.
By including both totals the reported size of resources will now be larger, and the cache will therefore become
much more aggressive about flushing.
Objects are stored in size-adjusted and popularity-aware LRU lists as before, but encoded size is now always
used when determining the correct LRU list.
The flush algorithm for the memory cache has been rewritten to first destroy decoded data before evicting
resources. By being able to compact its resources without evicting them, the memory cache can now hold many more
unique resources (encoded) in the same amount of space. Depending on how much of a hit we want to take from
re-decoding images, the memory cache could in theory have its size significantly reduced now while still holding
more resources than it did at the larger size!
Reviewed by mjs
* WebCore.xcodeproj/project.pbxproj:
* loader/Cache.cpp:
(WebCore::Cache::requestResource):
(WebCore::Cache::prune):
(WebCore::Cache::remove):
(WebCore::Cache::lruListFor):
(WebCore::Cache::adjustSize):
* loader/Cache.h:
* loader/CachedCSSStyleSheet.cpp:
(WebCore::CachedCSSStyleSheet::data):
* loader/CachedImage.cpp:
(WebCore::CachedImage::CachedImage):
(WebCore::CachedImage::allReferencesRemoved):
(WebCore::CachedImage::clear):
(WebCore::CachedImage::data):
(WebCore::CachedImage::destroyDecodedData):
(WebCore::CachedImage::decodedSize):
(WebCore::CachedImage::decodedSizeChanged):
(WebCore::CachedImage::shouldPauseAnimation):
* loader/CachedImage.h:
* loader/CachedResource.cpp:
(WebCore::CachedResource::CachedResource):
(WebCore::CachedResource::deref):
(WebCore::CachedResource::setEncodedSize):
* loader/CachedResource.h:
(WebCore::CachedResource::allReferencesRemoved):
(WebCore::CachedResource::size):
(WebCore::CachedResource::encodedSize):
(WebCore::CachedResource::decodedSize):
(WebCore::CachedResource::destroyDecodedData):
* loader/CachedScript.cpp:
(WebCore::CachedScript::data):
* loader/CachedXSLStyleSheet.cpp:
(WebCore::CachedXSLStyleSheet::data):
* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::BitmapImage):
(WebCore::BitmapImage::~BitmapImage):
(WebCore::BitmapImage::destroyDecodedData):
(WebCore::BitmapImage::pruneDecodedDataIfNeeded):
(WebCore::BitmapImage::cacheFrame):
(WebCore::BitmapImage::setNativeData):
(WebCore::BitmapImage::shouldAnimate):
(WebCore::BitmapImage::advanceAnimation):
* platform/graphics/BitmapImage.h:
(WebCore::BitmapImage::decodedSize):
* platform/graphics/Image.cpp:
(WebCore::Image::Image):
* platform/graphics/Image.h:
(WebCore::Image::destroyDecodedData):
(WebCore::Image::decodedSize):
(WebCore::Image::imageObserver):
* platform/graphics/ImageAnimationObserver.h: Removed.
* platform/graphics/ImageObserver.h: Added.
(WebCore::ImageObserver::~ImageObserver):
* platform/graphics/svg/SVGImage.cpp:
(WebCore::SVGImage::SVGImage):
* platform/graphics/svg/SVGImage.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebCoreChangeLog">trunk/WebCore/ChangeLog</a></li>
<li><a href="#trunkWebCoreWebCorexcodeprojprojectpbxproj">trunk/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkWebCoreloaderCachecpp">trunk/WebCore/loader/Cache.cpp</a></li>
<li><a href="#trunkWebCoreloaderCacheh">trunk/WebCore/loader/Cache.h</a></li>
<li><a href="#trunkWebCoreloaderCachedCSSStyleSheetcpp">trunk/WebCore/loader/CachedCSSStyleSheet.cpp</a></li>
<li><a href="#trunkWebCoreloaderCachedImagecpp">trunk/WebCore/loader/CachedImage.cpp</a></li>
<li><a href="#trunkWebCoreloaderCachedImageh">trunk/WebCore/loader/CachedImage.h</a></li>
<li><a href="#trunkWebCoreloaderCachedResourcecpp">trunk/WebCore/loader/CachedResource.cpp</a></li>
<li><a href="#trunkWebCoreloaderCachedResourceh">trunk/WebCore/loader/CachedResource.h</a></li>
<li><a href="#trunkWebCoreloaderCachedScriptcpp">trunk/WebCore/loader/CachedScript.cpp</a></li>
<li><a href="#trunkWebCoreloaderCachedXSLStyleSheetcpp">trunk/WebCore/loader/CachedXSLStyleSheet.cpp</a></li>
<li><a href="#trunkWebCoreplatformgraphicsBitmapImagecpp">trunk/WebCore/platform/graphics/BitmapImage.cpp</a></li>
<li><a href="#trunkWebCoreplatformgraphicsBitmapImageh">trunk/WebCore/platform/graphics/BitmapImage.h</a></li>
<li><a href="#trunkWebCoreplatformgraphicsImagecpp">trunk/WebCore/platform/graphics/Image.cpp</a></li>
<li><a href="#trunkWebCoreplatformgraphicsImageh">trunk/WebCore/platform/graphics/Image.h</a></li>
<li><a href="#trunkWebCoreplatformgraphicssvgSVGImagecpp">trunk/WebCore/platform/graphics/svg/SVGImage.cpp</a></li>
<li><a href="#trunkWebCoreplatformgraphicssvgSVGImageh">trunk/WebCore/platform/graphics/svg/SVGImage.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkWebCoreplatformgraphicsImageObserverh">trunk/WebCore/platform/graphics/ImageObserver.h</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkWebCoreplatformgraphicsImageAnimationObserverh">trunk/WebCore/platform/graphics/ImageAnimationObserver.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/ChangeLog (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/ChangeLog        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/ChangeLog        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -1,3 +1,86 @@
</span><ins>+2007-03-06 David Hyatt <hyatt@apple.com>
+
+ This patch reworks the WebCore memory cache to significantly reduce the amount of memory consumed by
+ images in the cache and to enhance the accuracy of the cache size as an absolute bound for the objects
+ contained within it. WebCore's memory use over time should significantly improve as a result of these
+ changes.
+
+ Cached resources now have both an encoded size (the original data stream) and a decoded size (an estimate of
+ the amount of memory consumed by an expanded version of that resource, e.g., the decoded frames of an image).
+ Both sizes now count towards the total size of the object and towards the allowed memory cache total.
+
+ By including both totals the reported size of resources will now be larger, and the cache will therefore become
+ much more aggressive about flushing.
+
+ Objects are stored in size-adjusted and popularity-aware LRU lists as before, but encoded size is now always
+ used when determining the correct LRU list.
+
+ The flush algorithm for the memory cache has been rewritten to first destroy decoded data before evicting
+ resources. By being able to compact its resources without evicting them, the memory cache can now hold many more
+ unique resources (encoded) in the same amount of space. Depending on how much of a hit we want to take from
+ re-decoding images, the memory cache could in theory have its size significantly reduced now while still holding
+ more resources than it did at the larger size!
+
+ Reviewed by mjs
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * loader/Cache.cpp:
+ (WebCore::Cache::requestResource):
+ (WebCore::Cache::prune):
+ (WebCore::Cache::remove):
+ (WebCore::Cache::lruListFor):
+ (WebCore::Cache::adjustSize):
+ * loader/Cache.h:
+ * loader/CachedCSSStyleSheet.cpp:
+ (WebCore::CachedCSSStyleSheet::data):
+ * loader/CachedImage.cpp:
+ (WebCore::CachedImage::CachedImage):
+ (WebCore::CachedImage::allReferencesRemoved):
+ (WebCore::CachedImage::clear):
+ (WebCore::CachedImage::data):
+ (WebCore::CachedImage::destroyDecodedData):
+ (WebCore::CachedImage::decodedSize):
+ (WebCore::CachedImage::decodedSizeChanged):
+ (WebCore::CachedImage::shouldPauseAnimation):
+ * loader/CachedImage.h:
+ * loader/CachedResource.cpp:
+ (WebCore::CachedResource::CachedResource):
+ (WebCore::CachedResource::deref):
+ (WebCore::CachedResource::setEncodedSize):
+ * loader/CachedResource.h:
+ (WebCore::CachedResource::allReferencesRemoved):
+ (WebCore::CachedResource::size):
+ (WebCore::CachedResource::encodedSize):
+ (WebCore::CachedResource::decodedSize):
+ (WebCore::CachedResource::destroyDecodedData):
+ * loader/CachedScript.cpp:
+ (WebCore::CachedScript::data):
+ * loader/CachedXSLStyleSheet.cpp:
+ (WebCore::CachedXSLStyleSheet::data):
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::BitmapImage):
+ (WebCore::BitmapImage::~BitmapImage):
+ (WebCore::BitmapImage::destroyDecodedData):
+ (WebCore::BitmapImage::pruneDecodedDataIfNeeded):
+ (WebCore::BitmapImage::cacheFrame):
+ (WebCore::BitmapImage::setNativeData):
+ (WebCore::BitmapImage::shouldAnimate):
+ (WebCore::BitmapImage::advanceAnimation):
+ * platform/graphics/BitmapImage.h:
+ (WebCore::BitmapImage::decodedSize):
+ * platform/graphics/Image.cpp:
+ (WebCore::Image::Image):
+ * platform/graphics/Image.h:
+ (WebCore::Image::destroyDecodedData):
+ (WebCore::Image::decodedSize):
+ (WebCore::Image::imageObserver):
+ * platform/graphics/ImageAnimationObserver.h: Removed.
+ * platform/graphics/ImageObserver.h: Added.
+ (WebCore::ImageObserver::~ImageObserver):
+ * platform/graphics/svg/SVGImage.cpp:
+ (WebCore::SVGImage::SVGImage):
+ * platform/graphics/svg/SVGImage.h:
+
</ins><span class="cx"> 2007-03-06 Alexey Proskuryakov <ap@webkit.org>
</span><span class="cx">
</span><span class="cx"> Reviewed by Sam Weinig.
</span></span></pre></div>
<a id="trunkWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/WebCore.xcodeproj/project.pbxproj (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/WebCore.xcodeproj/project.pbxproj        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/WebCore.xcodeproj/project.pbxproj        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -2353,7 +2353,6 @@
</span><span class="cx">                 B2A015BA0AF6CD53006BCE0E /* SVGResourceMasker.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A015A70AF6CD53006BCE0E /* SVGResourceMasker.h */; };
</span><span class="cx">                 B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A10B910B3818BD00099AA4 /* ImageBuffer.h */; };
</span><span class="cx">                 B2A10B940B3818D700099AA4 /* ImageBufferCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */; };
</span><del>-                B2BFB5A00B22F76200567E80 /* ImageAnimationObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = B2BFB59F0B22F76200567E80 /* ImageAnimationObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 B2C96D8D0B3AF2B7005E80EC /* JSSVGPathSegCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2C96D8C0B3AF2B7005E80EC /* JSSVGPathSegCustom.cpp */; };
</span><span class="cx">                 B2CB41930AB75904004D9C45 /* SVGRenderingIntent.h in Headers */ = {isa = PBXBuildFile; fileRef = B2CB414C0AB75904004D9C45 /* SVGRenderingIntent.h */; };
</span><span class="cx">                 B2CB41A60AB75904004D9C45 /* SVGUnitTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B2CB415F0AB75904004D9C45 /* SVGUnitTypes.h */; };
</span><span class="lines">@@ -2745,6 +2744,7 @@
</span><span class="cx">                 BC6DB3690A1A7CB700E5CD14 /* GlyphPageTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6DB3680A1A7CB700E5CD14 /* GlyphPageTreeNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 BC6DB4740A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4730A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp */; };
</span><span class="cx">                 BC6DB4D40A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4D30A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp */; };
</span><ins>+                BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F44A70B9E324E00A9D081 /* ImageObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 BCAA90C30A7EBA60008B1229 /* ScrollBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */; };
</span><span class="cx">                 BCB16B8B0979B01400467741 /* DeprecatedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB16B880979B01400467741 /* DeprecatedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 BCB16B8C0979B01400467741 /* ArrayImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB16B890979B01400467741 /* ArrayImpl.cpp */; };
</span><span class="lines">@@ -5415,7 +5415,6 @@
</span><span class="cx">                 B2A015A70AF6CD53006BCE0E /* SVGResourceMasker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGResourceMasker.h; sourceTree = "<group>"; };
</span><span class="cx">                 B2A10B910B3818BD00099AA4 /* ImageBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageBuffer.h; sourceTree = "<group>"; };
</span><span class="cx">                 B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ImageBufferCG.cpp; sourceTree = "<group>"; };
</span><del>-                B2BFB59F0B22F76200567E80 /* ImageAnimationObserver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageAnimationObserver.h; sourceTree = "<group>"; };
</del><span class="cx">                 B2C96D8C0B3AF2B7005E80EC /* JSSVGPathSegCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSSVGPathSegCustom.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 B2CB41010AB758E6004D9C45 /* SVGAElement.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SVGAElement.idl; sourceTree = "<group>"; };
</span><span class="cx">                 B2CB41020AB758E6004D9C45 /* SVGAnimateColorElement.idl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SVGAnimateColorElement.idl; sourceTree = "<group>"; };
</span><span class="lines">@@ -5931,6 +5930,7 @@
</span><span class="cx">                 BC6DB4D30A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphPageTreeNodeMac.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 BC7B2AF80450824100A8000F /* ScrollBar.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ScrollBar.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
</span><span class="cx">                 BC7B2AF90450824100A8000F /* PlatformScrollBarMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformScrollBarMac.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
</span><ins>+                BC7F44A70B9E324E00A9D081 /* ImageObserver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageObserver.h; sourceTree = "<group>"; };
</ins><span class="cx">                 BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScrollBar.cpp; path = platform/ScrollBar.cpp; sourceTree = SOURCE_ROOT; };
</span><span class="cx">                 BCB16B880979B01400467741 /* DeprecatedArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DeprecatedArray.h; sourceTree = "<group>"; };
</span><span class="cx">                 BCB16B890979B01400467741 /* ArrayImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayImpl.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -8690,9 +8690,9 @@
</span><span class="cx">                                 B27535400B053814002CE64F /* Icon.h */,
</span><span class="cx">                                 B27535410B053814002CE64F /* Image.cpp */,
</span><span class="cx">                                 B27535420B053814002CE64F /* Image.h */,
</span><del>-                                B2BFB59F0B22F76200567E80 /* ImageAnimationObserver.h */,
</del><span class="cx">                                 B23BCCE40B3829C9005B2415 /* ImageBuffer.cpp */,
</span><span class="cx">                                 B2A10B910B3818BD00099AA4 /* ImageBuffer.h */,
</span><ins>+                                BC7F44A70B9E324E00A9D081 /* ImageObserver.h */,
</ins><span class="cx">                                 B27535430B053814002CE64F /* ImageSource.h */,
</span><span class="cx">                                 B27535440B053814002CE64F /* IntPoint.h */,
</span><span class="cx">                                 B27535450B053814002CE64F /* IntRect.cpp */,
</span><span class="lines">@@ -11100,7 +11100,6 @@
</span><span class="cx">                                 06027CAD0B1CBFC000884B2D /* ContextMenuItem.h in Headers */,
</span><span class="cx">                                 B2310B770B1F46A200D55D87 /* CgSupport.h in Headers */,
</span><span class="cx">                                 932871C00B20DEB70049035A /* PlatformMenuDescription.h in Headers */,
</span><del>-                                B2BFB5A00B22F76200567E80 /* ImageAnimationObserver.h in Headers */,
</del><span class="cx">                                 E1D8E3160B29E39C00F4BAF6 /* HTTPParsers.h in Headers */,
</span><span class="cx">                                 BC18C5D00B2A886F0018461D /* TextBreakIterator.h in Headers */,
</span><span class="cx">                                 AA4C3A770B2B1679002334A2 /* StyleElement.h in Headers */,
</span><span class="lines">@@ -11160,6 +11159,7 @@
</span><span class="cx">                                 06A6A73D0B8BA44800DF1703 /* StringTruncator.h in Headers */,
</span><span class="cx">                                 934D9BA70B8C1175007B42A9 /* WebCoreNSStringExtras.h in Headers */,
</span><span class="cx">                                 51DF6D7E0B92A16D00C2DC85 /* ThreadCheck.h in Headers */,
</span><ins>+                                BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */,
</ins><span class="cx">                         );
</span><span class="cx">                         runOnlyForDeploymentPostprocessing = 0;
</span><span class="cx">                 };
</span></span></pre></div>
<a id="trunkWebCoreloaderCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/Cache.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/Cache.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/Cache.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -89,14 +89,10 @@
</span><span class="cx"> CachedResource* resource = m_resources.get(url.url());
</span><span class="cx">
</span><span class="cx"> if (resource) {
</span><del>- if (!skipCanLoadCheck
- && FrameLoader::restrictAccessToLocal()
- && !FrameLoader::canLoad(*resource, docLoader->doc()))
</del><ins>+ if (!skipCanLoadCheck && FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(*resource, docLoader->doc()))
</ins><span class="cx"> return 0;
</span><span class="cx"> } else {
</span><del>- if (!skipCanLoadCheck
- && FrameLoader::restrictAccessToLocal()
- && !FrameLoader::canLoad(url, docLoader->doc()))
</del><ins>+ if (!skipCanLoadCheck && FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(url, docLoader->doc()))
</ins><span class="cx"> return 0;
</span><span class="cx">
</span><span class="cx"> // The resource does not exist. Create it.
</span><span class="lines">@@ -135,9 +131,30 @@
</span><span class="cx"> if (unreferencedResourcesSize < m_maximumSize)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- bool canShrinkLRULists = true;
</del><ins>+ // Our first pass over the objects in the cache will destroy any decoded data in unreferenced objects.
</ins><span class="cx"> unsigned size = m_lruLists.size();
</span><span class="cx"> for (int i = size - 1; i >= 0; i--) {
</span><ins>+ // Start from the tail, since this is the least frequently accessed of the objects.
+ CachedResource* current = m_lruLists[i].m_tail;
+ while (current) {
+ CachedResource* prev = current->m_prevInLRUList;
+ if (!current->referenced()) {
+ // Go ahead and destroy our decoded data.
+ current->destroyDecodedData();
+
+ // Stop pruning if our total cache size is back under the maximum or if every
+ // remaining object in the cache is live (meaning there is nothing left we are able
+ // to prune).
+ if (m_currentSize <= m_maximumSize || m_currentSize == m_liveResourcesSize)
+ return;
+ }
+ current = prev;
+ }
+ }
+
+ // Our second pass over the objects in the cache will actually evict objects from the cache.
+ bool canShrinkLRULists = true;
+ for (int i = size - 1; i >= 0; i--) {
</ins><span class="cx"> // Remove from the tail, since this is the least frequently accessed of the objects.
</span><span class="cx"> CachedResource* current = m_lruLists[i].m_tail;
</span><span class="cx"> while (current) {
</span><span class="lines">@@ -188,9 +205,9 @@
</span><span class="cx"> (*itr)->removeCachedResource(resource);
</span><span class="cx">
</span><span class="cx"> // Subtract from our size totals.
</span><del>- m_currentSize -= resource->size();
- if (resource->referenced())
- m_liveResourcesSize -= resource->size();
</del><ins>+ int delta = -resource->size();
+ if (delta)
+ adjustSize(resource->referenced(), delta);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (resource->canDelete())
</span><span class="lines">@@ -228,7 +245,7 @@
</span><span class="cx"> LRUList* Cache::lruListFor(CachedResource* resource)
</span><span class="cx"> {
</span><span class="cx"> unsigned accessCount = max(resource->accessCount(), 1U);
</span><del>- unsigned queueIndex = fastLog2(resource->size() / accessCount);
</del><ins>+ unsigned queueIndex = fastLog2(resource->encodedSize() / accessCount);
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> resource->m_lruIndex = queueIndex;
</span><span class="cx"> #endif
</span><span class="lines">@@ -327,15 +344,11 @@
</span><span class="cx"> insertInLRUList(resource);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Cache::adjustSize(bool live, unsigned oldResourceSize, unsigned newResourceSize)
</del><ins>+void Cache::adjustSize(bool live, int delta)
</ins><span class="cx"> {
</span><del>- m_currentSize -= oldResourceSize;
</del><ins>+ m_currentSize += delta;
</ins><span class="cx"> if (live)
</span><del>- m_liveResourcesSize -= oldResourceSize;
-
- m_currentSize += newResourceSize;
- if (live)
- m_liveResourcesSize += newResourceSize;
</del><ins>+ m_liveResourcesSize += delta;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> Cache::Statistics Cache::getStatistics()
</span></span></pre></div>
<a id="trunkWebCoreloaderCacheh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/Cache.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/Cache.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/Cache.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -93,7 +93,7 @@
</span><span class="cx"> void removeFromLRUList(CachedResource*);
</span><span class="cx">
</span><span class="cx"> // Called to adjust the cache totals when a resource changes size.
</span><del>- void adjustSize(bool live, unsigned oldResourceSize, unsigned newResourceSize);
</del><ins>+ void adjustSize(bool live, int delta);
</ins><span class="cx">
</span><span class="cx"> // Track the size of all resources that are in the cache and still referenced by a Web page.
</span><span class="cx"> void addToLiveObjectSize(unsigned s) { m_liveResourcesSize += s; }
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedCSSStyleSheetcpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedCSSStyleSheet.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedCSSStyleSheet.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedCSSStyleSheet.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -72,8 +72,8 @@
</span><span class="cx"> if (!allDataReceived)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- setSize(data.size());
- m_sheet = m_decoder->decode(data.data(), size());
</del><ins>+ setEncodedSize(data.size());
+ m_sheet = m_decoder->decode(data.data(), encodedSize());
</ins><span class="cx"> m_sheet += m_decoder->flush();
</span><span class="cx"> m_loading = false;
</span><span class="cx"> checkNotify();
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedImage.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedImage.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedImage.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -53,7 +53,6 @@
</span><span class="cx">
</span><span class="cx"> CachedImage::CachedImage(DocLoader* docLoader, const String& url, CachePolicy cachePolicy, time_t _expireDate)
</span><span class="cx"> : CachedResource(url, ImageResource, cachePolicy, _expireDate)
</span><del>- , m_dataSize(0)
</del><span class="cx"> {
</span><span class="cx"> m_image = 0;
</span><span class="cx"> m_status = Unknown;
</span><span class="lines">@@ -66,7 +65,6 @@
</span><span class="cx">
</span><span class="cx"> CachedImage::CachedImage(Image* image)
</span><span class="cx"> : CachedResource(String(), ImageResource, CachePolicyCache, 0)
</span><del>- , m_dataSize(0)
</del><span class="cx"> {
</span><span class="cx"> m_image = image;
</span><span class="cx"> m_status = Cached;
</span><span class="lines">@@ -89,6 +87,12 @@
</span><span class="cx"> c->notifyFinished(this);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void CachedImage::allReferencesRemoved()
+{
+ if (m_image && !m_errorOccurred)
+ m_image->resetAnimation();
+}
+
</ins><span class="cx"> static Image* brokenImage()
</span><span class="cx"> {
</span><span class="cx"> static Image* brokenImage;
</span><span class="lines">@@ -135,7 +139,7 @@
</span><span class="cx"> {
</span><span class="cx"> delete m_image;
</span><span class="cx"> m_image = 0;
</span><del>- setSize(0);
</del><ins>+ setEncodedSize(0);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> inline void CachedImage::createImage()
</span><span class="lines">@@ -201,8 +205,6 @@
</span><span class="cx">
</span><span class="cx"> bool sizeAvailable = false;
</span><span class="cx">
</span><del>- m_dataSize = data.size();
-
</del><span class="cx"> // Have the image update its data from its internal buffer.
</span><span class="cx"> // It will not do anything now, but will delay decoding until
</span><span class="cx"> // queried for info (like size or specific image frames).
</span><span class="lines">@@ -221,12 +223,10 @@
</span><span class="cx"> } else
</span><span class="cx"> notifyObservers();
</span><span class="cx">
</span><del>- // FIXME: An animated GIF with a huge frame count can't have its size properly estimated. The reason is that we don't
- // want to decode the image to determine the frame count, so what we do instead is max the projected size of a single
- // RGBA32 buffer (width*height*4) with the data size. This will help ensure that large animated GIFs with thousands of
- // frames are at least given a reasonably large size.
- IntSize s = imageSize();
- setSize(max(s.width() * s.height() * 4, m_dataSize));
</del><ins>+ if (m_image) {
+ Vector<char>& imageBuffer = m_image->dataBuffer();
+ setEncodedSize(imageBuffer.size());
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if (allDataReceived) {
</span><span class="lines">@@ -254,9 +254,30 @@
</span><span class="cx"> c->notifyFinished(this);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool CachedImage::shouldStopAnimation(const Image* image)
</del><ins>+void CachedImage::destroyDecodedData()
</ins><span class="cx"> {
</span><ins>+ if (m_image && !m_errorOccurred)
+ m_image->destroyDecodedData();
+}
+
+unsigned CachedImage::decodedSize() const
+{
+ if (m_image && !m_errorOccurred)
+ return m_image->decodedSize();
+ return 0;
+}
+
+void CachedImage::decodedSizeChanged(const Image* image, int delta)
+{
</ins><span class="cx"> if (image != m_image)
</span><ins>+ return;
+
+ cache()->adjustSize(referenced(), delta);
+}
+
+bool CachedImage::shouldPauseAnimation(const Image* image)
+{
+ if (image != m_image)
</ins><span class="cx"> return false;
</span><span class="cx">
</span><span class="cx"> CachedResourceClientWalker w(m_clients);
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedImageh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedImage.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedImage.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedImage.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -29,7 +29,7 @@
</span><span class="cx"> #define CachedImage_h
</span><span class="cx">
</span><span class="cx"> #include "CachedResource.h"
</span><del>-#include "ImageAnimationObserver.h"
</del><ins>+#include "ImageObserver.h"
</ins><span class="cx"> #include "IntRect.h"
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx">
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> class Cache;
</span><span class="cx"> class Image;
</span><span class="cx">
</span><del>-class CachedImage : public CachedResource, public ImageAnimationObserver {
</del><ins>+class CachedImage : public CachedResource, public ImageObserver {
</ins><span class="cx"> public:
</span><span class="cx"> CachedImage(DocLoader*, const String& url, CachePolicy, time_t expireDate);
</span><span class="cx"> CachedImage(Image*);
</span><span class="lines">@@ -53,6 +53,9 @@
</span><span class="cx"> IntRect imageRect() const; // The size of the image.
</span><span class="cx">
</span><span class="cx"> virtual void ref(CachedResourceClient*);
</span><ins>+
+ virtual void allReferencesRemoved();
+ virtual void destroyDecodedData();
</ins><span class="cx">
</span><span class="cx"> virtual Vector<char>& bufferData(const char* bytes, int addedSize, Request*);
</span><span class="cx"> virtual void data(Vector<char>&, bool allDataReceived);
</span><span class="lines">@@ -66,7 +69,10 @@
</span><span class="cx">
</span><span class="cx"> void clear();
</span><span class="cx">
</span><del>- virtual bool shouldStopAnimation(const Image* image);
</del><ins>+ virtual unsigned decodedSize() const;
+
+ virtual void decodedSizeChanged(const Image* image, int delta);
+ virtual bool shouldPauseAnimation(const Image* image);
</ins><span class="cx"> virtual void animationAdvanced(const Image* image);
</span><span class="cx">
</span><span class="cx"> bool stillNeedsLoad() const { return !m_errorOccurred && m_status == Unknown && m_loading == false; }
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedResourcecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedResource.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedResource.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedResource.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> m_url = URL;
</span><span class="cx"> m_type = type;
</span><span class="cx"> m_status = Pending;
</span><del>- m_size = size;
</del><ins>+ m_encodedSize = size;
</ins><span class="cx"> m_inCache = false;
</span><span class="cx"> m_cachePolicy = cachePolicy;
</span><span class="cx"> m_request = 0;
</span><span class="lines">@@ -119,32 +119,33 @@
</span><span class="cx"> if (canDelete() && !inCache())
</span><span class="cx"> delete this;
</span><span class="cx"> else if (!referenced() && inCache()) {
</span><ins>+ allReferencesRemoved();
</ins><span class="cx"> cache()->removeFromLiveObjectSize(size());
</span><span class="cx"> cache()->prune();
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void CachedResource::setSize(unsigned size)
</del><ins>+void CachedResource::setEncodedSize(unsigned size)
</ins><span class="cx"> {
</span><del>- if (size == m_size)
</del><ins>+ if (size == m_encodedSize)
</ins><span class="cx"> return;
</span><span class="cx">
</span><del>- unsigned oldSize = m_size;
</del><ins>+ unsigned oldSize = m_encodedSize;
</ins><span class="cx">
</span><span class="cx"> // The object must now be moved to a different queue, since its size has been changed.
</span><del>- // We have to remove explicitly before updating m_size, so that we find the correct previous
</del><ins>+ // We have to remove explicitly before updating m_encodedSize, so that we find the correct previous
</ins><span class="cx"> // queue.
</span><span class="cx"> if (inCache())
</span><span class="cx"> cache()->removeFromLRUList(this);
</span><span class="cx">
</span><del>- m_size = size;
</del><ins>+ m_encodedSize = size;
</ins><span class="cx">
</span><span class="cx"> if (inCache()) {
</span><span class="cx"> // Now insert into the new LRU list.
</span><span class="cx"> cache()->insertInLRUList(this);
</span><span class="cx">
</span><span class="cx"> // Update the cache's size totals.
</span><del>- cache()->adjustSize(referenced(), oldSize, size);
</del><ins>+ cache()->adjustSize(referenced(), size - oldSize);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedResourceh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedResource.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedResource.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedResource.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -67,7 +67,7 @@
</span><span class="cx"> Cached // regular case
</span><span class="cx"> };
</span><span class="cx">
</span><del>- CachedResource(const String& URL, Type type, CachePolicy cachePolicy, unsigned size = 0);
</del><ins>+ CachedResource(const String& URL, Type type, CachePolicy cachePolicy, unsigned encodedSize = 0);
</ins><span class="cx"> virtual ~CachedResource();
</span><span class="cx">
</span><span class="cx"> virtual void setEncoding(const String&) { }
</span><span class="lines">@@ -81,13 +81,16 @@
</span><span class="cx"> virtual void ref(CachedResourceClient*);
</span><span class="cx"> void deref(CachedResourceClient*);
</span><span class="cx"> bool referenced() const { return !m_clients.isEmpty(); }
</span><ins>+ virtual void allReferencesRemoved() {};
</ins><span class="cx">
</span><span class="cx"> unsigned count() const { return m_clients.size(); }
</span><span class="cx">
</span><span class="cx"> Status status() const { return m_status; }
</span><span class="cx">
</span><del>- unsigned size() const { return m_size; }
-
</del><ins>+ unsigned size() const { return encodedSize() + decodedSize(); }
+ unsigned encodedSize() const { return m_encodedSize; }
+ virtual unsigned decodedSize() const { return 0; }
+
</ins><span class="cx"> bool isLoaded() const { return !m_loading; }
</span><span class="cx"> void setLoading(bool b) { m_loading = b; }
</span><span class="cx">
</span><span class="lines">@@ -130,8 +133,10 @@
</span><span class="cx"> bool errorOccurred() const { return m_errorOccurred; }
</span><span class="cx"> bool treatAsLocal() const { return m_shouldTreatAsLocal; }
</span><span class="cx">
</span><ins>+ virtual void destroyDecodedData() {};
+
</ins><span class="cx"> protected:
</span><del>- void setSize(unsigned size);
</del><ins>+ void setEncodedSize(unsigned);
</ins><span class="cx">
</span><span class="cx"> HashSet<CachedResourceClient*> m_clients;
</span><span class="cx">
</span><span class="lines">@@ -148,7 +153,7 @@
</span><span class="cx"> bool m_errorOccurred;
</span><span class="cx">
</span><span class="cx"> private:
</span><del>- unsigned m_size;
</del><ins>+ unsigned m_encodedSize;
</ins><span class="cx"> unsigned m_accessCount;
</span><span class="cx">
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedScriptcpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedScript.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedScript.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedScript.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -75,8 +75,8 @@
</span><span class="cx"> if (!allDataReceived)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- setSize(data.size());
- m_script = m_encoding.decode(data.data(), size());
</del><ins>+ setEncodedSize(data.size());
+ m_script = m_encoding.decode(data.data(), encodedSize());
</ins><span class="cx"> m_loading = false;
</span><span class="cx"> checkNotify();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebCoreloaderCachedXSLStyleSheetcpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/loader/CachedXSLStyleSheet.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/loader/CachedXSLStyleSheet.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/loader/CachedXSLStyleSheet.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -71,8 +71,8 @@
</span><span class="cx"> if (!allDataReceived)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- setSize(data.size());
- m_sheet = String(m_decoder->decode(data.data(), size()));
</del><ins>+ setEncodedSize(data.size());
+ m_sheet = String(m_decoder->decode(data.data(), encodedSize()));
</ins><span class="cx"> m_sheet += m_decoder->flush();
</span><span class="cx"> m_loading = false;
</span><span class="cx"> checkNotify();
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicsBitmapImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/BitmapImage.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/BitmapImage.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/BitmapImage.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -28,7 +28,7 @@
</span><span class="cx"> #include "BitmapImage.h"
</span><span class="cx">
</span><span class="cx"> #include "FloatRect.h"
</span><del>-#include "ImageAnimationObserver.h"
</del><ins>+#include "ImageObserver.h"
</ins><span class="cx"> #include "IntRect.h"
</span><span class="cx"> #include "PlatformString.h"
</span><span class="cx"> #include "Timer.h"
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-BitmapImage::BitmapImage(ImageAnimationObserver* observer)
</del><ins>+BitmapImage::BitmapImage(ImageObserver* observer)
</ins><span class="cx"> : Image(observer)
</span><span class="cx"> , m_currentFrame(0)
</span><span class="cx"> , m_frames(0)
</span><span class="lines">@@ -49,23 +49,40 @@
</span><span class="cx"> , m_animationFinished(false)
</span><span class="cx"> , m_haveSize(false)
</span><span class="cx"> , m_sizeAvailable(false)
</span><ins>+ , m_decodedSize(0)
</ins><span class="cx"> {
</span><span class="cx"> initPlatformData();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> BitmapImage::~BitmapImage()
</span><span class="cx"> {
</span><del>- invalidateData();
</del><ins>+ destroyDecodedData();
</ins><span class="cx"> stopAnimation();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void BitmapImage::invalidateData()
</del><ins>+void BitmapImage::destroyDecodedData(bool incremental)
</ins><span class="cx"> {
</span><span class="cx"> // Destroy the cached images and release them.
</span><span class="cx"> if (m_frames.size()) {
</span><del>- m_frames.last().clear();
</del><ins>+ int sizeChange = 0;
+ int frameSize = m_size.width() * m_size.height() * 4;
+ for (unsigned i = incremental ? m_frames.size() - 1 : 0; i < m_frames.size(); i++) {
+ if (m_frames[i].m_frame) {
+ sizeChange -= frameSize;
+ m_frames[i].clear();
+ }
+ }
+
+ // We just always invalidate our platform data, even in the incremental case.
+ // This could be better, but it's not a big deal.
</ins><span class="cx"> m_isSolidColor = false;
</span><span class="cx"> invalidatePlatformData();
</span><ins>+
+ if (sizeChange) {
+ m_decodedSize += sizeChange;
+ if (imageObserver())
+ imageObserver()->decodedSizeChanged(this, sizeChange);
+ }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -83,12 +100,19 @@
</span><span class="cx"> m_frames.resize(numFrames);
</span><span class="cx">
</span><span class="cx"> m_frames[index].m_frame = m_source.createFrameAtIndex(index);
</span><del>- if (m_frames[index].m_frame)
</del><ins>+ if (numFrames == 1 && m_frames[index].m_frame)
</ins><span class="cx"> checkForSolidColor();
</span><span class="cx">
</span><span class="cx"> if (shouldAnimate())
</span><span class="cx"> m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
</span><span class="cx"> m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
</span><ins>+
+ int sizeChange = m_size.width() * m_size.height() * 4;
+ if (sizeChange) {
+ m_decodedSize += sizeChange;
+ if (imageObserver())
+ imageObserver()->decodedSizeChanged(this, sizeChange);
+ }
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> IntSize BitmapImage::size() const
</span><span class="lines">@@ -102,7 +126,7 @@
</span><span class="cx">
</span><span class="cx"> bool BitmapImage::setNativeData(NativeBytePtr data, bool allDataReceived)
</span><span class="cx"> {
</span><del>- invalidateData();
</del><ins>+ destroyDecodedData(true);
</ins><span class="cx">
</span><span class="cx"> // Feed all the data we've seen so far to the image decoder.
</span><span class="cx"> m_source.setData(data, allDataReceived);
</span><span class="lines">@@ -162,7 +186,7 @@
</span><span class="cx">
</span><span class="cx"> bool BitmapImage::shouldAnimate()
</span><span class="cx"> {
</span><del>- return (m_animatingImageType && !m_animationFinished && animationObserver());
</del><ins>+ return (m_animatingImageType && !m_animationFinished && imageObserver());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void BitmapImage::startAnimation()
</span><span class="lines">@@ -190,22 +214,21 @@
</span><span class="cx"> m_animationFinished = false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
</del><span class="cx"> void BitmapImage::advanceAnimation(Timer<BitmapImage>* timer)
</span><span class="cx"> {
</span><span class="cx"> // Stop the animation.
</span><span class="cx"> stopAnimation();
</span><span class="cx">
</span><span class="cx"> // See if anyone is still paying attention to this animation. If not, we don't
</span><del>- // advance and will simply pause the animation.
- if (animationObserver()->shouldStopAnimation(this))
</del><ins>+ // advance and will remain suspended at the current frame until the animation is resumed.
+ if (imageObserver()->shouldPauseAnimation(this))
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> m_currentFrame++;
</span><span class="cx"> if (m_currentFrame >= frameCount()) {
</span><span class="cx"> m_repetitionsComplete += 1;
</span><span class="cx"> if (m_repetitionCount && m_repetitionsComplete >= m_repetitionCount) {
</span><del>- m_animationFinished = false;
</del><ins>+ m_animationFinished = true;
</ins><span class="cx"> m_currentFrame--;
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="lines">@@ -213,7 +236,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Notify our observer that the animation has advanced.
</span><del>- animationObserver()->animationAdvanced(this);
</del><ins>+ imageObserver()->animationAdvanced(this);
</ins><span class="cx">
</span><span class="cx"> // Kick off a timer to move to the next frame.
</span><span class="cx"> m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicsBitmapImageh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/BitmapImage.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/BitmapImage.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/BitmapImage.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx"> class BitmapImage : public Image {
</span><span class="cx"> friend class GraphicsContext;
</span><span class="cx"> public:
</span><del>- BitmapImage(ImageAnimationObserver* = 0);
</del><ins>+ BitmapImage(ImageObserver* = 0);
</ins><span class="cx"> ~BitmapImage();
</span><span class="cx">
</span><span class="cx"> virtual IntSize size() const;
</span><span class="lines">@@ -102,6 +102,8 @@
</span><span class="cx"> virtual void stopAnimation();
</span><span class="cx"> virtual void resetAnimation();
</span><span class="cx">
</span><ins>+ virtual unsigned decodedSize() const { return m_decodedSize; }
+
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx"> // Accessors for native image formats.
</span><span class="cx"> virtual NSImage* getNSImage();
</span><span class="lines">@@ -137,8 +139,9 @@
</span><span class="cx"> // Decodes and caches a frame. Never accessed except internally.
</span><span class="cx"> void cacheFrame(size_t index);
</span><span class="cx">
</span><del>- // Called to invalidate all our cached data when more bytes are available.
- void invalidateData();
</del><ins>+ // Called to invalidate all our cached data. If an image is loading incrementally, we only
+ // invalidate the last cached frame.
+ virtual void destroyDecodedData(bool incremental = false);
</ins><span class="cx">
</span><span class="cx"> // Whether or not size is available yet.
</span><span class="cx"> bool isSizeAvailable();
</span><span class="lines">@@ -151,7 +154,7 @@
</span><span class="cx"> // Handle platform-specific data
</span><span class="cx"> void initPlatformData();
</span><span class="cx"> void invalidatePlatformData();
</span><del>-
</del><ins>+
</ins><span class="cx"> // Checks to see if the image is a 1x1 solid color. We optimize these images and just do a fill rect instead.
</span><span class="cx"> void checkForSolidColor();
</span><span class="cx">
</span><span class="lines">@@ -181,6 +184,7 @@
</span><span class="cx">
</span><span class="cx"> mutable bool m_haveSize; // Whether or not our |m_size| member variable has the final overall image size yet.
</span><span class="cx"> bool m_sizeAvailable; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
</span><ins>+ unsigned m_decodedSize; // The current size of all decoded frames.
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicsImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/Image.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/Image.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/Image.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -40,8 +40,8 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-Image::Image(ImageAnimationObserver* observer)
- : m_animationObserver(observer)
</del><ins>+Image::Image(ImageObserver* observer)
+ : m_imageObserver(observer)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicsImageh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/Image.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/Image.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/Image.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -62,13 +62,13 @@
</span><span class="cx"> class IntSize;
</span><span class="cx"> class String;
</span><span class="cx">
</span><del>-// This class gets notified when an image advances animation frames.
-class ImageAnimationObserver;
</del><ins>+// This class gets notified when an image creates or destroys decoded frames and when it advances animation frames.
+class ImageObserver;
</ins><span class="cx">
</span><span class="cx"> class Image : Noncopyable {
</span><span class="cx"> friend class GraphicsContext;
</span><span class="cx"> public:
</span><del>- Image(ImageAnimationObserver* = 0);
</del><ins>+ Image(ImageObserver* = 0);
</ins><span class="cx"> virtual ~Image();
</span><span class="cx">
</span><span class="cx"> static Image* loadPlatformResource(const char* name);
</span><span class="lines">@@ -84,6 +84,11 @@
</span><span class="cx"> virtual bool setData(bool allDataReceived);
</span><span class="cx"> virtual bool setNativeData(NativeBytePtr, bool allDataReceived) { return false; }
</span><span class="cx">
</span><ins>+ // FIXME: PDF/SVG will be underreporting decoded sizes and will be unable to prune because these functions are not
+ // implemented yet for those image types.
+ virtual void destroyDecodedData(bool incremental = false) {};
+ virtual unsigned decodedSize() const { return 0; }
+
</ins><span class="cx"> Vector<char>& dataBuffer() { return m_data; }
</span><span class="cx">
</span><span class="cx"> // It may look unusual that there is no start animation call as public API. This is because
</span><span class="lines">@@ -93,7 +98,7 @@
</span><span class="cx"> virtual void resetAnimation() {}
</span><span class="cx">
</span><span class="cx"> // Typically the CachedImage that owns us.
</span><del>- ImageAnimationObserver* animationObserver() const { return m_animationObserver; }
</del><ins>+ ImageObserver* imageObserver() const { return m_imageObserver; }
</ins><span class="cx">
</span><span class="cx"> enum TileRule { StretchTile, RepeatTile };
</span><span class="cx">
</span><span class="lines">@@ -140,7 +145,7 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> Vector<char> m_data; // The encoded raw data for the image.
</span><del>- ImageAnimationObserver* m_animationObserver;
</del><ins>+ ImageObserver* m_imageObserver;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicsImageAnimationObserverh"></a>
<div class="delfile"><h4>Deleted: trunk/WebCore/platform/graphics/ImageAnimationObserver.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/ImageAnimationObserver.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/ImageAnimationObserver.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -1,44 +0,0 @@
</span><del>-/*
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ImageAnimationObserver_h
-#define ImageAnimationObserver_h
-
-namespace WebCore {
-
-class Image;
-
-// This class gets notified when an image advances animation frames.
-class ImageAnimationObserver {
-protected:
- virtual ~ImageAnimationObserver() {}
-public:
- virtual bool shouldStopAnimation(const Image*) = 0;
- virtual void animationAdvanced(const Image*) = 0;
-};
-
-}
-
-#endif
</del></span></pre></div>
<a id="trunkWebCoreplatformgraphicsImageObserverh"></a>
<div class="addfile"><h4>Added: trunk/WebCore/platform/graphics/ImageObserver.h (0 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/ImageObserver.h         (rev 0)
+++ trunk/WebCore/platform/graphics/ImageObserver.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageObserver_h
+#define ImageObserver_h
+
+namespace WebCore {
+
+class Image;
+
+// This class gets notified when an image advances animation frames.
+class ImageObserver {
+protected:
+ virtual ~ImageObserver() {}
+public:
+ virtual void decodedSizeChanged(const Image*, int delta) = 0;
+
+ virtual bool shouldPauseAnimation(const Image*) = 0;
+ virtual void animationAdvanced(const Image*) = 0;
+};
+
+}
+
+#endif
</ins></span></pre></div>
<a id="trunkWebCoreplatformgraphicssvgSVGImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/svg/SVGImage.cpp (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/svg/SVGImage.cpp        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/svg/SVGImage.cpp        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-SVGImage::SVGImage(ImageAnimationObserver* observer)
</del><ins>+SVGImage::SVGImage(ImageObserver* observer)
</ins><span class="cx"> : Image(observer)
</span><span class="cx"> , m_document(0)
</span><span class="cx"> , m_page(0)
</span></span></pre></div>
<a id="trunkWebCoreplatformgraphicssvgSVGImageh"></a>
<div class="modfile"><h4>Modified: trunk/WebCore/platform/graphics/svg/SVGImage.h (20008 => 20009)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/WebCore/platform/graphics/svg/SVGImage.h        2007-03-07 06:03:27 UTC (rev 20008)
+++ trunk/WebCore/platform/graphics/svg/SVGImage.h        2007-03-07 07:42:45 UTC (rev 20009)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx">
</span><span class="cx"> class SVGImage : public Image {
</span><span class="cx"> public:
</span><del>- SVGImage(ImageAnimationObserver*);
</del><ins>+ SVGImage(ImageObserver*);
</ins><span class="cx"> ~SVGImage();
</span><span class="cx">
</span><span class="cx"> virtual IntSize size() const;
</span></span></pre>
</div>
</div>
</body>
</html>