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

#include "SkColorSpace_XYZ.h"
#include "SkColorSpacePriv.h"
#include "SkColorSpaceXform_Base.h"
#include "SkOpts.h"

SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50)
    : INHERITED(nullptr)
    , fGammaNamed(gammaNamed)
    , fGammas(nullptr)
    , fToXYZD50(toXYZD50)
    , fToXYZD50Hash(SkOpts::hash_fn(toXYZD50.values(), 16 * sizeof(SkMScalar), 0))
    , fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
{}

SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, sk_sp<SkGammas> gammas,
                                   const SkMatrix44& toXYZD50, sk_sp<SkData> profileData)
    : INHERITED(std::move(profileData))
    , fGammaNamed(gammaNamed)
    , fGammas(std::move(gammas))
    , fToXYZD50(toXYZD50)
    , fToXYZD50Hash(SkOpts::hash_fn(toXYZD50.values(), 16 * sizeof(SkMScalar), 0))
    , fFromXYZD50(SkMatrix44::kUninitialized_Constructor) {
    SkASSERT(!fGammas || 3 == fGammas->channels());
    if (fGammas) {
        for (int i = 0; i < fGammas->channels(); ++i) {
            if (SkGammas::Type::kTable_Type == fGammas->type(i)) {
                SkASSERT(fGammas->data(i).fTable.fSize >= 2);
            }
        }
    }
}

const SkMatrix44* SkColorSpace_XYZ::fromXYZD50() const {
    fFromXYZOnce([this] {
        if (!fToXYZD50.invert(&fFromXYZD50)) {
            // If a client gives us a dst gamut with a transform that we can't invert, we will
            // simply give them back a transform to sRGB gamut.
            SkDEBUGFAIL("Non-invertible XYZ matrix, defaulting to sRGB");
            SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
            srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
            srgbToxyzD50.invert(&fFromXYZD50);
        }
    });
    return &fFromXYZD50;
}

bool SkColorSpace_XYZ::onGammaCloseToSRGB() const {
    return kSRGB_SkGammaNamed == fGammaNamed || k2Dot2Curve_SkGammaNamed == fGammaNamed;
}

bool SkColorSpace_XYZ::onGammaIsLinear() const {
    return kLinear_SkGammaNamed == fGammaNamed;
}

bool SkColorSpace_XYZ::onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const {
    if (named_to_parametric(coeffs, fGammaNamed)) {
        return true;
    }

    SkASSERT(fGammas);
    if (fGammas->data(0) != fGammas->data(1) || fGammas->data(0) != fGammas->data(2)) {
        return false;
    }

    if (fGammas->isValue(0)) {
        value_to_parametric(coeffs, fGammas->data(0).fValue);
        return true;
    }

    if (fGammas->isParametric(0)) {
        *coeffs = fGammas->params(0);
        return true;
    }

    return false;
}

sk_sp<SkColorSpace> SkColorSpace_XYZ::makeLinearGamma() const {
    if (this->gammaIsLinear()) {
        return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
    }
    return SkColorSpace_Base::MakeRGB(kLinear_SkGammaNamed, fToXYZD50);
}

sk_sp<SkColorSpace> SkColorSpace_XYZ::makeSRGBGamma() const {
    if (this->gammaCloseToSRGB()) {
        return sk_ref_sp(const_cast<SkColorSpace_XYZ*>(this));
    }
    return SkColorSpace_Base::MakeRGB(kSRGB_SkGammaNamed, fToXYZD50);
}

void SkColorSpace_XYZ::toDstGammaTables(const uint8_t* tables[3], sk_sp<SkData>* storage,
                                         int numTables) const {
    fToDstGammaOnce([this, numTables] {
        const bool gammasAreMatching = numTables <= 1;
        fDstStorage =
                SkData::MakeUninitialized(numTables * SkColorSpaceXform_Base::kDstGammaTableSize);
        SkColorSpaceXform_Base::BuildDstGammaTables(fToDstGammaTables,
                                                    (uint8_t*) fDstStorage->writable_data(), this,
                                                    gammasAreMatching);
    });

    *storage = fDstStorage;
    tables[0] = fToDstGammaTables[0];
    tables[1] = fToDstGammaTables[1];
    tables[2] = fToDstGammaTables[2];
}
