// 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/fpdfapi/page/cpdf_devicecs.h"

#include <algorithm>

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fxcodec/fx_codec.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/notreached.h"
#include "core/fxge/dib/cfx_cmyk_to_srgb.h"

namespace {

float NormalizeChannel(float fVal) {
  return std::clamp(fVal, 0.0f, 1.0f);
}

}  // namespace

CPDF_DeviceCS::CPDF_DeviceCS(Family family) : CPDF_ColorSpace(family) {
  DCHECK(family == Family::kDeviceGray || family == Family::kDeviceRGB ||
         family == Family::kDeviceCMYK);
  SetComponentsForStockCS(ComponentsForFamily(GetFamily()));
}

CPDF_DeviceCS::~CPDF_DeviceCS() = default;

uint32_t CPDF_DeviceCS::v_Load(CPDF_Document* pDoc,
                               const CPDF_Array* pArray,
                               std::set<const CPDF_Object*>* pVisited) {
  // Unlike other classes that inherit from CPDF_ColorSpace, CPDF_DeviceCS is
  // never loaded by CPDF_ColorSpace.
  NOTREACHED_NORETURN();
}

bool CPDF_DeviceCS::GetRGB(pdfium::span<const float> pBuf,
                           float* R,
                           float* G,
                           float* B) const {
  switch (GetFamily()) {
    case Family::kDeviceGray: {
      const float pix = NormalizeChannel(pBuf.front());
      *R = pix;
      *G = pix;
      *B = pix;
      return true;
    }
    case Family::kDeviceRGB: {
      auto rgb =
          fxcrt::truncating_reinterpret_span<const FX_RGB_STRUCT<float>>(pBuf);
      *R = NormalizeChannel(rgb.front().red);
      *G = NormalizeChannel(rgb.front().green);
      *B = NormalizeChannel(rgb.front().blue);
      return true;
    }
    case Family::kDeviceCMYK: {
      auto cmyk =
          fxcrt::truncating_reinterpret_span<const FX_CMYK_STRUCT<float>>(pBuf);
      if (IsStdConversionEnabled()) {
        float k = cmyk.front().key;
        *R = 1.0f - std::min(1.0f, cmyk.front().cyan + k);
        *G = 1.0f - std::min(1.0f, cmyk.front().magenta + k);
        *B = 1.0f - std::min(1.0f, cmyk.front().yellow + k);
        return true;
      }
      FX_RGB_STRUCT<float> rgb =
          AdobeCMYK_to_sRGB(NormalizeChannel(cmyk.front().cyan),
                            NormalizeChannel(cmyk.front().magenta),
                            NormalizeChannel(cmyk.front().yellow),
                            NormalizeChannel(cmyk.front().key));
      *R = rgb.red;
      *G = rgb.green;
      *B = rgb.blue;
      return true;
    }
    default:
      NOTREACHED_NORETURN();
  }
}

void CPDF_DeviceCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
                                       pdfium::span<const uint8_t> src_span,
                                       int pixels,
                                       int image_width,
                                       int image_height,
                                       bool bTransMask) const {
  auto rgb_out =
      fxcrt::truncating_reinterpret_span<FX_RGB_STRUCT<uint8_t>>(dest_span);
  switch (GetFamily()) {
    case Family::kDeviceGray:
      CHECK(!bTransMask);  // bTransMask only allowed for CMYK colorspaces.
      // Compiler can't conclude src/dest don't overlap, avoid interleaved
      // loads and stores by not using an auto& reference here.
      for (const auto pix : src_span.first(pixels)) {
        rgb_out.front().red = pix;
        rgb_out.front().green = pix;
        rgb_out.front().blue = pix;
        rgb_out = rgb_out.subspan(1);
      }
      break;
    case Family::kDeviceRGB:
      CHECK(!bTransMask);  // bTransMask only allowed for CMYK colorspaces.
      fxcodec::ReverseRGB(dest_span.data(), src_span.data(), pixels);
      break;
    case Family::kDeviceCMYK: {
      auto cmyk_in =
          fxcrt::truncating_reinterpret_span<const FX_CMYK_STRUCT<uint8_t>>(
              src_span);
      if (bTransMask) {
        // Compiler can't conclude src/dest don't overlap, avoid interleaved
        // loads and stores by not using an auto& reference here.
        for (const auto cmyk : cmyk_in.first(pixels)) {
          const int k = 255 - cmyk.key;
          rgb_out.front().red = ((255 - cmyk.cyan) * k) / 255;
          rgb_out.front().green = ((255 - cmyk.magenta) * k) / 255;
          rgb_out.front().blue = ((255 - cmyk.yellow) * k) / 255;
          rgb_out = rgb_out.subspan(1);
        }
        break;
      }
      if (IsStdConversionEnabled()) {
        // Compiler can't conclude src/dest don't overlap, avoid interleaved
        // loads and stores by not using am auto& reference here,
        for (const auto cmyk : cmyk_in.first(pixels)) {
          const uint8_t k = cmyk.key;
          rgb_out.front().blue = 255 - std::min(255, cmyk.cyan + k);
          rgb_out.front().green = 255 - std::min(255, cmyk.magenta + k);
          rgb_out.front().red = 255 - std::min(255, cmyk.yellow + k);
          rgb_out = rgb_out.subspan(1);
        }
        break;
      }
      for (const auto& cmyk : cmyk_in.first(pixels)) {
        // TODO(tsepez): maybe this is a FX_BGR_STRUCT in reality?
        FX_RGB_STRUCT<uint8_t> rgb =
            AdobeCMYK_to_sRGB1(cmyk.cyan, cmyk.magenta, cmyk.yellow, cmyk.key);
        rgb_out.front().red = rgb.blue;
        rgb_out.front().green = rgb.green;
        rgb_out.front().blue = rgb.red;
        rgb_out = rgb_out.subspan(1);
      }
      break;
    }
    default:
      NOTREACHED_NORETURN();
  }
}
