Reverse ownership relation of StyleCachedImage and CSSImageValue
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Sep 2016 13:42:42 +0000 (13:42 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Sep 2016 13:42:42 +0000 (13:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161447

Reviewed by Andreas Kling.

Currently StyleCachedImage (which represents an image in RenderStyle) has a weak ref to the
underlying CSSImageValue/CSSImageSetValue which actually owns it. This is awkwards especially since
StyleGeneratedImage, the other StyleImage subclass has reversed relationship where it refs
the underlying CSSImageGeneratorValue.

This patch makes StyleCachedImage similar to StyleGeneratedImage. StyleCachedImage now refs the
underlying CSSImageValue/CSSImageSetValue. CSSImageValues no longer need to know about StyleCachedImage.
Instead they reference CachedImages (memory cache objects) directly. StyleCachedImage instances are now
conceptually unique to RenderStyle instances. Actual resources are shared as before by sharing CachedImages.

* css/CSSCursorImageValue.cpp:
(WebCore::CSSCursorImageValue::loadImage):
(WebCore::CSSCursorImageValue::cachedImage):
(WebCore::CSSCursorImageValue::styleImage): Deleted.
* css/CSSCursorImageValue.h:
* css/CSSImageGeneratorValue.cpp:
(WebCore::CSSImageGeneratorValue::cachedImageForCSSValue):
* css/CSSImageSetValue.cpp:
(WebCore::CSSImageSetValue::~CSSImageSetValue):
(WebCore::CSSImageSetValue::loadBestFitImage):
(WebCore::CSSImageSetValue::traverseSubresources):
(WebCore::CSSImageSetValue::styleImage): Deleted.
* css/CSSImageSetValue.h:
* css/CSSImageValue.cpp:
(WebCore::CSSImageValue::CSSImageValue):
(WebCore::CSSImageValue::~CSSImageValue):
(WebCore::CSSImageValue::isPending):
(WebCore::CSSImageValue::loadImage):
(WebCore::CSSImageValue::traverseSubresources):
(WebCore::CSSImageValue::knownToBeOpaque):
(WebCore::CSSImageValue::styleImage): Deleted.
* css/CSSImageValue.h:
* css/StyleBuilderCustom.h:
(WebCore::StyleBuilderCustom::applyValueContent):
* css/StyleResolver.cpp:
(WebCore::StyleResolver::styleImage):
(WebCore::StyleResolver::styleCachedImageFromValue):
(WebCore::StyleResolver::styleGeneratedImageFromValue):
(WebCore::StyleResolver::cachedOrPendingFromValue): Deleted.
(WebCore::StyleResolver::generatedOrPendingFromValue): Deleted.
(WebCore::StyleResolver::setOrPendingFromValue): Deleted.
(WebCore::StyleResolver::cursorOrPendingFromValue): Deleted.
* css/StyleResolver.h:
* editing/TextIterator.cpp:
(WebCore::fullyClipsContents):
* page/PageSerializer.cpp:
(WebCore::PageSerializer::retrieveResourcesForProperties):
* rendering/style/FillLayer.cpp:
(WebCore::FillLayer::imagesIdentical):

    Compare data equality instead of pointer equality for StyleImages (since StyleImages are no longer shared).

(WebCore::layerImagesIdentical): Deleted.
* rendering/style/StyleCachedImage.cpp:
(WebCore::StyleCachedImage::StyleCachedImage):
(WebCore::StyleCachedImage::~StyleCachedImage):
(WebCore::StyleCachedImage::cachedImage):
(WebCore::StyleCachedImage::cssValue):
(WebCore::StyleCachedImage::canRender):
(WebCore::StyleCachedImage::isPending):
(WebCore::StyleCachedImage::isLoaded):
(WebCore::StyleCachedImage::errorOccurred):
(WebCore::StyleCachedImage::imageSize):
(WebCore::StyleCachedImage::imageHasRelativeWidth):
(WebCore::StyleCachedImage::imageHasRelativeHeight):
(WebCore::StyleCachedImage::computeIntrinsicDimensions):
(WebCore::StyleCachedImage::usesImageContainerSize):
(WebCore::StyleCachedImage::setContainerSizeForRenderer):
(WebCore::StyleCachedImage::addClient):
(WebCore::StyleCachedImage::removeClient):
(WebCore::StyleCachedImage::image):
(WebCore::StyleCachedImage::knownToBeOpaque):
(WebCore::StyleCachedImage::setCachedImage): Deleted.
* rendering/style/StyleCachedImage.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@205419 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/css/CSSCursorImageValue.cpp
Source/WebCore/css/CSSCursorImageValue.h
Source/WebCore/css/CSSImageGeneratorValue.cpp
Source/WebCore/css/CSSImageSetValue.cpp
Source/WebCore/css/CSSImageSetValue.h
Source/WebCore/css/CSSImageValue.cpp
Source/WebCore/css/CSSImageValue.h
Source/WebCore/css/StyleBuilderCustom.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/page/PageSerializer.cpp
Source/WebCore/rendering/style/FillLayer.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/style/StylePendingResources.cpp

index 634753f..704b752 100644 (file)
@@ -1,3 +1,85 @@
+2016-09-04  Antti Koivisto  <antti@apple.com>
+
+        Reverse ownership relation of StyleCachedImage and CSSImageValue
+        https://bugs.webkit.org/show_bug.cgi?id=161447
+
+        Reviewed by Andreas Kling.
+
+        Currently StyleCachedImage (which represents an image in RenderStyle) has a weak ref to the
+        underlying CSSImageValue/CSSImageSetValue which actually owns it. This is awkwards especially since
+        StyleGeneratedImage, the other StyleImage subclass has reversed relationship where it refs
+        the underlying CSSImageGeneratorValue.
+
+        This patch makes StyleCachedImage similar to StyleGeneratedImage. StyleCachedImage now refs the
+        underlying CSSImageValue/CSSImageSetValue. CSSImageValues no longer need to know about StyleCachedImage.
+        Instead they reference CachedImages (memory cache objects) directly. StyleCachedImage instances are now
+        conceptually unique to RenderStyle instances. Actual resources are shared as before by sharing CachedImages.
+
+        * css/CSSCursorImageValue.cpp:
+        (WebCore::CSSCursorImageValue::loadImage):
+        (WebCore::CSSCursorImageValue::cachedImage):
+        (WebCore::CSSCursorImageValue::styleImage): Deleted.
+        * css/CSSCursorImageValue.h:
+        * css/CSSImageGeneratorValue.cpp:
+        (WebCore::CSSImageGeneratorValue::cachedImageForCSSValue):
+        * css/CSSImageSetValue.cpp:
+        (WebCore::CSSImageSetValue::~CSSImageSetValue):
+        (WebCore::CSSImageSetValue::loadBestFitImage):
+        (WebCore::CSSImageSetValue::traverseSubresources):
+        (WebCore::CSSImageSetValue::styleImage): Deleted.
+        * css/CSSImageSetValue.h:
+        * css/CSSImageValue.cpp:
+        (WebCore::CSSImageValue::CSSImageValue):
+        (WebCore::CSSImageValue::~CSSImageValue):
+        (WebCore::CSSImageValue::isPending):
+        (WebCore::CSSImageValue::loadImage):
+        (WebCore::CSSImageValue::traverseSubresources):
+        (WebCore::CSSImageValue::knownToBeOpaque):
+        (WebCore::CSSImageValue::styleImage): Deleted.
+        * css/CSSImageValue.h:
+        * css/StyleBuilderCustom.h:
+        (WebCore::StyleBuilderCustom::applyValueContent):
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::styleImage):
+        (WebCore::StyleResolver::styleCachedImageFromValue):
+        (WebCore::StyleResolver::styleGeneratedImageFromValue):
+        (WebCore::StyleResolver::cachedOrPendingFromValue): Deleted.
+        (WebCore::StyleResolver::generatedOrPendingFromValue): Deleted.
+        (WebCore::StyleResolver::setOrPendingFromValue): Deleted.
+        (WebCore::StyleResolver::cursorOrPendingFromValue): Deleted.
+        * css/StyleResolver.h:
+        * editing/TextIterator.cpp:
+        (WebCore::fullyClipsContents):
+        * page/PageSerializer.cpp:
+        (WebCore::PageSerializer::retrieveResourcesForProperties):
+        * rendering/style/FillLayer.cpp:
+        (WebCore::FillLayer::imagesIdentical):
+
+            Compare data equality instead of pointer equality for StyleImages (since StyleImages are no longer shared).
+
+        (WebCore::layerImagesIdentical): Deleted.
+        * rendering/style/StyleCachedImage.cpp:
+        (WebCore::StyleCachedImage::StyleCachedImage):
+        (WebCore::StyleCachedImage::~StyleCachedImage):
+        (WebCore::StyleCachedImage::cachedImage):
+        (WebCore::StyleCachedImage::cssValue):
+        (WebCore::StyleCachedImage::canRender):
+        (WebCore::StyleCachedImage::isPending):
+        (WebCore::StyleCachedImage::isLoaded):
+        (WebCore::StyleCachedImage::errorOccurred):
+        (WebCore::StyleCachedImage::imageSize):
+        (WebCore::StyleCachedImage::imageHasRelativeWidth):
+        (WebCore::StyleCachedImage::imageHasRelativeHeight):
+        (WebCore::StyleCachedImage::computeIntrinsicDimensions):
+        (WebCore::StyleCachedImage::usesImageContainerSize):
+        (WebCore::StyleCachedImage::setContainerSizeForRenderer):
+        (WebCore::StyleCachedImage::addClient):
+        (WebCore::StyleCachedImage::removeClient):
+        (WebCore::StyleCachedImage::image):
+        (WebCore::StyleCachedImage::knownToBeOpaque):
+        (WebCore::StyleCachedImage::setCachedImage): Deleted.
+        * rendering/style/StyleCachedImage.h:
+
 2016-09-03  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Media controls behave strangely when videos mute from within a playing handler
index ae4ac05..222351f 100644 (file)
@@ -26,8 +26,6 @@
 #include "CSSImageValue.h"
 #include "CachedImage.h"
 #include "CachedResourceLoader.h"
-#include "StyleCachedImage.h"
-#include "StyleImage.h"
 #include "SVGCursorElement.h"
 #include "SVGLengthContext.h"
 #include "SVGNames.h"
@@ -102,32 +100,17 @@ void CSSCursorImageValue::cursorElementChanged(SVGCursorElement& cursorElement)
     m_hotSpot.setY(static_cast<int>(y));
 }
 
-void CSSCursorImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
+std::pair<CachedImage*, float> CSSCursorImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
 {
-    if (is<CSSImageSetValue>(m_imageValue.get())) {
-        downcast<CSSImageSetValue>(m_imageValue.get()).loadBestFitImage(loader, options);
-        return;
-    }
-
-    downcast<CSSImageValue>(m_imageValue.get()).loadImage(loader, options);
-}
-
-StyleCachedImage& CSSCursorImageValue::styleImage(const Document& document)
-{
-    // Need to delegate completely so that changes in device scale factor can be handled appropriately.
-    StyleCachedImage* styleImage;
     if (is<CSSImageSetValue>(m_imageValue.get()))
-        styleImage = &downcast<CSSImageSetValue>(m_imageValue.get()).styleImage(document);
-    else {
-        if (auto* cursorElement = updateCursorElement(document)) {
-            if (cursorElement->href() != downcast<CSSImageValue>(m_imageValue.get()).url())
-                m_imageValue = CSSImageValue::create(cursorElement->href());
-        }
-        styleImage = &downcast<CSSImageValue>(m_imageValue.get()).styleImage();
+        return downcast<CSSImageSetValue>(m_imageValue.get()).loadBestFitImage(loader, options);
+
+    if (auto* cursorElement = updateCursorElement(*loader.document())) {
+        if (cursorElement->href() != downcast<CSSImageValue>(m_imageValue.get()).url())
+            m_imageValue = CSSImageValue::create(cursorElement->href());
     }
-    styleImage->setCSSValue(*this);
 
-    return *styleImage;
+    return { downcast<CSSImageValue>(m_imageValue.get()).loadImage(loader, options), 1 };
 }
 
 bool CSSCursorImageValue::equals(const CSSCursorImageValue& other) const
index f8e1eda..996096e 100644 (file)
@@ -31,7 +31,6 @@ class Document;
 class Element;
 class SVGCursorElement;
 class SVGElement;
-class StyleCachedImage;
 
 class CSSCursorImageValue final : public CSSValue {
 public:
@@ -53,8 +52,7 @@ public:
 
     String customCSSText() const;
 
-    void loadImage(CachedResourceLoader&, const ResourceLoaderOptions&);
-    StyleCachedImage& styleImage(const Document&);
+    std::pair<CachedImage*, float> loadImage(CachedResourceLoader&, const ResourceLoaderOptions&);
 
     void removeReferencedElement(SVGElement*);
 
index 3d54b6a..e3b6d32 100644 (file)
@@ -252,8 +252,7 @@ CachedImage* CSSImageGeneratorValue::cachedImageForCSSValue(CSSValue& value, Cac
 {
     if (is<CSSImageValue>(value)) {
         auto& imageValue = downcast<CSSImageValue>(value);
-        imageValue.loadImage(cachedResourceLoader, options);
-        return imageValue.styleImage().cachedImage();
+        return imageValue.loadImage(cachedResourceLoader, options);
     }
     
     if (is<CSSImageGeneratorValue>(value)) {
index ba4af1e..9190407 100644 (file)
 #include "CrossOriginAccessControl.h"
 #include "Document.h"
 #include "Page.h"
-#include "StyleCachedImage.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
 CSSImageSetValue::CSSImageSetValue()
     : CSSValueList(ImageSetClass, CommaSeparator)
-    , m_accessedBestFitImage(false)
-    , m_scaleFactor(1)
 {
 }
 
 CSSImageSetValue::~CSSImageSetValue()
 {
-    if (m_image)
-        m_image->detachFromCSSValue();
 }
 
 void CSSImageSetValue::fillImageSet()
@@ -79,63 +74,51 @@ void CSSImageSetValue::fillImageSet()
 
 CSSImageSetValue::ImageWithScale CSSImageSetValue::bestImageForScaleFactor()
 {
+    if (!m_imagesInSet.size())
+        fillImageSet();
+
     ImageWithScale image;
     size_t numberOfImages = m_imagesInSet.size();
     for (size_t i = 0; i < numberOfImages; ++i) {
         image = m_imagesInSet.at(i);
-        if (image.scaleFactor >= m_scaleFactor)
+        if (image.scaleFactor >= m_deviceScaleFactor)
             return image;
     }
     return image;
 }
 
-void CSSImageSetValue::loadBestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
+std::pair<CachedImage*, float> CSSImageSetValue::loadBestFitImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
 {
     Document* document = loader.document();
-    if (Page* page = document->page())
-        m_scaleFactor = page->deviceScaleFactor();
-    else
-        m_scaleFactor = 1;
-
-    if (!m_imagesInSet.size())
-        fillImageSet();
-
-    if (m_accessedBestFitImage)
-        return;
-    // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here.
-    // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(),
-    // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
-    ImageWithScale image = bestImageForScaleFactor();
-    CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options);
-    request.setInitiator(cachedResourceRequestInitiators().css);
-    if (options.mode == FetchOptions::Mode::Cors) {
-        ASSERT(document->securityOrigin());
-        updateRequestForAccessControl(request.mutableResourceRequest(), *document->securityOrigin(), options.allowCredentials);
-    }
-    if (CachedResourceHandle<CachedImage> cachedImage = loader.requestImage(request)) {
-        styleImage(*document).setCachedImage(*cachedImage, image.scaleFactor);
+    updateDeviceScaleFactor(*document);
+    
+    if (!m_accessedBestFitImage) {
         m_accessedBestFitImage = true;
-    }
-}
 
-StyleCachedImage& CSSImageSetValue::styleImage(const Document& document)
-{
-    if (!m_image)
-        m_image = StyleCachedImage::create(*this);
-    else if (!m_image->isPending()) {
-        float deviceScaleFactor = 1;
-        if (Page* page = document.page())
-            deviceScaleFactor = page->deviceScaleFactor();
-
-        // If the deviceScaleFactor has changed, we may not have the best image loaded, so we have to re-assess.
-        if (deviceScaleFactor != m_scaleFactor) {
-            m_accessedBestFitImage = false;
-            m_image->detachFromCSSValue();
-            m_image = StyleCachedImage::create(*this);
+        // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here.
+        // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(),
+        // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
+        ImageWithScale image = bestImageForScaleFactor();
+        CachedResourceRequest request(ResourceRequest(document->completeURL(image.imageURL)), options);
+        request.setInitiator(cachedResourceRequestInitiators().css);
+        if (options.mode == FetchOptions::Mode::Cors) {
+            ASSERT(document->securityOrigin());
+            updateRequestForAccessControl(request.mutableResourceRequest(), *document->securityOrigin(), options.allowCredentials);
         }
+        m_cachedImage = loader.requestImage(request);
+        m_bestFitImageScaleFactor = image.scaleFactor;
     }
+    return { m_cachedImage.get(), m_bestFitImageScaleFactor };
+}
 
-    return *m_image;
+void CSSImageSetValue::updateDeviceScaleFactor(const Document& document)
+{
+    float deviceScaleFactor = document.page() ? document.page()->deviceScaleFactor() : 1;
+    if (deviceScaleFactor == m_deviceScaleFactor)
+        return;
+    m_deviceScaleFactor = deviceScaleFactor;
+    m_accessedBestFitImage = false;
+    m_cachedImage = nullptr;
 }
 
 String CSSImageSetValue::customCSSText() const
@@ -170,18 +153,13 @@ String CSSImageSetValue::customCSSText() const
 
 bool CSSImageSetValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
-    if (!m_image)
-        return false;
-    CachedImage* cachedResource = m_image->cachedImage();
-    if (!cachedResource)
+    if (!m_cachedImage)
         return false;
-    return handler(*cachedResource);
+    return handler(*m_cachedImage);
 }
 
 CSSImageSetValue::CSSImageSetValue(const CSSImageSetValue& cloneFrom)
     : CSSValueList(cloneFrom)
-    , m_accessedBestFitImage(false)
-    , m_scaleFactor(1)
 {
     // Non-CSSValueList data is not accessible through CSS OM, no need to clone.
 }
index 27e8465..6f38107 100644 (file)
 #define CSSImageSetValue_h
 
 #include "CSSValueList.h"
+#include "CachedImageClient.h"
+#include "CachedResourceHandle.h"
 
 namespace WebCore {
 
 class CachedResourceLoader;
 class Document;
-class StyleCachedImage;
-class StyleImage;
 struct ResourceLoaderOptions;
 
 class CSSImageSetValue final : public CSSValueList {
 public:
-
     static Ref<CSSImageSetValue> create()
     {
         return adoptRef(*new CSSImageSetValue());
     }
     ~CSSImageSetValue();
 
-    void loadBestFitImage(CachedResourceLoader&, const ResourceLoaderOptions&);
-    StyleCachedImage& styleImage(const Document&);
+    std::pair<CachedImage*, float>  loadBestFitImage(CachedResourceLoader&, const ResourceLoaderOptions&);
+    CachedImage* cachedImage() const { return m_cachedImage.get(); }
 
     String customCSSText() const;
 
-    bool isPending() const { return !m_accessedBestFitImage; }
-
     struct ImageWithScale {
         String imageURL;
         float scaleFactor;
@@ -61,6 +58,8 @@ public:
 
     Ref<CSSImageSetValue> cloneForCSSOM() const;
 
+    void updateDeviceScaleFactor(const Document&);
+
 protected:
     ImageWithScale bestImageForScaleFactor();
 
@@ -71,12 +70,10 @@ private:
     void fillImageSet();
     static inline bool compareByScaleFactor(ImageWithScale first, ImageWithScale second) { return first.scaleFactor < second.scaleFactor; }
 
-    RefPtr<StyleCachedImage> m_image;
-    bool m_accessedBestFitImage;
-
-    // This represents the scale factor that we used to find the best fit image. It does not necessarily
-    // correspond to the scale factor of the best fit image.
-    float m_scaleFactor;
+    CachedResourceHandle<CachedImage> m_cachedImage;
+    bool m_accessedBestFitImage { false };
+    float m_bestFitImageScaleFactor { 1 };
+    float m_deviceScaleFactor { 1 };
 
     Vector<ImageWithScale> m_imagesInSet;
 };
index c8aee0d..6f68ab8 100644 (file)
@@ -32,7 +32,6 @@
 #include "Document.h"
 #include "Element.h"
 #include "MemoryCache.h"
-#include "StyleCachedImage.h"
 
 namespace WebCore {
 
@@ -46,60 +45,46 @@ CSSImageValue::CSSImageValue(const String& url)
 CSSImageValue::CSSImageValue(CachedImage& image)
     : CSSValue(ImageClass)
     , m_url(image.url())
-    , m_image(StyleCachedImage::create(*this))
+    , m_cachedImage(&image)
     , m_accessedImage(true)
 {
-    m_image->setCachedImage(image);
 }
 
 
 CSSImageValue::~CSSImageValue()
 {
-    if (m_image)
-        m_image->detachFromCSSValue();
 }
 
 bool CSSImageValue::isPending() const
 {
-    return !m_image || !m_image->cachedImage();
+    return !m_accessedImage;
 }
 
-StyleCachedImage& CSSImageValue::styleImage()
+CachedImage* CSSImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
 {
-    if (!m_image)
-        m_image = StyleCachedImage::create(*this);
-
-    return *m_image;
-}
-
-void CSSImageValue::loadImage(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
-{
-    if (m_accessedImage)
-        return;
-    m_accessedImage = true;
-
-    CachedResourceRequest request(ResourceRequest(loader.document()->completeURL(m_url)), options);
-    if (m_initiatorName.isEmpty())
-        request.setInitiator(cachedResourceRequestInitiators().css);
-    else
-        request.setInitiator(m_initiatorName);
-
-    if (options.mode == FetchOptions::Mode::Cors) {
-        ASSERT(loader.document()->securityOrigin());
-        updateRequestForAccessControl(request.mutableResourceRequest(), *loader.document()->securityOrigin(), options.allowCredentials);
+    if (!m_accessedImage) {
+        m_accessedImage = true;
+
+        CachedResourceRequest request(ResourceRequest(loader.document()->completeURL(m_url)), options);
+        if (m_initiatorName.isEmpty())
+            request.setInitiator(cachedResourceRequestInitiators().css);
+        else
+            request.setInitiator(m_initiatorName);
+
+        if (options.mode == FetchOptions::Mode::Cors) {
+            ASSERT(loader.document()->securityOrigin());
+            updateRequestForAccessControl(request.mutableResourceRequest(), *loader.document()->securityOrigin(), options.allowCredentials);
+        }
+        m_cachedImage = loader.requestImage(request);
     }
-    if (CachedResourceHandle<CachedImage> cachedImage = loader.requestImage(request))
-        styleImage().setCachedImage(*cachedImage);
+    return m_cachedImage.get();
 }
 
 bool CSSImageValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
-    if (!m_image)
-        return false;
-    CachedResource* cachedResource = m_image->cachedImage();
-    if (!cachedResource)
+    if (!m_cachedImage)
         return false;
-    return handler(*cachedResource);
+    return handler(*m_cachedImage);
 }
 
 bool CSSImageValue::equals(const CSSImageValue& other) const
@@ -122,7 +107,9 @@ Ref<CSSValue> CSSImageValue::cloneForCSSOM() const
 
 bool CSSImageValue::knownToBeOpaque(const RenderElement* renderer) const
 {
-    return m_image ? m_image->knownToBeOpaque(renderer) : false;
+    if (!m_cachedImage)
+        return false;
+    return m_cachedImage->currentFrameKnownToBeOpaque(renderer);
 }
 
 } // namespace WebCore
index 0a8de95..8b8076e 100644 (file)
@@ -22,6 +22,7 @@
 #define CSSImageValue_h
 
 #include "CSSValue.h"
+#include "CachedResourceHandle.h"
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -29,7 +30,6 @@ namespace WebCore {
 class CachedImage;
 class CachedResourceLoader;
 class Element;
-class StyleCachedImage;
 class RenderElement;
 struct ResourceLoaderOptions;
 
@@ -40,8 +40,8 @@ public:
     ~CSSImageValue();
 
     bool isPending() const;
-    void loadImage(CachedResourceLoader&, const ResourceLoaderOptions&);
-    StyleCachedImage& styleImage();
+    CachedImage* loadImage(CachedResourceLoader&, const ResourceLoaderOptions&);
+    CachedImage* cachedImage() const { return m_cachedImage.get(); }
 
     const String& url() const { return m_url; }
 
@@ -62,7 +62,7 @@ private:
     explicit CSSImageValue(CachedImage&);
 
     String m_url;
-    RefPtr<StyleCachedImage> m_image;
+    CachedResourceHandle<CachedImage> m_cachedImage;
     bool m_accessedImage;
     AtomicString m_initiatorName;
 };
index b1c5523..7a17290 100644 (file)
@@ -46,6 +46,7 @@
 #include "SVGElement.h"
 #include "SVGRenderStyle.h"
 #include "StyleBuilderConverter.h"
+#include "StyleCachedImage.h"
 #include "StyleFontSizeFunctions.h"
 #include "StyleGeneratedImage.h"
 #include "StyleResolver.h"
@@ -1313,12 +1314,12 @@ inline void StyleBuilderCustom::applyValueContent(StyleResolver& styleResolver,
                 styleResolver.style()->setContent(StyleGeneratedImage::create(downcast<CSSImageGeneratorValue>(item.get())), didSet);
             didSet = true;
         } else if (is<CSSImageSetValue>(item.get())) {
-            styleResolver.style()->setContent(styleResolver.setOrPendingFromValue(CSSPropertyContent, downcast<CSSImageSetValue>(item.get())), didSet);
+            styleResolver.style()->setContent(styleResolver.styleCachedImageFromValue(CSSPropertyContent, item), didSet);
             didSet = true;
         }
 
         if (is<CSSImageValue>(item.get())) {
-            styleResolver.style()->setContent(styleResolver.cachedOrPendingFromValue(CSSPropertyContent, downcast<CSSImageValue>(item.get())), didSet);
+            styleResolver.style()->setContent(styleResolver.styleCachedImageFromValue(CSSPropertyContent, item), didSet);
             didSet = true;
             continue;
         }
index 3594b2a..f4123bb 100644 (file)
@@ -1702,33 +1702,27 @@ RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, cons
 
 RefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue& value)
 {
-    if (is<CSSImageValue>(value))
-        return cachedOrPendingFromValue(property, downcast<CSSImageValue>(value));
-
     if (is<CSSImageGeneratorValue>(value)) {
         if (is<CSSGradientValue>(value))
-            return generatedOrPendingFromValue(property, *downcast<CSSGradientValue>(value).gradientWithStylesResolved(this));
-        return generatedOrPendingFromValue(property, downcast<CSSImageGeneratorValue>(value));
+            return styleGeneratedImageFromValue(property, *downcast<CSSGradientValue>(value).gradientWithStylesResolved(this));
+        return styleGeneratedImageFromValue(property, downcast<CSSImageGeneratorValue>(value));
     }
 
-    if (is<CSSImageSetValue>(value))
-        return setOrPendingFromValue(property, downcast<CSSImageSetValue>(value));
-
-    if (is<CSSCursorImageValue>(value))
-        return cursorOrPendingFromValue(property, downcast<CSSCursorImageValue>(value));
+    if (is<CSSImageValue>(value) || is<CSSImageSetValue>(value) || is<CSSCursorImageValue>(value))
+        return styleCachedImageFromValue(property, value);
 
     return nullptr;
 }
 
-Ref<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue& value)
+Ref<StyleCachedImage> StyleResolver::styleCachedImageFromValue(CSSPropertyID property, CSSValue& value)
 {
-    Ref<StyleImage> image = value.styleImage();
+    auto image = StyleCachedImage::create(value);
     if (image->isPending())
         m_state.ensurePendingResources().pendingImages.set(property, &value);
     return image;
 }
 
-Ref<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
+Ref<StyleGeneratedImage> StyleResolver::styleGeneratedImageFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
 {
     if (is<CSSFilterImageValue>(value)) {
         // FilterImage needs to calculate FilterOperations.
@@ -1740,22 +1734,6 @@ Ref<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID propert
     return StyleGeneratedImage::create(value);
 }
 
-RefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue& value)
-{
-    auto& image = value.styleImage(document());
-    if (image.isPending())
-        m_state.ensurePendingResources().pendingImages.set(property, &value);
-    return &image;
-}
-
-RefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue& value)
-{
-    auto& image = value.styleImage(document());
-    if (image.isPending())
-        m_state.ensurePendingResources().pendingImages.set(property, &value);
-    return &image;
-}
-
 #if ENABLE(IOS_TEXT_AUTOSIZING)
 void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
 {
index 3f01195..22e1be6 100644 (file)
@@ -72,6 +72,8 @@ class RuleData;
 class RuleSet;
 class SelectorFilter;
 class Settings;
+class StyleCachedImage;
+class StyleGeneratedImage;
 class StyleImage;
 class StyleKeyframe;
 class StylePendingImage;
@@ -458,10 +460,8 @@ public:
     const State& state() const { return m_state; }
 
     RefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue&);
-    Ref<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue&);
-    Ref<StyleImage> generatedOrPendingFromValue(CSSPropertyID, CSSImageGeneratorValue&);
-    RefPtr<StyleImage> setOrPendingFromValue(CSSPropertyID, CSSImageSetValue&);
-    RefPtr<StyleImage> cursorOrPendingFromValue(CSSPropertyID, CSSCursorImageValue&);
+    Ref<StyleCachedImage> styleCachedImageFromValue(CSSPropertyID, CSSValue&);
+    Ref<StyleGeneratedImage> styleGeneratedImageFromValue(CSSPropertyID, CSSImageGeneratorValue&);
 
     bool applyPropertyToRegularStyle() const { return m_state.applyPropertyToRegularStyle(); }
     bool applyPropertyToVisitedLinkStyle() const { return m_state.applyPropertyToVisitedLinkStyle(); }
index 279b206..5316d67 100644 (file)
@@ -331,9 +331,7 @@ void PageSerializer::retrieveResourcesForProperties(const StyleProperties* style
         if (!is<CSSImageValue>(*cssValue))
             continue;
 
-        auto& styleImage = downcast<CSSImageValue>(*cssValue).styleImage();
-
-        auto* image = styleImage.cachedImage();
+        auto* image = downcast<CSSImageValue>(*cssValue).cachedImage();
         if (!image)
             continue;
 
index a0f0abe..d85d9e2 100644 (file)
@@ -380,16 +380,10 @@ bool FillLayer::hasFixedImage() const
     return false;
 }
 
-static inline bool layerImagesIdentical(const FillLayer& layer1, const FillLayer& layer2)
-{
-    // We just care about pointer equivalency.
-    return layer1.image() == layer2.image();
-}
-
 bool FillLayer::imagesIdentical(const FillLayer* layer1, const FillLayer* layer2)
 {
     for (; layer1 && layer2; layer1 = layer1->next(), layer2 = layer2->next()) {
-        if (!layerImagesIdentical(*layer1, *layer2))
+        if (!arePointingToEqualData(layer1->image(), layer2->image()))
             return false;
     }
 
index fe62cc7..285f405 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2005-2008, 2016 Apple Inc. 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
 #include "config.h"
 #include "StyleCachedImage.h"
 
+#include "CSSCursorImageValue.h"
 #include "CSSImageSetValue.h"
+#include "CSSImageValue.h"
 #include "CachedImage.h"
 #include "RenderElement.h"
 
 namespace WebCore {
 
 StyleCachedImage::StyleCachedImage(CSSValue& cssValue)
-    : m_cssValue(&cssValue)
+    : m_cssValue(cssValue)
 {
+    ASSERT(is<CSSImageValue>(m_cssValue) || is<CSSImageSetValue>(m_cssValue) || is<CSSCursorImageValue>(m_cssValue));
+
     m_isCachedImage = true;
 }
 
 StyleCachedImage::~StyleCachedImage()
 {
-    if (m_image)
-        m_image->removeClient(this);
 }
 
-void StyleCachedImage::setCachedImage(CachedImage& image, float scaleFactor)
+bool StyleCachedImage::operator==(const StyleImage& other) const
+{
+    if (!is<StyleCachedImage>(other))
+        return false;
+    auto& otherCached = downcast<StyleCachedImage>(other);
+    if (&otherCached == this)
+        return true;
+    if (m_scaleFactor != otherCached.m_scaleFactor)
+        return false;
+    if (m_cssValue.ptr() == otherCached.m_cssValue.ptr())
+        return true;
+    if (m_cachedImage && m_cachedImage == otherCached.m_cachedImage)
+        return true;
+    return false;
+}
+
+void StyleCachedImage::load(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
+{
+    ASSERT(isPending());
+
+    if (is<CSSImageValue>(m_cssValue)) {
+        auto& imageValue = downcast<CSSImageValue>(m_cssValue.get());
+        m_cachedImage = imageValue.loadImage(loader, options);
+        return;
+    }
+
+    if (is<CSSImageSetValue>(m_cssValue)) {
+        auto& imageSetValue = downcast<CSSImageSetValue>(m_cssValue.get());
+        std::tie(m_cachedImage, m_scaleFactor) = imageSetValue.loadBestFitImage(loader, options);
+        return;
+    }
+
+    if (is<CSSCursorImageValue>(m_cssValue.get())) {
+        auto& cursorValue = downcast<CSSCursorImageValue>(m_cssValue.get());
+        std::tie(m_cachedImage, m_scaleFactor) = cursorValue.loadImage(loader, options);
+        return;
+    }
+}
+
+CachedImage* StyleCachedImage::cachedImage() const
 {
-    ASSERT(!m_image);
-    m_image = &image;
-    m_image->addClient(this);
-    m_scaleFactor = scaleFactor;
+    return m_cachedImage.get();
 }
 
 PassRefPtr<CSSValue> StyleCachedImage::cssValue() const
 {
-    if (m_cssValue)
-        return m_cssValue;
-    return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI);
+    return const_cast<CSSValue*>(m_cssValue.ptr());
 }
 
 bool StyleCachedImage::canRender(const RenderObject* renderer, float multiplier) const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->canRender(renderer, multiplier);
+    return m_cachedImage->canRender(renderer, multiplier);
 }
 
 bool StyleCachedImage::isPending() const
 {
-    return !m_image;
+    return !m_cachedImage;
 }
 
 bool StyleCachedImage::isLoaded() const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->isLoaded();
+    return m_cachedImage->isLoaded();
 }
 
 bool StyleCachedImage::errorOccurred() const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->errorOccurred();
+    return m_cachedImage->errorOccurred();
 }
 
 FloatSize StyleCachedImage::imageSize(const RenderElement* renderer, float multiplier) const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return { };
-    FloatSize size = m_image->imageSizeForRenderer(renderer, multiplier);
+    FloatSize size = m_cachedImage->imageSizeForRenderer(renderer, multiplier);
     size.scale(1 / m_scaleFactor);
     return size;
 }
 
 bool StyleCachedImage::imageHasRelativeWidth() const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->imageHasRelativeWidth();
+    return m_cachedImage->imageHasRelativeWidth();
 }
 
 bool StyleCachedImage::imageHasRelativeHeight() const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->imageHasRelativeHeight();
+    return m_cachedImage->imageHasRelativeHeight();
 }
 
 void StyleCachedImage::computeIntrinsicDimensions(const RenderElement*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return;
-    m_image->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+    m_cachedImage->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
 }
 
 bool StyleCachedImage::usesImageContainerSize() const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->usesImageContainerSize();
+    return m_cachedImage->usesImageContainerSize();
 }
 
 void StyleCachedImage::setContainerSizeForRenderer(const RenderElement* renderer, const FloatSize& imageContainerSize, float imageContainerZoomFactor)
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return;
-    m_image->setContainerSizeForRenderer(renderer, LayoutSize(imageContainerSize), imageContainerZoomFactor);
+    m_cachedImage->setContainerSizeForRenderer(renderer, LayoutSize(imageContainerSize), imageContainerZoomFactor);
 }
 
 void StyleCachedImage::addClient(RenderElement* renderer)
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return;
-    m_image->addClient(renderer);
+    m_cachedImage->addClient(renderer);
 }
 
 void StyleCachedImage::removeClient(RenderElement* renderer)
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return;
-    m_image->removeClient(renderer);
+    m_cachedImage->removeClient(renderer);
 }
 
 RefPtr<Image> StyleCachedImage::image(RenderElement* renderer, const FloatSize&) const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return nullptr;
-    return m_image->imageForRenderer(renderer);
+    return m_cachedImage->imageForRenderer(renderer);
 }
 
 float StyleCachedImage::imageScaleFactor() const
@@ -155,9 +191,9 @@ float StyleCachedImage::imageScaleFactor() const
 
 bool StyleCachedImage::knownToBeOpaque(const RenderElement* renderer) const
 {
-    if (!m_image)
+    if (!m_cachedImage)
         return false;
-    return m_image->currentFrameKnownToBeOpaque(renderer);
+    return m_cachedImage->currentFrameKnownToBeOpaque(renderer);
 }
 
 }
index f8a5d31..1410c10 100644 (file)
@@ -32,26 +32,25 @@ namespace WebCore {
 
 class CSSValue;
 class CachedImage;
+class Document;
 
-class StyleCachedImage final : public StyleImage, private CachedImageClient {
+class StyleCachedImage final : public StyleImage {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     static Ref<StyleCachedImage> create(CSSValue& cssValue) { return adoptRef(*new StyleCachedImage(cssValue)); }
     virtual ~StyleCachedImage();
 
-    CachedImage* cachedImage() const override { return m_image.get(); }
+    bool operator==(const StyleImage& other) const override;
 
-    void detachFromCSSValue() { m_cssValue = nullptr; }
-    void setCSSValue(CSSValue& value) { m_cssValue = &value; }
+    CachedImage* cachedImage() const override;
 
-    void setCachedImage(CachedImage&, float scaleFactor = 1);
-
-    WrappedImagePtr data() const override { return m_image.get(); }
+    WrappedImagePtr data() const override { return m_cachedImage.get(); }
 
     PassRefPtr<CSSValue> cssValue() const override;
     
     bool canRender(const RenderObject*, float multiplier) const override;
     bool isPending() const override;
+    void load(CachedResourceLoader&, const ResourceLoaderOptions&) override;
     bool isLoaded() const override;
     bool errorOccurred() const override;
     FloatSize imageSize(const RenderElement*, float multiplier) const override;
@@ -69,9 +68,9 @@ public:
 private:
     StyleCachedImage(CSSValue&);
 
-    CSSValue* m_cssValue;
-    float m_scaleFactor { 1 };
-    CachedResourceHandle<CachedImage> m_image;
+    Ref<CSSValue> m_cssValue;
+    mutable float m_scaleFactor { 1 };
+    mutable CachedResourceHandle<CachedImage> m_cachedImage;
 };
 
 } // namespace WebCore
index 1c92519..66c8cba 100644 (file)
@@ -47,6 +47,11 @@ bool StyleGeneratedImage::isPending() const
     return m_imageGeneratorValue->isPending();
 }
 
+void StyleGeneratedImage::load(CachedResourceLoader& loader, const ResourceLoaderOptions& options)
+{
+    m_imageGeneratorValue->loadSubimages(loader, options);
+}
+
 FloatSize StyleGeneratedImage::imageSize(const RenderElement* renderer, float multiplier) const
 {
     if (m_fixedSize) {
index 63c5922..0bf4cc4 100644 (file)
@@ -41,11 +41,14 @@ public:
     CSSImageGeneratorValue& imageValue() { return m_imageGeneratorValue; }
 
 private:
+    bool operator==(const StyleImage& other) const override { return data() == other.data(); }
+
     WrappedImagePtr data() const override { return m_imageGeneratorValue.ptr(); }
 
     PassRefPtr<CSSValue> cssValue() const override;
 
     bool isPending() const override;
+    void load(CachedResourceLoader&, const ResourceLoaderOptions&) override;
     FloatSize imageSize(const RenderElement*, float multiplier) const override;
     bool imageHasRelativeWidth() const override { return !m_fixedSize; }
     bool imageHasRelativeHeight() const override { return !m_fixedSize; }
index aa45637..3454297 100644 (file)
 namespace WebCore {
 
 class CachedImage;
+class CachedResourceLoader;
 class CSSValue;
 class RenderElement;
 class RenderObject;
+struct ResourceLoaderOptions;
 
 typedef const void* WrappedImagePtr;
 
@@ -45,15 +47,13 @@ class StyleImage : public RefCounted<StyleImage> {
 public:
     virtual ~StyleImage() { }
 
-    bool operator==(const StyleImage& other) const
-    {
-        return &other == this || (data() && data() == other.data());
-    }
+    virtual bool operator==(const StyleImage& other) const = 0;
 
     virtual PassRefPtr<CSSValue> cssValue() const = 0;
 
     virtual bool canRender(const RenderObject*, float /*multiplier*/) const { return true; }
     virtual bool isPending() const = 0;
+    virtual void load(CachedResourceLoader&, const ResourceLoaderOptions&) = 0;
     virtual bool isLoaded() const { return true; }
     virtual bool errorOccurred() const { return false; }
     virtual FloatSize imageSize(const RenderElement*, float multiplier) const = 0;
index d996cf5..7a9e985 100644 (file)
@@ -27,9 +27,6 @@
 #include "StylePendingResources.h"
 
 #include "CSSCursorImageValue.h"
-#include "CSSImageGeneratorValue.h"
-#include "CSSImageSetValue.h"
-#include "CSSImageValue.h"
 #include "CachedResourceLoader.h"
 #include "CachedSVGDocumentReference.h"
 #include "ContentData.h"
@@ -60,26 +57,7 @@ static void loadPendingImage(Document& document, const StyleImage* styleImage, c
         options.allowCredentials = DoNotAllowStoredCredentials;
     }
 
-    auto cssValue = const_cast<StyleImage*>(styleImage)->cssValue();
-    if (is<CSSImageValue>(cssValue.get())) {
-        downcast<CSSImageValue>(*cssValue).loadImage(document.cachedResourceLoader(), options);
-        return;
-    };
-
-    if (is<CSSImageSetValue>(cssValue.get())) {
-        downcast<CSSImageSetValue>(*cssValue).loadBestFitImage(document.cachedResourceLoader(), options);
-        return;
-    };
-
-    if (is<CSSImageGeneratorValue>(cssValue.get())) {
-        downcast<CSSImageGeneratorValue>(*cssValue).loadSubimages(document.cachedResourceLoader(), options);
-        return;
-    };
-
-    if (is<CSSCursorImageValue>(cssValue.get())) {
-        downcast<CSSCursorImageValue>(*cssValue).loadImage(document.cachedResourceLoader(), options);
-        return;
-    };
+    const_cast<StyleImage&>(*styleImage).load(document.cachedResourceLoader(), options);
 }
 
 static void loadPendingImages(const PendingResources& pendingResources, Document& document, RenderStyle& style, const Element* element)