/*
 * 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 "SkCodecPriv.h"
#include "SkColorPriv.h"
#include "SkColorTable.h"
#include "SkGifCodec.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(const void* buf, size_t bytesRead) {
    if (bytesRead >= 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;
}

/*
 * 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) {
#if GIFLIB_MAJOR < 5
    return DGifOpen(stream, read_bytes_callback);
#else
    return DGifOpen(stream, read_bytes_callback, nullptr);
#endif
}

/*
 * 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) {
#if GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)
    DGifCloseFile(gif);
#else
    DGifCloseFile(gif, nullptr);
#endif
}

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

/*
 * 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");
            return false;
        }
        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()])
    , fFrameRect(frameRect)
    // 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)
    , fFrameIsSubset(frameIsSubset)
    , fSwizzler(NULL)
    , fColorTable(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 GIFLIB_MAJOR < 5
                    if (AddExtensionBlock(&saveExt, extData[0],
                                          &extData[1]) == GIF_ERROR) {
#else
                    if (GIF_ERROR == GifAddExtensionBlock(&saveExt.ExtensionBlockCount,
                                                          &saveExt.ExtensionBlocks,
                                                          extFunction, extData[0], &extData[1])) {
#endif
                        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);

    this->initializeSwizzler(dstInfo, opts);
    return kSuccess;
}

void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, const Options& opts) {
    const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
    const SkIRect* frameRect = fFrameIsSubset ? &fFrameRect : nullptr;
    fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, colorPtr, dstInfo, opts,
            frameRect));
    SkASSERT(fSwizzler);
}

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) {
        // Fill the background
        SkSampler::Fill(dstInfo, dst, dstRowBytes, this->getFillValue(dstInfo.colorType()),
                opts.fZeroInitialized);
    }

    // Iterate over rows of the input
    for (int y = fFrameRect.top(); y < fFrameRect.bottom(); 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) 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) {
    return this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, this->options());
}

void SkGifCodec::handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame) {
    if (fFrameIsSubset) {
        const int currRow = this->currScanline();

        // The number of rows that remain to be skipped before reaching rows that we
        // actually must decode into.
        // This must be at least zero.  We also make sure that it is less than or
        // equal to count, since we will skip at most count rows.
        *rowsBeforeFrame = SkTMin(count, SkTMax(0, fFrameRect.top() - currRow));

        // Rows left to decode once we reach the start of the frame.
        const int rowsLeft = count - *rowsBeforeFrame;

        // Count the number of that extend beyond the bottom of the frame.  We do not
        // need to decode into these rows.
        const int rowsAfterFrame = SkTMax(0, currRow + rowsLeft - fFrameRect.bottom());

        // Set the actual number of source rows that we need to decode.
        *rowsInFrame = rowsLeft - rowsAfterFrame;
    } else {
        *rowsBeforeFrame = 0;
        *rowsInFrame = count;
    }
}

int SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
    int rowsBeforeFrame;
    int rowsInFrame;
    this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame);

    if (fFrameIsSubset) {
        // Fill the requested rows
        SkImageInfo fillInfo = this->dstInfo().makeWH(this->dstInfo().width(), count);
        uint32_t fillValue = this->onGetFillValue(this->dstInfo().colorType());
        fSwizzler->fill(fillInfo, dst, rowBytes, fillValue, this->options().fZeroInitialized);

        // Start to write pixels at the start of the image frame
        dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
    }

    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;
}

bool SkGifCodec::onSkipScanlines(int count) {
    int rowsBeforeFrame;
    int rowsInFrame;
    this->handleScanlineFrame(count, &rowsBeforeFrame, &rowsInFrame);

    for (int i = 0; i < rowsInFrame; i++) {
        if (!this->readRow()) {
            return false;
        }
    }

    return true;
}

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()) +
                fFrameRect.top();
    }
    return inputScanline;
}
