/*
 * 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 "SkColorPriv.h"
#include "SkColorSpace.h"
#include "SkColorSpace_Base.h"
#include "SkArenaAlloc.h"
#include "SkPM4f.h"
#include "SkRasterPipeline.h"
#include "SkSRGB.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.
static inline bool append_gamut_transform(SkRasterPipeline* p, float scratch_matrix_3x4[12],
                                          SkColorSpace* src, SkColorSpace* dst) {
    if (src == dst) { return true; }
    if (!dst)       { return true; }   // Legacy modes intentionally ignore color gamut.
    if (!src)       { return true; }   // A null src color space means linear gamma, dst gamut.

    auto toXYZ = as_CSB(src)->  toXYZD50(),
       fromXYZ = as_CSB(dst)->fromXYZD50();
    if (!toXYZ || !fromXYZ) { return false; }  // Unsupported color space type.

    if (as_CSB(src)->toXYZD50Hash() == as_CSB(dst)->toXYZD50Hash()) { return true; }

    SkMatrix44 m44(*fromXYZ, *toXYZ);

    // Convert from 4x4 to (column-major) 3x4.
    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);

    bool needs_clamp_0, needs_clamp_a;
    analyze_3x4_matrix(scratch_matrix_3x4, &needs_clamp_0, &needs_clamp_a);

    p->append(SkRasterPipeline::matrix_3x4, scratch_matrix_3x4);
    if (needs_clamp_0) { p->append(SkRasterPipeline::clamp_0); }
    if (needs_clamp_a) { p->append(SkRasterPipeline::clamp_a); }
    return true;
}

static inline bool append_gamut_transform(SkRasterPipeline* p, SkArenaAlloc* scratch,
                                          SkColorSpace* src, SkColorSpace* dst) {
    struct matrix_3x4 { float arr[12]; };
    return append_gamut_transform(p, scratch->make<matrix_3x4>()->arr, src, dst);
}

static inline SkColor4f SkColor4f_from_SkColor(SkColor color, SkColorSpace* dst) {
    SkColor4f color4f;
    if (dst) {
        // sRGB gamma, sRGB gamut.
        color4f = SkColor4f::FromColor(color);
        void* color4f_ptr = &color4f;

        float scratch_matrix_3x4[12];

        SkRasterPipeline p;
        p.append(SkRasterPipeline::constant_color, color4f_ptr);
        append_gamut_transform(&p, scratch_matrix_3x4,
                               SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named).get(), dst);
        p.append(SkRasterPipeline::store_f32, &color4f_ptr);

        p.run(0,0,1);
    } 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
