RefCount CPDF_TransferFunc all the time.

Prefer internal reference counts over ad-hoc schemes.

Change-Id: I8d420e9e9827ac39fdc0bc8146a532caeee10f26
Reviewed-on: https://pdfium-review.googlesource.com/3615
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_generalstate.cpp b/core/fpdfapi/page/cpdf_generalstate.cpp
index dd5c5af..513e5ff 100644
--- a/core/fpdfapi/page/cpdf_generalstate.cpp
+++ b/core/fpdfapi/page/cpdf_generalstate.cpp
@@ -124,12 +124,13 @@
   m_Ref.GetPrivateCopy()->m_pTR = pObject;
 }
 
-CPDF_TransferFunc* CPDF_GeneralState::GetTransferFunc() const {
+CFX_RetainPtr<CPDF_TransferFunc> CPDF_GeneralState::GetTransferFunc() const {
   const StateData* pData = m_Ref.GetObject();
   return pData ? pData->m_pTransferFunc : nullptr;
 }
 
-void CPDF_GeneralState::SetTransferFunc(CPDF_TransferFunc* pFunc) {
+void CPDF_GeneralState::SetTransferFunc(
+    const CFX_RetainPtr<CPDF_TransferFunc>& pFunc) {
   m_Ref.GetPrivateCopy()->m_pTransferFunc = pFunc;
 }
 
@@ -277,7 +278,9 @@
 CPDF_GeneralState::StateData::~StateData() {
   if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) {
     CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData();
-    if (pDocCache)
-      pDocCache->ReleaseTransferFunc(m_pTR);
+    if (pDocCache) {
+      m_pTransferFunc.Reset();  // Give up our reference first.
+      pDocCache->MaybePurgeTransferFunc(m_pTR);
+    }
   }
 }
diff --git a/core/fpdfapi/page/cpdf_generalstate.h b/core/fpdfapi/page/cpdf_generalstate.h
index 1c5ddee..8de5a36 100644
--- a/core/fpdfapi/page/cpdf_generalstate.h
+++ b/core/fpdfapi/page/cpdf_generalstate.h
@@ -41,8 +41,8 @@
   CPDF_Object* GetTR() const;
   void SetTR(CPDF_Object* pObject);
 
-  CPDF_TransferFunc* GetTransferFunc() const;
-  void SetTransferFunc(CPDF_TransferFunc* pFunc);
+  CFX_RetainPtr<CPDF_TransferFunc> GetTransferFunc() const;
+  void SetTransferFunc(const CFX_RetainPtr<CPDF_TransferFunc>& pFunc);
 
   void SetBlendMode(const CFX_ByteString& mode);
 
@@ -88,7 +88,7 @@
     float m_StrokeAlpha;
     float m_FillAlpha;
     CPDF_Object* m_pTR;
-    CPDF_TransferFunc* m_pTransferFunc;
+    CFX_RetainPtr<CPDF_TransferFunc> m_pTransferFunc;
     CFX_Matrix m_Matrix;
     int m_RenderIntent;
     bool m_StrokeAdjust;
diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
index 41575fc..6ba148e 100644
--- a/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
+++ b/core/fpdfapi/render/cpdf_dibtransferfunc.cpp
@@ -12,7 +12,8 @@
 #include "core/fpdfapi/render/cpdf_transferfunc.h"
 
 CPDF_DIBTransferFunc::CPDF_DIBTransferFunc(
-    const CPDF_TransferFunc* pTransferFunc) {
+    const CFX_RetainPtr<CPDF_TransferFunc>& pTransferFunc)
+    : m_pTransferFunc(pTransferFunc) {
   m_RampR = pTransferFunc->m_Samples;
   m_RampG = &pTransferFunc->m_Samples[256];
   m_RampB = &pTransferFunc->m_Samples[512];
diff --git a/core/fpdfapi/render/cpdf_dibtransferfunc.h b/core/fpdfapi/render/cpdf_dibtransferfunc.h
index 25c76ec..b22ae9c 100644
--- a/core/fpdfapi/render/cpdf_dibtransferfunc.h
+++ b/core/fpdfapi/render/cpdf_dibtransferfunc.h
@@ -32,11 +32,13 @@
                             int Bpp) const override;
 
  private:
-  explicit CPDF_DIBTransferFunc(const CPDF_TransferFunc* pTransferFunc);
+  explicit CPDF_DIBTransferFunc(
+      const CFX_RetainPtr<CPDF_TransferFunc>& pTransferFunc);
 
   const uint8_t* m_RampR;
   const uint8_t* m_RampG;
   const uint8_t* m_RampB;
+  CFX_RetainPtr<CPDF_TransferFunc> m_pTransferFunc;
 };
 
 #endif  // CORE_FPDFAPI_RENDER_CPDF_DIBTRANSFERFUNC_H_
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.cpp b/core/fpdfapi/render/cpdf_docrenderdata.cpp
index b34fa2c..39d1fcd 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.cpp
+++ b/core/fpdfapi/render/cpdf_docrenderdata.cpp
@@ -42,12 +42,8 @@
 
   for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
     auto curr_it = it++;
-    CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
-    if (bRelease || value->use_count() < 2) {
-      delete value->get();
-      delete value;
+    if (bRelease || curr_it->second->HasOneRef())
       m_TransferFuncMap.erase(curr_it);
-    }
   }
 }
 
@@ -76,15 +72,14 @@
   }
 }
 
-CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
+CFX_RetainPtr<CPDF_TransferFunc> CPDF_DocRenderData::GetTransferFunc(
+    CPDF_Object* pObj) {
   if (!pObj)
     return nullptr;
 
   auto it = m_TransferFuncMap.find(pObj);
-  if (it != m_TransferFuncMap.end()) {
-    CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
-    return pTransferCounter->AddRef();
-  }
+  if (it != m_TransferFuncMap.end())
+    return it->second;
 
   std::unique_ptr<CPDF_Function> pFuncs[3];
   bool bUniTransfer = true;
@@ -104,15 +99,13 @@
     if (!pFuncs[0])
       return nullptr;
   }
-  CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
-      new CPDF_CountedObject<CPDF_TransferFunc>(
-          pdfium::MakeUnique<CPDF_TransferFunc>(m_pPDFDoc));
-  CPDF_TransferFunc* pTransfer = pTransferCounter->get();
-  m_TransferFuncMap[pObj] = pTransferCounter;
-  float output[kMaxOutputs];
-  memset(output, 0, sizeof(output));
+  auto pTransfer = pdfium::MakeRetain<CPDF_TransferFunc>(m_pPDFDoc);
+  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;
     if (bUniTransfer) {
@@ -139,17 +132,11 @@
   }
 
   pTransfer->m_bIdentity = bIdentity;
-  return pTransferCounter->AddRef();
+  return pTransfer;
 }
 
-void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) {
+void CPDF_DocRenderData::MaybePurgeTransferFunc(CPDF_Object* pObj) {
   auto it = m_TransferFuncMap.find(pObj);
-  if (it != m_TransferFuncMap.end()) {
-    it->second->RemoveRef();
-    if (it->second->use_count() < 2) {
-      delete it->second->get();
-      delete it->second;
-      m_TransferFuncMap.erase(it);
-    }
-  }
+  if (it != m_TransferFuncMap.end() && it->second->HasOneRef())
+    m_TransferFuncMap.erase(it);
 }
diff --git a/core/fpdfapi/render/cpdf_docrenderdata.h b/core/fpdfapi/render/cpdf_docrenderdata.h
index a8f4167..5daee34 100644
--- a/core/fpdfapi/render/cpdf_docrenderdata.h
+++ b/core/fpdfapi/render/cpdf_docrenderdata.h
@@ -10,11 +10,11 @@
 #include <map>
 
 #include "core/fpdfapi/page/cpdf_countedobject.h"
+#include "core/fpdfapi/render/cpdf_transferfunc.h"
 
 class CPDF_Document;
 class CPDF_Font;
 class CPDF_Object;
-class CPDF_TransferFunc;
 class CPDF_Type3Cache;
 class CPDF_Type3Font;
 
@@ -25,19 +25,19 @@
 
   CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont);
   void ReleaseCachedType3(CPDF_Type3Font* pFont);
-  CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObj);
-  void ReleaseTransferFunc(CPDF_Object* pObj);
+
+  CFX_RetainPtr<CPDF_TransferFunc> GetTransferFunc(CPDF_Object* pObj);
+  void MaybePurgeTransferFunc(CPDF_Object* pOb);
+
   void Clear(bool bRelease);
 
  private:
   using CPDF_Type3CacheMap =
       std::map<CPDF_Font*, CPDF_CountedObject<CPDF_Type3Cache>*>;
-  using CPDF_TransferFuncMap =
-      std::map<CPDF_Object*, CPDF_CountedObject<CPDF_TransferFunc>*>;
 
   CPDF_Document* m_pPDFDoc;  // Not Owned
   CPDF_Type3CacheMap m_Type3FaceMap;
-  CPDF_TransferFuncMap m_TransferFuncMap;
+  std::map<CPDF_Object*, CFX_RetainPtr<CPDF_TransferFunc>> m_TransferFuncMap;
 };
 
 #endif  // CORE_FPDFAPI_RENDER_CPDF_DOCRENDERDATA_H_
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 97bb0ac..69293e6 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -1300,7 +1300,8 @@
       fill_argb, stroke_argb, FillType, m_curBlend);
 }
 
-CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const {
+CFX_RetainPtr<CPDF_TransferFunc> CPDF_RenderStatus::GetTransferFunc(
+    CPDF_Object* pObj) const {
   ASSERT(pObj);
   CPDF_DocRenderData* pDocCache = m_pContext->GetDocument()->GetRenderData();
   return pDocCache ? pDocCache->GetTransferFunc(pObj) : nullptr;
diff --git a/core/fpdfapi/render/cpdf_renderstatus.h b/core/fpdfapi/render/cpdf_renderstatus.h
index e3dcd73..354c7b1 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.h
+++ b/core/fpdfapi/render/cpdf_renderstatus.h
@@ -144,7 +144,7 @@
   static CPDF_Type3Cache* GetCachedType3(CPDF_Type3Font* pFont);
   static CPDF_GraphicStates* CloneObjStates(const CPDF_GraphicStates* pPathObj,
                                             bool bStroke);
-  CPDF_TransferFunc* GetTransferFunc(CPDF_Object* pObject) const;
+  CFX_RetainPtr<CPDF_TransferFunc> GetTransferFunc(CPDF_Object* pObject) const;
   FX_ARGB GetFillArgb(CPDF_PageObject* pObj, bool bType3 = false) const;
   FX_ARGB GetStrokeArgb(CPDF_PageObject* pObj) const;
   bool GetObjectClippedRect(const CPDF_PageObject* pObj,
diff --git a/core/fpdfapi/render/cpdf_transferfunc.cpp b/core/fpdfapi/render/cpdf_transferfunc.cpp
index ed1f27d..a7ee42f 100644
--- a/core/fpdfapi/render/cpdf_transferfunc.cpp
+++ b/core/fpdfapi/render/cpdf_transferfunc.cpp
@@ -11,6 +11,8 @@
 
 CPDF_TransferFunc::CPDF_TransferFunc(CPDF_Document* pDoc) : m_pPDFDoc(pDoc) {}
 
+CPDF_TransferFunc::~CPDF_TransferFunc() {}
+
 FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF rgb) const {
   return FXSYS_RGB(m_Samples[FXSYS_GetRValue(rgb)],
                    m_Samples[256 + FXSYS_GetGValue(rgb)],
@@ -19,7 +21,8 @@
 
 CFX_RetainPtr<CFX_DIBSource> CPDF_TransferFunc::TranslateImage(
     const CFX_RetainPtr<CFX_DIBSource>& pSrc) {
-  auto pDest = pdfium::MakeRetain<CPDF_DIBTransferFunc>(this);
+  CFX_RetainPtr<CPDF_TransferFunc> pHolder(this);
+  auto pDest = pdfium::MakeRetain<CPDF_DIBTransferFunc>(pHolder);
   pDest->LoadSrc(pSrc);
   return pDest;
 }
diff --git a/core/fpdfapi/render/cpdf_transferfunc.h b/core/fpdfapi/render/cpdf_transferfunc.h
index 05219d4..8f94d96 100644
--- a/core/fpdfapi/render/cpdf_transferfunc.h
+++ b/core/fpdfapi/render/cpdf_transferfunc.h
@@ -7,13 +7,15 @@
 #ifndef CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_
 #define CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_
 
+#include "core/fxcrt/cfx_retain_ptr.h"
 #include "core/fxge/fx_dib.h"
 
 class CPDF_Document;
 
-class CPDF_TransferFunc {
+class CPDF_TransferFunc : public CFX_Retainable {
  public:
-  explicit CPDF_TransferFunc(CPDF_Document* pDoc);
+  template <typename T, typename... Args>
+  friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
   FX_COLORREF TranslateColor(FX_COLORREF src) const;
   CFX_RetainPtr<CFX_DIBSource> TranslateImage(
@@ -22,6 +24,10 @@
   CPDF_Document* const m_pPDFDoc;
   bool m_bIdentity;
   uint8_t m_Samples[256 * 3];
+
+ private:
+  explicit CPDF_TransferFunc(CPDF_Document* pDoc);
+  ~CPDF_TransferFunc() override;
 };
 
 #endif  // CORE_FPDFAPI_RENDER_CPDF_TRANSFERFUNC_H_