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

#include "include/codec/SkPngRustDecoder.h"

#include <algorithm>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "include/codec/SkAndroidCodec.h"
#include "include/codec/SkCodec.h"
#include "include/codec/SkCodecAnimation.h"
#include "include/codec/SkPngChunkReader.h"
#if defined(SK_CODEC_DECODES_PNG_WITH_LIBPNG)
#include "include/codec/SkPngDecoder.h"
#endif
#include "include/core/SkBitmap.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/private/SkGainmapInfo.h"
#include "src/codec/SkCodecPriv.h"
#include "tests/FakeStreams.h"
#include "tests/Test.h"
#include "tools/Resources.h"

#define REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, actualResult) \
    REPORTER_ASSERT(r,                                           \
                    actualResult == SkCodec::kSuccess,           \
                    "actualResult=\"%s\" != kSuccess",           \
                    SkCodec::ResultToString(actualResult))

namespace {
// This class wraps another SkStream. It does not own the underlying stream, so
// that the underlying stream can be reused starting from where the first
// client left off. This mimics Android's JavaInputStreamAdaptor.
// Replicated from tests/CodecExactReadTest.cpp.
class UnowningStream : public SkStream {
public:
    explicit UnowningStream(SkStream* stream) : fStream(stream) {}

    size_t read(void* buf, size_t bytes) override { return fStream->read(buf, bytes); }

    bool rewind() override { return fStream->rewind(); }

    bool isAtEnd() const override { return fStream->isAtEnd(); }

private:
    SkStream* fStream;  // Unowned.
};

}  // namespace

// Helper wrapping a call to `SkPngRustDecoder::Decode`.
std::unique_ptr<SkCodec> SkPngRustDecoderDecode(skiatest::Reporter* r, const char* path) {
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return nullptr;
    }

    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec =
            SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(std::move(data)), &result);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);

    return codec;
}

void AssertPixelColor(skiatest::Reporter* r,
                      const SkPixmap& pixmap,
                      int x,
                      int y,
                      SkColor expectedColor,
                      const char* description) {
    SkASSERT(r);
    SkASSERT(x >= 0);
    SkASSERT(y >= 0);
    SkASSERT(description);

    REPORTER_ASSERT(r, x < pixmap.width(), "x=%d >= width=%d", x, pixmap.width());
    REPORTER_ASSERT(r, y < pixmap.height(), "y=%d >= height=%d", y, pixmap.height());
    REPORTER_ASSERT(r,
                    kN32_SkColorType == pixmap.colorType(),
                    "kN32_SkColorType != pixmap.ColorType()=%d",
                    pixmap.colorType());

    SkColor actualColor = pixmap.getColor(x, y);
    REPORTER_ASSERT(r,
                    actualColor == expectedColor,
                    "actualColor=0x%08X != expectedColor==0x%08X at (%d,%d) (%s)",
                    actualColor,
                    expectedColor,
                    x,
                    y,
                    description);
}

void AssertGreenPixel(skiatest::Reporter* r,
                      const SkPixmap& pixmap,
                      int x,
                      int y,
                      const char* description = "Expecting a green pixel") {
    AssertPixelColor(r, pixmap, x, y, SkColorSetRGB(0x00, 0xFF, 0x00), description);
}

void AssertRedPixel(skiatest::Reporter* r,
                    const SkPixmap& pixmap,
                    int x,
                    int y,
                    const char* description = "Expecting a red pixel") {
    AssertPixelColor(r, pixmap, x, y, SkColorSetRGB(0xFF, 0x00, 0x00), description);
}

void AssertBluePixel(skiatest::Reporter* r,
                     const SkPixmap& pixmap,
                     int x,
                     int y,
                     const char* description = "Expecting a blue pixel") {
    AssertPixelColor(r, pixmap, x, y, SkColorSetRGB(0x00, 0x00, 0xFF), description);
}

void AssertSingleGreenFrame(skiatest::Reporter* r,
                            int expectedWidth,
                            int expectedHeight,
                            const char* resourcePath) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, resourcePath);
    if (!codec) {
        return;
    }

    REPORTER_ASSERT(r, codec->getFrameCount() == 1);
    REPORTER_ASSERT(r, codec->getRepetitionCount() == 0);

    SkCodec::FrameInfo info;
    REPORTER_ASSERT(r, codec->getFrameInfo(0, &info));
    REPORTER_ASSERT(r, info.fBlend == SkCodecAnimation::Blend::kSrc);
    REPORTER_ASSERT(r, info.fDisposalMethod == SkCodecAnimation::DisposalMethod::kKeep);
    REPORTER_ASSERT(r, info.fFrameRect == SkIRect::MakeWH(expectedWidth, expectedHeight));
    REPORTER_ASSERT(r, info.fRequiredFrame == SkCodec::kNoFrame);

    auto [image, result] = codec->getImage();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);

    REPORTER_ASSERT(r, image);
    REPORTER_ASSERT(r,
                    image->width() == expectedWidth,
                    "actualWidth=%d != expectedWidth=%d",
                    image->width(),
                    expectedWidth);
    REPORTER_ASSERT(r,
                    image->height() == expectedHeight,
                    "actualHeight=%d != expectedHeight=%d",
                    image->height(),
                    expectedHeight);

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));

    AssertGreenPixel(r, pixmap, 0, 0);
    AssertGreenPixel(r, pixmap, expectedWidth / 2, expectedHeight / 2);
}

// Sentinel fill color used to detect pixels left unwritten by the codec.
static constexpr SkColor kUnreadSentinelColor = SK_ColorMAGENTA;

static std::unique_ptr<SkCodec> StartIncrementalDecode(
        skiatest::Reporter* r,
        std::unique_ptr<SkStream> stream,
        SkBitmap* dstBitmap,
        std::function<SkImageInfo(const SkImageInfo&)> makeDstInfo = nullptr,
        const SkCodec::Options& options = {}) {
    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec = SkPngRustDecoder::Decode(std::move(stream), &result);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (!codec) {
        return nullptr;
    }

    const SkImageInfo dstInfo = makeDstInfo ? makeDstInfo(codec->getInfo()) : codec->getInfo();
    SkImageInfo allocInfo = dstInfo;
    if (options.fSubset) {
        allocInfo = allocInfo.makeDimensions(options.fSubset->size());
    }
    REPORTER_ASSERT(r, dstBitmap->tryAllocPixels(allocInfo));
    dstBitmap->eraseColor(options.fZeroInitialized == SkCodec::kYes_ZeroInitialized
                                  ? SK_ColorTRANSPARENT
                                  : kUnreadSentinelColor);

    result = codec->startIncrementalDecode(
            dstInfo, dstBitmap->getPixels(), dstBitmap->rowBytes(), &options);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (result != SkCodec::kSuccess) {
        return nullptr;
    }

    return codec;
}

static std::optional<SkBitmap> DecodeIncrementalOneShot(
        skiatest::Reporter* r,
        sk_sp<SkData> data,
        std::function<SkImageInfo(const SkImageInfo&)> makeDstInfo = nullptr,
        const SkCodec::Options& options = {}) {
    SkBitmap bm;
    std::unique_ptr<SkCodec> codec = StartIncrementalDecode(
            r, SkMemoryStream::Make(std::move(data)), &bm, std::move(makeDstInfo), options);
    if (!codec) {
        return std::nullopt;
    }
    SkCodec::Result result = codec->incrementalDecode();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (result != SkCodec::kSuccess) {
        return std::nullopt;
    }
    return bm;
}

static void CompareBitmaps(skiatest::Reporter* r, const SkBitmap& bm1, const SkBitmap& bm2) {
    const SkImageInfo& info = bm1.info();
    if (info != bm2.info()) {
        ERRORF(r, "Bitmaps have different image infos!");
        return;
    }
    const size_t rowBytes = info.minRowBytes();
    for (int i = 0; i < info.height(); i++) {
        if (0 != memcmp(bm1.getAddr(0, i), bm2.getAddr(0, i), rowBytes)) {
            ERRORF(r, "Bitmaps have different pixels, starting on line %i!", i);
            return;
        }
    }
}

// Returns the number of rows in `bm` up to and including the last row that contains at least one
// pixel differing from `sentinelColor`.
static int CountNonSentinelRows(const SkBitmap& bm, SkColor sentinelColor) {
    for (int y = bm.height() - 1; y >= 0; --y) {
        for (int x = 0; x < bm.width(); ++x) {
            if (bm.getColor(x, y) != sentinelColor) {
                return y + 1;
            }
        }
    }
    return 0;
}

// Returns the decoded height of `bm` (pre-filled with `sentinelColor`), measured as the number of
// rows up to and including the last row that differs from `sentinelColor`, and asserts that every
// pixel in rows `0 .. writtenRows - 1` was overwritten.
static int CountWrittenRows(skiatest::Reporter* r,
                            const SkBitmap& bm,
                            SkColor sentinelColor = kUnreadSentinelColor) {
    const int writtenRows = CountNonSentinelRows(bm, sentinelColor);
    for (int y = 0; y < writtenRows; ++y) {
        for (int x = 0; x < bm.width(); ++x) {
            if (bm.getColor(x, y) == sentinelColor) {
                ERRORF(r,
                       "Row %d < writtenRows (%d) still has sentinel pixel at (%d, %d)",
                       y,
                       writtenRows,
                       x,
                       y);
                return writtenRows;
            }
        }
    }
    return writtenRows;
}

// A valid `IEND` chunk has an empty payload: 4-byte length (0), 4-byte type ("IEND"), 4-byte CRC.
static constexpr size_t kIendChunkSize = 12;

static bool HasTrailingIendChunk(const SkData* data) {
    return data->size() > kIendChunkSize &&
           memcmp(data->bytes() + data->size() - kIendChunkSize, "\0\0\0\0IEND", 8) == 0;
}

// Returns a copy of `data` with the last byte of the trailing `IEND` CRC flipped.
static sk_sp<SkData> WithCorruptIendCrc(const SkData* data) {
    SkASSERT(HasTrailingIendChunk(data));
    sk_sp<SkData> copy = SkData::MakeWithCopy(data->data(), data->size());
    static_cast<uint8_t*>(copy->writable_data())[copy->size() - 1] ^= 0xFF;
    return copy;
}

// Returns `data` without the trailing 4-byte `IEND` CRC (the 8-byte chunk header is kept).
static sk_sp<SkData> WithoutIendCrc(const SkData* data) {
    SkASSERT(HasTrailingIendChunk(data));
    return SkData::MakeSubset(data, 0, data->size() - 4);
}

// Returns `data` without the entire 12-byte trailing `IEND` chunk.
static sk_sp<SkData> WithoutIendChunk(const SkData* data) {
    SkASSERT(HasTrailingIendChunk(data));
    return SkData::MakeSubset(data, 0, data->size() - kIendChunkSize);
}

// Returns a copy of `data` with the last byte of the CRC of its `idatIndex`-th (0-based) `IDAT`
// chunk flipped, or nullptr if there is no such chunk. Decoding then fails with `kErrorInInput`
// once that chunk has been read, after the rows from the preceding `IDAT` chunks.
static sk_sp<SkData> WithCorruptIdatCrc(const SkData* data, int idatIndex) {
    constexpr size_t kSignatureSize = 8;
    constexpr size_t kChunkHeaderSize = 8;  // 4-byte length + 4-byte type.
    constexpr size_t kCrcSize = 4;

    sk_sp<SkData> copy = SkData::MakeWithCopy(data->data(), data->size());
    uint8_t* bytes = static_cast<uint8_t*>(copy->writable_data());
    size_t offset = kSignatureSize;
    while (offset + kChunkHeaderSize <= copy->size()) {
        const size_t length = (size_t{bytes[offset]} << 24) | (size_t{bytes[offset + 1]} << 16) |
                              (size_t{bytes[offset + 2]} << 8) | size_t{bytes[offset + 3]};
        const size_t crcEnd = offset + kChunkHeaderSize + length + kCrcSize;
        if (crcEnd > copy->size()) {
            break;
        }
        if (memcmp(bytes + offset + 4, "IDAT", 4) == 0 && idatIndex-- == 0) {
            bytes[crcEnd - 1] ^= 0xFF;
            return copy;
        }
        offset = crcEnd;
    }
    return nullptr;
}

static std::optional<SkBitmap> DecodeToBitmap(skiatest::Reporter* r,
                                              const SkImageInfo& dstInfo,
                                              SkCodec::Result expectedResult,
                                              std::function<SkCodec::Result(SkBitmap&)> decode) {
    SkBitmap bm;
    REPORTER_ASSERT(r, bm.tryAllocPixels(dstInfo));
    SkCodec::Result result = decode(bm);
    REPORTER_ASSERT(r,
                    result == expectedResult,
                    "Expected %s, got %s",
                    SkCodec::ResultToString(expectedResult),
                    SkCodec::ResultToString(result));
    if (result != expectedResult ||
        (result != SkCodec::kSuccess && result != SkCodec::kIncompleteInput &&
         result != SkCodec::kErrorInInput)) {
        return std::nullopt;
    }
    return bm;
}

static std::optional<SkBitmap> DecodeAndroidPixels(
        skiatest::Reporter* r,
        std::unique_ptr<SkCodec> codec,
        int sampleSize,
        std::function<SkIRect(const SkImageInfo&)> getSubset = nullptr,
        size_t maxDecodeMemory = 0,
        SkCodec::Result expectedResult = SkCodec::kSuccess) {
    REPORTER_ASSERT(r, codec);
    if (!codec) {
        return std::nullopt;
    }

    auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
    REPORTER_ASSERT(r, androidCodec);
    if (!androidCodec) {
        return std::nullopt;
    }

    SkISize sampledDims = androidCodec->getSampledDimensions(sampleSize);
    SkImageInfo info =
            androidCodec->getInfo().makeDimensions(sampledDims).makeColorType(kN32_SkColorType);
    SkIRect subset;
    if (getSubset) {
        subset = getSubset(androidCodec->getInfo());
        int subsetWidth = SkCodecPriv::GetSampledDimension(subset.width(), sampleSize);
        int subsetHeight = SkCodecPriv::GetSampledDimension(subset.height(), sampleSize);
        info = info.makeWH(subsetWidth, subsetHeight);
    }

    return DecodeToBitmap(r, info, expectedResult, [&](SkBitmap& bm) {
        SkAndroidCodec::AndroidOptions opts;
        opts.fSampleSize = sampleSize;
        if (getSubset) {
            opts.fSubset = &subset;
        }
        opts.fMaxDecodeMemory = maxDecodeMemory;
        bm.eraseColor(kUnreadSentinelColor);
        return androidCodec->getAndroidPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts);
    });
}

// Decodes `codec` with `SkCodec::getPixels`. The plain-`SkCodec` counterpart of
// `DecodeAndroidPixels`.
//
// The destination is zeroed for `kYes_ZeroInitialized` (as that option requires), and otherwise
// pre-filled with `kUnreadSentinelColor` so that pixels left unwritten by the codec are detectable.
static std::optional<SkBitmap> DecodePixels(
        skiatest::Reporter* r,
        std::unique_ptr<SkCodec> codec,
        std::function<SkImageInfo(const SkImageInfo&)> makeDstInfo = nullptr,
        const SkCodec::Options& options = {},
        SkCodec::Result expectedResult = SkCodec::kSuccess) {
    REPORTER_ASSERT(r, codec);
    if (!codec) {
        return std::nullopt;
    }

    SkImageInfo info = makeDstInfo ? makeDstInfo(codec->getInfo()) : codec->getInfo();
    return DecodeToBitmap(r, info, expectedResult, [&](SkBitmap& bm) {
        bm.eraseColor(options.fZeroInitialized == SkCodec::kYes_ZeroInitialized
                              ? SK_ColorTRANSPARENT
                              : kUnreadSentinelColor);
        return codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &options);
    });
}

// Returns default `SkCodec::Options` with `fMaxDecodeMemory` set to `maxDecodeMemory`.
static SkCodec::Options MakeBudgetOptions(size_t maxDecodeMemory) {
    SkCodec::Options options;
    options.fMaxDecodeMemory = maxDecodeMemory;
    return options;
}

// Verifies that decoding `path` with `expectedBudgetBytes - 1` fails with `kOutOfMemory` and
// decoding with `expectedBudgetBytes` succeeds.
static void AssertDecodeBudget(
        skiatest::Reporter* r,
        const char* path,
        size_t expectedBudgetBytes,
        std::function<std::optional<SkBitmap>(std::unique_ptr<SkCodec>, size_t, SkCodec::Result)>
                decode) {
    REPORTER_ASSERT(
            r,
            !decode(SkPngRustDecoderDecode(r, path), expectedBudgetBytes - 1, SkCodec::kOutOfMemory)
                     .has_value());
    REPORTER_ASSERT(r,
                    decode(SkPngRustDecoderDecode(r, path), expectedBudgetBytes, SkCodec::kSuccess)
                            .has_value());
}

static void AssertAndroidDecodeSampling(
        skiatest::Reporter* r,
        const char* path,
        int sampleSize,
        std::function<SkIRect(const SkImageInfo&)> getSubset = nullptr) {
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    std::optional<SkBitmap> rustBm = DecodeAndroidPixels(
            r,
            SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr),
            sampleSize,
            getSubset);

#if defined(SK_CODEC_DECODES_PNG_WITH_LIBPNG)
    std::optional<SkBitmap> libpngBm = DecodeAndroidPixels(
            r,
            SkPngDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr),
            sampleSize,
            getSubset);

    if (!rustBm || !libpngBm) {
        return;
    }

    CompareBitmaps(r, *rustBm, *libpngBm);
#else
    REPORTER_ASSERT(r, rustBm.has_value());
#endif
}

#if defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
static void AssertAndroidStaticApng(skiatest::Reporter* r,
                                    const char* path,
                                    std::optional<SkColor> expectedTopLeftColor = std::nullopt) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, path);
    if (!codec) {
        return;
    }

    REPORTER_ASSERT(r, codec->isAnimated() == SkCodec::IsAnimated::kNo);
    REPORTER_ASSERT(r, codec->getFrameCount() == 1);
    REPORTER_ASSERT(r, codec->getRepetitionCount() == 0);

    SkCodec::FrameInfo info;
    REPORTER_ASSERT(r, codec->getFrameInfo(0, &info));
    REPORTER_ASSERT(r, info.fRequiredFrame == SkCodec::kNoFrame);

    if (expectedTopLeftColor.has_value()) {
        auto [image, result] = codec->getImage();
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
        if (image) {
            SkPixmap pixmap;
            REPORTER_ASSERT(r, image->peekPixels(&pixmap));
            AssertPixelColor(r, pixmap, 0, 0, *expectedTopLeftColor, "IDAT top-left pixel");
        }
    }

    // Verify full, downsampled, and subset+downsampled decodes succeed and match `libpng`.
    AssertAndroidDecodeSampling(r, path, /*sampleSize=*/1);
    AssertAndroidDecodeSampling(r, path, /*sampleSize=*/2);
    AssertAndroidDecodeSampling(r, path, /*sampleSize=*/2, [](const SkImageInfo& imgInfo) {
        return SkIRect::MakeXYWH(0, 0, imgInfo.width() / 2, imgInfo.height() / 2);
    });
}
#endif

#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
// Decodes into a buffer surrounded by guard bytes to detect out-of-bounds writes
// even in builds without ASAN, and asserts that the decode is refused with
// `SkCodec::kUnimplemented`.
static void AssertAndroidDecodeRefused(skiatest::Reporter* r,
                                       const sk_sp<SkData>& data,
                                       int sampleSize,
                                       bool useSubset,
                                       size_t customRowBytes = 0) {
    constexpr size_t kGuardBytes = 64 * 1024;
    constexpr uint8_t kGuardValue = 0x5A;

    auto codec = SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr);
    REPORTER_ASSERT(r, codec);
    if (!codec) {
        return;
    }

    auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
    REPORTER_ASSERT(r, androidCodec);
    if (!androidCodec) {
        return;
    }

    const SkISize fullDims = androidCodec->getInfo().dimensions();
    SkIRect subset = SkIRect::MakeWH(fullDims.width(), std::max(1, fullDims.height() / 2));
    if (useSubset) {
        REPORTER_ASSERT(r, androidCodec->getSupportedSubset(&subset));
    }

    const SkISize dims =
            useSubset ? SkISize::Make(SkCodecPriv::GetSampledDimension(subset.width(), sampleSize),
                                      SkCodecPriv::GetSampledDimension(subset.height(), sampleSize))
                      : androidCodec->getSampledDimensions(sampleSize);

    const SkImageInfo info = androidCodec->getInfo()
                                     .makeDimensions(dims)
                                     .makeColorType(kN32_SkColorType)
                                     .makeAlphaType(kPremul_SkAlphaType);
    const size_t rowBytes = customRowBytes ? customRowBytes : info.minRowBytes();
    const size_t pixelBytes = info.computeByteSize(rowBytes);
    std::vector<uint8_t> buffer(kGuardBytes + pixelBytes + kGuardBytes, kGuardValue);

    SkAndroidCodec::AndroidOptions options;
    options.fSampleSize = sampleSize;
    if (useSubset) {
        options.fSubset = &subset;
    }

    SkCodec::Result result =
            androidCodec->getAndroidPixels(info, buffer.data() + kGuardBytes, rowBytes, &options);
    REPORTER_ASSERT(r,
                    result == SkCodec::kUnimplemented,
                    "Expected the decode to be refused with kUnimplemented, got %s "
                    "(sampleSize=%d, useSubset=%d, rowBytes=%zu)",
                    SkCodec::ResultToString(result),
                    sampleSize,
                    (int)useSubset,
                    rowBytes);

    const bool guardBytesIntact = std::all_of(buffer.begin(),
                                              buffer.begin() + kGuardBytes,
                                              [](uint8_t b) { return b == kGuardValue; }) &&
                                  std::all_of(buffer.begin() + kGuardBytes + pixelBytes,
                                              buffer.end(),
                                              [](uint8_t b) { return b == kGuardValue; });
    REPORTER_ASSERT(r,
                    guardBytesIntact,
                    "The decode wrote outside of the destination buffer "
                    "(sampleSize=%d, useSubset=%d, rowBytes=%zu)",
                    sampleSize,
                    (int)useSubset,
                    rowBytes);
}
#endif

// Asserts that `decode` produces the same pixels for `path` as for copies of it with a corrupt
// and with a truncated trailing `IEND` CRC. Both variants leave all of `IDAT` intact.
static void AssertBrokenIendTailMatchesIntact(
        skiatest::Reporter* r,
        const char* path,
        std::function<std::optional<SkBitmap>(sk_sp<SkData>)> decode) {
    sk_sp<SkData> fullData = GetResourceAsData(path);
    if (!fullData) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    std::optional<SkBitmap> refBm = decode(fullData);
    REPORTER_ASSERT(r, refBm.has_value());
    if (!refBm) {
        return;
    }

    const struct {
        const char* fLabel;
        sk_sp<SkData> fData;
    } variants[] = {
            {"corrupt IEND CRC", WithCorruptIendCrc(fullData.get())},
            {"truncated IEND CRC", WithoutIendCrc(fullData.get())},
    };
    for (const auto& [label, variant] : variants) {
        std::optional<SkBitmap> bm = decode(variant);
        REPORTER_ASSERT(
                r, bm.has_value(), "%s: decode failed for variant '%s'", path, label);
        if (bm) {
            CompareBitmaps(r, *refBm, *bm);
        }
    }
}

// Full decodes, in the color configurations that cover both decode paths.
static void AssertDecodesWithBrokenIendTail(skiatest::Reporter* r, const char* path) {
    // kRGBA_8888 + kUnpremul on an RGBA8 source with an `iCCP` chunk is the only combination that
    // satisfies `canReadRow()`, i.e. the only one decoded by `incrementalDecode` (`read_row`).
    // The others go through `incrementalDecodeXForm`.
    static constexpr struct {
        SkColorType fColorType;
        SkAlphaType fAlphaType;
    } kConfigs[] = {
            {kN32_SkColorType, kUnpremul_SkAlphaType},
            {kN32_SkColorType, kPremul_SkAlphaType},
            {kRGBA_8888_SkColorType, kUnpremul_SkAlphaType},
    };

    for (const auto& config : kConfigs) {
        AssertBrokenIendTailMatchesIntact(r, path, [&](sk_sp<SkData> data) {
            return DecodePixels(r,
                                SkPngRustDecoder::Decode(
                                        std::make_unique<SkMemoryStream>(std::move(data)), nullptr),
                                [&](const SkImageInfo& info) {
                                    return info.makeColorType(config.fColorType)
                                            .makeAlphaType(config.fAlphaType);
                                });
        });
    }
}

// Same, for a sampled decode. It goes through `SkAndroidCodec`, always decodes to `kN32`, and
// skips `finish_decoding()` altogether rather than ignoring its result.
static void AssertSampledDecodeWithBrokenIendTail(skiatest::Reporter* r,
                                                  const char* path,
                                                  int sampleSize) {
    auto decode = [&](sk_sp<SkData> data) {
        return DecodeAndroidPixels(
                r,
                SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(std::move(data)),
                                         nullptr),
                sampleSize);
    };
    AssertBrokenIendTailMatchesIntact(r, path, decode);

    // Because a non-interlaced sampled decode stops after the last needed scanline without reading
    // the `IDAT` CRC or the 8-byte `IEND` chunk header (`stopsBeforeEndOfFrame`), it must also
    // succeed when the entire 12-byte `IEND` chunk is stripped.
    sk_sp<SkData> fullData = GetResourceAsData(path);
    std::optional<SkBitmap> refBm = decode(fullData);
    std::optional<SkBitmap> withoutIendBm = decode(WithoutIendChunk(fullData.get()));
    REPORTER_ASSERT(r, withoutIendBm.has_value());
    if (refBm && withoutIendBm) {
        CompareBitmaps(r, *refBm, *withoutIendBm);
    }
}

sk_sp<SkImage> DecodeLastFrame(skiatest::Reporter* r, SkCodec* codec) {
    int frameCount = codec->getFrameCount();
    sk_sp<SkImage> image;
    SkCodec::Result result = SkCodec::kSuccess;
    for (int i = 0; i < frameCount; i++) {
        SkCodec::FrameInfo info;
        REPORTER_ASSERT(r, codec->getFrameInfo(i, &info));

        // This test method only supports `kKeep` disposal method.
        SkASSERT(info.fDisposalMethod == SkCodecAnimation::DisposalMethod::kKeep);

        if (!image) {
            std::tie(image, result) = codec->getImage();
            REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
            if (result != SkCodec::kSuccess) {
                return nullptr;
            }
        } else {
            SkPixmap pixmap;
            REPORTER_ASSERT(r, image->peekPixels(&pixmap));

            SkCodec::Options options;
            options.fZeroInitialized = SkCodec::kNo_ZeroInitialized;
            options.fSubset = nullptr;
            options.fFrameIndex = i;
            options.fPriorFrame = i - 1;

            result = codec->getPixels(pixmap, &options);
            REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
            if (result != SkCodec::kSuccess) {
                return nullptr;
            }
        }
    }

    return image;
}

sk_sp<SkImage> DecodeLastFrame(skiatest::Reporter* r, const char* resourcePath) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, resourcePath);
    if (!codec) {
        return nullptr;
    }

    return DecodeLastFrame(r, codec.get());
}

void AssertAnimationRepetitionCount(skiatest::Reporter* r,
                                    int expectedRepetitionCount,
                                    const char* resourcePath) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, resourcePath);
    if (!codec) {
        return;
    }

    int actualRepetitionCount = codec->getRepetitionCount();
    REPORTER_ASSERT(r,
                    actualRepetitionCount == expectedRepetitionCount,
                    "actualRepetitionCount=%d != expectedRepetitionCount=%d",
                    actualRepetitionCount,
                    expectedRepetitionCount);
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#trivial-static-image
DEF_TEST(RustPngCodec_apng_basic_trivial_static_image, r) {
    AssertSingleGreenFrame(r, 128, 64, "images/apng-test-suite--basic--trivial-static-image.png");
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#trivial-animated-image-one-frame-using-default-image
DEF_TEST(RustPngCodec_apng_basic_using_default_image, r) {
    const char* kResource = "images/apng-test-suite--basic--using-default-image.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    AssertSingleGreenFrame(r, 128, 64, kResource);
#else
    AssertAndroidStaticApng(r, kResource, SK_ColorGREEN);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#trivial-animated-image-one-frame-ignoring-default-image
//
// The input file contains the following PNG chunks: IHDR, acTL, IDAT, fcTL,
// fdAT, IEND.  Presence of acTL chunk + no fcTL chunk before IDAT means that
// the IDAT chunk is *not* part of the animation:
// * On non-Android (APNG-aware), `SkPngRustCodec` ignores the red `IDAT` default
//   image and decodes the green `fdAT` animation frame.
// * On Android (`SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID`), `SkPngRustCodec`
//   ignores `acTL`/`fcTL` for `SkPngCodec` (libpng) parity and decodes the red
//   `IDAT` default image as a static single-frame PNG.
DEF_TEST(RustPngCodec_apng_basic_ignoring_default_image, r) {
    const char* kResource = "images/apng-test-suite--basic--ignoring-default-image.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    AssertSingleGreenFrame(r, 128, 64, kResource);
#else
    AssertAndroidStaticApng(r, kResource, SK_ColorRED);
#endif
}

// Regression test for b/562862995: When an APNG has no `fcTL` chunk before
// `IDAT` (`IDAT` is the fallback default image and Frame 0 starts at `fdAT`),
// callers that decode Frame 0 directly via `getImage()`, `getPixels()`,
// `startIncrementalDecode()`, or `SkAndroidCodec::getAndroidPixels()` without
// calling `getFrameCount()` first must still succeed rather than failing with
// `kInvalidParameters` (decoding the green `fdAT` frame on non-Android, or the
// red `IDAT` default image on Android where APNG chunks are ignored).
DEF_TEST(RustPngCodec_apng_ignoring_default_image_without_getFrameCount, r) {
    const char* kResource = "images/apng-test-suite--basic--ignoring-default-image.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    // 1. Direct `getImage()` / `getPixels()` without `getFrameCount()`.
    {
        std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
        REPORTER_ASSERT(r, codec);
        auto [image, result] = codec->getImage();
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
        if (image) {
            SkPixmap pixmap;
            REPORTER_ASSERT(r, image->peekPixels(&pixmap));
            AssertGreenPixel(r, pixmap, 0, 0);
        }
    }

    // 2. Direct `startIncrementalDecode()` + `incrementalDecode()` without `getFrameCount()`.
    {
        std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
        REPORTER_ASSERT(r, codec);
        SkBitmap bitmap;
        REPORTER_ASSERT(r, bitmap.tryAllocPixels(codec->getInfo()));
        SkCodec::Result result =
                codec->startIncrementalDecode(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes());
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
        if (result == SkCodec::kSuccess) {
            result = codec->incrementalDecode();
            REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
            AssertGreenPixel(r, bitmap.pixmap(), 0, 0);
        }
    }

    // 3. Direct `SkAndroidCodec::getAndroidPixels()` (with downsampling) without `getFrameCount()`.
    {
        std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
        REPORTER_ASSERT(r, codec);
        std::unique_ptr<SkAndroidCodec> androidCodec =
                SkAndroidCodec::MakeFromCodec(std::move(codec));
        REPORTER_ASSERT(r, androidCodec);
        SkISize sampledDims = androidCodec->getSampledDimensions(2);
        SkImageInfo sampledInfo = androidCodec->getInfo().makeDimensions(sampledDims);
        SkBitmap bitmap;
        REPORTER_ASSERT(r, bitmap.tryAllocPixels(sampledInfo));
        SkAndroidCodec::AndroidOptions options;
        options.fSampleSize = 2;
        SkCodec::Result result = androidCodec->getAndroidPixels(
                sampledInfo, bitmap.getPixels(), bitmap.rowBytes(), &options);
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
        if (result == SkCodec::kSuccess) {
            AssertGreenPixel(r, bitmap.pixmap(), 0, 0);
        }
    }
#else
    AssertAndroidStaticApng(r, kResource, SK_ColorRED);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-dispose-op-none-basic
//
// This test covers two aspects of `SkPngRustCodec` implementation:
//
// * Blink expects that `onGetFrameCount` returns the total frame count when
//   the complete image resource is available (i.e. a lower frame count should
//   only happen upon `SkCodec::kIncompleteInput`).  Before http://review.skia.org/911038
//   `SkPngRustCodec::onGetFrameCount` would not discover additional frames if
//   previous frames haven't been decoded yet.
// * Skia client (e.g. Blink; or here the testcase) is expected to handle
//   `SkCodecAnimation::DisposalMethod` and populate the target buffer (and
//   `SkCodec::Options::fPriorFrame`) with the expected pixels.  OTOH,
//   `SkPngRustCodec` needs to handle `SkCodecAnimation::Blend` - without this
//   the final frame in this test will contain red pixels.
DEF_TEST(RustPngCodec_apng_dispose_op_none_basic, r) {
    const char* kResource = "images/apng-test-suite--dispose-ops--none-basic.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
    if (!codec) {
        return;
    }

    REPORTER_ASSERT(r, codec->getFrameCount() == 3);
    REPORTER_ASSERT(r, codec->getRepetitionCount() == 0);

    // We should have `FrameInfo` for all 3 frames.
    SkCodec::FrameInfo info[3];
    REPORTER_ASSERT(r, codec->getFrameInfo(0, &info[0]));
    REPORTER_ASSERT(r, codec->getFrameInfo(1, &info[1]));
    REPORTER_ASSERT(r, codec->getFrameInfo(2, &info[2]));

    // The codec should realize that the `SkStream` contains all the data of the
    // first 2 frames.  Currently `SkPngRustCodec::onGetFrameCount` stops after
    // parsing the final, 3rd `fcTL` chunk and therefore it can't tell if the
    // subsequent `fdAT` chunk has been fully received or not.
    REPORTER_ASSERT(r, info[0].fFullyReceived);
    REPORTER_ASSERT(r, info[1].fFullyReceived);
    REPORTER_ASSERT(r, !info[2].fFullyReceived);

    // Spot-check frame metadata.
    REPORTER_ASSERT(r, info[1].fAlphaType == kUnpremul_SkAlphaType);
    REPORTER_ASSERT(r, info[1].fBlend == SkCodecAnimation::Blend::kSrcOver);
    REPORTER_ASSERT(r, info[1].fDisposalMethod == SkCodecAnimation::DisposalMethod::kKeep);
    REPORTER_ASSERT(r, info[1].fDuration == 100, "dur = %d", info[1].fDuration);
    REPORTER_ASSERT(r, info[1].fFrameRect == SkIRect::MakeWH(128, 64));
    REPORTER_ASSERT(r, info[1].fHasAlphaWithinBounds);
    REPORTER_ASSERT(r, info[1].fRequiredFrame == 0);

    // Validate contents of the first frame.
    auto [image, result] = codec->getImage();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    REPORTER_ASSERT(r, image);
    REPORTER_ASSERT(r, image->width() == 128, "width %d != 128", image->width());
    REPORTER_ASSERT(r, image->height() == 64, "height %d != 64", image->height());
    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertRedPixel(r, pixmap, 0, 0, "Frame #0 should be red");

    // Validate contents of the second frame.
    SkCodec::Options options;
    options.fZeroInitialized = SkCodec::kNo_ZeroInitialized;
    options.fSubset = nullptr;
    options.fFrameIndex = 1;  // We want to decode the second frame.
    options.fPriorFrame = 0;  // `pixmap` contains the first frame before `getPixels` call.
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, codec->getPixels(pixmap, &options));
    AssertGreenPixel(r, pixmap, 0, 0, "Frame #1 should be green");

    // Validate contents of the third frame.
    options.fFrameIndex = 2;  // We want to decode the second frame.
    options.fPriorFrame = 1;  // `pixmap` contains the second frame before `getPixels` call.
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, codec->getPixels(pixmap, &options));
    AssertGreenPixel(r, pixmap, 0, 0, "Frame #2 should be green");
#else
    AssertAndroidStaticApng(r, kResource, SK_ColorRED);
#endif
}

// This test covers an incomplete input scenario:
//
// * Only half of 1st frame is available during `onGetFrameCount`.
//   In this situation `onGetFrameCount` may consume the whole input in a
//   (futile in this case) attempt to discover `fcTL` chunks for 2nd and 3rd
//   frame.  This will mean that the input stream is in the middle of the 1st
//   frame - no longer positioned correctly for decoding the 1st frame.
// * Full input is available when subsequently decoding 1st frame.
DEF_TEST(RustPngCodec_apng_dispose_op_none_basic_incomplete_input1, r) {
    const char* path = "images/apng-test-suite--dispose-ops--none-basic.png";
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }
    size_t fullLength = data->size();

    // Initially expose roughly middle of `IDAT` chunk (in this image `fcTL` is
    // present before the `IDAT` chunk and therefore the `IDAT` chunk is part of
    // the animated image).
    constexpr size_t kInitialBytes = 0xAD;
    auto streamForCodec = std::make_unique<HaltingStream>(std::move(data), kInitialBytes);
    HaltingStream* retainedStream = streamForCodec.get();

    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec = SkPngRustDecoder::Decode(std::move(streamForCodec), &result);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (!codec) {
        return;
    }

    SkBitmap bitmap;
    if (!bitmap.tryAllocN32Pixels(codec->dimensions().width(), codec->dimensions().height())) {
        ERRORF(r, "Failed to allocate SkBitmap");
        return;
    }

    // Try to provoke the codec to consume the currently-available part of the
    // input stream.
    //
    // At this point only the metadata for the first frame is available.
    int frameCount = codec->getFrameCount();
    REPORTER_ASSERT(r, frameCount == 1);

    // Make the rest of the input available to the codec.
    retainedStream->addNewData(fullLength);

    // Try to decode the first frame and check its contents.
    sk_sp<SkImage> image;
    std::tie(image, result) = codec->getImage();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    REPORTER_ASSERT(r, image);
    REPORTER_ASSERT(r, image->width() == 128, "width %d != 128", image->width());
    REPORTER_ASSERT(r, image->height() == 64, "height %d != 64", image->height());
    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertRedPixel(r, pixmap, 0, 0, "Frame #0 should be red");
}

// This test covers an incomplete input scenario:
//
// * Only half of 1st frame is available during the initial `incrementalDecode`.
// * Before retrying, `getFrameCount` is called.  This should *not* reposition
//   the stream while in the middle of an active incremental decode.
// * Then we retry `incrementalDecode`.
DEF_TEST(RustPngCodec_apng_dispose_op_none_basic_incomplete_input2, r) {
    const char* path = "images/apng-test-suite--dispose-ops--none-basic.png";
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }
    size_t fullLength = data->size();

    constexpr size_t kInitialBytes = 0x8D;  // Roughly middle of IDAT chunk.
    auto streamForCodec = std::make_unique<HaltingStream>(std::move(data), kInitialBytes);
    HaltingStream* retainedStream = streamForCodec.get();

    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec = SkPngRustDecoder::Decode(std::move(streamForCodec), &result);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (!codec) {
        return;
    }

    SkBitmap bitmap;
    if (!bitmap.tryAllocN32Pixels(codec->dimensions().width(), codec->dimensions().height())) {
        ERRORF(r, "Failed to allocate SkBitmap");
        return;
    }
    const SkPixmap& pixmap = bitmap.pixmap();

    // Fill the `bitmap` with blue pixels to detect which pixels have been filled
    // by the codec during a partially-successful `incrementalDecode`.
    //
    // (The first frame has all red pixels.)
    bitmap.erase(SkColorSetRGB(0, 0, 0xFF), bitmap.bounds());
    AssertBluePixel(r, pixmap, 0, 0);
    AssertBluePixel(r, pixmap, 40, 29);
    AssertBluePixel(r, pixmap, 80, 35);
    AssertBluePixel(r, pixmap, 127, 63);

    // Decode partially-available, incomplete image.
    SkCodec::Options options;
    options.fZeroInitialized = SkCodec::kNo_ZeroInitialized;
    options.fSubset = nullptr;
    options.fFrameIndex = 0;
    options.fPriorFrame = SkCodec::kNoFrame;
    result = codec->startIncrementalDecode(bitmap.pixmap().info(),
                                           bitmap.pixmap().writable_addr(),
                                           bitmap.pixmap().rowBytes(),
                                           &options);
    REPORTER_ASSERT(r, result == SkCodec::kSuccess);
    int rowsDecoded = -1;
    result = codec->incrementalDecode(&rowsDecoded);
    REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
    REPORTER_ASSERT(r, rowsDecoded == 10, "actual rowsDecoded = %d", rowsDecoded);
    AssertRedPixel(r, pixmap, 0, 0);
    AssertBluePixel(r, pixmap, 40, 29);
    AssertBluePixel(r, pixmap, 80, 35);
    AssertBluePixel(r, pixmap, 127, 63);

    // Make the rest of the input available to the codec.
    retainedStream->addNewData(fullLength);

    // Try to provoke the codec to consume further into the input stream (doing
    // this would loose the position inside the currently active incremental
    // decode).
    //
    // At this point metadata of all the frames is available, but the codec
    // shouldn't read the other two `fcTL` chunks during an active incremental
    // decode.
    int frameCount = codec->getFrameCount();
    REPORTER_ASSERT(r, frameCount == 1);

    // Check that all the pixels of the first frame got decoded.
    rowsDecoded = -1;
    result = codec->incrementalDecode(&rowsDecoded);
    REPORTER_ASSERT(r, result == SkCodec::kSuccess);
    REPORTER_ASSERT(r, rowsDecoded == -1);  // Not set when `kSuccess`.
    AssertRedPixel(r, pixmap, 0, 0);
    AssertRedPixel(r, pixmap, 40, 29);
    AssertRedPixel(r, pixmap, 80, 35);
    AssertRedPixel(r, pixmap, 127, 63);
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-blend-op-source-on-solid-colour
DEF_TEST(RustPngCodec_apng_blend_ops_source_on_solid, r) {
    const char* kResource = "images/apng-test-suite--blend-ops--source-on-solid.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
    if (!codec) {
        return;
    }
    sk_sp<SkImage> image = DecodeLastFrame(r, codec.get());
    if (!image) {
        return;
    }

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertGreenPixel(r, pixmap, 0, 0);

    SkCodec::FrameInfo info;
    REPORTER_ASSERT(r, codec->getFrameInfo(1, &info));
    REPORTER_ASSERT(r, info.fBlend == SkCodecAnimation::Blend::kSrc);
    REPORTER_ASSERT(r, info.fRequiredFrame == SkCodec::kNoFrame);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-blend-op-source-on-nearly-transparent-colour
DEF_TEST(RustPngCodec_apng_blend_ops_source_on_nearly_transparent, r) {
    const char* kResource = "images/apng-test-suite--blend-ops--source-on-nearly-transparent.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkImage> image = DecodeLastFrame(r, kResource);
    if (!image) {
        return;
    }

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertPixelColor(r,
                     pixmap,
                     0,
                     0,
                     SkColorSetARGB(0x02, 0x00, 0xFF, 0x00),
                     "Expecting a nearly transparent pixel");
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-blend-op-over-on-solid-and-transparent-colours
DEF_TEST(RustPngCodec_apng_blend_ops_over_on_solid_and_transparent, r) {
    const char* kResource = "images/apng-test-suite--blend-ops--over-on-solid-and-transparent.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkImage> image = DecodeLastFrame(r, kResource);
    if (!image) {
        return;
    }

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertGreenPixel(r, pixmap, 0, 0);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-blend-op-over-repeatedly-with-nearly-transparent-colours
DEF_TEST(RustPngCodec_apng_blend_ops_over_repeatedly, r) {
    const char* kResource = "images/apng-test-suite--blend-ops--over-repeatedly.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkImage> image = DecodeLastFrame(r, kResource);
    if (!image) {
        return;
    }

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    AssertGreenPixel(r, pixmap, 0, 0);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#apng-dispose-op-none-in-region
DEF_TEST(RustPngCodec_apng_regions_dispose_op_none, r) {
    const char* kResource = "images/apng-test-suite--regions--dispose-op-none.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkImage> image = DecodeLastFrame(r, kResource);
    if (!image) {
        return;
    }

    // Check all pixels.
    //
    // * The image (and the first frame) is 128x64
    // * The 2nd frame is 64x32 at offset (32,16)
    // * The 3rd frame is 1x1 at offset (0,0)
    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    for (int y = 0; y < pixmap.height(); y++) {
        for (int x = 0; x < pixmap.width(); x++) {
            AssertGreenPixel(r, pixmap, x, y);
        }
    }
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#num-plays-0
DEF_TEST(RustPngCodec_apng_num_plays_0, r) {
    const char* kResource = "images/apng-test-suite--num-plays--0.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    AssertAnimationRepetitionCount(r, SkCodec::kRepetitionCountInfinite, kResource);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#num-plays-1
DEF_TEST(RustPngCodec_apng_num_plays_1, r) {
    const char* kResource = "images/apng-test-suite--num-plays--1.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    AssertAnimationRepetitionCount(r, 0, kResource);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#num-plays-2
DEF_TEST(RustPngCodec_apng_num_plays_2, r) {
    const char* kResource = "images/apng-test-suite--num-plays--2.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    AssertAnimationRepetitionCount(r, 1, kResource);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

// Test based on
// https://philip.html5.org/tests/apng/tests.html#num-frames-outside-valid-range
//
// In this test the `acTL` chunk sets `num_frames` to `2147483649u` (or `0x80000001u`):
//
// * AFAICT version 1.0 of the APNG spec only says that "0 is not a valid value"
// * The test suite webpage says that at one point the APNG spec said that
//   `num_frames` shall be "limited to the range 0 to (2^31)-1"
DEF_TEST(RustPngCodec_apng_invalid_num_frames_outside_valid_range, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(
            r, "images/apng-test-suite--invalid--num-frames-outside-valid-range.png");
    if (!codec) {
        return;
    }

    // Calling `codec->getFrameCount` exercises the code used to discover and
    // parse `fcTL` chunks on non-Android (where `onGetFrameCount` returns the
    // number of successfully parsed `fcTL` chunks, 1, rather than the raw
    // `acTL.num_frames`), and returns 1 immediately on Android where `acTL` is
    // ignored.
    REPORTER_ASSERT(r, codec->getFrameCount() == 1);
}

DEF_TEST(RustPngCodec_png_swizzling_target_unimplemented, r) {
    std::unique_ptr<SkCodec> codec =
            SkPngRustDecoderDecode(r, "images/apng-test-suite--basic--ignoring-default-image.png");
    if (!codec) {
        return;
    }
    REPORTER_ASSERT(r, codec->getFrameCount() == 1);

    // Ask to decode into an esoteric `SkColorType`:
    //
    // * Unsupported by `SkSwizzler`.
    // * Supported by `SkCodec::conversionSupported`.
    SkImageInfo dstInfo = SkImageInfo::Make(
            codec->dimensions(), kBGRA_10101010_XR_SkColorType, kPremul_SkAlphaType);

    auto [image, result] = codec->getImage(dstInfo);
    REPORTER_ASSERT(r, result == SkCodec::kUnimplemented);
    REPORTER_ASSERT(r, !image);
}

DEF_TEST(RustPngCodec_png_was_encoded_with_16_bits_or_more_per_component, r) {
    struct Test {
        const char* fFilename;
        bool fEncodedWith16bits;
    };
    const std::array<Test, 4> kTests = {
            Test{"images/pngsuite/basn0g04.png", false},  // 4 bit (16 level) grayscale
            Test{"images/pngsuite/basn2c08.png", false},  // 3x8 bits rgb color
            Test{"images/pngsuite/basn2c16.png", true},   // 3x16 bits rgb color
            Test{"images/pngsuite/basn3p01.png", false}   // 1 bit (2 color) paletted
    };
    for (const auto& test : kTests) {
        std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, test.fFilename);
        if (codec) {
            REPORTER_ASSERT(r, codec->hasHighBitDepthEncodedData() == test.fEncodedWith16bits);
        }
    }
}

DEF_TEST(RustPngCodec_png_cicp, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, "images/cicp_pq.png");
    if (!codec) {
        return;
    }

    const skcms_ICCProfile* profile = codec->getICCProfile();
    REPORTER_ASSERT(r, profile);
    if (!profile) {
        return;
    }
    auto cs = SkColorSpace::Make(*profile);
    skcms_TransferFunction tf;
    cs->transferFn(&tf);

    REPORTER_ASSERT(r, skcms_TransferFunction_isPQish(&tf) ||
                       skcms_TransferFunction_isPQ(&tf));
}

DEF_TEST(RustPngCodec_green15x15, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, "images/green15x15.png");
    if (!codec) {
        return;
    }

    SkImageInfo dstInfo = codec->getInfo();
    dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGB());
    auto [image, result] = codec->getImage(dstInfo);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    if (result != SkCodec::kSuccess) {
        return;
    }

    SkPixmap pixmap;
    REPORTER_ASSERT(r, image->peekPixels(&pixmap));
    const SkColor kExpectedColor = SkColorSetARGB(0xFF, 0x00, 0x80, 0x00);
    AssertPixelColor(r, pixmap, 0, 0, kExpectedColor, "Expecting a dark green pixel");
}

DEF_TEST(RustPngCodec_exif_orientation, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, "images/F-exif-chunk-early.png");
    if (!codec) {
        return;
    }

    REPORTER_ASSERT(r, codec->getOrigin() == kRightTop_SkEncodedOrigin);
}

DEF_TEST(RustPngCodec_f16_trc_tables, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, "images/f16-trc-tables.png");
    REPORTER_ASSERT(r, codec);

    const SkImageInfo info = codec->getInfo();
    REPORTER_ASSERT(r, info.colorSpace());

    // Decoding to F16 without color space conversion.
    const SkImageInfo dstInfo = info.makeColorType(kRGBA_F16_SkColorType)
                                    .makeColorSpace(nullptr);
    // This should not crash.
    auto [image, result] = codec->getImage(dstInfo);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
}

DEF_TEST(RustPngCodec_crbug445556737, r) {
    const char* kResource = "images/crbug445556737.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkImage> image = DecodeLastFrame(r, kResource);
    if (!image) {
        return;
    }

    // The main test verification is that there are no assertion failures nor
    // other crashes.  Cursory verification below is supplementary/secondary.
    REPORTER_ASSERT(r, image->height() == 5);
    REPORTER_ASSERT(r, image->width() == 5);
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

DEF_TEST(RustPngCodec_invalid_profile, r) {
    // This image has an gamma value of 0. For parity with Blink, we want to disregard
    // the ICC profile in this case and create the codec without it. This is different
    // than libpng SkPngCodec behavior, which will default to an SRGB icc profile.
    std::unique_ptr<SkCodec> codec =
        SkPngRustDecoderDecode(r, "images/png-zero-gamma-color-profile.png");
    REPORTER_ASSERT(r, codec);

    // There should be no ICC profile.
    REPORTER_ASSERT(r, !codec->getICCProfile());

    // This should not crash.
    auto [image, result] = codec->getImage(codec->getInfo());
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
}

static void test_subset_decode(skiatest::Reporter* r, const char* resource) {
    skiatest::ReporterContext context(r, resource);
    std::unique_ptr<SkStream> stream(GetResourceAsStream(resource));
    REPORTER_ASSERT(r, stream);

    std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
    REPORTER_ASSERT(r, codec);

    const SkImageInfo info = codec->getInfo();

    SkBitmap bm;
    bm.allocPixels(info);
    codec->getPixels(info, bm.getPixels(), bm.rowBytes());

    SkBitmap tiledBM;
    tiledBM.allocPixels(info);

    const int height = info.height();
    const int width = info.width();
    // Note that if numStripes does not evenly divide height there will be an extra
    // stripe.
    const int numStripes = 4;
    const int numVerticalStripes = 2;

    if (numStripes > height || numVerticalStripes > width) {
        // Image is too small.
        return;
    }

    const int stripeHeight = height / numStripes;
    const int stripeWidth = width / numVerticalStripes;

    // Iterate through the image twice. Once to decode odd stripes, and once for even.
    for (int oddEven = 1; oddEven >= 0; oddEven--) {
        for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) {
            for (int xStripe = 0; xStripe < numVerticalStripes; xStripe++) {
                // Calculate all four bounds for the grid section
                const int top = y;
                const int bottom = std::min(y + stripeHeight, height);
                const int left = xStripe * stripeWidth;
                const int right = std::min((xStripe + 1) * stripeWidth, width);

                SkIRect subset = SkIRect::MakeLTRB(left, top, right, bottom);
                SkCodec::Options options;
                options.fSubset = &subset;

                // Decode each subset tile into a tightly allocated temporary bitmap
                // (sized exactly to the subset). This is a valid use case that
                // replicates how clients (like Android) perform subset decodes.
                // Doing so explicitly exercises the tight-allocation path where the
                // stride is exactly the subset row size (lacking full-image stride
                // padding), ensuring fDstRowBytes is calculated correctly.
                SkBitmap subsetBM;
                subsetBM.allocPixels(info.makeDimensions(subset.size()));

                REPORTER_ASSERT(
                        r,
                        SkCodec::kSuccess ==
                                codec->startIncrementalDecode(
                                        info, subsetBM.getPixels(), subsetBM.rowBytes(), &options));
                REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode());

                // Copy the decoded subset into the full tiled bitmap
                REPORTER_ASSERT(r, tiledBM.writePixels(subsetBM.pixmap(), left, top));
            }
        }
    }

    CompareBitmaps(r, bm, tiledBM);
}

DEF_TEST(RustPngCodec_subset, r) {
    // Tests subsets by splitting the image into 8 or 10 different tiles and decoding
    // those each separately, then comparing to the full image decoded.
    test_subset_decode(r, "images/baby_tux.png");
    test_subset_decode(r, "images/plane_interlaced.png");
    test_subset_decode(r, "images/basi3p01.png");
}

DEF_TEST(RustPngCodec_interlaced_animated_blending, r) {
    const char* kResource = "images/interlaced-multiframe-with-blending.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, kResource);
    REPORTER_ASSERT(r, codec);

    // Use incrementalDecode for each frame of this image. This should not crash.
    SkBitmap bm;
    SkImageInfo info = codec->getInfo();
    bm.allocPixels(info);
    REPORTER_ASSERT(r, codec->getFrameCount() == 4);
    for (int i = 0; i < codec->getFrameCount(); ++i) {
        SkCodec::Options options;
        options.fFrameIndex = i;
        options.fPriorFrame = i - 1;
        SkCodec::Result result;
        result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes(), &options);
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
        std::ignore = codec->incrementalDecode();
    }
#else
    AssertAndroidStaticApng(r, kResource);
#endif
}

DEF_TEST(RustPngCodec_sbit565_ihdr16bits, r) {
    std::unique_ptr<SkCodec> codec = SkPngRustDecoderDecode(r, "images/basn2c16-sbit565.png");
    REPORTER_ASSERT(r, codec);

    SkBitmap bm;
    SkImageInfo info = codec->getInfo();
    bm.allocPixels(info);
    REPORTER_ASSERT(r, codec->getFrameCount() == 1);
    SkCodec::Result result;
    result = codec->startIncrementalDecode(info, bm.getPixels(), bm.rowBytes());
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    result = codec->incrementalDecode();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
}

#ifdef SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID
class MockChunkReader : public SkPngChunkReader {
public:
    bool readChunk(const char tag[], const void* data, size_t length) override {
        fChunks.push_back({tag, std::string((const char*)data, length)});
        return true;
    }

    std::vector<std::pair<std::string, std::string>> fChunks;
};

DEF_TEST(RustPngCodec_gainmapDecode, r) {
    auto stream = GetResourceAsStream("images/gainmap.png", false);
    REPORTER_ASSERT(r, stream);

    SkCodec::Result result = SkCodec::kSuccess;
    std::unique_ptr<SkCodec> baseCodec = SkPngRustDecoder::Decode(std::move(stream), &result);
    REPORTER_ASSERT(r, baseCodec);

    std::unique_ptr<SkAndroidCodec> androidCodec =
            SkAndroidCodec::MakeFromCodec(std::move(baseCodec));
    REPORTER_ASSERT(r, androidCodec);

    SkGainmapInfo gainmapInfo;
    std::unique_ptr<SkAndroidCodec> gainmapCodec;
    bool hasGainmap = androidCodec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec);

    REPORTER_ASSERT(r, hasGainmap);
    REPORTER_ASSERT(r, gainmapCodec);

    // Decode the gainmap bitmap.
    SkBitmap gainmapBitmap;
    gainmapBitmap.allocPixels(gainmapCodec->getInfo());
    REPORTER_ASSERT(r,
                    SkCodec::kSuccess == gainmapCodec->getAndroidPixels(gainmapBitmap.info(),
                                                                        gainmapBitmap.getPixels(),
                                                                        gainmapBitmap.rowBytes()));

    // Spot-check the image size and pixels (dimensions should be 32x32 for gainmap.png)
    REPORTER_ASSERT(r, gainmapBitmap.dimensions() == SkISize::Make(32, 32));
    REPORTER_ASSERT(r, gainmapBitmap.getColor(0, 0) == 0xffffffff);
    REPORTER_ASSERT(r, gainmapBitmap.getColor(31, 31) == 0xff000000);

    // Verify some gainmap info values (matching recs in PngGainmapTest.cpp)
    REPORTER_ASSERT(r, gainmapInfo.fType == SkGainmapInfo::Type::kDefault);
    REPORTER_ASSERT(r, gainmapInfo.fBaseImageType == SkGainmapInfo::BaseImageType::kHDR);
    REPORTER_ASSERT(r, gainmapInfo.fDisplayRatioSdr == 2.f);
    REPORTER_ASSERT(r, gainmapInfo.fDisplayRatioHdr == 4.f);
}

DEF_TEST(RustPngCodec_gainmapRewind, r) {
    auto stream = GetResourceAsStream("images/gainmap.png", false);
    REPORTER_ASSERT(r, stream);

    MockChunkReader chunkReader;
    SkCodec::Result result = SkCodec::kSuccess;
    std::unique_ptr<SkCodec> baseCodec =
            SkPngRustDecoder::Decode(std::move(stream), &result, &chunkReader);
    REPORTER_ASSERT(r, baseCodec);
    REPORTER_ASSERT(r, chunkReader.fChunks.size() == 2);

    // Decode pixels the first time.
    SkImageInfo info = baseCodec->getInfo();
    SkBitmap bm;
    bm.allocPixels(info);
    result = baseCodec->getPixels(info, bm.getPixels(), bm.rowBytes());
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    // Should still be 2 (no rewind was needed for first decode).
    REPORTER_ASSERT(r, chunkReader.fChunks.size() == 2);

    // Decode pixels again (forces rewind).
    result = baseCodec->getPixels(info, bm.getPixels(), bm.rowBytes());
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);
    // Should be 4 now because rewind recreated the reader and processed chunks again.
    REPORTER_ASSERT(r, chunkReader.fChunks.size() == 4);
}

DEF_TEST(RustPngCodec_ninepatchPngChunkReader, r) {
    auto stream = GetResourceAsStream("images/ninepatch.png", false);
    REPORTER_ASSERT(r, stream);

    MockChunkReader chunkReader;

    SkCodec::Result result;
    std::unique_ptr<SkCodec> codec(
            SkPngRustDecoder::Decode(std::move(stream), &result, &chunkReader));
    REPORTER_ASSERT(r, codec);
    if (!codec) {
        return;
    }

    // Now compare to the original.
    SkBitmap decodedBm;
    decodedBm.setInfo(codec->getInfo());
    decodedBm.allocPixels();
    result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm.rowBytes());
    REPORTER_ASSERT(r, SkCodec::kSuccess == result);
    REPORTER_ASSERT(r, decodedBm.getColor(0, 0) == SK_ColorBLUE);
    REPORTER_ASSERT(r, chunkReader.fChunks.size() == 3);
    REPORTER_ASSERT(r,
                    chunkReader.fChunks[0] ==
                            std::make_pair(std::string("npOl"), std::string("outline", 8)));
    REPORTER_ASSERT(r,
                    chunkReader.fChunks[1] ==
                            std::make_pair(std::string("npLb"), std::string("layoutBounds", 13)));
    REPORTER_ASSERT(r,
                    chunkReader.fChunks[2] ==
                            std::make_pair(std::string("npTc"), std::string("ninePatchData", 14)));
}

DEF_TEST(RustPngCodec_exactRead, r) {
    // Replicates the Codec_end test from CodecExactReadTest.cpp.
    // Verifies that with the limit reader enabled, we don't overshoot
    // and can decode subsequent images from the same stream.
    for (const char* path : {
                 "images/plane.png",
                 "images/yellow_rose.png",
                 "images/plane_interlaced.png",
         }) {
        sk_sp<SkData> data = GetResourceAsData(path);
        if (!data) {
            continue;
        }

        const int kNumImages = 2;
        const size_t size = data->size();
        sk_sp<SkData> multiData = SkData::MakeUninitialized(size * kNumImages);
        void* dst = multiData->writable_data();
        for (int i = 0; i < kNumImages; i++) {
            memcpy(SkTAddOffset<void>(dst, size * i), data->data(), size);
        }
        data.reset();

        SkMemoryStream stream(std::move(multiData));

        for (int i = 0; i < kNumImages; ++i) {
            SkCodec::Result result;
            std::unique_ptr<SkCodec> codec =
                    SkPngRustDecoder::Decode(std::make_unique<UnowningStream>(&stream), &result);
            if (!codec) {
                ERRORF(r, "Failed to create a codec from %s, iteration %i", path, i);
                continue;
            }

            auto info = codec->getInfo().makeColorType(kN32_SkColorType);
            SkBitmap bm;
            bm.allocPixels(info);

            result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes());
            if (result != SkCodec::kSuccess) {
                ERRORF(r, "Failed to getPixels from %s, iteration %i error %i", path, i, result);
                continue;
            }

            // A full decode must drain the stream through `IEND`, leaving it exactly at the start
            // of the next image.
            REPORTER_ASSERT(r,
                            stream.getPosition() == size * (i + 1),
                            "%s: decode %i left the stream at %zu, expected %zu",
                            path,
                            i,
                            stream.getPosition(),
                            size * (i + 1));
        }
    }
}
#else
DEF_TEST(RustPngCodec_gainmapNoOp, r) {
    auto stream = GetResourceAsStream("images/gainmap.png", false);
    REPORTER_ASSERT(r, stream);

    SkCodec::Result result = SkCodec::kSuccess;
    std::unique_ptr<SkCodec> baseCodec = SkPngRustDecoder::Decode(std::move(stream), &result);
    REPORTER_ASSERT(r, baseCodec);

    std::unique_ptr<SkAndroidCodec> androidCodec =
            SkAndroidCodec::MakeFromCodec(std::move(baseCodec));
    REPORTER_ASSERT(r, androidCodec);

    SkGainmapInfo gainmapInfo;
    std::unique_ptr<SkAndroidCodec> gainmapCodec;
    bool hasGainmap = androidCodec->getGainmapAndroidCodec(&gainmapInfo, &gainmapCodec);

    // When the build flag is off, it should return false (no gainmap).
    REPORTER_ASSERT(r, !hasGainmap);
    REPORTER_ASSERT(r, !gainmapCodec);
}

DEF_TEST(RustPngCodec_exactRead_overshoot, r) {
    // Replicates the Codec_end test from CodecExactReadTest.cpp.
    // Verifies that without the limit reader, the decoder overshoots
    // and fails to decode the second image because the stream is misaligned.
    const char* path = "images/plane.png";
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        return;
    }

    const int kNumImages = 2;
    const size_t size = data->size();
    sk_sp<SkData> multiData = SkData::MakeUninitialized(size * kNumImages);
    void* dst = multiData->writable_data();
    for (int i = 0; i < kNumImages; i++) {
        memcpy(SkTAddOffset<void>(dst, size * i), data->data(), size);
    }
    data.reset();

    SkMemoryStream stream(std::move(multiData));

    for (int i = 0; i < kNumImages; ++i) {
        SkCodec::Result result;
        std::unique_ptr<SkCodec> codec =
                SkPngRustDecoder::Decode(std::make_unique<UnowningStream>(&stream), &result);
        if (i == 0) {
            if (!codec) {
                ERRORF(r, "Failed to create a codec from %s, iteration %i", path, i);
                return;
            }
            auto info = codec->getInfo().makeColorType(kN32_SkColorType);
            SkBitmap bm;
            bm.allocPixels(info);
            result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes());
            if (result != SkCodec::kSuccess) {
                ERRORF(r, "Failed to getPixels from %s, iteration %i error %i", path, i, result);
                return;
            }
        } else {
            // We expect failure on the second iteration because the first decode overshot.
            REPORTER_ASSERT(r, !codec);
        }
    }
}
#endif

DEF_TEST(RustPngCodec_subset_halting, r) {
    sk_sp<SkData> data = GetResourceAsData("images/mandrill_128.png");
    if (!data) {
        ERRORF(r, "Missing resource: images/mandrill_128.png");
        return;
    }

    // Mandrill is 128x128. We target a center 64x64 subset.
    SkIRect subset = SkIRect::MakeXYWH(32, 32, 64, 64);
    SkCodec::Options options;
    options.fSubset = &subset;
    auto makeN32 = [](const SkImageInfo& info) { return info.makeColorType(kN32_SkColorType); };

    std::optional<SkBitmap> bmOneShot = DecodeIncrementalOneShot(r, data, makeN32, options);
    if (!bmOneShot) {
        return;
    }

    const size_t initialLimit = data->size() / 2;
    auto haltingStream = std::make_unique<HaltingStream>(data, initialLimit);
    HaltingStream* retainedStream = haltingStream.get();
    SkBitmap bmHalting;
    std::unique_ptr<SkCodec> codec =
            StartIncrementalDecode(r, std::move(haltingStream), &bmHalting, makeN32, options);
    if (!codec) {
        return;
    }
    int rowsDecoded = -1;
    REPORTER_ASSERT(r, codec->incrementalDecode(&rowsDecoded) == SkCodec::kIncompleteInput);
    REPORTER_ASSERT(r, rowsDecoded > 0 && rowsDecoded < subset.height());
    REPORTER_ASSERT(r, CountWrittenRows(r, bmHalting) == rowsDecoded);
    retainedStream->addNewData(data->size() - initialLimit);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, codec->incrementalDecode());

    CompareBitmaps(r, *bmOneShot, bmHalting);
}

DEF_TEST(RustPngCodec_subsampling, r) {
    for (int sampleSize : {2, 3, 5, 8, 100, 1000}) {
        AssertAndroidDecodeSampling(r, "images/plane.png", sampleSize);
    }
}

DEF_TEST(RustPngCodec_subsampling_interlaced, r) {
    for (int sampleSize : {2, 3, 5, 8, 100, 1000}) {
        AssertAndroidDecodeSampling(r, "images/plane_interlaced.png", sampleSize);
    }
}

DEF_TEST(RustPngCodec_subsampling_subset, r) {
    for (int sampleSize : {2, 3, 5, 8, 100, 1000}) {
        AssertAndroidDecodeSampling(r, "images/plane.png", sampleSize, [](const SkImageInfo& info) {
            return SkIRect::MakeXYWH(info.width() / 2, 0, info.width() / 2, info.height());
        });
    }
}

DEF_TEST(RustPngCodec_subsampling_subset_interlaced, r) {
    for (int sampleSize : {2, 3, 5, 8, 100, 1000}) {
        AssertAndroidDecodeSampling(
                r, "images/plane_interlaced.png", sampleSize, [](const SkImageInfo& info) {
                    return SkIRect::MakeXYWH(0, 1, info.width(), info.height() - 1);
                });
    }
}

// Regression test for a heap buffer overflow.
//
// In `apng-single-frame-with-offset.png`, `IDAT` is a full-canvas 64x64 default
// image, followed by a single `fcTL`/`fdAT` animation frame of size 64x32 at
// y-origin 32:
// * On non-Android (`!SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID`), `onIsAnimated`
//   reports `kNo` for a 1-frame APNG, while Frame 0 uses the `fcTL` sub-rect
//   `(0, 32, 64, 64)`. Since that origin is only valid in a full-canvas
//   destination, the codec must refuse sampled or subset decodes (`kUnimplemented`)
//   rather than writing outside the caller's buffer.
// * On Android (`SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID`), `acTL`/`fcTL` are
//   ignored for `libpng` parity, so the full-canvas 64x64 `IDAT` default image
//   is decoded and sampled/subset decodes succeed.
DEF_TEST(RustPngCodec_apng_offset_frame_does_not_overflow_dst, r) {
    // 64x64 canvas.  The single frame covers the bottom half: y-origin of 32.
    const char* path = "images/apng-single-frame-with-offset.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    struct Case {
        int fSampleSize;
        bool fUseSubset;
        // `0` means `info.minRowBytes()`.  A larger value gives the destination
        // buffer row padding, which makes `rowBytes >= dstInfo.minRowBytes()`
        // even though the buffer holds fewer rows than the full canvas.
        size_t fRowBytes;
    };
    static constexpr Case kCases[] = {
            // Sampling only.  `sampleSize` of 2 halves both dimensions, while a
            // `sampleSize` of 64 makes the destination a single pixel.
            {2, false, 0},
            {64, false, 0},
            {2, false, 256},

            // Subset only.
            {1, true, 0},

            // Subset and sampling.
            {2, true, 0},
    };

    for (const Case& testCase : kCases) {
        AssertAndroidDecodeRefused(
                r, data, testCase.fSampleSize, testCase.fUseSubset, testCase.fRowBytes);
    }
#else
    AssertAndroidStaticApng(r, path);
#endif
}

// A caller that drives `SkCodec` directly (rather than through
// `SkAndroidCodec`) can pass a `rowBytes` that is too small for a full-canvas
// destination.  `SkSampledCodec` does this and then narrows the destination
// with a sampler, but a caller that never asks for a sampler must get a clean
// error instead of a decode into an undersized buffer.
DEF_TEST(RustPngCodec_apng_offset_frame_small_row_bytes, r) {
    const char* path = "images/apng-single-frame-with-offset.png";
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    auto codec = SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr);
    REPORTER_ASSERT(r, codec);
    if (!codec) {
        return;
    }

    const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
    std::vector<uint8_t> buffer(info.computeMinByteSize(), 0x00);
    SkCodec::Result result =
            codec->startIncrementalDecode(info, buffer.data(), info.minRowBytes() / 2);
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);

    result = codec->incrementalDecode();
    REPORTER_ASSERT(r,
                    result == SkCodec::kInvalidParameters,
                    "expected kInvalidParameters, got %s",
                    SkCodec::ResultToString(result));
}

// On non-Android (`!SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID`), the refusal above
// must not change a full-canvas decode: the `fdAT` frame still goes to its
// y=32 origin.  On Android (`SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID`), the
// 64x64 `IDAT` default image is decoded instead, matching `libpng`.
DEF_TEST(RustPngCodec_apng_offset_frame_full_canvas_placement, r) {
    const char* path = "images/apng-single-frame-with-offset.png";
#if !defined(SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID)
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    auto codec = SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr);
    if (!codec) {
        ERRORF(r, "Failed to create a codec for %s", path);
        return;
    }

    for (SkAlphaType alphaType : {kUnpremul_SkAlphaType, kPremul_SkAlphaType}) {
        SkBitmap bm;
        bm.allocPixels(codec->getInfo().makeColorType(kN32_SkColorType).makeAlphaType(alphaType));
        // The APNG spec says the output buffer starts as transparent black.
        bm.eraseColor(SK_ColorTRANSPARENT);

        SkCodec::Result result = codec->getPixels(bm.pixmap());
        REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);

        // Rows above the frame stay transparent.  The frame fills rows 32..63.
        REPORTER_ASSERT(r, bm.getColor(0, 0) == SK_ColorTRANSPARENT);
        REPORTER_ASSERT(r, bm.getColor(63, 31) == SK_ColorTRANSPARENT);
        REPORTER_ASSERT(r, bm.getColor(0, 32) == SK_ColorMAGENTA);
        REPORTER_ASSERT(r, bm.getColor(63, 63) == SK_ColorMAGENTA);
    }
#else
    AssertAndroidStaticApng(r, path);
#endif
}

#ifdef SK_CODEC_USES_PNG_WITH_RUST_FOR_ANDROID
// Decodes a top subset of `path` and asserts that the decode stopped short of the end of the
// stream, i.e. that `finish_decoding()` was not called. libpng stops early the same way: its row
// callbacks longjmp out once the requested rows have been written, and only a whole-image decode
// reads through `IEND` (`SkPngCodec.cpp`).
// A non-interlaced decode stops inside `IDAT`. An interlaced one has to read every Adam7 pass, and
// the `png` crate consumes `IEND`'s 8-byte length+type header while detecting the end of the
// frame, so it stops with only the 4-byte CRC left.
// Only `for_android` builds limit reads to chunk boundaries; elsewhere the `BufReader` inside the
// `png` crate may have buffered the rest of the file, so the position says nothing.
static void AssertPartialDecodeStopsBeforeIend(
        skiatest::Reporter* r,
        const char* path,
        bool interlaced,
        int sampleSize,
        std::function<SkIRect(const SkImageInfo&)> getSubset = nullptr) {
    sk_sp<SkData> data = GetResourceAsData(path);
    if (!data) {
        ERRORF(r, "Missing resource: %s", path);
        return;
    }

    SkMemoryStream memStream(data);
    std::optional<SkBitmap> bm = DecodeAndroidPixels(
            r,
            SkPngRustDecoder::Decode(std::make_unique<UnowningStream>(&memStream), nullptr),
            sampleSize,
            std::move(getSubset));
    REPORTER_ASSERT(r, bm.has_value());

    // A non-interlaced subset/sampled decode never reads into `IEND` (at most the end of `IDAT`,
    // i.e. `<= data->size() - kIendChunkSize`). An interlaced one reads the 8-byte `IEND` header
    // while detecting end-of-frame, but stops before the 4-byte `IEND` CRC (`< data->size()`).
    const size_t limit = interlaced ? data->size() : data->size() - kIendChunkSize + 1;
    REPORTER_ASSERT(r,
                    memStream.getPosition() < limit,
                    "%s: decode read too far, pos=%zu (expected < %zu, file is %zu, IEND at %zu)",
                    path,
                    memStream.getPosition(),
                    limit,
                    data->size(),
                    data->size() - kIendChunkSize);
}

// Regression tests for b/562939096:
// A subset or subsampled decode must stop after the last row it needs, rather than reading and
// CRC-checking the rest of the PNG stream through `IEND` via `finish_decoding()`.
DEF_TEST(RustPngCodec_subsetDoesNotReadToIend, r) {
    AssertPartialDecodeStopsBeforeIend(
            r,
            "images/mandrill_128.png",
            /*interlaced=*/false,
            /*sampleSize=*/1,
            [](const SkImageInfo& info) { return SkIRect::MakeWH(info.width(), 16); });
}

DEF_TEST(RustPngCodec_subsetDoesNotReadToIend_interlaced, r) {
    AssertPartialDecodeStopsBeforeIend(
            r,
            "images/plane_interlaced.png",
            /*interlaced=*/true,
            /*sampleSize=*/1,
            [](const SkImageInfo& info) { return SkIRect::MakeWH(info.width(), 16); });
}

DEF_TEST(RustPngCodec_subsamplingDoesNotReadToIend, r) {
    AssertPartialDecodeStopsBeforeIend(
            r, "images/mandrill_128.png", /*interlaced=*/false, /*sampleSize=*/2);
}

DEF_TEST(RustPngCodec_subsamplingDoesNotReadToIend_interlaced, r) {
    AssertPartialDecodeStopsBeforeIend(
            r, "images/plane_interlaced.png", /*interlaced=*/true, /*sampleSize=*/2);
}
#endif

// A top subset must decode even if everything after the rows it needs is missing.
DEF_TEST(RustPngCodec_subsetOfTruncatedFile, r) {
    static constexpr char kPath[] = "images/mandrill_128.png";
    sk_sp<SkData> data = GetResourceAsData(kPath);
    if (!data) {
        ERRORF(r, "Missing resource: %s", kPath);
        return;
    }

    auto topSubset = [](const SkImageInfo& info) { return SkIRect::MakeWH(info.width(), 16); };
    std::optional<SkBitmap> refBm = DecodeAndroidPixels(
            r,
            SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(data), nullptr),
            /*sampleSize=*/1,
            topSubset);
    REPORTER_ASSERT(r, refBm.has_value());

    sk_sp<SkData> truncatedHalf = SkData::MakeSubset(data.get(), 0, data->size() / 2);
    std::optional<SkBitmap> bm = DecodeAndroidPixels(
            r,
            SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(truncatedHalf), nullptr),
            /*sampleSize=*/1,
            topSubset);
    REPORTER_ASSERT(r, bm.has_value());
    if (refBm && bm) {
        CompareBitmaps(r, *refBm, *bm);
    }
}

// Regression tests for b/562802947:
// When all scanlines and the IDAT chunk have been decoded, a corrupt or truncated trailing `IEND`
// CRC in `finish_decoding()` must not cause the decode to fail or zero-fill the output bitmap
// (matching `SkPngCodec` / libpng `png_read_end` behavior and Chrome's `SkPngRustCodec`).
DEF_TEST(RustPngCodec_missingOrCorruptIendSucceeds, r) {
    AssertDecodesWithBrokenIendTail(r, "images/mandrill_128.png");
}

DEF_TEST(RustPngCodec_missingOrCorruptIendSucceeds_interlaced, r) {
    AssertDecodesWithBrokenIendTail(r, "images/plane_interlaced.png");
}

// `images/color_wheel_with_profile.png` is RGBA8 with an `iCCP` chunk, so this covers the
// `read_row` decode path (see `AssertDecodesWithBrokenIendTail`).
DEF_TEST(RustPngCodec_missingOrCorruptIendSucceeds_readRow, r) {
    AssertDecodesWithBrokenIendTail(r, "images/color_wheel_with_profile.png");
}

DEF_TEST(RustPngCodec_missingOrCorruptIendSucceeds_sampled, r) {
    AssertSampledDecodeWithBrokenIendTail(r, "images/mandrill_128.png", /*sampleSize=*/2);
}

// Regression tests for b/565484678 on `images/plane_interlaced.png` (250x126, 8-bit RGB with
// `tRNS`, expanded to RGBA8 -> 4 bytes per encoded pixel = 1000 bytes/row).
//
// First two tests verify that `fPreblendBuffer` in `SkPngRustCodec` is charged against
// `fMaxDecodeMemory` (`allocateFromBudget`) for interlaced sampled/subset decodes, which buffer
// all 126 rows in `fPreblendBuffer`.
DEF_TEST(RustPngCodec_interlacedPreblendBufferBudget_sampled, r) {
    constexpr size_t kEncodedRowBytes = 250 * 4;
    constexpr size_t kFullBufferBytes = 126 * kEncodedRowBytes;

    AssertDecodeBudget(r,
                       "images/plane_interlaced.png",
                       kFullBufferBytes,
                       [&](std::unique_ptr<SkCodec> codec,
                           size_t maxDecodeMemory,
                           SkCodec::Result expectedResult) {
                           return DecodeAndroidPixels(r,
                                                      std::move(codec),
                                                      /*sampleSize=*/2,
                                                      /*getSubset=*/nullptr,
                                                      maxDecodeMemory,
                                                      expectedResult);
                       });
}

DEF_TEST(RustPngCodec_interlacedPreblendBufferBudget_subset, r) {
    constexpr size_t kEncodedRowBytes = 250 * 4;
    constexpr size_t kFullBufferBytes = 126 * kEncodedRowBytes;

    AssertDecodeBudget(r,
                       "images/plane_interlaced.png",
                       kFullBufferBytes,
                       [&](std::unique_ptr<SkCodec> codec,
                           size_t maxDecodeMemory,
                           SkCodec::Result expectedResult) {
                           return DecodeAndroidPixels(
                                   r,
                                   std::move(codec),
                                   /*sampleSize=*/1,
                                   [](const SkImageInfo& info) {
                                       return SkIRect::MakeXYWH(
                                               0, 1, info.width(), info.height() - 1);
                                   },
                                   maxDecodeMemory,
                                   expectedResult);
                       });
}

// Next tests verify that the single-row interlaced scratch buffers
// (`fDecodedInterlacedFullWidthRow`, `fXformedInterlacedRow`, and `SkPngCodecBase::fStorage`) are
// charged against `fMaxDecodeMemory` even when `fPreblendBuffer` is empty (full-image decode of a
// non-blended interlaced PNG).
//
// Note: `plane_interlaced.png` has no embedded ICC profile (`getEncodedInfo().profile() ==
// nullptr`), so `makeColorSpace(nullptr)` is required for `canReadRow()` to match when
// `alphaType == kUnpremul_SkAlphaType`.
DEF_TEST(RustPngCodec_interlacedRowBufferBudget_readRow, r) {
    // `kUnpremul_SkAlphaType` + `kRGBA_8888_SkColorType` + `nullptr` colorSpace takes the
    // `canReadRow()` path, which only allocates `fDecodedInterlacedFullWidthRow`
    // (250 * 4 = 1000 bytes).
    constexpr size_t kEncodedRowBytes = 250 * 4;

    AssertDecodeBudget(r,
                       "images/plane_interlaced.png",
                       kEncodedRowBytes,
                       [&](std::unique_ptr<SkCodec> codec,
                           size_t maxDecodeMemory,
                           SkCodec::Result expectedResult) {
                           return DecodePixels(
                                   r,
                                   std::move(codec),
                                   [](const SkImageInfo& info) {
                                       return info.makeColorType(kRGBA_8888_SkColorType)
                                               .makeAlphaType(kUnpremul_SkAlphaType)
                                               .makeColorSpace(nullptr);
                                   },
                                   MakeBudgetOptions(maxDecodeMemory),
                                   expectedResult);
                       });
}

DEF_TEST(RustPngCodec_interlacedRowBufferBudget_xform, r) {
    // `kPremul_SkAlphaType` + `nullptr` colorSpace takes the `!canReadRow()`
    // (`incrementalDecodeXForm`) path with `kSwizzleOnly_XformMode`, which allocates both
    // `fDecodedInterlacedFullWidthRow` (1000 bytes) and `fXformedInterlacedRow` (1000 bytes).
    constexpr size_t kEncodedRowBytes = 250 * 4;
    constexpr size_t kDstRowBytes = 250 * 4;

    AssertDecodeBudget(r,
                       "images/plane_interlaced.png",
                       kEncodedRowBytes + kDstRowBytes,
                       [&](std::unique_ptr<SkCodec> codec,
                           size_t maxDecodeMemory,
                           SkCodec::Result expectedResult) {
                           return DecodePixels(
                                   r,
                                   std::move(codec),
                                   [](const SkImageInfo& info) {
                                       return info.makeColorType(kRGBA_8888_SkColorType)
                                               .makeAlphaType(kPremul_SkAlphaType)
                                               .makeColorSpace(nullptr);
                                   },
                                   MakeBudgetOptions(maxDecodeMemory),
                                   expectedResult);
                       });
}

// With `kYes_ZeroInitialized`, `fSwizzler` skips writing leading transparent pixels, so
// `fXformedInterlacedRow` must be re-zeroed before each row, or pixels from the previous row
// leak into them. `plane_interlaced.png` has `tRNS` transparency, and `kPremul_SkAlphaType`
// takes the `incrementalDecodeXForm` path.
DEF_TEST(RustPngCodec_interlacedXformZeroInitialized, r) {
    auto decode = [&](SkCodec::ZeroInitialized zeroInit) {
        SkCodec::Options options;
        options.fZeroInitialized = zeroInit;
        return DecodePixels(
                r,
                SkPngRustDecoderDecode(r, "images/plane_interlaced.png"),
                [](const SkImageInfo& info) {
                    return info.makeColorType(kRGBA_8888_SkColorType)
                            .makeAlphaType(kPremul_SkAlphaType)
                            .makeColorSpace(nullptr);
                },
                options);
    };

    std::optional<SkBitmap> zeroInitBm = decode(SkCodec::kYes_ZeroInitialized);
    std::optional<SkBitmap> noZeroInitBm = decode(SkCodec::kNo_ZeroInitialized);
    if (zeroInitBm && noZeroInitBm) {
        CompareBitmaps(r, *noZeroInitBm, *zeroInitBm);
    }
}

DEF_TEST(RustPngCodec_interlacedRowBufferBudget_colorXform, r) {
    // Decoding into a non-sRGB color space (`SkColorSpace::MakeSRGBLinear()`) activates
    // `SkPngCodecBase::allocateStorage` (`fStorage`, 1000 bytes) in addition to
    // `fDecodedInterlacedFullWidthRow` (1000 bytes) and `fXformedInterlacedRow` (1000 bytes).
    constexpr size_t kEncodedRowBytes = 250 * 4;
    constexpr size_t kDstRowBytes = 250 * 4;
    constexpr size_t kColorXformBytes = 250 * 4;

    AssertDecodeBudget(r,
                       "images/plane_interlaced.png",
                       kEncodedRowBytes + kDstRowBytes + kColorXformBytes,
                       [&](std::unique_ptr<SkCodec> codec,
                           size_t maxDecodeMemory,
                           SkCodec::Result expectedResult) {
                           return DecodePixels(
                                   r,
                                   std::move(codec),
                                   [](const SkImageInfo& info) {
                                       return info.makeColorType(kRGBA_8888_SkColorType)
                                               .makeAlphaType(kPremul_SkAlphaType)
                                               .makeColorSpace(SkColorSpace::MakeSRGBLinear());
                                   },
                                   MakeBudgetOptions(maxDecodeMemory),
                                   expectedResult);
                       });
}

// Verifies that the top `rowsDecoded` rows of `actualBm` match `expectedBm`, and that any
// remaining rows (`rowsDecoded .. height - 1`) were zero-filled by `SkCodec::fillIncompleteImage`.
static void AssertPartialBitmapMatches(skiatest::Reporter* r,
                                       const SkBitmap& actualBm,
                                       const SkBitmap& expectedBm,
                                       int rowsDecoded) {
    const SkIRect decodedRect = SkIRect::MakeWH(actualBm.width(), rowsDecoded);
    SkBitmap actualDecodedRows, expectedDecodedRows;
    REPORTER_ASSERT(r, actualBm.extractSubset(&actualDecodedRows, decodedRect));
    REPORTER_ASSERT(r, expectedBm.extractSubset(&expectedDecodedRows, decodedRect));
    CompareBitmaps(r, actualDecodedRows, expectedDecodedRows);

    if (rowsDecoded < actualBm.height()) {
        SkBitmap remainingRows;
        REPORTER_ASSERT(
                r,
                actualBm.extractSubset(
                        &remainingRows,
                        SkIRect::MakeLTRB(0, rowsDecoded, actualBm.width(), actualBm.height())));
        REPORTER_ASSERT(r, CountWrittenRows(r, remainingRows, SK_ColorTRANSPARENT) == 0);
    }
}

// Regression test helper for b/562804783: like `SkPngCodec`, `SkPngRustCodec` must report
// `rowsDecoded` for `kErrorInInput` (not just `kIncompleteInput`), so that callers such as
// `SkCodec::getPixels` keep the rows decoded before the error instead of filling the whole image.
static void AssertRowsDecodedReportedOnErrorInInput(skiatest::Reporter* r,
                                                    SkColorType colorType,
                                                    SkAlphaType alphaType,
                                                    sk_sp<SkColorSpace> colorSpace) {
    // Non-interlaced RGBA8 image whose image data is split across 12 `IDAT` chunks.
    static constexpr char kPath[] = "images/text.png";
    sk_sp<SkData> data = GetResourceAsData(kPath);
    if (!data) {
        ERRORF(r, "Missing resource: %s", kPath);
        return;
    }
    sk_sp<SkData> corruptData = WithCorruptIdatCrc(data.get(), /*idatIndex=*/5);
    if (!corruptData) {
        ERRORF(r, "Failed to corrupt IDAT CRC in %s", kPath);
        return;
    }

    auto makeDstInfo = [&](const SkImageInfo& info) {
        return info.makeColorType(colorType).makeAlphaType(alphaType).makeColorSpace(colorSpace);
    };
    std::optional<SkBitmap> refBitmap = DecodePixels(
            r, SkPngRustDecoder::Decode(SkMemoryStream::Make(data), nullptr), makeDstInfo);
    if (!refBitmap) {
        return;
    }

    SkBitmap bitmap;
    std::unique_ptr<SkCodec> codec =
            StartIncrementalDecode(r, SkMemoryStream::Make(corruptData), &bitmap, makeDstInfo);
    if (!codec) {
        return;
    }
    const SkImageInfo& info = bitmap.info();
    int rowsDecoded = -1;
    SkCodec::Result result = codec->incrementalDecode(&rowsDecoded);
    REPORTER_ASSERT(r,
                    result == SkCodec::kErrorInInput,
                    "actualResult=\"%s\" != kErrorInInput",
                    SkCodec::ResultToString(result));
    REPORTER_ASSERT(r,
                    rowsDecoded > 0 && rowsDecoded < info.height(),
                    "rowsDecoded=%d, height=%d",
                    rowsDecoded,
                    info.height());
    REPORTER_ASSERT(r, CountWrittenRows(r, bitmap) == rowsDecoded);
    if (rowsDecoded <= 0 || rowsDecoded >= info.height()) {
        return;
    }

    // `getPixels` keeps the decoded rows, and only fills the rows after them.
    if (std::optional<SkBitmap> getPixelsBm =
                DecodePixels(r,
                             SkPngRustDecoder::Decode(SkMemoryStream::Make(corruptData), nullptr),
                             makeDstInfo,
                             /*options=*/{},
                             SkCodec::kErrorInInput)) {
        AssertPartialBitmapMatches(r, *getPixelsBm, *refBitmap, rowsDecoded);
    }
}

// kRGBA_8888 + kUnpremul without a color space on an RGBA8 source without `iCCP` satisfies
// `canReadRow()`, i.e. goes through `incrementalDecode` (`read_row`).
DEF_TEST(RustPngCodec_rowsDecodedReportedOnErrorInInput_readRow, r) {
    AssertRowsDecodedReportedOnErrorInInput(
            r, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, /*colorSpace=*/nullptr);
}

DEF_TEST(RustPngCodec_rowsDecodedReportedOnErrorInInput_xform, r) {
    AssertRowsDecodedReportedOnErrorInInput(
            r, kN32_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
}

static int AssertInterlacedIncrementalDecodeHalting(
        skiatest::Reporter* r,
        SkColorType colorType,
        SkAlphaType alphaType,
        std::optional<int> expectedRowsAtHalt = std::nullopt,
        std::optional<size_t> initialLimit = std::nullopt,
        const SkIRect* subset = nullptr,
        SkCodec::ZeroInitialized zeroInit = SkCodec::kNo_ZeroInitialized) {
    static constexpr char kPath[] = "images/plane_interlaced.png";
    sk_sp<SkData> data = GetResourceAsData(kPath);
    if (!data) {
        ERRORF(r, "Missing resource: %s", kPath);
        return 0;
    }
    const size_t limit = initialLimit.value_or(data->size() / 2);

    // `plane_interlaced.png` has no embedded ICC profile, so `makeColorSpace(nullptr)` is required
    // for `kRGBA_8888_SkColorType` + `kUnpremul_SkAlphaType` to satisfy `canReadRow()`.
    auto makeDstInfo = [colorType, alphaType](const SkImageInfo& info) {
        return info.makeColorType(colorType).makeAlphaType(alphaType).makeColorSpace(nullptr);
    };
    SkCodec::Options options;
    options.fSubset = subset;
    options.fZeroInitialized = zeroInit;

    auto stream = std::make_unique<HaltingStream>(data, limit);
    HaltingStream* retainedStream = stream.get();
    SkBitmap bm;
    std::unique_ptr<SkCodec> codec =
            StartIncrementalDecode(r, std::move(stream), &bm, makeDstInfo, options);
    if (!codec) {
        return 0;
    }

    int rowsDecoded = -1;
    SkCodec::Result result = codec->incrementalDecode(&rowsDecoded);
    REPORTER_ASSERT(r, result == SkCodec::kIncompleteInput);
    if (zeroInit == SkCodec::kNo_ZeroInitialized) {
        const int writtenRows = CountWrittenRows(r, bm);
        REPORTER_ASSERT(r,
                        rowsDecoded == writtenRows,
                        "API rowsDecoded (%d) != written rows (%d)",
                        rowsDecoded,
                        writtenRows);
    }
    if (expectedRowsAtHalt.has_value()) {
        REPORTER_ASSERT(r,
                        rowsDecoded == *expectedRowsAtHalt,
                        "rowsDecoded (%d) != expectedRowsAtHalt (%d)",
                        rowsDecoded,
                        *expectedRowsAtHalt);
    } else {
        REPORTER_ASSERT(r,
                        rowsDecoded > 0 && rowsDecoded < bm.height() && rowsDecoded % 8 == 0,
                        "Unexpected rowsDecoded (%d) for height %d",
                        rowsDecoded,
                        bm.height());
    }

    // For full-image decodes, also verify `SkCodec::getPixels` (`onGetPixels`) on the truncated
    // prefix: the top `rowsDecoded` rows must match `bm` and any remaining rows must be
    // zero-filled by `SkCodec::fillIncompleteImage`.
    if (!subset && zeroInit == SkCodec::kNo_ZeroInitialized && rowsDecoded > 0) {
        sk_sp<SkData> truncated = SkData::MakeSubset(data.get(), 0, limit);
        if (std::optional<SkBitmap> getPixelsBm = DecodePixels(
                    r,
                    SkPngRustDecoder::Decode(std::make_unique<SkMemoryStream>(std::move(truncated)),
                                             nullptr),
                    makeDstInfo,
                    options,
                    SkCodec::kIncompleteInput)) {
            AssertPartialBitmapMatches(r, *getPixelsBm, bm, rowsDecoded);
        }
    }

    retainedStream->addNewData(data->size() - limit);
    result = codec->incrementalDecode();
    REPORTER_ASSERT_SUCCESSFUL_CODEC_RESULT(r, result);

    if (std::optional<SkBitmap> refBm = DecodeIncrementalOneShot(r, data, makeDstInfo, options)) {
        CompareBitmaps(r, *refBm, bm);
    }
    return rowsDecoded;
}

static void AssertInterlacedAndroidDecodeHalting(
        skiatest::Reporter* r,
        int sampleSize,
        std::function<SkIRect(const SkImageInfo&)> getSubset = nullptr) {
    static constexpr char kPath[] = "images/plane_interlaced.png";
    sk_sp<SkData> data = GetResourceAsData(kPath);
    if (!data) {
        ERRORF(r, "Missing resource: %s", kPath);
        return;
    }

    const struct {
        size_t fLimit;
        bool fExpectPartialHeight;
    } kLimits[] = {
            {300, true},
            {data->size() / 2, false},
    };
    for (const auto& [limit, expectPartialHeight] : kLimits) {
        std::optional<SkBitmap> rustBm = DecodeAndroidPixels(
                r,
                SkPngRustDecoder::Decode(std::make_unique<HaltingStream>(data, limit), nullptr),
                sampleSize,
                getSubset,
                /*maxDecodeMemory=*/0,
                SkCodec::kIncompleteInput);
        if (!rustBm) {
            continue;
        }

        // Every pixel must be overwritten (rows `0 .. decodedRows - 1` by the codec and the
        // remaining rows by `SkCodec::fillIncompleteImage` with `SK_ColorTRANSPARENT`). Counting
        // up to the last non-`SK_ColorTRANSPARENT` row measures `decodedRows` because, for
        // `plane_interlaced.png` (full image and the `(10, 10, 100, 50)` subset), the last decoded
        // row at both halting points contains non-transparent airplane pixels in the sampled
        // columns (earlier rows may be fully transparent, which is fine).
        REPORTER_ASSERT(r, CountWrittenRows(r, *rustBm) == rustBm->height());
        const int decodedRows = CountNonSentinelRows(*rustBm, SK_ColorTRANSPARENT);
        if (expectPartialHeight) {
            REPORTER_ASSERT(r, decodedRows > 0 && decodedRows < rustBm->height());
        } else {
            REPORTER_ASSERT(r, decodedRows == rustBm->height());
        }

#if defined(SK_CODEC_DECODES_PNG_WITH_LIBPNG)
        std::optional<SkBitmap> libpngBm = DecodeAndroidPixels(
                r,
                SkPngDecoder::Decode(std::make_unique<HaltingStream>(data, limit), nullptr),
                sampleSize,
                getSubset,
                /*maxDecodeMemory=*/0,
                SkCodec::kIncompleteInput);
        if (libpngBm) {
            REPORTER_ASSERT(r, CountWrittenRows(r, *libpngBm) == libpngBm->height());
            const int libpngDecodedRows = CountNonSentinelRows(*libpngBm, SK_ColorTRANSPARENT);
            REPORTER_ASSERT(r,
                            decodedRows == libpngDecodedRows,
                            "decodedRows mismatch at halt: Rust %d != Libpng %d",
                            decodedRows,
                            libpngDecodedRows);
        }
#endif
    }
}

static constexpr int kPlaneInterlacedHeight = 126;

// Tests progressive (halting + resume) decoding of an interlaced PNG across both decode paths:
// * `kRGBA_8888_SkColorType` + `kUnpremul_SkAlphaType` (`canReadRow()` -> `incrementalDecode`)
// * `kN32_SkColorType` + `kPremul_SkAlphaType` (`!canReadRow()` -> `incrementalDecodeXForm`)
DEF_TEST(RustPngCodec_interlacedHalting, r) {
    for (const auto& [colorType, alphaType] : {
                 std::make_pair(kRGBA_8888_SkColorType, kUnpremul_SkAlphaType),
                 std::make_pair(kN32_SkColorType, kPremul_SkAlphaType),
         }) {
        // At 300 bytes, Pass 1 has partially completed (`0 < rowsDecoded < 126`, multiple of 8).
        AssertInterlacedIncrementalDecodeHalting(
                r, colorType, alphaType, /*expectedRowsAtHalt=*/std::nullopt, /*initialLimit=*/300);
        // At half the file (`initialLimit = std::nullopt`), Pass 1's 16 scanlines have completed
        // and splatted all 126 rows (clamped from 16 * 8 = 128), so every pixel in the destination
        // has been approximated by the closest already-decoded Adam7 sample.
        AssertInterlacedIncrementalDecodeHalting(
                r, colorType, alphaType, /*expectedRowsAtHalt=*/kPlaneInterlacedHeight);
    }
}

DEF_TEST(RustPngCodec_interlacedSubsetHalting, r) {
    const int fullImageRowsAtHalt =
            AssertInterlacedIncrementalDecodeHalting(r,
                                                     kN32_SkColorType,
                                                     kPremul_SkAlphaType,
                                                     /*expectedRowsAtHalt=*/std::nullopt,
                                                     /*initialLimit=*/300);
    if (fullImageRowsAtHalt <= 0) {
        return;
    }

    const SkIRect kSubset = SkIRect::MakeXYWH(10, 10, 100, 50);
    const int expectedSubsetRowsAtHalt =
            std::clamp(fullImageRowsAtHalt - kSubset.top(), 0, kSubset.height());
    for (SkCodec::ZeroInitialized zeroInit :
         {SkCodec::kNo_ZeroInitialized, SkCodec::kYes_ZeroInitialized}) {
        AssertInterlacedIncrementalDecodeHalting(r,
                                                 kN32_SkColorType,
                                                 kPremul_SkAlphaType,
                                                 expectedSubsetRowsAtHalt,
                                                 /*initialLimit=*/300,
                                                 &kSubset,
                                                 zeroInit);
        // At half the file, all 50 subset rows are flushed.
        AssertInterlacedIncrementalDecodeHalting(r,
                                                 kN32_SkColorType,
                                                 kPremul_SkAlphaType,
                                                 /*expectedRowsAtHalt=*/kSubset.height(),
                                                 /*initialLimit=*/std::nullopt,
                                                 &kSubset,
                                                 zeroInit);
    }

    // A subset starting below the decoded rows at halt reports 0 rows decoded.
    const SkIRect kLowerSubset =
            SkIRect::MakeLTRB(10, fullImageRowsAtHalt, 110, kPlaneInterlacedHeight);
    AssertInterlacedIncrementalDecodeHalting(r,
                                             kN32_SkColorType,
                                             kPremul_SkAlphaType,
                                             /*expectedRowsAtHalt=*/0,
                                             /*initialLimit=*/300,
                                             &kLowerSubset);
}

DEF_TEST(RustPngCodec_interlacedSamplingHalting, r) {
    for (int sampleSize : {2, 3, 8}) {
        AssertInterlacedAndroidDecodeHalting(r, sampleSize);
    }
}

DEF_TEST(RustPngCodec_interlacedSamplingSubsetHalting, r) {
    for (int sampleSize : {1, 2, 3, 8}) {
        AssertInterlacedAndroidDecodeHalting(r, sampleSize, [](const SkImageInfo&) {
            return SkIRect::MakeXYWH(10, 10, 100, 50);
        });
    }
}
