Add a test case for FPDFAnnot_SetBorder() to test rendering.

The existing test case that exercises FPDFAnnot_SetBorder() cannot
render the line annotations in its test PDF. Rather than waiting for
that issue to get resolved, just leave the existing test case alone and
write a second test that uses a different annotation type which is known
to have support for borders.

Add a new square annotation to annots.pdf, and use that in a new test
case to make sure FPDFAnnot_SetBorder() calls reflect in the rendered
in-memory PDF and in the saved PDF. With only the new test by itself,
it fails, which shows FPDFAnnot_SetBorder() does not work properly.
To make the test pass, change FPDFAnnot_SetBorder() to remove appearance
streams.

Change-Id: I0f34832c545f8d29350542bb57ab1de5f14b39f4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/79533
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 8545459..d68983c 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -933,6 +933,10 @@
   if (!annot_dict)
     return false;
 
+  // Remove the appearance stream. Otherwise PDF viewers will render that and
+  // not use the border values.
+  annot_dict->RemoveFor(pdfium::annotation::kAP);
+
   CPDF_Array* border =
       annot_dict->SetNewFor<CPDF_Array>(pdfium::annotation::kBorder);
   border->AppendNew<CPDF_Number>(horizontal_radius);
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index c5fef24..987605c 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -3565,3 +3565,59 @@
 
   UnloadPage(page);
 }
+
+// Due to https://crbug.com/pdfium/570, the AnnotationBorder test above cannot
+// actually render the line annotations inside line_annot.pdf. For now, use a
+// square annotation in annots.pdf for testing.
+TEST_F(FPDFAnnotEmbedderTest, AnnotationBorderRendering) {
+  ASSERT_TRUE(OpenDocument("annots.pdf"));
+  FPDF_PAGE page = LoadPage(1);
+  ASSERT_TRUE(page);
+  EXPECT_EQ(3, FPDFPage_GetAnnotCount(page));
+
+#if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
+  constexpr char kOriginalChecksum[] = "bc9ba381d6d46ff93ed0b5288b763b60";
+  constexpr char kModifiedChecksum[] = "0f3e10336f67cb6a8731a06d26d01e50";
+#elif defined(OS_WIN)
+  constexpr char kOriginalChecksum[] = "f9fcab6ac610ee2347c4eba6be86a90c";
+  constexpr char kModifiedChecksum[] = "e0e9ad5b67ef84288d446861265898b3";
+#elif defined(OS_APPLE)
+  constexpr char kOriginalChecksum[] = "1839f5df5fb4fae10cf3793568e73ede";
+  constexpr char kModifiedChecksum[] = "abd4f5d1c3b8d8cfc572b389e589da5a";
+#else
+  constexpr char kOriginalChecksum[] = "ccf6667b34ec2452bea0b5f1a0194191";
+  constexpr char kModifiedChecksum[] = "1bbdb473d0757843e82053b0bd3298bc";
+#endif
+
+  {
+    ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 2));
+    ASSERT_TRUE(annot);
+    EXPECT_EQ(FPDF_ANNOT_SQUARE, FPDFAnnot_GetSubtype(annot.get()));
+
+    {
+      ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
+      CompareBitmap(bitmap.get(), 612, 792, kOriginalChecksum);
+    }
+
+    EXPECT_TRUE(FPDFAnnot_SetBorder(annot.get(), /*horizontal_radius=*/2.0f,
+                                    /*vertical_radius=*/3.5f,
+                                    /*border_width=*/4.0f));
+
+    {
+      ScopedFPDFBitmap bitmap = RenderLoadedPageWithFlags(page, FPDF_ANNOT);
+      CompareBitmap(bitmap.get(), 612, 792, kModifiedChecksum);
+    }
+  }
+
+  // Save the document and close the page.
+  EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+  UnloadPage(page);
+
+  ASSERT_TRUE(OpenSavedDocument());
+  page = LoadSavedPage(1);
+  ASSERT_TRUE(page);
+  VerifySavedRendering(page, 612, 792, kModifiedChecksum);
+
+  CloseSavedPage(page);
+  CloseSavedDocument();
+}
diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
index 04e411a..149fbf1 100644
--- a/public/fpdf_annot.h
+++ b/public/fpdf_annot.h
@@ -471,7 +471,10 @@
 //   vertical_radius    - vertical corner radius, in default user space units
 //   border_width       - border width, in default user space units
 //
-// Returns true if |annot| is valid, false otherwise.
+// Returns true if setting the border for |annot| succeeds, false otherwise.
+//
+// If |annot| contains an appearance stream that overrides the border values,
+// then the appearance stream will be removed on success.
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetBorder(FPDF_ANNOTATION annot,
                                                         float horizontal_radius,
                                                         float vertical_radius,
diff --git a/testing/resources/annots.in b/testing/resources/annots.in
index c68bd78..cf575f5 100644
--- a/testing/resources/annots.in
+++ b/testing/resources/annots.in
@@ -41,7 +41,7 @@
   /Type /Page
   /Parent 2 0 R
   /Contents 6 0 R
-  /Annots [15 0 R 16 0 R]
+  /Annots [15 0 R 16 0 R 26 0 R]
 >>
 endobj
 {{object 5 0}} <<
@@ -346,6 +346,16 @@
   /BM /Multiply
 >>
 endobj
+{{object 26 0}} <<
+  /Type /Annot
+  /Subtype /Square
+  /Border [0 0 2]
+  /C [1 0 0]
+  /F 4
+  /P 3 0 R
+  /Rect [50 100 60 120]
+>>
+endobj
 {{xref}}
 {{trailer}}
 {{startxref}}
diff --git a/testing/resources/annots.pdf b/testing/resources/annots.pdf
index b514c7d..745346c 100644
--- a/testing/resources/annots.pdf
+++ b/testing/resources/annots.pdf
@@ -42,7 +42,7 @@
   /Type /Page
   /Parent 2 0 R
   /Contents 6 0 R
-  /Annots [15 0 R 16 0 R]
+  /Annots [15 0 R 16 0 R 26 0 R]
 >>
 endobj
 5 0 obj <<
@@ -347,38 +347,49 @@
   /BM /Multiply
 >>
 endobj
+26 0 obj <<
+  /Type /Annot
+  /Subtype /Square
+  /Border [0 0 2]
+  /C [1 0 0]
+  /F 4
+  /P 3 0 R
+  /Rect [50 100 60 120]
+>>
+endobj
 xref
-0 26
+0 27
 0000000000 65535 f 
 0000000015 00000 n 
 0000000169 00000 n 
 0000000439 00000 n 
 0000000583 00000 n 
-0000000678 00000 n 
-0000001216 00000 n 
-0000001453 00000 n 
-0000001531 00000 n 
-0000001607 00000 n 
-0000001857 00000 n 
-0000002080 00000 n 
-0000002330 00000 n 
-0000002550 00000 n 
-0000002801 00000 n 
-0000003024 00000 n 
-0000003164 00000 n 
-0000003304 00000 n 
-0000003551 00000 n 
-0000003835 00000 n 
-0000004052 00000 n 
-0000004279 00000 n 
-0000004377 00000 n 
-0000004652 00000 n 
-0000004842 00000 n 
-0000004913 00000 n 
+0000000685 00000 n 
+0000001223 00000 n 
+0000001460 00000 n 
+0000001538 00000 n 
+0000001614 00000 n 
+0000001864 00000 n 
+0000002087 00000 n 
+0000002337 00000 n 
+0000002557 00000 n 
+0000002808 00000 n 
+0000003031 00000 n 
+0000003171 00000 n 
+0000003311 00000 n 
+0000003558 00000 n 
+0000003842 00000 n 
+0000004059 00000 n 
+0000004286 00000 n 
+0000004384 00000 n 
+0000004659 00000 n 
+0000004849 00000 n 
+0000004920 00000 n 
+0000005006 00000 n 
 trailer <<
   /Root 1 0 R
-  /Size 26
+  /Size 27
 >>
 startxref
-4999
+5135
 %%EOF