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 "ImageData.h"
35 FEComposite::FEComposite(const CompositeOperationType& type, float k1, float k2, float k3, float k4)
45 PassRefPtr<FEComposite> FEComposite::create(const CompositeOperationType& type, float k1, float k2, float k3, float k4)
47 return adoptRef(new FEComposite(type, k1, k2, k3, k4));
50 CompositeOperationType FEComposite::operation() const
55 void FEComposite::setOperation(CompositeOperationType type)
60 float FEComposite::k1() const
65 void FEComposite::setK1(float k1)
70 float FEComposite::k2() const
75 void FEComposite::setK2(float k2)
80 float FEComposite::k3() const
85 void FEComposite::setK3(float k3)
90 float FEComposite::k4() const
95 void FEComposite::setK4(float k4)
100 inline void arithmetic(const ByteArray* srcPixelArrayA, ByteArray* srcPixelArrayB,
101 float k1, float k2, float k3, float k4)
103 float scaledK1 = k1 / 255.f;
104 float scaledK4 = k4 * 255.f;
105 unsigned pixelArrayLength = srcPixelArrayA->length();
106 for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
107 for (unsigned channel = 0; channel < 4; ++channel) {
108 unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
109 unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
111 double result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
112 srcPixelArrayB->set(pixelOffset + channel, result);
117 void FEComposite::determineAbsolutePaintRect(Filter* filter)
120 case FECOMPOSITE_OPERATOR_IN:
121 case FECOMPOSITE_OPERATOR_ATOP:
122 // For In and Atop the first effect just influences the result of
123 // the second effect. So just use the absolute paint rect of the second effect here.
124 setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
126 case FECOMPOSITE_OPERATOR_ARITHMETIC:
127 // Arithmetic may influnce the compele filter primitive region. So we can't
128 // optimize the paint region here.
129 setAbsolutePaintRect(maxEffectRect());
132 // Take the union of both input effects.
133 FilterEffect::determineAbsolutePaintRect(filter);
138 void FEComposite::apply(Filter* filter)
140 FilterEffect* in = inputEffect(0);
141 FilterEffect* in2 = inputEffect(1);
144 if (!in->resultImage() || !in2->resultImage())
147 GraphicsContext* filterContext = effectContext(filter);
151 FloatRect srcRect = FloatRect(0, 0, -1, -1);
153 case FECOMPOSITE_OPERATOR_OVER:
154 filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
155 filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
157 case FECOMPOSITE_OPERATOR_IN:
158 filterContext->save();
159 filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->absolutePaintRect()));
160 filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
161 filterContext->restore();
163 case FECOMPOSITE_OPERATOR_OUT:
164 filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
165 filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
167 case FECOMPOSITE_OPERATOR_ATOP:
168 filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
169 filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
171 case FECOMPOSITE_OPERATOR_XOR:
172 filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
173 filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
175 case FECOMPOSITE_OPERATOR_ARITHMETIC: {
176 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
177 RefPtr<ImageData> srcImageData = in->resultImage()->getPremultipliedImageData(effectADrawingRect);
178 ByteArray* srcPixelArrayA = srcImageData->data()->data();
180 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
181 RefPtr<ImageData> imageData = in2->resultImage()->getPremultipliedImageData(effectBDrawingRect);
182 ByteArray* srcPixelArrayB = imageData->data()->data();
184 arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
185 resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
193 void FEComposite::dump()
197 static TextStream& operator<<(TextStream& ts, const CompositeOperationType& type)
200 case FECOMPOSITE_OPERATOR_UNKNOWN:
203 case FECOMPOSITE_OPERATOR_OVER:
206 case FECOMPOSITE_OPERATOR_IN:
209 case FECOMPOSITE_OPERATOR_OUT:
212 case FECOMPOSITE_OPERATOR_ATOP:
215 case FECOMPOSITE_OPERATOR_XOR:
218 case FECOMPOSITE_OPERATOR_ARITHMETIC:
225 TextStream& FEComposite::externalRepresentation(TextStream& ts, int indent) const
227 writeIndent(ts, indent);
228 ts << "[feComposite";
229 FilterEffect::externalRepresentation(ts);
230 ts << " operation=\"" << m_type << "\"";
231 if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC)
232 ts << " k1=\"" << m_k1 << "\" k2=\"" << m_k2 << "\" k3=\"" << m_k3 << "\" k4=\"" << m_k4 << "\"";
234 inputEffect(0)->externalRepresentation(ts, indent + 1);
235 inputEffect(1)->externalRepresentation(ts, indent + 1);
239 } // namespace WebCore
241 #endif // ENABLE(FILTERS)