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
45namespace WebCore {
46
47// CSS Filters
48
49class CachedSVGDocumentReference;
50
51class FilterOperation : public RefCounted<FilterOperation> {
52public:
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
110protected:
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
122class DefaultFilterOperation : public FilterOperation {
123public:
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
136private:
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
148FILTEROPERATION_TYPE_CASTS(DefaultFilterOperation, type() == FilterOperation::DEFAULT);
149
150
151class PassthroughFilterOperation : public FilterOperation {
152public:
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
163private:
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
175FILTEROPERATION_TYPE_CASTS(PassthroughFilterOperation, type() == FilterOperation::PASSTHROUGH);
176
177class ReferenceFilterOperation : public FilterOperation {
178public:
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
204private:
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
215FILTEROPERATION_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.
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    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
235private:
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
249FILTEROPERATION_TYPE_CASTS(BasicColorMatrixFilterOperation, isBasicColorMatrixFilterOperation());
250
251// INVERT, BRIGHTNESS, CONTRAST and OPACITY are variations on a basic component transfer effect.
252class BasicComponentTransferFilterOperation : public FilterOperation {
253public:
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
270private:
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
284FILTEROPERATION_TYPE_CASTS(BasicComponentTransferFilterOperation, isBasicComponentTransferFilterOperation());
285
286class BlurFilterOperation : public FilterOperation {
287public:
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
305private:
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
317FILTEROPERATION_TYPE_CASTS(BlurFilterOperation, type() == FilterOperation::BLUR);
318
319class DropShadowFilterOperation : public FilterOperation {
320public:
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
342private:
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
358FILTEROPERATION_TYPE_CASTS(DropShadowFilterOperation, type() == FilterOperation::DROP_SHADOW);
359
360} // namespace WebCore
361
362#endif // ENABLE(CSS_FILTERS)
363
364#endif // FilterOperation_h
365