Implement CPDF_Object::MakeReference method.

Change-Id: I153747ef587a184eaef58ff09dbf8f214c9ddfb3
Reviewed-on: https://pdfium-review.googlesource.com/17230
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Art Snake <art-snake@yandex-team.ru>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index ba0aeef..3365b5f 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -91,48 +91,44 @@
   if (pContent) {
     CPDF_Array* pArray = ToArray(pContent);
     if (pArray) {
-      pArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
+      pArray->Add(pStream->MakeReference(pDoc));
       return;
     }
     CPDF_Reference* pReference = ToReference(pContent);
     if (!pReference) {
-      pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
-                                           pStream->GetObjNum());
+      pPageDict->SetFor("Contents", pStream->MakeReference(pDoc));
       return;
     }
     CPDF_Object* pDirectObj = pReference->GetDirect();
     if (!pDirectObj) {
-      pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
-                                           pStream->GetObjNum());
+      pPageDict->SetFor("Contents", pStream->MakeReference(pDoc));
       return;
     }
     CPDF_Array* pObjArray = pDirectObj->AsArray();
     if (pObjArray) {
-      pObjArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
+      pObjArray->Add(pStream->MakeReference(pDoc));
       return;
     }
     if (pDirectObj->IsStream()) {
       CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
-      pContentArray->AddNew<CPDF_Reference>(pDoc, pDirectObj->GetObjNum());
-      pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
-      pPageDict->SetNewFor<CPDF_Reference>("Contents", pDoc,
-                                           pContentArray->GetObjNum());
+      pContentArray->Add(pDirectObj->MakeReference(pDoc));
+      pContentArray->Add(pStream->MakeReference(pDoc));
+      pPageDict->SetFor("Contents", pContentArray->MakeReference(pDoc));
       return;
     }
   }
-  pPageDict->SetNewFor<CPDF_Reference>("Contents", m_pDocument.Get(),
-                                       pStream->GetObjNum());
+  pPageDict->SetFor("Contents", pStream->MakeReference(pDoc));
 }
 
 ByteString CPDF_PageContentGenerator::RealizeResource(
-    uint32_t dwResourceObjNum,
+    const CPDF_Object* pResource,
     const ByteString& bsType) {
-  ASSERT(dwResourceObjNum);
+  ASSERT(pResource);
   if (!m_pObjHolder->m_pResources) {
     m_pObjHolder->m_pResources = m_pDocument->NewIndirect<CPDF_Dictionary>();
-    m_pObjHolder->GetDict()->SetNewFor<CPDF_Reference>(
-        "Resources", m_pDocument.Get(),
-        m_pObjHolder->m_pResources->GetObjNum());
+    m_pObjHolder->GetDict()->SetFor(
+        "Resources",
+        m_pObjHolder->m_pResources->MakeReference(m_pDocument.Get()));
   }
   CPDF_Dictionary* pResList = m_pObjHolder->m_pResources->GetDictFor(bsType);
   if (!pResList)
@@ -147,8 +143,7 @@
 
     idnum++;
   }
-  pResList->SetNewFor<CPDF_Reference>(name, m_pDocument.Get(),
-                                      dwResourceObjNum);
+  pResList->SetFor(name, pResource->MakeReference(m_pDocument.Get()));
   return name;
 }
 
@@ -190,10 +185,10 @@
   if (bWasInline)
     pImage->ConvertStreamToIndirectObject();
 
-  uint32_t dwObjNum = pStream->GetObjNum();
-  ByteString name = RealizeResource(dwObjNum, "XObject");
+  ByteString name = RealizeResource(pStream, "XObject");
   if (bWasInline)
-    pImageObj->SetImage(m_pDocument->GetPageData()->GetImage(dwObjNum));
+    pImageObj->SetImage(
+        m_pDocument->GetPageData()->GetImage(pStream->GetObjNum()));
 
   *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
 }
@@ -323,8 +318,7 @@
                                    pPageObj->m_GeneralState.GetBlendMode());
     }
     CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
-    uint32_t dwObjNum = pDict->GetObjNum();
-    name = RealizeResource(dwObjNum, "ExtGState");
+    name = RealizeResource(pDict, "ExtGState");
     m_pObjHolder->m_GraphicsMap[graphD] = name;
   }
   *buf << "/" << PDF_NameEncode(name) << " gs ";
@@ -349,8 +343,7 @@
     gsDict->SetNewFor<CPDF_Number>("CA", defaultGraphics.strokeAlpha);
     gsDict->SetNewFor<CPDF_Name>("BM", "Normal");
     CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict));
-    uint32_t dwObjNum = pDict->GetObjNum();
-    name = RealizeResource(dwObjNum, "ExtGState");
+    name = RealizeResource(pDict, "ExtGState");
     m_pObjHolder->m_GraphicsMap[defaultGraphics] = name;
   }
   *buf << "/" << PDF_NameEncode(name).c_str() << " gs ";
@@ -382,17 +375,16 @@
   if (it != m_pObjHolder->m_FontsMap.end()) {
     dictName = it->second;
   } else {
-    uint32_t dwObjNum = pFont->GetFontDict()->GetObjNum();
-    if (!dwObjNum) {
+    CPDF_Object* pIndirectFont = pFont->GetFontDict();
+    if (pIndirectFont->IsInline()) {
       // In this case we assume it must be a standard font
       auto fontDict = pdfium::MakeUnique<CPDF_Dictionary>();
       fontDict->SetNewFor<CPDF_Name>("Type", "Font");
       fontDict->SetNewFor<CPDF_Name>("Subtype", fontD.type);
       fontDict->SetNewFor<CPDF_Name>("BaseFont", fontD.baseFont);
-      CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(fontDict));
-      dwObjNum = pDict->GetObjNum();
+      pIndirectFont = m_pDocument->AddIndirectObject(std::move(fontDict));
     }
-    dictName = RealizeResource(dwObjNum, "Font");
+    dictName = RealizeResource(pIndirectFont, "Font");
     m_pObjHolder->m_FontsMap[fontD] = dictName;
   }
   *buf << "/" << PDF_NameEncode(dictName) << " " << pTextObj->GetFontSize()
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index efc5739..a6cf215 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -16,6 +16,7 @@
 
 class CPDF_Document;
 class CPDF_ImageObject;
+class CPDF_Object;
 class CPDF_PageObject;
 class CPDF_PageObjectHolder;
 class CPDF_PathObject;
@@ -37,7 +38,7 @@
   void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);
   void ProcessDefaultGraphics(std::ostringstream* buf);
   void ProcessText(std::ostringstream* buf, CPDF_TextObject* pTextObj);
-  ByteString RealizeResource(uint32_t dwResourceObjNum,
+  ByteString RealizeResource(const CPDF_Object* pResource,
                              const ByteString& bsType);
 
   UnownedPtr<CPDF_PageObjectHolder> const m_pObjHolder;
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index 5d9e029..354aa67 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -247,8 +247,7 @@
     CPDF_Dictionary* pDesc = pDoc->NewIndirect<CPDF_Dictionary>();
     pDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
     pDesc->SetNewFor<CPDF_Name>("FontName", pFont->GetBaseFont());
-    pDict->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc.get(),
-                                     pDesc->GetObjNum());
+    pDict->SetFor("FontDescriptor", pDesc->MakeReference(pDoc.get()));
 
     CPDF_Font* loadedFont = pDoc->LoadFont(pDict);
     pTextObj->m_TextState.SetFont(loadedFont);
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 8720342..a8b5936 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -238,9 +238,8 @@
           pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
       CPDF_Stream* pCTS = m_pDocument->NewIndirect<CPDF_Stream>(
           std::move(pColorTable), iPalette * 3, std::move(pNewDict));
-      pCS->AddNew<CPDF_Reference>(m_pDocument.Get(), pCTS->GetObjNum());
-      pDict->SetNewFor<CPDF_Reference>("ColorSpace", m_pDocument.Get(),
-                                       pCS->GetObjNum());
+      pCS->Add(pCTS->MakeReference(m_pDocument.Get()));
+      pDict->SetFor("ColorSpace", pCS->MakeReference(m_pDocument.Get()));
     } else {
       pDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
     }
@@ -281,8 +280,7 @@
     pMaskDict->SetNewFor<CPDF_Number>("Length", mask_size);
     CPDF_Stream* pNewStream = m_pDocument->NewIndirect<CPDF_Stream>(
         std::move(mask_buf), mask_size, std::move(pMaskDict));
-    pDict->SetNewFor<CPDF_Reference>("SMask", m_pDocument.Get(),
-                                     pNewStream->GetObjNum());
+    pDict->SetFor("SMask", pNewStream->MakeReference(m_pDocument.Get()));
   }
 
   uint8_t* src_buf = pBitmap->GetBuffer();
diff --git a/core/fpdfapi/page/cpdf_streamcontentparser.cpp b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
index 7e7c337..7562fb3 100644
--- a/core/fpdfapi/page/cpdf_streamcontentparser.cpp
+++ b/core/fpdfapi/page/cpdf_streamcontentparser.cpp
@@ -630,9 +630,8 @@
     ByteString key(word.Right(word.GetLength() - 1));
     auto pObj = m_pSyntax->ReadNextObject(false, false, 0);
     if (!key.IsEmpty()) {
-      uint32_t dwObjNum = pObj ? pObj->GetObjNum() : 0;
-      if (dwObjNum)
-        pDict->SetNewFor<CPDF_Reference>(key, m_pDocument.Get(), dwObjNum);
+      if (pObj && !pObj->IsInline())
+        pDict->SetFor(key, pObj->MakeReference(m_pDocument.Get()));
       else
         pDict->SetFor(key, std::move(pObj));
     }
diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp
index a5361fb..d53476d 100644
--- a/core/fpdfapi/parser/cpdf_array.cpp
+++ b/core/fpdfapi/parser/cpdf_array.cpp
@@ -191,7 +191,7 @@
     return;
 
   CPDF_Object* pNew = pHolder->AddIndirectObject(std::move(m_Objects[i]));
-  m_Objects[i] = pdfium::MakeUnique<CPDF_Reference>(pHolder, pNew->GetObjNum());
+  m_Objects[i] = pNew->MakeReference(pHolder);
 }
 
 CPDF_Object* CPDF_Array::SetAt(size_t i, std::unique_ptr<CPDF_Object> pObj) {
diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp
index c6127fa..071461b 100644
--- a/core/fpdfapi/parser/cpdf_dictionary.cpp
+++ b/core/fpdfapi/parser/cpdf_dictionary.cpp
@@ -224,7 +224,7 @@
     return;
 
   CPDF_Object* pObj = pHolder->AddIndirectObject(std::move(it->second));
-  it->second = pdfium::MakeUnique<CPDF_Reference>(pHolder, pObj->GetObjNum());
+  it->second = pObj->MakeReference(pHolder);
 }
 
 std::unique_ptr<CPDF_Object> CPDF_Dictionary::RemoveFor(const ByteString& key) {
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 59927bc..b163caf 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -513,7 +513,7 @@
   pPages->SetNewFor<CPDF_Name>("Type", "Pages");
   pPages->SetNewFor<CPDF_Number>("Count", 0);
   pPages->SetNewFor<CPDF_Array>("Kids");
-  m_pRootDict->SetNewFor<CPDF_Reference>("Pages", this, pPages->GetObjNum());
+  m_pRootDict->SetFor("Pages", pPages->MakeReference(this));
   m_pInfoDict = NewIndirect<CPDF_Dictionary>();
 }
 
@@ -545,9 +545,8 @@
         continue;
       }
       if (bInsert) {
-        pKidList->InsertNewAt<CPDF_Reference>(i, this, pPageDict->GetObjNum());
-        pPageDict->SetNewFor<CPDF_Reference>("Parent", this,
-                                             pPages->GetObjNum());
+        pKidList->InsertAt(i, pPageDict->MakeReference(this));
+        pPageDict->SetFor("Parent", pPages->MakeReference(this));
       } else {
         pKidList->RemoveAt(i);
       }
@@ -589,9 +588,9 @@
     CPDF_Array* pPagesList = pPages->GetArrayFor("Kids");
     if (!pPagesList)
       pPagesList = pPages->SetNewFor<CPDF_Array>("Kids");
-    pPagesList->AddNew<CPDF_Reference>(this, pPageDict->GetObjNum());
+    pPagesList->Add(pPageDict->MakeReference(this));
     pPages->SetNewFor<CPDF_Number>("Count", nPages + 1);
-    pPageDict->SetNewFor<CPDF_Reference>("Parent", this, pPages->GetObjNum());
+    pPageDict->SetFor("Parent", pPages->MakeReference(this));
     ResetTraversal();
   } else {
     std::set<CPDF_Dictionary*> stack = {pPages};
@@ -647,8 +646,7 @@
     ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]);
     pArray->AddNew<CPDF_Name>(name.IsEmpty() ? ".notdef" : name);
   }
-  pBaseDict->SetNewFor<CPDF_Reference>("Encoding", this,
-                                       pEncodingDict->GetObjNum());
+  pBaseDict->SetFor("Encoding", pEncodingDict->MakeReference(this));
   return i;
 }
 
@@ -715,7 +713,7 @@
   pCIDSysInfo->SetNewFor<CPDF_Number>("Supplement", supplement);
 
   CPDF_Array* pArray = pBaseDict->SetNewFor<CPDF_Array>("DescendantFonts");
-  pArray->AddNew<CPDF_Reference>(this, pFontDict->GetObjNum());
+  pArray->Add(pFontDict->MakeReference(this));
   return pFontDict;
 }
 
@@ -796,8 +794,7 @@
   CPDF_Dictionary* pFontDesc = ToDictionary(AddIndirectObject(
       CalculateFontDesc(this, basefont, flags, italicangle, pFont->GetAscent(),
                         pFont->GetDescent(), std::move(pBBox), nStemV)));
-  pFontDict->SetNewFor<CPDF_Reference>("FontDescriptor", this,
-                                       pFontDesc->GetObjNum());
+  pFontDict->SetFor("FontDescriptor", pFontDesc->MakeReference(this));
   return LoadFont(pBaseDict);
 }
 
@@ -889,9 +886,9 @@
       CalculateFontDesc(this, basefont, flags, italicangle, ascend, descend,
                         std::move(pBBox), pLogFont->lfWeight / 5);
   pFontDesc->SetNewFor<CPDF_Number>("CapHeight", capheight);
-  pFontDict->SetNewFor<CPDF_Reference>(
-      "FontDescriptor", this,
-      AddIndirectObject(std::move(pFontDesc))->GetObjNum());
+  pFontDict->SetFor(
+      "FontDescriptor",
+      AddIndirectObject(std::move(pFontDesc))->MakeReference(this));
   hFont = SelectObject(hDC, hFont);
   DeleteObject(hFont);
   DeleteDC(hDC);
diff --git a/core/fpdfapi/parser/cpdf_object.cpp b/core/fpdfapi/parser/cpdf_object.cpp
index 8190d34..6fedd25 100644
--- a/core/fpdfapi/parser/cpdf_object.cpp
+++ b/core/fpdfapi/parser/cpdf_object.cpp
@@ -12,6 +12,7 @@
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
 #include "core/fpdfapi/parser/cpdf_parser.h"
+#include "core/fpdfapi/parser/cpdf_reference.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
 #include "core/fxcrt/fx_string.h"
 #include "third_party/base/logging.h"
@@ -170,3 +171,12 @@
 const CPDF_String* CPDF_Object::AsString() const {
   return nullptr;
 }
+
+std::unique_ptr<CPDF_Object> CPDF_Object::MakeReference(
+    CPDF_IndirectObjectHolder* holder) const {
+  if (IsInline()) {
+    NOTREACHED();
+    return nullptr;
+  }
+  return pdfium::MakeUnique<CPDF_Reference>(holder, GetObjNum());
+}
diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h
index 21eec62..5ff028e 100644
--- a/core/fpdfapi/parser/cpdf_object.h
+++ b/core/fpdfapi/parser/cpdf_object.h
@@ -17,6 +17,7 @@
 class CPDF_Array;
 class CPDF_Boolean;
 class CPDF_Dictionary;
+class CPDF_IndirectObjectHolder;
 class CPDF_Name;
 class CPDF_Null;
 class CPDF_Number;
@@ -106,6 +107,11 @@
       bool bDirect,
       std::set<const CPDF_Object*>* pVisited) const;
 
+  // Return a reference to itself.
+  // The object must be direct (!IsInlined).
+  virtual std::unique_ptr<CPDF_Object> MakeReference(
+      CPDF_IndirectObjectHolder* holder) const;
+
  protected:
   CPDF_Object() : m_ObjNum(0), m_GenNum(0) {}
 
diff --git a/core/fpdfapi/parser/cpdf_object_unittest.cpp b/core/fpdfapi/parser/cpdf_object_unittest.cpp
index 856dd0a..78a0af7 100644
--- a/core/fpdfapi/parser/cpdf_object_unittest.cpp
+++ b/core/fpdfapi/parser/cpdf_object_unittest.cpp
@@ -393,6 +393,18 @@
   }
 }
 
+TEST_F(PDFObjectsTest, MakeReferenceGeneric) {
+  auto original_obj = pdfium::MakeUnique<CPDF_Null>();
+  original_obj->SetObjNum(42);
+  ASSERT_FALSE(original_obj->IsInline());
+
+  auto ref_obj = original_obj->MakeReference(m_ObjHolder.get());
+
+  ASSERT_TRUE(ref_obj->IsReference());
+  EXPECT_EQ(original_obj->GetObjNum(),
+            ToReference(ref_obj.get())->GetRefObjNum());
+}
+
 TEST(PDFArrayTest, GetMatrix) {
   float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
                       {1, 2, 3, 4, 5, 6},
@@ -971,3 +983,18 @@
   extracted_object = dict->RemoveFor("non_exists_object");
   EXPECT_FALSE(extracted_object);
 }
+
+TEST(PDFRefernceTest, MakeReferenceToReference) {
+  auto obj_holder = pdfium::MakeUnique<CPDF_IndirectObjectHolder>();
+  auto original_ref = pdfium::MakeUnique<CPDF_Reference>(obj_holder.get(), 42);
+  original_ref->SetObjNum(1952);
+  ASSERT_FALSE(original_ref->IsInline());
+
+  auto ref_obj = original_ref->MakeReference(obj_holder.get());
+
+  ASSERT_TRUE(ref_obj->IsReference());
+  // We do not allow reference to reference.
+  // New reference should have same RefObjNum.
+  EXPECT_EQ(original_ref->GetRefObjNum(),
+            ToReference(ref_obj.get())->GetRefObjNum());
+}
diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp
index 3f45a96..0f3b762 100644
--- a/core/fpdfapi/parser/cpdf_reference.cpp
+++ b/core/fpdfapi/parser/cpdf_reference.cpp
@@ -103,3 +103,11 @@
   return archive->WriteString(" ") && archive->WriteDWord(GetRefObjNum()) &&
          archive->WriteString(" 0 R ");
 }
+
+std::unique_ptr<CPDF_Object> CPDF_Reference::MakeReference(
+    CPDF_IndirectObjectHolder* holder) const {
+  ASSERT(holder == m_pObjList.Get());
+  // Do not allow reference to reference, just create other reference for same
+  // object.
+  return pdfium::MakeUnique<CPDF_Reference>(holder, GetRefObjNum());
+}
diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h
index 4cfb5c2..d1e0a07 100644
--- a/core/fpdfapi/parser/cpdf_reference.h
+++ b/core/fpdfapi/parser/cpdf_reference.h
@@ -34,6 +34,8 @@
   CPDF_Reference* AsReference() override;
   const CPDF_Reference* AsReference() const override;
   bool WriteTo(IFX_ArchiveStream* archive) const override;
+  std::unique_ptr<CPDF_Object> MakeReference(
+      CPDF_IndirectObjectHolder* holder) const override;
 
   CPDF_IndirectObjectHolder* GetObjList() const { return m_pObjList.Get(); }
   uint32_t GetRefObjNum() const { return m_RefObjNum; }
diff --git a/core/fpdfdoc/cpdf_interform.cpp b/core/fpdfdoc/cpdf_interform.cpp
index 2e5c175..de37709 100644
--- a/core/fpdfdoc/cpdf_interform.cpp
+++ b/core/fpdfdoc/cpdf_interform.cpp
@@ -43,8 +43,8 @@
 
   if (!pFormDict) {
     pFormDict = pDocument->NewIndirect<CPDF_Dictionary>();
-    pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument,
-                                                    pFormDict->GetObjNum());
+    pDocument->GetRoot()->SetFor("AcroForm",
+                                 pFormDict->MakeReference(pDocument));
   }
 
   ByteString csDA;
@@ -248,8 +248,7 @@
   csNameTag->Remove(' ');
   *csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4,
                                                        csNameTag->c_str());
-  pFonts->SetNewFor<CPDF_Reference>(*csNameTag, pDocument,
-                                    pFont->GetFontDict()->GetObjNum());
+  pFonts->SetFor(*csNameTag, pFont->GetFontDict()->MakeReference(pDocument));
 }
 
 CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict,
diff --git a/core/fpdfdoc/cpvt_fontmap.cpp b/core/fpdfdoc/cpvt_fontmap.cpp
index 6164062..16ce440 100644
--- a/core/fpdfdoc/cpvt_fontmap.cpp
+++ b/core/fpdfdoc/cpvt_fontmap.cpp
@@ -39,8 +39,8 @@
 
   CPDF_Dictionary* pFontList = pResDict->GetDictFor("Font");
   if (pFontList && !pFontList->KeyExist(*sSysFontAlias)) {
-    pFontList->SetNewFor<CPDF_Reference>(*sSysFontAlias, pDoc,
-                                         pPDFFont->GetFontDict()->GetObjNum());
+    pFontList->SetFor(*sSysFontAlias,
+                      pPDFFont->GetFontDict()->MakeReference(pDoc));
   }
   return pPDFFont;
 }
diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp
index cf55e95..a582feb 100644
--- a/core/fpdfdoc/cpvt_generateap.cpp
+++ b/core/fpdfdoc/cpvt_generateap.cpp
@@ -404,8 +404,7 @@
 
   auto pResourceFontDict =
       pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool());
-  pResourceFontDict->SetNewFor<CPDF_Reference>(sFontDictName, pDoc,
-                                               pFontDict->GetObjNum());
+  pResourceFontDict->SetFor(sFontDictName, pFontDict->MakeReference(pDoc));
   return pResourceFontDict;
 }
 
@@ -511,7 +510,7 @@
   if (!pAPDict)
     pAPDict = pAnnotDict->SetNewFor<CPDF_Dictionary>("AP");
 
-  pAPDict->SetNewFor<CPDF_Reference>("N", pDoc, pNormalStream->GetObjNum());
+  pAPDict->SetFor("N", pNormalStream->MakeReference(pDoc));
 
   CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
   pStreamDict->SetNewFor<CPDF_Number>("FormType", 1);
@@ -951,9 +950,8 @@
     pFontDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
     pFontDict->SetNewFor<CPDF_Name>("BaseFont", CFX_Font::kDefaultAnsiFontName);
     pFontDict->SetNewFor<CPDF_Name>("Encoding", "WinAnsiEncoding");
-    pDRFontDict->SetNewFor<CPDF_Reference>(
-        sFontName.Right(sFontName.GetLength() - 1), pDoc,
-        pFontDict->GetObjNum());
+    pDRFontDict->SetFor(sFontName.Right(sFontName.GetLength() - 1),
+                        pFontDict->MakeReference(pDoc));
   }
   CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict);
   if (!pDefFont)
@@ -1062,7 +1060,7 @@
   CPDF_Stream* pNormalStream = pAPDict->GetStreamFor("N");
   if (!pNormalStream) {
     pNormalStream = pDoc->NewIndirect<CPDF_Stream>();
-    pAPDict->SetNewFor<CPDF_Reference>("N", pDoc, pNormalStream->GetObjNum());
+    pAPDict->SetFor("N", pNormalStream->MakeReference(pDoc));
   }
   CPDF_Dictionary* pStreamDict = pNormalStream->GetDict();
   if (pStreamDict) {
@@ -1074,8 +1072,7 @@
       if (!pStreamResFontList)
         pStreamResFontList = pStreamResList->SetNewFor<CPDF_Dictionary>("Font");
       if (!pStreamResFontList->KeyExist(sFontName)) {
-        pStreamResFontList->SetNewFor<CPDF_Reference>(sFontName, pDoc,
-                                                      pFontDict->GetObjNum());
+        pStreamResFontList->SetFor(sFontName, pFontDict->MakeReference(pDoc));
       }
     } else {
       pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone());
@@ -1322,8 +1319,7 @@
               pStreamResList->SetNewFor<CPDF_Dictionary>("Font");
         }
         if (!pStreamResFontList->KeyExist(sFontName)) {
-          pStreamResFontList->SetNewFor<CPDF_Reference>(sFontName, pDoc,
-                                                        pFontDict->GetObjNum());
+          pStreamResFontList->SetFor(sFontName, pFontDict->MakeReference(pDoc));
         }
       } else {
         pStreamDict->SetFor("Resources", pFormDict->GetDictFor("DR")->Clone());
diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp
index 671ba92..d8d7dff 100644
--- a/fpdfsdk/formfiller/cba_fontmap.cpp
+++ b/fpdfsdk/formfiller/cba_fontmap.cpp
@@ -166,8 +166,7 @@
   CPDF_Stream* pStream = pAPDict->GetStreamFor(m_sAPType);
   if (!pStream) {
     pStream = m_pDocument->NewIndirect<CPDF_Stream>();
-    pAPDict->SetNewFor<CPDF_Reference>(m_sAPType, m_pDocument.Get(),
-                                       pStream->GetObjNum());
+    pAPDict->SetFor(m_sAPType, pStream->MakeReference(m_pDocument.Get()));
   }
 
   CPDF_Dictionary* pStreamDict = pStream->GetDict();
@@ -184,12 +183,12 @@
   CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictFor("Font");
   if (!pStreamResFontList) {
     pStreamResFontList = m_pDocument->NewIndirect<CPDF_Dictionary>();
-    pStreamResList->SetNewFor<CPDF_Reference>("Font", m_pDocument.Get(),
-                                              pStreamResFontList->GetObjNum());
+    pStreamResList->SetFor(
+        "Font", pStreamResFontList->MakeReference(m_pDocument.Get()));
   }
   if (!pStreamResFontList->KeyExist(sAlias)) {
-    pStreamResFontList->SetNewFor<CPDF_Reference>(
-        sAlias, m_pDocument.Get(), pFont->GetFontDict()->GetObjNum());
+    pStreamResFontList->SetFor(
+        sAlias, pFont->GetFontDict()->MakeReference(m_pDocument.Get()));
   }
 }
 
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index f2ed684..6a4faf6 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -72,15 +72,14 @@
   CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
   if (!pNames) {
     pNames = pDoc->NewIndirect<CPDF_Dictionary>();
-    pRoot->SetNewFor<CPDF_Reference>("Names", pDoc, pNames->GetObjNum());
+    pRoot->SetFor("Names", pNames->MakeReference(pDoc));
   }
 
   // Create the EmbeddedFiles dictionary if missing.
   if (!pNames->GetDictFor("EmbeddedFiles")) {
     CPDF_Dictionary* pFiles = pDoc->NewIndirect<CPDF_Dictionary>();
     pFiles->SetNewFor<CPDF_Array>("Names");
-    pNames->SetNewFor<CPDF_Reference>("EmbeddedFiles", pDoc,
-                                      pFiles->GetObjNum());
+    pNames->SetFor("EmbeddedFiles", pFiles->MakeReference(pDoc));
   }
 
   // Set up the basic entries in the filespec dictionary.
@@ -91,9 +90,7 @@
 
   // Add the new attachment name and filespec into the document's EmbeddedFiles.
   CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
-  if (!nameTree.AddValueAndName(
-          pdfium::MakeUnique<CPDF_Reference>(pDoc, pFile->GetObjNum()),
-          wsName)) {
+  if (!nameTree.AddValueAndName(pFile->MakeReference(pDoc), wsName)) {
     return nullptr;
   }
 
@@ -254,7 +251,7 @@
       std::move(stream), len, std::move(pFileStreamDict));
   CPDF_Dictionary* pEFDict =
       pFile->AsDictionary()->SetNewFor<CPDF_Dictionary>("EF");
-  pEFDict->SetNewFor<CPDF_Reference>("F", pDoc, pFileStream->GetObjNum());
+  pEFDict->SetFor("F", pFileStream->MakeReference(pDoc));
   return true;
 }
 
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 2996a50..2ead789 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -74,7 +74,7 @@
                                                static_cast<int>(size));
   }
   ByteString fontFile = font_type == FPDF_FONT_TYPE1 ? "FontFile" : "FontFile2";
-  pFontDesc->SetNewFor<CPDF_Reference>(fontFile, pDoc, pStream->GetObjNum());
+  pFontDesc->SetFor(fontFile, pStream->MakeReference(pDoc));
   return pFontDesc;
 }
 
@@ -270,12 +270,11 @@
     currentChar = nextChar;
   }
   fontDict->SetNewFor<CPDF_Number>("LastChar", static_cast<int>(currentChar));
-  fontDict->SetNewFor<CPDF_Reference>("Widths", pDoc, widthsArray->GetObjNum());
+  fontDict->SetFor("Widths", widthsArray->MakeReference(pDoc));
   CPDF_Dictionary* pFontDesc =
       LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type);
 
-  fontDict->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc,
-                                      pFontDesc->GetObjNum());
+  fontDict->SetFor("FontDescriptor", pFontDesc->MakeReference(pDoc));
   return pDoc->LoadFont(fontDict);
 }
 
@@ -311,13 +310,11 @@
   pCIDSystemInfo->SetNewFor<CPDF_Name>("Registry", "Adobe");
   pCIDSystemInfo->SetNewFor<CPDF_Name>("Ordering", "Identity");
   pCIDSystemInfo->SetNewFor<CPDF_Number>("Supplement", 0);
-  pCIDFont->SetNewFor<CPDF_Reference>("CIDSystemInfo", pDoc,
-                                      pCIDSystemInfo->GetObjNum());
+  pCIDFont->SetFor("CIDSystemInfo", pCIDSystemInfo->MakeReference(pDoc));
 
   CPDF_Dictionary* pFontDesc =
       LoadFontDesc(pDoc, name, pFont.get(), data, size, font_type);
-  pCIDFont->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc,
-                                      pFontDesc->GetObjNum());
+  pCIDFont->SetFor("FontDescriptor", pFontDesc->MakeReference(pDoc));
 
   uint32_t glyphIndex;
   uint32_t currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex);
@@ -386,15 +383,14 @@
     }
     widthsArray->Add(std::move(curWidthArray));
   }
-  pCIDFont->SetNewFor<CPDF_Reference>("W", pDoc, widthsArray->GetObjNum());
+  pCIDFont->SetFor("W", widthsArray->MakeReference(pDoc));
   // TODO(npm): Support vertical writing
 
   auto pDescendant = pdfium::MakeUnique<CPDF_Array>();
-  pDescendant->AddNew<CPDF_Reference>(pDoc, pCIDFont->GetObjNum());
+  pDescendant->Add(pCIDFont->MakeReference(pDoc));
   fontDict->SetFor("DescendantFonts", std::move(pDescendant));
   CPDF_Stream* toUnicodeStream = LoadUnicode(pDoc, to_unicode);
-  fontDict->SetNewFor<CPDF_Reference>("ToUnicode", pDoc,
-                                      toUnicodeStream->GetObjNum());
+  fontDict->SetFor("ToUnicode", toUnicodeStream->MakeReference(pDoc));
   return pDoc->LoadFont(fontDict);
 }
 
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index d35cfe3..4b9e1f8 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -169,15 +169,15 @@
   return rcRet;
 }
 
-uint32_t NewIndirectContentsStream(const ByteString& key,
-                                   CPDF_Document* pDocument) {
+CPDF_Object* NewIndirectContentsStream(const ByteString& key,
+                                       CPDF_Document* pDocument) {
   CPDF_Stream* pNewContents = pDocument->NewIndirect<CPDF_Stream>(
       nullptr, 0,
       pdfium::MakeUnique<CPDF_Dictionary>(pDocument->GetByteStringPool()));
   ByteString sStream =
       ByteString::Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
   pNewContents->SetData(sStream.raw_str(), sStream.GetLength());
-  return pNewContents->GetObjNum();
+  return pNewContents;
 }
 
 void SetPageContents(const ByteString& key,
@@ -190,9 +190,9 @@
     pContentsArray = pPage->GetArrayFor(pdfium::page_object::kContents);
     if (!pContentsArray) {
       if (!key.IsEmpty()) {
-        pPage->SetNewFor<CPDF_Reference>(
-            pdfium::page_object::kContents, pDocument,
-            NewIndirectContentsStream(key, pDocument));
+        pPage->SetFor(pdfium::page_object::kContents,
+                      NewIndirectContentsStream(key, pDocument)
+                          ->MakeReference(pDocument));
       }
       return;
     }
@@ -207,14 +207,13 @@
     sStream = sStream + sBody + "\nQ";
     pContentsStream->SetDataAndRemoveFilter(sStream.raw_str(),
                                             sStream.GetLength());
-    pContentsArray->AddNew<CPDF_Reference>(pDocument,
-                                           pContentsStream->GetObjNum());
-    pPage->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents, pDocument,
-                                     pContentsArray->GetObjNum());
+    pContentsArray->Add(pContentsStream->MakeReference(pDocument));
+    pPage->SetFor(pdfium::page_object::kContents,
+                  pContentsArray->MakeReference(pDocument));
   }
   if (!key.IsEmpty()) {
-    pContentsArray->AddNew<CPDF_Reference>(
-        pDocument, NewIndirectContentsStream(key, pDocument));
+    pContentsArray->Add(
+        NewIndirectContentsStream(key, pDocument)->MakeReference(pDocument));
   }
 }
 
@@ -290,7 +289,6 @@
       nullptr, 0,
       pdfium::MakeUnique<CPDF_Dictionary>(pDocument->GetByteStringPool()));
 
-  uint32_t dwObjNum = pNewXObject->GetObjNum();
   CPDF_Dictionary* pPageXObject = pRes->GetDictFor("XObject");
   if (!pPageXObject)
     pPageXObject = pRes->SetNewFor<CPDF_Dictionary>("XObject");
@@ -312,7 +310,7 @@
 
   CPDF_Dictionary* pNewXORes = nullptr;
   if (!key.IsEmpty()) {
-    pPageXObject->SetNewFor<CPDF_Reference>(key, pDocument, dwObjNum);
+    pPageXObject->SetFor(key, pNewXObject->MakeReference(pDocument));
     CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict();
     pNewXORes = pNewOXbjectDic->SetNewFor<CPDF_Dictionary>("Resources");
     pNewOXbjectDic->SetNewFor<CPDF_Name>("Type", "XObject");
@@ -387,8 +385,7 @@
       pXObject = pNewXORes->SetNewFor<CPDF_Dictionary>("XObject");
 
     ByteString sFormName = ByteString::Format("F%d", i);
-    pXObject->SetNewFor<CPDF_Reference>(sFormName, pDocument,
-                                        pObj->GetObjNum());
+    pXObject->SetFor(sFormName, pObj->MakeReference(pDocument));
 
     auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pNewXObject);
     pAcc->LoadAllDataFiltered();
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index c4bd51e..8bbae72 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -337,8 +337,7 @@
       pElement ? ToDictionary(pElement->GetDirect()) : nullptr;
   if (!pNewPages) {
     pNewPages = dest()->NewIndirect<CPDF_Dictionary>();
-    pNewRoot->SetNewFor<CPDF_Reference>("Pages", dest(),
-                                        pNewPages->GetObjNum());
+    pNewRoot->SetFor("Pages", pNewPages->MakeReference(dest()));
   }
 
   ByteString cbPageType = pNewPages->GetStringFor("Type", "");
@@ -347,8 +346,8 @@
 
   if (!pNewPages->GetArrayFor("Kids")) {
     pNewPages->SetNewFor<CPDF_Number>("Count", 0);
-    pNewPages->SetNewFor<CPDF_Reference>(
-        "Kids", dest(), dest()->NewIndirect<CPDF_Array>()->GetObjNum());
+    pNewPages->SetFor("Kids",
+                      dest()->NewIndirect<CPDF_Array>()->MakeReference(dest()));
   }
 
   return true;
@@ -754,8 +753,8 @@
   CPDF_Stream* pStream =
       dest()->NewIndirect<CPDF_Stream>(nullptr, 0, std::move(pDict));
   pStream->SetData(bsContent.raw_str(), bsContent.GetLength());
-  pDestPageDict->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents,
-                                           dest(), pStream->GetObjNum());
+  pDestPageDict->SetFor(pdfium::page_object::kContents,
+                        pStream->MakeReference(dest()));
 }
 
 }  // namespace
diff --git a/fpdfsdk/fpdf_save.cpp b/fpdfsdk/fpdf_save.cpp
index 6064a73..52b8726 100644
--- a/fpdfsdk/fpdf_save.cpp
+++ b/fpdfsdk/fpdf_save.cpp
@@ -138,8 +138,7 @@
         pData->InitStreamFromFile(pDsfileWrite, std::move(pDataDict));
         iLast = pArray->GetCount() - 2;
         pArray->InsertNewAt<CPDF_String>(iLast, "datasets", false);
-        pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
-                                            pData->GetObjNum());
+        pArray->InsertAt(iLast + 1, pData->MakeReference(pPDFDocument));
       }
       fileList->push_back(std::move(pDsfileWrite));
     }
@@ -164,8 +163,7 @@
         pData->InitStreamFromFile(pfileWrite, std::move(pDataDict));
         iLast = pArray->GetCount() - 2;
         pArray->InsertNewAt<CPDF_String>(iLast, "form", false);
-        pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
-                                            pData->GetObjNum());
+        pArray->InsertAt(iLast + 1, pData->MakeReference(pPDFDocument));
       }
       fileList->push_back(std::move(pfileWrite));
     }
diff --git a/fpdfsdk/fpdf_transformpage.cpp b/fpdfsdk/fpdf_transformpage.cpp
index 267b582..d20b28f 100644
--- a/fpdfsdk/fpdf_transformpage.cpp
+++ b/fpdfsdk/fpdf_transformpage.cpp
@@ -144,15 +144,15 @@
   pEndStream->SetData((const uint8_t*)" Q", 2);
 
   if (CPDF_Array* pContentArray = ToArray(pContentObj)) {
-    pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
+    pContentArray->InsertAt(0, pStream->MakeReference(pDoc));
+    pContentArray->Add(pEndStream->MakeReference(pDoc));
   } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
     CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum());
-    pPageDict->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents, pDoc,
-                                         pContentArray->GetObjNum());
+    pContentArray->Add(pStream->MakeReference(pDoc));
+    pContentArray->Add(pContentObj->MakeReference(pDoc));
+    pContentArray->Add(pEndStream->MakeReference(pDoc));
+    pPageDict->SetFor(pdfium::page_object::kContents,
+                      pContentArray->MakeReference(pDoc));
   }
 
   // Need to transform the patterns as well.
@@ -298,12 +298,12 @@
   pStream->SetData(&strClip);
 
   if (CPDF_Array* pArray = ToArray(pContentObj)) {
-    pArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum());
+    pArray->InsertAt(0, pStream->MakeReference(pDoc));
   } else if (pContentObj->IsStream() && !pContentObj->IsInline()) {
     CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>();
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum());
-    pContentArray->AddNew<CPDF_Reference>(pDoc, pContentObj->GetObjNum());
-    pPageDict->SetNewFor<CPDF_Reference>(pdfium::page_object::kContents, pDoc,
-                                         pContentArray->GetObjNum());
+    pContentArray->Add(pStream->MakeReference(pDoc));
+    pContentArray->Add(pContentObj->MakeReference(pDoc));
+    pPageDict->SetFor(pdfium::page_object::kContents,
+                      pContentArray->MakeReference(pDoc));
   }
 }
diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp
index cbe6501..01ef48a 100644
--- a/fpdfsdk/pwl/cpwl_appstream.cpp
+++ b/fpdfsdk/pwl/cpwl_appstream.cpp
@@ -1910,9 +1910,8 @@
 
   CPDF_Dictionary* pXObject =
       pStreamResList->SetNewFor<CPDF_Dictionary>("XObject");
-  pXObject->SetNewFor<CPDF_Reference>(sImageAlias,
-                                      widget_->GetPageView()->GetPDFDocument(),
-                                      pImage->GetObjNum());
+  pXObject->SetFor(sImageAlias, pImage->MakeReference(
+                                    widget_->GetPageView()->GetPDFDocument()));
 }
 
 void CPWL_AppStream::Write(const ByteString& sAPType,
@@ -1935,7 +1934,7 @@
   if (!pStream) {
     CPDF_Document* doc = widget_->GetPageView()->GetPDFDocument();
     pStream = doc->NewIndirect<CPDF_Stream>();
-    pParentDict->SetNewFor<CPDF_Reference>(sAPType, doc, pStream->GetObjNum());
+    pParentDict->SetFor(sAPType, pStream->MakeReference(doc));
   }
 
   CPDF_Dictionary* pStreamDict = pStream->GetDict();