diff options
-rw-r--r-- | sw/CppunitTest_sw_core_text.mk | 1 | ||||
-rw-r--r-- | sw/inc/EnhancedPDFExportHelper.hxx | 4 | ||||
-rw-r--r-- | sw/qa/core/text/text.cxx | 52 | ||||
-rw-r--r-- | sw/source/core/text/EnhancedPDFExportHelper.cxx | 62 |
4 files changed, 119 insertions, 0 deletions
diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk index b0c4d03fac38..cb4801accac9 100644 --- a/sw/CppunitTest_sw_core_text.mk +++ b/sw/CppunitTest_sw_core_text.mk @@ -26,6 +26,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \ sw \ swqahelper \ test \ + tl \ unotest \ utl \ vcl \ diff --git a/sw/inc/EnhancedPDFExportHelper.hxx b/sw/inc/EnhancedPDFExportHelper.hxx index 8273cf29ad85..eb813773abb3 100644 --- a/sw/inc/EnhancedPDFExportHelper.hxx +++ b/sw/inc/EnhancedPDFExportHelper.hxx @@ -219,6 +219,10 @@ class SwEnhancedPDFExportHelper static LanguageType s_eLanguageDefault; void EnhancedPDFExport(); + + /// Exports bibliography entry links. + void ExportAuthorityEntryLinks(); + sal_Int32 CalcOutputPageNum( const SwRect& rRect ) const; std::vector< sal_Int32 > CalcOutputPageNums( const SwRect& rRect ) const; diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx index 8b4c6ae336bb..f3a4b458b3ae 100644 --- a/sw/qa/core/text/text.cxx +++ b/sw/qa/core/text/text.cxx @@ -9,7 +9,14 @@ #include <swmodeltestbase.hxx> +#include <memory> + +#include <com/sun/star/text/BibliographyDataType.hpp> + #include <vcl/gdimtf.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> +#include <comphelper/propertyvalue.hxx> +#include <unotools/mediadescriptor.hxx> #include <docsh.hxx> #include <unotxdoc.hxx> @@ -69,6 +76,51 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testSemiTransparentText) assertXPath(pXmlDoc, "//floattransparent"); } +CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testBibliographyUrlPdfExport) +{ + // Given a document with a bibliography entry field: + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + createSwDoc(); + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xField( + xFactory->createInstance("com.sun.star.text.TextField.Bibliography"), uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aFields = { + comphelper::makePropertyValue("BibiliographicType", text::BibliographyDataType::WWW), + comphelper::makePropertyValue("Identifier", OUString("AT")), + comphelper::makePropertyValue("Author", OUString("Author")), + comphelper::makePropertyValue("Title", OUString("Title")), + comphelper::makePropertyValue("URL", OUString("http://www.example.com/test.pdf#page=1")), + }; + xField->setPropertyValue("Fields", uno::makeAny(aFields)); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + uno::Reference<text::XTextContent> xContent(xField, uno::UNO_QUERY); + xText->insertTextContent(xCursor, xContent, /*bAbsorb=*/false); + + // 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 the field links the source. + SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFile); + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize()); + CPPUNIT_ASSERT(pPdfDocument); + std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + // Without the accompanying fix in place, this test would have failed, the field was not + // clickable (while it was clickable on the UI). + CPPUNIT_ASSERT(pPdfPage->hasLinks()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx b/sw/source/core/text/EnhancedPDFExportHelper.cxx index 29719590dc4c..51785be1a1c4 100644 --- a/sw/source/core/text/EnhancedPDFExportHelper.cxx +++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx @@ -79,6 +79,7 @@ #include <frmtool.hxx> #include <strings.hrc> #include <frameformats.hxx> +#include <authfld.hxx> #include <tools/globname.hxx> #include <svx/svdobj.hxx> @@ -1923,6 +1924,8 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() mrSh.SwCursorShell::ClearMark(); } + ExportAuthorityEntryLinks(); + // FOOTNOTES const size_t nFootnoteCount = pDoc->GetFootnoteIdxs().size(); @@ -2162,6 +2165,65 @@ void SwEnhancedPDFExportHelper::EnhancedPDFExport() mrOut.Pop(); } +void SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks() +{ + auto pPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData*>(mrOut.GetExtOutDevData()); + if (!pPDFExtOutDevData) + { + return; + } + + std::vector<SwFormatField*> aFields; + SwFieldType* pType = mrSh.GetFieldType(SwFieldIds::TableOfAuthorities, OUString()); + if (!pType) + { + return; + } + + pType->GatherFields(aFields); + const auto pPageFrame = static_cast<const SwPageFrame*>(mrSh.GetLayout()->Lower()); + for (const auto pFormatField : aFields) + { + if (!pFormatField->GetTextField() || !pFormatField->IsFieldInDoc()) + { + continue; + } + + const auto& rAuthorityField + = *static_cast<const SwAuthorityField*>(pFormatField->GetField()); + if (!rAuthorityField.HasURL()) + { + continue; + } + + const OUString& rURL = rAuthorityField.GetAuthEntry()->GetAuthorField(AUTH_FIELD_URL); + const SwTextNode& rTextNode = pFormatField->GetTextField()->GetTextNode(); + if (!lcl_TryMoveToNonHiddenField(mrSh, rTextNode, *pFormatField)) + { + continue; + } + + // Select the field. + mrSh.SwCursorShell::SetMark(); + mrSh.SwCursorShell::Right(1, CRSR_SKIP_CHARS); + + // Create the links. + for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_()) + { + for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect)) + { + tools::Rectangle aRect(SwRectToPDFRect(pPageFrame, rLinkRect.SVRect())); + sal_Int32 nLinkId = pPDFExtOutDevData->CreateLink(aRect, rLinkPageNum); + IdMapEntry aLinkEntry(rLinkRect, nLinkId); + s_aLinkIdMap.push_back(aLinkEntry); + pPDFExtOutDevData->SetLinkURL(nLinkId, rURL); + } + } + + mrSh.SwCursorShell::ClearMark(); + } +} + // Returns the page number in the output pdf on which the given rect is located. // If this page is duplicated, method will return first occurrence of it. sal_Int32 SwEnhancedPDFExportHelper::CalcOutputPageNum( const SwRect& rRect ) const |