vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf |binary vcl/qa/cppunit/pdfexport/pdfexport.cxx | 50 ++++++++++++++++++++++++++ vcl/source/gdi/pdfobjectcopier.cxx | 26 +++++++++++++ 3 files changed, 76 insertions(+)
New commits: commit 4cb521b28e8582eda1a63bc4d92061fd111a2e3d Author: Dennis Francis <dennis.fran...@collabora.com> AuthorDate: Fri Dec 2 13:11:42 2022 +0530 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Fri Dec 16 13:52:10 2022 +0000 vcl: Copy the resource kind object itself if... some of the items in that resource are themselves dictionaries instead of references. Change-Id: I427386b14fe5507dfdfc9745dad27a8fceefd929 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143564 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf index 0390ccad8410..fdda33f78231 100644 Binary files a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf and b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index 8b9541e9478e..ab62a54b74db 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -3494,6 +3494,56 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testRexportMediaBoxOrigin) #endif } +CPPUNIT_TEST_FIXTURE(PdfExportTest, testRexportResourceItemReference) +{ +// setenv only works on unix based systems +#ifndef _WIN32 + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + setenv("LO_IMPORT_USE_PDFIUM", "1", false); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + unsetenv("LO_IMPORT_USE_PDFIUM"); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"ref-to-kids.pdf", aDocument); + + std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size()); + + // Directly go to the inner XObject Im10 that has reference to Font in page 2. + auto pInnerIm = aDocument.LookupObject(10); + CPPUNIT_ASSERT(pInnerIm); + + auto pResources + = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pInnerIm->Lookup("Resources")); + CPPUNIT_ASSERT(pResources); + auto pFontsReference + = dynamic_cast<vcl::filter::PDFReferenceElement*>(pResources->LookupElement("Font")); + CPPUNIT_ASSERT(pFontsReference); + + auto pFontsObject = pFontsReference->LookupObject(); + CPPUNIT_ASSERT(pFontsObject); + + auto pFontDict + = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pFontsObject->Lookup("FF132")); + CPPUNIT_ASSERT(pFontDict); + + auto pFontDescriptor = pFontDict->LookupObject("FontDescriptor"); + CPPUNIT_ASSERT(pFontDescriptor); + + auto pFontWidths = pFontDict->LookupObject("Widths"); + CPPUNIT_ASSERT(pFontWidths); + +#endif +} + } // end anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/vcl/source/gdi/pdfobjectcopier.cxx b/vcl/source/gdi/pdfobjectcopier.cxx index 67f70d10f2a9..cbf3dc308c3b 100644 --- a/vcl/source/gdi/pdfobjectcopier.cxx +++ b/vcl/source/gdi/pdfobjectcopier.cxx @@ -184,6 +184,7 @@ OString PDFObjectCopier::copyExternalResources(filter::PDFObjectElement& rPage, // Get the rKind subset of the resource dictionary. std::map<OString, filter::PDFElement*> aItems; + filter::PDFObjectElement* pKindObject = nullptr; if (auto pResources = dynamic_cast<filter::PDFDictionaryElement*>(rPage.Lookup("Resources"))) { // Resources is a direct dictionary. @@ -202,6 +203,7 @@ OString PDFObjectCopier::copyExternalResources(filter::PDFObjectElement& rPage, return {}; } + pKindObject = pReferenced; aItems = pReferenced->GetDictionaryItems(); } } @@ -210,23 +212,40 @@ OString PDFObjectCopier::copyExternalResources(filter::PDFObjectElement& rPage, // Resources is an indirect object. filter::PDFElement* pValue = pPageResources->Lookup(rKind); if (auto pDictionary = dynamic_cast<filter::PDFDictionaryElement*>(pValue)) + { // Kind is a direct dictionary. aItems = pDictionary->GetItems(); + } else if (filter::PDFObjectElement* pObject = pPageResources->LookupObject(rKind)) + { // Kind is an indirect object. aItems = pObject->GetDictionaryItems(); + pKindObject = pObject; + } } if (aItems.empty()) return {}; SvMemoryStream& rDocBuffer = rPage.GetDocument().GetEditBuffer(); + bool bHasDictValue = false; for (const auto& rItem : aItems) { // For each item copy it over to our output then insert it into aRet. auto pReference = dynamic_cast<filter::PDFReferenceElement*>(rItem.second); if (!pReference) + { + if (pKindObject) + { + if (auto* pDict = dynamic_cast<filter::PDFDictionaryElement*>(rItem.second)) + { + bHasDictValue = true; + break; + } + } + continue; + } filter::PDFObjectElement* pValue = pReference->LookupObject(); if (!pValue) @@ -237,6 +256,13 @@ OString PDFObjectCopier::copyExternalResources(filter::PDFObjectElement& rPage, aRet[rItem.first] = nObject; } + if (bHasDictValue && pKindObject) + { + sal_Int32 nObject = copyExternalResource(rDocBuffer, *pKindObject, rCopiedResources); + OStringBuffer sRet("/" + rKind + " " + OString::number(nObject) + " 0 R"); + return sRet.makeStringAndClear(); + } + // Build the dictionary entry string. OStringBuffer sRet("/" + rKind + "<<"); for (const auto& rPair : aRet)