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>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
29 #include "FloatPoint.h"
30 #include "GraphicsContext.h"
31 #include "RenderTreeAsText.h"
32 #include "TextStream.h"
34 #include <wtf/ByteArray.h>
36 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
40 FEBlend::FEBlend(Filter* filter, BlendModeType mode)
41 : FilterEffect(filter)
46 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode)
48 return adoptRef(new FEBlend(filter, mode));
51 BlendModeType FEBlend::blendMode() const
56 bool FEBlend::setBlendMode(BlendModeType mode)
64 static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
69 static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
71 return (((255 - alphaA) * colorB + colorA * 255) / 255);
74 static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
76 return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
79 static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
81 return (((colorB + colorA) * 255 - colorA * colorB) / 255);
84 static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
86 return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
89 static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
91 return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
98 FilterEffect* in = inputEffect(0);
99 FilterEffect* in2 = inputEffect(1);
102 if (!in->hasResult() || !in2->hasResult())
105 ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
106 ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
108 ByteArray* dstPixelArray = createPremultipliedImageResult();
112 IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
113 RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
115 IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
116 RefPtr<ByteArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
118 // Keep synchronized with BlendModeType
119 static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
121 unsigned pixelArrayLength = srcPixelArrayA->length();
122 ASSERT(pixelArrayLength == srcPixelArrayB->length());
123 for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
124 unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
125 unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
126 for (unsigned channel = 0; channel < 3; ++channel) {
127 unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
128 unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
130 unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
131 dstPixelArray->set(pixelOffset + channel, result);
133 unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
134 dstPixelArray->set(pixelOffset + 3, alphaR);
142 static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
145 case FEBLEND_MODE_UNKNOWN:
148 case FEBLEND_MODE_NORMAL:
151 case FEBLEND_MODE_MULTIPLY:
154 case FEBLEND_MODE_SCREEN:
157 case FEBLEND_MODE_DARKEN:
160 case FEBLEND_MODE_LIGHTEN:
167 TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const
169 writeIndent(ts, indent);
171 FilterEffect::externalRepresentation(ts);
172 ts << " mode=\"" << m_mode << "\"]\n";
173 inputEffect(0)->externalRepresentation(ts, indent + 1);
174 inputEffect(1)->externalRepresentation(ts, indent + 1);
178 } // namespace WebCore
180 #endif // ENABLE(FILTERS)