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,