Stop using PassRefPtr in platform/graphics
[WebKit-https.git] / Source / WebCore / css / CSSFilterImageValue.cpp
1 /*
2  * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
17  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
18  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
22  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
23  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "CSSFilterImageValue.h"
29
30 #include "CSSImageValue.h"
31 #include "CachedImage.h"
32 #include "CachedResourceLoader.h"
33 #include "CachedSVGDocumentReference.h"
34 #include "CrossfadeGeneratedImage.h"
35 #include "FilterEffectRenderer.h"
36 #include "GraphicsContext.h"
37 #include "ImageBuffer.h"
38 #include "RenderElement.h"
39 #include "StyleCachedImage.h"
40 #include "StyleGeneratedImage.h"
41 #include "StyleResolver.h"
42 #include <wtf/text/StringBuilder.h>
43
44 namespace WebCore {
45
46 CSSFilterImageValue::~CSSFilterImageValue()
47 {
48     if (m_cachedImage)
49         m_cachedImage->removeClient(m_filterSubimageObserver);
50 }
51
52 String CSSFilterImageValue::customCSSText() const
53 {
54     StringBuilder result;
55     result.appendLiteral("filter(");
56     result.append(m_imageValue->cssText());
57     result.appendLiteral(", ");
58     result.append(m_filterValue->cssText());
59     result.append(')');
60     return result.toString();
61 }
62
63 FloatSize CSSFilterImageValue::fixedSize(const RenderElement* renderer)
64 {
65     // FIXME: Skip Content Security Policy check when filter is applied to an element in a user agent shadow tree.
66     // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
67     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
68
69     CachedResourceLoader& cachedResourceLoader = renderer->document().cachedResourceLoader();
70     CachedImage* cachedImage = cachedImageForCSSValue(m_imageValue, cachedResourceLoader, options);
71
72     if (!cachedImage)
73         return FloatSize();
74
75     return cachedImage->imageForRenderer(renderer)->size();
76 }
77
78 bool CSSFilterImageValue::isPending() const
79 {
80     return CSSImageGeneratorValue::subimageIsPending(m_imageValue);
81 }
82
83 bool CSSFilterImageValue::knownToBeOpaque(const RenderElement*) const
84 {
85     return false;
86 }
87
88 void CSSFilterImageValue::loadSubimages(CachedResourceLoader& cachedResourceLoader, const ResourceLoaderOptions& options)
89 {
90     CachedResourceHandle<CachedImage> oldCachedImage = m_cachedImage;
91
92     m_cachedImage = CSSImageGeneratorValue::cachedImageForCSSValue(m_imageValue, cachedResourceLoader, options);
93
94     if (m_cachedImage != oldCachedImage) {
95         if (oldCachedImage)
96             oldCachedImage->removeClient(m_filterSubimageObserver);
97         if (m_cachedImage)
98             m_cachedImage->addClient(m_filterSubimageObserver);
99     }
100
101     for (auto& filterOperation : m_filterOperations.operations()) {
102         if (!is<ReferenceFilterOperation>(filterOperation.get()))
103             continue;
104         auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(*filterOperation);
105         referenceFilterOperation.loadExternalDocumentIfNeeded(cachedResourceLoader, options);
106     }
107
108     m_filterSubimageObserver.setReady(true);
109 }
110
111 RefPtr<Image> CSSFilterImageValue::image(RenderElement* renderer, const FloatSize& size)
112 {
113     ASSERT(renderer);
114
115     if (size.isEmpty())
116         return nullptr;
117
118     // FIXME: Skip Content Security Policy check when filter is applied to an element in a user agent shadow tree.
119     // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
120     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
121     auto* cachedImage = cachedImageForCSSValue(m_imageValue, renderer->document().cachedResourceLoader(), options);
122     if (!cachedImage)
123         return &Image::nullImage();
124
125     auto* image = cachedImage->imageForRenderer(renderer);
126     if (!image)
127         return &Image::nullImage();
128
129     // Transform Image into ImageBuffer.
130     // FIXME (149424): This buffer should not be unconditionally unaccelerated.
131     auto texture = ImageBuffer::create(size, Unaccelerated);
132     if (!texture)
133         return &Image::nullImage();
134
135     auto imageRect = FloatRect { { }, size };
136     texture->context().drawImage(*image, imageRect);
137
138     auto filterRenderer = FilterEffectRenderer::create();
139     filterRenderer->setSourceImage(WTFMove(texture));
140     filterRenderer->setSourceImageRect(imageRect);
141     filterRenderer->setFilterRegion(imageRect);
142     if (!filterRenderer->build(*renderer, m_filterOperations, FilterFunction))
143         return &Image::nullImage();
144     filterRenderer->apply();
145
146     return filterRenderer->output()->copyImage();
147 }
148
149 void CSSFilterImageValue::filterImageChanged(const IntRect&)
150 {
151     for (auto& client : clients())
152         client.key->imageChanged(static_cast<WrappedImagePtr>(this));
153 }
154
155 void CSSFilterImageValue::createFilterOperations(StyleResolver* resolver)
156 {
157     m_filterOperations.clear();
158     resolver->createFilterOperations(m_filterValue, m_filterOperations);
159 }
160
161 void CSSFilterImageValue::FilterSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect)
162 {
163     if (m_ready)
164         m_ownerValue->filterImageChanged(*rect);
165 }
166
167 bool CSSFilterImageValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
168 {
169     if (!m_cachedImage)
170         return false;
171     return handler(*m_cachedImage);
172 }
173
174 bool CSSFilterImageValue::equals(const CSSFilterImageValue& other) const
175 {
176     return equalInputImages(other) && compareCSSValue(m_filterValue, other.m_filterValue);
177 }
178
179 bool CSSFilterImageValue::equalInputImages(const CSSFilterImageValue& other) const
180 {
181     return compareCSSValue(m_imageValue, other.m_imageValue);
182 }
183
184 } // namespace WebCore