include/tools/UnitConversion.hxx | 31 +++ include/tools/mapunit.hxx | 11 - include/vcl/VectorGraphicSearch.hxx | 39 ++++ include/vcl/vectorgraphicdata.hxx | 3 sd/inc/Outliner.hxx | 6 sd/source/ui/view/Outliner.cxx | 11 - svx/source/svdraw/svdedtv2.cxx | 2 vcl/CppunitTest_vcl_graphic_test.mk | 7 vcl/Library_vcl.mk | 1 vcl/qa/cppunit/VectorGraphicSearchTest.cxx | 50 +++++ vcl/qa/cppunit/data/Pangram.pdf |binary vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf |binary vcl/qa/cppunit/pdfexport/pdfexport.cxx | 137 +++++++++++++++ vcl/source/graphic/VectorGraphicSearch.cxx | 168 +++++++++++++++++++ 14 files changed, 439 insertions(+), 27 deletions(-)
New commits: commit 71adf9126b99405d7928b0d4295d586e4551ac12 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu May 7 22:01:22 2020 +0200 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Wed Jul 29 20:43:19 2020 +0200 vcl: VectorGraphicSearch - for searching text inside PDF Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95254 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit efba780d6155317b592b6f5f73945a7851ec4d3b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95801 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit c0de8e44e92c8d83c98afe8f807deb2633b3d2bd) Change-Id: Iee940a3927330c8739774ff3c1af15998f89193b diff --git a/include/vcl/VectorGraphicSearch.hxx b/include/vcl/VectorGraphicSearch.hxx new file mode 100644 index 000000000000..3411d0a931e6 --- /dev/null +++ b/include/vcl/VectorGraphicSearch.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include <vcl/graph.hxx> +#include <vcl/vectorgraphicdata.hxx> +#include <vcl/dllapi.h> + +#include <fpdf_doc.h> + +#include <memory> + +class SearchContext; + +class VCL_DLLPUBLIC VectorGraphicSearch final +{ +private: + Graphic maGraphic; + FPDF_DOCUMENT mpPdfDocument; + std::unique_ptr<SearchContext> mpSearchContext; + bool searchPDF(std::shared_ptr<VectorGraphicData> const& rData, OUString const& rSearchString); + +public: + VectorGraphicSearch(Graphic const& rGraphic); + ~VectorGraphicSearch(); + bool search(OUString const& rSearchString); + bool next(); + int index(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/CppunitTest_vcl_graphic_test.mk b/vcl/CppunitTest_vcl_graphic_test.mk index 89cb122bc7d6..ad0377860bc8 100644 --- a/vcl/CppunitTest_vcl_graphic_test.mk +++ b/vcl/CppunitTest_vcl_graphic_test.mk @@ -12,11 +12,12 @@ $(eval $(call gb_CppunitTest_CppunitTest,vcl_graphic_test)) $(eval $(call gb_CppunitTest_add_exception_objects,vcl_graphic_test, \ vcl/qa/cppunit/GraphicTest \ vcl/qa/cppunit/GraphicDescriptorTest \ + vcl/qa/cppunit/VectorGraphicSearchTest \ )) -$(eval $(call gb_CppunitTest_use_externals,vcl_graphic_test,\ - boost_headers \ - glm_headers \ +$(eval $(call gb_CppunitTest_use_externals,vcl_graphic_test, \ + boost_headers \ + $(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \ )) $(eval $(call gb_CppunitTest_set_include,vcl_graphic_test,\ diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index c3badab07d9f..d65aad0a5e6d 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -315,6 +315,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/graphic/UnoGraphicObject \ vcl/source/graphic/UnoGraphicProvider \ vcl/source/graphic/UnoGraphicTransformer \ + vcl/source/graphic/VectorGraphicSearch \ vcl/source/bitmap/bitmap \ vcl/source/bitmap/bitmapfilter \ vcl/source/bitmap/BitmapAlphaClampFilter \ diff --git a/vcl/qa/cppunit/VectorGraphicSearchTest.cxx b/vcl/qa/cppunit/VectorGraphicSearchTest.cxx new file mode 100644 index 000000000000..0ed21ccf9e26 --- /dev/null +++ b/vcl/qa/cppunit/VectorGraphicSearchTest.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cppunit/TestAssert.h> +#include <cppunit/extensions/HelperMacros.h> +#include <unotest/bootstrapfixturebase.hxx> +#include <unotest/directories.hxx> + +#include <vcl/VectorGraphicSearch.hxx> +#include <vcl/graph.hxx> +#include <vcl/graphicfilter.hxx> +#include <tools/stream.hxx> + +class VectorGraphicSearchTest : public test::BootstrapFixtureBase +{ + OUString getFullUrl(const OUString& sFileName) + { + return m_directories.getURLFromSrc("/vcl/qa/cppunit/data/") + sFileName; + } + + void test(); + + CPPUNIT_TEST_SUITE(VectorGraphicSearchTest); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +}; + +void VectorGraphicSearchTest::test() +{ + OUString aURL = getFullUrl("Pangram.pdf"); + SvFileStream aStream(aURL, StreamMode::READ); + GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream); + aGraphic.makeAvailable(); + + VectorGraphicSearch aSearch(aGraphic); + CPPUNIT_ASSERT_EQUAL(true, aSearch.search("lazy")); + CPPUNIT_ASSERT_EQUAL(true, aSearch.next()); + CPPUNIT_ASSERT_EQUAL(34, aSearch.index()); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(VectorGraphicSearchTest); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qa/cppunit/data/Pangram.pdf b/vcl/qa/cppunit/data/Pangram.pdf new file mode 100644 index 000000000000..0714fda4e4dd Binary files /dev/null and b/vcl/qa/cppunit/data/Pangram.pdf differ diff --git a/vcl/source/graphic/VectorGraphicSearch.cxx b/vcl/source/graphic/VectorGraphicSearch.cxx new file mode 100644 index 000000000000..864c65f2dda2 --- /dev/null +++ b/vcl/source/graphic/VectorGraphicSearch.cxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <sal/config.h> +#include <vcl/VectorGraphicSearch.hxx> + +#include <fpdf_text.h> + +class SearchContext +{ +public: + bool bInitialized = false; + + FPDF_DOCUMENT mpPdfDocument; + sal_Int32 mnPageIndex; + FPDF_PAGE mpPage; + FPDF_TEXTPAGE mpTextPage; + OUString maSearchString; + FPDF_SCHHANDLE mpSearchHandle; + + SearchContext(FPDF_DOCUMENT pPdfDocument, sal_Int32 nPageIndex, OUString const& rSearchString) + : mpPdfDocument(pPdfDocument) + , mnPageIndex(nPageIndex) + , mpPage(nullptr) + , mpTextPage(nullptr) + , maSearchString(rSearchString) + , mpSearchHandle(nullptr) + { + } + + ~SearchContext() + { + if (mpSearchHandle) + FPDFText_FindClose(mpSearchHandle); + if (mpTextPage) + FPDFText_ClosePage(mpTextPage); + if (mpPage) + FPDF_ClosePage(mpPage); + } + + bool initialize() + { + if (!mpPdfDocument) + return false; + mpPage = FPDF_LoadPage(mpPdfDocument, mnPageIndex); + if (!mpPage) + return false; + mpTextPage = FPDFText_LoadPage(mpPage); + if (!mpTextPage) + return false; + + FPDF_WIDESTRING pString = reinterpret_cast<FPDF_WIDESTRING>(maSearchString.getStr()); + mpSearchHandle = FPDFText_FindStart(mpTextPage, pString, 0, 0); + + return mpSearchHandle != nullptr; + } + + bool next() + { + if (mpSearchHandle) + return FPDFText_FindNext(mpSearchHandle); + return false; + } + + int index() + { + if (mpSearchHandle) + return FPDFText_GetSchResultIndex(mpSearchHandle); + return -1; + } +}; + +VectorGraphicSearch::VectorGraphicSearch(Graphic const& rGraphic) + : maGraphic(rGraphic) + , mpPdfDocument(nullptr) +{ + FPDF_LIBRARY_CONFIG aConfig; + aConfig.version = 2; + aConfig.m_pUserFontPaths = nullptr; + aConfig.m_pIsolate = nullptr; + aConfig.m_v8EmbedderSlot = 0; + FPDF_InitLibraryWithConfig(&aConfig); +} + +VectorGraphicSearch::~VectorGraphicSearch() +{ + mpSearchContext.reset(); + + if (mpPdfDocument) + FPDF_CloseDocument(mpPdfDocument); + FPDF_DestroyLibrary(); +} + +bool VectorGraphicSearch::search(OUString const& rSearchString) +{ + auto pData = maGraphic.getVectorGraphicData(); + + if (pData && pData->getVectorGraphicDataType() == VectorGraphicDataType::Pdf) + { + return searchPDF(pData, rSearchString); + } + return false; +} + +bool VectorGraphicSearch::searchPDF(std::shared_ptr<VectorGraphicData> const& rData, + OUString const& rSearchString) +{ + if (rSearchString.isEmpty()) + return false; + + mpPdfDocument + = FPDF_LoadMemDocument(rData->getVectorGraphicDataArray().getConstArray(), + rData->getVectorGraphicDataArrayLength(), /*password=*/nullptr); + + if (!mpPdfDocument) + { + //TODO: Handle failure to load. + switch (FPDF_GetLastError()) + { + case FPDF_ERR_SUCCESS: + break; + case FPDF_ERR_UNKNOWN: + break; + case FPDF_ERR_FILE: + break; + case FPDF_ERR_FORMAT: + break; + case FPDF_ERR_PASSWORD: + break; + case FPDF_ERR_SECURITY: + break; + case FPDF_ERR_PAGE: + break; + default: + break; + } + return false; + } + + sal_Int32 nPageIndex = std::max(rData->getPageIndex(), 0); + + mpSearchContext.reset(new SearchContext(mpPdfDocument, nPageIndex, rSearchString)); + + return mpSearchContext->initialize(); +} + +bool VectorGraphicSearch::next() +{ + if (mpSearchContext) + return mpSearchContext->next(); + return false; +} + +int VectorGraphicSearch::index() +{ + if (mpSearchContext) + return mpSearchContext->index(); + return -1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 7b9cbd12fde96242ddb6fc6467010ae5611cead8 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sat May 23 16:52:09 2020 +0200 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Wed Jul 29 18:45:56 2020 +0200 sd: move SearchSelection constructor to header file Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94727 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit beacca27ecc1b1463477c644e36a7e5815053433) Change-Id: I71d7986044208b6c733c1d46db7bf84bc6254915 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95798 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit 1f48b99b218d3ef78b60e1006fea095d77c35c0d) diff --git a/sd/inc/Outliner.hxx b/sd/inc/Outliner.hxx index 7f25e9a0fcf4..78a32cbb1e83 100644 --- a/sd/inc/Outliner.hxx +++ b/sd/inc/Outliner.hxx @@ -47,7 +47,11 @@ struct SearchSelection */ OString const m_aRectangles; - SearchSelection(int nPage, const OString& rRectangles); + SearchSelection(int nPage, const OString& rRectangles) + : m_nPage(nPage) + , m_aRectangles(rRectangles) + { + } bool operator==(const SearchSelection& rOther) const { diff --git a/sd/source/ui/view/Outliner.cxx b/sd/source/ui/view/Outliner.cxx index 73f34cf64372..20c248a78fd0 100644 --- a/sd/source/ui/view/Outliner.cxx +++ b/sd/source/ui/view/Outliner.cxx @@ -81,17 +81,6 @@ using namespace ::com::sun::star::linguistic2; class SfxStyleSheetPool; -namespace sd { - -SearchSelection::SearchSelection(int nPage, const OString& rRectangles) - : m_nPage(nPage), - m_aRectangles(rRectangles) -{ -} - -} // end of namespace sd - - class SdOutliner::Implementation { public: commit 90b043013fdcf7ea5daffe09b6f26446e902f1d0 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Sun May 31 20:25:11 2020 +0200 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Wed Jul 29 18:44:33 2020 +0200 tdf#133547 Fix breaking of PDF graphic objects ImpSdrPdfImport did not handle -1 as the page number correctly. When the page number is -1 it means it was never explicitly set and should be treated as page with index 0 most of the time. So instead of allowing -1 as the page index, return it as 0 already in Graphic (VectorGraphicData). Change-Id: I3813f3ceeb5e41cb06fc40d67297d2439d7f3407 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95227 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit 573de30566e4477c8dc09abec08f1082d16c74bc) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95800 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> (cherry picked from commit 1e6b3014f1ecb06c40d3f1549351870abc4f9582) diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx index 10069d5119a8..75688d2b00a7 100644 --- a/include/vcl/vectorgraphicdata.hxx +++ b/include/vcl/vectorgraphicdata.hxx @@ -27,6 +27,7 @@ #include <rtl/ustring.hxx> #include <deque> #include <memory> +#include <algorithm> typedef css::uno::Sequence<sal_Int8> VectorGraphicDataArray; @@ -109,7 +110,7 @@ public: const BitmapEx& getReplacement() const; BitmapChecksum GetChecksum() const; - sal_Int32 getPageIndex() const { return mnPageIndex; } + sal_Int32 getPageIndex() const { return std::max(sal_Int32(0), mnPageIndex); } bool isPrimitiveSequenceCreated() const { return mbSequenceCreated; } }; diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx index cf9746ae93ba..e4d58699ad1d 100644 --- a/svx/source/svdraw/svdedtv2.cxx +++ b/svx/source/svdraw/svdedtv2.cxx @@ -2052,7 +2052,7 @@ void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) #if HAVE_FEATURE_PDFIUM aLogicRect = pGraf->GetLogicRect(); ImpSdrPdfImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect, aGraphic); - if (pGraf->getEmbeddedPageNumber() < aFilter.GetPageCount()) + if (aGraphic.getPageNumber() < aFilter.GetPageCount()) { nInsAnz = aFilter.DoImport(*pOL, nInsPos, aGraphic.getPageNumber(), pProgrInfo); } commit 001ef8612d938299781dec4730ae702082d18a24 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri May 1 17:20:26 2020 +0200 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Wed Jul 29 18:32:22 2020 +0200 move unit conversions to UnitConversion, add convertPointToMm100 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93332 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit 09e28008376e2f2a187067409d3076e81eba022e) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95783 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit fab4420f23ae77f8c7266d4b4d44313f2e3129d8) Change-Id: I3e5a4632e9809562885c1e0ec5c5262acec145d0 diff --git a/include/tools/UnitConversion.hxx b/include/tools/UnitConversion.hxx new file mode 100644 index 000000000000..e59077d8a5fa --- /dev/null +++ b/include/tools/UnitConversion.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +constexpr sal_Int64 convertTwipToMm100(sal_Int64 n) +{ + return (n >= 0) ? (n * 127 + 36) / 72 : (n * 127 - 36) / 72; +} + +constexpr sal_Int64 convertPointToMm100(sal_Int64 n) { return convertTwipToMm100(n * 20); } + +constexpr sal_Int64 convertMm100ToTwip(sal_Int64 n) +{ + return (n >= 0) ? (n * 72 + 63) / 127 : (n * 72 - 63) / 127; +} + +// Convert PPT's "master unit" (1/576 inch) to twips +constexpr sal_Int64 convertMasterUnitToTwip(sal_Int64 n) { return n * 2540.0 / 576.0; } + +// Convert twips to PPT's "master unit" +constexpr sal_Int64 convertTwipToMasterUnit(sal_Int64 n) { return n / (2540.0 / 576.0); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/mapunit.hxx b/include/tools/mapunit.hxx index 2209f4d35261..6112bc7ef461 100644 --- a/include/tools/mapunit.hxx +++ b/include/tools/mapunit.hxx @@ -21,6 +21,7 @@ #define INCLUDED_TOOLS_MAPUNIT_HXX #include <sal/types.h> +#include <tools/UnitConversion.hxx> enum class MapUnit { @@ -34,16 +35,6 @@ enum class MapUnit LASTENUMDUMMY // used as an error return }; -constexpr sal_Int64 convertTwipToMm100(sal_Int64 n) -{ - return (n >= 0)? (n*127+36)/72: (n*127-36)/72; -} - -constexpr sal_Int64 convertMm100ToTwip(sal_Int64 n) -{ - return (n >= 0)? (n*72+63)/127: (n*72-63)/127; -} - #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit e0af7e85eb3b99cceb8302b3ff0a7656816b6174 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu Apr 30 07:54:46 2020 +0200 Commit: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> CommitDate: Wed Jul 29 14:31:55 2020 +0200 test import and export of multi-page PDF with PDFium filter The test checks that the exported PDFs contain embedded PDF for different pages. Change-Id: I4e5cd108d8597851d86aa774efbde0d4f2b9d2ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93322 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95701 Tested-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf new file mode 100644 index 000000000000..af665fcba8a0 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index 60bfdff7be45..9b2268f3bf8e 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -18,6 +18,7 @@ #include <com/sun/star/frame/XStorable.hpp> #include <com/sun/star/view/XPrintable.hpp> +#include <comphelper/scopeguard.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/propertysequence.hxx> #include <cppuhelper/implbase.hxx> @@ -132,6 +133,8 @@ public: void testLargePage(); void testVersion15(); void testDefaultVersion(); + void testMultiPagePDF(); + CPPUNIT_TEST_SUITE(PdfExportTest); CPPUNIT_TEST(testTdf106059); @@ -170,6 +173,7 @@ public: CPPUNIT_TEST(testLargePage); CPPUNIT_TEST(testVersion15); CPPUNIT_TEST(testDefaultVersion); + CPPUNIT_TEST(testMultiPagePDF); CPPUNIT_TEST_SUITE_END(); }; @@ -1807,6 +1811,139 @@ void PdfExportTest::testVersion15() CPPUNIT_ASSERT_EQUAL(15, nFileVersion); } +// Check round-trip of importing and exporting the PDF with PDFium filter, +// which imports the PDF document as multiple PDFs as graphic object. +// Each page in the document has one PDF graphic object which content is +// the correcponding page in the PDF. When such a document is exported, +// the PDF graphic gets embedded into the exported PDF document (as a +// Form XObject). +void PdfExportTest::testMultiPagePDF() +{ +// 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 + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "SimpleMultiPagePDF.pdf"; + mxComponent = loadFromDesktop(aURL); + CPPUNIT_ASSERT(mxComponent.is()); + + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aPages.size()); + + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"); + CPPUNIT_ASSERT(pResources); + + auto pXObjects = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject")); + CPPUNIT_ASSERT(pXObjects); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), pXObjects->GetItems().size()); // 3 PDFs as Form XObjects + + std::vector<OString> rIDs; + for (auto const & rPair : pXObjects->GetItems()) { + rIDs.push_back(rPair.first); + } + + // Let's check the embedded PDF pages - just make sure the size differs, + // which should indicate we don't have 3 times the same page. + + { // embedded PDF page 1 + vcl::filter::PDFObjectElement* pXObject1 = pXObjects->LookupObject(rIDs[0]); + CPPUNIT_ASSERT(pXObject1); + CPPUNIT_ASSERT_EQUAL(OString("Im19"), rIDs[0]); + + auto pSubtype1 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject1->Lookup("Subtype")); + CPPUNIT_ASSERT(pSubtype1); + CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype1->GetValue()); + + auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject1->Lookup("Resources")); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject")); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected. + CPPUNIT_ASSERT_EQUAL(sal_uInt64(230), rObjectStream.remainingSize()); + } + + { // embedded PDF page 2 + vcl::filter::PDFObjectElement* pXObject2 = pXObjects->LookupObject(rIDs[1]); + CPPUNIT_ASSERT(pXObject2); + CPPUNIT_ASSERT_EQUAL(OString("Im34"), rIDs[1]); + + auto pSubtype2 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject2->Lookup("Subtype")); + CPPUNIT_ASSERT(pSubtype2); + CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype2->GetValue()); + + auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject2->Lookup("Resources")); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject")); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected + CPPUNIT_ASSERT_EQUAL(sal_uInt64(309), rObjectStream.remainingSize()); + } + + { // embedded PDF page 3 + vcl::filter::PDFObjectElement* pXObject3 = pXObjects->LookupObject(rIDs[2]); + CPPUNIT_ASSERT(pXObject3); + CPPUNIT_ASSERT_EQUAL(OString("Im4"), rIDs[2]); + + auto pSubtype3 = dynamic_cast<vcl::filter::PDFNameElement*>(pXObject3->Lookup("Subtype")); + CPPUNIT_ASSERT(pSubtype3); + CPPUNIT_ASSERT_EQUAL(OString("Form"), pSubtype3->GetValue()); + + auto pXObjectResources = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObject3->Lookup("Resources")); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast<vcl::filter::PDFDictionaryElement*>(pXObjectResources->LookupElement("XObject")); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected + CPPUNIT_ASSERT_EQUAL(sal_uInt64(193), rObjectStream.remainingSize()); + } +#endif +} + CPPUNIT_TEST_SUITE_REGISTRATION(PdfExportTest); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits