Clean up CPDF_TransferFunc.

- Prepare samples in the ctor caller and std::move() the samples in.
- Make members all const.
- Use spans.

Change-Id: I5a819fcc9d46328eb5aa2e79f2eaedde29bb84e1
Reviewed-on: https://pdfium-review.googlesource.com/c/45290
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
index b73fc77..ee27378 100644
--- a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
+++ b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
@@ -14,13 +14,12 @@
 
 CPDF_DIBTransferFunc::CPDF_DIBTransferFunc(
     const RetainPtr<CPDF_TransferFunc>& pTransferFunc)
-    : m_pTransferFunc(pTransferFunc) {
-  m_RampR = pTransferFunc->GetSamples();
-  m_RampG = &pTransferFunc->GetSamples()[256];
-  m_RampB = &pTransferFunc->GetSamples()[512];
-}
+    : m_pTransferFunc(pTransferFunc),
+      m_RampR(pTransferFunc->GetSamplesR()),
+      m_RampG(pTransferFunc->GetSamplesG()),
+      m_RampB(pTransferFunc->GetSamplesB()) {}
 
-CPDF_DIBTransferFunc::~CPDF_DIBTransferFunc() {}
+CPDF_DIBTransferFunc::~CPDF_DIBTransferFunc() = default;
 
 FXDIB_Format CPDF_DIBTransferFunc::GetDestFormat() {
   if (m_pSrc->IsAlphaMask())
diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.h b/core/fpdfapi/render/cpdf_dibtransferfunc.h
index 9db97f1..3ad9023 100644
--- a/core/fpdfapi/render/cpdf_dibtransferfunc.h
+++ b/core/fpdfapi/render/cpdf_dibtransferfunc.h
@@ -11,6 +11,7 @@
 
 #include "core/fxge/dib/cfx_filtereddib.h"
 #include "core/fxge/fx_dib.h"
+#include "third_party/base/span.h"
 
 class CPDF_TransferFunc;
 
@@ -35,9 +36,9 @@
   ~CPDF_DIBTransferFunc() override;
 
   RetainPtr<CPDF_TransferFunc> m_pTransferFunc;
-  const uint8_t* m_RampR;
-  const uint8_t* m_RampG;
-  const uint8_t* m_RampB;
+  const pdfium::span<const uint8_t> m_RampR;
+  const pdfium::span<const uint8_t> m_RampG;
+  const pdfium::span<const uint8_t> m_RampB;
 };
 
 #endif  // CORE_FPDFAPI_RENDER_CPDF_DIBTRANSFERFUNC_H_
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp
index fb54e14..e713866 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp
@@ -6,7 +6,10 @@
 
 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
 
+#include <array>
 #include <memory>
+#include <utility>
+#include <vector>
 
 #include "core/fpdfapi/font/cpdf_type3font.h"
 #include "core/fpdfapi/page/cpdf_function.h"
@@ -88,39 +91,46 @@
     if (!pFuncs[0])
       return nullptr;
   }
-  auto pTransfer = pdfium::MakeRetain<CPDF_TransferFunc>(m_pPDFDoc.Get());
-  m_TransferFuncMap[pObj] = pTransfer;
 
   float input;
   int noutput;
   float output[kMaxOutputs];
   memset(output, 0, sizeof(output));
-  for (int v = 0; v < 256; ++v) {
-    input = (float)v / 255.0f;
+
+  std::vector<uint8_t> samples_r(CPDF_TransferFunc::kChannelSampleSize);
+  std::vector<uint8_t> samples_g(CPDF_TransferFunc::kChannelSampleSize);
+  std::vector<uint8_t> samples_b(CPDF_TransferFunc::kChannelSampleSize);
+  std::array<pdfium::span<uint8_t>, 3> samples = {samples_r, samples_g,
+                                                  samples_b};
+  for (size_t v = 0; v < CPDF_TransferFunc::kChannelSampleSize; ++v) {
+    input = static_cast<float>(v) / 255.0f;
     if (bUniTransfer) {
       if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
         pFuncs[0]->Call(&input, 1, output, &noutput);
-      int o = FXSYS_round(output[0] * 255);
+      size_t o = FXSYS_round(output[0] * 255);
       if (o != v)
         bIdentity = false;
-      for (int i = 0; i < 3; ++i)
-        pTransfer->GetSamples()[i * 256 + v] = o;
+      for (auto& channel : samples)
+        channel[v] = o;
       continue;
     }
     for (int i = 0; i < 3; ++i) {
       if (!pFuncs[i] || pFuncs[i]->CountOutputs() > kMaxOutputs) {
-        pTransfer->GetSamples()[i * 256 + v] = v;
+        samples[i][v] = v;
         continue;
       }
       pFuncs[i]->Call(&input, 1, output, &noutput);
-      int o = FXSYS_round(output[0] * 255);
+      size_t o = FXSYS_round(output[0] * 255);
       if (o != v)
         bIdentity = false;
-      pTransfer->GetSamples()[i * 256 + v] = o;
+      samples[i][v] = o;
     }
   }
 
-  pTransfer->SetIdentity(bIdentity);
+  auto pTransfer = pdfium::MakeRetain<CPDF_TransferFunc>(
+      m_pPDFDoc.Get(), bIdentity, std::move(samples_r), std::move(samples_g),
+      std::move(samples_b));
+  m_TransferFuncMap[pObj] = pTransfer;
   return pTransfer;
 }
 
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.h b/core/fpdfapi/render/cpdf_docrenderdata.h
index e4e3548..71ca9f4 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.h
+++ b/core/fpdfapi/render/cpdf_docrenderdata.h
@@ -10,13 +10,14 @@
 #include <map>
 
 #include "core/fpdfapi/page/cpdf_countedobject.h"
-#include "core/fpdfapi/render/cpdf_transferfunc.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 
 class CPDF_Document;
 class CPDF_Font;
 class CPDF_Object;
+class CPDF_TransferFunc;
 class CPDF_Type3Cache;
 class CPDF_Type3Font;
 
diff --git a/core/fpdfapi/render/cpdf_transferfunc.cpp b/core/fpdfapi/render/cpdf_transferfunc.cpp
index f67f508..9f7a029 100644
--- a/core/fpdfapi/render/cpdf_transferfunc.cpp
+++ b/core/fpdfapi/render/cpdf_transferfunc.cpp
@@ -6,18 +6,33 @@
 
 #include "core/fpdfapi/render/cpdf_transferfunc.h"
 
+#include <utility>
+
 #include "core/fpdfapi/parser/cpdf_document.h"
 #include "core/fpdfapi/render/cpdf_dibtransferfunc.h"
 #include "core/fxge/dib/cfx_dibbase.h"
 
-CPDF_TransferFunc::CPDF_TransferFunc(CPDF_Document* pDoc) : m_pPDFDoc(pDoc) {}
+CPDF_TransferFunc::CPDF_TransferFunc(CPDF_Document* pDoc,
+                                     bool bIdentify,
+                                     std::vector<uint8_t> samples_r,
+                                     std::vector<uint8_t> samples_g,
+                                     std::vector<uint8_t> samples_b)
+    : m_pPDFDoc(pDoc),
+      m_bIdentity(bIdentify),
+      m_SamplesR(std::move(samples_r)),
+      m_SamplesG(std::move(samples_g)),
+      m_SamplesB(std::move(samples_b)) {
+  ASSERT(m_SamplesR.size() == kChannelSampleSize);
+  ASSERT(m_SamplesG.size() == kChannelSampleSize);
+  ASSERT(m_SamplesB.size() == kChannelSampleSize);
+}
 
-CPDF_TransferFunc::~CPDF_TransferFunc() {}
+CPDF_TransferFunc::~CPDF_TransferFunc() = default;
 
 FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF colorref) const {
-  return FXSYS_BGR(m_Samples[512 + FXSYS_GetBValue(colorref)],
-                   m_Samples[256 + FXSYS_GetGValue(colorref)],
-                   m_Samples[FXSYS_GetRValue(colorref)]);
+  return FXSYS_BGR(m_SamplesB[FXSYS_GetBValue(colorref)],
+                   m_SamplesG[FXSYS_GetGValue(colorref)],
+                   m_SamplesR[FXSYS_GetRValue(colorref)]);
 }
 
 RetainPtr<CFX_DIBBase> CPDF_TransferFunc::TranslateImage(
@@ -27,3 +42,15 @@
   pDest->LoadSrc(pSrc);
   return pDest;
 }
+
+pdfium::span<const uint8_t> CPDF_TransferFunc::GetSamplesR() const {
+  return m_SamplesR;
+}
+
+pdfium::span<const uint8_t> CPDF_TransferFunc::GetSamplesG() const {
+  return m_SamplesG;
+}
+
+pdfium::span<const uint8_t> CPDF_TransferFunc::GetSamplesB() const {
+  return m_SamplesB;
+}
diff --git a/core/fpdfapi/render/cpdf_transferfunc.h b/core/fpdfapi/render/cpdf_transferfunc.h
index d45184e..74fc01d 100644
--- a/core/fpdfapi/render/cpdf_transferfunc.h
+++ b/core/fpdfapi/render/cpdf_transferfunc.h
@@ -7,9 +7,12 @@
 #ifndef CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_
 #define CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_
 
+#include <vector>
+
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxge/fx_dib.h"
+#include "third_party/base/span.h"
 
 class CPDF_Document;
 class CFX_DIBBase;
@@ -19,24 +22,33 @@
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+  static constexpr size_t kChannelSampleSize = 256;
+
   FX_COLORREF TranslateColor(FX_COLORREF colorref) const;
   RetainPtr<CFX_DIBBase> TranslateImage(const RetainPtr<CFX_DIBBase>& pSrc);
 
   const CPDF_Document* GetDocument() const { return m_pPDFDoc.Get(); }
 
-  const uint8_t* GetSamples() const { return m_Samples; }
-  uint8_t* GetSamples() { return m_Samples; }
+  // Spans are |kChannelSampleSize| in size.
+  pdfium::span<const uint8_t> GetSamplesR() const;
+  pdfium::span<const uint8_t> GetSamplesG() const;
+  pdfium::span<const uint8_t> GetSamplesB() const;
 
   bool GetIdentity() const { return m_bIdentity; }
-  void SetIdentity(bool identity) { m_bIdentity = identity; }
 
  private:
-  explicit CPDF_TransferFunc(CPDF_Document* pDoc);
+  CPDF_TransferFunc(CPDF_Document* pDoc,
+                    bool bIdentify,
+                    std::vector<uint8_t> samples_r,
+                    std::vector<uint8_t> samples_g,
+                    std::vector<uint8_t> samples_b);
   ~CPDF_TransferFunc() override;
 
   UnownedPtr<CPDF_Document> const m_pPDFDoc;
-  bool m_bIdentity;
-  uint8_t m_Samples[256 * 3];
+  const bool m_bIdentity;
+  const std::vector<uint8_t> m_SamplesR;
+  const std::vector<uint8_t> m_SamplesG;
+  const std::vector<uint8_t> m_SamplesB;
 };
 
 #endif  // CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_