2011-10-13 Nikolas Zimmermann <nzimmermann@rim.com>
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2011 08:08:51 +0000 (08:08 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Oct 2011 08:08:51 +0000 (08:08 +0000)
        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: https://svn.webkit.org/repository/webkit/trunk@97448 268f45cc-cd09-0410-ab3c-d52691b4dbfc

61 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.pro
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Source/WebCore/bindings/objc/DOM.mm
Source/WebCore/bridge/qt/qt_pixmapruntime.cpp
Source/WebCore/css/CSSCanvasValue.cpp
Source/WebCore/css/CSSGradientValue.cpp
Source/WebCore/css/CSSImageGeneratorValue.cpp
Source/WebCore/css/CSSImageGeneratorValue.h
Source/WebCore/editing/DeleteButtonController.cpp
Source/WebCore/html/HTMLImageElement.cpp
Source/WebCore/html/ImageDocument.cpp
Source/WebCore/html/canvas/CanvasRenderingContext.cpp
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/html/canvas/WebGLRenderingContext.cpp
Source/WebCore/loader/cache/CachedImage.cpp
Source/WebCore/loader/cache/CachedImage.h
Source/WebCore/page/DragController.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/PageSerializer.cpp
Source/WebCore/page/PageSerializer.h
Source/WebCore/platform/chromium/ClipboardChromium.cpp
Source/WebCore/platform/chromium/PasteboardChromium.cpp
Source/WebCore/platform/graphics/Image.h
Source/WebCore/platform/gtk/ClipboardGtk.cpp
Source/WebCore/platform/gtk/PasteboardGtk.cpp
Source/WebCore/platform/mac/HTMLConverter.mm
Source/WebCore/platform/mac/PasteboardMac.mm
Source/WebCore/platform/qt/ClipboardQt.cpp
Source/WebCore/platform/qt/PasteboardQt.cpp
Source/WebCore/platform/win/ClipboardWin.cpp
Source/WebCore/platform/win/PasteboardWin.cpp
Source/WebCore/platform/wince/PasteboardWinCE.cpp
Source/WebCore/rendering/HitTestResult.cpp
Source/WebCore/rendering/ImageBySizeCache.cpp [new file with mode: 0644]
Source/WebCore/rendering/ImageBySizeCache.h [new file with mode: 0644]
Source/WebCore/rendering/InlineFlowBox.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBoxModelObject.cpp
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/rendering/RenderImageResource.cpp
Source/WebCore/rendering/RenderImageResource.h
Source/WebCore/rendering/RenderImageResourceStyleImage.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/RenderListMarker.cpp
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/style/StyleCachedImage.cpp
Source/WebCore/rendering/style/StyleCachedImage.h
Source/WebCore/rendering/style/StyleGeneratedImage.cpp
Source/WebCore/rendering/style/StyleGeneratedImage.h
Source/WebCore/rendering/style/StyleImage.h
Source/WebCore/rendering/style/StylePendingImage.h
Source/WebCore/svg/SVGFEImageElement.cpp
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImage.h

index 1051c0c..b97580b 100644 (file)
@@ -1199,6 +1199,7 @@ SET(WebCore_SOURCES
     rendering/FixedTableLayout.cpp
     rendering/HitTestingTransformState.cpp
     rendering/HitTestResult.cpp
+    rendering/ImageBySizeCache.cpp
     rendering/InlineBox.cpp
     rendering/InlineFlowBox.cpp
     rendering/InlineTextBox.cpp
index 826de3e..82d03e9 100644 (file)
@@ -1,3 +1,224 @@
+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.
+
 2011-10-13  Kenichi Ishibashi  <bashi@chromium.org>
 
         [Chromium] Uninitialized read in WebCore::*Font* / HB_GSUB_Select_Feature
index 024d170..3aed5ab 100644 (file)
@@ -2968,6 +2968,8 @@ webcore_sources += \
        Source/WebCore/rendering/HitTestingTransformState.h \
        Source/WebCore/rendering/HitTestResult.cpp \
        Source/WebCore/rendering/HitTestResult.h \
+       Source/WebCore/rendering/ImageBySizeCache.cpp \
+       Source/WebCore/rendering/ImageBySizeCache.h \
        Source/WebCore/rendering/InlineBox.cpp \
        Source/WebCore/rendering/InlineBox.h \
        Source/WebCore/rendering/InlineFlowBox.cpp \
index 938cd81..3012e4d 100644 (file)
@@ -1105,7 +1105,7 @@ __ZNK7WebCore10ScrollView16windowToContentsERKNS_7IntRectE
 __ZNK7WebCore10ScrollView16contentsToWindowERKNS_8IntPointE
 __ZNK7WebCore10ScrollView16windowToContentsERKNS_8IntPointE
 __ZNK7WebCore10ScrollView18visibleContentRectEb
-__ZNK7WebCore11CachedImage5imageEv
+__ZN7WebCore11CachedImage5imageEv
 __ZNK7WebCore11FrameLoader10isCompleteEv
 __ZNK7WebCore11FrameLoader14cancelledErrorERKNS_15ResourceRequestE
 __ZNK7WebCore11FrameLoader14frameHasLoadedEv
index 3b8813d..1183c8a 100644 (file)
             'rendering/GapRects.h',
             'rendering/HitTestRequest.h',
             'rendering/HitTestResult.h',
+            'rendering/ImageBySizeCache.h',
             'rendering/InlineBox.h',
             'rendering/InlineFlowBox.h',
             'rendering/InlineTextBox.h',
             'rendering/HitTestingTransformState.cpp',
             'rendering/HitTestingTransformState.h',
             'rendering/HitTestResult.cpp',
+            'rendering/ImageBySizeCache.cpp',
             'rendering/InlineBox.cpp',
             'rendering/InlineFlowBox.cpp',
             'rendering/InlineIterator.h',
index a8e3331..2e30ac9 100644 (file)
@@ -1121,6 +1121,7 @@ SOURCES += \
     rendering/FixedTableLayout.cpp \
     rendering/HitTestingTransformState.cpp \
     rendering/HitTestResult.cpp \
+    rendering/ImageBySizeCache.cpp \
     rendering/InlineBox.cpp \
     rendering/InlineFlowBox.cpp \
     rendering/InlineTextBox.cpp \
@@ -2181,6 +2182,7 @@ HEADERS += \
     rendering/FixedTableLayout.h \
     rendering/HitTestingTransformState.h \
     rendering/HitTestResult.h \
+    rendering/ImageBySizeCache.h \
     rendering/InlineBox.h \
     rendering/InlineFlowBox.h \
     rendering/InlineTextBox.h \
index 56602fa..bdd7348 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\rendering\ImageBySizeCache.cpp"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\rendering\ImageBySizeCache.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\rendering\InlineBox.cpp"
                                >
                                <FileConfiguration
index 024a8f1..f841c21 100644 (file)
                6EBF0E7712A9868800DB1709 /* JSOESTextureFloat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EBF0E7512A9868800DB1709 /* JSOESTextureFloat.h */; };
                6EE8A77210F803F3005A4A24 /* JSWebGLContextAttributes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */; };
                6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */; };
+               71CCB49C144824AC00C676D6 /* ImageBySizeCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 71CCB49A144824AC00C676D6 /* ImageBySizeCache.cpp */; };
+               71CCB49D144824AC00C676D6 /* ImageBySizeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 71CCB49B144824AC00C676D6 /* ImageBySizeCache.h */; };
                71FB967B1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 71FB967A1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h */; settings = {ATTRIBUTES = (Private, ); }; };
                72626E020EF022FE00A07E20 /* FontFastPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 72626E010EF022FE00A07E20 /* FontFastPath.cpp */; };
                750D029311D0E7F300BD1B27 /* RenderInputSpeech.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 750D029111D0E7F300BD1B27 /* RenderInputSpeech.cpp */; };
                6EBF0E7512A9868800DB1709 /* JSOESTextureFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSOESTextureFloat.h; sourceTree = "<group>"; };
                6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
                6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
+               71CCB49A144824AC00C676D6 /* ImageBySizeCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageBySizeCache.cpp; sourceTree = "<group>"; };
+               71CCB49B144824AC00C676D6 /* ImageBySizeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBySizeCache.h; sourceTree = "<group>"; };
                71FB967A1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedEnumerationPropertyTearOff.h; sourceTree = "<group>"; };
                72626E010EF022FE00A07E20 /* FontFastPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFastPath.cpp; sourceTree = "<group>"; };
                750D029111D0E7F300BD1B27 /* RenderInputSpeech.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderInputSpeech.cpp; sourceTree = "<group>"; };
                                930908900AF7EDE40081DF01 /* HitTestRequest.h */,
                                9307F1D50AF2D59000DBA31A /* HitTestResult.cpp */,
                                9307F1D60AF2D59000DBA31A /* HitTestResult.h */,
+                               71CCB49A144824AC00C676D6 /* ImageBySizeCache.cpp */,
+                               71CCB49B144824AC00C676D6 /* ImageBySizeCache.h */,
                                A8CFF5DF0A155A05000A4234 /* InlineBox.cpp */,
                                A8CFF5DE0A155A05000A4234 /* InlineBox.h */,
                                A8CFF5DD0A155A05000A4234 /* InlineFlowBox.cpp */,
                                3106037B143281CD00ABF4BA /* DOMWebKitCSSFilterValueInternal.h in Headers */,
                                29ACB212143E7128006BCA5F /* AccessibilityMockObject.h in Headers */,
                                49AF2D6914435D050016A784 /* DisplayRefreshMonitor.h in Headers */,
+                               71CCB49D144824AC00C676D6 /* ImageBySizeCache.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                0F09087F1444FDB200028917 /* ScrollbarTheme.cpp in Sources */,
                                49AF2D6C14435D210016A784 /* DisplayRefreshMonitorMac.cpp in Sources */,
                                49FC7A501444AF5F00A5D864 /* DisplayRefreshMonitor.cpp in Sources */,
+                               71CCB49C144824AC00C676D6 /* ImageBySizeCache.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index f94756c..8409836 100644 (file)
@@ -1913,7 +1913,7 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
             
             // check whether rendered image was stretched from one-dimensional file image
             if (image->cachedImage()) {
-                LayoutSize imageSize = image->cachedImage()->imageSize(image->view()->zoomFactor());
+                LayoutSize imageSize = image->cachedImage()->imageSizeForRenderer(m_renderer, image->view()->zoomFactor());
                 return imageSize.height() <= 1 || imageSize.width() <= 1;
             }
         }
index a18cb03..7c55c6d 100644 (file)
@@ -439,7 +439,7 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget)
     WebCore::CachedImage* cachedImage = static_cast<WebCore::RenderImage*>(renderer)->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return nil;
-    return cachedImage->image()->getNSImage();
+    return cachedImage->imageForRenderer(renderer)->getNSImage();
 }
 
 @end
@@ -464,7 +464,7 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget)
     WebCore::CachedImage* cachedImage = static_cast<WebCore::RenderImage*>(renderer)->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return nil;
-    return (NSData *)cachedImage->image()->getTIFFRepresentation();
+    return (NSData *)cachedImage->imageForRenderer(renderer)->getTIFFRepresentation();
 }
 
 - (NSURL *)_getURLAttribute:(NSString *)name
index eb17fdb..9c1cdad 100644 (file)
@@ -378,7 +378,7 @@ QVariant QtPixmapInstance::variantFromObject(JSObject* object, QMetaType::Type h
         if (!cachedImage)
             goto returnEmptyVariant;
 
-        Image* image = cachedImage->image();
+        Image* image = cachedImage->imageForRenderer(imageElement->renderer());
         if (!image)
             goto returnEmptyVariant;
 
index 7f61d25..3473963 100644 (file)
@@ -47,16 +47,16 @@ String CSSCanvasValue::cssText() const
 void CSSCanvasValue::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect)
 {
     IntRect imageChangeRect = enclosingIntRect(changedRect);
-    RenderObjectSizeCountMap::const_iterator end = m_clients.end();
-    for (RenderObjectSizeCountMap::const_iterator curr = m_clients.begin(); curr != end; ++curr)
-        curr->first->imageChanged(static_cast<WrappedImagePtr>(this), &imageChangeRect);
+    RenderObjectSizeCountMap::const_iterator end = clients().end();
+    for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)
+        const_cast<RenderObject*>(curr->first)->imageChanged(static_cast<WrappedImagePtr>(this), &imageChangeRect);
 }
 
 void CSSCanvasValue::canvasResized(HTMLCanvasElement*)
 {
-    RenderObjectSizeCountMap::const_iterator end = m_clients.end();
-    for (RenderObjectSizeCountMap::const_iterator curr = m_clients.begin(); curr != end; ++curr)
-        curr->first->imageChanged(static_cast<WrappedImagePtr>(this));
+    RenderObjectSizeCountMap::const_iterator end = clients().end();
+    for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)
+        const_cast<RenderObject*>(curr->first)->imageChanged(static_cast<WrappedImagePtr>(this));
 }
 
 void CSSCanvasValue::canvasDestroyed(HTMLCanvasElement* element)
@@ -85,7 +85,7 @@ HTMLCanvasElement* CSSCanvasValue::element(Document* document)
 
 PassRefPtr<Image> CSSCanvasValue::image(RenderObject* renderer, const IntSize& /*size*/)
 {
-    ASSERT(m_clients.contains(renderer));
+    ASSERT(clients().contains(renderer));
     HTMLCanvasElement* elt = element(renderer->document());
     if (!elt || !elt->buffer())
         return 0;
index 24e63db..266e4e9 100644 (file)
@@ -48,7 +48,7 @@ PassRefPtr<Image> CSSGradientValue::image(RenderObject* renderer, const IntSize&
 
     bool cacheable = isCacheable();
     if (cacheable) {
-        if (!m_clients.contains(renderer))
+        if (!clients().contains(renderer))
             return 0;
 
         // Need to look up our size.  Create a string of width*height to use as a hash key.
index 784f438..cf18f6a 100644 (file)
@@ -47,62 +47,25 @@ CSSImageGeneratorValue::~CSSImageGeneratorValue()
 void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size)
 {
     ref();
-    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;
-    }
+    m_imageCache.addClient(renderer, size);
 }
 
 void CSSImageGeneratorValue::removeClient(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);
-
+    m_imageCache.removeClient(renderer);
     deref();
 }
 
 Image* CSSImageGeneratorValue::getImage(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) {
-        // If renderer is the only client, make sure we don't delete this.
-        RefPtr<CSSImageGeneratorValue> protect(this);
-        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();
+    // If renderer is the only client, make sure we don't delete this, if the size changes (as this will result in addClient/removeClient calls).
+    RefPtr<CSSImageGeneratorValue> protect(this);
+    return m_imageCache.getImage(renderer, size);
 }
 
 void CSSImageGeneratorValue::putImage(const IntSize& size, PassRefPtr<Image> image)
 {
-    m_images.add(size, image);
+    m_imageCache.putImage(size, image);
 }
 
 StyleGeneratedImage* CSSImageGeneratorValue::generatedImage()
index 46524fb..a53c965 100644 (file)
 #define CSSImageGeneratorValue_h
 
 #include "CSSValue.h"
-#include "IntSizeHash.h"
-#include <wtf/HashMap.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/RefPtr.h>
+#include "ImageBySizeCache.h"
 
 namespace WebCore {
 
@@ -56,14 +53,9 @@ protected:
     
     Image* getImage(RenderObject*, const IntSize&);
     void putImage(const IntSize&, PassRefPtr<Image>);
+    const RenderObjectSizeCountMap& clients() const { return m_imageCache.clients(); }
 
-    typedef pair<IntSize, int> SizeCountPair;
-    typedef HashMap<RenderObject*, SizeCountPair> RenderObjectSizeCountMap;
-
-    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.
-    
+    ImageBySizeCache m_imageCache;
     RefPtr<StyleGeneratedImage> m_image;
     bool m_accessedImage;
 
index 046d67d..dcabe1a 100644 (file)
@@ -115,7 +115,7 @@ static bool isDeletableElement(const Node* node)
         // Allow blocks that have background images
         if (style->hasBackgroundImage()) {
             for (const FillLayer* background = style->backgroundLayers(); background; background = background->next()) {
-                if (background->image() && background->image()->canRender(1))
+                if (background->image() && background->image()->canRender(renderer, 1))
                     return true;
             }
         }
index 357f116..8eebc49 100644 (file)
@@ -257,7 +257,7 @@ int HTMLImageElement::width(bool ignorePendingStylesheets)
 
         // if the image is available, use its width
         if (m_imageLoader.image())
-            return m_imageLoader.image()->imageSize(1.0f).width();
+            return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).width();
     }
 
     if (ignorePendingStylesheets)
@@ -280,7 +280,7 @@ int HTMLImageElement::height(bool ignorePendingStylesheets)
 
         // if the image is available, use its height
         if (m_imageLoader.image())
-            return m_imageLoader.image()->imageSize(1.0f).height();
+            return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height();
     }
 
     if (ignorePendingStylesheets)
@@ -297,7 +297,7 @@ int HTMLImageElement::naturalWidth() const
     if (!m_imageLoader.image())
         return 0;
 
-    return m_imageLoader.image()->imageSize(1.0f).width();
+    return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).width();
 }
 
 int HTMLImageElement::naturalHeight() const
@@ -305,7 +305,7 @@ int HTMLImageElement::naturalHeight() const
     if (!m_imageLoader.image())
         return 0;
 
-    return m_imageLoader.image()->imageSize(1.0f).height();
+    return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height();
 }
 
 bool HTMLImageElement::isURLAttribute(Attribute* attr) const
index 4617b6f..e53316e 100644 (file)
@@ -155,7 +155,7 @@ void ImageDocumentParser::finish()
 
         // Report the natural image size in the page title, regardless of zoom
         // level.
-        LayoutSize size = cachedImage->imageSize(1.0f);
+        LayoutSize size = cachedImage->imageSizeForRenderer(document()->imageElement()->renderer(), 1.0f);
         if (size.width()) {
             // Compute the title, we use the decoded filename of the resource, falling
             // back on the (decoded) hostname if there is no path.
@@ -233,8 +233,8 @@ float ImageDocument::scale() const
     if (!view)
         return 1;
 
-    LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(pageZoomFactor(this));
-    LayoutSize windowSize = IntSize(view->width(), view->height());
+    LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
+    LayoutSize windowSize = LayoutSize(view->width(), view->height());
     
     float widthScale = (float)windowSize.width() / imageSize.width();
     float heightScale = (float)windowSize.height() / imageSize.height();
@@ -247,7 +247,7 @@ void ImageDocument::resizeImageToFit()
     if (!m_imageElement)
         return;
 
-    LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(pageZoomFactor(this));
+    LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
 
     float scale = this->scale();
     m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale));
@@ -287,7 +287,7 @@ void ImageDocument::imageUpdated()
     if (m_imageSizeIsKnown)
         return;
 
-    if (m_imageElement->cachedImage()->imageSize(pageZoomFactor(this)).isEmpty())
+    if (m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this)).isEmpty())
         return;
     
     m_imageSizeIsKnown = true;
@@ -303,8 +303,9 @@ void ImageDocument::restoreImageSize()
     if (!m_imageElement || !m_imageSizeIsKnown)
         return;
     
-    m_imageElement->setWidth(m_imageElement->cachedImage()->imageSize(pageZoomFactor(this)).width());
-    m_imageElement->setHeight(m_imageElement->cachedImage()->imageSize(pageZoomFactor(this)).height());
+    LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
+    m_imageElement->setWidth(imageSize.width());
+    m_imageElement->setHeight(imageSize.height());
     
     ExceptionCode ec;
     if (imageFitsInWindow())
@@ -324,7 +325,7 @@ bool ImageDocument::imageFitsInWindow() const
     if (!view)
         return true;
 
-    LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(pageZoomFactor(this));
+    LayoutSize imageSize = m_imageElement->cachedImage()->imageSizeForRenderer(m_imageElement->renderer(), pageZoomFactor(this));
     LayoutSize windowSize = LayoutSize(view->width(), view->height());
     
     return imageSize.width() <= windowSize.width() && imageSize.height() <= windowSize.height();    
index 0ad9b0d..b632045 100644 (file)
@@ -61,7 +61,7 @@ bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* image)
         return false;
 
     CachedImage* cachedImage = image->cachedImage();
-    if (!cachedImage->image()->hasSingleSecurityOrigin())
+    if (!cachedImage->imageForRenderer(image->renderer())->hasSingleSecurityOrigin())
         return true;
 
     return wouldTaintOrigin(cachedImage->response().url()) && !cachedImage->passesAccessControlCheck(canvas()->securityOrigin());
index 9e9ff0d..dc00077 100644 (file)
@@ -83,9 +83,9 @@ using namespace HTMLNames;
 
 static const char* const defaultFont = "10px sans-serif";
 
-static bool isOriginClean(CachedImage* cachedImage, SecurityOrigin* securityOrigin)
+static bool isOriginClean(CachedImage* cachedImage, HTMLImageElement* image, SecurityOrigin* securityOrigin)
 {
-    if (!cachedImage->image()->hasSingleSecurityOrigin())
+    if (!cachedImage->imageForRenderer(image->renderer())->hasSingleSecurityOrigin())
         return false;
     if (cachedImage->passesAccessControlCheck(securityOrigin))
         return true;
@@ -1220,7 +1220,7 @@ void CanvasRenderingContext2D::applyShadow()
 static LayoutSize size(HTMLImageElement* image)
 {
     if (CachedImage* cachedImage = image->cachedImage())
-        return cachedImage->imageSize(1.0f); // FIXME: Not sure about this.
+        return cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this.
     return IntSize();
 }
 
@@ -1320,7 +1320,7 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec
 
     checkOrigin(image);
 
-    c->drawImage(cachedImage->image(), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op);
+    c->drawImage(cachedImage->imageForRenderer(image->renderer()), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op);
     didDraw(normalizedDstRect);
 }
 
@@ -1631,11 +1631,11 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme
         return 0;
 
     CachedImage* cachedImage = image->cachedImage();
-    if (!cachedImage || !image->cachedImage()->image())
+    if (!cachedImage || !image->cachedImage()->imageForRenderer(image->renderer()))
         return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true);
 
-    bool originClean = isOriginClean(cachedImage, canvas()->securityOrigin());
-    return CanvasPattern::create(cachedImage->image(), repeatX, repeatY, originClean);
+    bool originClean = isOriginClean(cachedImage, image, canvas()->securityOrigin());
+    return CanvasPattern::create(cachedImage->imageForRenderer(image->renderer()), repeatX, repeatY, originClean);
 }
 
 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas,
index 1a9cd15..2fe6ead 100644 (file)
@@ -3172,7 +3172,7 @@ void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum
         return;
     }
 
-    texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
+    texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 }
 
@@ -3373,7 +3373,7 @@ void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din
         ec = SECURITY_ERR;
         return;
     }
-    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->imageForRenderer(image->renderer()),
                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 }
 
index f7c35b6..fed4c0c 100644 (file)
@@ -129,7 +129,28 @@ bool CachedImage::willPaintBrokenImage() const
     return errorOccurred() && m_shouldPaintBrokenImage;
 }
 
-Image* CachedImage::image() const
+Image* CachedImage::lookupImageForSize(const IntSize& size) const
+{
+    // FIXME: Add logic for this in webkit.org/b/47156.
+    UNUSED_PARAM(size);
+    return m_image.get();
+}
+
+Image* CachedImage::lookupImageForRenderer(const RenderObject* renderer) const
+{
+    // FIXME: Add logic for this in webkit.org/b/47156.
+    UNUSED_PARAM(renderer);
+    return m_image.get();
+}
+
+PassRefPtr<Image> CachedImage::lookupOrCreateImageForRenderer(const RenderObject* renderer)
+{
+    // FIXME: Add logic for this in webkit.org/b/47156.
+    UNUSED_PARAM(renderer);
+    return m_image;
+}
+
+Image* CachedImage::image()
 {
     ASSERT(!isPurgeable());
 
@@ -146,10 +167,31 @@ Image* CachedImage::image() const
     return Image::nullImage();
 }
 
-void CachedImage::setImageContainerSize(const IntSize& containerSize)
+Image* CachedImage::imageForRenderer(const RenderObject* renderer)
 {
+    ASSERT(!isPurgeable());
+
+    if (errorOccurred() && m_shouldPaintBrokenImage) {
+        // Returning the 1x broken image is non-ideal, but we cannot reliably access the appropriate
+        // deviceScaleFactor from here. It is critical that callers use CachedImage::brokenImage() 
+        // when they need the real, deviceScaleFactor-appropriate broken image icon. 
+        return brokenImage(1).first;
+    }
+
     if (m_image)
-        m_image->setContainerSize(containerSize);
+        return lookupOrCreateImageForRenderer(renderer).get();
+
+    return Image::nullImage();
+}
+
+void CachedImage::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& containerSize)
+{
+    if (!m_image)
+        return;
+
+    // FIXME: Add logic for this in webkit.org/b/47156.
+    UNUSED_PARAM(renderer);
+    m_image->setContainerSize(containerSize);
 }
 
 bool CachedImage::usesImageContainerSize() const
@@ -176,11 +218,12 @@ bool CachedImage::imageHasRelativeHeight() const
     return false;
 }
 
-IntSize CachedImage::imageSize(float multiplier) const
+IntSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float multiplier)
 {
     ASSERT(!isPurgeable());
 
-    if (!m_image)
+    Image* image = lookupImageForRenderer(renderer);
+    if (!image)
         return IntSize();
     if (multiplier == 1.0f)
         return m_image->size();
@@ -197,35 +240,6 @@ IntSize CachedImage::imageSize(float multiplier) const
     return IntSize(width, height);
 }
 
-IntRect CachedImage::imageRect(float multiplier) const
-{
-    ASSERT(!isPurgeable());
-
-    if (!m_image)
-        return IntRect();
-    if (multiplier == 1.0f || (!m_image->hasRelativeWidth() && !m_image->hasRelativeHeight()))
-        return m_image->rect();
-
-    float widthMultiplier = (m_image->hasRelativeWidth() ? 1.0f : multiplier);
-    float heightMultiplier = (m_image->hasRelativeHeight() ? 1.0f : multiplier);
-
-    // Don't let images that have a width/height >= 1 shrink below 1 when zoomed.
-    bool hasWidth = m_image->rect().width() > 0;
-    bool hasHeight = m_image->rect().height() > 0;
-
-    int width = static_cast<int>(m_image->rect().width() * widthMultiplier);
-    int height = static_cast<int>(m_image->rect().height() * heightMultiplier);
-    if (hasWidth)
-        width = max(1, width);
-    if (hasHeight)
-        height = max(1, height);
-
-    int x = static_cast<int>(m_image->rect().x() * widthMultiplier);
-    int y = static_cast<int>(m_image->rect().y() * heightMultiplier);
-
-    return IntRect(x, y, width, height);
-}
-
 void CachedImage::notifyObservers(const IntRect* changeRect)
 {
     CachedResourceClientWalker<CachedImageClient> w(m_clients);
@@ -245,6 +259,7 @@ void CachedImage::checkShouldPaintBrokenImage()
 void CachedImage::clear()
 {
     destroyDecodedData();
+    m_svgImageCache.clear();
     m_image = 0;
     setEncodedSize(0);
 }
@@ -297,7 +312,7 @@ void CachedImage::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
     // to decode.
     if (sizeAvailable || allDataReceived) {
         size_t maxDecodedImageSize = maximumDecodedImageSize();
-        IntSize s = imageSize(1.0f);
+        IntSize s = m_image->size();
         size_t estimatedDecodedImageSize = s.width() * s.height() * 4; // no overflow check
         if (m_image->isNull() || (maxDecodedImageSize > 0 && estimatedDecodedImageSize > maxDecodedImageSize)) {
             error(errorOccurred() ? status() : DecodeError);
@@ -342,13 +357,16 @@ void CachedImage::destroyDecodedData()
         setDecodedSize(0);
         if (!MemoryCache::shouldMakeResourcePurgeableOnEviction())
             makePurgeable(true);
-    } else if (m_image && !errorOccurred())
+    } else if (m_image && !errorOccurred() && !m_image->isSVGImage())
         m_image->destroyDecodedData();
 }
 
 void CachedImage::decodedSizeChanged(const Image* image, int delta)
 {
-    if (image != m_image)
+    if (!image)
+        return;
+    Image* useImage = lookupImageForSize(image->size());
+    if (image != useImage)
         return;
     
     setDecodedSize(decodedSize() + delta);
@@ -356,7 +374,10 @@ void CachedImage::decodedSizeChanged(const Image* image, int delta)
 
 void CachedImage::didDraw(const Image* image)
 {
-    if (image != m_image)
+    if (!image)
+        return;
+    Image* useImage = lookupImageForSize(image->size());
+    if (image != useImage)
         return;
     
     double timeStamp = FrameView::currentPaintTimeStamp();
@@ -368,7 +389,10 @@ void CachedImage::didDraw(const Image* image)
 
 bool CachedImage::shouldPauseAnimation(const Image* image)
 {
-    if (image != m_image)
+    if (!image)
+        return false;
+    Image* useImage = lookupImageForSize(image->size());
+    if (image != useImage)
         return false;
     
     CachedResourceClientWalker<CachedImageClient> w(m_clients);
@@ -382,14 +406,22 @@ bool CachedImage::shouldPauseAnimation(const Image* image)
 
 void CachedImage::animationAdvanced(const Image* image)
 {
-    if (image == m_image)
-        notifyObservers();
+    if (!image)
+        return;
+    Image* useImage = lookupImageForSize(image->size());
+    if (image != useImage)
+        return;
+    notifyObservers();
 }
 
 void CachedImage::changedInRect(const Image* image, const IntRect& rect)
 {
-    if (image == m_image)
-        notifyObservers(&rect);
+    if (!image)
+        return;
+    Image* useImage = lookupImageForSize(image->size());
+    if (image != useImage)
+        return;
+    notifyObservers(&rect);
 }
 
 } //namespace WebCore
index 87f1014..4ed080d 100644 (file)
@@ -24,6 +24,7 @@
 #define CachedImage_h
 
 #include "CachedResource.h"
+#include "ImageBySizeCache.h"
 #include "CachedResourceClient.h"
 #include "ImageObserver.h"
 #include "IntRect.h"
@@ -34,6 +35,7 @@ namespace WebCore {
 
 class CachedResourceLoader;
 class MemoryCache;
+class RenderObject;
 
 class CachedImage : public CachedResource, public ImageObserver {
     friend class MemoryCache;
@@ -45,24 +47,23 @@ public:
     
     virtual void load(CachedResourceLoader*, const ResourceLoaderOptions&);
 
-    Image* image() const; // Returns the nullImage() if the image is not available yet.
+    Image* image(); // Returns the nullImage() if the image is not available yet.
+    Image* imageForRenderer(const RenderObject*); // Returns the nullImage() if the image is not available yet.
     bool hasImage() const { return m_image.get(); }
 
     std::pair<Image*, float> brokenImage(float deviceScaleFactor) const; // Returns an image and the image's resolution scale factor.
     bool willPaintBrokenImage() const; 
 
-    bool canRender(float multiplier) const { return !errorOccurred() && !imageSize(multiplier).isEmpty(); }
+    bool canRender(const RenderObject* renderer, float multiplier) { return !errorOccurred() && !imageSizeForRenderer(renderer, multiplier).isEmpty(); }
 
     // These are only used for SVGImage right now
-    void setImageContainerSize(const IntSize&);
+    void setContainerSizeForRenderer(const RenderObject*, const IntSize&);
     bool usesImageContainerSize() const;
     bool imageHasRelativeWidth() const;
     bool imageHasRelativeHeight() const;
     
-    // Both of these methods take a zoom multiplier that can be used to increase the natural size of the image by the
-    // zoom.
-    IntSize imageSize(float multiplier) const;  // returns the size of the complete image.
-    IntRect imageRect(float multiplier) const;  // The size of the currently decoded portion of the image.
+    // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom.
+    IntSize imageSizeForRenderer(const RenderObject*, float multiplier); // returns the size of the complete image.
 
     virtual void didAddClient(CachedResourceClient*);
     
@@ -91,6 +92,10 @@ public:
     virtual void changedInRect(const Image*, const IntRect&);
 
 private:
+    Image* lookupImageForSize(const IntSize&) const;
+    Image* lookupImageForRenderer(const RenderObject*) const;
+    PassRefPtr<Image> lookupOrCreateImageForRenderer(const RenderObject*);
+
     void createImage();
     size_t maximumDecodedImageSize();
     // If not null, changeRect is the changed part of the image.
@@ -100,6 +105,7 @@ private:
     void checkShouldPaintBrokenImage();
 
     RefPtr<Image> m_image;
+    mutable ImageBySizeCache m_svgImageCache;
     Timer<CachedImage> m_decodedDataDeletionTimer;
     bool m_shouldPaintBrokenImage;
 };
index d18357f..8d8b7b0 100644 (file)
@@ -611,7 +611,7 @@ static Image* getImage(Element* element)
     ASSERT(element);
     CachedImage* cachedImage = getCachedImage(element);
     return (cachedImage && !cachedImage->errorOccurred()) ?
-        cachedImage->image() : 0;
+        cachedImage->imageForRenderer(element->renderer()) : 0;
 }
 
 static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
index c63faee..96ec77d 100644 (file)
@@ -1202,7 +1202,7 @@ OptionalCursor EventHandler::selectCursor(const MouseEventWithHitTestResults& ev
     if (style && style->cursors()) {
         const CursorList* cursors = style->cursors();
         for (unsigned i = 0; i < cursors->size(); ++i) {
-            const CachedImage* cimage = 0;
+            CachedImage* cimage = 0;
             StyleImage* image = (*cursors)[i].image();
             if (image && image->isCachedImage())
                 cimage = static_cast<StyleCachedImage*>(image)->cachedImage();
@@ -1210,11 +1210,11 @@ OptionalCursor EventHandler::selectCursor(const MouseEventWithHitTestResults& ev
                 continue;
             IntPoint hotSpot = (*cursors)[i].hotSpot();
             // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
-            IntSize size = cimage->image()->size();
+            IntSize size = cimage->imageForRenderer(renderer)->size();
             if (size.width() > 128 || size.height() > 128)
                 continue;
             if (!cimage->errorOccurred())
-                return Cursor(cimage->image(), hotSpot);
+                return Cursor(cimage->imageForRenderer(renderer), hotSpot);
         }
     }
 
index 353b7ad..9bae17a 100644 (file)
@@ -231,7 +231,7 @@ void PageSerializer::serializeFrame(Frame* frame)
             HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(element);
             KURL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr));
             CachedImage* cachedImage = imageElement->cachedImage();
-            addImageToResources(cachedImage, url);
+            addImageToResources(cachedImage, imageElement->renderer(), url);
         } else if (element->hasTagName(HTMLNames::linkTag)) {
             HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(element);
             StyleSheet* sheet = linkElement->sheet();
@@ -288,7 +288,7 @@ void PageSerializer::serializeCSSStyleSheet(CSSStyleSheet* styleSheet, const KUR
     }
 }
 
-void PageSerializer::addImageToResources(CachedImage* image, const KURL& url)
+void PageSerializer::addImageToResources(CachedImage* image, RenderObject* imageRenderer, const KURL& url)
 {
     if (!url.isValid() || m_resourceURLs.contains(url))
         return;
@@ -297,7 +297,7 @@ void PageSerializer::addImageToResources(CachedImage* image, const KURL& url)
         return;
 
     String mimeType = image->response().mimeType();
-    m_resources->append(Resource(url, mimeType, image->image()->data()));
+    m_resources->append(Resource(url, mimeType, imageRenderer ? image->imageForRenderer(imageRenderer)->data() : image->image()->data()));
     m_resourceURLs.add(url);
 }
 
@@ -337,7 +337,7 @@ void PageSerializer::retrieveResourcesForCSSDeclaration(CSSStyleDeclaration* sty
         CachedImage* image = static_cast<StyleCachedImage*>(styleImage)->cachedImage();
 
         KURL url = cssStyleSheet->document()->completeURL(image->url());
-        addImageToResources(image, url);
+        addImageToResources(image, 0, url);
     }
 }
 
index 8e57546..66b16b0 100644 (file)
@@ -46,6 +46,7 @@ class CSSStyleRule;
 class CSSStyleSheet;
 class Frame;
 class Page;
+class RenderObject;
 
 // This class is used to serialize a page contents back to text (typically HTML).
 // It serializes all the page frames and retrieves resources such as images and CSS stylesheets.
@@ -75,7 +76,7 @@ private:
     // It also adds any resources included in that stylesheet (including any imported stylesheets and their own resources).
     void serializeCSSStyleSheet(CSSStyleSheet*, const KURL&);
 
-    void addImageToResources(CachedImage*, const KURL&);
+    void addImageToResources(CachedImage*, RenderObject*, const KURL&);
     void retrieveResourcesForCSSDeclaration(CSSStyleDeclaration*);
     void retrieveResourcesForCSSRule(CSSStyleRule*);
 
index b0b008c..0bcdeeb 100644 (file)
@@ -224,10 +224,10 @@ static void writeImageToDataObject(ChromiumDataObject* dataObject, Element* elem
 {
     // Shove image data into a DataObject for use as a file
     CachedImage* cachedImage = getCachedImage(element);
-    if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
+    if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded())
         return;
 
-    SharedBuffer* imageBuffer = cachedImage->image()->data();
+    SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data();
     if (!imageBuffer || !imageBuffer->size())
         return;
 
index 6f56077..dc46b58 100644 (file)
@@ -130,7 +130,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String& title)
     CachedImage* cachedImage = renderer->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return;
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(renderer);
     ASSERT(image);
 
     NativeImagePtr bitmap = image->nativeImageForCurrentFrame();
index 267b2db..dd2ad2c 100644 (file)
 #include "GraphicsTypes.h"
 #include "ImageSource.h"
 #include "IntRect.h"
-#include "PlatformString.h"
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/text/WTFString.h>
 
 #if PLATFORM(MAC)
 #ifdef __OBJC__
@@ -66,12 +66,12 @@ typedef struct _GdkPixbuf GdkPixbuf;
 
 namespace WebCore {
 
+class AffineTransform;
 class FloatPoint;
 class FloatRect;
 class FloatSize;
 class GraphicsContext;
 class SharedBuffer;
-class AffineTransform;
 
 // This class gets notified when an image creates or destroys decoded frames and when it advances animation frames.
 class ImageObserver;
@@ -87,6 +87,7 @@ public:
     static PassRefPtr<Image> loadPlatformResource(const char* name);
     static bool supportsType(const String&); 
 
+    virtual bool isSVGImage() const { return false; }
     virtual bool isBitmapImage() const { return false; }
     virtual bool currentFrameHasAlpha() { return false; }
 
index 6f3acbe..5b33335 100644 (file)
@@ -292,7 +292,7 @@ void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, c
     if (!image || !image->isLoaded())
         return;
 
-    GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->image()->getGdkPixbuf());
+    GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->imageForRenderer(element->renderer())->getGdkPixbuf());
     if (!pixbuf)
         return;
 
index ca585d6..bfbfd67 100644 (file)
@@ -112,7 +112,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String& title)
     CachedImage* cachedImage = renderer->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return;
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(renderer);
     ASSERT(image);
 
     GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);
index 283a740..ef4ca3a 100644 (file)
@@ -1759,7 +1759,7 @@ static NSFileWrapper *fileWrapperForElement(Element* element)
     if (!wrapper) {
         RenderImage* renderer = toRenderImage(element->renderer());
         if (renderer->cachedImage() && !renderer->cachedImage()->errorOccurred()) {
-            wrapper = [[NSFileWrapper alloc] initRegularFileWithContents:(NSData *)(renderer->cachedImage()->image()->getTIFFRepresentation())];
+            wrapper = [[NSFileWrapper alloc] initRegularFileWithContents:(NSData *)(renderer->cachedImage()->imageForRenderer(renderer)->getTIFFRepresentation())];
             [wrapper setPreferredFilename:@"image.tiff"];
             [wrapper autorelease];
         }
index 4cebb00..d1e90a9 100644 (file)
@@ -309,7 +309,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
     [m_pasteboard.get() declareTypes:types owner:nil];
     writeURL(m_pasteboard.get(), types, cocoaURL, nsStringNilIfEmpty(title), frame);
     
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(renderer);
     ASSERT(image);
     
     [m_pasteboard.get() setData:[image->getNSImage() TIFFRepresentation] forType:NSTIFFPboardType];
index f25d820..e8c5214 100644 (file)
@@ -282,9 +282,9 @@ void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, co
         m_writableData = new QMimeData;
 
     CachedImage* cachedImage = getCachedImage(element);
-    if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
+    if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded())
         return;
-    QPixmap* pixmap = cachedImage->image()->nativeImageForCurrentFrame();
+    QPixmap* pixmap = cachedImage->imageForRenderer(element->renderer())->nativeImageForCurrentFrame();
     if (pixmap)
         m_writableData->setImageData(*pixmap);
 
index 88116cb..c9e7c1e 100644 (file)
@@ -162,7 +162,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
     if (!cachedImage || cachedImage->errorOccurred())
         return;
 
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(node->renderer());
     ASSERT(image);
 
     QPixmap* pixmap = image->nativeImageForCurrentFrame();
index 8ca61c8..045b6f2 100644 (file)
@@ -635,10 +635,10 @@ static void writeImageToDataObject(IDataObject* dataObject, Element* element, co
 {
     // Shove image data into a DataObject for use as a file
     CachedImage* cachedImage = getCachedImage(element);
-    if (!cachedImage || !cachedImage->image() || !cachedImage->isLoaded())
+    if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded())
         return;
 
-    SharedBuffer* imageBuffer = cachedImage->image()->data();
+    SharedBuffer* imageBuffer = cachedImage->imageForRenderer(element->renderer())->data();
     if (!imageBuffer || !imageBuffer->size())
         return;
 
index a573c78..e0cc86a 100644 (file)
@@ -217,7 +217,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
     CachedImage* cachedImage = renderer->cachedImage();
     if (!cachedImage || cachedImage->errorOccurred())
         return;
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(renderer);
     ASSERT(image);
 
     clear();
index 1a61894..53dbfa8 100644 (file)
@@ -208,7 +208,7 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&)
     RenderImage* renderer = static_cast<RenderImage*>(node->renderer());
     CachedImage* cachedImage = static_cast<CachedImage*>(renderer->cachedImage());
     ASSERT(cachedImage);
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(renderer);
     ASSERT(image);
 
     clear();
index ebe7453..1733232 100644 (file)
@@ -304,7 +304,7 @@ Image* HitTestResult::image() const
     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 (file)
index 0000000..4965bb9
--- /dev/null
@@ -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 (file)
index 0000000..404dba6
--- /dev/null
@@ -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
index 4699bd8..5c49ddd 100644 (file)
@@ -1074,7 +1074,7 @@ void InlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c,
 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 @@ void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&
         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 @@ void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffs
     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.
 
index 7044c16..707e581 100644 (file)
@@ -1016,7 +1016,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa
             // 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 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
     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) {
index 5a743d0..a0a8717 100644 (file)
@@ -629,7 +629,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
 
     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 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
 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 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
     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 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
     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();
index d7fcaf4..ccb30f9 100644 (file)
@@ -82,7 +82,7 @@ static const int maxAltTextHeight = 256;
 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 @@ IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
         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 @@ IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
 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 @@ LayoutUnit RenderImage::computeReplacedLogicalWidth(bool includeMaxWidth) const
     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;
index a943c3d..eb748f6 100644 (file)
@@ -89,14 +89,11 @@ void RenderImageResource::resetAnimation()
         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()
index f1ec75b..ac24fba 100644 (file)
@@ -54,15 +54,15 @@ public:
 
     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(); }
 
index 278a82c..fcad246 100644 (file)
@@ -49,7 +49,7 @@ public:
     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(); }
index 133537b..a715ef0 100644 (file)
@@ -926,7 +926,7 @@ bool RenderLayerBacking::isDirectlyCompositedImage() const
     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 @@ void RenderLayerBacking::updateImageContents()
     if (!cachedImage)
         return;
 
-    Image* image = cachedImage->image();
+    Image* image = cachedImage->imageForRenderer(imageRenderer);
     if (!image)
         return;
 
index e21ccca..876c809 100644 (file)
@@ -1350,7 +1350,7 @@ void RenderListMarker::computePreferredLogicalWidths()
         // 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);
index 3ccbd03..aaaa116 100644 (file)
@@ -745,7 +745,7 @@ static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer*
 
     // 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 @@ bool RenderObject::borderImageIsLoadedAndCanBeRendered() const
     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
index 05cb0ea..2054742 100644 (file)
@@ -34,9 +34,9 @@ PassRefPtr<CSSValue> StyleCachedImage::cssValue() const
     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 @@ bool StyleCachedImage::errorOccurred() const
     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 @@ bool StyleCachedImage::usesImageContainerSize() const
     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);
 }
 
 }
index 17bf596..0c714ec 100644 (file)
@@ -40,14 +40,14 @@ public:
     
     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;
index 9889818..f5c74d2 100644 (file)
@@ -58,11 +58,6 @@ IntSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float multi
     return m_containerSize;
 }
 
-void StyleGeneratedImage::setImageContainerSize(const IntSize& size)
-{
-    m_containerSize = size;
-}
-
 void StyleGeneratedImage::addClient(RenderObject* renderer)
 {
     m_generator->addClient(renderer, IntSize());
index b79d3f3..167362f 100644 (file)
@@ -46,7 +46,7 @@ public:
     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;
index 13c5030..42a521e 100644 (file)
@@ -49,14 +49,14 @@ public:
 
     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;
index 62cce7f..a577e23 100644 (file)
@@ -48,7 +48,7 @@ public:
     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
index 494e1b8..1d877fb 100644 (file)
@@ -178,7 +178,7 @@ PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*, Filter* fil
         SVGImageBufferTools::renderSubtreeToImageBuffer(m_targetImage.get(), renderer, contentTransformation);
     }
 
-    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage(CopyBackingStore) : m_cachedImage->image(), preserveAspectRatio());
+    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage(CopyBackingStore) : m_cachedImage->imageForRenderer(renderer()), preserveAspectRatio());
 }
 
 void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
index efa83ac..42558f4 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006 Eric Seidel <eric@webkit.org>
  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
+
 #if ENABLE(SVG)
 #include "SVGImage.h"
 
 #include "CachedPage.h"
 #include "DocumentLoader.h"
+#include "EmptyClients.h"
 #include "FileChooser.h"
 #include "FileIconLoader.h"
 #include "FloatRect.h"
 #include "SVGSVGElement.h"
 #include "Settings.h"
 
-// Moving this #include above FrameLoader.h causes the Windows build to fail due to warnings about
-// alignment in Timer<FrameLoader>. It seems that the definition of EmptyFrameLoaderClient is what
-// causes this (removing that definition fixes the warnings), but it isn't clear why.
-#include "EmptyClients.h" // NOLINT
-
 namespace WebCore {
 
 class SVGImageChromeClient : public EmptyChromeClient {
@@ -101,7 +99,7 @@ SVGImage::~SVGImage()
     ASSERT(!m_chromeClient || !m_chromeClient->image());
 }
 
-void SVGImage::setContainerSize(const LayoutSize& containerSize)
+void SVGImage::setContainerSize(const IntSize& containerSize)
 {
     if (containerSize.isEmpty())
         return;
index 2336644..ea9c509 100644 (file)
@@ -44,12 +44,14 @@ public:
         return adoptRef(new SVGImage(observer));
     }
 
+    virtual bool isSVGImage() const { return true; }
+
 private:
     virtual ~SVGImage();
 
     virtual String filenameExtension() const;
 
-    virtual void setContainerSize(const LayoutSize&);
+    virtual void setContainerSize(const IntSize&);
     virtual bool usesContainerSize() const;
     virtual bool hasRelativeWidth() const;
     virtual bool hasRelativeHeight() const;