3036b4822cf064259064f0d5d9369207256933ce
[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/ThreadSafeRefCounted.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 ResourceLoaderOptions;
48 template<typename T> struct ColorComponents;
49
50 class FilterOperation : public ThreadSafeRefCounted<FilterOperation> {
51 public:
52     enum OperationType {
53         REFERENCE, // url(#somefilter)
54         GRAYSCALE,
55         SEPIA,
56         SATURATE,
57         HUE_ROTATE,
58         INVERT,
59         APPLE_INVERT_LIGHTNESS,
60         OPACITY,
61         BRIGHTNESS,
62         CONTRAST,
63         BLUR,
64         DROP_SHADOW,
65         PASSTHROUGH,
66         DEFAULT,
67         NONE
68     };
69
70     virtual ~FilterOperation() = default;
71
72     virtual Ref<FilterOperation> clone() const = 0;
73
74     virtual bool operator==(const FilterOperation&) const = 0;
75     bool operator!=(const FilterOperation& o) const { return !(*this == o); }
76
77     virtual RefPtr<FilterOperation> blend(const FilterOperation* /*from*/, double /*progress*/, bool /*blendToPassthrough*/ = false)
78     {
79         return nullptr;
80     }
81     
82     virtual bool transformColor(ColorComponents<float>&) const { return false; }
83     virtual bool inverseTransformColor(ColorComponents<float>&) const { return false; }
84
85     OperationType type() const { return m_type; }
86
87     bool isBasicColorMatrixFilterOperation() const
88     {
89         return m_type == GRAYSCALE || m_type == SEPIA || m_type == SATURATE || m_type == HUE_ROTATE;
90     }
91
92     bool isBasicComponentTransferFilterOperation() const
93     {
94         return m_type == INVERT || m_type == BRIGHTNESS || m_type == CONTRAST || m_type == OPACITY;
95     }
96
97     bool isSameType(const FilterOperation& o) const { return o.type() == m_type; }
98
99     // True if the alpha channel of any pixel can change under this operation.
100     virtual bool affectsOpacity() const { return false; }
101     // True if the value of one pixel can affect the value of another pixel under this operation, such as blur.
102     virtual bool movesPixels() const { return false; }
103     // True if the filter should not be allowed to work on content that is not available from this security origin.
104     virtual bool shouldBeRestrictedBySecurityOrigin() const { return false; }
105
106 protected:
107     FilterOperation(OperationType type)
108         : m_type(type)
109     {
110     }
111
112     OperationType m_type;
113 };
114
115 class WEBCORE_EXPORT DefaultFilterOperation : public FilterOperation {
116 public:
117     static Ref<DefaultFilterOperation> create(OperationType representedType)
118     {
119         return adoptRef(*new DefaultFilterOperation(representedType));
120     }
121
122     Ref<FilterOperation> clone() const override
123     {
124         return adoptRef(*new DefaultFilterOperation(representedType()));
125     }
126
127     OperationType representedType() const { return m_representedType; }
128
129 private:
130     bool operator==(const FilterOperation&) const override;
131
132     DefaultFilterOperation(OperationType representedType)
133         : FilterOperation(DEFAULT)
134         , m_representedType(representedType)
135     {
136     }
137
138     OperationType m_representedType;
139 };
140
141 class PassthroughFilterOperation : public FilterOperation {
142 public:
143     static Ref<PassthroughFilterOperation> create()
144     {
145         return adoptRef(*new PassthroughFilterOperation());
146     }
147
148     Ref<FilterOperation> clone() const override
149     {
150         return adoptRef(*new PassthroughFilterOperation());
151     }
152
153 private:
154     bool operator==(const FilterOperation& o) const override
155     {
156         return isSameType(o);
157     }
158
159     PassthroughFilterOperation()
160         : FilterOperation(PASSTHROUGH)
161     {
162     }
163 };
164
165 class ReferenceFilterOperation : public FilterOperation {
166 public:
167     static Ref<ReferenceFilterOperation> create(const String& url, const String& fragment)
168     {
169         return adoptRef(*new ReferenceFilterOperation(url, fragment));
170     }
171     virtual ~ReferenceFilterOperation();
172
173     Ref<FilterOperation> clone() const final
174     {
175         // Reference filters cannot be cloned.
176         RELEASE_ASSERT_NOT_REACHED();
177     }
178
179     bool affectsOpacity() const override { return true; }
180     bool movesPixels() const override { return true; }
181     // FIXME: This only needs to return true for graphs that include ConvolveMatrix, DisplacementMap, Morphology and possibly Lighting.
182     // https://bugs.webkit.org/show_bug.cgi?id=171753
183     bool shouldBeRestrictedBySecurityOrigin() const override { return true; }
184
185     const String& url() const { return m_url; }
186     const String& fragment() const { return m_fragment; }
187
188     void loadExternalDocumentIfNeeded(CachedResourceLoader&, const ResourceLoaderOptions&);
189
190     CachedSVGDocumentReference* cachedSVGDocumentReference() const { return m_cachedSVGDocumentReference.get(); }
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 };
201
202 // GRAYSCALE, SEPIA, SATURATE and HUE_ROTATE are variations on a basic color matrix effect.
203 // For HUE_ROTATE, the angle of rotation is stored in m_amount.
204 class WEBCORE_EXPORT BasicColorMatrixFilterOperation : public FilterOperation {
205 public:
206     static Ref<BasicColorMatrixFilterOperation> create(double amount, OperationType type)
207     {
208         return adoptRef(*new BasicColorMatrixFilterOperation(amount, type));
209     }
210
211     Ref<FilterOperation> clone() const override
212     {
213         return adoptRef(*new BasicColorMatrixFilterOperation(amount(), type()));
214     }
215
216     double amount() const { return m_amount; }
217
218     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
219
220 private:
221     bool operator==(const FilterOperation&) const override;
222
223     double passthroughAmount() const;
224
225     BasicColorMatrixFilterOperation(double amount, OperationType type)
226         : FilterOperation(type)
227         , m_amount(amount)
228     {
229     }
230
231     bool transformColor(ColorComponents<float>&) const override;
232
233     double m_amount;
234 };
235
236 // INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect.
237 class WEBCORE_EXPORT BasicComponentTransferFilterOperation : public FilterOperation {
238 public:
239     static Ref<BasicComponentTransferFilterOperation> create(double amount, OperationType type)
240     {
241         return adoptRef(*new BasicComponentTransferFilterOperation(amount, type));
242     }
243
244     Ref<FilterOperation> clone() const override
245     {
246         return adoptRef(*new BasicComponentTransferFilterOperation(amount(), type()));
247     }
248
249     double amount() const { return m_amount; }
250
251     bool affectsOpacity() const override { return m_type == OPACITY; }
252
253     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
254
255 private:
256     bool operator==(const FilterOperation&) const override;
257
258     double passthroughAmount() const;
259
260     BasicComponentTransferFilterOperation(double amount, OperationType type)
261         : FilterOperation(type)
262         , m_amount(amount)
263     {
264     }
265
266     bool transformColor(ColorComponents<float>&) const override;
267
268     double m_amount;
269 };
270
271 class WEBCORE_EXPORT InvertLightnessFilterOperation : public FilterOperation {
272 public:
273     static Ref<InvertLightnessFilterOperation> create()
274     {
275         return adoptRef(*new InvertLightnessFilterOperation());
276     }
277
278     Ref<FilterOperation> clone() const final
279     {
280         return adoptRef(*new InvertLightnessFilterOperation());
281     }
282
283     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
284
285 private:
286     bool operator==(const FilterOperation&) const final;
287
288     InvertLightnessFilterOperation()
289         : FilterOperation(APPLE_INVERT_LIGHTNESS)
290     {
291     }
292
293     bool transformColor(ColorComponents<float>&) const final;
294     bool inverseTransformColor(ColorComponents<float>&) const final;
295 };
296
297 class WEBCORE_EXPORT BlurFilterOperation : public FilterOperation {
298 public:
299     static Ref<BlurFilterOperation> create(Length stdDeviation)
300     {
301         return adoptRef(*new BlurFilterOperation(WTFMove(stdDeviation)));
302     }
303
304     Ref<FilterOperation> clone() const override
305     {
306         return adoptRef(*new BlurFilterOperation(stdDeviation()));
307     }
308
309     const Length& stdDeviation() const { return m_stdDeviation; }
310
311     bool affectsOpacity() const override { return true; }
312     bool movesPixels() const override { return true; }
313
314     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
315
316 private:
317     bool operator==(const FilterOperation&) const override;
318
319     BlurFilterOperation(Length stdDeviation)
320         : FilterOperation(BLUR)
321         , m_stdDeviation(WTFMove(stdDeviation))
322     {
323     }
324
325     Length m_stdDeviation;
326 };
327
328 class WEBCORE_EXPORT DropShadowFilterOperation : public FilterOperation {
329 public:
330     static Ref<DropShadowFilterOperation> create(const IntPoint& location, int stdDeviation, const Color& color)
331     {
332         return adoptRef(*new DropShadowFilterOperation(location, stdDeviation, color));
333     }
334
335     Ref<FilterOperation> clone() const override
336     {
337         return adoptRef(*new DropShadowFilterOperation(location(), stdDeviation(), color()));
338     }
339
340     int x() const { return m_location.x(); }
341     int y() const { return m_location.y(); }
342     IntPoint location() const { return m_location; }
343     int stdDeviation() const { return m_stdDeviation; }
344     const Color& color() const { return m_color; }
345
346     bool affectsOpacity() const override { return true; }
347     bool movesPixels() const override { return true; }
348
349     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
350
351 private:
352     bool operator==(const FilterOperation&) const override;
353
354     DropShadowFilterOperation(const IntPoint& location, int stdDeviation, const Color& color)
355         : FilterOperation(DROP_SHADOW)
356         , m_location(location)
357         , m_stdDeviation(stdDeviation)
358         , m_color(color)
359     {
360     }
361
362     IntPoint m_location; // FIXME: should location be in Lengths?
363     int m_stdDeviation;
364     Color m_color;
365 };
366
367 WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FilterOperation&);
368
369 } // namespace WebCore
370
371 #define SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ToValueTypeName, predicate) \
372 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
373     static bool isType(const WebCore::FilterOperation& operation) { return operation.predicate; } \
374 SPECIALIZE_TYPE_TRAITS_END()
375
376 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DefaultFilterOperation, type() == WebCore::FilterOperation::DEFAULT)
377 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(PassthroughFilterOperation, type() == WebCore::FilterOperation::PASSTHROUGH)
378 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(ReferenceFilterOperation, type() == WebCore::FilterOperation::REFERENCE)
379 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicColorMatrixFilterOperation, isBasicColorMatrixFilterOperation())
380 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BasicComponentTransferFilterOperation, isBasicComponentTransferFilterOperation())
381 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(InvertLightnessFilterOperation, type() == WebCore::FilterOperation::APPLE_INVERT_LIGHTNESS)
382 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(BlurFilterOperation, type() == WebCore::FilterOperation::BLUR)
383 SPECIALIZE_TYPE_TRAITS_FILTEROPERATION(DropShadowFilterOperation, type() == WebCore::FilterOperation::DROP_SHADOW)
384