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

#include "SkColorSpaceXform.h"
#include "SkData.h"
#include "SkMakeUnique.h"
#include "skcms.h"

class SkColorSpaceXform_skcms : public SkColorSpaceXform {
public:
    SkColorSpaceXform_skcms(const skcms_ICCProfile& srcProfile,
                            const skcms_ICCProfile& dstProfile,
                            skcms_AlphaFormat premulFormat)
        : fSrcProfile(srcProfile)
        , fDstProfile(dstProfile)
        , fPremulFormat(premulFormat) {}

    bool apply(ColorFormat, void*, ColorFormat, const void*, int, SkAlphaType) const override;

private:
    skcms_ICCProfile  fSrcProfile;
    skcms_ICCProfile  fDstProfile;
    skcms_AlphaFormat fPremulFormat;
};

static skcms_PixelFormat get_skcms_format(SkColorSpaceXform::ColorFormat fmt) {
    switch (fmt) {
        case SkColorSpaceXform::kRGBA_8888_ColorFormat:
            return skcms_PixelFormat_RGBA_8888;
        case SkColorSpaceXform::kBGRA_8888_ColorFormat:
            return skcms_PixelFormat_BGRA_8888;
        case SkColorSpaceXform::kRGB_U16_BE_ColorFormat:
            return skcms_PixelFormat_RGB_161616;
        case SkColorSpaceXform::kRGBA_U16_BE_ColorFormat:
            return skcms_PixelFormat_RGBA_16161616;
        case SkColorSpaceXform::kRGBA_F16_ColorFormat:
            return skcms_PixelFormat_RGBA_hhhh;
        case SkColorSpaceXform::kRGBA_F32_ColorFormat:
            return skcms_PixelFormat_RGBA_ffff;
        case SkColorSpaceXform::kBGR_565_ColorFormat:
            return skcms_PixelFormat_BGR_565;
        default:
            SkDEBUGFAIL("Invalid ColorFormat");
            return skcms_PixelFormat_RGBA_8888;
    }
}

bool SkColorSpaceXform_skcms::apply(ColorFormat dstFormat, void* dst,
                                    ColorFormat srcFormat, const void* src,
                                    int count, SkAlphaType alphaType) const {
    skcms_AlphaFormat srcAlpha = skcms_AlphaFormat_Unpremul;
    skcms_AlphaFormat dstAlpha = kPremul_SkAlphaType == alphaType ? fPremulFormat
                                                                  : skcms_AlphaFormat_Unpremul;

    return skcms_Transform(src, get_skcms_format(srcFormat), srcAlpha, &fSrcProfile,
                           dst, get_skcms_format(dstFormat), dstAlpha, &fDstProfile, count);
}

void SkColorSpace::toProfile(skcms_ICCProfile* profile) const {
    if (auto blob = this->onProfileData()) {
        SkAssertResult(skcms_Parse(blob->data(), blob->size(), profile));
    } else {
        SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
        SkColorSpaceTransferFn tf;
        SkAssertResult(this->toXYZD50(&toXYZ) && this->isNumericalTransferFn(&tf));

        skcms_Matrix3x3 m = {{
            { toXYZ.get(0, 0), toXYZ.get(0, 1), toXYZ.get(0, 2) },
            { toXYZ.get(1, 0), toXYZ.get(1, 1), toXYZ.get(1, 2) },
            { toXYZ.get(2, 0), toXYZ.get(2, 1), toXYZ.get(2, 2) },
        }};

        skcms_Init(profile);
        skcms_SetTransferFunction(profile, (const skcms_TransferFunction*)&tf);
        skcms_SetXYZD50(profile, &m);
    }
}

std::unique_ptr<SkColorSpaceXform> SkMakeColorSpaceXform_skcms(SkColorSpace* src,
                                                               SkColorSpace* dst,
                                                               SkTransferFunctionBehavior premul) {
    // Construct skcms_ICCProfiles from each color space. For now, support A2B and XYZ.
    // Eventually, only need to support XYZ. Map premul to one of the two premul formats
    // in skcms.
    skcms_ICCProfile srcProfile, dstProfile;

    src->toProfile(&srcProfile);
    dst->toProfile(&dstProfile);

    if (!skcms_MakeUsableAsDestination(&dstProfile)) {
        return nullptr;
    }

    skcms_AlphaFormat premulFormat = SkTransferFunctionBehavior::kRespect == premul
            ? skcms_AlphaFormat_PremulLinear
            : skcms_AlphaFormat_PremulAsEncoded;
    return skstd::make_unique<SkColorSpaceXform_skcms>(srcProfile, dstProfile, premulFormat);
}

sk_sp<SkColorSpace> SkColorSpace::Make(const skcms_ICCProfile& profile) {
    if (!profile.has_toXYZD50 || !profile.has_trc) {
        return nullptr;
    }

    if (skcms_ApproximatelyEqualProfiles(&profile, skcms_sRGB_profile())) {
        return SkColorSpace::MakeSRGB();
    }

    SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
    toXYZD50.set3x3RowMajorf(&profile.toXYZD50.vals[0][0]);
    if (!toXYZD50.invert(nullptr)) {
        return nullptr;
    }

    const skcms_Curve* trc = profile.trc;
    if (trc[0].table_entries ||
        trc[1].table_entries ||
        trc[2].table_entries ||
        memcmp(&trc[0].parametric, &trc[1].parametric, sizeof(trc[0].parametric)) ||
        memcmp(&trc[0].parametric, &trc[2].parametric, sizeof(trc[0].parametric))) {
        return nullptr;
    }

    SkColorSpaceTransferFn skia_tf;
    memcpy(&skia_tf, &profile.trc[0].parametric, sizeof(skia_tf));

    return SkColorSpace::MakeRGB(skia_tf, toXYZD50);
}

bool skcms_can_parse(const void* buf, size_t len) {
    skcms_ICCProfile p;
    return skcms_Parse(buf, len, &p);
}
