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

#ifndef SkPM4fPriv_DEFINED
#define SkPM4fPriv_DEFINED

#include "SkColorData.h"
#include "SkColorSpace.h"
#include "SkArenaAlloc.h"
#include "SkPM4f.h"
#include "SkRasterPipeline.h"
#include "SkSRGB.h"
#include "../jumper/SkJumper.h"

static inline Sk4f set_alpha(const Sk4f& px, float alpha) {
    return { px[0], px[1], px[2], alpha };
}

static inline float get_alpha(const Sk4f& px) {
    return px[3];
}


static inline Sk4f Sk4f_fromL32(uint32_t px) {
    return SkNx_cast<float>(Sk4b::Load(&px)) * (1/255.0f);
}

static inline Sk4f Sk4f_fromS32(uint32_t px) {
    return { sk_linear_from_srgb[(px >>  0) & 0xff],
             sk_linear_from_srgb[(px >>  8) & 0xff],
             sk_linear_from_srgb[(px >> 16) & 0xff],
                    (1/255.0f) * (px >> 24)          };
}

static inline uint32_t Sk4f_toL32(const Sk4f& px) {
    uint32_t l32;
    SkNx_cast<uint8_t>(Sk4f_round(px * 255.0f)).store(&l32);
    return l32;
}

static inline uint32_t Sk4f_toS32(const Sk4f& px) {
    Sk4i  rgb = sk_linear_to_srgb(px),
         srgb = { rgb[0], rgb[1], rgb[2], (int)(255.0f * px[3] + 0.5f) };

    uint32_t s32;
    SkNx_cast<uint8_t>(srgb).store(&s32);
    return s32;
}


// SkColor handling:
//   SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swizzles r and b to
// produce the needed (r, g, b, a) ordering.
static inline Sk4f Sk4f_from_SkColor(SkColor color) {
    return swizzle_rb(Sk4f_fromS32(color));
}

static inline void assert_unit(float x) {
    SkASSERT(0 <= x && x <= 1);
}

static inline float exact_srgb_to_linear(float srgb) {
    assert_unit(srgb);
    float linear;
    if (srgb <= 0.04045) {
        linear = srgb / 12.92f;
    } else {
        linear = powf((srgb + 0.055f) / 1.055f, 2.4f);
    }
    assert_unit(linear);
    return linear;
}

static inline void analyze_3x4_matrix(const float matrix[12],
                                      bool* can_underflow, bool* can_overflow) {
    // | 0 3 6  9 |   |r|   |x|
    // | 1 4 7 10 | x |g| = |y|
    // | 2 5 8 11 |   |b|   |z|
    //                |1|
    // We'll find min/max bounds on each of x,y,z assuming r,g,b are all in [0,1].
    // If any can be <0, we'll set can_underflow; if any can be >1, can_overflow.
    bool underflow = false,
          overflow = false;
    for (int i = 0; i < 3; i++) {
        SkScalar min = matrix[i+9],
                 max = matrix[i+9];
        (matrix[i+0] < 0 ? min : max) += matrix[i+0];
        (matrix[i+3] < 0 ? min : max) += matrix[i+3];
        (matrix[i+6] < 0 ? min : max) += matrix[i+6];
        underflow = underflow || min < 0;
        overflow  =  overflow || max > 1;
    }
    *can_underflow = underflow;
    *can_overflow  =  overflow;
}

// N.B. scratch_matrix_3x4 must live at least as long as p.
// Returns false if no gamut tranformation was necessary.
static inline bool append_gamut_transform_noclamp(SkRasterPipeline* p,
                                                  float scratch_matrix_3x4[12],
                                                  SkColorSpace* src,
                                                  SkColorSpace* dst) {
    if (src == dst || !dst || !src) {
        return false;
    }

    const SkMatrix44 *fromSrc = src->  toXYZD50(),
                       *toDst = dst->fromXYZD50();
    if (!fromSrc || !toDst) {
        SkDEBUGFAIL("We can't handle non-XYZ color spaces in append_gamut_transform().");
        return false;
    }

    // Slightly more sophisticated version of if (src == dst)
    if (src->toXYZD50Hash() == dst->toXYZD50Hash()) {
        return false;
    }

    // Convert from 4x4 to (column-major) 3x4.
    SkMatrix44 m44(*toDst, *fromSrc);
    auto ptr = scratch_matrix_3x4;
    *ptr++ = m44.get(0,0); *ptr++ = m44.get(1,0); *ptr++ = m44.get(2,0);
    *ptr++ = m44.get(0,1); *ptr++ = m44.get(1,1); *ptr++ = m44.get(2,1);
    *ptr++ = m44.get(0,2); *ptr++ = m44.get(1,2); *ptr++ = m44.get(2,2);
    *ptr++ = m44.get(0,3); *ptr++ = m44.get(1,3); *ptr++ = m44.get(2,3);

    p->append(SkRasterPipeline::matrix_3x4, scratch_matrix_3x4);
    return true;
}


// N.B. scratch_matrix_3x4 must live at least as long as p.
static inline void append_gamut_transform(SkRasterPipeline* p,
                                          float scratch_matrix_3x4[12],
                                          SkColorSpace* src,
                                          SkColorSpace* dst,
                                          SkAlphaType alphaType) {
    if (append_gamut_transform_noclamp(p, scratch_matrix_3x4, src, dst)) {
        bool needs_clamp_0, needs_clamp_1;
        analyze_3x4_matrix(scratch_matrix_3x4, &needs_clamp_0, &needs_clamp_1);

        if (needs_clamp_0) { p->append(SkRasterPipeline::clamp_0); }
        if (needs_clamp_1) {
            (kPremul_SkAlphaType == alphaType) ? p->append(SkRasterPipeline::clamp_a)
                                               : p->append(SkRasterPipeline::clamp_1);
        }
    }
}

static inline void append_gamut_transform(SkRasterPipeline* p,
                                          SkArenaAlloc* alloc,
                                          SkColorSpace* src,
                                          SkColorSpace* dst,
                                          SkAlphaType alphaType) {
    append_gamut_transform(p, alloc->makeArrayDefault<float>(12), src, dst, alphaType);
}

static inline SkColor4f to_colorspace(const SkColor4f& c, SkColorSpace* src, SkColorSpace* dst) {
    SkColor4f color4f = c;
    if (src && dst && !SkColorSpace::Equals(src, dst)) {
        SkJumper_MemoryCtx color4f_ptr = { &color4f, 0 };

        float scratch_matrix_3x4[12];

        SkSTArenaAlloc<256> alloc;
        SkRasterPipeline p(&alloc);
        p.append_constant_color(&alloc, color4f);
        append_gamut_transform(&p, scratch_matrix_3x4, src, dst, kUnpremul_SkAlphaType);
        p.append(SkRasterPipeline::store_f32, &color4f_ptr);

        p.run(0,0,1,1);
    }
    return color4f;
}

static inline SkColor4f SkColor4f_from_SkColor(SkColor color, SkColorSpace* dst) {
    SkColor4f color4f;
    if (dst) {
        // sRGB gamma, sRGB gamut.
        color4f = to_colorspace(SkColor4f::FromColor(color),
                                SkColorSpace::MakeSRGB().get(), dst);
    } else {
        // Linear gamma, dst gamut.
        swizzle_rb(SkNx_cast<float>(Sk4b::Load(&color)) * (1/255.0f)).store(&color4f);
    }
    return color4f;
}

static inline SkPM4f SkPM4f_from_SkColor(SkColor color, SkColorSpace* dst) {
    return SkColor4f_from_SkColor(color, dst).premul();
}

#endif
