d9eb5309212cc09fa6d27278e52bcc2ce8dc8f67
[WebKit-https.git] / Source / WebCore / platform / graphics / filters / FilterOperation.h
1 /*
2  * Copyright (C) 2011 Apple Inc. 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 APPLE INC. ``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 APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, 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 THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef FilterOperation_h
27 #define FilterOperation_h
28
29 #include "Color.h"
30 #include "LayoutSize.h"
31 #include "Length.h"
32 #include <wtf/RefCounted.h>
33 #include <wtf/TypeCasts.h>
34 #include <wtf/text/WTFString.h>
35
36 // Annoyingly, wingdi.h #defines this.
37 #ifdef PASSTHROUGH
38 #undef PASSTHROUGH
39 #endif
40
41 namespace WebCore {
42
43 // CSS Filters
44
45 class CachedResourceLoader;
46 class CachedSVGDocumentReference;
47 class FilterEffect;
48 struct ResourceLoaderOptions;
49
50 class FilterOperation : public RefCounted<FilterOperation> {
51 public:
52     enum OperationType {
53         REFERENCE, // url(#somefilter)
54         GRAYSCALE,
55         SEPIA,
56         SATURATE,
57         HUE_ROTATE,
58         INVERT,
59         OPACITY,
60         BRIGHTNESS,
61         CONTRAST,
62         BLUR,
63         DROP_SHADOW,
64         PASSTHROUGH,
65         DEFAULT,
66         NONE
67     };
68
69     virtual ~FilterOperation() = default;
70
71     virtual Ref<FilterOperation> clone() const = 0;
72
73     virtual bool operator==(const FilterOperation&) const = 0;
74     bool operator!=(const FilterOperation& o) const { return !(*this == o); }
75
76     virtual RefPtr<FilterOperation> blend(const FilterOperation* /*from*/, double /*progress*/, bool /*blendToPassthrough*/ = false)
77     {
78         return nullptr;
79     }
80
81     OperationType type() const { return m_type; }
82
83     bool isBasicColorMatrixFilterOperation() const
84     {
85         return m_type == GRAYSCALE || m_type == SEPIA || m_type == SATURATE || m_type == HUE_ROTATE;
86     }
87
88     bool isBasicComponentTransferFilterOperation() const
89     {
90         return m_type == INVERT || m_type == BRIGHTNESS || m_type == CONTRAST || m_type == OPACITY;
91     }
92
93     bool isSameType(const FilterOperation& o) const { return o.type() == m_type; }
94
95     // True if the alpha channel of any pixel can change under this operation.
96     virtual bool affectsOpacity() const { return false; }
97     // True if the value of one pixel can affect the value of another pixel under this operation, such as blur.
98     virtual bool movesPixels() const { return false; }
99     // True if the filter should not be allowed to work on content that is not available from this security origin.
100     virtual bool shouldBeRestrictedBySecurityOrigin() const { return false; }
101
102 protected:
103     FilterOperation(OperationType type)
104         : m_type(type)
105     {
106     }
107
108     OperationType m_type;
109 };
110
111 class WEBCORE_EXPORT DefaultFilterOperation : public FilterOperation {
112 public:
113     static Ref<DefaultFilterOperation> create(OperationType representedType)
114     {
115         return adoptRef(*new DefaultFilterOperation(representedType));
116     }
117
118     Ref<FilterOperation> clone() const override
119     {
120         return adoptRef(*new DefaultFilterOperation(representedType()));
121     }
122
123     OperationType representedType() const { return m_representedType; }
124
125 private:
126     bool operator==(const FilterOperation&) const override;
127
128     DefaultFilterOperation(OperationType representedType)
129         : FilterOperation(DEFAULT)
130         , m_representedType(representedType)
131     {
132     }
133
134     OperationType m_representedType;
135 };
136
137 class PassthroughFilterOperation : public FilterOperation {
138 public:
139     static Ref<PassthroughFilterOperation> create()
140     {
141         return adoptRef(*new PassthroughFilterOperation());
142     }
143
144     Ref<FilterOperation> clone() const override
145     {
146         return adoptRef(*new PassthroughFilterOperation());
147     }
148
149 private:
150     bool operator==(const FilterOperation& o) const override
151     {
152         return isSameType(o);
153     }
154
155     PassthroughFilterOperation()
156         : FilterOperation(PASSTHROUGH)
157     {
158     }
159 };
160
161 class ReferenceFilterOperation : public FilterOperation {
162 public:
163     static Ref<ReferenceFilterOperation> create(const String& url, const String& fragment)
164     {
165         return adoptRef(*new ReferenceFilterOperation(url, fragment));
166     }
167     virtual ~ReferenceFilterOperation();
168
169     Ref<FilterOperation> clone() const override
170     {
171         // Reference filters cannot be cloned.
172         RELEASE_ASSERT_NOT_REACHED();
173         return *static_cast<FilterOperation*>(nullptr);
174     }
175
176     bool affectsOpacity() const override { return true; }
177     bool movesPixels() const override { return true; }
178     // FIXME: This only needs to return true for graphs that include ConvolveMatrix, DisplacementMap, Morphology and possibly Lighting.
179     // https://bugs.webkit.org/show_bug.cgi?id=171753
180     bool shouldBeRestrictedBySecurityOrigin() const override { return true; }
181
182     const String& url() const { return m_url; }
183     const String& fragment() const { return m_fragment; }
184
185     void loadExternalDocumentIfNeeded(CachedResourceLoader&, const ResourceLoaderOptions&);
186
187     CachedSVGDocumentReference* cachedSVGDocumentReference() const { return m_cachedSVGDocumentReference.get(); }
188
189     FilterEffect* filterEffect() const { return m_filterEffect.get(); }
190     void setFilterEffect(RefPtr<FilterEffect>&&);
191
192 private:
193     ReferenceFilterOperation(const String& url, const String& fragment);
194
195     bool operator==(const FilterOperation&) const override;
196
197     String m_url;
198     String m_fragment;
199     std::unique_ptr<CachedSVGDocumentReference> m_cachedSVGDocumentReference;
200     RefPtr<FilterEffect> m_filterEffect;
201 };
202
203 // GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect.
204 // For HUE_ROTATE, the angle of rotation is stored in m_amount.
205 class WEBCORE_EXPORT BasicColorMatrixFilterOperation : public FilterOperation {
206 public:
207     static Ref<BasicColorMatrixFilterOperation> create(double amount, OperationType type)
208     {
209         return adoptRef(*new BasicColorMatrixFilterOperation(amount, type));
210     }
211
212     Ref<FilterOperation> clone() const override
213     {
214         return adoptRef(*new BasicColorMatrixFilterOperation(amount(), type()));
215     }
216
217     double amount() const { return m_amount; }
218
219     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
220
221 private:
222     bool operator==(const FilterOperation&) const override;
223
224     double passthroughAmount() const;
225
226     BasicColorMatrixFilterOperation(double amount, OperationType type)
227         : FilterOperation(type)
228         , m_amount(amount)
229     {
230     }
231
232     double m_amount;
233 };
234
235 // INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect.
236 class WEBCORE_EXPORT BasicComponentTransferFilterOperation : public FilterOperation {
237 public:
238     static Ref<BasicComponentTransferFilterOperation> create(double amount, OperationType type)
239     {
240         return adoptRef(*new BasicComponentTransferFilterOperation(amount, type));
241     }
242
243     Ref<FilterOperation> clone() const override
244     {
245         return adoptRef(*new BasicComponentTransferFilterOperation(amount(), type()));
246     }
247
248     double amount() const { return m_amount; }
249
250     bool affectsOpacity() const override { return m_type == OPACITY; }
251
252     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
253
254 private:
255     bool operator==(const FilterOperation&) const override;
256
257     double passthroughAmount() const;
258
259     BasicComponentTransferFilterOperation(double amount, OperationType type)
260         : FilterOperation(type)
261         , m_amount(amount)
262     {
263     }
264
265     double m_amount;
266 };
267
268 class WEBCORE_EXPORT BlurFilterOperation : public FilterOperation {
269 public:
270     static Ref<BlurFilterOperation> create(Length stdDeviation)
271     {
272         return adoptRef(*new BlurFilterOperation(WTFMove(stdDeviation)));
273     }
274
275     Ref<FilterOperation> clone() const override
276     {
277         return adoptRef(*new BlurFilterOperation(stdDeviation()));
278     }
279
280     const Length& stdDeviation() const { return m_stdDeviation; }
281
282     bool affectsOpacity() const override { return true; }
283     bool movesPixels() const override { return true; }
284
285     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
286
287 private:
288     bool operator==(const FilterOperation&) const override;
289
290     BlurFilterOperation(Length stdDeviation)
291         : FilterOperation(BLUR)
292         , m_stdDeviation(WTFMove(stdDeviation))
293     {
294     }
295
296     Length m_stdDeviation;
297 };
298
299 class WEBCORE_EXPORT DropShadowFilterOperation : public FilterOperation {
300 public:
301     static Ref<DropShadowFilterOperation> create(const IntPoint& location, int stdDeviation, const Color& color)
302     {
303         return adoptRef(*new DropShadowFilterOperation(location, stdDeviation, color));
304     }
305
306     Ref<FilterOperation> clone() const override
307     {
308         return adoptRef(*new DropShadowFilterOperation(location(), stdDeviation(), color()));
309     }
310
311     int x() const { return m_location.x(); }
312     int y() const { return m_location.y(); }
313     IntPoint location() const { return m_location; }
314     int stdDeviation() const { return m_stdDeviation; }
315     const Color& color() const { return m_color; }
316
317     bool affectsOpacity() const override { return true; }
318     bool movesPixels() const override { return true; }
319
320     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
321
322 private:
323     bool operator==(const FilterOperation&) const override;
324
325     DropShadowFilterOperation(const IntPoint& location, int stdDeviation, const Color& color)
326         : FilterOperation(DROP_SHADOW)
327         , m_location(location)
328         , m_stdDeviation(stdDeviation)
329         , m_color(color)
330     {
331     }
332
333     IntPoint m_location; // FIXME: should location be in Lengths?
334     int m_stdDeviation;
335     Color m_color;
336 };
337
338 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FilterOperation&);
339
340 } // namespace WebCore
341
342 #define SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ToValueTypeName, predicate) \
343 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
344     static bool isType(const WebCore::FilterOperation& operation) { return operation.predicate; } \
345 SPECIALIZE_TYPE_TRAITS_END()
346
347 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DefaultFilterOperation, type() == WebCore::FilterOperation::DEFAULT)
348 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(PassthroughFilterOperation, type() == WebCore::FilterOperation::PASSTHROUGH)
349 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ReferenceFilterOperation, type() == WebCore::FilterOperation::REFERENCE)
350 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicColorMatrixFilterOperation, isBasicColorMatrixFilterOperation())
351 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicComponentTransferFilterOperation, isBasicComponentTransferFilterOperation())
352 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BlurFilterOperation, type() == WebCore::FilterOperation::BLUR)
353 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DropShadowFilterOperation, type() == WebCore::FilterOperation::DROP_SHADOW)
354
355 #endif // FilterOperation_h