// 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/compiler_specific.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* doc,
                               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();
}

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

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::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(static_cast<size_t>(pixels))) {
        rgb_out.front().red = pix;
        rgb_out.front().green = pix;
        rgb_out.front().blue = pix;
        rgb_out = rgb_out.subspan<1u>();
      }
      break;
    case Family::kDeviceRGB:
      CHECK(!bTransMask);  // bTransMask only allowed for CMYK colorspaces.
      fxcodec::ReverseRGB(dest_span, src_span, pixels);
      break;
    case Family::kDeviceCMYK: {
      auto cmyk_in =
          fxcrt::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(static_cast<size_t>(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<1u>();
        }
        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(static_cast<size_t>(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<1u>();
        }
        break;
      }
      for (const auto& cmyk : cmyk_in.first(static_cast<size_t>(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<1u>();
      }
      break;
    }
    default:
      NOTREACHED();
  }
}
