/*
 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
 * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 * Copyright (C) 2021 Apple Inc.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "FEComponentTransferSoftwareApplier.h"

#include "FEComponentTransfer.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "PixelBuffer.h"
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>

namespace WebCore {

void FEComponentTransferSoftwareApplier::computeIdentityTable(LookupTable&, const ComponentTransferFunction&)
{
}

void FEComponentTransferSoftwareApplier::computeTabularTable(LookupTable& values, const ComponentTransferFunction& transferFunction)
{
    const Vector<float>& tableValues = transferFunction.tableValues;
    unsigned n = tableValues.size();
    if (n < 1)
        return;
    for (unsigned i = 0; i < values.size(); ++i) {
        double c = i / 255.0;
        unsigned k = static_cast<unsigned>(c * (n - 1));
        double v1 = tableValues[k];
        double v2 = tableValues[std::min((k + 1), (n - 1))];
        double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1));
        val = std::max(0.0, std::min(255.0, val));
        values[i] = static_cast<uint8_t>(val);
    }
}

void FEComponentTransferSoftwareApplier::computeDiscreteTable(LookupTable& values, const ComponentTransferFunction& transferFunction)
{
    const Vector<float>& tableValues = transferFunction.tableValues;
    unsigned n = tableValues.size();
    if (n < 1)
        return;
    for (unsigned i = 0; i < values.size(); ++i) {
        unsigned k = static_cast<unsigned>((i * n) / 255.0);
        k = std::min(k, n - 1);
        double val = 255 * tableValues[k];
        val = std::max(0.0, std::min(255.0, val));
        values[i] = static_cast<uint8_t>(val);
    }
}

void FEComponentTransferSoftwareApplier::computeLinearTable(LookupTable& values, const ComponentTransferFunction& transferFunction)
{
    for (unsigned i = 0; i < values.size(); ++i) {
        double val = transferFunction.slope * i + 255 * transferFunction.intercept;
        val = std::max(0.0, std::min(255.0, val));
        values[i] = static_cast<uint8_t>(val);
    }
}

void FEComponentTransferSoftwareApplier::computeGammaTable(LookupTable& values, const ComponentTransferFunction& transferFunction)
{
    for (unsigned i = 0; i < values.size(); ++i) {
        double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double
        double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset);
        val = std::max(0.0, std::min(255.0, val));
        values[i] = static_cast<uint8_t>(val);
    }
}

FEComponentTransferSoftwareApplier::LookupTable FEComponentTransferSoftwareApplier::computeLookupTable(const ComponentTransferFunction& function)
{
    LookupTable table;

    for (unsigned i = 0; i < table.size(); ++i)
        table[i] = i;

    using TransferType = void (*)(LookupTable&, const ComponentTransferFunction&);
    TransferType callEffect[] = {
        computeIdentityTable,   // FECOMPONENTTRANSFER_TYPE_UNKNOWN
        computeIdentityTable,   // FECOMPONENTTRANSFER_TYPE_IDENTITY
        computeTabularTable,    // FECOMPONENTTRANSFER_TYPE_TABLE
        computeDiscreteTable,   // FECOMPONENTTRANSFER_TYPE_DISCRETE
        computeLinearTable,     // FECOMPONENTTRANSFER_TYPE_LINEAR
        computeGammaTable       // FECOMPONENTTRANSFER_TYPE_GAMMA
    };

    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(static_cast<size_t>(function.type) < WTF_ARRAY_LENGTH(callEffect));
    callEffect[function.type](table, function);

    return table;
}

void FEComponentTransferSoftwareApplier::applyPlatform(PixelBuffer& pixelBuffer) const
{
    auto& pixelArray = pixelBuffer.data();
    unsigned pixelArrayLength = pixelArray.length();
    uint8_t* data = pixelArray.data();

    auto redTable   = computeLookupTable(m_effect.redFunction());
    auto greenTable = computeLookupTable(m_effect.greenFunction());
    auto blueTable  = computeLookupTable(m_effect.blueFunction());
    auto alphaTable = computeLookupTable(m_effect.alphaFunction());

    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        data[pixelOffset]     = redTable[data[pixelOffset]];
        data[pixelOffset + 1] = greenTable[data[pixelOffset + 1]];
        data[pixelOffset + 2] = blueTable[data[pixelOffset + 2]];
        data[pixelOffset + 3] = alphaTable[data[pixelOffset + 3]];
    }
}

bool FEComponentTransferSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result)
{
    auto& input = inputs[0].get();
    
    auto destinationPixelBuffer = result.pixelBuffer(AlphaPremultiplication::Unpremultiplied);
    if (!destinationPixelBuffer)
        return false;

    auto drawingRect = m_effect.requestedRegionOfInputPixelBuffer(input.absoluteImageRect());
    input.copyPixelBuffer(*destinationPixelBuffer, drawingRect);

    applyPlatform(*destinationPixelBuffer);
    return true;
}

} // namespace WebCore
