Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / filters / FEColorMatrix.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) 2013 Google Inc. All rights reserved.
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 #include "platform/graphics/filters/FEColorMatrix.h"
26
27 #include "SkColorFilterImageFilter.h"
28 #include "SkColorMatrixFilter.h"
29 #include "platform/graphics/GraphicsContext.h"
30 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
31 #include "platform/graphics/skia/NativeImageSkia.h"
32 #include "platform/text/TextStream.h"
33 #include "wtf/MathExtras.h"
34 #include "wtf/Uint8ClampedArray.h"
35
36 namespace WebCore {
37
38 FEColorMatrix::FEColorMatrix(Filter* filter, ColorMatrixType type, const Vector<float>& values)
39     : FilterEffect(filter)
40     , m_type(type)
41     , m_values(values)
42 {
43 }
44
45 PassRefPtr<FEColorMatrix> FEColorMatrix::create(Filter* filter, ColorMatrixType type, const Vector<float>& values)
46 {
47     return adoptRef(new FEColorMatrix(filter, type, values));
48 }
49
50 ColorMatrixType FEColorMatrix::type() const
51 {
52     return m_type;
53 }
54
55 bool FEColorMatrix::setType(ColorMatrixType type)
56 {
57     if (m_type == type)
58         return false;
59     m_type = type;
60     return true;
61 }
62
63 const Vector<float>& FEColorMatrix::values() const
64 {
65     return m_values;
66 }
67
68 bool FEColorMatrix::setValues(const Vector<float> &values)
69 {
70     if (m_values == values)
71         return false;
72     m_values = values;
73     return true;
74 }
75
76 static void saturateMatrix(float s, SkScalar matrix[20])
77 {
78     matrix[0] = 0.213f + 0.787f * s;
79     matrix[1] = 0.715f - 0.715f * s;
80     matrix[2] = 0.072f - 0.072f * s;
81     matrix[3] = matrix[4] = 0;
82     matrix[5] = 0.213f - 0.213f * s;
83     matrix[6] = 0.715f + 0.285f * s;
84     matrix[7] = 0.072f - 0.072f * s;
85     matrix[8] = matrix[9] = 0;
86     matrix[10] = 0.213f - 0.213f * s;
87     matrix[11] = 0.715f - 0.715f * s;
88     matrix[12] = 0.072f + 0.928f * s;
89     matrix[13] = matrix[14] = 0;
90     matrix[15] = matrix[16] = matrix[17] = 0;
91     matrix[18] = 1;
92     matrix[19] = 0;
93 }
94
95 static void hueRotateMatrix(float hue, SkScalar matrix[20])
96 {
97     float cosHue = cosf(hue * piFloat / 180);
98     float sinHue = sinf(hue * piFloat / 180);
99     matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
100     matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
101     matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
102     matrix[3] = matrix[4] = 0;
103     matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
104     matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
105     matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
106     matrix[8] = matrix[9] = 0;
107     matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
108     matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
109     matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
110     matrix[13] = matrix[14] = 0;
111     matrix[15] = matrix[16] = matrix[17] = 0;
112     matrix[18] = 1;
113     matrix[19] = 0;
114 }
115
116 static void luminanceToAlphaMatrix(SkScalar matrix[20])
117 {
118     memset(matrix, 0, 20 * sizeof(SkScalar));
119     matrix[15] = 0.2125f;
120     matrix[16] = 0.7154f;
121     matrix[17] = 0.0721f;
122 }
123
124 static SkColorFilter* createColorFilter(ColorMatrixType type, const float* values)
125 {
126     SkScalar matrix[20];
127     switch (type) {
128     case FECOLORMATRIX_TYPE_UNKNOWN:
129         break;
130     case FECOLORMATRIX_TYPE_MATRIX:
131         for (int i = 0; i < 20; ++i)
132             matrix[i] = values[i];
133
134         matrix[4] *= SkScalar(255);
135         matrix[9] *= SkScalar(255);
136         matrix[14] *= SkScalar(255);
137         matrix[19] *= SkScalar(255);
138         break;
139     case FECOLORMATRIX_TYPE_SATURATE:
140         saturateMatrix(values[0], matrix);
141         break;
142     case FECOLORMATRIX_TYPE_HUEROTATE:
143         hueRotateMatrix(values[0], matrix);
144         break;
145     case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
146         luminanceToAlphaMatrix(matrix);
147         break;
148     }
149     return SkColorMatrixFilter::Create(matrix);
150 }
151
152 void FEColorMatrix::applySoftware()
153 {
154     ImageBuffer* resultImage = createImageBufferResult();
155     if (!resultImage)
156         return;
157
158     FilterEffect* in = inputEffect(0);
159
160     IntRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
161
162     SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data()));
163
164     RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
165     RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
166     if (!nativeImage)
167         return;
168
169     SkPaint paint;
170     paint.setColorFilter(filter);
171     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
172     resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y(), &paint);
173
174     if (affectsTransparentPixels()) {
175         IntRect fullRect = IntRect(IntPoint(), absolutePaintRect().size());
176         resultImage->context()->clipOut(drawingRegion);
177         resultImage->context()->fillRect(fullRect, Color(m_values[4], m_values[9], m_values[14], m_values[19]));
178     }
179     return;
180 }
181
182 bool FEColorMatrix::affectsTransparentPixels()
183 {
184     // Because the input pixels are premultiplied, the only way clear pixels can be
185     // painted is if the additive component for the alpha is not 0.
186     return m_type == FECOLORMATRIX_TYPE_MATRIX && m_values[19] > 0;
187 }
188
189 PassRefPtr<SkImageFilter> FEColorMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
190 {
191     RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
192     SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data()));
193     SkImageFilter::CropRect rect = getCropRect(builder->cropOffset());
194     return adoptRef(SkColorFilterImageFilter::Create(filter, input.get(), &rect));
195 }
196
197 static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type)
198 {
199     switch (type) {
200     case FECOLORMATRIX_TYPE_UNKNOWN:
201         ts << "UNKNOWN";
202         break;
203     case FECOLORMATRIX_TYPE_MATRIX:
204         ts << "MATRIX";
205         break;
206     case FECOLORMATRIX_TYPE_SATURATE:
207         ts << "SATURATE";
208         break;
209     case FECOLORMATRIX_TYPE_HUEROTATE:
210         ts << "HUEROTATE";
211         break;
212     case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
213         ts << "LUMINANCETOALPHA";
214         break;
215     }
216     return ts;
217 }
218
219 TextStream& FEColorMatrix::externalRepresentation(TextStream& ts, int indent) const
220 {
221     writeIndent(ts, indent);
222     ts << "[feColorMatrix";
223     FilterEffect::externalRepresentation(ts);
224     ts << " type=\"" << m_type << "\"";
225     if (!m_values.isEmpty()) {
226         ts << " values=\"";
227         Vector<float>::const_iterator ptr = m_values.begin();
228         const Vector<float>::const_iterator end = m_values.end();
229         while (ptr < end) {
230             ts << *ptr;
231             ++ptr;
232             if (ptr < end)
233                 ts << " ";
234         }
235         ts << "\"";
236     }
237     ts << "]\n";
238     inputEffect(0)->externalRepresentation(ts, indent + 1);
239     return ts;
240 }
241
242 } // namespace WebCore