// Copyright 2014 PDFium Authors. All rights reserved.
// 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/fxge/dib/cfx_cmyk_to_srgb.h"
#include "third_party/base/check.h"
#include "third_party/base/cxx17_backports.h"
#include "third_party/base/notreached.h"

namespace {

float NormalizeChannel(float fVal) {
  return pdfium::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();
  return 0;
}

bool CPDF_DeviceCS::GetRGB(pdfium::span<const float> pBuf,
                           float* R,
                           float* G,
                           float* B) const {
  switch (m_Family) {
    case Family::kDeviceGray:
      *R = NormalizeChannel(pBuf[0]);
      *G = *R;
      *B = *R;
      return true;
    case Family::kDeviceRGB:
      *R = NormalizeChannel(pBuf[0]);
      *G = NormalizeChannel(pBuf[1]);
      *B = NormalizeChannel(pBuf[2]);
      return true;
    case Family::kDeviceCMYK:
      if (IsStdConversionEnabled()) {
        float k = pBuf[3];
        *R = 1.0f - std::min(1.0f, pBuf[0] + k);
        *G = 1.0f - std::min(1.0f, pBuf[1] + k);
        *B = 1.0f - std::min(1.0f, pBuf[2] + k);
      } else {
        std::tie(*R, *G, *B) = AdobeCMYK_to_sRGB(
            NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]),
            NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3]));
      }
      return true;
    default:
      NOTREACHED();
      return false;
  }
}

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 {
  uint8_t* pDestBuf = dest_span.data();
  const uint8_t* pSrcBuf = src_span.data();
  switch (m_Family) {
    case Family::kDeviceGray:
      for (int i = 0; i < pixels; i++) {
        // Compiler can not conclude that src/dest don't overlap, avoid
        // duplicate loads.
        const uint8_t pix = pSrcBuf[i];
        *pDestBuf++ = pix;
        *pDestBuf++ = pix;
        *pDestBuf++ = pix;
      }
      break;
    case Family::kDeviceRGB:
      fxcodec::ReverseRGB(pDestBuf, pSrcBuf, pixels);
      break;
    case Family::kDeviceCMYK:
      if (bTransMask) {
        for (int i = 0; i < pixels; i++) {
          // Compiler can't conclude src/dest don't overlap, avoid interleaved
          // loads and stores.
          const uint8_t s0 = pSrcBuf[0];
          const uint8_t s1 = pSrcBuf[1];
          const uint8_t s2 = pSrcBuf[2];
          const int k = 255 - pSrcBuf[3];
          pDestBuf[0] = ((255 - s0) * k) / 255;
          pDestBuf[1] = ((255 - s1) * k) / 255;
          pDestBuf[2] = ((255 - s2) * k) / 255;
          pDestBuf += 3;
          pSrcBuf += 4;
        }
      } else {
        if (IsStdConversionEnabled()) {
          for (int i = 0; i < pixels; i++) {
            // Compiler can't conclude src/dest don't overlap, avoid
            // interleaved loads and stores.
            const uint8_t s0 = pSrcBuf[0];
            const uint8_t s1 = pSrcBuf[1];
            const uint8_t s2 = pSrcBuf[2];
            const uint8_t k = pSrcBuf[3];
            pDestBuf[2] = 255 - std::min(255, s0 + k);
            pDestBuf[1] = 255 - std::min(255, s1 + k);
            pDestBuf[0] = 255 - std::min(255, s2 + k);
            pSrcBuf += 4;
            pDestBuf += 3;
          }
        } else {
          for (int i = 0; i < pixels; i++) {
            std::tie(pDestBuf[2], pDestBuf[1], pDestBuf[0]) =
                AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2],
                                   pSrcBuf[3]);
            pSrcBuf += 4;
            pDestBuf += 3;
          }
        }
      }
      break;
    default:
      NOTREACHED();
      break;
  }
}
