/*
 * 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 SkColorSpace_Base_DEFINED
#define SkColorSpace_Base_DEFINED

#include "SkColorLookUpTable.h"
#include "SkColorSpace.h"
#include "SkData.h"
#include "SkOnce.h"
#include "SkTemplates.h"

enum SkGammaNamed : uint8_t {
    kLinear_SkGammaNamed,
    kSRGB_SkGammaNamed,
    k2Dot2Curve_SkGammaNamed,
    kNonStandard_SkGammaNamed,
};

struct SkGammas : SkRefCnt {

    // There are four possible representations for gamma curves.  kNone_Type is used
    // as a placeholder until the struct is initialized.  It is not a valid value.
    enum class Type : uint8_t {
        kNone_Type,
        kNamed_Type,
        kValue_Type,
        kTable_Type,
        kParam_Type,
    };

    // Contains information for a gamma table.
    struct Table {
        size_t fOffset;
        int    fSize;

        const float* table(const SkGammas* base) const {
            return SkTAddOffset<const float>(base, sizeof(SkGammas) + fOffset);
        }
    };

    // Contains the actual gamma curve information.  Should be interpreted
    // based on the type of the gamma curve.
    union Data {
        Data()
            : fTable{ 0, 0 }
        {}

        inline bool operator==(const Data& that) const {
            return this->fTable.fOffset == that.fTable.fOffset &&
                   this->fTable.fSize == that.fTable.fSize;
        }

        SkGammaNamed             fNamed;
        float                    fValue;
        Table                    fTable;
        size_t                   fParamOffset;

        const SkColorSpaceTransferFn& params(const SkGammas* base) const {
            return *SkTAddOffset<const SkColorSpaceTransferFn>(
                    base, sizeof(SkGammas) + fParamOffset);
        }
    };

    bool isNamed(int i) const {
        return Type::kNamed_Type == this->type(i);
    }

    bool isValue(int i) const {
        return Type::kValue_Type == this->type(i);
    }

    bool isTable(int i) const {
        return Type::kTable_Type == this->type(i);
    }

    bool isParametric(int i) const {
        return Type::kParam_Type == this->type(i);
    }

    const Data& data(int i) const {
        switch (i) {
            case 0:
                return fRedData;
            case 1:
                return fGreenData;
            case 2:
                return fBlueData;
            default:
                SkASSERT(false);
                return fRedData;
        }
    }

    const float* table(int i) const {
        SkASSERT(isTable(i));
        return this->data(i).fTable.table(this);
    }

    const SkColorSpaceTransferFn& params(int i) const {
        SkASSERT(isParametric(i));
        return this->data(i).params(this);
    }

    Type type(int i) const {
        switch (i) {
            case 0:
                return fRedType;
            case 1:
                return fGreenType;
            case 2:
                return fBlueType;
            default:
                SkASSERT(false);
                return fRedType;
        }
    }

    SkGammas()
        : fRedType(Type::kNone_Type)
        , fGreenType(Type::kNone_Type)
        , fBlueType(Type::kNone_Type)
    {}

    // These fields should only be modified when initializing the struct.
    Data fRedData;
    Data fGreenData;
    Data fBlueData;
    Type fRedType;
    Type fGreenType;
    Type fBlueType;

    // Objects of this type are sometimes created in a custom fashion using
    // sk_malloc_throw and therefore must be sk_freed.  We overload new to
    // also call sk_malloc_throw so that memory can be unconditionally released
    // using sk_free in an overloaded delete. Overloading regular new means we
    // must also overload placement new.
    void* operator new(size_t size) { return sk_malloc_throw(size); }
    void* operator new(size_t, void* p) { return p; }
    void operator delete(void* p) { sk_free(p); }
};

class SkColorSpace_Base : public SkColorSpace {
public:

    /**
     *  Describes color space gamut as a transformation to XYZ D50.
     *  Returns nullptr if color gamut cannot be described in terms of XYZ D50.
     */
    virtual const SkMatrix44* toXYZD50() const = 0;

    /**
     *  Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking
     *  of gamuts, at the (very small) risk of collision.
     *  Returns 0 if color gamut cannot be described in terms of XYZ D50.
     */
    virtual uint32_t toXYZD50Hash() const = 0;

    /**
     *  Describes color space gamut as a transformation from XYZ D50
     *  Returns nullptr if color gamut cannot be described in terms of XYZ D50.
     */
    virtual const SkMatrix44* fromXYZD50() const = 0;
    
    virtual bool onGammaCloseToSRGB() const = 0;
    
    virtual bool onGammaIsLinear() const = 0;
    
    /**
     *  Returns a color space with the same gamut as this one, but with a linear gamma.
     *  For color spaces whose gamut can not be described in terms of XYZ D50, returns
     *  linear sRGB.
     */
    virtual sk_sp<SkColorSpace> makeLinearGamma() = 0;

    /**
     *  Returns a color space with the same gamut as this one, with with the sRGB transfer
     *  function. For color spaces whose gamut can not be described in terms of XYZ D50, returns
     *  sRGB.
     */
    virtual sk_sp<SkColorSpace> makeSRGBGamma() = 0;

    enum class Type : uint8_t {
        kXYZ,
        kA2B
    };
    
    virtual Type type() const = 0;
    
protected:
    SkColorSpace_Base(sk_sp<SkData> profileData);

private:

    /**
     *  FIXME (msarett):
     *  Hiding this function until we can determine if we need it.  Known issues include:
     *  Only writes 3x3 matrices
     *  Only writes float gammas
     *  Rejected by some parsers because the "profile description" is empty
     */
    sk_sp<SkData> writeToICC() const;

    static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);

    SkColorSpace_Base(SkGammaNamed gammaNamed, const SkMatrix44& toXYZ);

    sk_sp<SkData> fProfileData;

    friend class SkColorSpace;
    friend class SkColorSpace_XYZ;
    friend class ColorSpaceXformTest;
    friend class ColorSpaceTest;
    typedef SkColorSpace INHERITED;
};

static inline SkColorSpace_Base* as_CSB(SkColorSpace* colorSpace) {
    return static_cast<SkColorSpace_Base*>(colorSpace);
}

static inline const SkColorSpace_Base* as_CSB(const SkColorSpace* colorSpace) {
    return static_cast<const SkColorSpace_Base*>(colorSpace);
}

static inline SkColorSpace_Base* as_CSB(const sk_sp<SkColorSpace>& colorSpace) {
    return static_cast<SkColorSpace_Base*>(colorSpace.get());
}

#endif
