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