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

#include "include/codec/SkCodec.h"
#include "include/codec/SkCodecAnimation.h"
#include "include/codec/SkEncodedImageFormat.h"
#include "include/codec/SkGifDecoder.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "include/private/SkEncodedInfo.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTo.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkFrameHolder.h"
#include "src/codec/SkSampler.h"
#include "src/codec/SkScalingCodec.h"
#include "src/core/SkDraw.h"
#include "src/core/SkMipmap.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkStreamPriv.h"

#include <climits>
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>
#include <vector>

// Documentation on the Wuffs language and standard library (in general) and
// its image decoding API (in particular) is at:
//
//  - https://github.com/google/wuffs/tree/master/doc
//  - https://github.com/google/wuffs/blob/master/doc/std/image-decoders.md

// Wuffs ships as a "single file C library" or "header file library" as per
// https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
//
// As we have not #define'd WUFFS_IMPLEMENTATION, the #include here is
// including a header file, even though that file name ends in ".c".
#if defined(WUFFS_IMPLEMENTATION)
#error "SkWuffsCodec should not #define WUFFS_IMPLEMENTATION"
#endif
#include "wuffs-v0.3.c"  // NO_G3_REWRITE
// Commit count 2514 is Wuffs 0.3.0-alpha.4.
#if WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT < 2514
#error "Wuffs version is too old. Upgrade to the latest version."
#endif

#define SK_WUFFS_CODEC_BUFFER_SIZE 4096

// Configuring a Skia build with
// SK_WUFFS_FAVORS_PERFORMANCE_OVER_ADDITIONAL_MEMORY_SAFETY can improve decode
// performance by some fixed amount (independent of the image size), which can
// be a noticeable proportional improvement if the input is relatively small.
//
// The Wuffs library is still memory-safe either way, in that there are no
// out-of-bounds reads or writes, and the library endeavours not to read
// uninitialized memory. There are just fewer compiler-enforced guarantees
// against reading uninitialized memory. For more detail, see
// https://github.com/google/wuffs/blob/master/doc/note/initialization.md#partial-zero-initialization
#if defined(SK_WUFFS_FAVORS_PERFORMANCE_OVER_ADDITIONAL_MEMORY_SAFETY)
#define SK_WUFFS_INITIALIZE_FLAGS WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED
#else
#define SK_WUFFS_INITIALIZE_FLAGS WUFFS_INITIALIZE__DEFAULT_OPTIONS
#endif

static bool fill_buffer(wuffs_base__io_buffer* b, SkStream* s) {
    b->compact();
    size_t num_read = s->read(b->data.ptr + b->meta.wi, b->data.len - b->meta.wi);
    b->meta.wi += num_read;
    // We hard-code false instead of s->isAtEnd(). In theory, Skia's
    // SkStream::isAtEnd() method has the same semantics as Wuffs'
    // wuffs_base__io_buffer_meta::closed field. Specifically, both are false
    // when reading from a network socket when all bytes *available right now*
    // have been read but there might be more later.
    //
    // However, SkStream is designed around synchronous I/O. The SkStream::read
    // method does not take a callback and, per its documentation comments, a
    // read request for N bytes should block until a full N bytes are
    // available. In practice, Blink's SkStream subclass builds on top of async
    // I/O and cannot afford to block. While it satisfies "the letter of the
    // law", in terms of what the C++ compiler needs, it does not satisfy "the
    // spirit of the law". Its read() can return short without blocking and its
    // isAtEnd() can return false positives.
    //
    // When closed is true, Wuffs treats incomplete input as a fatal error
    // instead of a recoverable "short read" suspension. We therefore hard-code
    // false and return kIncompleteInput (instead of kErrorInInput) up the call
    // stack even if the SkStream isAtEnd. The caller usually has more context
    // (more than what's in the SkStream) to differentiate the two, like this:
    // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc;l=115;drc=277dcc4d810ae4c0286d8af96d270ed9b686c5ff
    b->meta.closed = false;
    return num_read > 0;
}

static bool seek_buffer(wuffs_base__io_buffer* b, SkStream* s, uint64_t pos) {
    // Try to re-position the io_buffer's meta.ri read-index first, which is
    // cheaper than seeking in the backing SkStream.
    if ((pos >= b->meta.pos) && (pos - b->meta.pos <= b->meta.wi)) {
        b->meta.ri = pos - b->meta.pos;
        return true;
    }
    // Seek in the backing SkStream.
    if ((pos > SIZE_MAX) || (!s->seek(pos))) {
        return false;
    }
    b->meta.wi = 0;
    b->meta.ri = 0;
    b->meta.pos = pos;
    b->meta.closed = false;
    return true;
}

static SkCodecAnimation::DisposalMethod wuffs_disposal_to_skia_disposal(
    wuffs_base__animation_disposal w) {
    switch (w) {
        case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND:
            return SkCodecAnimation::DisposalMethod::kRestoreBGColor;
        case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS:
            return SkCodecAnimation::DisposalMethod::kRestorePrevious;
        default:
            return SkCodecAnimation::DisposalMethod::kKeep;
    }
}

static SkAlphaType to_alpha_type(bool opaque) {
    return opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
}

static SkCodec::Result reset_and_decode_image_config(wuffs_gif__decoder*       decoder,
                                                     wuffs_base__image_config* imgcfg,
                                                     wuffs_base__io_buffer*    b,
                                                     SkStream*                 s) {
    // Calling decoder->initialize will memset most or all of it to zero,
    // depending on SK_WUFFS_INITIALIZE_FLAGS.
    wuffs_base__status status =
        decoder->initialize(sizeof__wuffs_gif__decoder(), WUFFS_VERSION, SK_WUFFS_INITIALIZE_FLAGS);
    if (status.repr != nullptr) {
        SkCodecPrintf("initialize: %s", status.message());
        return SkCodec::kInternalError;
    }

    // See https://bugs.chromium.org/p/skia/issues/detail?id=12055
    decoder->set_quirk_enabled(WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA, true);

    while (true) {
        status = decoder->decode_image_config(imgcfg, b);
        if (status.repr == nullptr) {
            break;
        } else if (status.repr != wuffs_base__suspension__short_read) {
            SkCodecPrintf("decode_image_config: %s", status.message());
            return SkCodec::kErrorInInput;
        } else if (!fill_buffer(b, s)) {
            return SkCodec::kIncompleteInput;
        }
    }

    // A GIF image's natural color model is indexed color: 1 byte per pixel,
    // indexing a 256-element palette.
    //
    // For Skia, we override that to decode to 4 bytes per pixel, BGRA or RGBA.
    uint32_t pixfmt = WUFFS_BASE__PIXEL_FORMAT__INVALID;
    switch (kN32_SkColorType) {
        case kBGRA_8888_SkColorType:
            pixfmt = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
            break;
        case kRGBA_8888_SkColorType:
            pixfmt = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
            break;
        default:
            return SkCodec::kInternalError;
    }
    if (imgcfg) {
        imgcfg->pixcfg.set(pixfmt, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, imgcfg->pixcfg.width(),
                           imgcfg->pixcfg.height());
    }

    return SkCodec::kSuccess;
}

// -------------------------------- Class definitions

class SkWuffsCodec;

class SkWuffsFrame final : public SkFrame {
public:
    SkWuffsFrame(wuffs_base__frame_config* fc);

    uint64_t ioPosition() const;

    // SkFrame overrides.
    SkEncodedInfo::Alpha onReportedAlpha() const override;

private:
    uint64_t             fIOPosition;
    SkEncodedInfo::Alpha fReportedAlpha;

    using INHERITED = SkFrame;
};

// SkWuffsFrameHolder is a trivial indirector that forwards its calls onto a
// SkWuffsCodec. It is a separate class as SkWuffsCodec would otherwise
// inherit from both SkCodec and SkFrameHolder, and Skia style discourages
// multiple inheritance (e.g. with its "typedef Foo INHERITED" convention).
class SkWuffsFrameHolder final : public SkFrameHolder {
public:
    SkWuffsFrameHolder() : INHERITED() {}

    void init(SkWuffsCodec* codec, int width, int height);

    // SkFrameHolder overrides.
    const SkFrame* onGetFrame(int i) const override;

private:
    const SkWuffsCodec* fCodec;

    using INHERITED = SkFrameHolder;
};

class SkWuffsCodec final : public SkScalingCodec {
public:
    SkWuffsCodec(SkEncodedInfo&&                                         encodedInfo,
                 std::unique_ptr<SkStream>                               stream,
                 bool                                                    canSeek,
                 std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> dec,
                 std::unique_ptr<uint8_t, decltype(&sk_free)>            workbuf_ptr,
                 size_t                                                  workbuf_len,
                 wuffs_base__image_config                                imgcfg,
                 wuffs_base__io_buffer                                   iobuf);

    const SkWuffsFrame* frame(int i) const;

    std::unique_ptr<SkStream> getEncodedData() const override;

private:
    // SkCodec overrides.
    SkEncodedImageFormat onGetEncodedFormat() const override;
    Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, int*) override;
    const SkFrameHolder* getFrameHolder() const override;
    bool                 onSupportsIncrementalDecode(const SkImageInfo&) override { return true; }
    Result               onStartIncrementalDecode(const SkImageInfo&      dstInfo,
                                                  void*                   dst,
                                                  size_t                  rowBytes,
                                                  const SkCodec::Options& options) override;
    Result               onIncrementalDecode(int* rowsDecoded) override;
    int                  onGetFrameCount() override;
    bool                 onGetFrameInfo(int, FrameInfo*) const override;
    int                  onGetRepetitionCount() override;
    IsAnimated           onIsAnimated() override;

    // Two separate implementations of onStartIncrementalDecode and
    // onIncrementalDecode, named "one pass" and "two pass" decoding. One pass
    // decoding writes directly from the Wuffs image decoder to the dst buffer
    // (the dst argument to onStartIncrementalDecode). Two pass decoding first
    // writes into an intermediate buffer, and then composites and transforms
    // the intermediate buffer into the dst buffer.
    //
    // In the general case, we need the two pass decoder, because of Skia API
    // features that Wuffs doesn't support (e.g. color correction, scaling,
    // RGB565). But as an optimization, we use one pass decoding (it's faster
    // and uses less memory) if applicable (see the assignment to
    // fIncrDecOnePass that calculates when we can do so).
    Result onStartIncrementalDecodeOnePass(const SkImageInfo&      dstInfo,
                                           uint8_t*                dst,
                                           size_t                  rowBytes,
                                           const SkCodec::Options& options,
                                           uint32_t                pixelFormat,
                                           size_t                  bytesPerPixel);
    Result onStartIncrementalDecodeTwoPass();
    Result onIncrementalDecodeOnePass();
    Result onIncrementalDecodeTwoPass();

    void        onGetFrameCountInternal();
    Result      seekFrame(int frameIndex);
    Result      resetDecoder();
    const char* decodeFrameConfig();
    const char* decodeFrame();
    void        updateNumFullyReceivedFrames();

    SkWuffsFrameHolder                           fFrameHolder;
    std::unique_ptr<SkStream>                    fPrivStream;
    std::unique_ptr<uint8_t, decltype(&sk_free)> fWorkbufPtr;
    size_t                                       fWorkbufLen;

    std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> fDecoder;

    const uint64_t           fFirstFrameIOPosition;
    wuffs_base__frame_config fFrameConfig;
    wuffs_base__pixel_config fPixelConfig;
    wuffs_base__pixel_buffer fPixelBuffer;
    wuffs_base__io_buffer    fIOBuffer;

    // Incremental decoding state.
    uint8_t*                fIncrDecDst;
    size_t                  fIncrDecRowBytes;
    wuffs_base__pixel_blend fIncrDecPixelBlend;
    bool                    fIncrDecOnePass;
    bool                    fFirstCallToIncrementalDecode;

    // Lazily allocated intermediate pixel buffer, for two pass decoding.
    std::unique_ptr<uint8_t, decltype(&sk_free)> fTwoPassPixbufPtr;
    size_t                                       fTwoPassPixbufLen;

    uint64_t                  fNumFullyReceivedFrames;
    std::vector<SkWuffsFrame> fFrames;
    bool                      fFramesComplete;

    // If calling an fDecoder method returns an incomplete status, then
    // fDecoder is suspended in a coroutine (i.e. waiting on I/O or halted on a
    // non-recoverable error). To keep its internal proof-of-safety invariants
    // consistent, there's only two things you can safely do with a suspended
    // Wuffs object: resume the coroutine, or reset all state (memset to zero
    // and start again).
    //
    // If fDecoderIsSuspended, and we aren't sure that we're going to resume
    // the coroutine, then we will need to call this->resetDecoder before
    // calling other fDecoder methods.
    bool fDecoderIsSuspended;

    uint8_t fBuffer[SK_WUFFS_CODEC_BUFFER_SIZE];

    const bool fCanSeek;

    using INHERITED = SkScalingCodec;
};

// -------------------------------- SkWuffsFrame implementation

SkWuffsFrame::SkWuffsFrame(wuffs_base__frame_config* fc)
    : INHERITED(fc->index()),
      fIOPosition(fc->io_position()),
      fReportedAlpha(fc->opaque_within_bounds() ? SkEncodedInfo::kOpaque_Alpha
                                                : SkEncodedInfo::kUnpremul_Alpha) {
    wuffs_base__rect_ie_u32 r = fc->bounds();
    this->setXYWH(r.min_incl_x, r.min_incl_y, r.width(), r.height());
    this->setDisposalMethod(wuffs_disposal_to_skia_disposal(fc->disposal()));
    this->setDuration(fc->duration() / WUFFS_BASE__FLICKS_PER_MILLISECOND);
    this->setBlend(fc->overwrite_instead_of_blend() ? SkCodecAnimation::Blend::kSrc
                                                    : SkCodecAnimation::Blend::kSrcOver);
}

uint64_t SkWuffsFrame::ioPosition() const {
    return fIOPosition;
}

SkEncodedInfo::Alpha SkWuffsFrame::onReportedAlpha() const {
    return fReportedAlpha;
}

// -------------------------------- SkWuffsFrameHolder implementation

void SkWuffsFrameHolder::init(SkWuffsCodec* codec, int width, int height) {
    fCodec = codec;
    // Initialize SkFrameHolder's (the superclass) fields.
    fScreenWidth = width;
    fScreenHeight = height;
}

const SkFrame* SkWuffsFrameHolder::onGetFrame(int i) const {
    return fCodec->frame(i);
}

// -------------------------------- SkWuffsCodec implementation

SkWuffsCodec::SkWuffsCodec(SkEncodedInfo&& encodedInfo,
                           std::unique_ptr<SkStream> stream,
                           bool canSeek,
                           std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> dec,
                           std::unique_ptr<uint8_t, decltype(&sk_free)> workbuf_ptr,
                           size_t workbuf_len,
                           wuffs_base__image_config imgcfg,
                           wuffs_base__io_buffer iobuf)
        : INHERITED(std::move(encodedInfo),
                    skcms_PixelFormat_RGBA_8888,
                    // Pass a nullptr SkStream to the SkCodec constructor. We
                    // manage the stream ourselves, as the default SkCodec behavior
                    // is too trigger-happy on rewinding the stream.
                    //
                    // TODO(https://crbug.com/370522089): See if `SkCodec` can be
                    // tweaked to avoid the need to hide the stream from it.
                    nullptr)
        , fFrameHolder()
        , fPrivStream(std::move(stream))
        , fWorkbufPtr(std::move(workbuf_ptr))
        , fWorkbufLen(workbuf_len)
        , fDecoder(std::move(dec))
        , fFirstFrameIOPosition(imgcfg.first_frame_io_position())
        , fFrameConfig(wuffs_base__null_frame_config())
        , fPixelConfig(imgcfg.pixcfg)
        , fPixelBuffer(wuffs_base__null_pixel_buffer())
        , fIOBuffer(wuffs_base__empty_io_buffer())
        , fIncrDecDst(nullptr)
        , fIncrDecRowBytes(0)
        , fIncrDecPixelBlend(WUFFS_BASE__PIXEL_BLEND__SRC)
        , fIncrDecOnePass(false)
        , fFirstCallToIncrementalDecode(false)
        , fTwoPassPixbufPtr(nullptr, &sk_free)
        , fTwoPassPixbufLen(0)
        , fNumFullyReceivedFrames(0)
        , fFramesComplete(false)
        , fDecoderIsSuspended(false)
        , fCanSeek(canSeek) {
    fFrameHolder.init(this, imgcfg.pixcfg.width(), imgcfg.pixcfg.height());

    // Initialize fIOBuffer's fields, copying any outstanding data from iobuf to
    // fIOBuffer, as iobuf's backing array may not be valid for the lifetime of
    // this SkWuffsCodec object, but fIOBuffer's backing array (fBuffer) is.
    SkASSERT(iobuf.data.len == SK_WUFFS_CODEC_BUFFER_SIZE);
    memmove(fBuffer, iobuf.data.ptr, iobuf.meta.wi);
    fIOBuffer.data = wuffs_base__make_slice_u8(fBuffer, SK_WUFFS_CODEC_BUFFER_SIZE);
    fIOBuffer.meta = iobuf.meta;
}

const SkWuffsFrame* SkWuffsCodec::frame(int i) const {
    if ((0 <= i) && (static_cast<size_t>(i) < fFrames.size())) {
        return &fFrames[i];
    }
    return nullptr;
}

SkEncodedImageFormat SkWuffsCodec::onGetEncodedFormat() const {
    return SkEncodedImageFormat::kGIF;
}

SkCodec::Result SkWuffsCodec::onGetPixels(const SkImageInfo& dstInfo,
                                          void*              dst,
                                          size_t             rowBytes,
                                          const Options&     options,
                                          int*               rowsDecoded) {
    SkCodec::Result result = this->onStartIncrementalDecode(dstInfo, dst, rowBytes, options);
    if (result != kSuccess) {
        return result;
    }
    return this->onIncrementalDecode(rowsDecoded);
}

const SkFrameHolder* SkWuffsCodec::getFrameHolder() const {
    return &fFrameHolder;
}

SkCodec::Result SkWuffsCodec::onStartIncrementalDecode(const SkImageInfo&      dstInfo,
                                                       void*                   dst,
                                                       size_t                  rowBytes,
                                                       const SkCodec::Options& options) {
    if (!dst) {
        return SkCodec::kInvalidParameters;
    }
    if (options.fSubset) {
        return SkCodec::kUnimplemented;
    }
    SkCodec::Result result = this->seekFrame(options.fFrameIndex);
    if (result != SkCodec::kSuccess) {
        return result;
    }

    const char* status = this->decodeFrameConfig();
    if (status == wuffs_base__suspension__short_read) {
        return SkCodec::kIncompleteInput;
    } else if (status != nullptr) {
        SkCodecPrintf("decodeFrameConfig: %s", status);
        return SkCodec::kErrorInInput;
    }

    uint32_t pixelFormat = WUFFS_BASE__PIXEL_FORMAT__INVALID;
    size_t   bytesPerPixel = 0;

    switch (dstInfo.colorType()) {
        case kRGB_565_SkColorType:
            pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGR_565;
            bytesPerPixel = 2;
            break;
        case kBGRA_8888_SkColorType:
            pixelFormat = WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL;
            bytesPerPixel = 4;
            break;
        case kRGBA_8888_SkColorType:
            pixelFormat = WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL;
            bytesPerPixel = 4;
            break;
        default:
            break;
    }

    // We can use "one pass" decoding if we have a Skia pixel format that Wuffs
    // supports...
    fIncrDecOnePass = (pixelFormat != WUFFS_BASE__PIXEL_FORMAT__INVALID) &&
                      // ...and no color profile (as Wuffs does not support them)...
                      (!getEncodedInfo().colorProfile()) &&
                      // ...and we use the identity transform (as Wuffs does
                      // not support scaling).
                      (this->dimensions() == dstInfo.dimensions());

    result = fIncrDecOnePass ? this->onStartIncrementalDecodeOnePass(
                                   dstInfo, static_cast<uint8_t*>(dst), rowBytes, options,
                                   pixelFormat, bytesPerPixel)
                             : this->onStartIncrementalDecodeTwoPass();
    if (result != SkCodec::kSuccess) {
        return result;
    }

    fIncrDecDst = static_cast<uint8_t*>(dst);
    fIncrDecRowBytes = rowBytes;
    fFirstCallToIncrementalDecode = true;
    return SkCodec::kSuccess;
}

SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeOnePass(const SkImageInfo&      dstInfo,
                                                              uint8_t*                dst,
                                                              size_t                  rowBytes,
                                                              const SkCodec::Options& options,
                                                              uint32_t                pixelFormat,
                                                              size_t bytesPerPixel) {
    wuffs_base__pixel_config pixelConfig;
    pixelConfig.set(pixelFormat, WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, dstInfo.width(),
                    dstInfo.height());

    wuffs_base__table_u8 table;
    table.ptr = dst;
    table.width = static_cast<size_t>(dstInfo.width()) * bytesPerPixel;
    table.height = dstInfo.height();
    table.stride = rowBytes;

    wuffs_base__status status = fPixelBuffer.set_from_table(&pixelConfig, table);
    if (status.repr != nullptr) {
        SkCodecPrintf("set_from_table: %s", status.message());
        return SkCodec::kInternalError;
    }

    // SRC is usually faster than SRC_OVER, but for a dependent frame, dst is
    // assumed to hold the previous frame's pixels (after processing the
    // DisposalMethod). For one-pass decoding, we therefore use SRC_OVER.
    if ((options.fFrameIndex != 0) &&
        (this->frame(options.fFrameIndex)->getRequiredFrame() != SkCodec::kNoFrame)) {
        fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC_OVER;
    } else {
        SkSampler::Fill(dstInfo, dst, rowBytes, options.fZeroInitialized);
        fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
    }

    return SkCodec::kSuccess;
}

SkCodec::Result SkWuffsCodec::onStartIncrementalDecodeTwoPass() {
    // Either re-use the previously allocated "two pass" pixel buffer (and
    // memset to zero), or allocate (and zero initialize) a new one.
    bool already_zeroed = false;

    if (!fTwoPassPixbufPtr) {
        uint64_t pixbuf_len = fPixelConfig.pixbuf_len();
        void*    pixbuf_ptr_raw = (pixbuf_len <= SIZE_MAX)
                                      ? sk_malloc_flags(pixbuf_len, SK_MALLOC_ZERO_INITIALIZE)
                                      : nullptr;
        if (!pixbuf_ptr_raw) {
            return SkCodec::kInternalError;
        }
        fTwoPassPixbufPtr.reset(reinterpret_cast<uint8_t*>(pixbuf_ptr_raw));
        fTwoPassPixbufLen = SkToSizeT(pixbuf_len);
        already_zeroed = true;
    }

    wuffs_base__status status = fPixelBuffer.set_from_slice(
        &fPixelConfig, wuffs_base__make_slice_u8(fTwoPassPixbufPtr.get(), fTwoPassPixbufLen));
    if (status.repr != nullptr) {
        SkCodecPrintf("set_from_slice: %s", status.message());
        return SkCodec::kInternalError;
    }

    if (!already_zeroed) {
        uint32_t src_bits_per_pixel = fPixelConfig.pixel_format().bits_per_pixel();
        if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
            return SkCodec::kInternalError;
        }
        size_t src_bytes_per_pixel = src_bits_per_pixel / 8;

        wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
        wuffs_base__table_u8    pixels = fPixelBuffer.plane(0);

        uint8_t* ptr = pixels.ptr + (frame_rect.min_incl_y * pixels.stride) +
                       (frame_rect.min_incl_x * src_bytes_per_pixel);
        size_t len = frame_rect.width() * src_bytes_per_pixel;

        // As an optimization, issue a single sk_bzero call, if possible.
        // Otherwise, zero out each row separately.
        if ((len == pixels.stride) && (frame_rect.min_incl_y < frame_rect.max_excl_y)) {
            sk_bzero(ptr, len * (frame_rect.max_excl_y - frame_rect.min_incl_y));
        } else {
            for (uint32_t y = frame_rect.min_incl_y; y < frame_rect.max_excl_y; y++) {
                sk_bzero(ptr, len);
                ptr += pixels.stride;
            }
        }
    }

    fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
    return SkCodec::kSuccess;
}

SkCodec::Result SkWuffsCodec::onIncrementalDecode(int* rowsDecoded) {
    if (!fIncrDecDst) {
        return SkCodec::kInternalError;
    }

    if (rowsDecoded) {
        *rowsDecoded = dstInfo().height();
    }

    SkCodec::Result result =
        fIncrDecOnePass ? this->onIncrementalDecodeOnePass() : this->onIncrementalDecodeTwoPass();
    if (result == SkCodec::kSuccess) {
        fIncrDecDst = nullptr;
        fIncrDecRowBytes = 0;
        fIncrDecPixelBlend = WUFFS_BASE__PIXEL_BLEND__SRC;
        fIncrDecOnePass = false;
    }
    return result;
}

SkCodec::Result SkWuffsCodec::onIncrementalDecodeOnePass() {
    const char* status = this->decodeFrame();
    if (status != nullptr) {
        if (status == wuffs_base__suspension__short_read) {
            return SkCodec::kIncompleteInput;
        } else {
            SkCodecPrintf("decodeFrame: %s", status);
            return SkCodec::kErrorInInput;
        }
    }
    return SkCodec::kSuccess;
}

SkCodec::Result SkWuffsCodec::onIncrementalDecodeTwoPass() {
    SkCodec::Result result = SkCodec::kSuccess;
    const char*     status = this->decodeFrame();
    bool            independent;
    SkAlphaType     alphaType;
    const int       index = options().fFrameIndex;
    if (index == 0) {
        independent = true;
        alphaType = to_alpha_type(getEncodedInfo().opaque());
    } else {
        const SkWuffsFrame* f = this->frame(index);
        independent = f->getRequiredFrame() == SkCodec::kNoFrame;
        alphaType = to_alpha_type(f->reportedAlpha() == SkEncodedInfo::kOpaque_Alpha);
    }
    if (status != nullptr) {
        if (status == wuffs_base__suspension__short_read) {
            result = SkCodec::kIncompleteInput;
        } else {
            SkCodecPrintf("decodeFrame: %s", status);
            result = SkCodec::kErrorInInput;
        }

        if (!independent) {
            // For a dependent frame, we cannot blend the partial result, since
            // that will overwrite the contribution from prior frames.
            return result;
        }
    }

    uint32_t src_bits_per_pixel = fPixelBuffer.pixcfg.pixel_format().bits_per_pixel();
    if ((src_bits_per_pixel == 0) || (src_bits_per_pixel % 8 != 0)) {
        return SkCodec::kInternalError;
    }
    size_t src_bytes_per_pixel = src_bits_per_pixel / 8;

    wuffs_base__rect_ie_u32 frame_rect = fFrameConfig.bounds();
    if (fFirstCallToIncrementalDecode) {
        if (frame_rect.width() > (SIZE_MAX / src_bytes_per_pixel)) {
            return SkCodec::kInternalError;
        }

        auto bounds = SkIRect::MakeLTRB(frame_rect.min_incl_x, frame_rect.min_incl_y,
                                        frame_rect.max_excl_x, frame_rect.max_excl_y);

        // If the frame rect does not fill the output, ensure that those pixels are not
        // left uninitialized.
        if (independent && (bounds != this->bounds() || result != kSuccess)) {
            SkSampler::Fill(dstInfo(), fIncrDecDst, fIncrDecRowBytes, options().fZeroInitialized);
        }
        fFirstCallToIncrementalDecode = false;
    } else {
        // Existing clients intend to only show frames beyond the first if they
        // are complete (based on FrameInfo::fFullyReceived), since it might
        // look jarring to draw a partial frame over an existing frame. If they
        // changed their behavior and expected to continue decoding a partial
        // frame after the first one, we'll need to update our blending code.
        // Otherwise, if the frame were interlaced and not independent, the
        // second pass may have an overlapping dirty_rect with the first,
        // resulting in blending with the first pass.
        SkASSERT(index == 0);
    }

    // If the frame's dirty rect is empty, no need to swizzle.
    wuffs_base__rect_ie_u32 dirty_rect = fDecoder->frame_dirty_rect();
    if (!dirty_rect.is_empty()) {
        wuffs_base__table_u8 pixels = fPixelBuffer.plane(0);

        // The Wuffs model is that the dst buffer is the image, not the frame.
        // The expectation is that you allocate the buffer once, but re-use it
        // for the N frames, regardless of each frame's top-left co-ordinate.
        //
        // To get from the start (in the X-direction) of the image to the start
        // of the dirty_rect, we adjust s by (dirty_rect.min_incl_x * src_bytes_per_pixel).
        uint8_t* s = pixels.ptr + (dirty_rect.min_incl_y * pixels.stride) +
                     (dirty_rect.min_incl_x * src_bytes_per_pixel);

        // Currently, this is only used for GIF, which will never have an ICC profile. When it is
        // used for other formats that might have one, we will need to transform from profiles that
        // do not have corresponding SkColorSpaces.
        SkASSERT(!getEncodedInfo().colorProfile());

        auto srcInfo =
            getInfo().makeWH(dirty_rect.width(), dirty_rect.height()).makeAlphaType(alphaType);
        SkBitmap src;
        src.installPixels(srcInfo, s, pixels.stride);
        SkPaint paint;
        if (independent) {
            paint.setBlendMode(SkBlendMode::kSrc);
        }

        skcpu::Draw draw;
        draw.fDst.reset(dstInfo(), fIncrDecDst, fIncrDecRowBytes);
        SkMatrix matrix = SkMatrix::RectToRectOrIdentity(SkRect::Make(this->dimensions()),
                                                        SkRect::Make(this->dstInfo().dimensions()));
        draw.fCTM = &matrix;
        SkRasterClip rc(SkIRect::MakeSize(this->dstInfo().dimensions()));
        draw.fRC = &rc;

        SkMatrix translate = SkMatrix::Translate(dirty_rect.min_incl_x, dirty_rect.min_incl_y);
        draw.drawBitmap(src, translate, nullptr, SkSamplingOptions(), paint, nullptr);
    }

    if (result == SkCodec::kSuccess) {
        // On success, we are done using the "two pass" pixel buffer for this
        // frame. We have the option of releasing its memory, but there is a
        // trade-off. If decoding a subsequent frame will also need "two pass"
        // decoding, it would have to re-allocate the buffer instead of just
        // re-using it. On the other hand, if there is no subsequent frame, and
        // the SkWuffsCodec object isn't deleted soon, then we are holding
        // megabytes of memory longer than we need to.
        //
        // For example, when the Chromium web browser decodes the <img> tags in
        // a HTML page, the SkCodec object can live until navigating away from
        // the page, which can be much longer than when the pixels are fully
        // decoded, especially for a still (non-animated) image. Even for
        // looping animations, caching the decoded frames (at the higher HTML
        // renderer layer) may mean that each frame is only decoded once (at
        // the lower SkCodec layer), in sequence.
        //
        // The heuristic we use here is to free the memory if we have decoded
        // the last frame of the animation (or, for still images, the only
        // frame). The output of the next decode request (if any) should be the
        // same either way, but the steady state memory use should hopefully be
        // lower than always keeping the fTwoPassPixbufPtr buffer up until the
        // SkWuffsCodec destructor runs.
        //
        // This only applies to "two pass" decoding. "One pass" decoding does
        // not allocate, free or otherwise use fTwoPassPixbufPtr.
        if (fFramesComplete && (static_cast<size_t>(options().fFrameIndex) == fFrames.size() - 1)) {
            fTwoPassPixbufPtr.reset(nullptr);
            fTwoPassPixbufLen = 0;
        }
    }

    return result;
}

int SkWuffsCodec::onGetFrameCount() {
    if (!fCanSeek) {
        return 1;
    }

    // It is valid, in terms of the SkCodec API, to call SkCodec::getFrameCount
    // while in an incremental decode (after onStartIncrementalDecode returns
    // and before onIncrementalDecode returns kSuccess).
    //
    // We should not advance the SkWuffsCodec' stream while doing so, even
    // though other SkCodec implementations can return increasing values from
    // onGetFrameCount when given more data. If we tried to do so, the
    // subsequent resume of the incremental decode would continue reading from
    // a different position in the I/O stream, leading to an incorrect error.
    //
    // Other SkCodec implementations can move the stream forward during
    // onGetFrameCount because they assume that the stream is rewindable /
    // seekable. For example, an alternative GIF implementation may choose to
    // store, for each frame walked past when merely counting the number of
    // frames, the I/O position of each of the frame's GIF data blocks. (A GIF
    // frame's compressed data can have multiple data blocks, each at most 255
    // bytes in length). Obviously, this can require O(numberOfFrames) extra
    // memory to store these I/O positions. The constant factor is small, but
    // it's still O(N), not O(1).
    //
    // Wuffs and SkWuffsCodec try to minimize relying on the rewindable /
    // seekable assumption. By design, Wuffs per se aims for O(1) memory use
    // (after any pixel buffers are allocated) instead of O(N), and its I/O
    // type, wuffs_base__io_buffer, is not necessarily rewindable or seekable.
    //
    // The Wuffs API provides a limited, optional form of seeking, to the start
    // of an animation frame's data, but does not provide arbitrary save and
    // load of its internal state whilst in the middle of an animation frame.
    bool incrementalDecodeIsInProgress = fIncrDecDst != nullptr;

    if (!fFramesComplete && !incrementalDecodeIsInProgress) {
        this->onGetFrameCountInternal();
        this->updateNumFullyReceivedFrames();
    }
    return fFrames.size();
}

void SkWuffsCodec::onGetFrameCountInternal() {
    size_t n = fFrames.size();
    int    i = n ? n - 1 : 0;
    if (this->seekFrame(i) != SkCodec::kSuccess) {
        return;
    }

    // Iterate through the frames, converting from Wuffs'
    // wuffs_base__frame_config type to Skia's SkWuffsFrame type.
    for (; i < INT_MAX; i++) {
        const char* status = this->decodeFrameConfig();
        if (status == nullptr) {
            // No-op.
        } else if (status == wuffs_base__note__end_of_data) {
            break;
        } else {
            return;
        }

        if (static_cast<size_t>(i) < fFrames.size()) {
            continue;
        }
        fFrames.emplace_back(&fFrameConfig);
        SkWuffsFrame* f = &fFrames[fFrames.size() - 1];
        fFrameHolder.setAlphaAndRequiredFrame(f);
    }

    fFramesComplete = true;
}

bool SkWuffsCodec::onGetFrameInfo(int i, SkCodec::FrameInfo* frameInfo) const {
    if (!fCanSeek) {
        // We haven't read forward in the stream, so this info isn't available.
        return false;
    }

    const SkWuffsFrame* f = this->frame(i);
    if (!f) {
        return false;
    }
    if (frameInfo) {
        f->fillIn(frameInfo, static_cast<uint64_t>(i) < this->fNumFullyReceivedFrames);
    }
    return true;
}

int SkWuffsCodec::onGetRepetitionCount() {
    // Convert from Wuffs's loop count to Skia's repeat count. Wuffs' uint32_t
    // number is how many times to play the loop. Skia's int number is how many
    // times to play the loop *after the first play*. Wuffs and Skia use 0 and
    // kRepetitionCountInfinite respectively to mean loop forever.
    uint32_t n = fDecoder->num_animation_loops();
    if (n == 0) {
        return SkCodec::kRepetitionCountInfinite;
    }
    n--;
    return n < INT_MAX ? n : INT_MAX;
}

SkCodec::IsAnimated SkWuffsCodec::onIsAnimated() {
    if (fFrames.size() > 1) {
        return IsAnimated::kYes;
    }

    // If we only have encounted a single image frame so far, then we have an
    // ambiguous situation - maybe more frames will come, but maybe not.
    return fFramesComplete ? IsAnimated::kNo : IsAnimated::kUnknown;
}

SkCodec::Result SkWuffsCodec::seekFrame(int frameIndex) {
    if (fDecoderIsSuspended) {
        SkCodec::Result res = this->resetDecoder();
        if (res != SkCodec::kSuccess) {
            return res;
        }
    }

    uint64_t pos = 0;
    if (frameIndex < 0) {
        return SkCodec::kInternalError;
    } else if (frameIndex == 0) {
        pos = fFirstFrameIOPosition;
    } else if (static_cast<size_t>(frameIndex) < fFrames.size()) {
        pos = fFrames[frameIndex].ioPosition();
    } else {
        return SkCodec::kInternalError;
    }

    if (!seek_buffer(&fIOBuffer, fPrivStream.get(), pos)) {
        return SkCodec::kInternalError;
    }
    wuffs_base__status status =
        fDecoder->restart_frame(frameIndex, fIOBuffer.reader_io_position());
    if (status.repr != nullptr) {
        return SkCodec::kInternalError;
    }
    return SkCodec::kSuccess;
}

SkCodec::Result SkWuffsCodec::resetDecoder() {
    if (!fPrivStream->rewind()) {
        return SkCodec::kInternalError;
    }
    fIOBuffer.meta = wuffs_base__empty_io_buffer_meta();

    SkCodec::Result result =
        reset_and_decode_image_config(fDecoder.get(), nullptr, &fIOBuffer, fPrivStream.get());
    if (result == SkCodec::kIncompleteInput) {
        return SkCodec::kInternalError;
    } else if (result != SkCodec::kSuccess) {
        return result;
    }

    fDecoderIsSuspended = false;
    return SkCodec::kSuccess;
}

const char* SkWuffsCodec::decodeFrameConfig() {
    while (true) {
        wuffs_base__status status =
            fDecoder->decode_frame_config(&fFrameConfig, &fIOBuffer);
        if ((status.repr == wuffs_base__suspension__short_read) &&
            fill_buffer(&fIOBuffer, fPrivStream.get())) {
            continue;
        }
        fDecoderIsSuspended = !status.is_complete();
        this->updateNumFullyReceivedFrames();
        return status.repr;
    }
}

const char* SkWuffsCodec::decodeFrame() {
    while (true) {
        wuffs_base__status status = fDecoder->decode_frame(
            &fPixelBuffer, &fIOBuffer, fIncrDecPixelBlend,
            wuffs_base__make_slice_u8(fWorkbufPtr.get(), fWorkbufLen), nullptr);
        if ((status.repr == wuffs_base__suspension__short_read) &&
            fill_buffer(&fIOBuffer, fPrivStream.get())) {
            continue;
        }
        fDecoderIsSuspended = !status.is_complete();
        this->updateNumFullyReceivedFrames();
        return status.repr;
    }
}

void SkWuffsCodec::updateNumFullyReceivedFrames() {
    // num_decoded_frames's return value, n, can change over time, both up and
    // down, as we seek back and forth in the underlying stream.
    // fNumFullyReceivedFrames is the highest n we've seen.
    uint64_t n = fDecoder->num_decoded_frames();
    if (fNumFullyReceivedFrames < n) {
        fNumFullyReceivedFrames = n;
    }
}

// We cannot use the SkCodec implementation since we pass nullptr to the superclass out of
// an abundance of caution w/r to rewinding the stream.
//
// TODO(https://crbug.com/370522089): See if `SkCodec` can be tweaked to avoid
// the need to hide the stream from it.
std::unique_ptr<SkStream> SkWuffsCodec::getEncodedData() const {
    SkASSERT(fPrivStream);
    return fPrivStream->duplicate();
}

namespace SkGifDecoder {

bool IsGif(const void* buf, size_t bytesRead) {
    constexpr const char* gif_ptr = "GIF8";
    constexpr size_t      gif_len = 4;
    return (bytesRead >= gif_len) && (memcmp(buf, gif_ptr, gif_len) == 0);
}

std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream> stream,
                                        SkCodec::SelectionPolicy  selectionPolicy,
                                        SkCodec::Result*          result) {
    SkASSERT(result);
    if (!stream) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }

    bool canSeek = stream->hasPosition() && stream->hasLength();

    if (selectionPolicy != SkCodec::SelectionPolicy::kPreferStillImage) {
        // Some clients (e.g. Android) need to be able to seek the stream, but may
        // not provide a seekable stream. Copy the stream to one that can seek.
        if (!canSeek) {
            auto data = SkStreamPriv::CopyStreamToData(stream.get());
            stream = std::make_unique<SkMemoryStream>(std::move(data));
            canSeek = true;
        }
    }

    uint8_t               buffer[SK_WUFFS_CODEC_BUFFER_SIZE];
    wuffs_base__io_buffer iobuf =
        wuffs_base__make_io_buffer(wuffs_base__make_slice_u8(buffer, SK_WUFFS_CODEC_BUFFER_SIZE),
                                   wuffs_base__empty_io_buffer_meta());
    wuffs_base__image_config imgcfg = wuffs_base__null_image_config();

    // Wuffs is primarily a C library, not a C++ one. Furthermore, outside of
    // the wuffs_base__etc types, the sizeof a file format specific type like
    // GIF's wuffs_gif__decoder can vary between Wuffs versions. If p is of
    // type wuffs_gif__decoder*, then the supported API treats p as a pointer
    // to an opaque type: a private implementation detail. The API is always
    // "set_foo(p, etc)" and not "p->foo = etc".
    //
    // See https://en.wikipedia.org/wiki/Opaque_pointer#C
    //
    // Thus, we don't use C++'s new operator (which requires knowing the sizeof
    // the struct at compile time). Instead, we use sk_malloc_canfail, with
    // sizeof__wuffs_gif__decoder returning the appropriate value for the
    // (statically or dynamically) linked version of the Wuffs library.
    //
    // As a C (not C++) library, none of the Wuffs types have constructors or
    // destructors.
    //
    // In RAII style, we can still use std::unique_ptr with these pointers, but
    // we pair the pointer with sk_free instead of C++'s delete.
    void* decoder_raw = sk_malloc_canfail(sizeof__wuffs_gif__decoder());
    if (!decoder_raw) {
        *result = SkCodec::kInternalError;
        return nullptr;
    }
    std::unique_ptr<wuffs_gif__decoder, decltype(&sk_free)> decoder(
        reinterpret_cast<wuffs_gif__decoder*>(decoder_raw), &sk_free);

    SkCodec::Result reset_result =
        reset_and_decode_image_config(decoder.get(), &imgcfg, &iobuf, stream.get());
    if (reset_result != SkCodec::kSuccess) {
        *result = reset_result;
        return nullptr;
    }

    uint32_t width = imgcfg.pixcfg.width();
    uint32_t height = imgcfg.pixcfg.height();
    if ((width == 0) || (width > INT_MAX) || (height == 0) || (height > INT_MAX)) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }

    uint64_t workbuf_len = decoder->workbuf_len().max_incl;
    void*    workbuf_ptr_raw = nullptr;
    if (workbuf_len) {
        workbuf_ptr_raw = workbuf_len <= SIZE_MAX ? sk_malloc_canfail(workbuf_len) : nullptr;
        if (!workbuf_ptr_raw) {
            *result = SkCodec::kInternalError;
            return nullptr;
        }
    }
    std::unique_ptr<uint8_t, decltype(&sk_free)> workbuf_ptr(
        reinterpret_cast<uint8_t*>(workbuf_ptr_raw), &sk_free);

    SkEncodedInfo::Color color =
        (imgcfg.pixcfg.pixel_format().repr == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL)
            ? SkEncodedInfo::kBGRA_Color
            : SkEncodedInfo::kRGBA_Color;

    // In Skia's API, the alpha we calculate here and return is only for the
    // first frame.
    SkEncodedInfo::Alpha alpha = imgcfg.first_frame_is_opaque() ? SkEncodedInfo::kOpaque_Alpha
                                                                : SkEncodedInfo::kBinary_Alpha;

    SkEncodedInfo encodedInfo = SkEncodedInfo::Make(width, height, color, alpha, 8);

    *result = SkCodec::kSuccess;
    return std::unique_ptr<SkCodec>(new SkWuffsCodec(std::move(encodedInfo), std::move(stream),
                                                     canSeek,
                                                     std::move(decoder), std::move(workbuf_ptr),
                                                     workbuf_len, imgcfg, iobuf));
}

std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext ctx) {
    SkCodec::Result resultStorage;
    if (!outResult) {
        outResult = &resultStorage;
    }
    auto policy = SkCodec::SelectionPolicy::kPreferStillImage;
    if (ctx) {
        policy = *static_cast<SkCodec::SelectionPolicy*>(ctx);
    }
    return MakeFromStream(std::move(stream), policy, outResult);
}

std::unique_ptr<SkCodec> Decode(sk_sp<const SkData> data,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext ctx) {
    if (!data) {
        if (outResult) {
            *outResult = SkCodec::kInvalidInput;
        }
        return nullptr;
    }
    return Decode(SkMemoryStream::Make(std::move(data)), outResult, ctx);
}
}  // namespace SkGifDecoder

