153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This library is free software; you can redistribute it and/or
953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * modify it under the terms of the GNU Library General Public
1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * License as published by the Free Software Foundation; either
1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * version 2 of the License, or (at your option) any later version.
1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This library is distributed in the hope that it will be useful,
1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Library General Public License for more details.
1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * You should have received a copy of the GNU Library General Public License
1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Boston, MA 02110-1301, USA.
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "config.h"
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/FEColorMatrix.h"
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/GraphicsContext.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/Filter.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/filters/SkiaImageFilterBuilder.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/skia/NativeImageSkia.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/text/TextStream.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderTreeAsText.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h"
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "SkColorFilterImageFilter.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "SkColorMatrixFilter.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace WebCore {
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)FEColorMatrix::FEColorMatrix(Filter* filter, ColorMatrixType type, const Vector<float>& values)
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    : FilterEffect(filter)
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    , m_type(type)
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    , m_values(values)
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)PassRefPtr<FEColorMatrix> FEColorMatrix::create(Filter* filter, ColorMatrixType type, const Vector<float>& values)
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return adoptRef(new FEColorMatrix(filter, type, values));
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)ColorMatrixType FEColorMatrix::type() const
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_type;
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool FEColorMatrix::setType(ColorMatrixType type)
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_type == type)
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_type = type;
6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return true;
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)const Vector<float>& FEColorMatrix::values() const
6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_values;
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool FEColorMatrix::setValues(const Vector<float> &values)
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_values == values)
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_values = values;
7853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return true;
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)inline void matrix(float& red, float& green, float& blue, float& alpha, const Vector<float>& values)
8253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
8353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255;
8453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255;
8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255;
8653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255;
8753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    red = r;
8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    green = g;
9053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    blue = b;
9153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    alpha = a;
9253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
9353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
9453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)inline void saturateAndHueRotate(float& red, float& green, float& blue, const float* components)
9553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float r = red * components[0] + green * components[1] + blue * components[2];
9753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float g = red * components[3] + green * components[4] + blue * components[5];
9853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float b = red * components[6] + green * components[7] + blue * components[8];
9953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    red = r;
10153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    green = g;
10253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    blue = b;
10353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
10453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)inline void luminance(float& red, float& green, float& blue, float& alpha)
10653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
10753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    alpha = 0.2125 * red + 0.7154 * green + 0.0721 * blue;
10853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    red = 0;
10953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    green = 0;
11053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    blue = 0;
11153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
11253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
11353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)template<ColorMatrixType filterType>
11453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void effectType(Uint8ClampedArray* pixelArray, const Vector<float>& values)
11553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
11653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    unsigned pixelArrayLength = pixelArray->length();
11753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float components[9];
11853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
11953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (filterType == FECOLORMATRIX_TYPE_SATURATE)
12053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        FEColorMatrix::calculateSaturateComponents(components, values[0]);
12153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    else if (filterType == FECOLORMATRIX_TYPE_HUEROTATE)
12253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        FEColorMatrix::calculateHueRotateComponents(components, values[0]);
12353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
12453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    for (unsigned pixelByteOffset = 0; pixelByteOffset < pixelArrayLength; pixelByteOffset += 4) {
12553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        float red = pixelArray->item(pixelByteOffset);
12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        float green = pixelArray->item(pixelByteOffset + 1);
12753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        float blue = pixelArray->item(pixelByteOffset + 2);
12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        float alpha = pixelArray->item(pixelByteOffset + 3);
12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
13053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        switch (filterType) {
13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            case FECOLORMATRIX_TYPE_MATRIX:
13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                matrix(red, green, blue, alpha, values);
13353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                break;
13453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            case FECOLORMATRIX_TYPE_SATURATE:
13553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            case FECOLORMATRIX_TYPE_HUEROTATE:
13653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                saturateAndHueRotate(red, green, blue, components);
13753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                break;
13853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                luminance(red, green, blue, alpha);
14053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                break;
14153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        pixelArray->set(pixelByteOffset, red);
14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        pixelArray->set(pixelByteOffset + 1, green);
14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        pixelArray->set(pixelByteOffset + 2, blue);
14653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        pixelArray->set(pixelByteOffset + 3, alpha);
14753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
14853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
14953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEColorMatrix::applySoftware()
15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FilterEffect* in = inputEffect(0);
15353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
15553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!resultImage)
15653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
15753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1585267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    resultImage->context()->drawImageBuffer(in->asImageBuffer(), drawingRegionOfInputImage(in->absolutePaintRect()));
15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
16053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    IntRect imageRect(IntPoint(), absolutePaintRect().size());
16153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    switch (m_type) {
16453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_UNKNOWN:
16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
16653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_MATRIX:
16753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        effectType<FECOLORMATRIX_TYPE_MATRIX>(pixelArray.get(), m_values);
16853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
16902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    case FECOLORMATRIX_TYPE_SATURATE:
17053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        effectType<FECOLORMATRIX_TYPE_SATURATE>(pixelArray.get(), m_values);
17153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
17253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_HUEROTATE:
17353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        effectType<FECOLORMATRIX_TYPE_HUEROTATE>(pixelArray.get(), m_values);
17453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
17553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
17653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(pixelArray.get(), m_values);
17753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        setIsAlphaImage(true);
17853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
17953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
18053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
18153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint());
18253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
18453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static void saturateMatrix(float s, SkScalar matrix[20])
18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
18653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[0] = 0.213f + 0.787f * s;
18753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[1] = 0.715f - 0.715f * s;
18853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[2] = 0.072f - 0.072f * s;
18953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[3] = matrix[4] = 0;
19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[5] = 0.213f - 0.213f * s;
19153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[6] = 0.715f + 0.285f * s;
19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[7] = 0.072f - 0.072f * s;
19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[8] = matrix[9] = 0;
19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[10] = 0.213f - 0.213f * s;
19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[11] = 0.715f - 0.715f * s;
19653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[12] = 0.072f + 0.928f * s;
19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[13] = matrix[14] = 0;
19853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[15] = matrix[16] = matrix[17] = 0;
19953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[18] = 1;
20053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[19] = 0;
20153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static void hueRotateMatrix(float hue, SkScalar matrix[20])
20453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float cosHue = cosf(hue * piFloat / 180);
20653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float sinHue = sinf(hue * piFloat / 180);
20753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[0] = 0.213f + cosHue * 0.787f - sinHue * 0.213f;
20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[1] = 0.715f - cosHue * 0.715f - sinHue * 0.715f;
20953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[2] = 0.072f - cosHue * 0.072f + sinHue * 0.928f;
21053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[3] = matrix[4] = 0;
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[5] = 0.213f - cosHue * 0.213f + sinHue * 0.143f;
21253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[6] = 0.715f + cosHue * 0.285f + sinHue * 0.140f;
21353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[7] = 0.072f - cosHue * 0.072f - sinHue * 0.283f;
21453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[8] = matrix[9] = 0;
21553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[10] = 0.213f - cosHue * 0.213f - sinHue * 0.787f;
21653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[11] = 0.715f - cosHue * 0.715f + sinHue * 0.715f;
21753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[12] = 0.072f + cosHue * 0.928f + sinHue * 0.072f;
21853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[13] = matrix[14] = 0;
21953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[15] = matrix[16] = matrix[17] = 0;
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[18] = 1;
22153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[19] = 0;
22253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
22353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
22453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static void luminanceToAlphaMatrix(SkScalar matrix[20])
22553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
22653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    memset(matrix, 0, 20 * sizeof(SkScalar));
22753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[15] = 0.2125f;
22853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[16] = 0.7154f;
22953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    matrix[17] = 0.0721f;
23053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
23153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
23253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static SkColorFilter* createColorFilter(ColorMatrixType type, const float* values)
23353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkScalar matrix[20];
23553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    switch (type) {
23653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_UNKNOWN:
23753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
23853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_MATRIX:
23953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for (int i = 0; i < 20; ++i)
24053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            matrix[i] = values[i];
24153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
24253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        matrix[4] *= SkScalar(255);
24353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        matrix[9] *= SkScalar(255);
24453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        matrix[14] *= SkScalar(255);
24553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        matrix[19] *= SkScalar(255);
24653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
24753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_SATURATE:
24853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        saturateMatrix(values[0], matrix);
24953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
25053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_HUEROTATE:
25153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        hueRotateMatrix(values[0], matrix);
25253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
25353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
25453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        luminanceToAlphaMatrix(matrix);
25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
25753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return new SkColorMatrixFilter(matrix);
25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
25953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
26053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool FEColorMatrix::applySkia()
26153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
26253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
26353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!resultImage)
26453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
26553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FilterEffect* in = inputEffect(0);
26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
268e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    SkRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
26953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
27053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data()));
27153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
27253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
27353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
27453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!nativeImage)
27553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return false;
27653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
27753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPaint paint;
27853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    paint.setColorFilter(filter);
27953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
280e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    resultImage->context()->drawBitmap(nativeImage->bitmap(), drawingRegion.fLeft, drawingRegion.fTop, &paint);
28153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return true;
28253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
28353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
284e6d4491e48613634a83c1957c72759da80987961Ben MurdochPassRefPtr<SkImageFilter> FEColorMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
28553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
286e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
28753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkAutoTUnref<SkColorFilter> filter(createColorFilter(m_type, m_values.data()));
288e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    return adoptRef(SkColorFilterImageFilter::Create(filter, input.get()));
28953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
29053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
29153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static TextStream& operator<<(TextStream& ts, const ColorMatrixType& type)
29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
29353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    switch (type) {
29453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_UNKNOWN:
29553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "UNKNOWN";
29653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
29753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_MATRIX:
29853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "MATRIX";
29953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
30053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_SATURATE:
30153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "SATURATE";
30253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
30353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_HUEROTATE:
30453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "HUEROTATE";
30553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
30653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    case FECOLORMATRIX_TYPE_LUMINANCETOALPHA:
30753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "LUMINANCETOALPHA";
30853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        break;
30953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
31053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return ts;
31153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
31253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
31353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)TextStream& FEColorMatrix::externalRepresentation(TextStream& ts, int indent) const
31453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
31553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    writeIndent(ts, indent);
31653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ts << "[feColorMatrix";
31753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FilterEffect::externalRepresentation(ts);
31853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ts << " type=\"" << m_type << "\"";
31953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (!m_values.isEmpty()) {
32053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << " values=\"";
32153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        Vector<float>::const_iterator ptr = m_values.begin();
32253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        const Vector<float>::const_iterator end = m_values.end();
32353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        while (ptr < end) {
32453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            ts << *ptr;
32553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            ++ptr;
32602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch            if (ptr < end)
32753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)                ts << " ";
32853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
32953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        ts << "\"";
33053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
33153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    ts << "]\n";
33253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    inputEffect(0)->externalRepresentation(ts, indent + 1);
33353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return ts;
33453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
33553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
33653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} // namespace WebCore
337