// 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/fpdfapi/page/cpdf_transferfunc.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_;
}
