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

#include "include/core/SkColorFilter.h"
#include "include/effects/SkImageFilters.h"
#include "include/private/SkColorData.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGFeColorMatrix.h"
#include "modules/svg/include/SkSVGFilterContext.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGValue.h"

bool SkSVGFeColorMatrix::parseAndSetAttribute(const char* name, const char* value) {
    return INHERITED::parseAndSetAttribute(name, value) ||
           this->setType(
                   SkSVGAttributeParser::parse<SkSVGFeColorMatrixType>("type", name, value)) ||
           this->setValues(
                   SkSVGAttributeParser::parse<SkSVGFeColorMatrixValues>("values", name, value));
}

SkColorMatrix SkSVGFeColorMatrix::makeMatrixForType() const {
    if (fValues.empty() && fType != SkSVGFeColorMatrixType::kLuminanceToAlpha) {
        return SkColorMatrix();
    }

    switch (fType) {
        case SkSVGFeColorMatrixType::kMatrix: {
            if (fValues.count() < 20) {
                return SkColorMatrix();
            }
            SkColorMatrix m;
            m.setRowMajor(this->fValues.begin());
            return m;
        }
        case SkSVGFeColorMatrixType::kSaturate:
            return MakeSaturate(fValues.count() > 0 ? fValues[0] : 1);
        case SkSVGFeColorMatrixType::kHueRotate:
            return MakeHueRotate(fValues.count() > 0 ? fValues[0] : 0);
        case SkSVGFeColorMatrixType::kLuminanceToAlpha:
            return MakeLuminanceToAlpha();
    }

    SkUNREACHABLE;
}

SkColorMatrix SkSVGFeColorMatrix::MakeSaturate(SkSVGNumberType s) {
    SkColorMatrix m;
    m.setSaturation(s);
    return m;
}

SkColorMatrix SkSVGFeColorMatrix::MakeHueRotate(SkSVGNumberType degrees) {
    const SkScalar theta = SkDegreesToRadians(degrees);
    const SkSVGNumberType c = SkScalarCos(theta);
    const SkSVGNumberType s = SkScalarSin(theta);
    return SkColorMatrix(
        0.213f + c* 0.787f + s*-0.213f,
        0.715f + c*-0.715f + s*-0.715f,
        0.072f + c*-0.072f + s* 0.928f,
        0,
        0,

        0.213f + c*-0.213f + s* 0.143f,
        0.715f + c* 0.285f + s* 0.140f,
        0.072f + c*-0.072f + s*-0.283f,
        0,
        0,

        0.213f + c*-0.213f + s*-0.787f,
        0.715f + c*-0.715f + s* 0.715f,
        0.072f + c* 0.928f + s* 0.072f,
        0,
        0,

        0,0,0,1,0
    );
}

SkColorMatrix SkSVGFeColorMatrix::MakeLuminanceToAlpha() {
    return SkColorMatrix(
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B, 0, 0
    );
}

sk_sp<SkImageFilter> SkSVGFeColorMatrix::onMakeImageFilter(const SkSVGRenderContext& ctx,
                                                           const SkSVGFilterContext& fctx) const {
    return SkImageFilters::ColorFilter(
            SkColorFilters::Matrix(makeMatrixForType()),
            fctx.resolveInput(ctx, this->getIn(), this->resolveColorspace(ctx)),
            this->resolveFilterSubregion(ctx, fctx));
}

template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixValues* values) {
    SkSVGNumberType value;
    if (!this->parse(&value)) {
        return false;
    }

    values->push_back(value);
    while (true) {
        if (!this->parse(&value) || values->count() >= 20) {
            break;
        }
        values->push_back(value);
    }

    return this->parseEOSToken();
}

template <> bool SkSVGAttributeParser::parse(SkSVGFeColorMatrixType* type) {
    static constexpr std::tuple<const char*, SkSVGFeColorMatrixType> gTypeMap[] = {
            {"matrix", SkSVGFeColorMatrixType::kMatrix},
            {"saturate", SkSVGFeColorMatrixType::kSaturate},
            {"hueRotate", SkSVGFeColorMatrixType::kHueRotate},
            {"luminanceToAlpha", SkSVGFeColorMatrixType::kLuminanceToAlpha},
    };

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