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

#include "SkCodec_libgif.h"
#include "SkCodecPriv.h"
#include "SkColorPriv.h"
#include "SkColorTable.h"
#include "SkStream.h"
#include "SkSwizzler.h"
#include "SkUtils.h"

/*
 * Checks the start of the stream to see if the image is a gif
 */
bool SkGifCodec::IsGif(SkStream* stream) {
    char buf[GIF_STAMP_LEN];
    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
            memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
            memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0)
        {
            return true;
        }
    }
    return false;
}

/*
 * Warning reporting function
 */
static void gif_warning(const char* msg) {
    SkCodecPrintf("Gif Warning: %s\n", msg);
}

/*
 * Error function
 */
static SkCodec::Result gif_error(const char* msg, SkCodec::Result result = SkCodec::kInvalidInput) {
    SkCodecPrintf("Gif Error: %s\n", msg);
    return result;
}


/*
 * Read function that will be passed to gif_lib
 */
static int32_t read_bytes_callback(GifFileType* fileType, GifByteType* out, int32_t size) {
    SkStream* stream = (SkStream*) fileType->UserData;
    return (int32_t) stream->read(out, size);
}

/*
 * Open the gif file
 */
static GifFileType* open_gif(SkStream* stream) {
    return DGifOpen(stream, read_bytes_callback, nullptr);
}

/*
 * Check if a there is an index of the color table for a transparent pixel
 */
static uint32_t find_trans_index(const SavedImage& image) {
    // If there is a transparent index specified, it will be contained in an
    // extension block.  We will loop through extension blocks in reverse order
    // to check the most recent extension blocks first.
    for (int32_t i = image.ExtensionBlockCount - 1; i >= 0; i--) {
        // Get an extension block
        const ExtensionBlock& extBlock = image.ExtensionBlocks[i];

        // Specifically, we need to check for a graphics control extension,
        // which may contain transparency information.  Also, note that a valid
        // graphics control extension is always four bytes.  The fourth byte
        // is the transparent index (if it exists), so we need at least four
        // bytes.
        if (GRAPHICS_EXT_FUNC_CODE == extBlock.Function && extBlock.ByteCount >= 4) {
            // Check the transparent color flag which indicates whether a
            // transparent index exists.  It is the least significant bit of
            // the first byte of the extension block.
            if (1 == (extBlock.Bytes[0] & 1)) {
                // Use uint32_t to prevent sign extending
                return extBlock.Bytes[3];
            }

            // There should only be one graphics control extension for the image frame
            break;
        }
    }

    // Use maximum unsigned int (surely an invalid index) to indicate that a valid
    // index was not found.
    return SK_MaxU32;
}

inline uint32_t ceil_div(uint32_t a, uint32_t b) {
    return (a + b - 1) / b;
}

/*
 * Gets the output row corresponding to the encoded row for interlaced gifs
 */
inline uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) {
    SkASSERT(encodedRow < height);
    // First pass
    if (encodedRow * 8 < height) {
        return encodedRow * 8;
    }
    // Second pass
    if (encodedRow * 4 < height) {
        return 4 + 8 * (encodedRow - ceil_div(height, 8));
    }
    // Third pass
    if (encodedRow * 2 < height) {
        return 2 + 4 * (encodedRow - ceil_div(height, 4));
    }
    // Fourth pass
    return 1 + 2 * (encodedRow - ceil_div(height, 2));
}

/*
 * This function cleans up the gif object after the decode completes
 * It is used in a SkAutoTCallIProc template
 */
void SkGifCodec::CloseGif(GifFileType* gif) {
    DGifCloseFile(gif, NULL);
}

/*
 * This function free extension data that has been saved to assist the image
 * decoder
 */
void SkGifCodec::FreeExtension(SavedImage* image) {
    if (NULL != image->ExtensionBlocks) {
        GifFreeExtensions(&image->ExtensionBlockCount, &image->ExtensionBlocks);
    }
}

/*
 * Read enough of the stream to initialize the SkGifCodec.
 * Returns a bool representing success or failure.
 *
 * @param codecOut
 * If it returned true, and codecOut was not nullptr,
 * codecOut will be set to a new SkGifCodec.
 *
 * @param gifOut
 * If it returned true, and codecOut was nullptr,
 * gifOut must be non-nullptr and gifOut will be set to a new
 * GifFileType pointer.
 *
 * @param stream
 * Deleted on failure.
 * codecOut will take ownership of it in the case where we created a codec.
 * Ownership is unchanged when we returned a gifOut.
 *
 */
bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) {
    SkAutoTDelete<SkStream> streamDeleter(stream);

    // Read gif header, logical screen descriptor, and global color table
    SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream));

    if (nullptr == gif) {
        gif_error("DGifOpen failed.\n");
        return false;
    }

    // Read through gif extensions to get to the image data.  Set the
    // transparent index based on the extension data.
    uint32_t transIndex;
    SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex);
    if (kSuccess != result){
        return false;
    }

    // Read the image descriptor
    if (GIF_ERROR == DGifGetImageDesc(gif)) {
        return false;
    }
    // If reading the image descriptor is successful, the image count will be
    // incremented.
    SkASSERT(gif->ImageCount >= 1);

    if (nullptr != codecOut) {
        SkISize size;
        SkIRect frameRect;
        if (!GetDimensions(gif, &size, &frameRect)) {
            gif_error("Invalid gif size.\n");
        }
        bool frameIsSubset = (size != frameRect.size());

        // Determine the recommended alpha type.  The transIndex might be valid if it less
        // than 256.  We are not certain that the index is valid until we process the color
        // table, since some gifs have color tables with less than 256 colors.  If
        // there might be a valid transparent index, we must indicate that the image has
        // alpha.
        // In the case where we must support alpha, we have the option to set the
        // suggested alpha type to kPremul or kUnpremul.  Both are valid since the alpha
        // component will always be 0xFF or the entire 32-bit pixel will be set to zero.
        // We prefer kPremul because we support kPremul, and it is more efficient to use
        // kPremul directly even when kUnpremul is supported.
        SkAlphaType alphaType = (transIndex < 256) ? kPremul_SkAlphaType : kOpaque_SkAlphaType;

        // Return the codec
        // kIndex is the most natural color type for gifs, so we set this as
        // the default.
        SkImageInfo imageInfo = SkImageInfo::Make(size.width(), size.height(), kIndex_8_SkColorType,
                alphaType);
        *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach(), transIndex,
                frameRect, frameIsSubset);
    } else {
        SkASSERT(nullptr != gifOut);
        streamDeleter.detach();
        *gifOut = gif.detach();
    }
    return true;
}

/*
 * Assumes IsGif was called and returned true
 * Creates a gif decoder
 * Reads enough of the stream to determine the image format
 */
SkCodec* SkGifCodec::NewFromStream(SkStream* stream) {
    SkCodec* codec = nullptr;
    if (ReadHeader(stream, &codec, nullptr)) {
        return codec;
    }
    return nullptr;
}

SkGifCodec::SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif,
        uint32_t transIndex, const SkIRect& frameRect, bool frameIsSubset)
    : INHERITED(srcInfo, stream)
    , fGif(gif)
    , fSrcBuffer(new uint8_t[this->getInfo().width()])
    // If it is valid, fTransIndex will be used to set fFillIndex.  We don't know if
    // fTransIndex is valid until we process the color table, since fTransIndex may
    // be greater than the size of the color table.
    , fTransIndex(transIndex)
    // Default fFillIndex is 0.  We will overwrite this if fTransIndex is valid, or if
    // there is a valid background color.
    , fFillIndex(0)
    , fFrameRect(frameRect)
    , fFrameIsSubset(frameIsSubset)
    , fColorTable(NULL)
    , fSwizzler(NULL)
{}

bool SkGifCodec::onRewind() {
    GifFileType* gifOut = nullptr;
    if (!ReadHeader(this->stream(), nullptr, &gifOut)) {
        return false;
    }

    SkASSERT(nullptr != gifOut);
    fGif.reset(gifOut);
    return true;
}

SkCodec::Result SkGifCodec::ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex) {
    // Use this as a container to hold information about any gif extension
    // blocks.  This generally stores transparency and animation instructions.
    SavedImage saveExt;
    SkAutoTCallVProc<SavedImage, FreeExtension> autoFreeExt(&saveExt);
    saveExt.ExtensionBlocks = nullptr;
    saveExt.ExtensionBlockCount = 0;
    GifByteType* extData;
    int32_t extFunction;

    // We will loop over components of gif images until we find an image.  Once
    // we find an image, we will decode and return it.  While many gif files
    // contain more than one image, we will simply decode the first image.
    GifRecordType recordType;
    do {
        // Get the current record type
        if (GIF_ERROR == DGifGetRecordType(gif, &recordType)) {
            return gif_error("DGifGetRecordType failed.\n", kInvalidInput);
        }
        switch (recordType) {
            case IMAGE_DESC_RECORD_TYPE: {
                *transIndex = find_trans_index(saveExt);

                // FIXME: Gif files may have multiple images stored in a single
                //        file.  This is most commonly used to enable
                //        animations.  Since we are leaving animated gifs as a
                //        TODO, we will return kSuccess after decoding the
                //        first image in the file.  This is the same behavior
                //        as SkImageDecoder_libgif.
                //
                //        Most times this works pretty well, but sometimes it
                //        doesn't.  For example, I have an animated test image
                //        where the first image in the file is 1x1, but the
                //        subsequent images are meaningful.  This currently
                //        displays the 1x1 image, which is not ideal.  Right
                //        now I am leaving this as an issue that will be
                //        addressed when we implement animated gifs.
                //
                //        It is also possible (not explicitly disallowed in the
                //        specification) that gif files provide multiple
                //        images in a single file that are all meant to be
                //        displayed in the same frame together.  I will
                //        currently leave this unimplemented until I find a
                //        test case that expects this behavior.
                return kSuccess;
            }
            // Extensions are used to specify special properties of the image
            // such as transparency or animation.
            case EXTENSION_RECORD_TYPE:
                // Read extension data
                if (GIF_ERROR == DGifGetExtension(gif, &extFunction, &extData)) {
                    return gif_error("Could not get extension.\n", kIncompleteInput);
                }

                // Create an extension block with our data
                while (nullptr != extData) {
                    // Add a single block
                    if (GIF_ERROR == GifAddExtensionBlock(&saveExt.ExtensionBlockCount,
                                                          &saveExt.ExtensionBlocks,
                                                          extFunction, extData[0], &extData[1]))
                    {
                        return gif_error("Could not add extension block.\n", kIncompleteInput);
                    }
                    // Move to the next block
                    if (GIF_ERROR == DGifGetExtensionNext(gif, &extData)) {
                        return gif_error("Could not get next extension.\n", kIncompleteInput);
                    }
                }
                break;

            // Signals the end of the gif file
            case TERMINATE_RECORD_TYPE:
                break;

            default:
                // DGifGetRecordType returns an error if the record type does
                // not match one of the above cases.  This should not be
                // reached.
                SkASSERT(false);
                break;
        }
    } while (TERMINATE_RECORD_TYPE != recordType);

    return gif_error("Could not find any images to decode in gif file.\n", kInvalidInput);
}

bool SkGifCodec::GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect) {
    // Get the encoded dimension values
    SavedImage* image = &gif->SavedImages[gif->ImageCount - 1];
    const GifImageDesc& desc = image->ImageDesc;
    int frameLeft = desc.Left;
    int frameTop = desc.Top;
    int frameWidth = desc.Width;
    int frameHeight = desc.Height;
    int width = gif->SWidth;
    int height = gif->SHeight;

    // Ensure that the decode dimensions are large enough to contain the frame
    width = SkTMax(width, frameWidth + frameLeft);
    height = SkTMax(height, frameHeight + frameTop);

    // All of these dimensions should be positive, as they are encoded as unsigned 16-bit integers.
    // It is unclear why giflib casts them to ints.  We will go ahead and check that they are
    // in fact positive.
    if (frameLeft < 0 || frameTop < 0 || frameWidth < 0 || frameHeight < 0 || width <= 0 ||
            height <= 0) {
        return false;
    }

    frameRect->setXYWH(frameLeft, frameTop, frameWidth, frameHeight);
    size->set(width, height);
    return true;
}

void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
        int* inputColorCount) {
    // Set up our own color table
    const uint32_t maxColors = 256;
    SkPMColor colorPtr[256];
    if (NULL != inputColorCount) {
        // We set the number of colors to maxColors in order to ensure
        // safe memory accesses.  Otherwise, an invalid pixel could
        // access memory outside of our color table array.
        *inputColorCount = maxColors;
    }

    // Get local color table
    ColorMapObject* colorMap = fGif->Image.ColorMap;
    // If there is no local color table, use the global color table
    if (NULL == colorMap) {
        colorMap = fGif->SColorMap;
    }

    uint32_t colorCount = 0;
    if (NULL != colorMap) {
        colorCount = colorMap->ColorCount;
        // giflib guarantees these properties
        SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel)));
        SkASSERT(colorCount <= 256);
        for (uint32_t i = 0; i < colorCount; i++) {
            colorPtr[i] = SkPackARGB32(0xFF, colorMap->Colors[i].Red,
                    colorMap->Colors[i].Green, colorMap->Colors[i].Blue);
        }
    }

    // Gifs have the option to specify the color at a single index of the color
    // table as transparent.  If the transparent index is greater than the
    // colorCount, we know that there is no valid transparent color in the color
    // table.  If there is not valid transparent index, we will try to use the
    // backgroundIndex as the fill index.  If the backgroundIndex is also not
    // valid, we will let fFillIndex default to 0 (it is set to zero in the
    // constructor).  This behavior is not specified but matches
    // SkImageDecoder_libgif.
    uint32_t backgroundIndex = fGif->SBackGroundColor;
    if (fTransIndex < colorCount) {
        colorPtr[fTransIndex] = SK_ColorTRANSPARENT;
        fFillIndex = fTransIndex;
    } else if (backgroundIndex < colorCount) {
        fFillIndex = backgroundIndex;
    }

    // Fill in the color table for indices greater than color count.
    // This allows for predictable, safe behavior.
    for (uint32_t i = colorCount; i < maxColors; i++) {
        colorPtr[i] = colorPtr[fFillIndex];
    }

    fColorTable.reset(new SkColorTable(colorPtr, maxColors));
    copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount);
}

SkCodec::Result SkGifCodec::prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
        int* inputColorCount, const Options& opts) {
    // Check for valid input parameters
    if (!conversion_possible(dstInfo, this->getInfo())) {
        return gif_error("Cannot convert input type to output type.\n",
                kInvalidConversion);
    }

    // Initialize color table and copy to the client if necessary
    this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount);
    return kSuccess;
}

SkCodec::Result SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& opts) {
    const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
    fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dstInfo, opts));
    if (nullptr != fSwizzler.get()) {
        return kSuccess;
    }
    return kUnimplemented;
}

bool SkGifCodec::readRow() {
    return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameRect.width());
}

/*
 * Initiates the gif decode
 */
SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
                                        void* dst, size_t dstRowBytes,
                                        const Options& opts,
                                        SkPMColor* inputColorPtr,
                                        int* inputColorCount,
                                        int* rowsDecoded) {
    Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, opts);
    if (kSuccess != result) {
        return result;
    }

    if (dstInfo.dimensions() != this->getInfo().dimensions()) {
        return gif_error("Scaling not supported.\n", kInvalidScale);
    }

    // Initialize the swizzler
    if (fFrameIsSubset) {
        const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFrameRect.height());
        if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) {
            return gif_error("Could not initialize swizzler.\n", kUnimplemented);
        }

        // Fill the background
        SkSampler::Fill(dstInfo, dst, dstRowBytes,
                this->getFillValue(dstInfo.colorType(), dstInfo.alphaType()),
                opts.fZeroInitialized);

        // Modify the dst pointer
        const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorType());
        dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameRect.top() +
                dstBytesPerPixel * fFrameRect.left());
    } else {
        if (kSuccess != this->initializeSwizzler(dstInfo, opts)) {
            return gif_error("Could not initialize swizzler.\n", kUnimplemented);
        }
    }

    // Iterate over rows of the input
    uint32_t height = fFrameRect.height();
    for (uint32_t y = 0; y < height; y++) {
        if (!this->readRow()) {
            *rowsDecoded = y;
            return gif_error("Could not decode line.\n", kIncompleteInput);
        }
        void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->outputScanline(y));
        fSwizzler->swizzle(dstRow, fSrcBuffer.get());
    }
    return kSuccess;
}

// FIXME: This is similar to the implementation for bmp and png.  Can we share more code or
//        possibly make this non-virtual?
uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
    const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
    return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
}

SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
        const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColorCount) {

    Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->options());
    if (kSuccess != result) {
        return result;
    }

    // Initialize the swizzler
    if (fFrameIsSubset) {
        const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameRect.width(), fFrameRect.height());
        if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts)) {
            return gif_error("Could not initialize swizzler.\n", kUnimplemented);
        }
    } else {
        if (kSuccess != this->initializeSwizzler(dstInfo, opts)) {
            return gif_error("Could not initialize swizzler.\n", kUnimplemented);
        }
    }

    return kSuccess;
}

int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
    int rowsBeforeFrame = 0;
    int rowsAfterFrame = 0;
    int rowsInFrame = count;
    if (fFrameIsSubset) {
        // Fill the requested rows
        SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
        uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType(),
                this->dstInfo().alphaType());
        SkSampler::Fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized);

        // Do nothing for rows before the image frame
        rowsBeforeFrame = SkTMax(0, fFrameRect.top() - this->INHERITED::nextScanline());
        rowsInFrame = SkTMax(0, rowsInFrame - rowsBeforeFrame);
        dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);

        // Do nothing for rows after the image frame
        rowsAfterFrame = SkTMax(0,
                this->INHERITED::nextScanline() + rowsInFrame - fFrameRect.bottom());
        rowsInFrame = SkTMax(0, rowsInFrame - rowsAfterFrame);

        // Adjust dst pointer for left offset
        int offset = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrameRect.left();
        dst = SkTAddOffset<void>(dst, offset);
    }

    for (int i = 0; i < rowsInFrame; i++) {
        if (!this->readRow()) {
            return i + rowsBeforeFrame;
        }
        fSwizzler->swizzle(dst, fSrcBuffer.get());
        dst = SkTAddOffset<void>(dst, rowBytes);
    }

    return count;
}

SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const {
    if (fGif->Image.Interlace) {
        return kOutOfOrder_SkScanlineOrder;
    }
    return kTopDown_SkScanlineOrder;
}

int SkGifCodec::onOutputScanline(int inputScanline) const {
    if (fGif->Image.Interlace) {
        if (inputScanline < fFrameRect.top() || inputScanline >= fFrameRect.bottom()) {
            return inputScanline;
        }
        return get_output_row_interlaced(inputScanline - fFrameRect.top(), fFrameRect.height());
    }
    return inputScanline;
}
