Add FPDFAnnot_GetBorder() API

This is similar to FPDFAnnot_GetLine(), but a /Border key is valid for
all annotation types.

The array can have an optional 4th element, but that itself doesn't have
a fixed size, so it's not exposed by this API -- could be done by a
separate function.

Change-Id: I796c2ea17be1f039a6c6129dbde0b0a22276e19a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/77010
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 85f86e5..eee3567 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -913,6 +913,29 @@
   return true;
 }
 
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetBorder(FPDF_ANNOTATION annot,
+                    float* horizontal_radius,
+                    float* vertical_radius,
+                    float* border_width) {
+  if (!horizontal_radius || !vertical_radius || !border_width)
+    return false;
+
+  CPDF_Dictionary* annot_dict = GetAnnotDictFromFPDFAnnotation(annot);
+  if (!annot_dict)
+    return false;
+
+  CPDF_Array* border = annot_dict->GetArrayFor(pdfium::annotation::kBorder);
+  if (!border || border->size() < 3)
+    return false;
+
+  *horizontal_radius = border->GetNumberAt(0);
+  *vertical_radius = border->GetNumberAt(1);
+  *border_width = border->GetNumberAt(2);
+
+  return true;
+}
+
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot,
                                                      FPDF_BYTESTRING key) {
   CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 8a016b9..1fea030 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -3422,3 +3422,43 @@
 
   UnloadPage(page);
 }
+
+TEST_F(FPDFAnnotEmbedderTest, AnnotationBorder) {
+  ASSERT_TRUE(OpenDocument("line_annot.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+  EXPECT_EQ(2, FPDFPage_GetAnnotCount(page));
+
+  {
+    ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
+    ASSERT_TRUE(annot);
+
+    // FPDFAnnot_GetBorder() positive testing.
+    float horizontal_radius;
+    float vertical_radius;
+    float border_width;
+    ASSERT_TRUE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
+                                    &vertical_radius, &border_width));
+    EXPECT_FLOAT_EQ(0.25f, horizontal_radius);
+    EXPECT_FLOAT_EQ(0.5f, vertical_radius);
+    EXPECT_FLOAT_EQ(2.0f, border_width);
+
+    // FPDFAnnot_GetBorder() negative testing.
+    EXPECT_FALSE(FPDFAnnot_GetBorder(nullptr, nullptr, nullptr, nullptr));
+    EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), nullptr, nullptr, nullptr));
+  }
+
+  {
+    ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 1));
+    ASSERT_TRUE(annot);
+
+    // Too few elements in the border array.
+    float horizontal_radius;
+    float vertical_radius;
+    float border_width;
+    EXPECT_FALSE(FPDFAnnot_GetBorder(annot.get(), &horizontal_radius,
+                                     &vertical_radius, &border_width));
+  }
+
+  UnloadPage(page);
+}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index ff511f4..9fdbc63 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -46,6 +46,7 @@
     CHK(FPDFAnnot_CountAttachmentPoints);
     CHK(FPDFAnnot_GetAP);
     CHK(FPDFAnnot_GetAttachmentPoints);
+    CHK(FPDFAnnot_GetBorder);
     CHK(FPDFAnnot_GetColor);
     CHK(FPDFAnnot_GetFlags);
     CHK(FPDFAnnot_GetFocusableSubtypes);
diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
index 6c8a237..2b708af 100644
--- a/public/fpdf_annot.h
+++ b/public/fpdf_annot.h
@@ -453,6 +453,22 @@
                                                       FS_POINTF* end);
 
 // Experimental API.
+// Get the characteristics of the annotation's border (rounded rectangle).
+//
+//   annot  - handle to an annotation, as returned by e.g. FPDFPage_GetAnnot()
+//   horizontal_radius - horizontal corner radius, in default user space units
+//   vertical_radius - vertical corner radius, in default user space units
+//   border_width - border width, in default user space units
+//
+// Returns true if |horizontal_radius|, |vertical_radius| and |border_width| are
+// not NULL, false otherwise.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetBorder(FPDF_ANNOTATION annot,
+                    float* horizontal_radius,
+                    float* vertical_radius,
+                    float* border_width);
+
+// Experimental API.
 // Check if |annot|'s dictionary has |key| as a key.
 //
 //   annot  - handle to an annotation.
diff --git a/testing/resources/line_annot.in b/testing/resources/line_annot.in
index f8aecf2..0778169 100644
--- a/testing/resources/line_annot.in
+++ b/testing/resources/line_annot.in
@@ -29,6 +29,7 @@
   /P 3 0 R
   /C [1 0.90196 0]
   /Rect [293 530 349 542]
+  /Border [0.25 0.5 2]
 >>
 endobj
 {{object 5 0}} <<
@@ -40,6 +41,7 @@
   /P 3 0 R
   /C [1 0.90196 0]
   /Rect [293 530 349 542]
+  /Border [0.25 0.5]
 >>
 endobj
 {{xref}}
diff --git a/testing/resources/line_annot.pdf b/testing/resources/line_annot.pdf
index 0511d4c..7a7fee3 100644
--- a/testing/resources/line_annot.pdf
+++ b/testing/resources/line_annot.pdf
@@ -30,6 +30,7 @@
   /P 3 0 R
   /C [1 0.90196 0]
   /Rect [293 530 349 542]
+  /Border [0.25 0.5 2]
 >>
 endobj
 5 0 obj <<
@@ -41,6 +42,7 @@
   /P 3 0 R
   /C [1 0.90196 0]
   /Rect [293 530 349 542]
+  /Border [0.25 0.5]
 >>
 endobj
 xref
@@ -50,11 +52,11 @@
 0000000068 00000 n 
 0000000131 00000 n 
 0000000251 00000 n 
-0000000408 00000 n 
+0000000431 00000 n 
 trailer <<
   /Root 1 0 R
   /Size 6
 >>
 startxref
-558
+602
 %%EOF