Add FPDFAnnot_GetFontColor API

This is similar to FPDFAnnot_GetFontSize() and allows getting the
font/text color of an annotation widget.

Change-Id: I7ec83a5eef8277073154b14288e271b0fed0ba59
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/120750
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Miklos V <miklos.vajna@collabora.com>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
index 8cae36e..b2e1582 100644
--- a/fpdfsdk/fpdf_annot.cpp
+++ b/fpdfsdk/fpdf_annot.cpp
@@ -1373,6 +1373,32 @@
   return true;
 }
 
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetFontColor(FPDF_FORMHANDLE hHandle,
+                       FPDF_ANNOTATION annot,
+                       unsigned int* R,
+                       unsigned int* G,
+                       unsigned int* B) {
+  if (!R || !G || !B) {
+    return false;
+  }
+
+  const CPDFSDK_Widget* widget = GetWidgetOfTypes(hHandle, annot, {});
+  if (!widget) {
+    return false;
+  }
+
+  std::optional<FX_COLORREF> text_color = widget->GetTextColor();
+  if (!text_color) {
+    return false;
+  }
+
+  *R = FXSYS_GetRValue(*text_color);
+  *G = FXSYS_GetGValue(*text_color);
+  *B = FXSYS_GetBValue(*text_color);
+  return true;
+}
+
 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_IsChecked(FPDF_FORMHANDLE hHandle,
                                                         FPDF_ANNOTATION annot) {
   const CPDFSDK_Widget* pWidget =
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 4344365..3c91b5f 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -2800,6 +2800,43 @@
   UnloadPage(page);
 }
 
+TEST_F(FPDFAnnotEmbedderTest, GetFontColor) {
+  // Open a file with textfield annotations and load its first page.
+  ASSERT_TRUE(OpenDocument("text_form_color.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+
+  {
+    // Obtain the first annotation, a text field with orange color.
+    ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, 0));
+    ASSERT_TRUE(annot);
+
+    // Negative testing.
+    unsigned int R;
+    unsigned int G;
+    unsigned int B;
+    ASSERT_FALSE(
+        FPDFAnnot_GetFontColor(nullptr, nullptr, nullptr, nullptr, nullptr));
+    ASSERT_FALSE(FPDFAnnot_GetFontColor(form_handle(), nullptr, nullptr,
+                                        nullptr, nullptr));
+    ASSERT_FALSE(FPDFAnnot_GetFontColor(form_handle(), annot.get(), nullptr,
+                                        nullptr, nullptr));
+    ASSERT_FALSE(FPDFAnnot_GetFontColor(form_handle(), annot.get(), &R, nullptr,
+                                        nullptr));
+    ASSERT_FALSE(
+        FPDFAnnot_GetFontColor(form_handle(), annot.get(), &R, &G, nullptr));
+
+    // Positive testing.
+    ASSERT_TRUE(FPDFAnnot_GetFontColor(form_handle(), annot.get(), &R, &G, &B));
+    // Make sure it's #ff8000, i.e. orange.
+    EXPECT_EQ(0xffU, R);
+    EXPECT_EQ(0x80U, G);
+    EXPECT_EQ(0x00U, B);
+  }
+
+  UnloadPage(page);
+}
+
 TEST_F(FPDFAnnotEmbedderTest, IsCheckedCheckbox) {
   // Open a file with checkbox and radiobuttons widget annotations and load its
   // first page.
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index 5c275f5..7acc286 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -53,6 +53,7 @@
     CHK(FPDFAnnot_GetFlags);
     CHK(FPDFAnnot_GetFocusableSubtypes);
     CHK(FPDFAnnot_GetFocusableSubtypesCount);
+    CHK(FPDFAnnot_GetFontColor);
     CHK(FPDFAnnot_GetFontSize);
     CHK(FPDFAnnot_GetFormAdditionalActionJavaScript);
     CHK(FPDFAnnot_GetFormControlCount);
diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
index 337da58..ef30d9a 100644
--- a/public/fpdf_annot.h
+++ b/public/fpdf_annot.h
@@ -846,6 +846,23 @@
                       float* value);
 
 // Experimental API.
+// Get the RGB value of the font color for an |annot| with variable text.
+//
+//   hHandle  - handle to the form fill module, returned by
+//              FPDFDOC_InitFormFillEnvironment.
+//   annot    - handle to an annotation.
+//   R, G, B  - buffer to hold the RGB value of the color. Ranges from 0 to 255.
+//
+// Returns true if the font color was set, false on error or if the font
+// color was not provided.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+FPDFAnnot_GetFontColor(FPDF_FORMHANDLE hHandle,
+                       FPDF_ANNOTATION annot,
+                       unsigned int* R,
+                       unsigned int* G,
+                       unsigned int* B);
+
+// Experimental API.
 // Determine if |annot| is a form widget that is checked. Intended for use with
 // checkbox and radio button widgets.
 //
diff --git a/testing/resources/text_form_color.in b/testing/resources/text_form_color.in
new file mode 100644
index 0000000..1de5700
--- /dev/null
+++ b/testing/resources/text_form_color.in
@@ -0,0 +1,49 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm <<
+    /Fields [4 0 R]
+    /DR 5 0 R
+  >>
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}}
+<<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources 5 0 R
+  /MediaBox [0 0 300 300]
+  /Annots [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+  /Type /Annot
+  /FT /Tx
+  /T (Text Box)
+  /DA (1 0.5 0 rg /F1 12 Tf)
+  /Rect [100 100 200 130]
+  /Subtype /Widget
+  /V (Mountain Lion)
+>>
+endobj
+{{object 5 0}} <<
+  /Font <<
+    /F1 <<
+      /Type /Font
+      /Subtype /Type1
+      /BaseFont /Helvetica
+    >>
+  >>
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/text_form_color.pdf b/testing/resources/text_form_color.pdf
new file mode 100644
index 0000000..dc714915
--- /dev/null
+++ b/testing/resources/text_form_color.pdf
@@ -0,0 +1,61 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm <<
+    /Fields [4 0 R]
+    /DR 5 0 R
+  >>
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+3 0 obj
+<<
+  /Type /Page
+  /Parent 2 0 R
+  /Resources 5 0 R
+  /MediaBox [0 0 300 300]
+  /Annots [4 0 R]
+>>
+endobj
+4 0 obj <<
+  /Type /Annot
+  /FT /Tx
+  /T (Text Box)
+  /DA (1 0.5 0 rg /F1 12 Tf)
+  /Rect [100 100 200 130]
+  /Subtype /Widget
+  /V (Mountain Lion)
+>>
+endobj
+5 0 obj <<
+  /Font <<
+    /F1 <<
+      /Type /Font
+      /Subtype /Type1
+      /BaseFont /Helvetica
+    >>
+  >>
+>>
+endobj
+xref
+0 6
+0000000000 65535 f 
+0000000015 00000 n 
+0000000122 00000 n 
+0000000185 00000 n 
+0000000299 00000 n 
+0000000456 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 6
+>>
+startxref
+578
+%%EOF