2011-10-13  Nikolas Zimmermann  <nzimmermann@rim.com>

        Prepare SVGImage intrinsic size negotiation: Introduce an IntSize <-> SVGImage cache in CachedImage
        https://bugs.webkit.org/show_bug.cgi?id=69416

        Reviewed by Antti Koivisto.

        Refactor ImageBySizeCache out of CSSImageGeneratorValue as CachedImage wants to use the same type of cache for its purposes.
        When introducing the SVGImage intrinsic size negotiation the container size of an SVGImage is dependant on the place where
        it gets embedded (eg width/height attributes of host documents <img> force a certain size).

        Currently CachedImage only contains a single RefPtr<Image>, which it constructs out of the decoded data.
        Multiple RenderObjects share the same CachedImages, when embedding eg. a SVG document in a <html:img> or using it in a background-image for a <div>.
        Consider the case where two RenderObjects use the same CachedImage, each with a different container size (200x100 vs 100x200) and the embedded
        document contains a viewBox and some arbitary preserveAspectRatio settings. To honour these we have to relayout the document with the desired
        size (percentual unit resolving etc, all depend on the RenderSVGRoots size).

        With the current design this is hard to realize, w/o requring to relayout the embedded document for each embedder that uses an SVGImage.
        This patch introduces a cache right within CachedImage, which manages a map of images to certain sizes, by utilizing the new ImageBySizeCache.

        CachedImage::imageForRenderer() takes a RenderObject* parameter, which it uses to look up the last set image container size for a renderer.
        Using that size it queries the cache whether it already has an SVGImage for that size, if not it gets created, by creating a whole
        new instance of SVGImage, filling it with the already decoded data, and passing on a fixed image container size, which overrides the
        size that RenderSVGRoot reports, when computeReplacedLogicalWidth/Height is called and thus laying out the document at the desired size.
        This image is then put in the cache for further reusability.

        Likewise CachedImage::setContainerSizeForRenderer() now takes a RenderObject* parameter and stores that in the cache with an associated container size.
        It requires to touch several files which use CachedImage throughout WebCore/WebKit/WebKit2.

        The actual cache is not yet turned on yet, so this is not a functional change so far, as it needs some other changes to SVGImage,
        which will come with the master patch in bug 47156.

        No new tests yet, as the new cache isn't turned on yet.

        * CMakeLists.txt: Add rendering/ImageBySizeCache.* to build.
        * GNUmakefile.list.am: Ditto.
        * WebCore.gypi: Ditto.
        * WebCore.pro: Ditto.
        * WebCore.vcproj/WebCore.vcproj: Ditto.
        * WebCore.xcodeproj/project.pbxproj: Ditto.
        * accessibility/AccessibilityRenderObject.cpp:
        (WebCore::AccessibilityRenderObject::accessibilityIsIgnored): Use new CachedImage::imageSizeForRenderer(RenderObject*) method.
        * bindings/objc/DOM.mm: Ditto (for CachedImage::image()).
        (-[DOMElement image]):
        (-[DOMElement _imageTIFFRepresentation]):
        * bridge/qt/qt_pixmapruntime.cpp:
        (JSC::Bindings::QtPixmapInstance::variantFromObject): Ditto (for CachedImage::image()).
        * css/CSSCanvasValue.cpp: s/m_clients/clients()/, which now live in the ImageBySizeCache instead of CSSImageGeneratorValue.
        (WebCore::CSSCanvasValue::canvasChanged):
        (WebCore::CSSCanvasValue::canvasResized):
        (WebCore::CSSCanvasValue::image):
        * css/CSSGradientValue.cpp: Ditto.
        (WebCore::CSSGradientValue::image):
        * css/CSSImageGeneratorValue.cpp: Move the sizes/clients/images cache into a new ImageBySizeCache class, to make it usable for CachedImage as well.
        (WebCore::CSSImageGeneratorValue::addClient): Adapt to move.
        (WebCore::CSSImageGeneratorValue::removeClient): Ditto.
        (WebCore::CSSImageGeneratorValue::getImage): Ditto.
        (WebCore::CSSImageGeneratorValue::putImage): Ditto.
        * css/CSSImageGeneratorValue.h:
        (WebCore::CSSImageGeneratorValue::clients): Forwarded to the ImageBySizeCache.
        * editing/DeleteButtonController.cpp: 
        (WebCore::isDeletableElement): CachedImage::canRender() now takes a RenderObject* parameter.
        * html/HTMLImageElement.cpp:
        (WebCore::HTMLImageElement::width): Use new CachedImage::imageSizeForRenderer(RenderObject*) method.
        (WebCore::HTMLImageElement::height): Ditto.
        (WebCore::HTMLImageElement::naturalWidth): Ditto.
        (WebCore::HTMLImageElement::naturalHeight): Ditto.
        * html/ImageDocument.cpp:
        (WebCore::ImageDocumentParser::finish): Ditto.
        (WebCore::ImageDocument::scale): Ditto.
        (WebCore::ImageDocument::resizeImageToFit): Ditto.
        (WebCore::ImageDocument::imageUpdated): Ditto.
        (WebCore::ImageDocument::restoreImageSize): Ditto.
        (WebCore::ImageDocument::imageFitsInWindow): Ditto.
        * html/canvas/CanvasRenderingContext.cpp:
        (WebCore::CanvasRenderingContext::wouldTaintOrigin): Use new CachedImage::imageForRenderer(RenderObject*) method.
        * html/canvas/CanvasRenderingContext2D.cpp:
        (WebCore::isOriginClean): Ditto.
        (WebCore::size): Ditto (for CachedImage::imageSizeForRenderer()).
        (WebCore::CanvasRenderingContext2D::drawImage): Ditto.
        (WebCore::CanvasRenderingContext2D::createPattern): Ditto.
        * html/canvas/WebGLRenderingContext.cpp:
        (WebCore::WebGLRenderingContext::texImage2D): Ditto.
        (WebCore::WebGLRenderingContext::texSubImage2D): Ditto.
        * loader/cache/CachedImage.cpp: Add currently _disabled_ cache for SVGImages. The intrinsic size negotiation will need to use multiple SVGImages
        for each requested size (equal to the size of the embedding place for the image) - make it possible to cache these SVGImages, and maintain a cache
        for them. The hash code is a 1:1 refactoring from the already present code in CSSImageGeneratorValue, now named 'ImageBySizeCache'.
        (WebCore::CachedImage::lookupImageForSize): Looks up an Image from the cache for a given IntSize. Currently turned off.
        (WebCore::CachedImage::lookupImageForRenderer): Looks up an Image from the cache for a given renderer. Currently turned off.
        (WebCore::CachedImage::lookupOrCreateImageForRenderer): Looks up an Image from the cache or creates a new SVGImage for a given size and caches it, if possible. Currently turned off.
        All following changes share this: Don't operate on m_image directly, instead always look up one from the cache for a given size or renderer - if that's not present fallback to m_image.
        When an SVGImage is first created by CachedImage::createImage() and stored in m_image, the cache remains empty.

        If eg. <img width="30" height="70" src="foo.svg"> is used which implies a container size of 30x70 a new SVGImage is created with the additional information of a 30x70 container size
        which is immediately passed to the SVGImage after its creation. This SVGImage is put in the ImageBySizeCache associated with a container size of 30x70.
        We now have two SVGImage objects present, one living in CachedImage::m_image, created by createImage() during data decoding, and one living in the ImageBySizeCache
        created by lookupOrCreateImageForRenderer() associated with the 30x70 container. The first SVGImage::size() will return a value as defined in the referenced foo.svg,
        whereas the SVGImage::size() call of the new SVGImage living in the cache reports 30x70 and renders according to that.

        Whenever any method of CachedImage is called with a RenderObject* or IntSize, we can't just operate on m_image anymore but instead have to lookup the right
        images for a certain renderer/size from the cache and operate on these. When calling eg. CachedImage::image() with a null renderer, m_image is returned.
        When passing with a valid renderer only cache lookups are done if the m_image is actually a SVGImage, otherwhise lookupImageForSize/Renderer will just return the m_image.
        There is no logical change induced for non-SVGImage derived images.

        CachedImage::image() of course needs a RenderObject* parameter now, to identify which of the images from the cache to use, if the underlying image is a SVGImage.
        Luckily these information are already present in StyleCachedImage/StyleImage & friends and only need to be added for some additional methods.
        (WebCore::CachedImage::image): FIXME
        (WebCore::CachedImage::imageForRenderer): Call lookupOrCreateImageForRenderer() instead of returning m_image, if it's not null. Its a no-op for non SVGImage derived objects.
        (WebCore::CachedImage::setContainerSizeForRenderer): For non-SVGImages, just pass on the size to the m_image. For SVGImages, associate the passed in renderer with the IntSize in the cache.
                                                             This does NOT create the SVGImage yet, this is delayed until imageForRenderer() is called for a given renderer that wants this size.
        (WebCore::CachedImage::imageSize): Don't operate on m_image, ask lookupImageForRenderer() with the incoming renderer.
        (WebCore::CachedImage::imageRect): Ditto.
        (WebCore::CachedImage::clear): Force clearing the m_svgImageCache.
        (WebCore::CachedImage::data): Call m_image->size() instead of imageSize(), to avoid having to pass a null renderer to imageSize() as here no renderer is available yet.
        (WebCore::CachedImage::destroyDecodedData): Don't destroy decoded data for SVG images, as m_data needs to be accessable at any time to construct a cloned SVGImage.
                                                    In future we don't need this anymore if we make sure multiple SVGImages share the same trees, but that's for a follow-up patch.
        (WebCore::CachedImage::decodedSizeChanged): Don't operate on m_image, ask lookupImageForRenderer() with the incoming renderer.
        (WebCore::CachedImage::didDraw): Ditto.
        (WebCore::CachedImage::shouldPauseAnimation): Ditto.
        (WebCore::CachedImage::animationAdvanced): Ditto.
        (WebCore::CachedImage::changedInRect): Ditto. (eg. when leaving out this change animated SVG images wouldn't update anymore, as the animation didn't happen on m_image!)
        * loader/cache/CachedImage.h: imageForRenderer/canRender/setContainerSizeForRenderer/imageSizeForRenderer now all take a RenderObject* parameter to identifiy the current user of the image.
        (WebCore::CachedImage::canRender): Pass on the incoming renderer to imageSizeForRenderer().
        * page/DragController.cpp:
        (WebCore::getImage): Use new CachedImage::imageForRenderer(RenderObject*) method.
        * page/EventHandler.cpp:
        (WebCore::EventHandler::selectCursor): Ditto.
        * page/PageSerializer.cpp:
        (WebCore::PageSerializer::serializeFrame): Ditto.
        (WebCore::PageSerializer::addImageToResources): Ditto.
        (WebCore::PageSerializer::retrieveResourcesForCSSDeclaration): Ditto.
        * page/PageSerializer.h:
        * platform/chromium/ClipboardChromium.cpp:
        (WebCore::writeImageToDataObject): Ditto.
        * platform/chromium/PasteboardChromium.cpp:
        (WebCore::Pasteboard::writeImage): Ditto.
        * platform/graphics/Image.h:
        (WebCore::Image::isSVGImage): Add boolean helper to identify SVGImages, just like isBitmapImage().
        * platform/gtk/ClipboardGtk.cpp:
        (WebCore::ClipboardGtk::declareAndWriteDragImage): Use new CachedImage::imageForRenderer(RenderObject*) method.
        * platform/gtk/PasteboardGtk.cpp:
        (WebCore::Pasteboard::writeImage): Ditto.
        * platform/mac/HTMLConverter.mm:
        (fileWrapperForElement): Ditto.
        * platform/mac/PasteboardMac.mm:
        (WebCore::Pasteboard::writeImage): Ditto.
        * platform/qt/ClipboardQt.cpp:
        (WebCore::ClipboardQt::declareAndWriteDragImage): Ditto.
        * platform/qt/PasteboardQt.cpp:
        (WebCore::Pasteboard::writeImage): Ditto.
        * platform/win/ClipboardWin.cpp:
        (WebCore::writeImageToDataObject): Ditto.
        * platform/win/PasteboardWin.cpp:
        (WebCore::Pasteboard::writeImage): Ditto.
        * platform/wince/PasteboardWinCE.cpp:
        (WebCore::Pasteboard::writeImage): Ditto.
        * rendering/HitTestResult.cpp:
        (WebCore::HitTestResult::image): Ditto.
        * rendering/ImageBySizeCache.cpp: Copied from WebCore/css/CSSImageGeneratorValue.cpp, to preserve history for the original cache code.
        (WebCore::ImageBySizeCache::ImageBySizeCache): Straight copy from CSSImageGeneratorValue, renamed to ImageBySizeCache, removing all but the cache relevant code.
        (WebCore::ImageBySizeCache::addClient): Ditto.
        (WebCore::ImageBySizeCache::removeClient): Ditto.
        (WebCore::ImageBySizeCache::getImage): Ditto.
        (WebCore::ImageBySizeCache::putImage): Ditto.
        (WebCore::ImageBySizeCache::clear): New function, that clears the cache, introduced for the needs of CachedImage.
        (WebCore::ImageBySizeCache::imageForSize): New function to query an Image* for a given IntSize, introduced for the needs of CachedImage.
        (WebCore::ImageBySizeCache::sizeForClient): New function to query an IntSize for a given renderer.
        * rendering/ImageBySizeCache.h: Copied from WebCore/css/CSSImageGeneratorValue.h.
        (WebCore::ImageBySizeCache::clients):
        * rendering/InlineFlowBox.cpp:
        (WebCore::InlineFlowBox::paintFillLayer): CachedImage::canRender() now takes a RenderObject* parameter.
        (WebCore::InlineFlowBox::paintBoxDecorations): Ditto.
        (WebCore::InlineFlowBox::paintMask): Ditto.
        * rendering/RenderBox.cpp:
        (WebCore::RenderBox::paintMaskImages): Ditto.
        (WebCore::RenderBox::repaintLayerRectsForImage): Ditto.
        * rendering/RenderBoxModelObject.cpp:
        (WebCore::RenderBoxModelObject::paintFillLayerExtended): Ditto.
        (WebCore::RenderBoxModelObject::calculateFillTileSize): Ditto (for CachedImage::setContainerSizeForRenderer()).
        (WebCore::RenderBoxModelObject::paintNinePieceImage): Ditto.
        * rendering/RenderImage.cpp:
        (WebCore::RenderImage::imageSizeForError): Use new CachedImage::imageForRenderer(RenderObject*) method.
        (WebCore::RenderImage::setImageSizeForAltText): Ditto.
        (WebCore::RenderImage::computeReplacedLogicalWidth): FIXME
        * rendering/RenderImageResource.cpp:
        (WebCore::RenderImageResource::setContainerSizeForRenderer): Pass on m_renderer to CachedImage::setContainerSizeForRenderer().
        * rendering/RenderImageResource.h: Remove constness from setContainerSizeForRenderer.
        (WebCore::RenderImageResource::image): Pass on m_renderer to CachedImage::image().
        (WebCore::RenderImageResource::imageSize): Pass on m_renderer to CachedImage::imageSizeForRenderer().
        * rendering/RenderImageResourceStyleImage.h:
        (WebCore::RenderImageResourceStyleImage::setContainerSizeForRenderer): Remove constness, pass on m_renderer to StyleImage::setContainerSizeForRenderer().
        * rendering/RenderLayerBacking.cpp:
        (WebCore::RenderLayerBacking::isDirectlyCompositedImage): Use new CachedImage::imageForRenderer(RenderObject*) method.
        (WebCore::RenderLayerBacking::updateImageContents): Ditto.
        * rendering/RenderListMarker.cpp:
        (WebCore::RenderListMarker::computePreferredLogicalWidths): CachedImage::setContainerSizeForRenderer() now takes a RenderObject* parameter.
        * rendering/RenderObject.cpp:
        (WebCore::mustRepaintFillLayers): CachedImage::canRender() now takes a RenderObject* parameter.
        (WebCore::RenderObject::borderImageIsLoadedAndCanBeRendered): Ditto.
        * rendering/style/StyleCachedImage.cpp:
        (WebCore::StyleCachedImage::canRender): Pass on incoming renderer to CachedImage::canRender().
        (WebCore::StyleCachedImage::imageSize): Pass on incoming renderer to CachedImage::imageSizeForRenderer().
        (WebCore::StyleCachedImage::setContainerSizeForRenderer): Pass on incoming renderer to CachedImage::setContainerSizeForRenderer().
        (WebCore::StyleCachedImage::addClient): Remove unneeded return statment in void method.
        (WebCore::StyleCachedImage::removeClient): Ditto.
        (WebCore::StyleCachedImage::image): Pass on incoming renderer to CachedImage::image().
        * rendering/style/StyleCachedImage.h: Add RenderObject* parameter to canRender()/setContainerSizeForRenderer(). image() already has one, that was unused so far.
        * rendering/style/StyleGeneratedImage.cpp: Inlined setContainerSizeForRenderer.
        * rendering/style/StyleGeneratedImage.h: 
        (WebCore::StyleGeneratedImage::setContainerSizeForRenderer): Add RenderObject* parameter.
        * rendering/style/StyleImage.h:
        (WebCore::StyleImage::canRender): Ditto.
        * rendering/style/StylePendingImage.h:
        (WebCore::StylePendingImage::setContainerSizeForRenderer): Ditto.
        * svg/SVGFEImageElement.cpp:
        (WebCore::SVGFEImageElement::build): Use new CachedImage::imageForRenderer(RenderObject*) method.
        * svg/graphics/SVGImage.cpp: Cleanup file, the include hack seems not needed anymore.
        (WebCore::SVGImage::setContainerSize): s/LayoutSize/IntSize/ to match the code in platform/.
        * svg/graphics/SVGImage.h: Ditto.
        (WebCore::SVGImage::isSVGImage): Return true.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@97448 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index ebe7453..1733232 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -304,7 +304,7 @@
     if (renderer && renderer->isImage()) {
         RenderImage* image = static_cast<WebCore::RenderImage*>(renderer);
         if (image->cachedImage() && !image->cachedImage()->errorOccurred())
-            return image->cachedImage()->image();
+            return image->cachedImage()->imageForRenderer(image);
     }
 
     return 0;
diff --git a/Source/WebCore/rendering/ImageBySizeCache.cpp b/Source/WebCore/rendering/ImageBySizeCache.cpp
new file mode 100644
index 0000000..4965bb9
--- /dev/null
+++ b/Source/WebCore/rendering/ImageBySizeCache.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "ImageBySizeCache.h"
+
+#include "Image.h"
+#include "IntSize.h"
+#include "IntSizeHash.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+ImageBySizeCache::ImageBySizeCache()
+{
+}
+
+void ImageBySizeCache::addClient(const RenderObject* renderer, const IntSize& size)
+{
+    if (!size.isEmpty())
+        m_sizes.add(size);
+    
+    RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+    if (it == m_clients.end())
+        m_clients.add(renderer, SizeCountPair(size, 1));
+    else {
+        SizeCountPair& sizeCount = it->second;
+        ++sizeCount.second;
+    }
+}
+
+void ImageBySizeCache::removeClient(const RenderObject* renderer)
+{
+    RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+    ASSERT(it != m_clients.end());
+
+    SizeCountPair& sizeCount = it->second;
+    IntSize size = sizeCount.first;
+    if (!size.isEmpty()) {
+        m_sizes.remove(size);
+        if (!m_sizes.contains(size))
+            m_images.remove(size);
+    }
+    
+    if (!--sizeCount.second)
+        m_clients.remove(renderer);
+}
+
+Image* ImageBySizeCache::getImage(const RenderObject* renderer, const IntSize& size)
+{
+    RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+    ASSERT(it != m_clients.end());
+
+    SizeCountPair& sizeCount = it->second;
+    IntSize oldSize = sizeCount.first;
+    if (oldSize != size) {
+        removeClient(renderer);
+        addClient(renderer, size);
+    }
+
+    // Don't generate an image for empty sizes.
+    if (size.isEmpty())
+        return 0;
+
+    // Look up the image in our cache.
+    return m_images.get(size).get();
+}
+
+void ImageBySizeCache::putImage(const IntSize& size, PassRefPtr<Image> image)
+{
+    m_images.add(size, image);
+}
+
+void ImageBySizeCache::clear()
+{
+    m_sizes.clear();
+    m_clients.clear();
+    m_images.clear();
+}
+
+Image* ImageBySizeCache::imageForSize(const IntSize& size) const
+{
+    HashMap<IntSize, RefPtr<Image> >::const_iterator it = m_images.find(size);
+    if (it == m_images.end())
+        return 0;
+    return it->second.get();
+}
+
+IntSize ImageBySizeCache::sizeForClient(const RenderObject* renderer) const
+{
+    RenderObjectSizeCountMap::const_iterator it = m_clients.find(renderer);
+    if (it == m_clients.end())
+        return IntSize();
+    return it->second.first;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/ImageBySizeCache.h b/Source/WebCore/rendering/ImageBySizeCache.h
new file mode 100644
index 0000000..404dba6
--- /dev/null
+++ b/Source/WebCore/rendering/ImageBySizeCache.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ImageBySizeCache_h
+#define ImageBySizeCache_h
+
+#include "IntSizeHash.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Image;
+class RenderObject;
+
+typedef pair<IntSize, int> SizeCountPair;
+typedef HashMap<const RenderObject*, SizeCountPair> RenderObjectSizeCountMap;
+
+class ImageBySizeCache {
+public:
+    ImageBySizeCache();
+
+    void addClient(const RenderObject*, const IntSize&);
+    void removeClient(const RenderObject*);
+
+    Image* getImage(const RenderObject*, const IntSize&);
+    void putImage(const IntSize&, PassRefPtr<Image>);
+
+    void clear();
+
+    Image* imageForSize(const IntSize&) const;
+    IntSize sizeForClient(const RenderObject*) const;
+    const RenderObjectSizeCountMap& clients() const { return m_clients; }
+
+private:
+    HashCountedSet<IntSize> m_sizes; // A count of how many times a given image size is in use.
+    RenderObjectSizeCountMap m_clients; // A map from RenderObjects (with entry count) to image sizes.
+    HashMap<IntSize, RefPtr<Image> > m_images; // A cache of Image objects by image size.
+};
+
+} // namespace WebCore
+
+#endif // ImageBySizeCache_h
diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp
index 4699bd8..5c49ddd 100644
--- a/Source/WebCore/rendering/InlineFlowBox.cpp
+++ b/Source/WebCore/rendering/InlineFlowBox.cpp
@@ -1074,7 +1074,7 @@
 void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
 {
     StyleImage* img = fillLayer->image();
-    bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());
+    bool hasFillImage = img && img->canRender(renderer(), renderer()->style()->effectiveZoom());
     if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
         boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
     else {
@@ -1206,7 +1206,7 @@
         if (parent() && renderer()->style()->hasBorder()) {
             const NinePieceImage& borderImage = renderer()->style()->borderImage();
             StyleImage* borderImageSource = borderImage.image();
-            bool hasBorderImage = borderImageSource && borderImageSource->canRender(styleToUse->effectiveZoom());
+            bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
             if (hasBorderImage && !borderImageSource->isLoaded())
                 return; // Don't paint anything while we wait for the image to load.
 
@@ -1280,7 +1280,7 @@
     LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
     paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), paintRect, compositeOp);
     
-    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom());
+    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer()->style()->effectiveZoom());
     if (!hasBoxImage || !maskBoxImage->isLoaded())
         return; // Don't paint anything while we wait for the image to load.
 
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 7044c16..707e581 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -1016,7 +1016,7 @@
             // We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering
             // before pushing the transparency layer.
             for (const FillLayer* fillLayer = maskLayers->next(); fillLayer; fillLayer = fillLayer->next()) {
-                if (fillLayer->image() && fillLayer->image()->canRender(style()->effectiveZoom())) {
+                if (fillLayer->image() && fillLayer->image()->canRender(this, style()->effectiveZoom())) {
                     pushTransparencyLayer = true;
                     // We found one image that can be used in rendering, exit the loop
                     break;
@@ -1130,7 +1130,7 @@
     RenderBox* layerRenderer = 0;
 
     for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
-        if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(style()->effectiveZoom())) {
+        if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, style()->effectiveZoom())) {
             // Now that we know this image is being used, compute the renderer and the rect
             // if we haven't already
             if (!layerRenderer) {
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index 5a743d0..a0a8717 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -629,7 +629,7 @@
 
     Color bgColor = color;
     StyleImage* bgImage = bgLayer->image();
-    bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(style()->effectiveZoom());
+    bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(this, style()->effectiveZoom());
     
     // When this style flag is set, change existing background colors and images to a solid white background.
     // If there's no bg color or image, leave it untouched to avoid affecting transparency.
@@ -803,7 +803,7 @@
 LayoutSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, LayoutSize positioningAreaSize) const
 {
     StyleImage* image = fillLayer->image();
-    image->setImageContainerSize(positioningAreaSize); // Use the box established by background-origin.
+    image->setContainerSizeForRenderer(this, positioningAreaSize); // Use the box established by background-origin.
 
     EFillSizeType type = fillLayer->size().type;
 
@@ -988,7 +988,7 @@
     if (!styleImage->isLoaded())
         return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
 
-    if (!styleImage->canRender(style->effectiveZoom()))
+    if (!styleImage->canRender(this, style->effectiveZoom()))
         return false;
 
     // FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
@@ -1005,7 +1005,7 @@
     LayoutUnit rightWithOutset = rect.maxX() + rightOutset;
     LayoutRect borderImageRect = LayoutRect(leftWithOutset, topWithOutset, rightWithOutset - leftWithOutset, bottomWithOutset - topWithOutset);
 
-    styleImage->setImageContainerSize(borderImageRect.size());
+    styleImage->setContainerSizeForRenderer(this, borderImageRect.size());
     LayoutSize imageSize = styleImage->imageSize(this, 1.0f);
     LayoutUnit imageWidth = imageSize.width();
     LayoutUnit imageHeight = imageSize.height();
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index d7fcaf4..ccb30f9 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -82,7 +82,7 @@
 IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
 {
     ASSERT_ARG(newImage, newImage);
-    ASSERT_ARG(newImage, newImage->image());
+    ASSERT_ARG(newImage, newImage->imageForRenderer(this));
 
     IntSize imageSize;
     if (newImage->willPaintBrokenImage()) {
@@ -91,7 +91,7 @@
         imageSize = brokenImageAndImageScaleFactor.first->size();
         imageSize.scale(1 / brokenImageAndImageScaleFactor.second);
     } else
-        imageSize = newImage->image()->size();
+        imageSize = newImage->imageForRenderer(this)->size();
 
     // imageSize() returns 0 for the error image. We need the true size of the
     // error image, so we have to get it by grabbing image() directly.
@@ -103,7 +103,7 @@
 bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
 {
     IntSize imageSize;
-    if (newImage && newImage->image())
+    if (newImage && newImage->imageForRenderer(this))
         imageSize = imageSizeForError(newImage);
     else if (!m_altText.isEmpty() || newImage) {
         // If we'll be displaying either text or an image, add a little padding.
@@ -518,7 +518,7 @@
     if (m_imageResource->imageHasRelativeWidth())
         if (RenderObject* cb = isPositioned() ? container() : containingBlock()) {
             if (cb->isBox())
-                m_imageResource->setImageContainerSize(LayoutSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight()));
+                m_imageResource->setContainerSizeForRenderer(LayoutSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight()));
         }
 
     LayoutUnit logicalWidth;
diff --git a/Source/WebCore/rendering/RenderImageResource.cpp b/Source/WebCore/rendering/RenderImageResource.cpp
index a943c3d..eb748f6 100644
--- a/Source/WebCore/rendering/RenderImageResource.cpp
+++ b/Source/WebCore/rendering/RenderImageResource.cpp
@@ -89,14 +89,11 @@
         m_renderer->repaint();
 }
 
-void RenderImageResource::setImageContainerSize(const IntSize& size) const
+void RenderImageResource::setContainerSizeForRenderer(const IntSize& imageContainerSize)
 {
     ASSERT(m_renderer);
-
-    if (!m_cachedImage)
-        return;
-
-    m_cachedImage->setImageContainerSize(size);
+    if (m_cachedImage)
+        m_cachedImage->setContainerSizeForRenderer(m_renderer, imageContainerSize);
 }
 
 Image* RenderImageResource::nullImage()
diff --git a/Source/WebCore/rendering/RenderImageResource.h b/Source/WebCore/rendering/RenderImageResource.h
index f1ec75b..ac24fba 100644
--- a/Source/WebCore/rendering/RenderImageResource.h
+++ b/Source/WebCore/rendering/RenderImageResource.h
@@ -54,15 +54,15 @@
 
     void resetAnimation();
 
-    virtual PassRefPtr<Image> image(int /* width */ = 0, int /* height */ = 0) const { return m_cachedImage ? m_cachedImage->image() : nullImage(); }
+    virtual PassRefPtr<Image> image(int /* width */ = 0, int /* height */ = 0) const { return m_cachedImage ? m_cachedImage->imageForRenderer(m_renderer) : nullImage(); }
     virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
 
-    virtual void setImageContainerSize(const IntSize& size) const;
+    virtual void setContainerSizeForRenderer(const IntSize&);
     virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; }
     virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; }
     virtual bool imageHasRelativeHeight() const { return m_cachedImage ? m_cachedImage->imageHasRelativeHeight() : false; }
 
-    virtual IntSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSize(multiplier) : IntSize(); }
+    virtual IntSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSizeForRenderer(m_renderer, multiplier) : IntSize(); }
 
     virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); }
 
diff --git a/Source/WebCore/rendering/RenderImageResourceStyleImage.h b/Source/WebCore/rendering/RenderImageResourceStyleImage.h
index 278a82c..fcad246 100644
--- a/Source/WebCore/rendering/RenderImageResourceStyleImage.h
+++ b/Source/WebCore/rendering/RenderImageResourceStyleImage.h
@@ -49,7 +49,7 @@
     virtual PassRefPtr<Image> image(int width = 0, int height = 0) const { return m_styleImage->image(m_renderer, IntSize(width, height)); }
     virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); }
 
-    virtual void setImageContainerSize(const IntSize& size) const { m_styleImage->setImageContainerSize(size); }
+    virtual void setContainerSizeForRenderer(const IntSize& size) { m_styleImage->setContainerSizeForRenderer(m_renderer, size); }
     virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); }
     virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); }
     virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); }
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 133537b..a715ef0 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -926,7 +926,7 @@
     RenderImage* imageRenderer = toRenderImage(renderObject);
     if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
         if (cachedImage->hasImage())
-            return cachedImage->image()->isBitmapImage();
+            return cachedImage->imageForRenderer(imageRenderer)->isBitmapImage();
     }
 
     return false;
@@ -963,7 +963,7 @@
     if (!cachedImage)
         return;
 
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(imageRenderer);
     if (!image)
         return;
 
diff --git a/Source/WebCore/rendering/RenderListMarker.cpp b/Source/WebCore/rendering/RenderListMarker.cpp
index e21ccca..876c809 100644
--- a/Source/WebCore/rendering/RenderListMarker.cpp
+++ b/Source/WebCore/rendering/RenderListMarker.cpp
@@ -1350,7 +1350,7 @@
         // FIXME: This is a somewhat arbitrary width.  Generated images for markers really won't become particularly useful
         // until we support the CSS3 marker pseudoclass to allow control over the width and height of the marker box.
         LayoutUnit bulletWidth = fontMetrics.ascent() / 2;
-        m_image->setImageContainerSize(LayoutSize(bulletWidth, bulletWidth));
+        m_image->setContainerSizeForRenderer(this, LayoutSize(bulletWidth, bulletWidth));
         LayoutSize imageSize = m_image->imageSize(this, style()->effectiveZoom());
         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHorizontalWritingMode() ? imageSize.width() : imageSize.height();
         setPreferredLogicalWidthsDirty(false);
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 3ccbd03..aaaa116 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -745,7 +745,7 @@
 
     // Make sure we have a valid image.
     StyleImage* img = layer->image();
-    if (!img || !img->canRender(renderer->style()->effectiveZoom()))
+    if (!img || !img->canRender(renderer, renderer->style()->effectiveZoom()))
         return false;
 
     if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
@@ -765,7 +765,7 @@
     ASSERT(style()->hasBorder());
 
     StyleImage* borderImage = style()->borderImage().image();
-    return borderImage && borderImage->canRender(style()->effectiveZoom()) && borderImage->isLoaded();
+    return borderImage && borderImage->canRender(this, style()->effectiveZoom()) && borderImage->isLoaded();
 }
 
 bool RenderObject::mustRepaintBackgroundOrBorder() const
diff --git a/Source/WebCore/rendering/style/StyleCachedImage.cpp b/Source/WebCore/rendering/style/StyleCachedImage.cpp
index 05cb0ea..2054742 100644
--- a/Source/WebCore/rendering/style/StyleCachedImage.cpp
+++ b/Source/WebCore/rendering/style/StyleCachedImage.cpp
@@ -34,9 +34,9 @@
     return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI);
 }
 
-bool StyleCachedImage::canRender(float multiplier) const
+bool StyleCachedImage::canRender(const RenderObject* renderer, float multiplier) const
 {
-    return m_image->canRender(multiplier);
+    return m_image->canRender(renderer, multiplier);
 }
 
 bool StyleCachedImage::isLoaded() const
@@ -49,9 +49,9 @@
     return m_image->errorOccurred();
 }
 
-IntSize StyleCachedImage::imageSize(const RenderObject* /*renderer*/, float multiplier) const
+IntSize StyleCachedImage::imageSize(const RenderObject* renderer, float multiplier) const
 {
-    return m_image->imageSize(multiplier);
+    return m_image->imageSizeForRenderer(renderer, multiplier);
 }
 
 bool StyleCachedImage::imageHasRelativeWidth() const
@@ -69,24 +69,24 @@
     return m_image->usesImageContainerSize();
 }
 
-void StyleCachedImage::setImageContainerSize(const IntSize& size)
+void StyleCachedImage::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& imageContainerSize)
 {
-    return m_image->setImageContainerSize(size);
+    m_image->setContainerSizeForRenderer(renderer, imageContainerSize);
 }
 
 void StyleCachedImage::addClient(RenderObject* renderer)
 {
-    return m_image->addClient(renderer);
+    m_image->addClient(renderer);
 }
 
 void StyleCachedImage::removeClient(RenderObject* renderer)
 {
-    return m_image->removeClient(renderer);
+    m_image->removeClient(renderer);
 }
 
-PassRefPtr<Image> StyleCachedImage::image(RenderObject*, const IntSize&) const
+PassRefPtr<Image> StyleCachedImage::image(RenderObject* renderer, const IntSize&) const
 {
-    return m_image->image();
+    return m_image->imageForRenderer(renderer);
 }
 
 }
diff --git a/Source/WebCore/rendering/style/StyleCachedImage.h b/Source/WebCore/rendering/style/StyleCachedImage.h
index 17bf596..0c714ec 100644
--- a/Source/WebCore/rendering/style/StyleCachedImage.h
+++ b/Source/WebCore/rendering/style/StyleCachedImage.h
@@ -40,14 +40,14 @@
     
     CachedImage* cachedImage() const { return m_image.get(); }
 
-    virtual bool canRender(float multiplier) const;
+    virtual bool canRender(const RenderObject*, float multiplier) const;
     virtual bool isLoaded() const;
     virtual bool errorOccurred() const;
     virtual IntSize imageSize(const RenderObject*, float multiplier) const;
     virtual bool imageHasRelativeWidth() const;
     virtual bool imageHasRelativeHeight() const;
     virtual bool usesImageContainerSize() const;
-    virtual void setImageContainerSize(const IntSize&);
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&);
     virtual void addClient(RenderObject*);
     virtual void removeClient(RenderObject*);
     virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
diff --git a/Source/WebCore/rendering/style/StyleGeneratedImage.cpp b/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
index 9889818..f5c74d2 100644
--- a/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
+++ b/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
@@ -58,11 +58,6 @@
     return m_containerSize;
 }
 
-void StyleGeneratedImage::setImageContainerSize(const IntSize& size)
-{
-    m_containerSize = size;
-}
-
 void StyleGeneratedImage::addClient(RenderObject* renderer)
 {
     m_generator->addClient(renderer, IntSize());
diff --git a/Source/WebCore/rendering/style/StyleGeneratedImage.h b/Source/WebCore/rendering/style/StyleGeneratedImage.h
index b79d3f3..167362f 100644
--- a/Source/WebCore/rendering/style/StyleGeneratedImage.h
+++ b/Source/WebCore/rendering/style/StyleGeneratedImage.h
@@ -46,7 +46,7 @@
     virtual bool imageHasRelativeWidth() const { return !m_fixedSize; }
     virtual bool imageHasRelativeHeight() const { return !m_fixedSize; }
     virtual bool usesImageContainerSize() const { return !m_fixedSize; }
-    virtual void setImageContainerSize(const IntSize&);
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize& containerSize) { m_containerSize = containerSize; }
     virtual void addClient(RenderObject*);
     virtual void removeClient(RenderObject*);
     virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
diff --git a/Source/WebCore/rendering/style/StyleImage.h b/Source/WebCore/rendering/style/StyleImage.h
index 13c5030..42a521e 100644
--- a/Source/WebCore/rendering/style/StyleImage.h
+++ b/Source/WebCore/rendering/style/StyleImage.h
@@ -49,14 +49,14 @@
 
     virtual PassRefPtr<CSSValue> cssValue() const = 0;
 
-    virtual bool canRender(float /*multiplier*/) const { return true; }
+    virtual bool canRender(const RenderObject*, float /*multiplier*/) const { return true; }
     virtual bool isLoaded() const { return true; }
     virtual bool errorOccurred() const { return false; }
     virtual IntSize imageSize(const RenderObject*, float multiplier) const = 0;
     virtual bool imageHasRelativeWidth() const = 0;
     virtual bool imageHasRelativeHeight() const = 0;
     virtual bool usesImageContainerSize() const = 0;
-    virtual void setImageContainerSize(const IntSize&) = 0;
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&) = 0;
     virtual void addClient(RenderObject*) = 0;
     virtual void removeClient(RenderObject*) = 0;
     virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const = 0;
diff --git a/Source/WebCore/rendering/style/StylePendingImage.h b/Source/WebCore/rendering/style/StylePendingImage.h
index 62cce7f..a577e23 100644
--- a/Source/WebCore/rendering/style/StylePendingImage.h
+++ b/Source/WebCore/rendering/style/StylePendingImage.h
@@ -48,7 +48,7 @@
     virtual bool imageHasRelativeWidth() const { return false; }
     virtual bool imageHasRelativeHeight() const { return false; }
     virtual bool usesImageContainerSize() const { return false; }
-    virtual void setImageContainerSize(const IntSize&) { }
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&) { }
     virtual void addClient(RenderObject*) { }
     virtual void removeClient(RenderObject*) { }
     virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const