// 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 <algorithm>
#include <memory>
#include <vector>

#include "core/fxcodec/codec/ccodec_iccmodule.h"
#include "core/fxcodec/codec/codec_int.h"

namespace {

// For use with std::unique_ptr<cmsHPROFILE>.
struct CmsProfileDeleter {
  inline void operator()(cmsHPROFILE p) { cmsCloseProfile(p); }
};

using ScopedCmsProfile = std::unique_ptr<void, CmsProfileDeleter>;

bool Check3Components(cmsColorSpaceSignature cs) {
  switch (cs) {
    case cmsSigGrayData:
    case cmsSigCmykData:
      return false;
    default:
      return true;
  }
}

}  // namespace

CLcmsCmm::CLcmsCmm(cmsHTRANSFORM hTransform,
                   int srcComponents,
                   bool bIsLab,
                   bool bNormal)
    : m_hTransform(hTransform),
      m_nSrcComponents(srcComponents),
      m_bLab(bIsLab),
      m_bNormal(bNormal) {}

CLcmsCmm::~CLcmsCmm() {
  cmsDeleteTransform(m_hTransform);
}

CCodec_IccModule::CCodec_IccModule() {}

CCodec_IccModule::~CCodec_IccModule() {}

std::unique_ptr<CLcmsCmm> CCodec_IccModule::CreateTransform_sRGB(
    pdfium::span<const uint8_t> span) {
  ScopedCmsProfile srcProfile(cmsOpenProfileFromMem(span.data(), span.size()));
  if (!srcProfile)
    return nullptr;

  ScopedCmsProfile dstProfile(cmsCreate_sRGBProfile());
  if (!dstProfile)
    return nullptr;

  cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile.get());

  uint32_t nSrcComponents = cmsChannelsOf(srcCS);
  // According to PDF spec, number of components must be 1, 3, or 4.
  if (nSrcComponents != 1 && nSrcComponents != 3 && nSrcComponents != 4)
    return nullptr;

  int srcFormat;
  bool bLab = false;
  bool bNormal = false;
  if (srcCS == cmsSigLabData) {
    srcFormat =
        COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0);
    bLab = true;
  } else {
    srcFormat =
        COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1);
    // TODO(thestig): Check to see if lcms2 supports more colorspaces that can
    // be considered normal.
    bNormal = srcCS == cmsSigGrayData || srcCS == cmsSigRgbData ||
              srcCS == cmsSigCmykData;
  }
  cmsColorSpaceSignature dstCS = cmsGetColorSpace(dstProfile.get());
  if (!Check3Components(dstCS))
    return nullptr;

  cmsHTRANSFORM hTransform = nullptr;
  const int intent = 0;
  switch (dstCS) {
    case cmsSigRgbData:
      hTransform = cmsCreateTransform(srcProfile.get(), srcFormat,
                                      dstProfile.get(), TYPE_BGR_8, intent, 0);
      break;
    case cmsSigGrayData:
    case cmsSigCmykData:
      // Check3Components() already filtered these types.
      NOTREACHED();
      break;
    default:
      break;
  }
  if (!hTransform)
    return nullptr;

  return pdfium::MakeUnique<CLcmsCmm>(hTransform, nSrcComponents, bLab,
                                      bNormal);
}

void CCodec_IccModule::Translate(CLcmsCmm* pTransform,
                                 const float* pSrcValues,
                                 float* pDestValues) {
  if (!pTransform)
    return;

  uint32_t nSrcComponents = m_nComponents;
  uint8_t output[4];
  // TODO(npm): Currently the CmsDoTransform method is part of LCMS and it will
  // apply some member of m_hTransform to the input. We need to go over all the
  // places which set transform to verify that only nSrcComponents are used.
  if (pTransform->IsLab()) {
    std::vector<double> inputs(std::max(nSrcComponents, 16u));
    for (uint32_t i = 0; i < nSrcComponents; ++i)
      inputs[i] = pSrcValues[i];
    cmsDoTransform(pTransform->transform(), inputs.data(), output, 1);
  } else {
    std::vector<uint8_t> inputs(std::max(nSrcComponents, 16u));
    for (uint32_t i = 0; i < nSrcComponents; ++i) {
      inputs[i] =
          pdfium::clamp(static_cast<int>(pSrcValues[i] * 255.0f), 0, 255);
    }
    cmsDoTransform(pTransform->transform(), inputs.data(), output, 1);
  }
  pDestValues[0] = output[2] / 255.0f;
  pDestValues[1] = output[1] / 255.0f;
  pDestValues[2] = output[0] / 255.0f;
}

void CCodec_IccModule::TranslateScanline(CLcmsCmm* pTransform,
                                         unsigned char* pDest,
                                         const unsigned char* pSrc,
                                         int32_t pixels) {
  if (pTransform)
    cmsDoTransform(pTransform->transform(), pSrc, pDest, pixels);
}
