external/pdfium/UnpackedTarball_pdfium.mk |    2 
 external/pdfium/annot.patch.1             |   65 ++++++++++++++++++++++++++++++
 include/vcl/filter/PDFiumLibrary.hxx      |    1 
 sw/qa/core/text/itrform2.cxx              |   34 +++++++++++++++
 sw/source/core/text/itrform2.cxx          |    4 +
 vcl/source/pdf/PDFiumLibrary.cxx          |   13 ++++++
 6 files changed, 119 insertions(+)

New commits:
commit 0f165b7f2f03d806eb14ba7529223d31e30674a8
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Jun 21 08:32:05 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Jun 21 10:23:33 2024 +0200

    tdf#161708 sw content controls: handle font color when exporting to PDF form
    
    Export the bugdoc to PDF, the orange "date" lost its font color.
    
    This went wrong in commit 82d90529dc2b3cb8359dec78852cbd910a66d275 (sw
    content controls, rich text: add initial PDF export, 2022-09-12), we
    export the content control as a PDF form widget by default since then.
    Various properties like checkbox status and dropdown items were handled
    already, but not text color.
    
    Fix the problem by mapping the SwFont color to the widget descriptor
    color, this fixes the color of the already filled in content of the
    widget.
    
    Note that given this is a property of the form widget, the color is
    correctly applied also to strings filled in via PDF readers, interacting
    with the form.
    
    Change-Id: Id3e8611e415c0d571afe1cd14561c97b8a910ce9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169317
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/external/pdfium/UnpackedTarball_pdfium.mk 
b/external/pdfium/UnpackedTarball_pdfium.mk
index 6c5bce9b2e29..a5634f076d1d 100644
--- a/external/pdfium/UnpackedTarball_pdfium.mk
+++ b/external/pdfium/UnpackedTarball_pdfium.mk
@@ -18,6 +18,8 @@ pdfium_patches += constexpr-template.patch
 
 pdfium_patches += system-abseil.diff
 
+pdfium_patches += annot.patch.1
+
 $(eval $(call gb_UnpackedTarball_UnpackedTarball,pdfium))
 
 $(eval $(call gb_UnpackedTarball_set_tarball,pdfium,$(PDFIUM_TARBALL)))
diff --git a/external/pdfium/annot.patch.1 b/external/pdfium/annot.patch.1
new file mode 100644
index 000000000000..330685962b4e
--- /dev/null
+++ b/external/pdfium/annot.patch.1
@@ -0,0 +1,65 @@
+diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
+index bc1f7f7eb..075baf1df 100644
+--- a/fpdfsdk/fpdf_annot.cpp
++++ b/fpdfsdk/fpdf_annot.cpp
+@@ -1366,6 +1366,42 @@ FPDFAnnot_GetFontSize(FPDF_FORMHANDLE hHandle,
+   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;
++
++  CPDFSDK_InteractiveForm* pForm = FormHandleToInteractiveForm(hHandle);
++  if (!pForm)
++    return false;
++
++  const CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++  if (!pAnnotDict)
++    return false;
++
++  CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
++  CPDF_FormControl* pFormControl = pPDFForm->GetControlByDict(pAnnotDict);
++  if (!pFormControl)
++    return false;
++
++  CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
++  if (!pWidget)
++    return false;
++
++  std::optional<FX_COLORREF> text_color = pWidget->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/public/fpdf_annot.h b/public/fpdf_annot.h
+index 337da58f1..27de4b1a8 100644
+--- a/public/fpdf_annot.h
++++ b/public/fpdf_annot.h
+@@ -845,6 +845,13 @@ FPDFAnnot_GetFontSize(FPDF_FORMHANDLE hHandle,
+                       FPDF_ANNOTATION annot,
+                       float* value);
+ 
++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/include/vcl/filter/PDFiumLibrary.hxx 
b/include/vcl/filter/PDFiumLibrary.hxx
index e008a502be58..a5d757414429 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -110,6 +110,7 @@ public:
     virtual std::vector<basegfx::B2DPoint> getLineGeometry() = 0;
     virtual PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) = 0;
     virtual float getFontSize(PDFiumDocument* pDoc) = 0;
+    virtual Color getFontColor(PDFiumDocument* pDoc) = 0;
     virtual OUString getFormFieldAlternateName(PDFiumDocument* pDoc) = 0;
     virtual int getFormFieldFlags(PDFiumDocument* pDoc) = 0;
     virtual OUString getFormAdditionalActionJavaScript(PDFiumDocument* pDoc,
diff --git a/sw/qa/core/text/itrform2.cxx b/sw/qa/core/text/itrform2.cxx
index f4186a63e7e1..8753a797e9f8 100644
--- a/sw/qa/core/text/itrform2.cxx
+++ b/sw/qa/core/text/itrform2.cxx
@@ -11,6 +11,8 @@
 
 #include <memory>
 
+#include <editeng/colritem.hxx>
+
 #include <IDocumentLayoutAccess.hxx>
 #include <rootfrm.hxx>
 #include <sortedobjs.hxx>
@@ -224,6 +226,38 @@ CPPUNIT_TEST_FIXTURE(Test, 
testCheckedCheckboxContentControlPDF)
     // would match /V, leading to not showing the checked state.
     CPPUNIT_ASSERT_EQUAL(u"Yes"_ustr, aActual);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testContentControlPDFFontColor)
+{
+    std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+    if (!pPDFium)
+        return;
+
+    // Given a document with a custom orange font color and a content control:
+    createSwDoc();
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    SfxItemSetFixed<RES_CHRATR_COLOR, RES_CHRATR_COLOR> 
aSet(pWrtShell->GetAttrPool());
+    Color nOrange(0xff6b00);
+    SvxColorItem aItem(nOrange, RES_CHRATR_COLOR);
+    aSet.Put(aItem);
+    pWrtShell->SetAttrSet(aSet);
+    pWrtShell->InsertContentControl(SwContentControlType::RICH_TEXT);
+
+    // When exporting that document to PDF:
+    save(u"writer_pdf_Export"_ustr);
+
+    // Then make sure that the widget in the PDF result has that custom font 
color:
+    std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
+    std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+    pPage->onAfterLoadPage(pPdfDocument.get());
+    CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationCount());
+    std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnotation = 
pPage->getAnnotation(0);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: rgba[ff6b00ff]
+    // - Actual  : rgba[000000ff]
+    // i.e. the custom color was lost, the font color was black, not orange.
+    CPPUNIT_ASSERT_EQUAL(nOrange, 
pAnnotation->getFontColor(pPdfDocument.get()));
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 430e8d9aa778..621294528767 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1081,6 +1081,10 @@ bool SwContentControlPortion::DescribePDFControl(const 
SwTextPaintInfo& rInf) co
     if (pFont)
     {
         pDescriptor->TextFont = pFont->GetActualFont();
+
+        // Need to transport the color explicitly, so it's applied to both 
already filled in and
+        // future content.
+        pDescriptor->TextColor = pFont->GetColor();
     }
 
     // Description for accessibility purposes.
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index ffdc94adcf29..0c1ee041a223 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -297,6 +297,7 @@ public:
     std::vector<basegfx::B2DPoint> getLineGeometry() override;
     PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) override;
     float getFontSize(PDFiumDocument* pDoc) override;
+    Color getFontColor(PDFiumDocument* pDoc) override;
     OUString getFormFieldAlternateName(PDFiumDocument* pDoc) override;
     int getFormFieldFlags(PDFiumDocument* pDoc) override;
     OUString getFormAdditionalActionJavaScript(PDFiumDocument* pDoc,
@@ -1310,6 +1311,18 @@ float PDFiumAnnotationImpl::getFontSize(PDFiumDocument* 
pDoc)
     return fRet;
 }
 
+Color PDFiumAnnotationImpl::getFontColor(PDFiumDocument* pDoc)
+{
+    auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
+    unsigned int nR, nG, nB;
+    if (!FPDFAnnot_GetFontColor(pDocImpl->getFormHandlePointer(), 
mpAnnotation, &nR, &nG, &nB))
+    {
+        return Color();
+    }
+
+    return Color(nR, nG, nB);
+}
+
 OUString PDFiumAnnotationImpl::getFormFieldAlternateName(PDFiumDocument* pDoc)
 {
     auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);

Reply via email to