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#include "config.h"
27
28#if ENABLE(CSS_FILTERS)
29#include "FilterOperation.h"
30
31#include "AnimationUtilities.h"
32
33#if ENABLE(SVG)
34#include "CachedSVGDocumentReference.h"
35#endif
36
37namespace WebCore {
38
39bool DefaultFilterOperation::operator==(const FilterOperation& o) const
40{
41    if (!isSameType(o))
42        return false;
43
44    return representedType() == toDefaultFilterOperation(o).representedType();
45}
46
47ReferenceFilterOperation::ReferenceFilterOperation(const String& url, const String& fragment)
48    : FilterOperation(REFERENCE)
49    , m_url(url)
50    , m_fragment(fragment)
51{
52}
53
54ReferenceFilterOperation::~ReferenceFilterOperation()
55{
56}
57
58bool ReferenceFilterOperation::operator==(const FilterOperation& o) const
59{
60    if (!isSameType(o))
61        return false;
62
63    return m_url == toReferenceFilterOperation(o).m_url;
64}
65
66#if ENABLE(SVG)
67void ReferenceFilterOperation::setCachedSVGDocumentReference(PassOwnPtr<CachedSVGDocumentReference> cachedSVGDocumentReference)
68{
69    m_cachedSVGDocumentReference = cachedSVGDocumentReference;
70}
71#endif
72
73PassRefPtr<FilterOperation> BasicColorMatrixFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
74{
75    if (from && !from->isSameType(*this))
76        return this;
77
78    if (blendToPassthrough)
79        return BasicColorMatrixFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
80
81    const BasicColorMatrixFilterOperation* fromOp = toBasicColorMatrixFilterOperation(from);
82    double fromAmount = fromOp ? fromOp->amount() : passthroughAmount();
83    return BasicColorMatrixFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
84}
85
86inline bool BasicColorMatrixFilterOperation::operator==(const FilterOperation& o) const
87{
88    if (!isSameType(o))
89        return false;
90    const BasicColorMatrixFilterOperation& other = toBasicColorMatrixFilterOperation(o);
91    return m_amount == other.m_amount;
92}
93
94double BasicColorMatrixFilterOperation::passthroughAmount() const
95{
96    switch (m_type) {
97    case GRAYSCALE:
98    case SEPIA:
99    case HUE_ROTATE:
100        return 0;
101    case SATURATE:
102        return 1;
103    default:
104        ASSERT_NOT_REACHED();
105        return 0;
106    }
107}
108
109PassRefPtr<FilterOperation> BasicComponentTransferFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
110{
111    if (from && !from->isSameType(*this))
112        return this;
113
114    if (blendToPassthrough)
115        return BasicComponentTransferFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
116
117    const BasicComponentTransferFilterOperation* fromOp = toBasicComponentTransferFilterOperation(from);
118    double fromAmount = fromOp ? fromOp->amount() : passthroughAmount();
119    return BasicComponentTransferFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
120}
121
122inline bool BasicComponentTransferFilterOperation::operator==(const FilterOperation& o) const
123{
124    if (!isSameType(o))
125        return false;
126    const BasicComponentTransferFilterOperation& other = toBasicComponentTransferFilterOperation(o);
127    return m_amount == other.m_amount;
128}
129
130double BasicComponentTransferFilterOperation::passthroughAmount() const
131{
132    switch (m_type) {
133    case OPACITY:
134        return 1;
135    case INVERT:
136        return 0;
137    case CONTRAST:
138        return 1;
139    case BRIGHTNESS:
140        return 1;
141    default:
142        ASSERT_NOT_REACHED();
143        return 0;
144    }
145}
146
147bool BlurFilterOperation::operator==(const FilterOperation& o) const
148{
149    if (!isSameType(o))
150        return false;
151
152    return m_stdDeviation == toBlurFilterOperation(o).stdDeviation();
153}
154
155PassRefPtr<FilterOperation> BlurFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
156{
157    if (from && !from->isSameType(*this))
158        return this;
159
160    LengthType lengthType = m_stdDeviation.type();
161
162    if (blendToPassthrough)
163        return BlurFilterOperation::create(Length(lengthType).blend(m_stdDeviation, progress));
164
165    const BlurFilterOperation* fromOp = toBlurFilterOperation(from);
166    Length fromLength = fromOp ? fromOp->m_stdDeviation : Length(lengthType);
167    return BlurFilterOperation::create(m_stdDeviation.blend(fromLength, progress));
168}
169
170bool DropShadowFilterOperation::operator==(const FilterOperation& o) const
171{
172    if (!isSameType(o))
173        return false;
174    const DropShadowFilterOperation& other = toDropShadowFilterOperation(o);
175    return m_location == other.m_location && m_stdDeviation == other.m_stdDeviation && m_color == other.m_color;
176}
177
178PassRefPtr<FilterOperation> DropShadowFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
179{
180    if (from && !from->isSameType(*this))
181        return this;
182
183    if (blendToPassthrough)
184        return DropShadowFilterOperation::create(
185            WebCore::blend(m_location, IntPoint(), progress),
186            WebCore::blend(m_stdDeviation, 0, progress),
187            WebCore::blend(m_color, Color(Color::transparent), progress));
188
189    const DropShadowFilterOperation* fromOp = toDropShadowFilterOperation(from);
190    IntPoint fromLocation = fromOp ? fromOp->location() : IntPoint();
191    int fromStdDeviation = fromOp ? fromOp->stdDeviation() : 0;
192    Color fromColor = fromOp ? fromOp->color() : Color(Color::transparent);
193
194    return DropShadowFilterOperation::create(
195        WebCore::blend(fromLocation, m_location, progress),
196        WebCore::blend(fromStdDeviation, m_stdDeviation, progress),
197        WebCore::blend(fromColor, m_color, progress));
198}
199
200} // namespace WebCore
201
202#endif // ENABLE(CSS_FILTERS)
203