// 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* 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();
}

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(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, 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(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();
  }
}
