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.
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.
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.
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.
27 #include "platform/graphics/filters/FEComposite.h"
29 #include "SkArithmeticMode.h"
30 #include "SkXfermodeImageFilter.h"
32 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
33 #include "platform/text/TextStream.h"
37 FEComposite::FEComposite(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
38 : FilterEffect(filter)
47 PassRefPtr<FEComposite> FEComposite::create(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
49 return adoptRef(new FEComposite(filter, type, k1, k2, k3, k4));
52 CompositeOperationType FEComposite::operation() const
57 bool FEComposite::setOperation(CompositeOperationType type)
65 float FEComposite::k1() const
70 bool FEComposite::setK1(float k1)
78 float FEComposite::k2() const
83 bool FEComposite::setK2(float k2)
91 float FEComposite::k3() const
96 bool FEComposite::setK3(float k3)
104 float FEComposite::k4() const
109 bool FEComposite::setK4(float k4)
117 FloatRect FEComposite::determineAbsolutePaintRect(const FloatRect& originalRequestedRect)
119 FloatRect requestedRect = originalRequestedRect;
121 requestedRect.intersect(maxEffectRect());
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;
128 // No mapPaintRect required for FEComposite.
129 FloatRect input1Rect = inputEffect(1)->determineAbsolutePaintRect(requestedRect);
130 FloatRect affectedRect;
132 case FECOMPOSITE_OPERATOR_IN:
133 // 'in' has output only in the intersection of both inputs.
134 affectedRect = intersection(input1Rect, inputEffect(0)->determineAbsolutePaintRect(input1Rect));
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;
142 case FECOMPOSITE_OPERATOR_ARITHMETIC:
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;
152 // Input 0 does not appear where input 1 is not present.
153 FloatRect input0Rect = inputEffect(0)->determineAbsolutePaintRect(input1Rect);
155 affectedRect = input1Rect;
157 // Just k1 is positive. Use intersection.
158 affectedRect = intersection(input1Rect, input0Rect);
162 // else fall through to use union
164 // Take the union of both input effects.
165 affectedRect = unionRect(input1Rect, inputEffect(0)->determineAbsolutePaintRect(requestedRect));
169 affectedRect.intersect(requestedRect);
170 addAbsolutePaintRect(affectedRect);
174 SkXfermode::Mode toXfermode(CompositeOperationType 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;
188 ASSERT_NOT_REACHED();
189 return SkXfermode::kSrcOver_Mode;
193 PassRefPtr<SkImageFilter> FEComposite::createImageFilter(SkiaImageFilterBuilder* builder)
195 return createImageFilterInternal(builder, true);
198 PassRefPtr<SkImageFilter> FEComposite::createImageFilterWithoutValidation(SkiaImageFilterBuilder* builder)
200 return createImageFilterInternal(builder, false);
203 PassRefPtr<SkImageFilter> FEComposite::createImageFilterInternal(SkiaImageFilterBuilder* builder, bool requiresPMColorValidation)
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));
212 mode = adoptRef(SkXfermode::Create(toXfermode(m_type)));
213 return adoptRef(SkXfermodeImageFilter::Create(mode.get(), background.get(), foreground.get(), &cropRect));
216 static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
219 case FECOMPOSITE_OPERATOR_UNKNOWN:
222 case FECOMPOSITE_OPERATOR_OVER:
225 case FECOMPOSITE_OPERATOR_IN:
228 case FECOMPOSITE_OPERATOR_OUT:
231 case FECOMPOSITE_OPERATOR_ATOP:
234 case FECOMPOSITE_OPERATOR_XOR:
237 case FECOMPOSITE_OPERATOR_ARITHMETIC:
244 TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const
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 << "\"";
253 inputEffect(0)->externalRepresentation(ts, indent + 1);
254 inputEffect(1)->externalRepresentation(ts, indent + 1);