/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Chris Saari <saari@netscape.com>
 *   Apple Computer
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
The Graphics Interchange Format(c) is the copyright property of CompuServe
Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
enhance, alter, modify or change in any way the definition of the format.

CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
license for the use of the Graphics Interchange Format(sm) in computer
software; computer software utilizing GIF(sm) must acknowledge ownership of the
Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
User and Technical Documentation. Computer software utilizing GIF, which is
distributed or may be distributed without User or Technical Documentation must
display to the screen or printer a message acknowledging ownership of the
Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
this case, the acknowledgement may be displayed in an opening screen or leading
banner, or a closing screen or trailing banner. A message such as the following
may be used:

    "The Graphics Interchange Format(c) is the Copyright property of
    CompuServe Incorporated. GIF(sm) is a Service Mark property of
    CompuServe Incorporated."

For further information, please contact :

    CompuServe Incorporated
    Graphics Technology Department
    5000 Arlington Center Boulevard
    Columbus, Ohio  43220
    U. S. A.

CompuServe Incorporated maintains a mailing list with all those individuals and
organizations who wish to receive copies of this document when it is corrected
or revised. This service is offered free of charge; please provide us with your
mailing address.
*/

#include "SkGifImageReader.h"
#include "SkColorPriv.h"
#include "SkGifCodec.h"

#include <algorithm>
#include <string.h>


// GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'.
//
// Note, the hold will never need to be bigger than 256 bytes to gather up in the hold,
// as each GIF block (except colormaps) can never be bigger than 256 bytes.
// Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap.
// So a fixed buffer in SkGifImageReader is good enough.
// This buffer is only needed to copy left-over data from one GifWrite call to the next
#define GETN(n, s) \
    do { \
        m_bytesToConsume = (n); \
        m_state = (s); \
    } while (0)

// Get a 16-bit value stored in little-endian format.
#define GETINT16(p)   ((p)[1]<<8|(p)[0])

namespace {
    bool is_palette_index_valid(int transparentIndex) {
        // -1 is a signal that there is no transparent index.
        // Otherwise, it is encoded in 8 bits, and all 256 values are considered
        // valid since a GIF may use an index outside of the palette to be
        // transparent.
        return transparentIndex >= 0;
    }
} // anonymous namespace

// Send the data to the display front-end.
void SkGIFLZWContext::outputRow(const unsigned char* rowBegin)
{
    int drowStart = irow;
    int drowEnd = irow;

    // Haeberli-inspired hack for interlaced GIFs: Replicate lines while
    // displaying to diminish the "venetian-blind" effect as the image is
    // loaded. Adjust pixel vertical positions to avoid the appearance of the
    // image crawling up the screen as successive passes are drawn.
    if (m_frameContext->progressiveDisplay() && m_frameContext->interlaced() && ipass < 4) {
        unsigned rowDup = 0;
        unsigned rowShift = 0;

        switch (ipass) {
        case 1:
            rowDup = 7;
            rowShift = 3;
            break;
        case 2:
            rowDup = 3;
            rowShift = 1;
            break;
        case 3:
            rowDup = 1;
            rowShift = 0;
            break;
        default:
            break;
        }

        drowStart -= rowShift;
        drowEnd = drowStart + rowDup;

        // Extend if bottom edge isn't covered because of the shift upward.
        if ((unsigned)((m_frameContext->height() - 1) - drowEnd) <= rowShift)
            drowEnd = m_frameContext->height() - 1;

        // Clamp first and last rows to upper and lower edge of image.
        if (drowStart < 0)
            drowStart = 0;

        if (drowEnd >= m_frameContext->height())
            drowEnd = m_frameContext->height() - 1;
    }

    // Protect against too much image data.
    if (drowStart >= m_frameContext->height())
        return;

    // CALLBACK: Let the client know we have decoded a row.
    const bool writeTransparentPixels = (SkCodec::kNone == m_frameContext->getRequiredFrame());
    m_client->haveDecodedRow(m_frameContext->frameId(), rowBegin,
            drowStart, drowEnd - drowStart + 1, writeTransparentPixels);

    if (!m_frameContext->interlaced())
        irow++;
    else {
        do {
            switch (ipass) {
            case 1:
                irow += 8;
                if (irow >= (unsigned) m_frameContext->height()) {
                    ipass++;
                    irow = 4;
                }
                break;

            case 2:
                irow += 8;
                if (irow >= (unsigned) m_frameContext->height()) {
                    ipass++;
                    irow = 2;
                }
                break;

            case 3:
                irow += 4;
                if (irow >= (unsigned) m_frameContext->height()) {
                    ipass++;
                    irow = 1;
                }
                break;

            case 4:
                irow += 2;
                if (irow >= (unsigned) m_frameContext->height()) {
                    ipass++;
                    irow = 0;
                }
                break;

            default:
                break;
            }
        } while (irow > (unsigned) (m_frameContext->height() - 1));
    }
}

// Perform Lempel-Ziv-Welch decoding.
// Returns true if decoding was successful. In this case the block will have been completely consumed and/or rowsRemaining will be 0.
// Otherwise, decoding failed; returns false in this case, which will always cause the SkGifImageReader to set the "decode failed" flag.
bool SkGIFLZWContext::doLZW(const unsigned char* block, size_t bytesInBlock)
{
    const int width = m_frameContext->width();

    if (rowIter == rowBuffer.end())
        return true;

    for (const unsigned char* ch = block; bytesInBlock-- > 0; ch++) {
        // Feed the next byte into the decoder's 32-bit input buffer.
        datum += ((int) *ch) << bits;
        bits += 8;

        // Check for underflow of decoder's 32-bit input buffer.
        while (bits >= codesize) {
            // Get the leading variable-length symbol from the data stream.
            int code = datum & codemask;
            datum >>= codesize;
            bits -= codesize;

            // Reset the dictionary to its original state, if requested.
            if (code == clearCode) {
                codesize = m_frameContext->dataSize() + 1;
                codemask = (1 << codesize) - 1;
                avail = clearCode + 2;
                oldcode = -1;
                continue;
            }

            // Check for explicit end-of-stream code.
            if (code == (clearCode + 1)) {
                // end-of-stream should only appear after all image data.
                if (!rowsRemaining)
                    return true;
                return false;
            }

            const int tempCode = code;
            unsigned short codeLength = 0;
            if (code < avail) {
                // This is a pre-existing code, so we already know what it
                // encodes.
                codeLength = suffixLength[code];
                rowIter += codeLength;
            } else if (code == avail && oldcode != -1) {
                // This is a new code just being added to the dictionary.
                // It must encode the contents of the previous code, plus
                // the first character of the previous code again.
                codeLength = suffixLength[oldcode] + 1;
                rowIter += codeLength;
                *--rowIter = firstchar;
                code = oldcode;
            } else {
                // This is an invalid code. The dictionary is just initialized
                // and the code is incomplete. We don't know how to handle
                // this case.
                return false;
            }

            while (code >= clearCode) {
                *--rowIter = suffix[code];
                code = prefix[code];
            }

            *--rowIter = firstchar = suffix[code];

            // Define a new codeword in the dictionary as long as we've read
            // more than one value from the stream.
            if (avail < SK_MAX_DICTIONARY_ENTRIES && oldcode != -1) {
                prefix[avail] = oldcode;
                suffix[avail] = firstchar;
                suffixLength[avail] = suffixLength[oldcode] + 1;
                ++avail;

                // If we've used up all the codewords of a given length
                // increase the length of codewords by one bit, but don't
                // exceed the specified maximum codeword size.
                if (!(avail & codemask) && avail < SK_MAX_DICTIONARY_ENTRIES) {
                    ++codesize;
                    codemask += avail;
                }
            }
            oldcode = tempCode;
            rowIter += codeLength;

            // Output as many rows as possible.
            unsigned char* rowBegin = rowBuffer.begin();
            for (; rowBegin + width <= rowIter; rowBegin += width) {
                outputRow(rowBegin);
                rowsRemaining--;
                if (!rowsRemaining)
                    return true;
            }

            if (rowBegin != rowBuffer.begin()) {
                // Move the remaining bytes to the beginning of the buffer.
                const size_t bytesToCopy = rowIter - rowBegin;
                memcpy(&rowBuffer.front(), rowBegin, bytesToCopy);
                rowIter = rowBuffer.begin() + bytesToCopy;
            }
        }
    }
    return true;
}

sk_sp<SkColorTable> SkGIFColorMap::buildTable(SkStreamBuffer* streamBuffer, SkColorType colorType,
                                              int transparentPixel) const
{
    if (!m_isDefined)
        return nullptr;

    const PackColorProc proc = choose_pack_color_proc(false, colorType);
    if (m_table && proc == m_packColorProc && m_transPixel == transparentPixel) {
        SkASSERT(transparentPixel == kNotFound || transparentPixel > m_table->count()
                || m_table->operator[](transparentPixel) == SK_ColorTRANSPARENT);
        // This SkColorTable has already been built with the same transparent color and
        // packing proc. Reuse it.
        return m_table;
    }
    m_packColorProc = proc;
    m_transPixel = transparentPixel;

    const size_t bytes = m_colors * SK_BYTES_PER_COLORMAP_ENTRY;
    sk_sp<SkData> rawData(streamBuffer->getDataAtPosition(m_position, bytes));
    if (!rawData) {
        return nullptr;
    }

    SkASSERT(m_colors <= SK_MAX_COLORS);
    const uint8_t* srcColormap = rawData->bytes();
    SkPMColor colorStorage[SK_MAX_COLORS];
    for (int i = 0; i < m_colors; i++) {
        if (i == transparentPixel) {
            colorStorage[i] = SK_ColorTRANSPARENT;
        } else {
            colorStorage[i] = proc(255, srcColormap[0], srcColormap[1], srcColormap[2]);
        }
        srcColormap += SK_BYTES_PER_COLORMAP_ENTRY;
    }
    for (int i = m_colors; i < SK_MAX_COLORS; i++) {
        colorStorage[i] = SK_ColorTRANSPARENT;
    }
    m_table = sk_sp<SkColorTable>(new SkColorTable(colorStorage, SK_MAX_COLORS));
    return m_table;
}

sk_sp<SkColorTable> SkGifImageReader::getColorTable(SkColorType colorType, int index) {
    if (index < 0 || index >= m_frames.count()) {
        return nullptr;
    }

    const SkGIFFrameContext* frameContext = m_frames[index].get();
    const SkGIFColorMap& localColorMap = frameContext->localColorMap();
    const int transPix = frameContext->transparentPixel();
    if (localColorMap.isDefined()) {
        return localColorMap.buildTable(&m_streamBuffer, colorType, transPix);
    }
    if (m_globalColorMap.isDefined()) {
        return m_globalColorMap.buildTable(&m_streamBuffer, colorType, transPix);
    }
    return nullptr;
}

// Perform decoding for this frame. frameComplete will be true if the entire frame is decoded.
// Returns false if a decoding error occurred. This is a fatal error and causes the SkGifImageReader to set the "decode failed" flag.
// Otherwise, either not enough data is available to decode further than before, or the new data has been decoded successfully; returns true in this case.
bool SkGIFFrameContext::decode(SkStreamBuffer* streamBuffer, SkGifCodec* client,
                               bool* frameComplete)
{
    *frameComplete = false;
    if (!m_lzwContext) {
        // Wait for more data to properly initialize SkGIFLZWContext.
        if (!isDataSizeDefined() || !isHeaderDefined())
            return true;

        m_lzwContext.reset(new SkGIFLZWContext(client, this));
        if (!m_lzwContext->prepareToDecode()) {
            m_lzwContext.reset();
            return false;
        }

        m_currentLzwBlock = 0;
    }

    // Some bad GIFs have extra blocks beyond the last row, which we don't want to decode.
    while (m_currentLzwBlock < m_lzwBlocks.count() && m_lzwContext->hasRemainingRows()) {
        const auto& block = m_lzwBlocks[m_currentLzwBlock];
        const size_t len = block.blockSize;

        sk_sp<SkData> data(streamBuffer->getDataAtPosition(block.blockPosition, len));
        if (!data) {
            return false;
        }
        if (!m_lzwContext->doLZW(reinterpret_cast<const unsigned char*>(data->data()), len)) {
            return false;
        }
        ++m_currentLzwBlock;
    }

    // If this frame is data complete then the previous loop must have completely decoded all LZW blocks.
    // There will be no more decoding for this frame so it's time to cleanup.
    if (isComplete()) {
        *frameComplete = true;
        m_lzwContext.reset();
    }
    return true;
}

// Decode a frame.
// This method uses SkGIFFrameContext:decode() to decode the frame; decoding error is reported to client as a critical failure.
// Return true if decoding has progressed. Return false if an error has occurred.
bool SkGifImageReader::decode(int frameIndex, bool* frameComplete)
{
    SkGIFFrameContext* currentFrame = m_frames[frameIndex].get();

    return currentFrame->decode(&m_streamBuffer, m_client, frameComplete);
}

// Parse incoming GIF data stream into internal data structures.
SkCodec::Result SkGifImageReader::parse(SkGifImageReader::SkGIFParseQuery query)
{
    if (m_parseCompleted) {
        return SkCodec::kSuccess;
    }

    if (SkGIFLoopCountQuery == query && m_loopCount != cLoopCountNotSeen) {
        // Loop count has already been parsed.
        return SkCodec::kSuccess;
    }

    // SkGIFSizeQuery and SkGIFFrameCountQuery are negative, so this is only meaningful when >= 0.
    const int lastFrameToParse = (int) query;
    if (lastFrameToParse >= 0 && m_frames.count() > lastFrameToParse
                && m_frames[lastFrameToParse]->isComplete()) {
        // We have already parsed this frame.
        return SkCodec::kSuccess;
    }

    while (true) {
        if (!m_streamBuffer.buffer(m_bytesToConsume)) {
            // The stream does not yet have enough data.
            return SkCodec::kIncompleteInput;
        }

        switch (m_state) {
        case SkGIFLZW: {
            SkASSERT(!m_frames.empty());
            auto* frame = m_frames.back().get();
            frame->addLzwBlock(m_streamBuffer.markPosition(), m_bytesToConsume);
            GETN(1, SkGIFSubBlock);
            break;
        }
        case SkGIFLZWStart: {
            SkASSERT(!m_frames.empty());
            auto* currentFrame = m_frames.back().get();

            currentFrame->setDataSize(this->getOneByte());
            GETN(1, SkGIFSubBlock);
            break;
        }

        case SkGIFType: {
            const char* currentComponent = m_streamBuffer.get();

            // All GIF files begin with "GIF87a" or "GIF89a".
            if (!memcmp(currentComponent, "GIF89a", 6))
                m_version = 89;
            else if (!memcmp(currentComponent, "GIF87a", 6))
                m_version = 87;
            else {
                // This prevents attempting to continue reading this invalid stream.
                GETN(0, SkGIFDone);
                return SkCodec::kInvalidInput;
            }
            GETN(7, SkGIFGlobalHeader);
            break;
        }

        case SkGIFGlobalHeader: {
            const unsigned char* currentComponent =
                reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

            // This is the height and width of the "screen" or frame into which
            // images are rendered. The individual images can be smaller than
            // the screen size and located with an origin anywhere within the
            // screen.
            // Note that we don't inform the client of the size yet, as it might
            // change after we read the first frame's image header.
            fScreenWidth = GETINT16(currentComponent);
            fScreenHeight = GETINT16(currentComponent + 2);

            const int globalColorMapColors = 2 << (currentComponent[4] & 0x07);

            if ((currentComponent[4] & 0x80) && globalColorMapColors > 0) { /* global map */
                m_globalColorMap.setNumColors(globalColorMapColors);
                GETN(SK_BYTES_PER_COLORMAP_ENTRY * globalColorMapColors, SkGIFGlobalColormap);
                break;
            }

            GETN(1, SkGIFImageStart);
            break;
        }

        case SkGIFGlobalColormap: {
            m_globalColorMap.setTablePosition(m_streamBuffer.markPosition());
            GETN(1, SkGIFImageStart);
            break;
        }

        case SkGIFImageStart: {
            const char currentComponent = m_streamBuffer.get()[0];

            if (currentComponent == '!') { // extension.
                GETN(2, SkGIFExtension);
                break;
            }

            if (currentComponent == ',') { // image separator.
                GETN(9, SkGIFImageHeader);
                break;
            }

            // If we get anything other than ',' (image separator), '!'
            // (extension), or ';' (trailer), there is extraneous data
            // between blocks. The GIF87a spec tells us to keep reading
            // until we find an image separator, but GIF89a says such
            // a file is corrupt. We follow Mozilla's implementation and
            // proceed as if the file were correctly terminated, so the
            // GIF will display.
            GETN(0, SkGIFDone);
            break;
        }

        case SkGIFExtension: {
            const unsigned char* currentComponent =
                reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

            size_t bytesInBlock = currentComponent[1];
            SkGIFState exceptionState = SkGIFSkipBlock;

            switch (*currentComponent) {
            case 0xf9:
                // The GIF spec mandates that the GIFControlExtension header block length is 4 bytes,
                exceptionState = SkGIFControlExtension;
                // and the parser for this block reads 4 bytes, so we must enforce that the buffer
                // contains at least this many bytes. If the GIF specifies a different length, we
                // allow that, so long as it's larger; the additional data will simply be ignored.
                bytesInBlock = std::max(bytesInBlock, static_cast<size_t>(4));
                break;

            // The GIF spec also specifies the lengths of the following two extensions' headers
            // (as 12 and 11 bytes, respectively). Because we ignore the plain text extension entirely
            // and sanity-check the actual length of the application extension header before reading it,
            // we allow GIFs to deviate from these values in either direction. This is important for
            // real-world compatibility, as GIFs in the wild exist with application extension headers
            // that are both shorter and longer than 11 bytes.
            case 0x01:
                // ignoring plain text extension
                break;

            case 0xff:
                exceptionState = SkGIFApplicationExtension;
                break;

            case 0xfe:
                exceptionState = SkGIFConsumeComment;
                break;
            }

            if (bytesInBlock)
                GETN(bytesInBlock, exceptionState);
            else
                GETN(1, SkGIFImageStart);
            break;
        }

        case SkGIFConsumeBlock: {
            const unsigned char currentComponent = this->getOneByte();
            if (!currentComponent)
                GETN(1, SkGIFImageStart);
            else
                GETN(currentComponent, SkGIFSkipBlock);
            break;
        }

        case SkGIFSkipBlock: {
            GETN(1, SkGIFConsumeBlock);
            break;
        }

        case SkGIFControlExtension: {
            const unsigned char* currentComponent =
                reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

            addFrameIfNecessary();
            SkGIFFrameContext* currentFrame = m_frames.back().get();
            if (*currentComponent & 0x1)
                currentFrame->setTransparentPixel(currentComponent[3]);

            // We ignore the "user input" bit.

            // NOTE: This relies on the values in the FrameDisposalMethod enum
            // matching those in the GIF spec!
            int rawDisposalMethod = ((*currentComponent) >> 2) & 0x7;
            switch (rawDisposalMethod) {
            case 1:
            case 2:
            case 3:
                currentFrame->setDisposalMethod((SkCodecAnimation::DisposalMethod) rawDisposalMethod);
                break;
            case 4:
                // Some specs say that disposal method 3 is "overwrite previous", others that setting
                // the third bit of the field (i.e. method 4) is. We map both to the same value.
                currentFrame->setDisposalMethod(SkCodecAnimation::DisposalMethod::kRestorePrevious);
                break;
            default:
                // Other values use the default.
                currentFrame->setDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep);
                break;
            }
            currentFrame->setDuration(GETINT16(currentComponent + 1) * 10);
            GETN(1, SkGIFConsumeBlock);
            break;
        }

        case SkGIFCommentExtension: {
            const unsigned char currentComponent = this->getOneByte();
            if (currentComponent)
                GETN(currentComponent, SkGIFConsumeComment);
            else
                GETN(1, SkGIFImageStart);
            break;
        }

        case SkGIFConsumeComment: {
            GETN(1, SkGIFCommentExtension);
            break;
        }

        case SkGIFApplicationExtension: {
            // Check for netscape application extension.
            if (m_bytesToConsume == 11) {
                const unsigned char* currentComponent =
                    reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

                if (!memcmp(currentComponent, "NETSCAPE2.0", 11) || !memcmp(currentComponent, "ANIMEXTS1.0", 11))
                    GETN(1, SkGIFNetscapeExtensionBlock);
            }

            if (m_state != SkGIFNetscapeExtensionBlock)
                GETN(1, SkGIFConsumeBlock);
            break;
        }

        // Netscape-specific GIF extension: animation looping.
        case SkGIFNetscapeExtensionBlock: {
            const int currentComponent = this->getOneByte();
            // SkGIFConsumeNetscapeExtension always reads 3 bytes from the stream; we should at least wait for this amount.
            if (currentComponent)
                GETN(std::max(3, currentComponent), SkGIFConsumeNetscapeExtension);
            else
                GETN(1, SkGIFImageStart);
            break;
        }

        // Parse netscape-specific application extensions
        case SkGIFConsumeNetscapeExtension: {
            const unsigned char* currentComponent =
                reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

            int netscapeExtension = currentComponent[0] & 7;

            // Loop entire animation specified # of times. Only read the loop count during the first iteration.
            if (netscapeExtension == 1) {
                m_loopCount = GETINT16(currentComponent + 1);

                // Zero loop count is infinite animation loop request.
                if (!m_loopCount)
                    m_loopCount = SkCodec::kRepetitionCountInfinite;

                GETN(1, SkGIFNetscapeExtensionBlock);

                if (SkGIFLoopCountQuery == query) {
                    m_streamBuffer.flush();
                    return SkCodec::kSuccess;
                }
            } else if (netscapeExtension == 2) {
                // Wait for specified # of bytes to enter buffer.

                // Don't do this, this extension doesn't exist (isn't used at all)
                // and doesn't do anything, as our streaming/buffering takes care of it all...
                // See: http://semmix.pl/color/exgraf/eeg24.htm
                GETN(1, SkGIFNetscapeExtensionBlock);
            } else {
                // 0,3-7 are yet to be defined netscape extension codes
                // This prevents attempting to continue reading this invalid stream.
                GETN(0, SkGIFDone);
                return SkCodec::kInvalidInput;
            }
            break;
        }

        case SkGIFImageHeader: {
            int height, width, xOffset, yOffset;
            const unsigned char* currentComponent =
                reinterpret_cast<const unsigned char*>(m_streamBuffer.get());

            /* Get image offsets, with respect to the screen origin */
            xOffset = GETINT16(currentComponent);
            yOffset = GETINT16(currentComponent + 2);

            /* Get image width and height. */
            width  = GETINT16(currentComponent + 4);
            height = GETINT16(currentComponent + 6);

            // Some GIF files have frames that don't fit in the specified
            // overall image size. For the first frame, we can simply enlarge
            // the image size to allow the frame to be visible.  We can't do
            // this on subsequent frames because the rest of the decoding
            // infrastructure assumes the image size won't change as we
            // continue decoding, so any subsequent frames that are even
            // larger will be cropped.
            // Luckily, handling just the first frame is sufficient to deal
            // with most cases, e.g. ones where the image size is erroneously
            // set to zero, since usually the first frame completely fills
            // the image.
            if (currentFrameIsFirstFrame()) {
                fScreenHeight = std::max(fScreenHeight, yOffset + height);
                fScreenWidth = std::max(fScreenWidth, xOffset + width);
            }

            // NOTE: Chromium placed this block after setHeaderDefined, down
            // below we returned true when asked for the size. So Chromium
            // created an image which would fail. Is this the correct behavior?
            // We choose to return false early, so we will not create an
            // SkCodec.

            // Work around more broken GIF files that have zero image width or
            // height.
            if (!height || !width) {
                height = fScreenHeight;
                width = fScreenWidth;
                if (!height || !width) {
                    // This prevents attempting to continue reading this invalid stream.
                    GETN(0, SkGIFDone);
                    return SkCodec::kInvalidInput;
                }
            }

            const bool isLocalColormapDefined = SkToBool(currentComponent[8] & 0x80);
            // The three low-order bits of currentComponent[8] specify the bits per pixel.
            const int numColors = 2 << (currentComponent[8] & 0x7);
            if (currentFrameIsFirstFrame()) {
                const int transPix = m_frames.empty() ? SkGIFColorMap::kNotFound
                                                      : m_frames[0]->transparentPixel();
                if (is_palette_index_valid(transPix)) {
                    m_firstFrameHasAlpha = true;
                } else {
                    const bool frameIsSubset = xOffset > 0 || yOffset > 0
                            || width < fScreenWidth
                            || height < fScreenHeight;
                    m_firstFrameHasAlpha = frameIsSubset;
                }
            }

            addFrameIfNecessary();
            SkGIFFrameContext* currentFrame = m_frames.back().get();
            currentFrame->setHeaderDefined();

            if (query == SkGIFSizeQuery) {
                // The decoder needs to stop, so we return here, before
                // flushing the buffer. Next time through, we'll be in the same
                // state, requiring the same amount in the buffer.
                return SkCodec::kSuccess;
            }


            currentFrame->setXYWH(xOffset, yOffset, width, height);
            currentFrame->setInterlaced(SkToBool(currentComponent[8] & 0x40));

            // Overlaying interlaced, transparent GIFs over
            // existing image data using the Haeberli display hack
            // requires saving the underlying image in order to
            // avoid jaggies at the transparency edges. We are
            // unprepared to deal with that, so don't display such
            // images progressively. Which means only the first
            // frame can be progressively displayed.
            // FIXME: It is possible that a non-transparent frame
            // can be interlaced and progressively displayed.
            currentFrame->setProgressiveDisplay(currentFrameIsFirstFrame());

            if (isLocalColormapDefined) {
                currentFrame->localColorMap().setNumColors(numColors);
                GETN(SK_BYTES_PER_COLORMAP_ENTRY * numColors, SkGIFImageColormap);
                break;
            }

            setAlphaAndRequiredFrame(currentFrame);
            GETN(1, SkGIFLZWStart);
            break;
        }

        case SkGIFImageColormap: {
            SkASSERT(!m_frames.empty());
            auto* currentFrame = m_frames.back().get();
            auto& cmap = currentFrame->localColorMap();
            cmap.setTablePosition(m_streamBuffer.markPosition());
            setAlphaAndRequiredFrame(currentFrame);
            GETN(1, SkGIFLZWStart);
            break;
        }

        case SkGIFSubBlock: {
            const size_t bytesInBlock = this->getOneByte();
            if (bytesInBlock)
                GETN(bytesInBlock, SkGIFLZW);
            else {
                // Finished parsing one frame; Process next frame.
                SkASSERT(!m_frames.empty());
                // Note that some broken GIF files do not have enough LZW blocks to fully
                // decode all rows but we treat it as frame complete.
                m_frames.back()->setComplete();
                GETN(1, SkGIFImageStart);
                if (lastFrameToParse >= 0 && m_frames.count() > lastFrameToParse) {
                    m_streamBuffer.flush();
                    return SkCodec::kSuccess;
                }
            }
            break;
        }

        case SkGIFDone: {
            m_parseCompleted = true;
            return SkCodec::kSuccess;
        }

        default:
            // We shouldn't ever get here.
            // This prevents attempting to continue reading this invalid stream.
            GETN(0, SkGIFDone);
            return SkCodec::kInvalidInput;
            break;
        }   // switch
        m_streamBuffer.flush();
    }
}

void SkGifImageReader::addFrameIfNecessary()
{
    if (m_frames.empty() || m_frames.back()->isComplete()) {
        const int i = m_frames.count();
        m_frames.emplace_back(new SkGIFFrameContext(i));
    }
}

static SkIRect frame_rect_on_screen(SkIRect frameRect,
                                    const SkIRect& screenRect) {
    if (!frameRect.intersect(screenRect)) {
        return SkIRect::MakeEmpty();
    }

    return frameRect;
}

static bool independent(const SkFrame& frame) {
    return frame.getRequiredFrame() == SkCodec::kNone;
}

static bool restore_bg(const SkFrame& frame) {
    return frame.getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestoreBGColor;
}

SkEncodedInfo::Alpha SkGIFFrameContext::onReportedAlpha() const {
    // Note: We could correct these after decoding - i.e. some frames may turn out to be
    // independent and opaque if they do not use the transparent pixel, but that would require
    // checking whether each pixel used the transparent index.
    return is_palette_index_valid(this->transparentPixel()) ? SkEncodedInfo::kBinary_Alpha
                                                            : SkEncodedInfo::kOpaque_Alpha;
}

void SkFrameHolder::setAlphaAndRequiredFrame(SkFrame* frame) {
    const bool reportsAlpha = frame->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha;
    const auto screenRect = SkIRect::MakeWH(fScreenWidth, fScreenHeight);
    const auto frameRect = frame_rect_on_screen(frame->frameRect(), screenRect);

    const int i = frame->frameId();
    if (0 == i) {
        frame->setHasAlpha(reportsAlpha || frameRect != screenRect);
        frame->setRequiredFrame(SkCodec::kNone);
        return;
    }


    const bool blendWithPrevFrame = frame->getBlend() == SkCodecAnimation::Blend::kPriorFrame;
    if ((!reportsAlpha || !blendWithPrevFrame) && frameRect == screenRect) {
        frame->setHasAlpha(reportsAlpha);
        frame->setRequiredFrame(SkCodec::kNone);
        return;
    }

    const SkFrame* prevFrame = this->getFrame(i-1);
    while (prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
        const int prevId = prevFrame->frameId();
        if (0 == prevId) {
            frame->setHasAlpha(true);
            frame->setRequiredFrame(SkCodec::kNone);
            return;
        }

        prevFrame = this->getFrame(prevId - 1);
    }

    const bool clearPrevFrame = restore_bg(*prevFrame);
    auto prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);

    if (clearPrevFrame) {
        if (prevFrameRect == screenRect || independent(*prevFrame)) {
            frame->setHasAlpha(true);
            frame->setRequiredFrame(SkCodec::kNone);
            return;
        }
    }

    if (reportsAlpha && blendWithPrevFrame) {
        // Note: We could be more aggressive here. If prevFrame clears
        // to background color and covers its required frame (and that
        // frame is independent), prevFrame could be marked independent.
        // Would this extra complexity be worth it?
        frame->setRequiredFrame(prevFrame->frameId());
        frame->setHasAlpha(prevFrame->hasAlpha() || clearPrevFrame);
        return;
    }

    while (frameRect.contains(prevFrameRect)) {
        const int prevRequiredFrame = prevFrame->getRequiredFrame();
        if (prevRequiredFrame == SkCodec::kNone) {
            frame->setRequiredFrame(SkCodec::kNone);
            frame->setHasAlpha(true);
            return;
        }

        prevFrame = this->getFrame(prevRequiredFrame);
        prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);
    }

    if (restore_bg(*prevFrame)) {
        frame->setHasAlpha(true);
        if (prevFrameRect == screenRect || independent(*prevFrame)) {
            frame->setRequiredFrame(SkCodec::kNone);
        } else {
            // Note: As above, frame could still be independent, e.g. if
            // prevFrame covers its required frame and that frame is
            // independent.
            frame->setRequiredFrame(prevFrame->frameId());
        }
        return;
    }

    SkASSERT(prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kKeep);
    frame->setRequiredFrame(prevFrame->frameId());
    frame->setHasAlpha(prevFrame->hasAlpha() || (reportsAlpha && !blendWithPrevFrame));
}

// FIXME: Move this method to close to doLZW().
bool SkGIFLZWContext::prepareToDecode()
{
    SkASSERT(m_frameContext->isDataSizeDefined() && m_frameContext->isHeaderDefined());

    // Since we use a codesize of 1 more than the datasize, we need to ensure
    // that our datasize is strictly less than the SK_MAX_DICTIONARY_ENTRY_BITS.
    if (m_frameContext->dataSize() >= SK_MAX_DICTIONARY_ENTRY_BITS)
        return false;
    clearCode = 1 << m_frameContext->dataSize();
    avail = clearCode + 2;
    oldcode = -1;
    codesize = m_frameContext->dataSize() + 1;
    codemask = (1 << codesize) - 1;
    datum = bits = 0;
    ipass = m_frameContext->interlaced() ? 1 : 0;
    irow = 0;

    // We want to know the longest sequence encodable by a dictionary with
    // SK_MAX_DICTIONARY_ENTRIES entries. If we ignore the need to encode the base
    // values themselves at the beginning of the dictionary, as well as the need
    // for a clear code or a termination code, we could use every entry to
    // encode a series of multiple values. If the input value stream looked
    // like "AAAAA..." (a long string of just one value), the first dictionary
    // entry would encode AA, the next AAA, the next AAAA, and so forth. Thus
    // the longest sequence would be SK_MAX_DICTIONARY_ENTRIES + 1 values.
    //
    // However, we have to account for reserved entries. The first |datasize|
    // bits are reserved for the base values, and the next two entries are
    // reserved for the clear code and termination code. In theory a GIF can
    // set the datasize to 0, meaning we have just two reserved entries, making
    // the longest sequence (SK_MAX_DICTIONARY_ENTIRES + 1) - 2 values long. Since
    // each value is a byte, this is also the number of bytes in the longest
    // encodable sequence.
    const size_t maxBytes = SK_MAX_DICTIONARY_ENTRIES - 1;

    // Now allocate the output buffer. We decode directly into this buffer
    // until we have at least one row worth of data, then call outputRow().
    // This means worst case we may have (row width - 1) bytes in the buffer
    // and then decode a sequence |maxBytes| long to append.
    rowBuffer.reset(m_frameContext->width() - 1 + maxBytes);
    rowIter = rowBuffer.begin();
    rowsRemaining = m_frameContext->height();

    // Clearing the whole suffix table lets us be more tolerant of bad data.
    for (int i = 0; i < clearCode; ++i) {
        suffix[i] = i;
        suffixLength[i] = 1;
    }
    return true;
}

