/*
 * Copyright 2024 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "modules/svg/include/SkSVGFeComponentTransfer.h"

#include "include/core/SkColorFilter.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkRect.h"
#include "include/effects/SkImageFilters.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTo.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGFilterContext.h"
#include "modules/svg/include/SkSVGTypes.h"

#include <cmath>
#include <cstddef>
#include <cstdint>
#include <tuple>
#include <utility>

class SkSVGRenderContext;

sk_sp<SkImageFilter> SkSVGFeComponentTransfer::onMakeImageFilter(
        const SkSVGRenderContext& ctx,
        const SkSVGFilterContext& fctx) const {
    std::vector<uint8_t> a_tbl, b_tbl, g_tbl, r_tbl;

    for (const auto& child : fChildren) {
        switch (child->tag()) {
            case SkSVGTag::kFeFuncA:
                a_tbl = static_cast<const SkSVGFeFunc*>(child.get())->getTable();
                break;
            case SkSVGTag::kFeFuncB:
                b_tbl = static_cast<const SkSVGFeFunc*>(child.get())->getTable();
                break;
            case SkSVGTag::kFeFuncG:
                g_tbl = static_cast<const SkSVGFeFunc*>(child.get())->getTable();
                break;
            case SkSVGTag::kFeFuncR:
                r_tbl = static_cast<const SkSVGFeFunc*>(child.get())->getTable();
                break;
            default:
                break;
        }
    }
    SkASSERT(a_tbl.empty() || a_tbl.size() == 256);
    SkASSERT(b_tbl.empty() || b_tbl.size() == 256);
    SkASSERT(g_tbl.empty() || g_tbl.size() == 256);
    SkASSERT(r_tbl.empty() || r_tbl.size() == 256);

    const SkRect cropRect = this->resolveFilterSubregion(ctx, fctx);
    const sk_sp<SkImageFilter> input = fctx.resolveInput(ctx,
                                                         this->getIn(),
                                                         this->resolveColorspace(ctx, fctx));

    const auto cf =  SkColorFilters::TableARGB(a_tbl.empty() ? nullptr : a_tbl.data(),
                                               r_tbl.empty() ? nullptr : r_tbl.data(),
                                               g_tbl.empty() ? nullptr : g_tbl.data(),
                                               b_tbl.empty() ? nullptr : b_tbl.data());

    return SkImageFilters::ColorFilter(std::move(cf), std::move(input), cropRect);
}

std::vector<uint8_t> SkSVGFeFunc::getTable() const {
    // https://www.w3.org/TR/SVG11/filters.html#feComponentTransferTypeAttribute
    const auto make_linear = [this]() -> std::vector<uint8_t> {
        std::vector<uint8_t> tbl(256);
        const float slope = this->getSlope(),
             intercept255 = this->getIntercept() * 255;

        for (size_t i = 0; i < 256; ++i) {
            tbl[i] = SkTPin<int>(sk_float_round2int(intercept255 + i * slope), 0, 255);
        }

        return tbl;
    };

    const auto make_gamma = [this]() -> std::vector<uint8_t> {
        std::vector<uint8_t> tbl(256);
        const float exponent = this->getExponent(),
                      offset = this->getOffset();

        for (size_t i = 0; i < 256; ++i) {
            const float component = offset + std::pow(i * (1 / 255.f), exponent);
            tbl[i] = SkTPin<int>(sk_float_round2int(component * 255), 0, 255);
        }

        return tbl;
    };

    const auto lerp_from_table_values = [this](auto lerp_func) -> std::vector<uint8_t> {
        const auto& vals = this->getTableValues();
        if (vals.size() < 2 || vals.size() > 255) {
            return {};
        }

        // number of interpolation intervals
        const size_t n = vals.size() - 1;

        std::vector<uint8_t> tbl(256);
        for (size_t k = 0; k < n; ++k) {
            // interpolation values
            const SkSVGNumberType v0 = SkTPin(vals[k + 0], 0.f, 1.f),
                                  v1 = SkTPin(vals[k + 1], 0.f, 1.f);

            // start/end component table indices
            const size_t c_start = k * 255 / n,
                         c_end   = (k + 1) * 255 / n;
            SkASSERT(c_end <= 255);

            for (size_t ci = c_start; ci < c_end; ++ci) {
                const float lerp_t = static_cast<float>(ci - c_start) / (c_end - c_start),
                         component = lerp_func(v0, v1, lerp_t);
                SkASSERT(component >= 0 && component <= 1);

                tbl[ci] = SkToU8(sk_float_round2int(component * 255));
            }
        }

        tbl.back() = SkToU8(sk_float_round2int(255 * SkTPin(vals.back(), 0.f, 1.f)));

        return tbl;
    };

    const auto make_table = [&]() -> std::vector<uint8_t> {
        return lerp_from_table_values([](float v0, float v1, float t) {
            return v0 + (v1 - v0) * t;
        });
    };

    const auto make_discrete = [&]() -> std::vector<uint8_t> {
        return lerp_from_table_values([](float v0, float v1, float t) {
            return v0;
        });
    };

    switch (this->getType()) {
        case SkSVGFeFuncType::kIdentity: return {};
        case SkSVGFeFuncType::kTable:    return make_table();
        case SkSVGFeFuncType::kDiscrete: return make_discrete();
        case SkSVGFeFuncType::kLinear:   return make_linear();
        case SkSVGFeFuncType::kGamma:    return make_gamma();
    }

    SkUNREACHABLE;
}

bool SkSVGFeFunc::parseAndSetAttribute(const char* name, const char* val) {
    return INHERITED::parseAndSetAttribute(name, val) ||
      this->setAmplitude(SkSVGAttributeParser::parse<SkSVGNumberType>("amplitude", name, val)) ||
      this->setExponent(SkSVGAttributeParser::parse<SkSVGNumberType>("exponent", name, val)) ||
      this->setIntercept(SkSVGAttributeParser::parse<SkSVGNumberType>("intercept", name, val)) ||
      this->setOffset(SkSVGAttributeParser::parse<SkSVGNumberType>("offset", name, val)) ||
      this->setSlope(SkSVGAttributeParser::parse<SkSVGNumberType>("slope", name, val)) ||
      this->setTableValues(SkSVGAttributeParser::parse<std::vector<SkSVGNumberType>>("tableValues",
                                                                                     name, val)) ||
      this->setType(SkSVGAttributeParser::parse<SkSVGFeFuncType>("type", name, val));
}

template <>
bool SkSVGAttributeParser::parse(SkSVGFeFuncType* type) {
    static constexpr std::tuple<const char*, SkSVGFeFuncType> gTypeMap[] = {
            { "identity", SkSVGFeFuncType::kIdentity },
            { "table"   , SkSVGFeFuncType::kTable    },
            { "discrete", SkSVGFeFuncType::kDiscrete },
            { "linear"  , SkSVGFeFuncType::kLinear   },
            { "gamma"   , SkSVGFeFuncType::kGamma    },
    };

    return this->parseEnumMap(gTypeMap, type) && this->parseEOSToken();
}
