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