/*
 * 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.h"
#include "SkColorSpace.h"
#include "SkColorTable.h"
#include "SkImageInfo.h"
#include "SkSwizzler.h"

struct GifFileType;
struct SavedImage;

/*
 *
 * This class implements the decoding for gif images
 *
 */
class SkGifCodec : public SkCodec {
public:
    static bool IsGif(const void*, size_t);

    /*
     * Assumes IsGif was called and returned true
     * Creates a gif decoder
     * Reads enough of the stream to determine the image format
     */
    static SkCodec* NewFromStream(SkStream*);

protected:

    /*
     * 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.
     *
     */
    static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
            GifFileType** gifOut);

    /*
     * Performs the full gif decode
     */
    Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
            SkPMColor*, int*, int*) override;

    SkEncodedFormat onGetEncodedFormat() const override {
        return kGIF_SkEncodedFormat;
    }

    bool onRewind() override;

    uint64_t onGetFillValue(const SkImageInfo&) const override;

    int onOutputScanline(int inputScanline) const override;

private:

    /*
     * A gif can contain multiple image frames.  We will only decode the first
     * frame.  This function reads up to the first image frame, processing
     * transparency and/or animation information that comes before the image
     * data.
     *
     * @param gif        Pointer to the library type that manages the gif decode
     * @param transIndex This call will set the transparent index based on the
     *                   extension data.
     */
     static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex);

     /*
      * A gif may contain many image frames, all of different sizes.
      * This function checks if the gif dimensions are valid, based on the frame
      * dimensions, and corrects the gif dimensions if necessary.
      *
      * @param gif       Pointer to the library type that manages the gif decode
      * @param size      Size of the image that we will decode.
      *                  Will be set by this function if the return value is true.
      * @param frameRect Contains the dimenions and offset of the first image frame.
      *                  Will be set by this function if the return value is true.
      *
      * @return true on success, false otherwise
      */
     static bool GetDimensions(GifFileType* gif, SkISize* size, SkIRect* frameRect);

    /*
     * Initializes the color table that we will use for decoding.
     *
     * @param dstInfo         Contains the requested dst color type.
     * @param inputColorPtr   Copies the encoded color table to the client's
     *                        input color table if the client requests kIndex8.
     * @param inputColorCount If the client requests kIndex8, sets
     *                        inputColorCount to 256.  Since gifs always
     *                        contain 8-bit indices, we need a 256 entry color
     *                        table to ensure that indexing is always in
     *                        bounds.
     */
    void initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* colorPtr,
            int* inputColorCount);

   /*
    * Checks for invalid inputs and calls setFrameDimensions(), and
    * initializeColorTable() in the proper sequence.
    */
    Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
            int* inputColorCount, const Options& opts);

    /*
     * Initializes the swizzler.
     *
     * @param dstInfo  Output image information.  Dimensions may have been
     *                 adjusted if the image frame size does not match the size
     *                 indicated in the header.
     * @param options  Informs the swizzler if destination memory is zero initialized.
     *                 Contains subset information.
     */
    void initializeSwizzler(const SkImageInfo& dstInfo,
            const Options& options);

    SkSampler* getSampler(bool createIfNecessary) override {
        SkASSERT(fSwizzler);
        return fSwizzler;
    }

    /*
     * @return true if the read is successful and false if the read fails.
     */
    bool readRow();

    Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts,
                   SkPMColor inputColorPtr[], int* inputColorCount) override;

    int onGetScanlines(void* dst, int count, size_t rowBytes) override;

    bool onSkipScanlines(int count) override;

    /*
     * For a scanline decode of "count" lines, this function indicates how
     * many of the "count" lines should be skipped until we reach the top of
     * the image frame and how many of the "count" lines are actually inside
     * the image frame.
     *
     * @param count           The number of scanlines requested.
     * @param rowsBeforeFrame Output variable.  The number of lines before
     *                        we reach the top of the image frame.
     * @param rowsInFrame     Output variable.  The number of lines to decode
     *                        inside the image frame.
     */
    void handleScanlineFrame(int count, int* rowsBeforeFrame, int* rowsInFrame);

    SkScanlineOrder onGetScanlineOrder() const override;

    /*
     * This function cleans up the gif object after the decode completes
     * It is used in a SkAutoTCallIProc template
     */
    static void CloseGif(GifFileType* gif);

    /*
     * Frees any extension data used in the decode
     * Used in a SkAutoTCallVProc
     */
    static void FreeExtension(SavedImage* image);

    /*
     * Creates an instance of the decoder
     * Called only by NewFromStream
     *
     * @param info contains properties of the encoded data
     * @param stream the stream of image data
     * @param gif pointer to library type that manages gif decode
     *            takes ownership
     * @param transIndex  The transparent index.  An invalid value
     *            indicates that there is no transparent index.
     */
    SkGifCodec(int width, int height, const SkEncodedInfo& info, SkStream* stream,
            GifFileType* gif, uint32_t transIndex, const SkIRect& frameRect, bool frameIsSubset);

    SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned
    SkAutoTDeleteArray<uint8_t>             fSrcBuffer;
    const SkIRect                           fFrameRect;
    const uint32_t                          fTransIndex;
    uint32_t                                fFillIndex;
    const bool                              fFrameIsSubset;
    SkAutoTDelete<SkSwizzler>               fSwizzler;
    SkAutoTUnref<SkColorTable>              fColorTable;

    typedef SkCodec INHERITED;
};
