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

/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "SkCodecAnimation.h"
#include "SkCodecPriv.h"
#include "SkColorPriv.h"
#include "SkColorTable.h"
#include "SkGifCodec.h"
#include "SkStream.h"
#include "SkSwizzler.h"

#include <algorithm>

#define GIF87_STAMP "GIF87a"
#define GIF89_STAMP "GIF89a"
#define GIF_STAMP_LEN 6

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

/*
 * 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) {
    std::unique_ptr<SkGifImageReader> reader(new SkGifImageReader(stream));
    if (!reader->parse(SkGifImageReader::SkGIFSizeQuery)) {
        // Not enough data to determine the size.
        return nullptr;
    }

    if (0 == reader->screenWidth() || 0 == reader->screenHeight()) {
        return nullptr;
    }

    const auto alpha = reader->firstFrameHasAlpha() ? SkEncodedInfo::kBinary_Alpha
                                                    : SkEncodedInfo::kOpaque_Alpha;
    // Use kPalette since Gifs are encoded with a color table.
    // FIXME: Gifs can actually be encoded with 4-bits per pixel. Using 8 works, but we could skip
    //        expanding to 8 bits and take advantage of the SkSwizzler to work from 4.
    const auto encodedInfo = SkEncodedInfo::Make(SkEncodedInfo::kPalette_Color, alpha, 8);

    // Although the encodedInfo is always kPalette_Color, it is possible that kIndex_8 is
    // unsupported if the frame is subset and there is no transparent pixel.
    const auto colorType = reader->firstFrameSupportsIndex8() ? kIndex_8_SkColorType
                                                              : kN32_SkColorType;
    // The choice of unpremul versus premul is arbitrary, since all colors are either fully
    // opaque or fully transparent (i.e. kBinary), but we stored the transparent colors as all
    // zeroes, which is arguably premultiplied.
    const auto alphaType = reader->firstFrameHasAlpha() ? kUnpremul_SkAlphaType
                                                        : kOpaque_SkAlphaType;

    const auto imageInfo = SkImageInfo::Make(reader->screenWidth(), reader->screenHeight(),
                                             colorType, alphaType,
                                             SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named));
    return new SkGifCodec(encodedInfo, imageInfo, reader.release());
}

bool SkGifCodec::onRewind() {
    fReader->clearDecodeState();
    return true;
}

SkGifCodec::SkGifCodec(const SkEncodedInfo& encodedInfo, const SkImageInfo& imageInfo,
                       SkGifImageReader* reader)
    : INHERITED(encodedInfo, imageInfo, nullptr)
    , fReader(reader)
    , fTmpBuffer(nullptr)
    , fSwizzler(nullptr)
    , fCurrColorTable(nullptr)
    , fCurrColorTableIsReal(false)
    , fFilledBackground(false)
    , fFirstCallToIncrementalDecode(false)
    , fDst(nullptr)
    , fDstRowBytes(0)
    , fRowsDecoded(0)
{
    reader->setClient(this);
}

std::vector<SkCodec::FrameInfo> SkGifCodec::onGetFrameInfo() {
    fReader->parse(SkGifImageReader::SkGIFFrameCountQuery);
    const size_t size = fReader->imagesCount();
    std::vector<FrameInfo> result(size);
    for (size_t i = 0; i < size; i++) {
        const SkGIFFrameContext* frameContext = fReader->frameContext(i);
        result[i].fDuration = frameContext->delayTime();
        result[i].fRequiredFrame = frameContext->getRequiredFrame();
    }
    return result;
}

int SkGifCodec::onGetRepetitionCount() {
    fReader->parse(SkGifImageReader::SkGIFLoopCountQuery);
    return fReader->loopCount();
}

static const SkColorType kXformSrcColorType = kRGBA_8888_SkColorType;

void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex) {
    SkColorType colorTableColorType = dstInfo.colorType();
    if (this->colorXform()) {
        colorTableColorType = kXformSrcColorType;
    }

    sk_sp<SkColorTable> currColorTable = fReader->getColorTable(colorTableColorType, frameIndex);
    fCurrColorTableIsReal = currColorTable;
    if (!fCurrColorTableIsReal) {
        // This is possible for an empty frame. Create a dummy with one value (transparent).
        SkPMColor color = SK_ColorTRANSPARENT;
        fCurrColorTable.reset(new SkColorTable(&color, 1));
    } else if (this->colorXform() && !fXformOnDecode) {
        SkPMColor dstColors[256];
        const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
        const SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(kXformSrcColorType);
        const SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
                                                              this->getInfo().alphaType());
        SkAssertResult(this->colorXform()->apply(dstFormat, dstColors, srcFormat,
                                                 currColorTable->readColors(),
                                                 currColorTable->count(), xformAlphaType));
        fCurrColorTable.reset(new SkColorTable(dstColors, currColorTable->count()));
    } else {
        fCurrColorTable = std::move(currColorTable);
    }
}


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()) || !this->initializeColorXform(dstInfo)) {
        return gif_error("Cannot convert input type to output type.\n", kInvalidConversion);
    }

    fXformOnDecode = false;
    if (this->colorXform()) {
        fXformOnDecode = apply_xform_on_decode(dstInfo.colorType(), this->getEncodedInfo().color());
        if (fXformOnDecode) {
            fXformBuffer.reset(new uint32_t[dstInfo.width()]);
            sk_bzero(fXformBuffer.get(), dstInfo.width() * sizeof(uint32_t));
        }
    }

    if (opts.fSubset) {
        return gif_error("Subsets not supported.\n", kUnimplemented);
    }

    const size_t frameIndex = opts.fFrameIndex;
    if (frameIndex > 0) {
        switch (dstInfo.colorType()) {
            case kIndex_8_SkColorType:
                // FIXME: It is possible that a later frame can be decoded to index8, if it does one
                // of the following:
                // - Covers the entire previous frame
                // - Shares a color table (and transparent index) with any prior frames that are
                //   showing.
                // We must support index8 for the first frame to be backwards compatible on Android,
                // but we do not (currently) need to support later frames as index8.
                return gif_error("Cannot decode multiframe gif (except frame 0) as index 8.\n",
                                 kInvalidConversion);
            case kRGB_565_SkColorType:
                // FIXME: In theory, we might be able to support this, but it's not clear that it
                // is necessary (Chromium does not decode to 565, and Android does not decode
                // frames beyond the first). Disabling it because it is somewhat difficult:
                // - If there is a transparent pixel, and this frame draws on top of another frame
                //   (if the frame is independent with a transparent pixel, we should not decode to
                //   565 anyway, since it is not opaque), we need to skip drawing the transparent
                //   pixels (see writeTransparentPixels in haveDecodedRow). We currently do this by
                //   first swizzling into temporary memory, then copying into the destination. (We
                //   let the swizzler handle it first because it may need to sample.) After
                //   swizzling to 565, we do not know which pixels in our temporary memory
                //   correspond to the transparent pixel, so we do not know what to skip. We could
                //   special case the non-sampled case (no need to swizzle), but as this is
                //   currently unused we can just not support it.
                return gif_error("Cannot decode multiframe gif (except frame 0) as 565.\n",
                                 kInvalidConversion);
            default:
                break;
        }
    }

    fReader->parse((SkGifImageReader::SkGIFParseQuery) frameIndex);

    if (frameIndex >= fReader->imagesCount()) {
        return gif_error("frame index out of range!\n", kIncompleteInput);
    }

    fTmpBuffer.reset(new uint8_t[dstInfo.minRowBytes()]);

    this->initializeColorTable(dstInfo, frameIndex);
    this->initializeSwizzler(dstInfo, frameIndex);

    SkASSERT(fCurrColorTable);
    if (inputColorCount) {
        *inputColorCount = fCurrColorTable->count();
    }
    copy_color_table(dstInfo, fCurrColorTable.get(), inputColorPtr, inputColorCount);

    return kSuccess;
}

void SkGifCodec::initializeSwizzler(const SkImageInfo& dstInfo, size_t frameIndex) {
    const SkGIFFrameContext* frame = fReader->frameContext(frameIndex);
    // This is only called by prepareToDecode, which ensures frameIndex is in range.
    SkASSERT(frame);

    const int xBegin = frame->xOffset();
    const int xEnd = std::min(static_cast<int>(frame->xOffset() + frame->width()),
                              static_cast<int>(fReader->screenWidth()));

    // CreateSwizzler only reads left and right of the frame. We cannot use the frame's raw
    // frameRect, since it might extend beyond the edge of the frame.
    SkIRect swizzleRect = SkIRect::MakeLTRB(xBegin, 0, xEnd, 0);

    SkImageInfo swizzlerInfo = dstInfo;
    if (this->colorXform()) {
        swizzlerInfo = swizzlerInfo.makeColorType(kXformSrcColorType);
        if (kPremul_SkAlphaType == dstInfo.alphaType()) {
            swizzlerInfo = swizzlerInfo.makeAlphaType(kUnpremul_SkAlphaType);
        }
    }

    // The default Options should be fine:
    // - we'll ignore if the memory is zero initialized - unless we're the first frame, this won't
    //   matter anyway.
    // - subsets are not supported for gif
    // - the swizzler does not need to know about the frame.
    // We may not be able to use the real Options anyway, since getPixels does not store it (due to
    // a bug).
    fSwizzler.reset(SkSwizzler::CreateSwizzler(this->getEncodedInfo(),
                    fCurrColorTable->readColors(), swizzlerInfo, Options(), &swizzleRect));
    SkASSERT(fSwizzler.get());
}

/*
 * Initiates the gif decode
 */
SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
                                        void* pixels, 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);
    }

    fDst = pixels;
    fDstRowBytes = dstRowBytes;

    return this->decodeFrame(true, opts, rowsDecoded);
}

SkCodec::Result SkGifCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo,
                                                     void* pixels, size_t dstRowBytes,
                                                     const SkCodec::Options& opts,
                                                     SkPMColor* inputColorPtr,
                                                     int* inputColorCount) {
    Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, opts);
    if (result != kSuccess) {
        return result;
    }

    fDst = pixels;
    fDstRowBytes = dstRowBytes;

    fFirstCallToIncrementalDecode = true;

    return kSuccess;
}

SkCodec::Result SkGifCodec::onIncrementalDecode(int* rowsDecoded) {
    // It is possible the client has appended more data. Parse, if needed.
    const auto& options = this->options();
    const size_t frameIndex = options.fFrameIndex;
    fReader->parse((SkGifImageReader::SkGIFParseQuery) frameIndex);

    const bool firstCallToIncrementalDecode = fFirstCallToIncrementalDecode;
    fFirstCallToIncrementalDecode = false;
    return this->decodeFrame(firstCallToIncrementalDecode, options, rowsDecoded);
}

SkCodec::Result SkGifCodec::decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded) {
    const SkImageInfo& dstInfo = this->dstInfo();
    const size_t frameIndex = opts.fFrameIndex;
    SkASSERT(frameIndex < fReader->imagesCount());
    const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
    if (firstAttempt) {
        // rowsDecoded reports how many rows have been initialized, so a layer above
        // can fill the rest. In some cases, we fill the background before decoding
        // (or it is already filled for us), so we report rowsDecoded to be the full
        // height.
        bool filledBackground = false;
        if (frameContext->getRequiredFrame() == kNone) {
            // We may need to clear to transparent for one of the following reasons:
            // - The frameRect does not cover the full bounds. haveDecodedRow will
            //   only draw inside the frameRect, so we need to clear the rest.
            // - The frame is interlaced. There is no obvious way to fill
            //   afterwards for an incomplete image. (FIXME: Does the first pass
            //   cover all rows? If so, we do not have to fill here.)
            // - There is no color table for this frame. In that case will not
            //   draw anything, so we need to fill.
            if (frameContext->frameRect() != this->getInfo().bounds()
                    || frameContext->interlaced() || !fCurrColorTableIsReal) {
                // fill ignores the width (replaces it with the actual, scaled width).
                // But we need to scale in Y.
                const int scaledHeight = get_scaled_dimension(dstInfo.height(),
                                                              fSwizzler->sampleY());
                auto fillInfo = dstInfo.makeWH(0, scaledHeight);
                fSwizzler->fill(fillInfo, fDst, fDstRowBytes, this->getFillValue(dstInfo),
                                opts.fZeroInitialized);
                filledBackground = true;
            }
        } else {
            // Not independent
            if (!opts.fHasPriorFrame) {
                // Decode that frame into pixels.
                Options prevFrameOpts(opts);
                prevFrameOpts.fFrameIndex = frameContext->getRequiredFrame();
                prevFrameOpts.fHasPriorFrame = false;
                // The prior frame may have a different color table, so update it and the
                // swizzler.
                this->initializeColorTable(dstInfo, prevFrameOpts.fFrameIndex);
                this->initializeSwizzler(dstInfo, prevFrameOpts.fFrameIndex);

                const Result prevResult = this->decodeFrame(true, prevFrameOpts, nullptr);
                switch (prevResult) {
                    case kSuccess:
                        // Prior frame succeeded. Carry on.
                        break;
                    case kIncompleteInput:
                        // Prior frame was incomplete. So this frame cannot be decoded.
                        return kInvalidInput;
                    default:
                        return prevResult;
                }

                // Go back to using the correct color table for this frame.
                this->initializeColorTable(dstInfo, frameIndex);
                this->initializeSwizzler(dstInfo, frameIndex);
            }
            const auto* prevFrame = fReader->frameContext(frameContext->getRequiredFrame());
            if (prevFrame->getDisposalMethod() == SkCodecAnimation::RestoreBGColor_DisposalMethod) {
                const SkIRect prevRect = prevFrame->frameRect();
                auto left = get_scaled_dimension(prevRect.fLeft, fSwizzler->sampleX());
                auto top = get_scaled_dimension(prevRect.fTop, fSwizzler->sampleY());
                void* const eraseDst = SkTAddOffset<void>(fDst, top * fDstRowBytes
                        + left * SkColorTypeBytesPerPixel(dstInfo.colorType()));
                auto width = get_scaled_dimension(prevRect.width(), fSwizzler->sampleX());
                auto height = get_scaled_dimension(prevRect.height(), fSwizzler->sampleY());
                // fSwizzler->fill() would fill to the scaled width of the frame, but we want to
                // fill to the scaled with of the width of the PRIOR frame, so we do all the scaling
                // ourselves and call the static version.
                SkSampler::Fill(dstInfo.makeWH(width, height), eraseDst,
                                fDstRowBytes, this->getFillValue(dstInfo), kNo_ZeroInitialized);
            }
            filledBackground = true;
        }

        fFilledBackground = filledBackground;
        if (filledBackground) {
            // Report the full (scaled) height, since the client will never need to fill.
            fRowsDecoded = get_scaled_dimension(dstInfo.height(), fSwizzler->sampleY());
        } else {
            // This will be updated by haveDecodedRow.
            fRowsDecoded = 0;
        }
    }

    // Note: there is a difference between the following call to SkGifImageReader::decode
    // returning false and leaving frameDecoded false:
    // - If the method returns false, there was an error in the stream. We still treat this as
    //   incomplete, since we have already decoded some rows.
    // - If frameDecoded is false, that just means that we do not have enough data. If more data
    //   is supplied, we may be able to continue decoding this frame. We also treat this as
    //   incomplete.
    // FIXME: Ensure that we do not attempt to continue decoding if the method returns false and
    // more data is supplied.
    bool frameDecoded = false;
    if (!fReader->decode(frameIndex, &frameDecoded) || !frameDecoded) {
        if (rowsDecoded) {
            *rowsDecoded = fRowsDecoded;
        }
        return kIncompleteInput;
    }

    return kSuccess;
}

uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
    // Note: Using fCurrColorTable relies on having called initializeColorTable already.
    // This is (currently) safe because this method is only called when filling, after
    // initializeColorTable has been called.
    // FIXME: Is there a way to make this less fragile?
    if (dstInfo.colorType() == kIndex_8_SkColorType && fCurrColorTableIsReal) {
        // We only support index 8 for the first frame, for backwards
        // compatibity on Android, so we are using the color table for the first frame.
        SkASSERT(this->options().fFrameIndex == 0);
        // Use the transparent index for the first frame.
        const size_t transPixel = fReader->frameContext(0)->transparentPixel();
        if (transPixel < (size_t) fCurrColorTable->count()) {
            return transPixel;
        }
        // Fall through to return SK_ColorTRANSPARENT (i.e. 0). This choice is arbitrary,
        // but we have to pick something inside the color table, and this one is as good
        // as any.
    }
    // Using transparent as the fill value matches the behavior in Chromium,
    // which ignores the background color.
    // If the colorType is kIndex_8, and there was no color table (i.e.
    // fCurrColorTableIsReal is false), this value (zero) corresponds to the
    // only entry in the dummy color table provided to the client.
    return SK_ColorTRANSPARENT;
}

void SkGifCodec::applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const {
    if (this->colorXform() && fXformOnDecode) {
        fSwizzler->swizzle(fXformBuffer.get(), src);

        const SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
        const SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(kXformSrcColorType);
        const SkAlphaType xformAlphaType = select_xform_alpha(dstInfo.alphaType(),
                                                              this->getInfo().alphaType());
        const int xformWidth = get_scaled_dimension(dstInfo.width(), fSwizzler->sampleX());
        SkAssertResult(this->colorXform()->apply(dstFormat, dst, srcFormat, fXformBuffer.get(),
                                                 xformWidth, xformAlphaType));
    } else {
        fSwizzler->swizzle(dst, src);
    }
}

bool SkGifCodec::haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin,
                                size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels)
{
    const SkGIFFrameContext* frameContext = fReader->frameContext(frameIndex);
    // The pixel data and coordinates supplied to us are relative to the frame's
    // origin within the entire image size, i.e.
    // (frameContext->xOffset, frameContext->yOffset). There is no guarantee
    // that width == (size().width() - frameContext->xOffset), so
    // we must ensure we don't run off the end of either the source data or the
    // row's X-coordinates.
    const size_t width = frameContext->width();
    const int xBegin = frameContext->xOffset();
    const int yBegin = frameContext->yOffset() + rowNumber;
    const int xEnd = std::min(static_cast<int>(frameContext->xOffset() + width),
                              this->getInfo().width());
    const int yEnd = std::min(static_cast<int>(frameContext->yOffset() + rowNumber + repeatCount),
                              this->getInfo().height());
    // FIXME: No need to make the checks on width/xBegin/xEnd for every row. We could instead do
    // this once in prepareToDecode.
    if (!width || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
        return true;

    // yBegin is the first row in the non-sampled image. dstRow will be the row in the output,
    // after potentially scaling it.
    int dstRow = yBegin;

    const int sampleY = fSwizzler->sampleY();
    if (sampleY > 1) {
        // Check to see whether this row or one that falls in the repeatCount is needed in the
        // output.
        bool foundNecessaryRow = false;
        for (unsigned i = 0; i < repeatCount; i++) {
            const int potentialRow = yBegin + i;
            if (fSwizzler->rowNeeded(potentialRow)) {
                dstRow = potentialRow / sampleY;
                const int scaledHeight = get_scaled_dimension(this->dstInfo().height(), sampleY);
                if (dstRow >= scaledHeight) {
                    return true;
                }

                foundNecessaryRow = true;
                repeatCount -= i;

                repeatCount = (repeatCount - 1) / sampleY + 1;

                // Make sure the repeatCount does not take us beyond the end of the dst
                if (dstRow + (int) repeatCount > scaledHeight) {
                    repeatCount = scaledHeight - dstRow;
                    SkASSERT(repeatCount >= 1);
                }
                break;
            }
        }

        if (!foundNecessaryRow) {
            return true;
        }
    } else {
        // Make sure the repeatCount does not take us beyond the end of the dst
        SkASSERT(this->dstInfo().height() >= yBegin);
        repeatCount = SkTMin(repeatCount, (unsigned) (this->dstInfo().height() - yBegin));
    }

    if (!fFilledBackground) {
        // At this point, we are definitely going to write the row, so count it towards the number
        // of rows decoded.
        // We do not consider the repeatCount, which only happens for interlaced, in which case we
        // have already set fRowsDecoded to the proper value (reflecting that we have filled the
        // background).
        fRowsDecoded++;
    }

    if (!fCurrColorTableIsReal) {
        // No color table, so nothing to draw this frame.
        // FIXME: We can abort even earlier - no need to decode this frame.
        return true;
    }

    // The swizzler takes care of offsetting into the dst width-wise.
    void* dstLine = SkTAddOffset<void>(fDst, dstRow * fDstRowBytes);

    // We may or may not need to write transparent pixels to the buffer.
    // If we're compositing against a previous image, it's wrong, but if
    // we're decoding an interlaced gif and displaying it "Haeberli"-style,
    // we must write these for passes beyond the first, or the initial passes
    // will "show through" the later ones.
    const auto dstInfo = this->dstInfo();
    if (writeTransparentPixels) {
        this->applyXformRow(dstInfo, dstLine, rowBegin);
    } else {
        sk_bzero(fTmpBuffer.get(), dstInfo.minRowBytes());
        this->applyXformRow(dstInfo, fTmpBuffer.get(), rowBegin);

        const size_t offsetBytes = fSwizzler->swizzleOffsetBytes();
        switch (dstInfo.colorType()) {
            case kBGRA_8888_SkColorType:
            case kRGBA_8888_SkColorType: {
                uint32_t* dstPixel = SkTAddOffset<uint32_t>(dstLine, offsetBytes);
                uint32_t* srcPixel = SkTAddOffset<uint32_t>(fTmpBuffer.get(), offsetBytes);
                for (int i = 0; i < fSwizzler->swizzleWidth(); i++) {
                    // Technically SK_ColorTRANSPARENT is an SkPMColor, and srcPixel would have
                    // the opposite swizzle for the non-native swizzle, but TRANSPARENT is all
                    // zeroes, which is the same either way.
                    if (*srcPixel != SK_ColorTRANSPARENT) {
                        *dstPixel = *srcPixel;
                    }
                    dstPixel++;
                    srcPixel++;
                }
                break;
            }
            case kRGBA_F16_SkColorType: {
                uint64_t* dstPixel = SkTAddOffset<uint64_t>(dstLine, offsetBytes);
                uint64_t* srcPixel = SkTAddOffset<uint64_t>(fTmpBuffer.get(), offsetBytes);
                for (int i = 0; i < fSwizzler->swizzleWidth(); i++) {
                    if (*srcPixel != 0) {
                        *dstPixel = *srcPixel;
                    }
                    dstPixel++;
                    srcPixel++;
                }
                break;
            }
            default:
                SkASSERT(false);
                break;
        }
    }

    // Tell the frame to copy the row data if need be.
    if (repeatCount > 1) {
        const size_t bytesPerPixel = SkColorTypeBytesPerPixel(this->dstInfo().colorType());
        const size_t bytesToCopy = fSwizzler->swizzleWidth() * bytesPerPixel;
        void* copiedLine = SkTAddOffset<void>(dstLine, fSwizzler->swizzleOffsetBytes());
        void* dst = copiedLine;
        for (unsigned i = 1; i < repeatCount; i++) {
            dst = SkTAddOffset<void>(dst, fDstRowBytes);
            memcpy(dst, copiedLine, bytesToCopy);
        }
    }

    return true;
}
