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

#include <algorithm>
#include <utility>

#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/compiler_specific.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
#include "third_party/abseil-cpp/absl/container/inlined_vector.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, VisitedSet* pVisited) {
  RetainPtr<const CPDF_Stream> pStream(pObj->AsStream());
  if (!pStream) {
    return false;
  }

  RetainPtr<const CPDF_Dictionary> dict = pStream->GetDict();
  RetainPtr<const CPDF_Array> pSize = dict->GetArrayFor("Size");
  if (!pSize || pSize->IsEmpty()) {
    return false;
  }

  bits_per_sample_ = dict->GetIntegerFor("BitsPerSample");
  if (!IsValidBitsPerSample(bits_per_sample_)) {
    return false;
  }

  FX_SAFE_UINT32 nTotalSampleBits = bits_per_sample_;
  nTotalSampleBits *= outputs_;
  RetainPtr<const CPDF_Array> pEncode = dict->GetArrayFor("Encode");
  encode_info_.resize(inputs_);
  for (uint32_t i = 0; i < inputs_; i++) {
    int size = pSize->GetIntegerAt(i);
    if (size <= 0) {
      return false;
    }

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

  sample_max_ = 0xffffffff >> (32 - bits_per_sample_);
  sample_stream_ = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pStream));
  sample_stream_->LoadAllDataFiltered();
  if (nTotalSampleBytes.ValueOrDie() > sample_stream_->GetSize()) {
    return false;
  }

  RetainPtr<const CPDF_Array> pDecode = dict->GetArrayFor("Decode");
  decode_info_.resize(outputs_);
  for (uint32_t i = 0; i < outputs_; i++) {
    if (pDecode) {
      decode_info_[i].decode_min = pDecode->GetFloatAt(2 * i);
      decode_info_[i].decode_max = pDecode->GetFloatAt(2 * i + 1);
    } else {
      decode_info_[i].decode_min = ranges_[i * 2];
      decode_info_[i].decode_max = ranges_[i * 2 + 1];
    }
  }
  return true;
}

bool CPDF_SampledFunc::v_Call(pdfium::span<const float> inputs,
                              pdfium::span<float> results) const {
  int pos = 0;
  absl::InlinedVector<float, 16, FxAllocAllocator<float>> encoded_input(
      inputs_);
  absl::InlinedVector<uint32_t, 16, FxAllocAllocator<uint32_t>> index(inputs_);
  absl::InlinedVector<uint32_t, 16, FxAllocAllocator<uint32_t>> blocksize(
      inputs_);
  for (uint32_t i = 0; i < inputs_; i++) {
    if (i == 0) {
      blocksize[i] = 1;
    } else {
      blocksize[i] = blocksize[i - 1] * encode_info_[i - 1].sizes;
    }
    encoded_input[i] =
        Interpolate(inputs[i], domains_[i * 2], domains_[i * 2 + 1],
                    encode_info_[i].encode_min, encode_info_[i].encode_max);
    index[i] = std::clamp(static_cast<uint32_t>(encoded_input[i]), 0U,
                          encode_info_[i].sizes - 1);
    pos += index[i] * blocksize[i];
  }
  FX_SAFE_INT32 bits_to_output = outputs_;
  bits_to_output *= bits_per_sample_;
  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 = sample_stream_->GetSpan();
  if (pSampleData.empty()) {
    return false;
  }

  CFX_BitStream bitstream(pSampleData);
  bitstream.SkipBits(bits_to_skip);
  for (uint32_t i = 0; i < outputs_; ++i) {
    uint32_t sample = bitstream.GetBits(bits_per_sample_);
    float encoded = sample;
    for (uint32_t j = 0; j < inputs_; ++j) {
      if (index[j] == encode_info_[j].sizes - 1) {
        if (index[j] == 0) {
          encoded = encoded_input[j] * sample;
        }
      } else {
        FX_SAFE_INT32 bitpos2 = blocksize[j];
        bitpos2 += pos;
        bitpos2 *= outputs_;
        bitpos2 += i;
        bitpos2 *= bits_per_sample_;
        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(bits_per_sample_));
        encoded += (encoded_input[j] - index[j]) * (sample2 - sample);
      }
    }
    results[i] =
        Interpolate(encoded, 0, sample_max_, decode_info_[i].decode_min,
                    decode_info_[i].decode_max);
  }
  return true;
}

#if defined(PDF_USE_SKIA)
RetainPtr<CPDF_StreamAcc> CPDF_SampledFunc::GetSampleStream() const {
  return sample_stream_;
}
#endif
