include/vcl/filter/PDFiumLibrary.hxx |    2 +
 include/vcl/pdf/PDFFormFieldType.hxx |   29 +++++++++++++++++++++++++++
 include/vcl/pdfwriter.hxx            |    2 -
 sw/qa/core/text/text.cxx             |   37 +++++++++++++++++++++++++++++++++++
 sw/source/core/text/itrform2.cxx     |   14 ++++++++++---
 vcl/source/pdf/PDFiumLibrary.cxx     |   26 ++++++++++++++++++++++++
 6 files changed, 106 insertions(+), 4 deletions(-)

New commits:
commit 67624e5cfe8ed49d0123e709378779c4e1a3cd49
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Sep 13 15:23:31 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Sep 14 10:54:06 2022 +0200

    sw content controls, checkbox: add PDF export
    
    Map this to vcl::PDFWriter::CheckBoxWidget, which uses the /FT/Btn
    widget, i.e. a (toggle) button which is not a pushbutton or a
    radiobutton).
    
    Also avoid a border for content controls: it just cuts out some part of
    the rich text/plain text content control filled in text + causes a
    double border for checkboxes, so not useful.
    
    Change-Id: If8dd63fe71d7c2ba9bea4bf2ecc6621fefb74fd6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139868
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/include/vcl/filter/PDFiumLibrary.hxx 
b/include/vcl/filter/PDFiumLibrary.hxx
index 3a4d0d83faf6..8274ded92e1f 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -33,6 +33,7 @@
 #include <vcl/pdf/PDFFillMode.hxx>
 #include <vcl/pdf/PDFFindFlags.hxx>
 #include <vcl/pdf/PDFErrorType.hxx>
+#include <vcl/pdf/PDFFormFieldType.hxx>
 
 class SvMemoryStream;
 
@@ -100,6 +101,7 @@ public:
     virtual size_t getAttachmentPointsCount() = 0;
     virtual std::vector<basegfx::B2DPoint> getAttachmentPoints(size_t nIndex) 
= 0;
     virtual std::vector<basegfx::B2DPoint> getLineGeometry() = 0;
+    virtual PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) = 0;
 };
 
 class PDFiumTextPage;
diff --git a/include/vcl/pdf/PDFFormFieldType.hxx 
b/include/vcl/pdf/PDFFormFieldType.hxx
new file mode 100644
index 000000000000..96be9bffc188
--- /dev/null
+++ b/include/vcl/pdf/PDFFormFieldType.hxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+namespace vcl::pdf
+{
+enum class PDFFormFieldType
+{
+    Unknown = 0,
+    PushButton = 1,
+    CheckBox = 2,
+    RadioButton = 3,
+    ComboBox = 4,
+    ListBox = 5,
+    TextField = 6,
+    Signature = 7
+};
+
+} // namespace vcl::pdf
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index be15738fbd5d..56181deb5c3a 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -329,7 +329,7 @@ public:
         }
     };
 
-    struct CheckBoxWidget final : public AnyWidget
+    struct VCL_DLLPUBLIC CheckBoxWidget final : public AnyWidget
     {
         bool                Checked;
         OUString            OnValue; // the value of the checkbox if it is 
selected
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index ce1dab48f0cb..282456d491a7 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -567,6 +567,43 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testContentControlPDF)
     CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationCount());
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testCheckboxContentControlPDF)
+{
+    // Given a file with a checkbox content control:
+    SwDoc* pDoc = createSwDoc();
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->InsertContentControl(SwContentControlType::CHECKBOX);
+
+    // When exporting to PDF:
+    uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+    xStorable->storeToURL(maTempFile.GetURL(), 
aMediaDescriptor.getAsConstPropertyValueList());
+
+    // Then make sure that a checkbox form widget is emitted:
+    SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ);
+    SvMemoryStream aMemory;
+    aMemory.WriteStream(aFile);
+    std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+    if (!pPDFium)
+    {
+        return;
+    }
+    std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+        = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), 
OString());
+    std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 0
+    // i.e. the checkbox content control was just exported as normal text.
+    CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationCount());
+    std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnotation = 
pPage->getAnnotation(0);
+    CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Widget, 
pAnnotation->getSubType());
+    // Also check the form widget type:
+    CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFFormFieldType::CheckBox,
+                         pAnnotation->getFormFieldType(pPdfDocument.get()));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 1828967f8481..1d05e5cf605e 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -928,8 +928,19 @@ bool SwContentControlPortion::DescribePDFControl(const 
SwTextPaintInfo& rInf) co
     {
         case SwContentControlType::RICH_TEXT:
         case SwContentControlType::PLAIN_TEXT:
+        {
             pDescriptor = std::make_unique<vcl::PDFWriter::EditWidget>();
             break;
+        }
+        case SwContentControlType::CHECKBOX:
+        {
+            pDescriptor = std::make_unique<vcl::PDFWriter::CheckBoxWidget>();
+            auto pCheckBoxWidget = 
static_cast<vcl::PDFWriter::CheckBoxWidget*>(pDescriptor.get());
+            pCheckBoxWidget->Checked = pContentControl->GetChecked();
+            pCheckBoxWidget->OnValue = pContentControl->GetCheckedState();
+            pCheckBoxWidget->OffValue = pContentControl->GetUncheckedState();
+            break;
+        }
         default:
             break;
     }
@@ -939,9 +950,6 @@ bool SwContentControlPortion::DescribePDFControl(const 
SwTextPaintInfo& rInf) co
         return false;
     }
 
-    pDescriptor->Border = true;
-    pDescriptor->BorderColor = COL_BLACK;
-
     SwRect aLocation;
     rInf.CalcRect(*this, &aLocation);
     pDescriptor->Location = aLocation.SVRect();
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index 643039f2359f..1180410521f7 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -136,6 +136,24 @@ 
static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Security) == FPDF_ERR_SEC
 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Page) == FPDF_ERR_PAGE,
               "PDFErrorType::Page value mismatch");
 
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::Unknown) == 
FPDF_FORMFIELD_UNKNOWN,
+              "PDFFormFieldType::Unknown value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::PushButton) == 
FPDF_FORMFIELD_PUSHBUTTON,
+              "PDFFormFieldType::PushButton value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::CheckBox) == 
FPDF_FORMFIELD_CHECKBOX,
+              "PDFFormFieldType::CheckBox value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::RadioButton)
+                  == FPDF_FORMFIELD_RADIOBUTTON,
+              "PDFFormFieldType::RadioButton value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::ComboBox) == 
FPDF_FORMFIELD_COMBOBOX,
+              "PDFFormFieldType::ComboBox value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::ListBox) == 
FPDF_FORMFIELD_LISTBOX,
+              "PDFFormFieldType::ListBox value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::TextField) == 
FPDF_FORMFIELD_TEXTFIELD,
+              "PDFFormFieldType::TextField value mismatch");
+static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::Signature) == 
FPDF_FORMFIELD_SIGNATURE,
+              "PDFFormFieldType::Signature value mismatch");
+
 namespace
 {
 /// Callback class to be used with FPDF_SaveWithVersion().
@@ -230,6 +248,7 @@ public:
     size_t getAttachmentPointsCount() override;
     std::vector<basegfx::B2DPoint> getAttachmentPoints(size_t nIndex) override;
     std::vector<basegfx::B2DPoint> getLineGeometry() override;
+    PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) override;
 };
 
 class PDFiumPageObjectImpl final : public PDFiumPageObject
@@ -1108,6 +1127,13 @@ std::vector<basegfx::B2DPoint> 
PDFiumAnnotationImpl::getLineGeometry()
     return aLine;
 }
 
+PDFFormFieldType PDFiumAnnotationImpl::getFormFieldType(PDFiumDocument* pDoc)
+{
+    auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
+    return PDFFormFieldType(
+        FPDFAnnot_GetFormFieldType(pDocImpl->getFormHandlePointer(), 
mpAnnotation));
+}
+
 namespace
 {
 bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& 
rHorizontalCornerRadius,

Reply via email to