• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FEBlend(Filter * filter,BlendModeType mode)40 FEBlend::FEBlend(Filter* filter, BlendModeType mode)
41     : FilterEffect(filter)
42     , m_mode(mode)
43 {
44 }
45 
create(Filter * filter,BlendModeType mode)46 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode)
47 {
48     return adoptRef(new FEBlend(filter, mode));
49 }
50 
blendMode() const51 BlendModeType FEBlend::blendMode() const
52 {
53     return m_mode;
54 }
55 
setBlendMode(BlendModeType mode)56 bool FEBlend::setBlendMode(BlendModeType mode)
57 {
58     if (m_mode == mode)
59         return false;
60     m_mode = mode;
61     return true;
62 }
63 
unknown(unsigned char,unsigned char,unsigned char,unsigned char)64 static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
65 {
66     return 0;
67 }
68 
normal(unsigned char colorA,unsigned char colorB,unsigned char alphaA,unsigned char)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 
multiply(unsigned char colorA,unsigned char colorB,unsigned char alphaA,unsigned char alphaB)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 
screen(unsigned char colorA,unsigned char colorB,unsigned char,unsigned char)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 
darken(unsigned char colorA,unsigned char colorB,unsigned char alphaA,unsigned char alphaB)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 
lighten(unsigned char colorA,unsigned char colorB,unsigned char alphaA,unsigned char alphaB)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 
apply()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     if (m_mode <= FEBLEND_MODE_UNKNOWN || m_mode > FEBLEND_MODE_LIGHTEN)
106         return;
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 
dump()138 void FEBlend::dump()
139 {
140 }
141 
operator <<(TextStream & ts,const BlendModeType & type)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 
externalRepresentation(TextStream & ts,int indent) const167 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)
181