summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-01-07 12:23:34 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-01-07 14:59:22 +0100
commit1984a5c140cc3c7c291047dacf3bddd7061d2047 (patch)
treeb19074fbce1ffdf0be4d4e3a4777a949f391ffa4
parent7df337b3636f9df9bf05d7f493e6c89e43c3f5ca (diff)
PDF export of PDF images: preserve hyperlinks
The input file has a single page, with a full-page PDF image, which contains a hyperlink. Similar to pdfcrop, we used to wrap this into a form XObject, so page-level annotations like hyperlinks were lost. Explicitly merge page-level annotations from the source page to the page that contains the PDF image to preserve those annotations. Change-Id: I96e8bc9d33440b91f3514486d6a8bd75047546b2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128108 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odgbin0 -> 28633 bytes
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx18
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx35
3 files changed, 53 insertions, 0 deletions
diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg
new file mode 100644
index 000000000000..aa0f89300b2c
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg
Binary files differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index af5f396db14d..7c6e273bf173 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -2872,6 +2872,24 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf145873)
CPPUNIT_ASSERT_DOUBLES_EQUAL(3.49, pObject->getBounds().getHeight(), 0.1);
}
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageHyperlink)
+{
+ // Given a Draw file, containing a PDF image, which has a hyperlink in it:
+ aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+
+ // When saving to PDF:
+ saveAsPDF(u"pdf-image-hyperlink.odg");
+
+ // Then make sure that link is preserved:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parseExport();
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+ // Without the accompanying fix in place, this test would have failed, the hyperlink of the PDF
+ // image was lost.
+ CPPUNIT_ASSERT(pPdfPage->hasLinks());
+}
+
} // end anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 53552f4ec4c8..d102108a8513 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -8434,6 +8434,41 @@ void PDFWriterImpl::writeReferenceXObject(const ReferenceXObjectEmit& rEmit)
return;
}
+ // Merge page annotations (links, etc) from pPage to our page.
+ std::vector<filter::PDFObjectElement*> aAnnots;
+ if (auto pArray = dynamic_cast<filter::PDFArrayElement*>(pPage->Lookup("Annots")))
+ {
+ for (const auto pElement : pArray->GetElements())
+ {
+ auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pElement);
+ if (!pReference)
+ {
+ continue;
+ }
+
+ filter::PDFObjectElement* pObject = pReference->LookupObject();
+ if (!pObject)
+ {
+ continue;
+ }
+
+ // Annotation refers to an object, remember it.
+ aAnnots.push_back(pObject);
+ }
+ }
+ if (!aAnnots.empty())
+ {
+ PDFObjectCopier aCopier(*this);
+ SvMemoryStream& rDocBuffer = pPage->GetDocument().GetEditBuffer();
+ std::map<sal_Int32, sal_Int32> aMap;
+ for (const auto& pAnnot : aAnnots)
+ {
+ // Copy over the annotation and refer to its new id.
+ sal_Int32 nNewId = aCopier.copyExternalResource(rDocBuffer, *pAnnot, aMap);
+ m_aPages.back().m_aAnnotations.push_back(nNewId);
+ }
+ }
+
nWrappedFormObject = createObject();
// Write the form XObject wrapped below. This is a separate object from
// the wrapper, this way there is no need to alter the stream contents.