[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 5 commits - include/tools include/vcl sd/inc sd/source svx/source vcl/CppunitTest_vcl_graphic_test.mk vcl/Library_vcl.mk vcl/qa vcl/source

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Wed Jul 29 18:44:26 UTC 2020


 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.vajngerl at collabora.co.uk>
AuthorDate: Thu May 7 22:01:22 2020 +0200
Commit:     Tomaž Vajngerl <tomaz.vajngerl at 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 <quikee at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit efba780d6155317b592b6f5f73945a7851ec4d3b)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95801
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at 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.vajngerl at collabora.co.uk>
AuthorDate: Sat May 23 16:52:09 2020 +0200
Commit:     Tomaž Vajngerl <tomaz.vajngerl at 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 <quikee at gmail.com>
    (cherry picked from commit beacca27ecc1b1463477c644e36a7e5815053433)
    
    Change-Id: I71d7986044208b6c733c1d46db7bf84bc6254915
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95798
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at 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.vajngerl at collabora.co.uk>
AuthorDate: Sun May 31 20:25:11 2020 +0200
Commit:     Tomaž Vajngerl <tomaz.vajngerl at 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 <quikee at gmail.com>
    (cherry picked from commit 573de30566e4477c8dc09abec08f1082d16c74bc)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95800
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at 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.vajngerl at collabora.co.uk>
AuthorDate: Fri May 1 17:20:26 2020 +0200
Commit:     Tomaž Vajngerl <tomaz.vajngerl at 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 <quikee at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 09e28008376e2f2a187067409d3076e81eba022e)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95783
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at 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.vajngerl at collabora.co.uk>
AuthorDate: Thu Apr 30 07:54:46 2020 +0200
Commit:     Tomaž Vajngerl <tomaz.vajngerl at 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 <quikee at gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95701
    Tested-by: Tomaž Vajngerl <quikee at 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);
 
 }


More information about the Libreoffice-commits mailing list