initial import
[vuplus_webkit] / Source / WebCore / platform / graphics / filters / FEBlend.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  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "config.h"
24
25 #if ENABLE(FILTERS)
26 #include "FEBlend.h"
27
28 #include "Filter.h"
29 #include "FloatPoint.h"
30 #include "GraphicsContext.h"
31 #include "RenderTreeAsText.h"
32 #include "TextStream.h"
33
34 #include <wtf/ByteArray.h>
35
36 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
37
38 namespace WebCore {
39
40 FEBlend::FEBlend(Filter* filter, BlendModeType mode)
41     : FilterEffect(filter)
42     , m_mode(mode)
43 {
44 }
45
46 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode)
47 {
48     return adoptRef(new FEBlend(filter, mode));
49 }
50
51 BlendModeType FEBlend::blendMode() const
52 {
53     return m_mode;
54 }
55
56 bool FEBlend::setBlendMode(BlendModeType mode)
57 {
58     if (m_mode == mode)
59         return false;
60     m_mode = mode;
61     return true;
62 }
63
64 static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
65 {
66     return 0;
67 }
68
69 static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
70 {
71     return (((255 - alphaA) * colorB + colorA * 255) / 255);
72 }
73
74 static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
75 {
76     return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
77 }
78
79 static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
80 {
81     return (((colorB + colorA) * 255 - colorA * colorB) / 255);
82 }
83
84 static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
85 {
86     return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
87 }
88
89 static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
90 {
91     return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
92 }
93
94 void FEBlend::apply()
95 {
96     if (hasResult())
97         return;
98     FilterEffect* in = inputEffect(0);
99     FilterEffect* in2 = inputEffect(1);
100     in->apply();
101     in2->apply();
102     if (!in->hasResult() || !in2->hasResult())
103         return;
104
105     ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
106     ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
107
108     ByteArray* dstPixelArray = createPremultipliedImageResult();
109     if (!dstPixelArray)
110         return;
111
112     IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
113     RefPtr<ByteArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
114
115     IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
116     RefPtr<ByteArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
117
118     // Keep synchronized with BlendModeType
119     static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
120
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);
129
130             unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
131             dstPixelArray->set(pixelOffset + channel, result);
132         }
133         unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
134         dstPixelArray->set(pixelOffset + 3, alphaR);
135     }
136 }
137
138 void FEBlend::dump()
139 {
140 }
141
142 static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
143 {
144     switch (type) {
145     case FEBLEND_MODE_UNKNOWN:
146         ts << "UNKNOWN";
147         break;
148     case FEBLEND_MODE_NORMAL:
149         ts << "NORMAL";
150         break;
151     case FEBLEND_MODE_MULTIPLY:
152         ts << "MULTIPLY";
153         break;
154     case FEBLEND_MODE_SCREEN:
155         ts << "SCREEN";
156         break;
157     case FEBLEND_MODE_DARKEN:
158         ts << "DARKEN";
159         break;
160     case FEBLEND_MODE_LIGHTEN:
161         ts << "LIGHTEN";
162         break;
163     }
164     return ts;
165 }
166
167 TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const
168 {
169     writeIndent(ts, indent);
170     ts << "[feBlend";
171     FilterEffect::externalRepresentation(ts);
172     ts << " mode=\"" << m_mode << "\"]\n";
173     inputEffect(0)->externalRepresentation(ts, indent + 1);
174     inputEffect(1)->externalRepresentation(ts, indent + 1);
175     return ts;
176 }
177
178 } // namespace WebCore
179
180 #endif // ENABLE(FILTERS)