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