// Copyright 2017 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_sampledfunc.h"

#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fxcrt/cfx_bitstream.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/small_buffer.h"
#include "third_party/base/cxx17_backports.h"

namespace {

// See PDF Reference 1.7, page 170, table 3.36.
bool IsValidBitsPerSample(uint32_t x) {
  switch (x) {
    case 1:
    case 2:
    case 4:
    case 8:
    case 12:
    case 16:
    case 24:
    case 32:
      return true;
    default:
      return false;
  }
}

}  // namespace

CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {}

CPDF_SampledFunc::~CPDF_SampledFunc() = default;

bool CPDF_SampledFunc::v_Init(const CPDF_Object* pObj,
                              std::set<const CPDF_Object*>* pVisited) {
  const CPDF_Stream* pStream = pObj->AsStream();
  if (!pStream)
    return false;

  const CPDF_Dictionary* pDict = pStream->GetDict();
  const CPDF_Array* pSize = pDict->GetArrayFor("Size");
  if (!pSize || pSize->IsEmpty())
    return false;

  m_nBitsPerSample = pDict->GetIntegerFor("BitsPerSample");
  if (!IsValidBitsPerSample(m_nBitsPerSample))
    return false;

  FX_SAFE_UINT32 nTotalSampleBits = m_nBitsPerSample;
  nTotalSampleBits *= m_nOutputs;
  const CPDF_Array* pEncode = pDict->GetArrayFor("Encode");
  m_EncodeInfo.resize(m_nInputs);
  for (uint32_t i = 0; i < m_nInputs; i++) {
    int size = pSize->GetIntegerAt(i);
    if (size <= 0)
      return false;

    m_EncodeInfo[i].sizes = size;
    nTotalSampleBits *= m_EncodeInfo[i].sizes;
    if (pEncode) {
      m_EncodeInfo[i].encode_min = pEncode->GetNumberAt(i * 2);
      m_EncodeInfo[i].encode_max = pEncode->GetNumberAt(i * 2 + 1);
    } else {
      m_EncodeInfo[i].encode_min = 0;
      m_EncodeInfo[i].encode_max =
          m_EncodeInfo[i].sizes == 1 ? 1 : m_EncodeInfo[i].sizes - 1;
    }
  }
  FX_SAFE_UINT32 nTotalSampleBytes = (nTotalSampleBits + 7) / 8;
  if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0)
    return false;

  m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
  m_pSampleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
  m_pSampleStream->LoadAllDataFiltered();
  if (nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize())
    return false;

  const CPDF_Array* pDecode = pDict->GetArrayFor("Decode");
  m_DecodeInfo.resize(m_nOutputs);
  for (uint32_t i = 0; i < m_nOutputs; i++) {
    if (pDecode) {
      m_DecodeInfo[i].decode_min = pDecode->GetNumberAt(2 * i);
      m_DecodeInfo[i].decode_max = pDecode->GetNumberAt(2 * i + 1);
    } else {
      m_DecodeInfo[i].decode_min = m_Ranges[i * 2];
      m_DecodeInfo[i].decode_max = m_Ranges[i * 2 + 1];
    }
  }
  return true;
}

bool CPDF_SampledFunc::v_Call(pdfium::span<const float> inputs,
                              pdfium::span<float> results) const {
  int pos = 0;
  fxcrt::SmallBuffer<float, 16> encoded_input_buf(m_nInputs);
  fxcrt::SmallBuffer<uint32_t, 32> int_buf(m_nInputs * 2);
  float* encoded_input = encoded_input_buf.data();
  uint32_t* index = int_buf.data();
  uint32_t* blocksize = index + m_nInputs;
  for (uint32_t i = 0; i < m_nInputs; i++) {
    if (i == 0)
      blocksize[i] = 1;
    else
      blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes;
    encoded_input[i] =
        Interpolate(inputs[i], m_Domains[i * 2], m_Domains[i * 2 + 1],
                    m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max);
    index[i] = pdfium::clamp(static_cast<uint32_t>(encoded_input[i]), 0U,
                             m_EncodeInfo[i].sizes - 1);
    pos += index[i] * blocksize[i];
  }
  FX_SAFE_INT32 bits_to_output = m_nOutputs;
  bits_to_output *= m_nBitsPerSample;
  if (!bits_to_output.IsValid())
    return false;

  int bits_to_skip;
  {
    FX_SAFE_INT32 bitpos = pos;
    bitpos *= bits_to_output.ValueOrDie();
    bits_to_skip = bitpos.ValueOrDefault(-1);
    if (bits_to_skip < 0)
      return false;

    FX_SAFE_INT32 range_check = bitpos;
    range_check += bits_to_output.ValueOrDie();
    if (!range_check.IsValid())
      return false;
  }

  pdfium::span<const uint8_t> pSampleData = m_pSampleStream->GetSpan();
  if (pSampleData.empty())
    return false;

  CFX_BitStream bitstream(pSampleData);
  bitstream.SkipBits(bits_to_skip);
  for (uint32_t i = 0; i < m_nOutputs; ++i) {
    uint32_t sample = bitstream.GetBits(m_nBitsPerSample);
    float encoded = sample;
    for (uint32_t j = 0; j < m_nInputs; ++j) {
      if (index[j] == m_EncodeInfo[j].sizes - 1) {
        if (index[j] == 0)
          encoded = encoded_input[j] * sample;
      } else {
        FX_SAFE_INT32 bitpos2 = blocksize[j];
        bitpos2 += pos;
        bitpos2 *= m_nOutputs;
        bitpos2 += i;
        bitpos2 *= m_nBitsPerSample;
        int bits_to_skip2 = bitpos2.ValueOrDefault(-1);
        if (bits_to_skip2 < 0)
          return false;

        CFX_BitStream bitstream2(pSampleData);
        bitstream2.SkipBits(bits_to_skip2);
        float sample2 =
            static_cast<float>(bitstream2.GetBits(m_nBitsPerSample));
        encoded += (encoded_input[j] - index[j]) * (sample2 - sample);
      }
    }
    results[i] =
        Interpolate(encoded, 0, m_SampleMax, m_DecodeInfo[i].decode_min,
                    m_DecodeInfo[i].decode_max);
  }
  return true;
}

#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
RetainPtr<CPDF_StreamAcc> CPDF_SampledFunc::GetSampleStream() const {
  return m_pSampleStream;
}
#endif
