Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / filters / FEComposite.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7  * Copyright (C) 2013 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #include "config.h"
26
27 #include "platform/graphics/filters/FEComposite.h"
28
29 #include "SkArithmeticMode.h"
30 #include "SkXfermodeImageFilter.h"
31
32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
33 #include "platform/text/TextStream.h"
34
35 namespace blink {
36
37 FEComposite::FEComposite(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
38     : FilterEffect(filter)
39     , m_type(type)
40     , m_k1(k1)
41     , m_k2(k2)
42     , m_k3(k3)
43     , m_k4(k4)
44 {
45 }
46
47 PassRefPtr<FEComposite> FEComposite::create(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
48 {
49     return adoptRef(new FEComposite(filter, type, k1, k2, k3, k4));
50 }
51
52 CompositeOperationType FEComposite::operation() const
53 {
54     return m_type;
55 }
56
57 bool FEComposite::setOperation(CompositeOperationType type)
58 {
59     if (m_type == type)
60         return false;
61     m_type = type;
62     return true;
63 }
64
65 float FEComposite::k1() const
66 {
67     return m_k1;
68 }
69
70 bool FEComposite::setK1(float k1)
71 {
72     if (m_k1 == k1)
73         return false;
74     m_k1 = k1;
75     return true;
76 }
77
78 float FEComposite::k2() const
79 {
80     return m_k2;
81 }
82
83 bool FEComposite::setK2(float k2)
84 {
85     if (m_k2 == k2)
86         return false;
87     m_k2 = k2;
88     return true;
89 }
90
91 float FEComposite::k3() const
92 {
93     return m_k3;
94 }
95
96 bool FEComposite::setK3(float k3)
97 {
98     if (m_k3 == k3)
99         return false;
100     m_k3 = k3;
101     return true;
102 }
103
104 float FEComposite::k4() const
105 {
106     return m_k4;
107 }
108
109 bool FEComposite::setK4(float k4)
110 {
111     if (m_k4 == k4)
112         return false;
113     m_k4 = k4;
114     return true;
115 }
116
117 FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
118 {
119     FloatRect requestedRect = originalRequestedRect;
120     if (clipsToBounds())
121         requestedRect.intersect(maxEffectRect());
122
123     // We may be called multiple times if result is used more than once. Return
124     // quickly if nothing new is required.
125     if (absolutePaintRect().contains(enclosingIntRect(requestedRect)))
126         return requestedRect;
127
128     // No mapPaintRect required for FEComposite.
129     FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect);
130     FloatRect affectedRect;
131     switch (m_type) {
132     case FECOMPOSITE_OPERATOR_IN:
133         // 'in' has output only in the intersection of both inputs.
134         affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect));
135         break;
136     case FECOMPOSITE_OPERATOR_ATOP:
137         // 'atop' has output only in the extents of the second input.
138         // Make sure first input knows where it needs to produce output.
139         inputEffect(0)->determineAbsolutePaintRect(input1Rect);
140         affectedRect = input1Rect;
141         break;
142     case FECOMPOSITE_OPERATOR_ARITHMETIC:
143         if (k4() > 0) {
144             // Make sure first input knows where it needs to produce output.
145             inputEffect(0)->determineAbsolutePaintRect(requestedRect);
146             // Arithmetic with non-zero k4 may influnce the complete filter primitive
147             // region. So we can't optimize the paint region here.
148             affectedRect = requestedRect;
149             break;
150         }
151         if (k2() <= 0) {
152             // Input 0 does not appear where input 1 is not present.
153             FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect);
154             if (k3() > 0) {
155                 affectedRect = input1Rect;
156             } else {
157                 // Just k1 is positive. Use intersection.
158                 affectedRect = intersection(input1Rect, input0Rect);
159             }
160             break;
161         }
162         // else fall through to use union
163     default:
164         // Take the union of both input effects.
165         affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect));
166         break;
167     }
168
169     affectedRect.intersect(requestedRect);
170     addAbsolutePaintRect(affectedRect);
171     return affectedRect;
172 }
173
174 SkXfermode::Mode toXfermode(CompositeOperationType mode)
175 {
176     switch (mode) {
177     case FECOMPOSITE_OPERATOR_OVER:
178         return SkXfermode::kSrcOver_Mode;
179     case FECOMPOSITE_OPERATOR_IN:
180         return SkXfermode::kSrcIn_Mode;
181     case FECOMPOSITE_OPERATOR_OUT:
182         return SkXfermode::kSrcOut_Mode;
183     case FECOMPOSITE_OPERATOR_ATOP:
184         return SkXfermode::kSrcATop_Mode;
185     case FECOMPOSITE_OPERATOR_XOR:
186         return SkXfermode::kXor_Mode;
187     default:
188         ASSERT_NOT_REACHED();
189         return SkXfermode::kSrcOver_Mode;
190     }
191 }
192
193 PassRefPtr<SkImageFilter> FEComposite::createImageFilter(SkiaImageFilterBuilder* builder)
194 {
195     return createImageFilterInternal(builder, true);
196 }
197
198 PassRefPtr<SkImageFilter> FEComposite::createImageFilterWithoutValidation(SkiaImageFilterBuilder* builder)
199 {
200     return createImageFilterInternal(builder, false);
201 }
202
203 PassRefPtr<SkImageFilter> FEComposite::createImageFilterInternal(SkiaImageFilterBuilder* builder, bool requiresPMColorValidation)
204 {
205     RefPtr<SkImageFilter> foreground(builder->build(inputEffect(0), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
206     RefPtr<SkImageFilter> background(builder->build(inputEffect(1), operatingColorSpace(), !mayProduceInvalidPreMultipliedPixels()));
207     SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
208     RefPtr<SkXfermode> mode;
209     if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
210         mode = adoptRef(SkArithmeticMode::Create(SkFloatToScalar(m_k1), SkFloatToScalar(m_k2), SkFloatToScalar(m_k3), SkFloatToScalar(m_k4), requiresPMColorValidation));
211     else
212         mode = adoptRef(SkXfermode::Create(toXfermode(m_type)));
213     return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
214 }
215
216 static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
217 {
218     switch (type) {
219     case FECOMPOSITE_OPERATOR_UNKNOWN:
220         ts << "UNKNOWN";
221         break;
222     case FECOMPOSITE_OPERATOR_OVER:
223         ts << "OVER";
224         break;
225     case FECOMPOSITE_OPERATOR_IN:
226         ts << "IN";
227         break;
228     case FECOMPOSITE_OPERATOR_OUT:
229         ts << "OUT";
230         break;
231     case FECOMPOSITE_OPERATOR_ATOP:
232         ts << "ATOP";
233         break;
234     case FECOMPOSITE_OPERATOR_XOR:
235         ts << "XOR";
236         break;
237     case FECOMPOSITE_OPERATOR_ARITHMETIC:
238         ts << "ARITHMETIC";
239         break;
240     }
241     return ts;
242 }
243
244 TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const
245 {
246     writeIndent(ts, indent);
247     ts << "[feComposite";
248     FilterEffect::externalRepresentation(ts);
249     ts << " operation=\"" << m_type << "\"";
250     if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
251         ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\"";
252     ts << "]\n";
253     inputEffect(0)->externalRepresentation(ts, indent + 1);
254     inputEffect(1)->externalRepresentation(ts, indent + 1);
255     return ts;
256 }
257
258 } // namespace blink