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.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
27 #include "FEComposite.h"
30 #include "GraphicsContext.h"
31 #include "RenderTreeAsText.h"
32 #include "TextStream.h"
34 #include <wtf/ByteArray.h>
38 FEComposite::FEComposite(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
39 : FilterEffect(filter)
48 PassRefPtr<FEComposite> FEComposite::create(Filter* filter, const CompositeOperationType& type, float k1, float k2, float k3, float k4)
50 return adoptRef(new FEComposite(filter, type, k1, k2, k3, k4));
53 CompositeOperationType FEComposite::operation() const
58 bool FEComposite::setOperation(CompositeOperationType type)
66 float FEComposite::k1() const
71 bool FEComposite::setK1(float k1)
79 float FEComposite::k2() const
84 bool FEComposite::setK2(float k2)
92 float FEComposite::k3() const
97 bool FEComposite::setK3(float k3)
105 float FEComposite::k4() const
110 bool FEComposite::setK4(float k4)
118 template <int b1, int b2, int b3, int b4>
119 inline void computeArithmeticPixels(unsigned char* source, unsigned char* destination, int pixelArrayLength,
120 float k1, float k2, float k3, float k4)
125 scaledK1 = k1 / 255.f;
127 scaledK4 = k4 * 255.f;
129 while (--pixelArrayLength >= 0) {
130 unsigned char i1 = *source;
131 unsigned char i2 = *destination;
134 result += scaledK1 * i1 * i2;
144 else if (result >= 255)
147 *destination = result;
153 inline void arithmetic(ByteArray* srcPixelArrayA, ByteArray* srcPixelArrayB,
154 float k1, float k2, float k3, float k4)
156 int pixelArrayLength = srcPixelArrayA->length();
157 ASSERT(pixelArrayLength == static_cast<int>(srcPixelArrayB->length()));
158 unsigned char* source = srcPixelArrayA->data();
159 unsigned char* destination = srcPixelArrayB->data();
163 computeArithmeticPixels<0, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
167 computeArithmeticPixels<1, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
172 computeArithmeticPixels<0, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
175 computeArithmeticPixels<1, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
178 void FEComposite::determineAbsolutePaintRect()
181 case FECOMPOSITE_OPERATOR_IN:
182 case FECOMPOSITE_OPERATOR_ATOP:
183 // For In and Atop the first effect just influences the result of
184 // the second effect. So just use the absolute paint rect of the second effect here.
185 setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
187 case FECOMPOSITE_OPERATOR_ARITHMETIC:
188 // Arithmetic may influnce the compele filter primitive region. So we can't
189 // optimize the paint region here.
190 setAbsolutePaintRect(enclosingIntRect(maxEffectRect()));
193 // Take the union of both input effects.
194 FilterEffect::determineAbsolutePaintRect();
199 void FEComposite::apply()
203 FilterEffect* in = inputEffect(0);
204 FilterEffect* in2 = inputEffect(1);
207 if (!in->hasResult() || !in2->hasResult())
210 if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
211 ByteArray* dstPixelArray = createPremultipliedImageResult();
215 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
216 RefPtr<ByteArray> srcPixelArray = in->asPremultipliedImage(effectADrawingRect);
218 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
219 in2->copyPremultipliedImage(dstPixelArray, effectBDrawingRect);
221 arithmetic(srcPixelArray.get(), dstPixelArray, m_k1, m_k2, m_k3, m_k4);
225 ImageBuffer* resultImage = createImageBufferResult();
228 GraphicsContext* filterContext = resultImage->context();
230 FloatRect srcRect = FloatRect(0, 0, -1, -1);
232 case FECOMPOSITE_OPERATOR_OVER:
233 filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
234 filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
236 case FECOMPOSITE_OPERATOR_IN: {
237 GraphicsContextStateSaver stateSaver(*filterContext);
238 filterContext->clipToImageBuffer(in2->asImageBuffer(), drawingRegionOfInputImage(in2->absolutePaintRect()));
239 filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
242 case FECOMPOSITE_OPERATOR_OUT:
243 filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
244 filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
246 case FECOMPOSITE_OPERATOR_ATOP:
247 filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
248 filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
250 case FECOMPOSITE_OPERATOR_XOR:
251 filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
252 filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
259 void FEComposite::dump()
263 static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
266 case FECOMPOSITE_OPERATOR_UNKNOWN:
269 case FECOMPOSITE_OPERATOR_OVER:
272 case FECOMPOSITE_OPERATOR_IN:
275 case FECOMPOSITE_OPERATOR_OUT:
278 case FECOMPOSITE_OPERATOR_ATOP:
281 case FECOMPOSITE_OPERATOR_XOR:
284 case FECOMPOSITE_OPERATOR_ARITHMETIC:
291 TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const
293 writeIndent(ts, indent);
294 ts << "[feComposite";
295 FilterEffect::externalRepresentation(ts);
296 ts << " operation=\"" << m_type << "\"";
297 if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
298 ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\"";
300 inputEffect(0)->externalRepresentation(ts, indent + 1);
301 inputEffect(1)->externalRepresentation(ts, indent + 1);
305 } // namespace WebCore
307 #endif // ENABLE(FILTERS)