// Copyright 2014 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxcodec/progressive_decoder.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "build/build_config.h"
#include "core/fxcodec/fx_codec.h"
#include "core/fxcodec/gif/cfx_gifcontext.h"
#include "core/fxcodec/progressive_decoder_context.h"
#include "core/fxcodec/tiff/libtiff_tiff_context.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/notreached.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/dib/cfx_cmyk_to_srgb.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"

#ifndef PDF_ENABLE_XFA
#error "XFA only"
#endif

#if defined(PDF_ENABLE_RUST_BMP)
#include "core/fxcodec/bmp/rust_bmp_context.h"
#else
#include "core/fxcodec/bmp/cfx_bmpcontext.h"
#endif

#if defined(PDF_ENABLE_RUST_JPEG)
#include "core/fxcodec/jpeg/rust_jpeg_context.h"
#else
#include "core/fxcodec/jpeg/libjpeg_jpeg_context.h"
#endif

#if defined(PDF_ENABLE_RUST_PNG)
#include "core/fxcodec/png/rust_png_context.h"
#else
#include "core/fxcodec/png/libpng_png_context.h"
#endif

namespace fxcodec {

namespace {

constexpr size_t kBlockSize = 4096;

std::unique_ptr<ProgressiveDecoderContext> CreateDecoderContext(
    FXCODEC_IMAGE_TYPE type,
    ProgressiveDecoder* delegate) {
  switch (type) {
    case FXCODEC_IMAGE_BMP:
#if defined(PDF_ENABLE_RUST_BMP)
      return std::make_unique<RustBmpContext>(delegate);
#else
      return std::make_unique<CFX_BmpContext>(delegate);
#endif
    case FXCODEC_IMAGE_GIF:
      return std::make_unique<CFX_GifContext>(delegate);
    case FXCODEC_IMAGE_JPG: {
#if defined(PDF_ENABLE_RUST_JPEG)
      return std::make_unique<RustJpegContext>(delegate);
#else
      auto context = std::make_unique<LibjpegJpegContext>(delegate);
      if (!context->create_ok_) {
        return nullptr;
      }
      return context;
#endif
    }
    case FXCODEC_IMAGE_PNG:
#if defined(PDF_ENABLE_RUST_PNG)
      return std::make_unique<RustPngContext>(delegate);
#else
    {
      auto context = std::make_unique<LibpngPngContext>(delegate);
      if (!context->png_ || !context->info_) {
        return nullptr;
      }
      return context;
    }
#endif
    default:
      return nullptr;
  }
}

}  // namespace

ProgressiveDecoder::ProgressiveDecoder() = default;

ProgressiveDecoder::~ProgressiveDecoder() = default;

bool ProgressiveDecoder::ReadMoreData(std::optional<uint32_t> rcd_pos,
                                      FXCODEC_STATUS* err_status) {
  if (rcd_pos.has_value()) {
    offset_ = rcd_pos.value();
    codec_memory_->Seek(codec_memory_->GetSize());
  }
  size_t unconsumed_bytes = codec_memory_->GetUnconsumedSpan().size();
  if (!ReadMoreDataInternal(unconsumed_bytes, err_status)) {
    return false;
  }
  if (context_) {
    context_->Input(codec_memory_);
  }
  return true;
}

uint32_t ProgressiveDecoder::GetCurrentInputPosition() const {
  uint32_t remain_size =
      context_ ? pdfium::checked_cast<uint32_t>(context_->GetAvailInput()) : 0;
  return offset_ - remain_size;
}

bool ProgressiveDecoder::PrepareScanlineResampling(
    int src_width,
    int src_height,
    Format src_format,
    pdfium::span<const FX_ARGB> palette,
    std::optional<FX_ARGB> fill_argb) {
  if (!device_bitmap_ || src_format == Format::kInvalid || src_width <= 0 ||
      src_height <= 0) {
    return false;
  }
  src_width_ = src_width;
  src_height_ = src_height;
  src_format_ = src_format;
  src_components_count_ = GetCompsFromFormat(src_format);
  src_bits_per_component_ = 8;
  SetTransMethod();
  decode_buf_.resize(GetScanlineSize());
  FXDIB_ResampleOptions options;
  options.bInterpolateBilinear = true;
  weight_horz_.CalculateWeights(src_width_, 0, src_width_, src_width_, 0,
                                src_width_, options);
  if (!palette.empty()) {
    device_bitmap_->SetPalette(palette);
    src_palette_ = DataVector<FX_ARGB>(palette.begin(), palette.end());
  }
  if (fill_argb.has_value()) {
    device_bitmap_->Clear(fill_argb.value());
  }
  return true;
}

void ProgressiveDecoder::ResampleScanline(
    int line,
    pdfium::span<const uint8_t> src_span) {
  CHECK(device_bitmap_);
  if (line < 0 || line >= src_height_) {
    return;
  }
  int scanline_size = GetScanlineSize();
  fxcrt::Copy(src_span.first(static_cast<size_t>(scanline_size)), decode_buf_);
  ResampleScanline(device_bitmap_, line, decode_buf_, src_format_);
}

bool ProgressiveDecoder::PrepareDirectOutput(int src_width,
                                             int src_height,
                                             Format src_format) {
  if (src_width <= 0 || src_height <= 0 || src_format != Format::kBgra) {
    return false;
  }
  src_width_ = src_width;
  src_height_ = src_height;
  src_format_ = src_format;
  src_bits_per_component_ = 8;
  src_components_count_ = 4;
  return true;
}

pdfium::span<uint8_t> ProgressiveDecoder::AskScanlineBuf(int line) {
  CHECK_GE(line, 0);
  CHECK_LT(line, src_height_);
  CHECK_EQ(device_bitmap_->GetFormat(), FXDIB_Format::kBgra);
  CHECK_EQ(src_format_, Format::kBgra);
  return device_bitmap_->GetWritableScanline(line);
}

pdfium::span<uint8_t> ProgressiveDecoder::AskImageBuf() {
  CHECK_EQ(device_bitmap_->GetFormat(), FXDIB_Format::kBgra);
  CHECK_EQ(src_format_, Format::kBgra);
  return device_bitmap_->GetWritableBuffer();
}

bool ProgressiveDecoder::BmpDetectImageTypeInBuffer(
    CFX_DIBAttribute* pAttribute) {
  std::unique_ptr<ProgressiveDecoderContext> pBmcontext =
      CreateDecoderContext(FXCODEC_IMAGE_BMP, this);
  pBmcontext->Input(codec_memory_);

#if defined(PDF_ENABLE_RUST_BMP)
  auto* ctx = static_cast<RustBmpContext*>(pBmcontext.get());
#else
  auto* ctx = static_cast<CFX_BmpContext*>(pBmcontext.get());
#endif

  pdfium::span<const FX_ARGB> palette;
  ProgressiveDecoderContext::Status read_result = ctx->ReadHeader(
      &src_width_, &src_height_, &src_components_count_, &palette, pAttribute);
  while (read_result == ProgressiveDecoderContext::Status::kContinue) {
    FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
    if (!BmpReadMoreData(pBmcontext.get(), &error_status)) {
      status_ = error_status;
      return false;
    }
    read_result = ctx->ReadHeader(&src_width_, &src_height_,
                                  &src_components_count_, &palette, pAttribute);
  }

  if (read_result != ProgressiveDecoderContext::Status::kSuccess) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }

  FXDIB_Format format = FXDIB_Format::kInvalid;
  switch (src_components_count_) {
    case 1:
      src_format_ = Format::k8bppRgb;
      format = FXDIB_Format::k8bppRgb;
      break;
    case 3:
      src_format_ = Format::kBgr;
      format = FXDIB_Format::kBgr;
      break;
    case 4:
      src_format_ = Format::kBgrx;
      format = FXDIB_Format::kBgrx;
      break;
    default:
      status_ = FXCODEC_STATUS::kError;
      return false;
  }

  // Set to 0 to make CalculatePitchAndSize() calculate it.
  static constexpr uint32_t kNoPitch = 0;
  std::optional<CFX_DIBitmap::PitchAndSize> needed_data =
      CFX_DIBitmap::CalculatePitchAndSize(src_width_, src_height_, format,
                                          kNoPitch);
  if (!needed_data.has_value()) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }

  uint32_t available_data = pdfium::checked_cast<uint32_t>(
      file_->GetSize() - offset_ + pBmcontext->GetAvailInput());
  if (needed_data.value().size / src_components_count_ > available_data) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }

  src_bits_per_component_ = 8;
  context_ = std::move(pBmcontext);
  if (!palette.empty()) {
    src_palette_.resize(palette.size());
    fxcrt::Copy(palette, src_palette_);
  } else {
    src_palette_.clear();
  }
  return true;
}

bool ProgressiveDecoder::BmpReadMoreData(ProgressiveDecoderContext* bmp_context,
                                         FXCODEC_STATUS* err_status) {
  // TODO(lukasza): Can this just use
  // `codec_memory_->GetUnconsumedSpan().size()`? (IIUC this is what
  // `GetAvailInput` uses in the end, but I haven't investigated that this is
  // the same instance of `CFX_CodecMemory`.)
  FX_SAFE_SIZE_T avail_input = bmp_context->GetAvailInput();
  if (!avail_input.IsValid()) {
    return false;
  }
  if (!ReadMoreDataInternal(avail_input.ValueOrDie(), err_status)) {
    return false;
  }
  bmp_context->Input(codec_memory_);
  return true;
}

FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode() {
  SetTransMethod();
  decode_buf_.resize(GetScanlineSize());
  FXDIB_ResampleOptions options;
  options.bInterpolateBilinear = true;
  weight_horz_.CalculateWeights(src_width_, 0, src_width_, src_width_, 0,
                                src_width_, options);
  status_ = FXCODEC_STATUS::kDecodeToBeContinued;
  return status_;
}

FXCODEC_STATUS ProgressiveDecoder::BmpContinueDecode() {
  ProgressiveDecoderContext::Status read_res = context_->DecodeImage();
  while (read_res == ProgressiveDecoderContext::Status::kContinue) {
    FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
    if (!BmpReadMoreData(context_.get(), &error_status)) {
      device_bitmap_ = nullptr;
      file_ = nullptr;
      status_ = error_status;
      return status_;
    }
    read_res = context_->DecodeImage();
  }

  device_bitmap_ = nullptr;
  file_ = nullptr;
  status_ = read_res == ProgressiveDecoderContext::Status::kSuccess
                ? FXCODEC_STATUS::kDecodeFinished
                : FXCODEC_STATUS::kError;
  return status_;
}

bool ProgressiveDecoder::GifReadMoreData(FXCODEC_STATUS* err_status) {
  // TODO(lukasza): Can this just use
  // `codec_memory_->GetUnconsumedSpan().size()`? (IIUC this is what
  // `GetAvailInput` uses in the end, but I haven't investigated that this is
  // the same instance of `CFX_CodecMemory`.)
  FX_SAFE_SIZE_T avail_input = context_->GetAvailInput();
  if (!avail_input.IsValid()) {
    return false;
  }
  if (!ReadMoreDataInternal(avail_input.ValueOrDie(), err_status)) {
    return false;
  }

  context_->Input(codec_memory_);
  return true;
}

bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
  context_ = CreateDecoderContext(FXCODEC_IMAGE_GIF, this);
  context_->Input(codec_memory_);
  src_components_count_ = 1;
  auto* ctx = static_cast<CFX_GifContext*>(context_.get());
  ProgressiveDecoderContext::Status readResult =
      ctx->ReadHeader(&src_width_, &src_height_);
  while (readResult == ProgressiveDecoderContext::Status::kContinue) {
    FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
    if (!GifReadMoreData(&error_status)) {
      context_ = nullptr;
      status_ = error_status;
      return false;
    }
    readResult = ctx->ReadHeader(&src_width_, &src_height_);
  }
  if (readResult == ProgressiveDecoderContext::Status::kSuccess) {
    src_bits_per_component_ = 8;
    return true;
  }
  context_ = nullptr;
  status_ = FXCODEC_STATUS::kError;
  return false;
}

FXCODEC_STATUS ProgressiveDecoder::GifStartDecode() {
  src_format_ = Format::k8bppRgb;
  SetTransMethod();
  decode_buf_.resize(GetScanlineSize());
  FXDIB_ResampleOptions options;
  options.bInterpolateBilinear = true;
  weight_horz_.CalculateWeights(src_width_, 0, src_width_, src_width_, 0,
                                src_width_, options);
  auto* ctx = static_cast<CFX_GifContext*>(context_.get());
  status_ = ctx->StartDecode(device_bitmap_);
  return status_;
}

FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
  auto* ctx = static_cast<CFX_GifContext*>(context_.get());
  status_ = ctx->ContinueDecode();  // Success or error, never continue.
  device_bitmap_ = nullptr;
  file_ = nullptr;
  return status_;
}

bool ProgressiveDecoder::JpegReadMoreData(FXCODEC_STATUS* err_status) {
  FX_SAFE_SIZE_T avail_input = context_->GetAvailInput();
  if (!avail_input.IsValid()) {
    return false;
  }
  if (!ReadMoreDataInternal(avail_input.ValueOrDie(), err_status)) {
    return false;
  }
  context_->Input(codec_memory_);
  return true;
}

bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
    CFX_DIBAttribute* pAttribute) {
  context_ = CreateDecoderContext(FXCODEC_IMAGE_JPG, this);
  if (!context_) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }
  context_->Input(codec_memory_);

#if defined(PDF_ENABLE_RUST_JPEG)
  auto* ctx = static_cast<RustJpegContext*>(context_.get());
  src_width_ = 0;
  src_height_ = 0;
  while (!ctx->ReadHeader()) {
    FXCODEC_STATUS status = FXCODEC_STATUS::kError;
    if (!ReadMoreData(std::nullopt, &status)) {
      break;
    }
  }

  bool got_metadata = (ctx->width() > 0 && ctx->height() > 0);
  if (got_metadata) {
    src_width_ = ctx->width();
    src_height_ = ctx->height();
    src_components_count_ = ctx->num_components();
    src_bits_per_component_ = 8;
#if defined(PDF_ENABLE_XFA)
    if (pAttribute) {
      pAttribute->x_dpi_ = ctx->x_density();
      pAttribute->y_dpi_ = ctx->y_density();
      pAttribute->dpi_unit_ =
          static_cast<CFX_DIBAttribute::ResUnit>(ctx->density_unit());
    }
#endif
  } else {
    status_ = FXCODEC_STATUS::kError;
  }
  context_.reset();
  return got_metadata;
#else
  auto* ctx = static_cast<LibjpegJpegContext*>(context_.get());
  while (1) {
    int read_result = ctx->ReadHeader(&src_width_, &src_height_,
                                      &src_components_count_, pAttribute);
    switch (read_result) {
      case LibjpegJpegContext::kFatal:
      case LibjpegJpegContext::kError:
        status_ = FXCODEC_STATUS::kError;
        return false;
      case LibjpegJpegContext::kOk:
        src_bits_per_component_ = 8;
        return true;
      case LibjpegJpegContext::kNeedsMoreInput: {
        FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
        if (!JpegReadMoreData(&error_status)) {
          status_ = error_status;
          return false;
        }
        break;
      }
      default:
        NOTREACHED();
    }
  }
#endif
}

FXCODEC_STATUS ProgressiveDecoder::JpegStartDecode() {
#if defined(PDF_ENABLE_RUST_JPEG)
  context_ = CreateDecoderContext(FXCODEC_IMAGE_JPG, this);
  if (!context_) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
    status_ = FXCODEC_STATUS::kError;
    return status_;
  }
  context_->Input(codec_memory_);
  auto* ctx = static_cast<RustJpegContext*>(context_.get());
  status_ = ctx->StartDecode(device_bitmap_);
  return status_;
#else
  status_ = static_cast<LibjpegJpegContext*>(context_.get())->StartDecode();
  if (status_ == FXCODEC_STATUS::kError) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
    context_.reset();
  }
  return status_;
#endif
}

FXCODEC_STATUS ProgressiveDecoder::JpegContinueDecode() {
#if defined(PDF_ENABLE_RUST_JPEG)
  auto* ctx = static_cast<RustJpegContext*>(context_.get());
  status_ = ctx->ContinueDecode();
  if (status_ != FXCODEC_STATUS::kDecodeToBeContinued) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
  }
  return status_;
#else
  status_ = static_cast<LibjpegJpegContext*>(context_.get())->ContinueDecode();
  if (status_ == FXCODEC_STATUS::kError) {
    context_.reset();
  }
  if (status_ != FXCODEC_STATUS::kDecodeToBeContinued) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
  }
  return status_;
#endif
}

bool ProgressiveDecoder::PngDetectImageTypeInBuffer() {
  context_ = CreateDecoderContext(FXCODEC_IMAGE_PNG, this);
  if (!context_) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }

  src_width_ = 0;
  src_height_ = 0;

#if defined(PDF_ENABLE_RUST_PNG)
  context_->Input(codec_memory_);
  auto* ctx = static_cast<RustPngContext*>(context_.get());
  FXCODEC_STATUS status = FXCODEC_STATUS::kError;
  while (src_width_ == 0) {
    if (ctx->ReadHeader()) {
      break;
    }
    if (ctx->has_error() || !ReadMoreData(std::nullopt, &status)) {
      break;
    }
  }
#else
  auto* ctx = static_cast<LibpngPngContext*>(context_.get());
  if (ctx->ReadHeader(codec_memory_)) {
    FXCODEC_STATUS status = FXCODEC_STATUS::kError;
    while (src_width_ == 0 && ReadMoreData(std::nullopt, &status)) {
      if (!ctx->ReadHeader(codec_memory_)) {
        break;
      }
    }
  }
#endif

  bool got_metadata = (src_width_ > 0 && src_height_ > 0);
  if (!got_metadata) {
    status_ = FXCODEC_STATUS::kError;
  }
  context_.reset();
  return got_metadata;
}

FXCODEC_STATUS ProgressiveDecoder::PngStartDecode() {
  context_ = CreateDecoderContext(FXCODEC_IMAGE_PNG, this);
  if (!context_) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
    status_ = FXCODEC_STATUS::kError;
    return status_;
  }
  context_->Input(codec_memory_);
#if defined(PDF_ENABLE_RUST_PNG)
  auto* ctx = static_cast<RustPngContext*>(context_.get());
#else
  auto* ctx = static_cast<LibpngPngContext*>(context_.get());
#endif
  status_ = ctx->StartDecode(device_bitmap_);
  return status_;
}

FXCODEC_STATUS ProgressiveDecoder::PngContinueDecode() {
#if defined(PDF_ENABLE_RUST_PNG)
  auto* ctx = static_cast<RustPngContext*>(context_.get());
#else
  auto* ctx = static_cast<LibpngPngContext*>(context_.get());
#endif
  status_ = ctx->ContinueDecode();
  if (status_ != FXCODEC_STATUS::kDecodeToBeContinued) {
    device_bitmap_ = nullptr;
    file_ = nullptr;
  }
  return status_;
}

bool ProgressiveDecoder::TiffDetectImageTypeFromFile(
    CFX_DIBAttribute* pAttribute) {
  auto ctx = std::make_unique<LibtiffTiffContext>();
  if (!ctx->InitDecoder(file_)) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }
  int32_t dummy_bpc;
  bool ret = ctx->LoadFrameInfo(0, &src_width_, &src_height_,
                                &src_components_count_, &dummy_bpc, pAttribute);
  src_components_count_ = 4;
  if (!ret) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }
  context_ = std::move(ctx);
  return true;
}

FXCODEC_STATUS ProgressiveDecoder::TiffContinueDecode() {
  // TODO(crbug.com/355630556): Consider adding support for
  // `FXDIB_Format::kBgraPremul`
  CHECK_EQ(device_bitmap_->GetFormat(), FXDIB_Format::kBgra);
  auto* ctx = static_cast<LibtiffTiffContext*>(context_.get());
  status_ = ctx->Decode(std::move(device_bitmap_))
                ? FXCODEC_STATUS::kDecodeFinished
                : FXCODEC_STATUS::kError;
  file_ = nullptr;
  return status_;
}

bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
                                         CFX_DIBAttribute* pAttribute) {
  if (imageType == FXCODEC_IMAGE_TIFF) {
    return TiffDetectImageTypeFromFile(pAttribute);
  }

  size_t size = pdfium::checked_cast<size_t>(
      std::min<FX_FILESIZE>(file_->GetSize(), kBlockSize));
  codec_memory_ = pdfium::MakeRetain<CFX_CodecMemory>(size);
  offset_ = 0;
  if (!file_->ReadBlockAtOffset(codec_memory_->GetBufferSpan().first(size),
                                offset_)) {
    status_ = FXCODEC_STATUS::kError;
    return false;
  }
  offset_ += size;

  if (imageType == FXCODEC_IMAGE_JPG) {
    return JpegDetectImageTypeInBuffer(pAttribute);
  }

  if (imageType == FXCODEC_IMAGE_BMP) {
    return BmpDetectImageTypeInBuffer(pAttribute);
  }
  if (imageType == FXCODEC_IMAGE_GIF) {
    return GifDetectImageTypeInBuffer();
  }
  if (imageType == FXCODEC_IMAGE_PNG) {
    return PngDetectImageTypeInBuffer();
  }

  status_ = FXCODEC_STATUS::kError;
  return false;
}

bool ProgressiveDecoder::ReadMoreDataInternal(size_t unconsumed_bytes,
                                              FXCODEC_STATUS* err_status) {
  // Check for EOF.
  if (offset_ >= static_cast<uint32_t>(file_->GetSize())) {
    return false;
  }

  // Try to get whatever remains.
  uint32_t bytes_to_fetch_from_file =
      pdfium::checked_cast<uint32_t>(file_->GetSize() - offset_);

  if (unconsumed_bytes == codec_memory_->GetSize()) {
    // Codec couldn't make any progress against the bytes in the buffer.
    // Increase the buffer size so that there might be enough contiguous
    // bytes to allow whatever operation is having difficulty to succeed.
    bytes_to_fetch_from_file =
        std::min<uint32_t>(bytes_to_fetch_from_file, kBlockSize);
    size_t new_size = codec_memory_->GetSize() + bytes_to_fetch_from_file;
    if (!codec_memory_->TryResize(new_size)) {
      *err_status = FXCODEC_STATUS::kError;
      return false;
    }
  } else {
    // TODO(crbug.com/42270919): Simplify the `CFX_CodecMemory` API so we
    // don't need to do this awkward dance to free up exactly enough buffer
    // space for the next read.
    size_t already_read_bytes = codec_memory_->GetSize() - unconsumed_bytes;
    bytes_to_fetch_from_file = pdfium::checked_cast<uint32_t>(
        std::min<size_t>(bytes_to_fetch_from_file, already_read_bytes));
    codec_memory_->Consume(bytes_to_fetch_from_file);
    codec_memory_->Seek(already_read_bytes - bytes_to_fetch_from_file);
    unconsumed_bytes += codec_memory_->GetPosition();
  }

  // Append new data past the bytes not yet processed by the codec.
  if (!file_->ReadBlockAtOffset(codec_memory_->GetBufferSpan().subspan(
                                    unconsumed_bytes, bytes_to_fetch_from_file),
                                offset_)) {
    *err_status = FXCODEC_STATUS::kError;
    return false;
  }
  offset_ += bytes_to_fetch_from_file;
  return true;
}

FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
    RetainPtr<IFX_SeekableReadStream> file,
    FXCODEC_IMAGE_TYPE image_type,
    CFX_DIBAttribute* attribute,
    bool skip_fallback_type_detection) {
  DCHECK(attribute);

  switch (status_) {
    case FXCODEC_STATUS::kFrameReady:
    case FXCODEC_STATUS::kFrameToBeContinued:
    case FXCODEC_STATUS::kDecodeReady:
    case FXCODEC_STATUS::kDecodeToBeContinued:
      return FXCODEC_STATUS::kError;
    case FXCODEC_STATUS::kError:
    case FXCODEC_STATUS::kDecodeFinished:
      break;
  }
  file_ = std::move(file);
  if (!file_) {
    status_ = FXCODEC_STATUS::kError;
    return status_;
  }
  offset_ = 0;
  src_width_ = 0;
  src_height_ = 0;
  src_components_count_ = 0;
  src_bits_per_component_ = 0;
  if (image_type != FXCODEC_IMAGE_UNKNOWN &&
      DetectImageType(image_type, attribute)) {
    image_type_ = image_type;
    status_ = FXCODEC_STATUS::kFrameReady;
    return status_;
  }
  // The image data does not match the requested decoder. If skipping fallback
  // type detection, bail out at this point and return the failed status.
  if (skip_fallback_type_detection) {
    status_ = FXCODEC_STATUS::kError;
    file_ = nullptr;
    return status_;
  }

  for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
    if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), attribute)) {
      image_type_ = static_cast<FXCODEC_IMAGE_TYPE>(type);
      status_ = FXCODEC_STATUS::kFrameReady;
      return status_;
    }
  }
  status_ = FXCODEC_STATUS::kError;
  file_ = nullptr;
  return status_;
}

void ProgressiveDecoder::SetTransMethod() {
  switch (device_bitmap_->GetFormat()) {
    case FXDIB_Format::kInvalid:
    case FXDIB_Format::k1bppMask:
    case FXDIB_Format::k1bppRgb:
    case FXDIB_Format::k8bppMask:
    case FXDIB_Format::k8bppRgb:
      NOTREACHED();
    case FXDIB_Format::kBgr: {
      switch (src_format_) {
        case Format::kInvalid:
          trans_method_ = TransformMethod::kInvalid;
          break;
        case Format::k8bppGray:
          trans_method_ = TransformMethod::k8BppGrayToRgbMaybeAlpha;
          break;
        case Format::k8bppRgb:
          trans_method_ = TransformMethod::k8BppRgbToRgbNoAlpha;
          break;
        case Format::kBgr:
        case Format::kBgrx:
        case Format::kBgra:
          trans_method_ = TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha;
          break;
        case Format::kRgb:
          trans_method_ = TransformMethod::kRgbToBgrMaybeAlpha;
          break;
        case Format::kCmyk:
          trans_method_ = TransformMethod::kCmykToRgbMaybeAlpha;
          break;
      }
      break;
    }
    case FXDIB_Format::kBgrx:
    case FXDIB_Format::kBgra: {
      switch (src_format_) {
        case Format::kInvalid:
          trans_method_ = TransformMethod::kInvalid;
          break;
        case Format::k8bppGray:
          trans_method_ = TransformMethod::k8BppGrayToRgbMaybeAlpha;
          break;
        case Format::k8bppRgb:
          if (device_bitmap_->GetFormat() == FXDIB_Format::kBgra) {
            trans_method_ = TransformMethod::k8BppRgbToArgb;
          } else {
            trans_method_ = TransformMethod::k8BppRgbToRgbNoAlpha;
          }
          break;
        case Format::kBgr:
        case Format::kBgrx:
          trans_method_ = TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha;
          break;
        case Format::kRgb:
          trans_method_ = TransformMethod::kRgbToBgrMaybeAlpha;
          break;
        case Format::kCmyk:
          trans_method_ = TransformMethod::kCmykToRgbMaybeAlpha;
          break;
        case Format::kBgra:
          trans_method_ = TransformMethod::kArgbToArgb;
          break;
      }
      break;
    }
#if defined(PDF_USE_SKIA)
    case FXDIB_Format::kBgraPremul:
      // TODO(crbug.com/355630556): Consider adding support for
      // `FXDIB_Format::kBgraPremul`
      NOTREACHED();
#endif
  }
}

void ProgressiveDecoder::ResampleScanline(
    const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
    int dest_line,
    pdfium::span<uint8_t> src_span,
    Format src_format) {
  uint8_t* src_scan = src_span.data();
  uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
  const int src_bytes_per_pixel = GetCompsFromFormat(src_format);
  const int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
  for (int dest_col = 0; dest_col < src_width_; dest_col++) {
    CStretchEngine::PixelWeight* pPixelWeights =
        weight_horz_.GetPixelWeight(dest_col);
    switch (trans_method_) {
      case TransformMethod::kInvalid:
        return;
      case TransformMethod::k8BppGrayToRgbMaybeAlpha: {
        UNSAFE_TODO({
          uint32_t dest_g = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            dest_g += pixel_weight * src_scan[j];
          }
          FXSYS_memset(dest_scan, CStretchEngine::PixelFromFixed(dest_g), 3);
          dest_scan += dest_bytes_per_pixel;
          break;
        });
      }
      case TransformMethod::k8BppRgbToRgbNoAlpha: {
        UNSAFE_TODO({
          uint32_t dest_r = 0;
          uint32_t dest_g = 0;
          uint32_t dest_b = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            uint32_t argb = src_palette_[src_scan[j]];
            dest_r += pixel_weight * FXARGB_R(argb);
            dest_g += pixel_weight * FXARGB_G(argb);
            dest_b += pixel_weight * FXARGB_B(argb);
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          dest_scan += dest_bytes_per_pixel - 3;
          break;
        });
      }
      case TransformMethod::k8BppRgbToArgb: {
        UNSAFE_TODO({
          uint32_t dest_a = 0;
          uint32_t dest_r = 0;
          uint32_t dest_g = 0;
          uint32_t dest_b = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            FX_ARGB argb = src_palette_[src_scan[j]];
            dest_a += pixel_weight * FXARGB_A(argb);
            dest_r += pixel_weight * FXARGB_R(argb);
            dest_g += pixel_weight * FXARGB_G(argb);
            dest_b += pixel_weight * FXARGB_B(argb);
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
          break;
        });
      }
      case TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha: {
        UNSAFE_TODO({
          uint32_t dest_b = 0;
          uint32_t dest_g = 0;
          uint32_t dest_r = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
            dest_b += pixel_weight * (*src_pixel++);
            dest_g += pixel_weight * (*src_pixel++);
            dest_r += pixel_weight * (*src_pixel);
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          dest_scan += dest_bytes_per_pixel - 3;
          break;
        });
      }
      case TransformMethod::kRgbToBgrMaybeAlpha: {
        UNSAFE_TODO({
          uint32_t dest_b = 0;
          uint32_t dest_g = 0;
          uint32_t dest_r = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
            dest_r += pixel_weight * (*src_pixel++);
            dest_g += pixel_weight * (*src_pixel++);
            dest_b += pixel_weight * (*src_pixel);
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          dest_scan += dest_bytes_per_pixel - 3;
          break;
        });
      }
      case TransformMethod::kCmykToRgbMaybeAlpha: {
        UNSAFE_TODO({
          uint32_t dest_b = 0;
          uint32_t dest_g = 0;
          uint32_t dest_r = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
            FX_RGB_STRUCT<uint8_t> src_rgb =
                AdobeCmykToStandardRgb(255 - src_pixel[0], 255 - src_pixel[1],
                                       255 - src_pixel[2], 255 - src_pixel[3]);
            dest_b += pixel_weight * src_rgb.blue;
            dest_g += pixel_weight * src_rgb.green;
            dest_r += pixel_weight * src_rgb.red;
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          dest_scan += dest_bytes_per_pixel - 3;
          break;
        });
      }
      case TransformMethod::kArgbToArgb: {
        UNSAFE_TODO({
          uint32_t dest_alpha = 0;
          uint32_t dest_r = 0;
          uint32_t dest_g = 0;
          uint32_t dest_b = 0;
          for (int j = pPixelWeights->src_start_; j <= pPixelWeights->src_end_;
               j++) {
            uint32_t pixel_weight =
                pPixelWeights->weights_[j - pPixelWeights->src_start_];
            const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
            pixel_weight = pixel_weight * src_pixel[3] / 255;
            dest_b += pixel_weight * (*src_pixel++);
            dest_g += pixel_weight * (*src_pixel++);
            dest_r += pixel_weight * (*src_pixel);
            dest_alpha += pixel_weight;
          }
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
          *dest_scan++ = CStretchEngine::PixelFromFixed(dest_alpha * 255);
          break;
        });
      }
    }
  }
}

void ProgressiveDecoder::Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
                                  int32_t src_line,
                                  uint8_t* src_scan,
                                  Format src_format) {
  if (src_line < 0 || src_line >= src_height_) {
    return;
  }

  ResampleScanline(pDeviceBitmap, src_line, decode_buf_, src_format);
}

FXDIB_Format ProgressiveDecoder::GetBitmapFormat() const {
  switch (image_type_) {
    case FXCODEC_IMAGE_JPG:
    case FXCODEC_IMAGE_BMP:
      return GetBitsPerPixel() <= 24 ? FXDIB_Format::kBgr : FXDIB_Format::kBgrx;
    case FXCODEC_IMAGE_PNG:
    case FXCODEC_IMAGE_TIFF:
    default:
      // TODO(crbug.com/355630556): Consider adding support for
      // `FXDIB_Format::kBgraPremul`
      return FXDIB_Format::kBgra;
  }
}

std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
  if (!(status_ == FXCODEC_STATUS::kFrameReady ||
        status_ == FXCODEC_STATUS::kFrameToBeContinued)) {
    return {FXCODEC_STATUS::kError, 0};
  }

  switch (image_type_) {
    case FXCODEC_IMAGE_JPG:
    case FXCODEC_IMAGE_BMP:
    case FXCODEC_IMAGE_PNG:
    case FXCODEC_IMAGE_TIFF:
      frame_number_ = 1;
      status_ = FXCODEC_STATUS::kDecodeReady;
      return {status_, 1};
    case FXCODEC_IMAGE_GIF: {
      auto* ctx = static_cast<CFX_GifContext*>(context_.get());
      while (true) {
        ProgressiveDecoderContext::Status readResult = ctx->GetFrame();
        frame_number_ =
            readResult == ProgressiveDecoderContext::Status::kSuccess
                ? ctx->GetFrameNum()
                : 0;
        while (readResult == ProgressiveDecoderContext::Status::kContinue) {
          FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
          if (!GifReadMoreData(&error_status)) {
            return {error_status, 0};
          }

          readResult = ctx->GetFrame();
          frame_number_ =
              readResult == ProgressiveDecoderContext::Status::kSuccess
                  ? ctx->GetFrameNum()
                  : 0;
        }
        if (readResult == ProgressiveDecoderContext::Status::kSuccess) {
          status_ = FXCODEC_STATUS::kDecodeReady;
          return {status_, frame_number_};
        }
        context_ = nullptr;
        status_ = FXCODEC_STATUS::kError;
        return {status_, 0};
      }
    }
    default:
      return {FXCODEC_STATUS::kError, 0};
  }
}

FXCODEC_STATUS ProgressiveDecoder::StartDecode(RetainPtr<CFX_DIBitmap> bitmap) {
  CHECK(bitmap);
  CHECK_EQ(bitmap->GetWidth(), src_width_);
  CHECK_EQ(bitmap->GetHeight(), src_height_);
  CHECK_GT(src_width_, 0);
  CHECK_GT(src_height_, 0);

  const FXDIB_Format format = bitmap->GetFormat();
  CHECK(format == FXDIB_Format::kBgra || format == FXDIB_Format::kBgr ||
        format == FXDIB_Format::kBgrx);

  if (status_ != FXCODEC_STATUS::kDecodeReady) {
    return FXCODEC_STATUS::kError;
  }

  if (frame_number_ == 0) {
    return FXCODEC_STATUS::kError;
  }

  if (bitmap->GetWidth() > 65535 || bitmap->GetHeight() > 65535) {
    return FXCODEC_STATUS::kError;
  }

  device_bitmap_ = std::move(bitmap);
  switch (image_type_) {
    case FXCODEC_IMAGE_JPG:
      return JpegStartDecode();
    case FXCODEC_IMAGE_BMP:
      return BmpStartDecode();
    case FXCODEC_IMAGE_GIF:
      return GifStartDecode();
    case FXCODEC_IMAGE_PNG:
      return PngStartDecode();
    case FXCODEC_IMAGE_TIFF:
      status_ = FXCODEC_STATUS::kDecodeToBeContinued;
      return status_;
    default:
      return FXCODEC_STATUS::kError;
  }
}

FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
  if (status_ != FXCODEC_STATUS::kDecodeToBeContinued) {
    return FXCODEC_STATUS::kError;
  }

  switch (image_type_) {
    case FXCODEC_IMAGE_JPG:
      return JpegContinueDecode();
    case FXCODEC_IMAGE_BMP:
      return BmpContinueDecode();
    case FXCODEC_IMAGE_GIF:
      return GifContinueDecode();
    case FXCODEC_IMAGE_PNG:
      return PngContinueDecode();
    case FXCODEC_IMAGE_TIFF:
      return TiffContinueDecode();
    default:
      return FXCODEC_STATUS::kError;
  }
}

int ProgressiveDecoder::GetScanlineSize() const {
  // Can't be called before basic image metadata is decoded.
  CHECK_NE(src_components_count_, 0);
  CHECK_NE(src_width_, 0);

  FX_SAFE_INT32 result = src_width_;
  result *= src_components_count_;

  return FxAlignToBoundary<4>(result).ValueOrDie();
}

}  // namespace fxcodec
