Fix FPDFEditEmbedderTest.ModifyFormObject.

Implement CPDF_PageContentGenerator::ProcessForm(), so the modified form
object in the test gets written out to the saved PDF properly.

Change-Id: Id49388b5ebaa05a0dc8fdf84f9fbe5d0cdada5e3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/82453
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 2f8f6c5..c856d06 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -19,6 +19,8 @@
 #include "core/fpdfapi/font/cpdf_type1font.h"
 #include "core/fpdfapi/page/cpdf_contentmarks.h"
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
+#include "core/fpdfapi/page/cpdf_form.h"
+#include "core/fpdfapi/page/cpdf_formobject.h"
 #include "core/fpdfapi/page/cpdf_image.h"
 #include "core/fpdfapi/page/cpdf_imageobject.h"
 #include "core/fpdfapi/page/cpdf_page.h"
@@ -289,6 +291,8 @@
                                                   CPDF_PageObject* pPageObj) {
   if (CPDF_ImageObject* pImageObject = pPageObj->AsImage())
     ProcessImage(buf, pImageObject);
+  else if (CPDF_FormObject* pFormObj = pPageObj->AsForm())
+    ProcessForm(buf, pFormObj);
   else if (CPDF_PathObject* pPathObj = pPageObj->AsPath())
     ProcessPath(buf, pPathObj);
   else if (CPDF_TextObject* pTextObj = pPageObj->AsText())
@@ -326,6 +330,23 @@
   *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
 }
 
+void CPDF_PageContentGenerator::ProcessForm(std::ostringstream* buf,
+                                            CPDF_FormObject* pFormObj) {
+  if ((pFormObj->form_matrix().a == 0 && pFormObj->form_matrix().b == 0) ||
+      (pFormObj->form_matrix().c == 0 && pFormObj->form_matrix().d == 0)) {
+    return;
+  }
+
+  const CPDF_Stream* pStream = pFormObj->form()->GetStream();
+  if (!pStream)
+    return;
+
+  *buf << "q\n" << pFormObj->form_matrix() << " cm ";
+
+  ByteString name = RealizeResource(pStream, "XObject");
+  *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
+}
+
 // Processing path construction with operators from Table 4.9 of PDF spec 1.7:
 // "re" appends a rectangle (here, used only if the whole path is a rectangle)
 // "m" moves current point to the given coordinates
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index ac9fd8a..f1133b3 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -17,6 +17,7 @@
 
 class CPDF_ContentMarks;
 class CPDF_Document;
+class CPDF_FormObject;
 class CPDF_ImageObject;
 class CPDF_Object;
 class CPDF_PageObject;
@@ -39,6 +40,7 @@
   void ProcessPageObject(std::ostringstream* buf, CPDF_PageObject* pPageObj);
   void ProcessPathPoints(std::ostringstream* buf, CPDF_Path* pPath);
   void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj);
+  void ProcessForm(std::ostringstream* buf, CPDF_FormObject* pFormObj);
   void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj);
   void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);
   void ProcessDefaultGraphics(std::ostringstream* buf);
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 311c2de..6077395 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -2562,10 +2562,8 @@
     CompareBitmap(bitmap.get(), 62, 69, kNewChecksum);
   }
 
-  // TODO(thestig): This renders blank, but should not.
-  const char kBlankChecksum[] = "0617d6a83d3a8c0eeedcfd6e5b98f994";
   EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
-  VerifySavedDocument(62, 69, kBlankChecksum);
+  VerifySavedDocument(62, 69, kNewChecksum);
 
   UnloadPage(page);
 }