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

#include "SkImageInfo.h"
#include "../private/SkImageInfoPriv.h"

struct SkEncodedInfo {
public:

    enum Alpha {
        kOpaque_Alpha,
        kUnpremul_Alpha,

        // Each pixel is either fully opaque or fully transparent.
        // There is no difference between requesting kPremul or kUnpremul.
        kBinary_Alpha,

        // Allows us to have a default constructor.  Should be treated as
        // invalid.
        kUnknown_Alpha,
    };

    /*
     * We strive to make the number of components per pixel obvious through
     * our naming conventions.
     * Ex: kRGB has 3 components.  kRGBA has 4 components.
     *
     * This sometimes results in redundant Alpha and Color information.
     * Ex: kRGB images must also be kOpaque.
     */
    enum Color {
        // PNG, WBMP
        kGray_Color,

        // PNG
        kGrayAlpha_Color,

        // PNG, GIF, BMP
        kPalette_Color,

        // PNG, RAW
        kRGB_Color,
        kRGBA_Color,

        // BMP
        kBGR_Color,
        kBGRX_Color,
        kBGRA_Color,

        // JPEG, WEBP
        kYUV_Color,

        // WEBP
        kYUVA_Color,

        // JPEG
        // Photoshop actually writes inverted CMYK data into JPEGs, where zero
        // represents 100% ink coverage.  For this reason, we treat CMYK JPEGs
        // as having inverted CMYK.  libjpeg-turbo warns that this may break
        // other applications, but the CMYK JPEGs we see on the web expect to
        // be treated as inverted CMYK.
        kInvertedCMYK_Color,
        kYCCK_Color,

        // Used internally to indicate that the decoding library has
        // pre-swizzled to the desired output format.
        kPreSwizzled_Color,

        // Allows us to have a default constructor.  Should be treated as
        // invalid.
        kUnknown_Color,
    };

    static SkEncodedInfo Make(Color color, Alpha alpha, int bitsPerComponent) {
        SkASSERT(1 == bitsPerComponent ||
                 2 == bitsPerComponent ||
                 4 == bitsPerComponent ||
                 8 == bitsPerComponent ||
                 16 == bitsPerComponent);

        switch (color) {
            case kGray_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                break;
            case kGrayAlpha_Color:
                SkASSERT(kOpaque_Alpha != alpha);
                break;
            case kPalette_Color:
                SkASSERT(16 != bitsPerComponent);
                break;
            case kRGB_Color:
            case kBGR_Color:
            case kBGRX_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                SkASSERT(bitsPerComponent >= 8);
                break;
            case kYUV_Color:
            case kInvertedCMYK_Color:
            case kYCCK_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                SkASSERT(8 == bitsPerComponent);
                break;
            case kRGBA_Color:
                SkASSERT(kOpaque_Alpha != alpha);
                SkASSERT(bitsPerComponent >= 8);
                break;
            case kBGRA_Color:
            case kYUVA_Color:
                SkASSERT(kOpaque_Alpha != alpha);
                SkASSERT(8 == bitsPerComponent);
                break;
            default:
                SkASSERT(false);
                break;
        }

        return SkEncodedInfo(color, alpha, bitsPerComponent);
    }

    /*
     * Returns an SkImageInfo with Skia color and alpha types that are the
     * closest possible match to the encoded info.
     */
    SkImageInfo makeImageInfo(int width, int height) const {
        SkColorProfileType profileType = SkDefaultColorProfile();
        switch (fColor) {
            case kGray_Color:
                SkASSERT(kOpaque_Alpha == fAlpha);
                return SkImageInfo::Make(width, height, kGray_8_SkColorType,
                                         kOpaque_SkAlphaType, profileType);
            case kGrayAlpha_Color:
                SkASSERT(kOpaque_Alpha != fAlpha);
                return SkImageInfo::Make(width, height, kN32_SkColorType,
                        kUnpremul_SkAlphaType, profileType);
            case kPalette_Color: {
                SkAlphaType alphaType = (kOpaque_Alpha == fAlpha) ? kOpaque_SkAlphaType :
                        kUnpremul_SkAlphaType;
                return SkImageInfo::Make(width, height, kIndex_8_SkColorType,
                                         alphaType, profileType);
            }
            case kRGB_Color:
            case kBGR_Color:
            case kBGRX_Color:
            case kYUV_Color:
            case kInvertedCMYK_Color:
            case kYCCK_Color:
                SkASSERT(kOpaque_Alpha == fAlpha);
                return SkImageInfo::Make(width, height, kN32_SkColorType,
                                         kOpaque_SkAlphaType, profileType);
            case kRGBA_Color:
            case kBGRA_Color:
            case kYUVA_Color:
                SkASSERT(kOpaque_Alpha != fAlpha);
                return SkImageInfo::Make(width, height, kN32_SkColorType,
                                         kUnpremul_SkAlphaType, profileType);
            default:
                SkASSERT(false);
                return SkImageInfo::MakeUnknown();
        }
    }

    Color color() const { return fColor; }
    Alpha alpha() const { return fAlpha; }
    uint8_t bitsPerComponent() const { return fBitsPerComponent; }

    uint8_t bitsPerPixel() const {
        switch (fColor) {
            case kGray_Color:
                return fBitsPerComponent;
            case kGrayAlpha_Color:
                return 2 * fBitsPerComponent;
            case kPalette_Color:
                return fBitsPerComponent;
            case kRGB_Color:
            case kBGR_Color:
            case kYUV_Color:
                return 3 * fBitsPerComponent;
            case kRGBA_Color:
            case kBGRA_Color:
            case kBGRX_Color:
            case kYUVA_Color:
            case kInvertedCMYK_Color:
            case kYCCK_Color:
                return 4 * fBitsPerComponent;
            default:
                SkASSERT(false);
                return 0;
        }
    }

    SkEncodedInfo()
        : fColor(kUnknown_Color)
        , fAlpha(kUnknown_Alpha)
        , fBitsPerComponent(0)
    {}

private:

    SkEncodedInfo(Color color, Alpha alpha, uint8_t bitsPerComponent)
        : fColor(color)
        , fAlpha(alpha)
        , fBitsPerComponent(bitsPerComponent)
    {}

    void setColor(Color color) {
        fColor = color;
    }

    Color   fColor;
    Alpha   fAlpha;
    uint8_t fBitsPerComponent;

    friend class SkJpegCodec;
};

#endif
