Make PNGImageDecoder::rowAvailable auto-vectorizable
[WebKit-https.git] / 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  * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
7  *
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.
12  *
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.
17  *
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.
22  */
23
24 #include "config.h"
25
26 #if ENABLE(FILTERS)
27 #include "FEBlend.h"
28 #include "FEBlendNEON.h"
29
30 #include "Filter.h"
31 #include "FloatPoint.h"
32 #include "GraphicsContext.h"
33 #include "RenderTreeAsText.h"
34 #include "TextStream.h"
35
36 #include <wtf/Uint8ClampedArray.h>
37
38 typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
39
40 namespace WebCore {
41
42 FEBlend::FEBlend(Filter* filter, BlendModeType mode)
43     : FilterEffect(filter)
44     , m_mode(mode)
45 {
46 }
47
48 PassRefPtr<FEBlend> FEBlend::create(Filter* filter, BlendModeType mode)
49 {
50     return adoptRef(new FEBlend(filter, mode));
51 }
52
53 BlendModeType FEBlend::blendMode() const
54 {
55     return m_mode;
56 }
57
58 bool FEBlend::setBlendMode(BlendModeType mode)
59 {
60     if (m_mode == mode)
61         return false;
62     m_mode = mode;
63     return true;
64 }
65
66 inline unsigned char feBlendNormal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
67 {
68     return fastDivideBy255((255 - alphaA) * colorB + colorA * 255);
69 }
70
71 inline unsigned char feBlendMultiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
72 {
73     return fastDivideBy255((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA);
74 }
75
76 inline unsigned char feBlendScreen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
77 {
78     return fastDivideBy255((colorB + colorA) * 255 - colorA * colorB);
79 }
80
81 inline unsigned char feBlendDarken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
82 {
83     return fastDivideBy255(std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
84 }
85
86 inline unsigned char feBlendLighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
87 {
88     return fastDivideBy255(std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255));
89 }
90
91 inline unsigned char feBlendUnknown(unsigned char, unsigned char, unsigned char, unsigned char)
92 {
93     return 0;
94 }
95
96 template<BlendType BlendFunction>
97 static void platformApply(unsigned char* sourcePixelA, unsigned char* sourcePixelB,
98                           unsigned char* destinationPixel, unsigned pixelArrayLength)
99 {
100     unsigned len = pixelArrayLength / 4;
101     for (unsigned pixelOffset = 0; pixelOffset < len; pixelOffset++) {
102         unsigned char alphaA = sourcePixelA[3];
103         unsigned char alphaB = sourcePixelB[3];
104         destinationPixel[0] = BlendFunction(sourcePixelA[0], sourcePixelB[0], alphaA, alphaB);
105         destinationPixel[1] = BlendFunction(sourcePixelA[1], sourcePixelB[1], alphaA, alphaB);
106         destinationPixel[2] = BlendFunction(sourcePixelA[2], sourcePixelB[2], alphaA, alphaB);
107         destinationPixel[3] = 255 - fastDivideBy255((255 - alphaA) * (255 - alphaB));
108         sourcePixelA += 4;
109         sourcePixelB += 4;
110         destinationPixel += 4;
111     }
112 }
113
114 void FEBlend::platformApplyGeneric(unsigned char* sourcePixelA, unsigned char* sourcePixelB,
115                                    unsigned char* destinationPixel, unsigned pixelArrayLength)
116 {
117     switch (m_mode) {
118     case FEBLEND_MODE_NORMAL:
119         platformApply<feBlendNormal>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
120         break;
121     case FEBLEND_MODE_MULTIPLY:
122         platformApply<feBlendMultiply>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
123         break;
124     case FEBLEND_MODE_SCREEN:
125         platformApply<feBlendScreen>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
126         break;
127     case FEBLEND_MODE_DARKEN:
128         platformApply<feBlendDarken>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
129         break;
130     case FEBLEND_MODE_LIGHTEN:
131         platformApply<feBlendLighten>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
132         break;
133     case FEBLEND_MODE_UNKNOWN:
134         platformApply<feBlendUnknown>(sourcePixelA, sourcePixelB, destinationPixel, pixelArrayLength);
135         break;
136     }
137 }
138
139 void FEBlend::platformApplySoftware()
140 {
141     FilterEffect* in = inputEffect(0);
142     FilterEffect* in2 = inputEffect(1);
143
144     ASSERT(m_mode > FEBLEND_MODE_UNKNOWN);
145     ASSERT(m_mode <= FEBLEND_MODE_LIGHTEN);
146
147     Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
148     if (!dstPixelArray)
149         return;
150
151     IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
152     RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
153
154     IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
155     RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asPremultipliedImage(effectBDrawingRect);
156
157     unsigned pixelArrayLength = srcPixelArrayA->length();
158     ASSERT(pixelArrayLength == srcPixelArrayB->length());
159
160 #if HAVE(ARM_NEON_INTRINSICS)
161     if (pixelArrayLength >= 8)
162         platformApplyNEON(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
163     else { // If there is just one pixel we expand it to two.
164         ASSERT(pixelArrayLength > 0);
165         uint32_t sourceA[2] = {0, 0};
166         uint32_t sourceBAndDest[2] = {0, 0};
167
168         sourceA[0] = reinterpret_cast<uint32_t*>(srcPixelArrayA->data())[0];
169         sourceBAndDest[0] = reinterpret_cast<uint32_t*>(srcPixelArrayB->data())[0];
170         platformApplyNEON(reinterpret_cast<uint8_t*>(sourceA), reinterpret_cast<uint8_t*>(sourceBAndDest), reinterpret_cast<uint8_t*>(sourceBAndDest), 8);
171         reinterpret_cast<uint32_t*>(dstPixelArray->data())[0] = sourceBAndDest[0];
172     }
173 #else
174     platformApplyGeneric(srcPixelArrayA->data(), srcPixelArrayB->data(), dstPixelArray->data(), pixelArrayLength);
175 #endif
176 }
177
178 void FEBlend::dump()
179 {
180 }
181
182 static TextStream& operator<<(TextStream& ts, const BlendModeType& type)
183 {
184     switch (type) {
185     case FEBLEND_MODE_UNKNOWN:
186         ts << "UNKNOWN";
187         break;
188     case FEBLEND_MODE_NORMAL:
189         ts << "NORMAL";
190         break;
191     case FEBLEND_MODE_MULTIPLY:
192         ts << "MULTIPLY";
193         break;
194     case FEBLEND_MODE_SCREEN:
195         ts << "SCREEN";
196         break;
197     case FEBLEND_MODE_DARKEN:
198         ts << "DARKEN";
199         break;
200     case FEBLEND_MODE_LIGHTEN:
201         ts << "LIGHTEN";
202         break;
203     }
204     return ts;
205 }
206
207 TextStream& FEBlend::externalRepresentation(TextStream& ts, int indent) const
208 {
209     writeIndent(ts, indent);
210     ts << "[feBlend";
211     FilterEffect::externalRepresentation(ts);
212     ts << " mode=\"" << m_mode << "\"]\n";
213     inputEffect(0)->externalRepresentation(ts, indent + 1);
214     inputEffect(1)->externalRepresentation(ts, indent + 1);
215     return ts;
216 }
217
218 } // namespace WebCore
219
220 #endif // ENABLE(FILTERS)