Extract UTI mapping and allow for additions
[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 "CSSFilter.h"
31 #include "CachedImage.h"
32 #include "CachedResourceLoader.h"
33 #include "GraphicsContext.h"
34 #include "ImageBuffer.h"
35 #include "RenderElement.h"
36 #include "StyleCachedImage.h"
37 #include "StyleResolver.h"
38 #include <wtf/text/StringBuilder.h>
39
40 namespace WebCore {
41
42 CSSFilterImageValue::~CSSFilterImageValue()
43 {
44     if (m_cachedImage)
45         m_cachedImage->removeClient(m_filterSubimageObserver);
46 }
47
48 String CSSFilterImageValue::customCSSText() const
49 {
50     StringBuilder result;
51     result.appendLiteral("filter(");
52     result.append(m_imageValue->cssText());
53     result.appendLiteral(", ");
54     result.append(m_filterValue->cssText());
55     result.append(')');
56     return result.toString();
57 }
58
59 FloatSize CSSFilterImageValue::fixedSize(const RenderElement* renderer)
60 {
61     // FIXME: Skip Content Security Policy check when filter is applied to an element in a user agent shadow tree.
62     // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
63     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
64
65     CachedResourceLoader& cachedResourceLoader = renderer->document().cachedResourceLoader();
66     CachedImage* cachedImage = cachedImageForCSSValue(m_imageValue, cachedResourceLoader, options);
67
68     if (!cachedImage)
69         return FloatSize();
70
71     return cachedImage->imageForRenderer(renderer)->size();
72 }
73
74 bool CSSFilterImageValue::isPending() const
75 {
76     return CSSImageGeneratorValue::subimageIsPending(m_imageValue);
77 }
78
79 bool CSSFilterImageValue::knownToBeOpaque(const RenderElement&) const
80 {
81     return false;
82 }
83
84 void CSSFilterImageValue::loadSubimages(CachedResourceLoader& cachedResourceLoader, const ResourceLoaderOptions& options)
85 {
86     CachedResourceHandle<CachedImage> oldCachedImage = m_cachedImage;
87
88     m_cachedImage = CSSImageGeneratorValue::cachedImageForCSSValue(m_imageValue, cachedResourceLoader, options);
89
90     if (m_cachedImage != oldCachedImage) {
91         if (oldCachedImage)
92             oldCachedImage->removeClient(m_filterSubimageObserver);
93         if (m_cachedImage)
94             m_cachedImage->addClient(m_filterSubimageObserver);
95     }
96
97     for (auto& filterOperation : m_filterOperations.operations()) {
98         if (!is<ReferenceFilterOperation>(filterOperation))
99             continue;
100         auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(*filterOperation);
101         referenceFilterOperation.loadExternalDocumentIfNeeded(cachedResourceLoader, options);
102     }
103
104     m_filterSubimageObserver.setReady(true);
105 }
106
107 RefPtr<Image> CSSFilterImageValue::image(RenderElement* renderer, const FloatSize& size)
108 {
109     ASSERT(renderer);
110
111     if (size.isEmpty())
112         return nullptr;
113
114     // FIXME: Skip Content Security Policy check when filter is applied to an element in a user agent shadow tree.
115     // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
116     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
117     auto* cachedImage = cachedImageForCSSValue(m_imageValue, renderer->document().cachedResourceLoader(), options);
118     if (!cachedImage)
119         return &Image::nullImage();
120
121     auto* image = cachedImage->imageForRenderer(renderer);
122     if (!image)
123         return &Image::nullImage();
124
125     // Transform Image into ImageBuffer.
126     // FIXME (149424): This buffer should not be unconditionally unaccelerated.
127     auto texture = ImageBuffer::create(size, Unaccelerated);
128     if (!texture)
129         return &Image::nullImage();
130
131     auto imageRect = FloatRect { { }, size };
132     texture->context().drawImage(*image, imageRect);
133
134     auto cssFilter = CSSFilter::create();
135     cssFilter->setSourceImage(WTFMove(texture));
136     cssFilter->setSourceImageRect(imageRect);
137     cssFilter->setFilterRegion(imageRect);
138     if (!cssFilter->build(*renderer, m_filterOperations, FilterConsumer::FilterFunction))
139         return &Image::nullImage();
140     cssFilter->apply();
141
142     return cssFilter->output()->copyImage();
143 }
144
145 void CSSFilterImageValue::filterImageChanged(const IntRect&)
146 {
147     for (auto& client : clients())
148         client.key->imageChanged(static_cast<WrappedImagePtr>(this));
149 }
150
151 void CSSFilterImageValue::createFilterOperations(StyleResolver* resolver)
152 {
153     m_filterOperations.clear();
154     resolver->createFilterOperations(m_filterValue, m_filterOperations);
155 }
156
157 void CSSFilterImageValue::FilterSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect)
158 {
159     if (m_ready)
160         m_ownerValue->filterImageChanged(*rect);
161 }
162
163 bool CSSFilterImageValue::traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const
164 {
165     if (!m_cachedImage)
166         return false;
167     return handler(*m_cachedImage);
168 }
169
170 bool CSSFilterImageValue::equals(const CSSFilterImageValue& other) const
171 {
172     return equalInputImages(other) && compareCSSValue(m_filterValue, other.m_filterValue);
173 }
174
175 bool CSSFilterImageValue::equalInputImages(const CSSFilterImageValue& other) const
176 {
177     return compareCSSValue(m_imageValue, other.m_imageValue);
178 }
179
180 } // namespace WebCore