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