[Libreoffice-commits] core.git: vcl/qa vcl/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Tue Nov 5 16:04:38 UTC 2019
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 <vmiklos at collabora.com>
AuthorDate: Tue Nov 5 16:12:43 2019 +0100
Commit: Miklos Vajna <vmiklos at 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 <vmiklos at 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"))
{
More information about the Libreoffice-commits
mailing list