Simplify some FPDF edit functions.

Fix an unlikely memory leak in FPDFPage_InsertObject().

BUG=pdfium:545

Review-Url: https://codereview.chromium.org/2195643002
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index 0d0dac4..0daa459 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -6,6 +6,10 @@
 
 #include "public/fpdf_edit.h"
 
+#include <algorithm>
+#include <memory>
+#include <utility>
+
 #include "core/fpdfapi/fpdf_edit/include/cpdf_pagecontentgenerator.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
@@ -37,6 +41,29 @@
 #include <ctime>
 #endif
 
+namespace {
+
+static_assert(FPDF_PAGEOBJ_TEXT == CPDF_PageObject::TEXT,
+              "FPDF_PAGEOBJ_TEXT/CPDF_PageObject::TEXT mismatch");
+static_assert(FPDF_PAGEOBJ_PATH == CPDF_PageObject::PATH,
+              "FPDF_PAGEOBJ_PATH/CPDF_PageObject::PATH mismatch");
+static_assert(FPDF_PAGEOBJ_IMAGE == CPDF_PageObject::IMAGE,
+              "FPDF_PAGEOBJ_IMAGE/CPDF_PageObject::IMAGE mismatch");
+static_assert(FPDF_PAGEOBJ_SHADING == CPDF_PageObject::SHADING,
+              "FPDF_PAGEOBJ_SHADING/CPDF_PageObject::SHADING mismatch");
+static_assert(FPDF_PAGEOBJ_FORM == CPDF_PageObject::FORM,
+              "FPDF_PAGEOBJ_FORM/CPDF_PageObject::FORM mismatch");
+
+bool IsPageObject(CPDF_Page* pPage) {
+  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type"))
+    return false;
+
+  CPDF_Object* pObject = pPage->m_pFormDict->GetObjectBy("Type")->GetDirect();
+  return pObject && !pObject->GetString().Compare("Page");
+}
+
+}  // namespace
+
 DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_CreateNewDocument() {
   CPDF_Document* pDoc = new CPDF_Document(nullptr);
   pDoc->CreateNewDoc();
@@ -79,14 +106,11 @@
   if (!pDoc)
     return nullptr;
 
-  if (page_index < 0)
-    page_index = 0;
-  if (pDoc->GetPageCount() < page_index)
-    page_index = pDoc->GetPageCount();
-
+  page_index = std::min(std::max(page_index, 0), pDoc->GetPageCount());
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(page_index);
   if (!pPageDict)
     return nullptr;
+
   CPDF_Array* pMediaBoxArray = new CPDF_Array;
   pMediaBoxArray->Add(new CPDF_Number(0));
   pMediaBoxArray->Add(new CPDF_Number(0));
@@ -111,16 +135,10 @@
 
 DLLEXPORT int STDCALL FPDFPage_GetRotation(FPDF_PAGE page) {
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      !pPage->m_pFormDict->GetObjectBy("Type")->GetDirect() ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
-    return -1;
-  }
-  CPDF_Dictionary* pDict = pPage->m_pFormDict;
-  if (!pDict)
+  if (!IsPageObject(pPage))
     return -1;
 
+  CPDF_Dictionary* pDict = pPage->m_pFormDict;
   while (pDict) {
     if (pDict->KeyExist("Rotate")) {
       CPDF_Object* pRotateObj = pDict->GetObjectBy("Rotate")->GetDirect();
@@ -137,68 +155,59 @@
 
 DLLEXPORT void STDCALL FPDFPage_InsertObject(FPDF_PAGE page,
                                              FPDF_PAGEOBJECT page_obj) {
-  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      !pPage->m_pFormDict->GetObjectBy("Type")->GetDirect() ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
-    return;
-  }
-  CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_obj;
+  CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(page_obj);
   if (!pPageObj)
     return;
 
-  pPage->GetPageObjectList()->push_back(
-      std::unique_ptr<CPDF_PageObject>(pPageObj));
+  std::unique_ptr<CPDF_PageObject> pPageObjHolder(pPageObj);
+  CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+  if (!IsPageObject(pPage))
+    return;
 
+  pPage->GetPageObjectList()->push_back(std::move(pPageObjHolder));
   switch (pPageObj->GetType()) {
-    case FPDF_PAGEOBJ_PATH: {
+    case CPDF_PageObject::TEXT: {
+      break;
+    }
+    case CPDF_PageObject::PATH: {
       CPDF_PathObject* pPathObj = pPageObj->AsPath();
       pPathObj->CalcBoundingBox();
       break;
     }
-    case FPDF_PAGEOBJ_TEXT: {
-      break;
-    }
-    case FPDF_PAGEOBJ_IMAGE: {
+    case CPDF_PageObject::IMAGE: {
       CPDF_ImageObject* pImageObj = pPageObj->AsImage();
       pImageObj->CalcBoundingBox();
       break;
     }
-    case FPDF_PAGEOBJ_SHADING: {
+    case CPDF_PageObject::SHADING: {
       CPDF_ShadingObject* pShadingObj = pPageObj->AsShading();
       pShadingObj->CalcBoundingBox();
       break;
     }
-    case FPDF_PAGEOBJ_FORM: {
+    case CPDF_PageObject::FORM: {
       CPDF_FormObject* pFormObj = pPageObj->AsForm();
       pFormObj->CalcBoundingBox();
       break;
     }
-    default:
+    default: {
+      ASSERT(false);
       break;
+    }
   }
 }
 
 DLLEXPORT int STDCALL FPDFPage_CountObject(FPDF_PAGE page) {
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      !pPage->m_pFormDict->GetObjectBy("Type")->GetDirect() ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
+  if (!IsPageObject(pPage))
     return -1;
-  }
   return pdfium::CollectionSize<int>(*pPage->GetPageObjectList());
 }
 
 DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPage_GetObject(FPDF_PAGE page,
                                                      int index) {
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
+  if (!IsPageObject(pPage))
     return nullptr;
-  }
   return pPage->GetPageObjectList()->GetPageObjectByIndex(index);
 }
 
@@ -211,8 +220,8 @@
 FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject) {
   if (!pageObject)
     return FALSE;
-  CPDF_PageObject* pPageObj = (CPDF_PageObject*)pageObject;
 
+  CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(pageObject);
   const CPDF_GeneralStateData* pGeneralState =
       pPageObj->m_GeneralState.GetObject();
   int blend_type =
@@ -228,35 +237,30 @@
   if (pGeneralState && pGeneralState->m_FillAlpha != 1.0f)
     return TRUE;
 
-  if (pPageObj->IsPath()) {
-    if (pGeneralState && pGeneralState->m_StrokeAlpha != 1.0f)
-      return TRUE;
+  if (pPageObj->IsPath() && pGeneralState &&
+      pGeneralState->m_StrokeAlpha != 1.0f) {
+    return TRUE;
   }
 
   if (pPageObj->IsForm()) {
-    CPDF_FormObject* pFormObj = pPageObj->AsForm();
-    if (pFormObj->m_pForm &&
-        (pFormObj->m_pForm->m_Transparency & PDFTRANS_ISOLATED))
-      return TRUE;
-    if (pFormObj->m_pForm &&
-        (!(pFormObj->m_pForm->m_Transparency & PDFTRANS_ISOLATED) &&
-         (pFormObj->m_pForm->m_Transparency & PDFTRANS_GROUP)))
-      return TRUE;
+    const CPDF_Form* pForm = pPageObj->AsForm()->form();
+    if (pForm) {
+      int trans = pForm->m_Transparency;
+      if ((trans & PDFTRANS_ISOLATED) || (trans & PDFTRANS_GROUP))
+        return TRUE;
+    }
   }
+
   return FALSE;
 }
 
 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page) {
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      !pPage->m_pFormDict->GetObjectBy("Type")->GetDirect() ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
+  if (!IsPageObject(pPage))
     return FALSE;
-  }
+
   CPDF_PageContentGenerator CG(pPage);
   CG.GenerateContent();
-
   return TRUE;
 }
 
@@ -267,7 +271,7 @@
                                              double d,
                                              double e,
                                              double f) {
-  CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
+  CPDF_PageObject* pPageObj = reinterpret_cast<CPDF_PageObject*>(page_object);
   if (!pPageObj)
     return;
 
@@ -275,6 +279,7 @@
                     (FX_FLOAT)e, (FX_FLOAT)f);
   pPageObj->Transform(matrix);
 }
+
 DLLEXPORT void STDCALL FPDFPage_TransformAnnots(FPDF_PAGE page,
                                                 double a,
                                                 double b,
@@ -285,6 +290,7 @@
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
   if (!pPage)
     return;
+
   CPDF_AnnotList AnnotList(pPage);
   for (size_t i = 0; i < AnnotList.Count(); ++i) {
     CPDF_Annot* pAnnot = AnnotList.GetAt(i);
@@ -310,14 +316,10 @@
 
 DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate) {
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
-  if (!pPage || !pPage->m_pFormDict || !pPage->m_pFormDict->KeyExist("Type") ||
-      !pPage->m_pFormDict->GetObjectBy("Type")->GetDirect() ||
-      pPage->m_pFormDict->GetObjectBy("Type")->GetDirect()->GetString().Compare(
-          "Page")) {
+  if (!IsPageObject(pPage))
     return;
-  }
+
   CPDF_Dictionary* pDict = pPage->m_pFormDict;
   rotate %= 4;
-
   pDict->SetAt("Rotate", new CPDF_Number(rotate * 90));
 }