// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "image_generator_apng.h"
#include <cstddef>
#include <cstring>

#include "flutter/fml/logging.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/codec/SkCodecAnimation.h"
#include "third_party/skia/include/core/SkAlphaType.h"
#include "third_party/skia/include/core/SkColorType.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/zlib/zlib.h"  // For crc32

namespace flutter {

APNGImageGenerator::~APNGImageGenerator() = default;

APNGImageGenerator::APNGImageGenerator(sk_sp<SkData>& data,
                                       SkImageInfo& image_info,
                                       APNGImage&& default_image,
                                       unsigned int frame_count,
                                       unsigned int play_count,
                                       const void* next_chunk_p,
                                       const std::vector<uint8_t>& header)
    : data_(data),
      image_info_(image_info),
      frame_count_(frame_count),
      play_count_(play_count),
      first_frame_index_(default_image.frame_info.has_value() ? 0 : 1),
      next_chunk_p_(next_chunk_p),
      header_(header) {
  images_.push_back(std::move(default_image));
}

const SkImageInfo& APNGImageGenerator::GetInfo() {
  return image_info_;
}

unsigned int APNGImageGenerator::GetFrameCount() const {
  return frame_count_;
}

unsigned int APNGImageGenerator::GetPlayCount() const {
  return frame_count_ > 1 ? play_count_ : 1;
}

const ImageGenerator::FrameInfo APNGImageGenerator::GetFrameInfo(
    unsigned int frame_index) {
  unsigned int image_index = first_frame_index_ + frame_index;
  if (!DemuxToImageIndex(image_index)) {
    return {};
  }

  auto frame_info = images_[image_index].frame_info;
  if (frame_info.has_value()) {
    return frame_info.value();
  }
  return {};
}

SkISize APNGImageGenerator::GetScaledDimensions(float desired_scale) {
  return image_info_.dimensions();
}

bool APNGImageGenerator::GetPixels(const SkImageInfo& info,
                                   void* pixels,
                                   size_t row_bytes,
                                   unsigned int frame_index,
                                   std::optional<unsigned int> prior_frame) {
  FML_DCHECK(images_.size() > 0);
  unsigned int image_index = first_frame_index_ + frame_index;

  //----------------------------------------------------------------------------
  /// 1. Demux the frame from the APNG stream.
  ///

  if (!DemuxToImageIndex(image_index)) {
    FML_DLOG(ERROR) << "Couldn't demux image at index " << image_index
                    << " (frame index: " << frame_index
                    << ") from APNG stream.";
    return RenderDefaultImage(info, pixels, row_bytes);
  }

  //----------------------------------------------------------------------------
  /// 2. Decode the frame.
  ///

  APNGImage& frame = images_[image_index];
  SkImageInfo frame_info = frame.codec->getInfo();
  auto frame_row_bytes = frame_info.bytesPerPixel() * frame_info.width();

  if (frame.pixels.empty()) {
    frame.pixels.resize(frame_row_bytes * frame_info.height());
    SkCodec::Result result = frame.codec->getPixels(
        frame.codec->getInfo(), frame.pixels.data(), frame_row_bytes);
    if (result != SkCodec::kSuccess) {
      FML_DLOG(ERROR) << "Failed to decode image at index " << image_index
                      << " (frame index: " << frame_index
                      << ") of APNG. SkCodec::Result: " << result;
      return RenderDefaultImage(info, pixels, row_bytes);
    }
  }
  if (!frame.frame_info.has_value()) {
    FML_DLOG(ERROR) << "Failed to decode image at index " << image_index
                    << " (frame index: " << frame_index
                    << ") of APNG due to the frame missing data (frame_info).";
    return false;
  }

  //----------------------------------------------------------------------------
  /// 3. Composite the frame onto the canvas.
  ///

  if (info.colorType() != kN32_SkColorType) {
    FML_DLOG(ERROR) << "Failed to composite image at index " << image_index
                    << " (frame index: " << frame_index
                    << ") of APNG due to the destination surface having an "
                       "unsupported color type.";
    return false;
  }
  if (frame_info.colorType() != kN32_SkColorType) {
    FML_DLOG(ERROR)
        << "Failed to composite image at index " << image_index
        << " (frame index: " << frame_index
        << ") of APNG due to the frame having an unsupported color type.";
    return false;
  }

  // Regardless of the byte order (RGBA vs BGRA), the blending operations are
  // the same.
  struct Pixel {
    uint8_t channel[4];

    uint8_t GetAlpha() { return channel[3]; }

    void Premultiply() {
      for (int i = 0; i < 3; i++) {
        channel[i] = channel[i] * GetAlpha() / 0xFF;
      }
    }

    void Unpremultiply() {
      if (GetAlpha() == 0) {
        channel[0] = channel[1] = channel[2] = 0;
        return;
      }
      for (int i = 0; i < 3; i++) {
        channel[i] = channel[i] * 0xFF / GetAlpha();
      }
    }
  };

  FML_DCHECK(frame_info.bytesPerPixel() == sizeof(Pixel));

  bool result = true;

  if (frame.frame_info->blend_mode == SkCodecAnimation::Blend::kSrc) {
    SkPixmap src_pixmap(frame_info, frame.pixels.data(), frame_row_bytes);
    uint8_t* dst_pixels = static_cast<uint8_t*>(pixels) +
                          frame.y_offset * row_bytes +
                          frame.x_offset * frame_info.bytesPerPixel();
    result = src_pixmap.readPixels(info, dst_pixels, row_bytes);
    if (!result) {
      FML_DLOG(ERROR) << "Failed to copy pixels at index " << image_index
                      << " (frame index: " << frame_index << ") of APNG.";
    }
  } else if (frame.frame_info->blend_mode ==
             SkCodecAnimation::Blend::kSrcOver) {
    for (int y = 0; y < frame_info.height(); y++) {
      auto src_row = frame.pixels.data() + y * frame_row_bytes;
      auto dst_row = static_cast<uint8_t*>(pixels) +
                     (y + frame.y_offset) * row_bytes +
                     frame.x_offset * frame_info.bytesPerPixel();

      for (int x = 0; x < frame_info.width(); x++) {
        auto x_offset_bytes = x * frame_info.bytesPerPixel();

        Pixel src = *reinterpret_cast<Pixel*>(src_row + x_offset_bytes);
        Pixel* dst_p = reinterpret_cast<Pixel*>(dst_row + x_offset_bytes);
        Pixel dst = *dst_p;

        // Ensure both colors are premultiplied for the blending operation.
        if (info.alphaType() == kUnpremul_SkAlphaType) {
          dst.Premultiply();
        }
        if (frame_info.alphaType() == kUnpremul_SkAlphaType) {
          src.Premultiply();
        }

        for (int i = 0; i < 4; i++) {
          dst.channel[i] =
              src.channel[i] + dst.channel[i] * (0xFF - src.GetAlpha()) / 0xFF;
        }

        // The final color is premultiplied. Unpremultiply to match the
        // backdrop surface if necessary.
        if (info.alphaType() == kUnpremul_SkAlphaType) {
          dst.Unpremultiply();
        }

        *dst_p = dst;
      }
    }
  }

  return result;
}

std::unique_ptr<ImageGenerator> APNGImageGenerator::MakeFromData(
    sk_sp<SkData> data) {
  // Ensure the buffer is large enough to at least contain the PNG signature
  // and a chunk header.
  if (data->size() < sizeof(kPngSignature) + sizeof(ChunkHeader)) {
    return nullptr;
  }
  // Validate the full PNG signature.
  const uint8_t* data_p = static_cast<const uint8_t*>(data.get()->data());
  if (memcmp(data_p, kPngSignature, sizeof(kPngSignature))) {
    return nullptr;
  }

  // Validate the header chunk.
  const ChunkHeader* chunk = reinterpret_cast<const ChunkHeader*>(data_p + 8);
  if (!IsValidChunkHeader(data_p, data->size(), chunk) ||
      chunk->get_data_length() != sizeof(ImageHeaderChunkData) ||
      chunk->get_type() != kImageHeaderChunkType) {
    return nullptr;
  }

  // Walk the chunks to find the "animation control" chunk. If an "image data"
  // chunk is found first, this PNG is not animated.
  while (true) {
    chunk = GetNextChunk(data_p, data->size(), chunk);

    if (chunk == nullptr) {
      return nullptr;
    }
    if (chunk->get_type() == kImageDataChunkType) {
      return nullptr;
    }
    if (chunk->get_type() == kAnimationControlChunkType) {
      break;
    }
  }

  const AnimationControlChunkData* animation_data =
      CastChunkData<AnimationControlChunkData>(chunk);

  // Extract the header signature and chunks to prepend when demuxing images.
  std::optional<std::vector<uint8_t>> header;
  const void* first_chunk_p;
  std::tie(header, first_chunk_p) = ExtractHeader(data_p, data->size());
  if (!header.has_value()) {
    return nullptr;
  }

  // Demux the first image in the APNG chunk stream in order to interpret
  // extent and blending info immediately.
  std::optional<APNGImage> default_image;
  const void* next_chunk_p;
  std::tie(default_image, next_chunk_p) =
      DemuxNextImage(data_p, data->size(), header.value(), first_chunk_p);
  if (!default_image.has_value()) {
    return nullptr;
  }

  unsigned int play_count = animation_data->get_num_plays();
  if (play_count == 0) {
    play_count = kInfinitePlayCount;
  }

  SkImageInfo image_info = default_image.value().codec->getInfo();
  return std::unique_ptr<APNGImageGenerator>(
      new APNGImageGenerator(data, image_info, std::move(default_image.value()),
                             animation_data->get_num_frames(), play_count,
                             next_chunk_p, header.value()));
}

bool APNGImageGenerator::IsValidChunkHeader(const void* buffer,
                                            size_t size,
                                            const ChunkHeader* chunk) {
  // Ensure the chunk doesn't start before the beginning of the buffer.
  if (reinterpret_cast<const uint8_t*>(chunk) <
      static_cast<const uint8_t*>(buffer)) {
    return false;
  }

  // Ensure the buffer is large enough to contain at least the chunk header.
  if (reinterpret_cast<const uint8_t*>(chunk) + sizeof(ChunkHeader) >
      static_cast<const uint8_t*>(buffer) + size) {
    return false;
  }

  // Ensure the buffer is large enough to contain the chunk's given data size
  // and CRC.
  const uint8_t* chunk_end =
      reinterpret_cast<const uint8_t*>(chunk) + GetChunkSize(chunk);
  if (chunk_end > static_cast<const uint8_t*>(buffer) + size) {
    return false;
  }

  // Ensure the 4-byte type only contains ISO 646 letters.
  uint32_t type = chunk->get_type();
  for (int i = 0; i < 4; i++) {
    uint8_t c = type >> i * 8 & 0xFF;
    if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
      return false;
    }
  }

  return true;
}

const APNGImageGenerator::ChunkHeader* APNGImageGenerator::GetNextChunk(
    const void* buffer,
    size_t size,
    const ChunkHeader* current_chunk) {
  FML_DCHECK((uint8_t*)current_chunk + sizeof(ChunkHeader) <=
             (uint8_t*)buffer + size);

  const ChunkHeader* next_chunk = reinterpret_cast<const ChunkHeader*>(
      reinterpret_cast<const uint8_t*>(current_chunk) +
      GetChunkSize(current_chunk));
  if (!IsValidChunkHeader(buffer, size, next_chunk)) {
    return nullptr;
  }

  return next_chunk;
}

std::pair<std::optional<std::vector<uint8_t>>, const void*>
APNGImageGenerator::ExtractHeader(const void* buffer_p, size_t buffer_size) {
  std::vector<uint8_t> result(sizeof(kPngSignature));
  memcpy(result.data(), kPngSignature, sizeof(kPngSignature));

  const ChunkHeader* chunk = reinterpret_cast<const ChunkHeader*>(
      static_cast<const uint8_t*>(buffer_p) + sizeof(kPngSignature));
  // Validate the first chunk to ensure it's safe to read.
  if (!IsValidChunkHeader(buffer_p, buffer_size, chunk)) {
    return std::make_pair(std::nullopt, nullptr);
  }

  // Walk the chunks and copy in the non-APNG chunks until we come across a
  // frame or image chunk.
  do {
    if (chunk->get_type() != kAnimationControlChunkType) {
      size_t chunk_size = GetChunkSize(chunk);
      result.resize(result.size() + chunk_size);
      memcpy(result.data() + result.size() - chunk_size, chunk, chunk_size);
    }

    chunk = GetNextChunk(buffer_p, buffer_size, chunk);
  } while (chunk != nullptr && chunk->get_type() != kFrameControlChunkType &&
           chunk->get_type() != kImageDataChunkType &&
           chunk->get_type() != kFrameDataChunkType);

  // nullptr means the end of the buffer was reached, which means there's no
  // frame or image data, so just return nothing because the PNG isn't even
  // valid.
  if (chunk == nullptr) {
    return std::make_pair(std::nullopt, nullptr);
  }

  return std::make_pair(result, chunk);
}

std::pair<std::optional<APNGImageGenerator::APNGImage>, const void*>
APNGImageGenerator::DemuxNextImage(const void* buffer_p,
                                   size_t buffer_size,
                                   const std::vector<uint8_t>& header,
                                   const void* chunk_p) {
  const ChunkHeader* chunk = reinterpret_cast<const ChunkHeader*>(chunk_p);
  // Validate the given chunk to ensure it's safe to read.
  if (!IsValidChunkHeader(buffer_p, buffer_size, chunk)) {
    return std::make_pair(std::nullopt, nullptr);
  }

  // Expect frame data to begin at fdAT or IDAT
  if (chunk->get_type() != kFrameControlChunkType &&
      chunk->get_type() != kImageDataChunkType) {
    return std::make_pair(std::nullopt, nullptr);
  }

  APNGImage result;
  const FrameControlChunkData* control_data = nullptr;

  // The presence of an fcTL chunk is optional for the first (default) image
  // of a PNG. Both cases are handled in APNGImage.
  if (chunk->get_type() == kFrameControlChunkType) {
    control_data = CastChunkData<FrameControlChunkData>(chunk);

    ImageGenerator::FrameInfo frame_info;
    switch (control_data->get_blend_op()) {
      case 0:  // APNG_BLEND_OP_SOURCE
        frame_info.blend_mode = SkCodecAnimation::Blend::kSrc;
        break;
      case 1:  // APNG_BLEND_OP_OVER
        frame_info.blend_mode = SkCodecAnimation::Blend::kSrcOver;
        break;
      default:
        return std::make_pair(std::nullopt, nullptr);
    }

    SkIRect frame_rect = SkIRect::MakeXYWH(
        control_data->get_x_offset(), control_data->get_y_offset(),
        control_data->get_width(), control_data->get_height());
    switch (control_data->get_dispose_op()) {
      case 0:  // APNG_DISPOSE_OP_NONE
        frame_info.disposal_method = SkCodecAnimation::DisposalMethod::kKeep;
        break;
      case 1:  // APNG_DISPOSE_OP_BACKGROUND
        frame_info.disposal_method =
            SkCodecAnimation::DisposalMethod::kRestoreBGColor;
        frame_info.disposal_rect = frame_rect;
        break;
      case 2:  // APNG_DISPOSE_OP_PREVIOUS
        frame_info.disposal_method =
            SkCodecAnimation::DisposalMethod::kRestorePrevious;
        break;
      default:
        return std::make_pair(std::nullopt, nullptr);
    }
    uint16_t denominator = control_data->get_delay_den() == 0
                               ? 100
                               : control_data->get_delay_den();
    frame_info.duration =
        static_cast<int>(control_data->get_delay_num() * 1000.f / denominator);

    result.frame_info = frame_info;
    result.x_offset = control_data->get_x_offset();
    result.y_offset = control_data->get_y_offset();
  }

  std::vector<const ChunkHeader*> image_chunks;
  size_t chunk_space = 0;

  // Walk the chunks until the next frame, end chunk, or an invalid chunk is
  // reached, recording the chunks to copy along with their required space.
  // TODO(bdero): Validate that IDAT/fdAT chunks are contiguous.
  // TODO(bdero): Validate the acTL/fcTL/fdAT sequence number ordering.
  do {
    if (chunk->get_type() != kFrameControlChunkType) {
      image_chunks.push_back(chunk);
      chunk_space += GetChunkSize(chunk);

      // fdAT chunks are converted into IDAT chunks when demuxed. The only
      // difference between these chunk types is that fdAT has a 4 byte
      // sequence number prepended to its data, so subtract that space from
      // the buffer.
      if (chunk->get_type() == kFrameDataChunkType) {
        chunk_space -= 4;
      }
    }

    chunk = GetNextChunk(buffer_p, buffer_size, chunk);
  } while (chunk != nullptr && chunk->get_type() != kFrameControlChunkType &&
           chunk->get_type() != kImageTrailerChunkType);

  const uint8_t end_chunk[] = {0,   0,   0,    0,    'I',  'E',
                               'N', 'D', 0xAE, 0x42, 0x60, 0x82};

  // Form a buffer for the new encoded PNG and copy the chunks in.
  sk_sp<SkData> new_png_buffer = SkData::MakeUninitialized(
      header.size() + chunk_space + sizeof(end_chunk));

  {
    uint8_t* write_cursor =
        static_cast<uint8_t*>(new_png_buffer->writable_data());

    // Copy the signature/header chunks
    memcpy(write_cursor, header.data(), header.size());
    // If this is a frame, override the width/height in the IHDR chunk.
    if (control_data) {
      ChunkHeader* ihdr_header =
          reinterpret_cast<ChunkHeader*>(write_cursor + sizeof(kPngSignature));
      ImageHeaderChunkData* ihdr_data = const_cast<ImageHeaderChunkData*>(
          CastChunkData<ImageHeaderChunkData>(ihdr_header));
      ihdr_data->set_width(control_data->get_width());
      ihdr_data->set_height(control_data->get_height());
      ihdr_header->UpdateChunkCrc32();
    }
    write_cursor += header.size();

    // Copy the image data/ancillary chunks.
    for (const ChunkHeader* c : image_chunks) {
      if (c->get_type() == kFrameDataChunkType) {
        // Write a new IDAT chunk header.
        ChunkHeader* write_header =
            reinterpret_cast<ChunkHeader*>(write_cursor);
        write_header->set_data_length(c->get_data_length() - 4);
        write_header->set_type(kImageDataChunkType);
        write_cursor += sizeof(ChunkHeader);

        // Copy all of the data except for the 4 byte sequence number at the
        // beginning of the fdAT data.
        memcpy(write_cursor,
               reinterpret_cast<const uint8_t*>(c) + sizeof(ChunkHeader) + 4,
               write_header->get_data_length());
        write_cursor += write_header->get_data_length();

        // Recompute the chunk CRC.
        write_header->UpdateChunkCrc32();
        write_cursor += 4;
      } else {
        size_t chunk_size = GetChunkSize(c);
        memcpy(write_cursor, c, chunk_size);
        write_cursor += chunk_size;
      }
    }

    // Copy the trailer chunk.
    memcpy(write_cursor, &end_chunk, sizeof(end_chunk));
  }

  SkCodec::Result header_parse_result;
  result.codec = SkCodec::MakeFromStream(SkMemoryStream::Make(new_png_buffer),
                                         &header_parse_result);
  if (header_parse_result != SkCodec::Result::kSuccess) {
    FML_DLOG(ERROR)
        << "Failed to parse image header during APNG demux. SkCodec::Result: "
        << header_parse_result;
    return std::make_pair(std::nullopt, nullptr);
  }

  if (chunk->get_type() == kImageTrailerChunkType) {
    chunk = nullptr;
  }

  return std::make_pair(std::optional<APNGImage>{std::move(result)}, chunk);
}

bool APNGImageGenerator::DemuxNextImageInternal() {
  if (next_chunk_p_ == nullptr) {
    return false;
  }

  std::optional<APNGImage> image;
  const void* data_p = const_cast<void*>(data_.get()->data());
  std::tie(image, next_chunk_p_) =
      DemuxNextImage(data_p, data_->size(), header_, next_chunk_p_);
  if (!image.has_value() || !image->frame_info.has_value()) {
    return false;
  }

  auto last_frame_info = images_.back().frame_info;
  if (!last_frame_info.has_value()) {
    return false;
  }

  if (images_.size() > first_frame_index_ &&
      (last_frame_info->disposal_method ==
           SkCodecAnimation::DisposalMethod::kKeep ||
       last_frame_info->disposal_method ==
           SkCodecAnimation::DisposalMethod::kRestoreBGColor)) {
    // Mark the required frame as the previous frame in all cases.
    image->frame_info->required_frame = images_.size() - 1;
  } else if (images_.size() > (first_frame_index_ + 1) &&
             last_frame_info->disposal_method ==
                 SkCodecAnimation::DisposalMethod::kRestorePrevious) {
    // Mark the required frame as the last previous frame
    // It is not valid if there are 2 or above frames set |disposal_method| to
    // |kRestorePrevious|. But it also works in MultiFrameCodec.
    image->frame_info->required_frame = images_.size() - 2;
  }

  // Calling SkCodec::getInfo at least once prior to decoding is mandatory.
  SkImageInfo info = image.value().codec->getInfo();
  FML_DCHECK(info.colorInfo() == image_info_.colorInfo());

  images_.push_back(std::move(image.value()));

  auto default_info = images_[0].codec->getInfo();
  if (info.colorType() != default_info.colorType()) {
    return false;
  }
  return true;
}

bool APNGImageGenerator::DemuxToImageIndex(unsigned int image_index) {
  // If the requested image doesn't exist yet, demux more frames from the APNG
  // stream.
  if (image_index >= images_.size()) {
    while (DemuxNextImageInternal() && image_index >= images_.size()) {
    }

    if (image_index >= images_.size()) {
      // The chunk stream was exhausted before the image was found.
      return false;
    }
  }

  return true;
}

void APNGImageGenerator::ChunkHeader::UpdateChunkCrc32() {
  uint32_t* crc_p =
      reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) +
                                  sizeof(ChunkHeader) + get_data_length());
  *crc_p = fml::BigEndianToArch(ComputeChunkCrc32());
}

uint32_t APNGImageGenerator::ChunkHeader::ComputeChunkCrc32() {
  // Exclude the length field at the beginning of the chunk header.
  size_t length = sizeof(ChunkHeader) - 4 + get_data_length();
  uint8_t* chunk_data_p = reinterpret_cast<uint8_t*>(this) + 4;
  uint32_t crc = 0;

  // zlib's crc32 can only take 16 bits at a time for the length, but PNG
  // supports a 32 bit chunk length, so looping is necessary here.
  // Note that crc32 is always called at least once, even if the chunk has an
  // empty data section.
  do {
    uint16_t length16 = length;
    if (length16 == 0 && length > 0) {
      length16 = std::numeric_limits<uint16_t>::max();
    }

    crc = crc32(crc, chunk_data_p, length16);
    length -= length16;
    chunk_data_p += length16;
  } while (length > 0);

  return crc;
}

bool APNGImageGenerator::RenderDefaultImage(const SkImageInfo& info,
                                            void* pixels,
                                            size_t row_bytes) {
  SkCodec::Result result = images_[0].codec->getPixels(info, pixels, row_bytes);
  if (result != SkCodec::kSuccess) {
    FML_DLOG(ERROR) << "Failed to decode the APNG's default/fallback image. "
                       "SkCodec::Result: "
                    << result;
    return false;
  }
  return true;
}

}  // namespace flutter
