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


#ifndef SkKTXFile_DEFINED
#define SkKTXFile_DEFINED

#include "SkData.h"
#include "SkTextureCompressor.h"
#include "SkTypes.h"
#include "SkTDArray.h"
#include "SkString.h"
#include "SkRefCnt.h"

class SkBitmap;
class SkStreamRewindable;
class SkWStream;

// KTX Image File
// ---
// KTX is a general texture data storage file format ratified by the Khronos Group. As an
// overview, a KTX file contains all of the appropriate values needed to fully specify a
// texture in an OpenGL application, including the use of compressed data.
//
// A full format specification can be found here:
// http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/

class SkKTXFile {
public:
    // The ownership of the data remains with the caller. This class is intended
    // to be used as a logical wrapper around the data in order to properly
    // access the pixels.
    SkKTXFile(SkData* data)
        : fData(data), fSwapBytes(false)
    {
        data->ref();
        fValid = this->readKTXFile(fData->bytes(), fData->size());
    }

    bool valid() const { return fValid; }

    int width() const { return static_cast<int>(fHeader.fPixelWidth); }
    int height() const { return static_cast<int>(fHeader.fPixelHeight); }

    const uint8_t *pixelData(int mipmap = 0) const {
        SkASSERT(!this->valid() || mipmap < fPixelData.count());
        return this->valid() ? fPixelData[mipmap].data() : NULL;
    }

    // If the decoded KTX file has the following key, then it will
    // return the associated value. If not found, the empty string
    // is returned.
    SkString getValueForKey(const SkString& key) const;

    int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); }

    bool isCompressedFormat(SkTextureCompressor::Format fmt) const;
    bool isRGBA8() const;
    bool isRGB8() const;

    static bool is_ktx(const uint8_t *data);
    static bool is_ktx(SkStreamRewindable* stream);

    static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data,
                               uint32_t width, uint32_t height);
    static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap);
private:

    // The blob holding the file data.
    SkAutoTUnref<SkData> fData;

    // This header captures all of the data that describes the format
    // of the image data in a KTX file.
    struct Header {
        uint32_t fGLType;
        uint32_t fGLTypeSize;
        uint32_t fGLFormat;
        uint32_t fGLInternalFormat;
        uint32_t fGLBaseInternalFormat;
        uint32_t fPixelWidth;
        uint32_t fPixelHeight;
        uint32_t fPixelDepth;
        uint32_t fNumberOfArrayElements;
        uint32_t fNumberOfFaces;
        uint32_t fNumberOfMipmapLevels;
        uint32_t fBytesOfKeyValueData;

        Header() { memset(this, 0, sizeof(*this)); }
    } fHeader;

    // A Key Value pair stored in the KTX file. There may be
    // arbitrarily many of these.
    class KeyValue {
    public:
        KeyValue(size_t size) : fDataSz(size) { }
        bool readKeyAndValue(const uint8_t *data);
        size_t size() const { return fDataSz; }
        const SkString& key() const { return fKey; }
        const SkString& value() const { return fValue; }
        bool writeKeyAndValueForKTX(SkWStream* strm);
    private:
        const size_t fDataSz;
        SkString     fKey;
        SkString     fValue;
    };

    static KeyValue CreateKeyValue(const char *key, const char *value);

    // The pixel data for a single mipmap level in an image. Based on how
    // the rest of the data is stored, this may be compressed, a cubemap, etc.
    // The header will describe the format of this data.
    class PixelData {
    public:
        PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { }
        const uint8_t *data() const { return fDataPtr; }
        size_t dataSize() const { return fDataSz; }
    private:
        const size_t fDataSz;
        const uint8_t *fDataPtr;
    };

    // This function is only called once from the constructor. It loads the data
    // and populates the appropriate fields of this class
    // (fKeyValuePairs, fPixelData, fSwapBytes)
    bool readKTXFile(const uint8_t *data, size_t dataLen);

    SkTArray<KeyValue> fKeyValuePairs;
    SkTDArray<PixelData> fPixelData;
    bool fValid;

    // If the endianness of the platform is different than the file,
    // then we need to do proper byte swapping.
    bool fSwapBytes;

    // Read an integer from a buffer, advance the buffer, and swap
    // bytes if fSwapBytes is set
    uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const;
};

#endif  // SkKTXFile_DEFINED
