/*
 * 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);
}

 /*
 * 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, nullptr);
}

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

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

static 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
 */
static 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));
}

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

    if (nullptr != codecOut) {
        // Get fields from header
        const int32_t width = gif->SWidth;
        const int32_t height = gif->SHeight;
        if (width <= 0 || height <= 0) {
            gif_error("Invalid dimensions.\n");
            return false;
        }

        // Return the codec
        // kIndex is the most natural color type for gifs, so we set this as
        // the default.
        // Many gifs specify a color table index for transparent pixels.  Every
        // other pixel is guaranteed to be opaque.  Despite this, because of the
        // possiblity of transparent pixels, we cannot assume that the image is
        // opaque.  We have the option to set the alpha type as 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.
        const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
                                                         kIndex_8_SkColorType, kPremul_SkAlphaType);
        *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach());
    } 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)
    : INHERITED(srcInfo, stream)
    , fGif(gif)
{}

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

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

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

    // Check for valid input parameters
    if (opts.fSubset) {
        // Subsets are not supported.
        return kUnimplemented;
    }
    if (dstInfo.dimensions() != this->getInfo().dimensions()) {
        return gif_error("Scaling not supported.\n", kInvalidScale);
    }
    if (!conversion_possible(dstInfo, this->getInfo())) {
        return gif_error("Cannot convert input type to output type.\n", kInvalidConversion);
    }

    // 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.
    const int32_t width = dstInfo.width();
    const int32_t height = dstInfo.height();
    GifRecordType recordType;
    do {
        // Get the current record type
        if (GIF_ERROR == DGifGetRecordType(fGif, &recordType)) {
            return gif_error("DGifGetRecordType failed.\n", kInvalidInput);
        }

        switch (recordType) {
            case IMAGE_DESC_RECORD_TYPE: {
                // Read the image descriptor
                if (GIF_ERROR == DGifGetImageDesc(fGif)) {
                    return gif_error("DGifGetImageDesc failed.\n", kInvalidInput);
                }

                // If reading the image descriptor is successful, the image
                // count will be incremented
                SkASSERT(fGif->ImageCount >= 1);
                SavedImage* image = &fGif->SavedImages[fGif->ImageCount - 1];

                // Process the descriptor
                const GifImageDesc& desc = image->ImageDesc;
                int32_t imageLeft = desc.Left;
                int32_t imageTop = desc.Top;
                int32_t innerWidth = desc.Width;
                int32_t innerHeight = desc.Height;
                // Fail on non-positive dimensions
                if (innerWidth <= 0 || innerHeight <= 0) {
                    return gif_error("Invalid dimensions for inner image.\n", kInvalidInput);
                }
                // Treat the following cases as warnings and try to fix
                if (innerWidth > width) {
                    gif_warning("Inner image too wide, shrinking.\n");
                    innerWidth = width;
                    imageLeft = 0;
                } else if (imageLeft + innerWidth > width) {
                    gif_warning("Shifting inner image to left to fit.\n");
                    imageLeft = width - innerWidth;
                } else if (imageLeft < 0) {
                    gif_warning("Shifting image to right to fit\n");
                    imageLeft = 0;
                }
                if (innerHeight > height) {
                    gif_warning("Inner image too tall, shrinking.\n");
                    innerHeight = height;
                    imageTop = 0;
                } else if (imageTop + innerHeight > height) {
                    gif_warning("Shifting inner image up to fit.\n");
                    imageTop = height - innerHeight;
                } else if (imageTop < 0) {
                    gif_warning("Shifting image down to fit\n");
                    imageTop = 0;
                }

                // Create a color table to store colors the giflib colorMap
                SkPMColor alternateColorPtr[256];
                SkPMColor* colorTable;
                SkColorType dstColorType = dstInfo.colorType();
                if (kIndex_8_SkColorType == dstColorType) {
                    SkASSERT(nullptr != inputColorPtr);
                    SkASSERT(nullptr != inputColorCount);
                    colorTable = inputColorPtr;
                } else {
                    colorTable = alternateColorPtr;
                }

                // Set up the color table
                uint32_t colorCount = 0;
                // Allocate maximum storage to deal with invalid indices safely
                const uint32_t maxColors = 256;
                ColorMapObject* colorMap = fGif->Image.ColorMap;
                // If there is no local color table, use the global color table
                if (nullptr == colorMap) {
                    colorMap = fGif->SColorMap;
                }
                if (nullptr != colorMap) {
                    colorCount = colorMap->ColorCount;
                    SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel)));
                    SkASSERT(colorCount <= 256);
                    for (uint32_t i = 0; i < colorCount; i++) {
                        colorTable[i] = SkPackARGB32(0xFF,
                                                     colorMap->Colors[i].Red,
                                                     colorMap->Colors[i].Green,
                                                     colorMap->Colors[i].Blue);
                    }
                }

                // This is used to fill unspecified pixels in the image data.
                uint32_t fillIndex = fGif->SBackGroundColor;
                ZeroInitialized zeroInit = opts.fZeroInitialized;

                // Gifs have the option to specify the color at a single
                // index of the color table as transparent.
                {
                    // Get the transparent index.  If the return value of this
                    // function is greater than the colorCount, we know that
                    // there is no valid transparent color in the color table.
                    // This occurs if there is no graphics control extension or
                    // if the index specified by the graphics control extension
                    // is out of range.
                    uint32_t transIndex = find_trans_index(saveExt);

                    if (transIndex < colorCount) {
                        colorTable[transIndex] = SK_ColorTRANSPARENT;
                        // If there is a transparent index, we also use this as
                        // the fill index.
                        fillIndex = transIndex;
                    } else if (fillIndex >= colorCount) {
                        // If the fill index is invalid, we default to 0.  This
                        // behavior is unspecified but matches SkImageDecoder.
                        fillIndex = 0;
                    }
                }

                // 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++) {
                    colorTable[i] = colorTable[fillIndex];
                } 

                // Check if image is only a subset of the image frame
                SkAutoTDelete<SkSwizzler> swizzler(nullptr);
                if (innerWidth < width || innerHeight < height) {

                    // Modify the destination info
                    const SkImageInfo subsetDstInfo = dstInfo.makeWH(innerWidth, innerHeight);

                    // Fill the destination with the fill color
                    // FIXME: This may not be the behavior that we want for
                    //        animated gifs where we draw on top of the
                    //        previous frame.
                    SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fillIndex, colorTable,
                            zeroInit);

                    // Modify the dst pointer
                    const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstColorType);
                    dst = SkTAddOffset<void*>(dst,
                                              dstRowBytes * imageTop +
                                              dstBytesPerPixel * imageLeft);

                    // Create the subset swizzler
                    swizzler.reset(SkSwizzler::CreateSwizzler(
                            SkSwizzler::kIndex, colorTable, subsetDstInfo,
                            zeroInit, this->getInfo()));
                } else {
                    // Create the fully dimensional swizzler
                    swizzler.reset(SkSwizzler::CreateSwizzler(
                            SkSwizzler::kIndex, colorTable, dstInfo, 
                            zeroInit, this->getInfo()));
                }

                // Stores output from dgiflib and input to the swizzler
                SkAutoTDeleteArray<uint8_t> buffer(new uint8_t[innerWidth]);

                // Check the interlace flag and iterate over rows of the input
                if (fGif->Image.Interlace) {
                    for (int32_t y = 0; y < innerHeight; y++) {
                        if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWidth)) {
                            // Recover from error by filling remainder of image
                            memset(buffer.get(), fillIndex, innerWidth);
                            for (; y < innerHeight; y++) {
                                void* dstRow = SkTAddOffset<void>(dst, dstRowBytes *
                                        get_output_row_interlaced(y, innerHeight));
                                swizzler->swizzle(dstRow, buffer.get());
                            }
                            return gif_error(SkStringPrintf(
                                    "Could not decode line %d of %d.\n",
                                    y, height - 1).c_str(), kIncompleteInput);
                        }
                        void* dstRow = SkTAddOffset<void>(dst,
                                dstRowBytes * get_output_row_interlaced(y, innerHeight));
                        swizzler->swizzle(dstRow, buffer.get());
                    }
                } else {
                    // Standard mode
                    void* dstRow = dst;
                    for (int32_t y = 0; y < innerHeight; y++) {
                        if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), innerWidth)) {
                            SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, innerHeight - y,
                                    fillIndex, colorTable, zeroInit);
                            return gif_error(SkStringPrintf(
                                    "Could not decode line %d of %d.\n",
                                    y, height - 1).c_str(), kIncompleteInput);
                        }
                        swizzler->swizzle(dstRow, buffer.get());
                        dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
                    }
                }

                // 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(fGif, &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(fGif, &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:
                // giflib returns an error code if the record type is not known.
                // We should catch this error immediately.
                SkASSERT(false);
                break;
        }
    } while (TERMINATE_RECORD_TYPE != recordType);

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