Add FPDFFormObj_CountObjects() API

To find out the number of sub-objects a form object has, similar to how
FPDFPage_CountObjects() does it for page objects.

Change-Id: I7e5775dece42b74fd5b71b1d9622a1aa37bf64ac
Reviewed-on: https://pdfium-review.googlesource.com/37316
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index be872ee..e169c46 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -1573,6 +1573,20 @@
   UnloadPage(page);
 }
 
+TEST_F(FPDFEditEmbeddertest, TestFormGetObjects) {
+  EXPECT_TRUE(OpenDocument("form_object.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+  ASSERT_EQ(1, FPDFPage_CountObjects(page));
+
+  FPDF_PAGEOBJECT form = FPDFPage_GetObject(page, 0);
+  EXPECT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(form));
+  ASSERT_EQ(-1, FPDFFormObj_CountObjects(nullptr));
+  ASSERT_EQ(2, FPDFFormObj_CountObjects(form));
+
+  UnloadPage(page);
+}
+
 // Tests adding text from standard font using FPDFText_LoadStandardFont.
 TEST_F(FPDFEditEmbeddertest, AddStandardFontText2) {
   // Start with a blank page
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 8a12008..4151de5 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -751,3 +751,24 @@
   pPageObj->SetDirty(true);
   return true;
 }
+
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFFormObj_CountObjects(FPDF_PAGEOBJECT page_object) {
+  auto* pPageObj = CPDFPageObjectFromFPDFPageObject(page_object);
+  if (!pPageObj)
+    return -1;
+
+  CPDF_FormObject* pFormObject = pPageObj->AsForm();
+  if (!pFormObject)
+    return -1;
+
+  const CPDF_Form* pForm = pFormObject->form();
+  if (!pForm)
+    return -1;
+
+  const CPDF_PageObjectList* pObjectList = pForm->GetPageObjectList();
+  if (!pObjectList)
+    return -1;
+
+  return pObjectList->size();
+}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 53d5a77..c0021fc 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -126,6 +126,7 @@
 
     // fpdf_edit.h
     CHK(FPDFFont_Close);
+    CHK(FPDFFormObj_CountObjects);
     CHK(FPDFImageObj_GetBitmap);
     CHK(FPDFImageObj_GetImageDataDecoded);
     CHK(FPDFImageObj_GetImageDataRaw);
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index b85537d..e6f193a 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -1226,6 +1226,15 @@
 // Returns one of the FPDF_TEXTRENDERMODE_* flags on success, -1 on error.
 FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetTextRenderMode(FPDF_PAGEOBJECT text);
 
+// Experimental API.
+// Get number of page objects inside |form_object|.
+//
+//   form_object - handle to a form object.
+//
+// Returns the number of objects in |form_object| on success, -1 on error.
+FPDF_EXPORT int FPDF_CALLCONV
+FPDFFormObj_CountObjects(FPDF_PAGEOBJECT form_object);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif  // __cplusplus
diff --git a/testing/resources/form_object.in b/testing/resources/form_object.in
new file mode 100644
index 0000000..9d196ba
--- /dev/null
+++ b/testing/resources/form_object.in
@@ -0,0 +1,80 @@
+{{header}}
+{{object 1 0}} <<
+/FormType 1
+/Subtype /Form
+/Resources
+<<
+/Font
+<<
+/F1 2 0 R
+>>
+>>
+/Type /XObject
+/BBox [0 0 612 446]
+/Length 0
+>>
+stream
+  BT
+  /F1 24 Tf
+  1 0 0 1 260 254 Tm
+  (Hello)Tj
+  ET
+  BT
+  /F1 24 Tf
+  1 0 0 1 260 204 Tm
+  (World)Tj
+  ET
+
+endstream
+endobj
+{{object 3 0}} <<
+/ProcSet [/PDF]
+/XObject
+<<
+/Im1 1 0 R
+>>
+>>
+endobj
+{{object 4 0}} <<
+/Resources 3 0 R
+/Parent 5 0 R
+/Contents 6 0 R
+/Type /Page
+/MediaBox [0 0 62 69]
+>>
+endobj
+{{object 6 0}} <<
+/Length 0
+>>
+stream
+q
+1 0 0 1 -260 -203 cm
+/Im1 Do
+Q
+endstream
+endobj
+{{object 5 0}} <<
+/Kids [4 0 R]
+/Type /Pages
+/Count 1
+>>
+endobj
+{{object 2 0}} <<
+/Subtype /Type1
+/Name /F1
+/Type /Font
+/BaseFont /Helvetica
+>>
+endobj
+{{object 7 0}} <<
+/Type /Catalog
+/Pages 5 0 R
+>>
+endobj
+{{xref}}
+trailer <<
+/Root 7 0 R
+/Size 8
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/form_object.pdf b/testing/resources/form_object.pdf
new file mode 100644
index 0000000..543f0bd
--- /dev/null
+++ b/testing/resources/form_object.pdf
@@ -0,0 +1,91 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+/FormType 1
+/Subtype /Form
+/Resources
+<<
+/Font
+<<
+/F1 2 0 R
+>>
+>>
+/Type /XObject
+/BBox [0 0 612 446]
+/Length 0
+>>
+stream
+  BT
+  /F1 24 Tf
+  1 0 0 1 260 254 Tm
+  (Hello)Tj
+  ET
+  BT
+  /F1 24 Tf
+  1 0 0 1 260 204 Tm
+  (World)Tj
+  ET
+
+endstream
+endobj
+3 0 obj <<
+/ProcSet [/PDF]
+/XObject
+<<
+/Im1 1 0 R
+>>
+>>
+endobj
+4 0 obj <<
+/Resources 3 0 R
+/Parent 5 0 R
+/Contents 6 0 R
+/Type /Page
+/MediaBox [0 0 62 69]
+>>
+endobj
+6 0 obj <<
+/Length 0
+>>
+stream
+q
+1 0 0 1 -260 -203 cm
+/Im1 Do
+Q
+endstream
+endobj
+5 0 obj <<
+/Kids [4 0 R]
+/Type /Pages
+/Count 1
+>>
+endobj
+2 0 obj <<
+/Subtype /Type1
+/Name /F1
+/Type /Font
+/BaseFont /Helvetica
+>>
+endobj
+7 0 obj <<
+/Type /Catalog
+/Pages 5 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f 
+0000000015 00000 n 
+0000000578 00000 n 
+0000000275 00000 n 
+0000000338 00000 n 
+0000000521 00000 n 
+0000000440 00000 n 
+0000000658 00000 n 
+trailer <<
+/Root 7 0 R
+/Size 8
+>>
+startxref
+707
+%%EOF