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 "FEColorMatrix.h" 27 28#include "Filter.h" 29#include "GraphicsContext.h" 30#include "TextStream.h" 31 32#include <runtime/Uint8ClampedArray.h> 33#include <wtf/MathExtras.h> 34 35namespace WebCore { 36 37FEColorMatrix::FEColorMatrix(Filter* filter, ColorMatrixType type, const Vector<float>& values) 38 : FilterEffect(filter) 39 , m_type(type) 40 , m_values(values) 41{ 42} 43 44PassRefPtr<FEColorMatrix> FEColorMatrix::create(Filter* filter, ColorMatrixType type, const Vector<float>& values) 45{ 46 return adoptRef(new FEColorMatrix(filter, type, values)); 47} 48 49ColorMatrixType FEColorMatrix::type() const 50{ 51 return m_type; 52} 53 54bool FEColorMatrix::setType(ColorMatrixType type) 55{ 56 if (m_type == type) 57 return false; 58 m_type = type; 59 return true; 60} 61 62const Vector<float>& FEColorMatrix::values() const 63{ 64 return m_values; 65} 66 67bool FEColorMatrix::setValues(const Vector<float> &values) 68{ 69 if (m_values == values) 70 return false; 71 m_values = values; 72 return true; 73} 74 75inline void matrix(float& red, float& green, float& blue, float& alpha, const Vector<float>& values) 76{ 77 float r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255; 78 float g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255; 79 float b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255; 80 float a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255; 81 82 red = r; 83 green = g; 84 blue = b; 85 alpha = a; 86} 87 88inline void saturateAndHueRotate(float& red, float& green, float& blue, const float* components) 89{ 90 float r = red * components[0] + green * components[1] + blue * components[2]; 91 float g = red * components[3] + green * components[4] + blue * components[5]; 92 float b = red * components[6] + green * components[7] + blue * components[8]; 93 94 red = r; 95 green = g; 96 blue = b; 97} 98 99inline void luminance(float& red, float& green, float& blue, float& alpha) 100{ 101 alpha = 0.2125 * red + 0.7154 * green + 0.0721 * blue; 102 red = 0; 103 green = 0; 104 blue = 0; 105} 106 107template<ColorMatrixType filterType> 108void effectType(Uint8ClampedArray* pixelArray, const Vector<float>& values) 109{ 110 unsigned pixelArrayLength = pixelArray->length(); 111 float components[9]; 112 113 if (filterType == FECOLORMATRIX_TYPE_SATURATE) 114 FEColorMatrix::calculateSaturateComponents(components, values[0]); 115 else if (filterType == FECOLORMATRIX_TYPE_HUEROTATE) 116 FEColorMatrix::calculateHueRotateComponents(components, values[0]); 117 118 for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) { 119 float red = pixelArray->item(pixelByteOffset); 120 float green = pixelArray->item(pixelByteOffset + 1); 121 float blue = pixelArray->item(pixelByteOffset + 2); 122 float alpha = pixelArray->item(pixelByteOffset + 3); 123 124 switch (filterType) { 125 case FECOLORMATRIX_TYPE_MATRIX: 126 matrix(red, green, blue, alpha, values); 127 break; 128 case FECOLORMATRIX_TYPE_SATURATE: 129 case FECOLORMATRIX_TYPE_HUEROTATE: 130 saturateAndHueRotate(red, green, blue, components); 131 break; 132 case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: 133 luminance(red, green, blue, alpha); 134 break; 135 } 136 137 pixelArray->set(pixelByteOffset, red); 138 pixelArray->set(pixelByteOffset + 1, green); 139 pixelArray->set(pixelByteOffset + 2, blue); 140 pixelArray->set(pixelByteOffset + 3, alpha); 141 } 142} 143 144void FEColorMatrix::platformApplySoftware() 145{ 146 FilterEffect* in = inputEffect(0); 147 148 ImageBuffer* resultImage = createImageBufferResult(); 149 if (!resultImage) 150 return; 151 152 resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect())); 153 154 IntRect imageRect(IntPoint(), absolutePaintRect().size()); 155 RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect); 156 157 switch (m_type) { 158 case FECOLORMATRIX_TYPE_UNKNOWN: 159 break; 160 case FECOLORMATRIX_TYPE_MATRIX: 161 effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values); 162 break; 163 case FECOLORMATRIX_TYPE_SATURATE: 164 effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values); 165 break; 166 case FECOLORMATRIX_TYPE_HUEROTATE: 167 effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values); 168 break; 169 case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: 170 effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values); 171 setIsAlphaImage(true); 172 break; 173 } 174 175 resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint()); 176} 177 178void FEColorMatrix::dump() 179{ 180} 181 182static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type) 183{ 184 switch (type) { 185 case FECOLORMATRIX_TYPE_UNKNOWN: 186 ts << "UNKNOWN"; 187 break; 188 case FECOLORMATRIX_TYPE_MATRIX: 189 ts << "MATRIX"; 190 break; 191 case FECOLORMATRIX_TYPE_SATURATE: 192 ts << "SATURATE"; 193 break; 194 case FECOLORMATRIX_TYPE_HUEROTATE: 195 ts << "HUEROTATE"; 196 break; 197 case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: 198 ts << "LUMINANCETOALPHA"; 199 break; 200 } 201 return ts; 202} 203 204TextStream& FEColorMatrix::externalRepresentation(TextStream& ts, int indent) const 205{ 206 writeIndent(ts, indent); 207 ts << "[feColorMatrix"; 208 FilterEffect::externalRepresentation(ts); 209 ts << " type=\"" << m_type << "\""; 210 if (!m_values.isEmpty()) { 211 ts << " values=\""; 212 Vector<float>::const_iterator ptr = m_values.begin(); 213 const Vector<float>::const_iterator end = m_values.end(); 214 while (ptr < end) { 215 ts << *ptr; 216 ++ptr; 217 if (ptr < end) 218 ts << " "; 219 } 220 ts << "\""; 221 } 222 ts << "]\n"; 223 inputEffect(0)->externalRepresentation(ts, indent + 1); 224 return ts; 225} 226 227} // namespace WebCore 228 229#endif // ENABLE(FILTERS) 230