vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf |binary vcl/qa/cppunit/pdfexport/pdfexport.cxx | 64 ++++++++++ vcl/source/gdi/pdfwriter_impl.cxx | 17 ++ 3 files changed, 80 insertions(+), 1 deletion(-)
New commits: commit adcdd56471f1cc10ff4135975ecadb3a703db6ad Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Nov 5 16:12:43 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Nov 5 17:03:32 2019 +0100 vcl PDF export: fix re-exporting PDF images for dict obj resource sub-keys Re-exporting PDF images works by tokenizing the PDF image, identifying which PDF object is the page object and then copying that over to the PDF output, together with the dependencies of that object. This involves copying the resources of the page object. Previously we assumed that the sub-keys of the resources are always inline dictionaries, but the bugdoc shows that they can be references as well, which point to dictionary objects, so add support for this scenario. Change-Id: I78ee1c726e6ecd958232e9fab64773595e5b9c86 Reviewed-on: https://gerrit.libreoffice.org/82076 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf new file mode 100644 index 000000000000..b62068eae9dd Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index eb779207de56..ba62f301bec4 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -19,6 +19,9 @@ #include <com/sun/star/view/XPrintable.hpp> #include <com/sun/star/text/XDocumentIndexesSupplier.hpp> #include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/text/XTextDocument.hpp> #include <comphelper/processfactory.hxx> #include <comphelper/propertysequence.hxx> @@ -131,6 +134,7 @@ public: void testTdf115967(); void testTdf121615(); void testTocLink(); + void testPdfImageResourceInlineXObjectRef(); CPPUNIT_TEST_SUITE(PdfExportTest); CPPUNIT_TEST(testTdf106059); @@ -166,6 +170,7 @@ public: CPPUNIT_TEST(testTdf115967); CPPUNIT_TEST(testTdf121615); CPPUNIT_TEST(testTocLink); + CPPUNIT_TEST(testPdfImageResourceInlineXObjectRef); CPPUNIT_TEST_SUITE_END(); }; @@ -1815,6 +1820,65 @@ void PdfExportTest::testTocLink() CPPUNIT_ASSERT(FPDFLink_Enumerate(pPdfPage.get(), &nStartPos, &pLinkAnnot)); } +void PdfExportTest::testPdfImageResourceInlineXObjectRef() +{ + // Create an empty document. + mxComponent = loadFromDesktop("private:factory/swriter"); + CPPUNIT_ASSERT(mxComponent.is()); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + + // Insert the PDF image. + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xGraphicObject( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + OUString aURL + = m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf-image-resource-inline-xobject-ref.pdf"; + xGraphicObject->setPropertyValue("GraphicURL", uno::makeAny(aURL)); + uno::Reference<drawing::XShape> xShape(xGraphicObject, uno::UNO_QUERY); + xShape->setSize(awt::Size(1000, 1000)); + uno::Reference<text::XTextContent> xTextContent(xGraphicObject, uno::UNO_QUERY); + xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false); + + // Save as 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()); + + // Init pdfium, vcl::ImportPDF() calls FPDF_DestroyLibrary after our setUp(). + FPDF_LIBRARY_CONFIG config; + config.version = 2; + config.m_pUserFontPaths = nullptr; + config.m_pIsolate = nullptr; + config.m_v8EmbedderSlot = 0; + FPDF_InitLibraryWithConfig(&config); + + // Parse the export result. + SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ); + maMemory.WriteStream(aFile); + DocumentHolder pPdfDocument( + FPDF_LoadMemDocument(maMemory.GetData(), maMemory.GetSize(), /*password=*/nullptr)); + CPPUNIT_ASSERT(pPdfDocument.get()); + CPPUNIT_ASSERT_EQUAL(1, FPDF_GetPageCount(pPdfDocument.get())); + + // Make sure that the page -> form -> form has a child image. + PageHolder pPdfPage(FPDF_LoadPage(pPdfDocument.get(), /*page_index=*/0)); + CPPUNIT_ASSERT(pPdfPage.get()); + CPPUNIT_ASSERT_EQUAL(1, FPDFPage_CountObjects(pPdfPage.get())); + FPDF_PAGEOBJECT pPageObject = FPDFPage_GetObject(pPdfPage.get(), 0); + CPPUNIT_ASSERT_EQUAL(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(pPageObject)); + CPPUNIT_ASSERT_EQUAL(1, FPDFFormObj_CountObjects(pPageObject)); + FPDF_PAGEOBJECT pFormObject = FPDFFormObj_GetObject(pPageObject, 0); + CPPUNIT_ASSERT_EQUAL(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(pFormObject)); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. the sub-form was missing its image. + CPPUNIT_ASSERT_EQUAL(1, FPDFFormObj_CountObjects(pFormObject)); +} + CPPUNIT_TEST_SUITE_REGISTRATION(PdfExportTest); } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 231872b72c45..faabdd8769f9 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -8699,8 +8699,23 @@ OString PDFWriterImpl::copyExternalResources(filter::PDFObjectElement& rPage, co if (auto pResources = dynamic_cast<filter::PDFDictionaryElement*>(rPage.Lookup("Resources"))) { // Resources is a direct dictionary. - if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pResources->LookupElement(rKind))) + filter::PDFElement* pLookup = pResources->LookupElement(rKind); + if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pLookup)) + { + // rKind is an inline dictionary. aItems = pDictionary->GetItems(); + } + else if (auto pReference = dynamic_cast<filter::PDFReferenceElement*>(pLookup)) + { + // rKind refers to a dictionary. + filter::PDFObjectElement* pReferenced = pReference->LookupObject(); + if (!pReferenced) + { + return OString(); + } + + aItems = pReferenced->GetDictionaryItems(); + } } else if (filter::PDFObjectElement* pPageResources = rPage.LookupObject("Resources")) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits