Make SharedCopyOnWrite() invoke class-specific Clone() method.

Underpinnings for use of SharedCopyOnWrite() with classes that
are subclassed so that it may someday replace the cumbersome
CPDF_CountedObject<> mechanism. This is essentialy the "virtual
copy constructor" pattern implemented as a Clone() method.

No functional change.

Change-Id: I8f583fc9f541c27736dfb963a317670151f3ff2a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/56712
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_clippath.cpp b/core/fpdfapi/page/cpdf_clippath.cpp
index 220e7f8..c04fafa 100644
--- a/core/fpdfapi/page/cpdf_clippath.cpp
+++ b/core/fpdfapi/page/cpdf_clippath.cpp
@@ -113,7 +113,7 @@
   }
 }
 
-CPDF_ClipPath::PathData::PathData() {}
+CPDF_ClipPath::PathData::PathData() = default;
 
 CPDF_ClipPath::PathData::PathData(const PathData& that) {
   m_PathAndTypeList = that.m_PathAndTypeList;
@@ -125,4 +125,8 @@
   }
 }
 
-CPDF_ClipPath::PathData::~PathData() {}
+CPDF_ClipPath::PathData::~PathData() = default;
+
+RetainPtr<CPDF_ClipPath::PathData> CPDF_ClipPath::PathData::Clone() const {
+  return pdfium::MakeRetain<CPDF_ClipPath::PathData>(*this);
+}
diff --git a/core/fpdfapi/page/cpdf_clippath.h b/core/fpdfapi/page/cpdf_clippath.h
index f8d09da..6db7b3a 100644
--- a/core/fpdfapi/page/cpdf_clippath.h
+++ b/core/fpdfapi/page/cpdf_clippath.h
@@ -49,6 +49,8 @@
     template <typename T, typename... Args>
     friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+    RetainPtr<PathData> Clone() const;
+
     using PathAndTypeData = std::pair<CPDF_Path, uint8_t>;
 
     std::vector<PathAndTypeData> m_PathAndTypeList;
diff --git a/core/fpdfapi/page/cpdf_colorstate.cpp b/core/fpdfapi/page/cpdf_colorstate.cpp
index 41269fa..706e5c9 100644
--- a/core/fpdfapi/page/cpdf_colorstate.cpp
+++ b/core/fpdfapi/page/cpdf_colorstate.cpp
@@ -154,3 +154,8 @@
   m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
   m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY));
 }
+
+RetainPtr<CPDF_ColorState::ColorData> CPDF_ColorState::ColorData::Clone()
+    const {
+  return pdfium::MakeRetain<CPDF_ColorState::ColorData>(*this);
+}
diff --git a/core/fpdfapi/page/cpdf_colorstate.h b/core/fpdfapi/page/cpdf_colorstate.h
index 3b7c152..43244cc 100644
--- a/core/fpdfapi/page/cpdf_colorstate.h
+++ b/core/fpdfapi/page/cpdf_colorstate.h
@@ -58,6 +58,8 @@
     template <typename T, typename... Args>
     friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+    RetainPtr<ColorData> Clone() const;
+
     void SetDefault();
 
     FX_COLORREF m_FillColorRef = 0;
diff --git a/core/fpdfapi/page/cpdf_generalstate.cpp b/core/fpdfapi/page/cpdf_generalstate.cpp
index 8d3bb7e..4549696 100644
--- a/core/fpdfapi/page/cpdf_generalstate.cpp
+++ b/core/fpdfapi/page/cpdf_generalstate.cpp
@@ -301,3 +301,8 @@
     }
   }
 }
+
+RetainPtr<CPDF_GeneralState::StateData> CPDF_GeneralState::StateData::Clone()
+    const {
+  return pdfium::MakeRetain<CPDF_GeneralState::StateData>(*this);
+}
diff --git a/core/fpdfapi/page/cpdf_generalstate.h b/core/fpdfapi/page/cpdf_generalstate.h
index 20b8679..fb4bb7f 100644
--- a/core/fpdfapi/page/cpdf_generalstate.h
+++ b/core/fpdfapi/page/cpdf_generalstate.h
@@ -83,6 +83,8 @@
     template <typename T, typename... Args>
     friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+    RetainPtr<StateData> Clone() const;
+
     ByteString m_BlendMode = pdfium::transparency::kNormal;
     BlendMode m_BlendType = BlendMode::kNormal;
     RetainPtr<CPDF_Object> m_pSoftMask;
diff --git a/core/fpdfapi/page/cpdf_path.cpp b/core/fpdfapi/page/cpdf_path.cpp
index b23c5dd..de5656d 100644
--- a/core/fpdfapi/page/cpdf_path.cpp
+++ b/core/fpdfapi/page/cpdf_path.cpp
@@ -6,11 +6,11 @@
 
 #include "core/fpdfapi/page/cpdf_path.h"
 
-CPDF_Path::CPDF_Path() {}
+CPDF_Path::CPDF_Path() = default;
 
 CPDF_Path::CPDF_Path(const CPDF_Path& that) : m_Ref(that.m_Ref) {}
 
-CPDF_Path::~CPDF_Path() {}
+CPDF_Path::~CPDF_Path() = default;
 
 const std::vector<FX_PATHPOINT>& CPDF_Path::GetPoints() const {
   return m_Ref.GetObject()->GetPoints();
diff --git a/core/fpdfapi/page/cpdf_textstate.cpp b/core/fpdfapi/page/cpdf_textstate.cpp
index 2810659..a72594c 100644
--- a/core/fpdfapi/page/cpdf_textstate.cpp
+++ b/core/fpdfapi/page/cpdf_textstate.cpp
@@ -10,8 +10,9 @@
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
 
-CPDF_TextState::CPDF_TextState() {}
-CPDF_TextState::~CPDF_TextState() {}
+CPDF_TextState::CPDF_TextState() = default;
+
+CPDF_TextState::~CPDF_TextState() = default;
 
 void CPDF_TextState::Emplace() {
   m_Ref.Emplace();
@@ -125,6 +126,10 @@
   ReleaseFont();
 }
 
+RetainPtr<CPDF_TextState::TextData> CPDF_TextState::TextData::Clone() const {
+  return pdfium::MakeRetain<CPDF_TextState::TextData>(*this);
+}
+
 void CPDF_TextState::TextData::SetFont(CPDF_Font* pFont) {
   ReleaseFont();
   m_pDocument = pFont ? pFont->GetDocument() : nullptr;
diff --git a/core/fpdfapi/page/cpdf_textstate.h b/core/fpdfapi/page/cpdf_textstate.h
index 0c914a6..c1c50ea 100644
--- a/core/fpdfapi/page/cpdf_textstate.h
+++ b/core/fpdfapi/page/cpdf_textstate.h
@@ -64,6 +64,8 @@
     template <typename T, typename... Args>
     friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+    RetainPtr<TextData> Clone() const;
+
     void SetFont(CPDF_Font* pFont);
     float GetFontSizeV() const;
     float GetFontSizeH() const;
diff --git a/core/fxcrt/shared_copy_on_write.h b/core/fxcrt/shared_copy_on_write.h
index b457746..a672ddf 100644
--- a/core/fxcrt/shared_copy_on_write.h
+++ b/core/fxcrt/shared_copy_on_write.h
@@ -12,8 +12,11 @@
 
 namespace fxcrt {
 
-// A shared object with Copy on Write semantics that makes it appear as
-// if each one were independent.
+// A shared pointer to an object with Copy on Write semantics that makes it
+// appear as if all instances were independent. |ObjClass| must implement the
+// requirements of |Retainable| from retain_ptr.h, and must also provide a
+// Clone() method. Often this will just call MakeRetain<>(*this) but will need
+// to be virtual if |ObjClass| is subclassed.
 template <class ObjClass>
 class SharedCopyOnWrite {
  public:
@@ -42,7 +45,7 @@
     if (!m_pObject)
       return Emplace(params...);
     if (!m_pObject->HasOneRef())
-      m_pObject = pdfium::MakeRetain<ObjClass>(*m_pObject);
+      m_pObject = m_pObject->Clone();
     return m_pObject.Get();
   }
 
diff --git a/core/fxcrt/shared_copy_on_write_unittest.cpp b/core/fxcrt/shared_copy_on_write_unittest.cpp
index 6764c69..f579358 100644
--- a/core/fxcrt/shared_copy_on_write_unittest.cpp
+++ b/core/fxcrt/shared_copy_on_write_unittest.cpp
@@ -40,6 +40,8 @@
   }
   ~Object() override { observer_->OnDestruct(name_); }
 
+  RetainPtr<Object> Clone() const { return pdfium::MakeRetain<Object>(*this); }
+
  private:
   std::string name_;
   Observer* observer_;
diff --git a/core/fxge/cfx_graphstatedata.cpp b/core/fxge/cfx_graphstatedata.cpp
index 495692c..43f6254 100644
--- a/core/fxge/cfx_graphstatedata.cpp
+++ b/core/fxge/cfx_graphstatedata.cpp
@@ -32,3 +32,8 @@
     : CFX_GraphStateData(src) {}
 
 CFX_RetainableGraphStateData::~CFX_RetainableGraphStateData() = default;
+
+RetainPtr<CFX_RetainableGraphStateData> CFX_RetainableGraphStateData::Clone()
+    const {
+  return pdfium::MakeRetain<CFX_RetainableGraphStateData>(*this);
+}
diff --git a/core/fxge/cfx_graphstatedata.h b/core/fxge/cfx_graphstatedata.h
index 4005ce7..b49d0cb 100644
--- a/core/fxge/cfx_graphstatedata.h
+++ b/core/fxge/cfx_graphstatedata.h
@@ -48,6 +48,8 @@
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+  RetainPtr<CFX_RetainableGraphStateData> Clone() const;
+
  private:
   CFX_RetainableGraphStateData();
   CFX_RetainableGraphStateData(const CFX_RetainableGraphStateData& src);
diff --git a/core/fxge/cfx_pathdata.cpp b/core/fxge/cfx_pathdata.cpp
index 1735dc7..4481a0d 100644
--- a/core/fxge/cfx_pathdata.cpp
+++ b/core/fxge/cfx_pathdata.cpp
@@ -509,3 +509,7 @@
     : CFX_PathData(src) {}
 
 CFX_RetainablePathData::~CFX_RetainablePathData() = default;
+
+RetainPtr<CFX_RetainablePathData> CFX_RetainablePathData::Clone() const {
+  return pdfium::MakeRetain<CFX_RetainablePathData>(*this);
+}
diff --git a/core/fxge/cfx_pathdata.h b/core/fxge/cfx_pathdata.h
index fcbcabf..3f176be 100644
--- a/core/fxge/cfx_pathdata.h
+++ b/core/fxge/cfx_pathdata.h
@@ -77,6 +77,8 @@
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
+  RetainPtr<CFX_RetainablePathData> Clone() const;
+
  private:
   CFX_RetainablePathData();
   CFX_RetainablePathData(const CFX_RetainablePathData& src);