// Copyright 2016 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/fpdfapi/page/cpdf_transferfuncdib.h"

#include <utility>

#include "build/build_config.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/zip.h"
#include "core/fxge/calculate_pitch.h"

#if defined(PDF_USE_SKIA)
#include "core/fxcrt/notreached.h"
#endif

namespace {

CFX_DIBBase::kPlatformRGBStruct MakePlatformRGBStruct(uint8_t red,
                                                      uint8_t green,
                                                      uint8_t blue) {
  // Note that the return value may have an alpha value that will be set to 0.
  return {
      .blue = blue,
      .green = green,
      .red = red,
  };
}

}  // namespace

CPDF_TransferFuncDIB::CPDF_TransferFuncDIB(
    RetainPtr<const CFX_DIBBase> src,
    RetainPtr<CPDF_TransferFunc> transfer_func)
    : src_(std::move(src)),
      transfer_func_(std::move(transfer_func)),
      r_samples_(transfer_func_->GetSamplesR()),
      g_samples_(transfer_func_->GetSamplesG()),
      b_samples_(transfer_func_->GetSamplesB()) {
  SetWidth(src_->GetWidth());
  SetHeight(src_->GetHeight());
  SetFormat(GetDestFormat());
  SetPitch(fxge::CalculatePitch32OrDie(GetBPP(), GetWidth()));
  scanline_.resize(GetPitch());
  CHECK(!HasPalette());
}

CPDF_TransferFuncDIB::~CPDF_TransferFuncDIB() = default;

FXDIB_Format CPDF_TransferFuncDIB::GetDestFormat() const {
  if (src_->IsMaskFormat()) {
    return FXDIB_Format::k8bppMask;
  }

  if (src_->IsAlphaFormat()) {
    // TODO(crbug.com/355676038): Consider adding support for
    // `FXDIB_Format::kBgraPremul`
    return FXDIB_Format::kBgra;
  }

  return CFX_DIBBase::kPlatformRGBFormat;
}

void CPDF_TransferFuncDIB::TranslateScanline(
    pdfium::span<const uint8_t> src_span) const {
  auto scanline_span = pdfium::span(scanline_);
  switch (src_->GetFormat()) {
    case FXDIB_Format::kInvalid: {
      break;
    }
    case FXDIB_Format::k1bppRgb: {
      const auto color0 =
          MakePlatformRGBStruct(r_samples_[0], g_samples_[0], b_samples_[0]);
      const auto color1 = MakePlatformRGBStruct(
          r_samples_[255], g_samples_[255], b_samples_[255]);
      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
      for (int i = 0; i < GetWidth(); i++) {
        const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
        dest[i] = is_on ? color1 : color0;
      }
      break;
    }
    case FXDIB_Format::k1bppMask: {
      const int m0 = r_samples_[0];
      const int m1 = r_samples_[255];
      for (int i = 0; i < GetWidth(); i++) {
        const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
        scanline_[i] = is_on ? m1 : m0;
      }
      break;
    }
    case FXDIB_Format::k8bppRgb: {
      pdfium::span<const uint32_t> src_palette = src_->GetPaletteSpan();
      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
      auto zip =
          fxcrt::Zip(src_span.first(static_cast<size_t>(GetWidth())), dest);
      if (src_->HasPalette()) {
        for (auto [input, output] : zip) {
          const FX_ARGB src_argb = src_palette[input];
          output = MakePlatformRGBStruct(r_samples_[FXARGB_B(src_argb)],
                                         g_samples_[FXARGB_G(src_argb)],
                                         b_samples_[FXARGB_R(src_argb)]);
        }
      } else {
        for (auto [input, output] : zip) {
          output = MakePlatformRGBStruct(r_samples_[input], g_samples_[input],
                                         b_samples_[input]);
        }
      }
      break;
    }
    case FXDIB_Format::k8bppMask: {
      for (auto [input, output] :
           fxcrt::Zip(src_span.first(static_cast<size_t>(GetWidth())),
                      scanline_span)) {
        output = r_samples_[input];
      }
      break;
    }
    case FXDIB_Format::kBgr: {
      auto src =
          fxcrt::reinterpret_span<const FX_BGR_STRUCT<uint8_t>>(src_span);
      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
      for (auto [input, output] :
           fxcrt::Zip(src.first(static_cast<size_t>(GetWidth())), dest)) {
        output = MakePlatformRGBStruct(r_samples_[input.red],
                                       g_samples_[input.green],
                                       b_samples_[input.blue]);
      }
      break;
    }
    case FXDIB_Format::kBgrx: {
      auto src =
          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
      for (auto [input, output] :
           fxcrt::Zip(src.first(static_cast<size_t>(GetWidth())), dest)) {
        output = MakePlatformRGBStruct(r_samples_[input.red],
                                       g_samples_[input.green],
                                       b_samples_[input.blue]);
      }
      break;
    }
    case FXDIB_Format::kBgra: {
      auto src =
          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
      auto dest =
          fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>>(scanline_span);
      for (auto [input, output] :
           fxcrt::Zip(src.first(static_cast<size_t>(GetWidth())), dest)) {
        output = {
            .blue = b_samples_[input.blue],
            .green = g_samples_[input.green],
            .red = r_samples_[input.red],
            .alpha = input.alpha,
        };
      }
      break;
    }
#if defined(PDF_USE_SKIA)
    case FXDIB_Format::kBgraPremul: {
      // TODO(crbug.com/355676038): Consider adding support for
      // `FXDIB_Format::kBgraPremul`
      NOTREACHED();
    }
#endif
  }
}

pdfium::span<const uint8_t> CPDF_TransferFuncDIB::GetScanline(int line) const {
  TranslateScanline(src_->GetScanline(line));
  return scanline_;
}
