1 /* 2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org> 4 * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org> 5 * Copyright (C) 2009 Dirk Schulze <krit (at) 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 blink { 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 blink 243