diff options
-rw-r--r-- | include/vcl/filter/PDFiumLibrary.hxx | 1 | ||||
-rw-r--r-- | sw/qa/core/text/text.cxx | 35 | ||||
-rw-r--r-- | sw/source/core/text/itrform2.cxx | 9 | ||||
-rw-r--r-- | vcl/source/pdf/PDFiumLibrary.cxx | 31 |
4 files changed, 74 insertions, 2 deletions
diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx index a0da94ab49f2..305c7f3f9d2f 100644 --- a/include/vcl/filter/PDFiumLibrary.hxx +++ b/include/vcl/filter/PDFiumLibrary.hxx @@ -106,6 +106,7 @@ public: virtual float getFontSize(PDFiumDocument* pDoc) = 0; virtual OUString getFormFieldAlternateName(PDFiumDocument* pDoc) = 0; virtual int getFormFieldFlags(PDFiumDocument* pDoc) = 0; + virtual OUString getFormFieldValue(PDFiumDocument* pDoc) = 0; }; class PDFiumTextPage; diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx index de15cadd4c36..8cc59e8e3a2a 100644 --- a/sw/qa/core/text/text.cxx +++ b/sw/qa/core/text/text.cxx @@ -770,6 +770,41 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testNumberPortionNoformat) getXPath(pXmlDoc, "//Special[@nType='PortionType::Number']/SwFont", "color")); } +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testCheckedCheckboxContentControlPDF) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + return; + + // Given a file with a checked checkbox content control: + SwDoc* pDoc = createSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->InsertContentControl(SwContentControlType::CHECKBOX); + // Toggle it, so we get a checked one: + SwTextContentControl* pTextContentControl = pWrtShell->CursorInsideContentControl(); + const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl(); + pWrtShell->GotoContentControl(rFormatContentControl); + + // When exporting to PDF: + StoreToTempFile("writer_pdf_Export"); + + // Then make sure that a checked checkbox form widget is emitted: + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = LoadPdfFromTempFile(); + std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0); + 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()); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFFormFieldType::CheckBox, + pAnnotation->getFormFieldType(pPdfDocument.get())); + OUString aActual = pAnnotation->getFormFieldValue(pPdfDocument.get()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: Yes + // - Actual : Off + // i.e. the /AP -> /N key of the checkbox widget annotation object didn't have a sub-key that + // would match /V, leading to not showing the checked state. + CPPUNIT_ASSERT_EQUAL(OUString("Yes"), aActual); +} + 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 fad85e12337e..fdbd8ef28050 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -951,8 +951,13 @@ bool SwContentControlPortion::DescribePDFControl(const SwTextPaintInfo& rInf) co 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(); + // If it is checked already, then leave the default "Yes" OnValue unchanged, so the + // appropriate appearance is found by PDF readers. + if (!pCheckBoxWidget->Checked) + { + pCheckBoxWidget->OnValue = pContentControl->GetCheckedState(); + pCheckBoxWidget->OffValue = pContentControl->GetUncheckedState(); + } break; } case SwContentControlType::DROP_DOWN_LIST: diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx index c6781bca2f26..5db5805b2250 100644 --- a/vcl/source/pdf/PDFiumLibrary.cxx +++ b/vcl/source/pdf/PDFiumLibrary.cxx @@ -253,6 +253,7 @@ public: float getFontSize(PDFiumDocument* pDoc) override; OUString getFormFieldAlternateName(PDFiumDocument* pDoc) override; int getFormFieldFlags(PDFiumDocument* pDoc) override; + OUString getFormFieldValue(PDFiumDocument* pDoc) override; }; class PDFiumPageObjectImpl final : public PDFiumPageObject @@ -1230,6 +1231,36 @@ OUString PDFiumAnnotationImpl::getFormFieldAlternateName(PDFiumDocument* pDoc) return aString; } +OUString PDFiumAnnotationImpl::getFormFieldValue(PDFiumDocument* pDoc) +{ + auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc); + OUString aString; + unsigned long nSize + = FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, nullptr, 0); + assert(nSize % 2 == 0); + nSize /= 2; + if (nSize > 1) + { + std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]); + unsigned long nStringSize + = FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, + reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2); + assert(nStringSize % 2 == 0); + nStringSize /= 2; + if (nStringSize > 0) + { +#if defined OSL_BIGENDIAN + for (unsigned long i = 0; i != nStringSize; ++i) + { + pText[i] = OSL_SWAPWORD(pText[i]); + } +#endif + aString = OUString(pText.get()); + } + } + return aString; +} + namespace { bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& rHorizontalCornerRadius, |