// 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/fxcodec/codec/iccmodule.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "core/fxcodec/codec/codec_int.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"

namespace fxcodec {

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

// static
std::unique_ptr<CLcmsCmm> IccModule::CreateTransformSRGB(
    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);
}

// static
void IccModule::Translate(CLcmsCmm* pTransform,
                          uint32_t nSrcComponents,
                          const float* pSrcValues,
                          float* pDestValues) {
  if (!pTransform)
    return;

  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;
}

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

}  // namespace fxcodec
