[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - include/vcl vcl/CppunitTest_vcl_pdfium_library_test.mk vcl/Module_vcl.mk vcl/qa vcl/source

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Mon Jun 29 18:35:54 UTC 2020


 include/vcl/filter/PDFiumLibrary.hxx       |   59 +++++++++++++++-
 vcl/CppunitTest_vcl_pdfium_library_test.mk |   45 ++++++++++++
 vcl/Module_vcl.mk                          |    1 
 vcl/qa/cppunit/PDFiumLibraryTest.cxx       |  105 +++++++++++++++++++++++++++++
 vcl/source/pdf/PDFiumLibrary.cxx           |   82 ++++++++++++++++++++++
 5 files changed, 289 insertions(+), 3 deletions(-)

New commits:
commit 046a23fd473bd497f08d35d9588a09aa192b9763
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon Jun 15 13:50:18 2020 +0200
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Jun 29 20:35:21 2020 +0200

    vcl: wrap PDFium types in c++ classes to ease lifecycle management
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96753
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    (cherry picked from commit 526b09604399a71c17b15ee80bab48967563bfb6)
    
    Change-Id: Idd33dfe752a22b6628750c06f02e9467a69802bc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97435
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx
index bc7912c17e81..6dde31f2927b 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -14,24 +14,79 @@
 
 #if HAVE_FEATURE_PDFIUM
 
+#include <vcl/dllapi.h>
+
 #include <memory>
 #include <rtl/instance.hxx>
-#include <vcl/dllapi.h>
+#include <basegfx/vector/b2dsize.hxx>
+#include <rtl/ustring.hxx>
+
+#include <fpdf_doc.h>
 
 namespace vcl::pdf
 {
+class PDFiumDocument;
+
 class VCL_DLLPUBLIC PDFium final
 {
 private:
     PDFium(const PDFium&) = delete;
     PDFium& operator=(const PDFium&) = delete;
 
+    OUString maLastError;
+
 public:
     PDFium();
     ~PDFium();
+
+    OUString getLastError() { return maLastError; }
+
+    std::unique_ptr<PDFiumDocument> openDocument(const void* pData, int nSize);
+};
+
+class VCL_DLLPUBLIC PDFiumPage final
+{
+private:
+    FPDF_PAGE mpPage;
+
+private:
+    PDFiumPage(const PDFiumPage&) = delete;
+    PDFiumPage& operator=(const PDFiumPage&) = delete;
+
+public:
+    PDFiumPage(FPDF_PAGE pPage)
+        : mpPage(pPage)
+    {
+    }
+
+    ~PDFiumPage()
+    {
+        if (mpPage)
+            FPDF_ClosePage(mpPage);
+    }
+};
+
+class VCL_DLLPUBLIC PDFiumDocument final
+{
+private:
+    FPDF_DOCUMENT mpPdfDocument;
+
+private:
+    PDFiumDocument(const PDFiumDocument&) = delete;
+    PDFiumDocument& operator=(const PDFiumDocument&) = delete;
+
+public:
+    PDFiumDocument(FPDF_DOCUMENT pPdfDocument);
+    ~PDFiumDocument();
+
+    // Page size in points
+    basegfx::B2DSize getPageSize(int nIndex);
+    int getPageCount();
+
+    std::unique_ptr<PDFiumPage> openPage(int nIndex);
 };
 
-struct PDFiumLibrary : public rtl::StaticWithInit<std::shared_ptr<PDFium>, PDFiumLibrary>
+struct PDFiumLibrary final : public rtl::StaticWithInit<std::shared_ptr<PDFium>, PDFiumLibrary>
 {
     std::shared_ptr<PDFium> operator()() { return std::make_shared<PDFium>(); }
 };
diff --git a/vcl/CppunitTest_vcl_pdfium_library_test.mk b/vcl/CppunitTest_vcl_pdfium_library_test.mk
new file mode 100644
index 000000000000..0f4a480c8254
--- /dev/null
+++ b/vcl/CppunitTest_vcl_pdfium_library_test.mk
@@ -0,0 +1,45 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,vcl_pdfium_library_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,vcl_pdfium_library_test, \
+    vcl/qa/cppunit/PDFiumLibraryTest \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,vcl_pdfium_library_test))
+
+$(eval $(call gb_CppunitTest_use_libraries,vcl_pdfium_library_test, \
+	basegfx \
+	comphelper \
+	cppu \
+	cppuhelper \
+	sal \
+	test \
+	unotest \
+	utl \
+	tl \
+	vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,vcl_pdfium_library_test, \
+	boost_headers \
+	$(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,vcl_pdfium_library_test))
+
+$(eval $(call gb_CppunitTest_use_ure,vcl_pdfium_library_test))
+$(eval $(call gb_CppunitTest_use_vcl,vcl_pdfium_library_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,vcl_pdfium_library_test,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,vcl_pdfium_library_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index a67a38c96b8a..8f4fa5adf6d6 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -204,6 +204,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
 	CppunitTest_vcl_png_test \
 	CppunitTest_vcl_widget_definition_reader_test \
 	CppunitTest_vcl_backend_test \
+	CppunitTest_vcl_pdfium_library_test \
 ))
 
 ifeq ($(USING_X11),TRUE)
diff --git a/vcl/qa/cppunit/PDFiumLibraryTest.cxx b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
new file mode 100644
index 000000000000..422325aa9b1d
--- /dev/null
+++ b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
@@ -0,0 +1,105 @@
+/* -*- 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 <config_features.h>
+
+#if HAVE_FEATURE_PDFIUM
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <unotest/directories.hxx>
+
+#include <vcl/graph.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/stream.hxx>
+
+#include <vcl/filter/PDFiumLibrary.hxx>
+
+class PDFiumLibraryTest : public test::BootstrapFixtureBase
+{
+    OUString getFullUrl(const OUString& sFileName)
+    {
+        return m_directories.getURLFromSrc("/vcl/qa/cppunit/data/") + sFileName;
+    }
+
+    void testDocument();
+    void testPages();
+
+    CPPUNIT_TEST_SUITE(PDFiumLibraryTest);
+    CPPUNIT_TEST(testDocument);
+    CPPUNIT_TEST(testPages);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void PDFiumLibraryTest::testDocument()
+{
+    OUString aURL = getFullUrl("Pangram.pdf");
+    SvFileStream aStream(aURL, StreamMode::READ);
+    GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+    Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+    aGraphic.makeAvailable();
+
+    auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+    CPPUNIT_ASSERT(pVectorGraphicData);
+    CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf,
+                         pVectorGraphicData->getVectorGraphicDataType());
+
+    const void* pData = pVectorGraphicData->getVectorGraphicDataArray().getConstArray();
+    int nLength = pVectorGraphicData->getVectorGraphicDataArrayLength();
+
+    auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+    CPPUNIT_ASSERT(pPdfium);
+    auto pDocument = pPdfium->openDocument(pData, nLength);
+    CPPUNIT_ASSERT(pDocument);
+
+    CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+    auto aSize = pDocument->getPageSize(0);
+    CPPUNIT_ASSERT_EQUAL(612.0, aSize.getX());
+    CPPUNIT_ASSERT_EQUAL(792.0, aSize.getY());
+
+    auto pPage = pDocument->openPage(0);
+    CPPUNIT_ASSERT(pPage);
+}
+
+void PDFiumLibraryTest::testPages()
+{
+    OUString aURL = getFullUrl("Pangram.pdf");
+    SvFileStream aStream(aURL, StreamMode::READ);
+    GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
+    Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
+    aGraphic.makeAvailable();
+
+    auto pVectorGraphicData = aGraphic.getVectorGraphicData();
+    CPPUNIT_ASSERT(pVectorGraphicData);
+    CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf,
+                         pVectorGraphicData->getVectorGraphicDataType());
+
+    const void* pData = pVectorGraphicData->getVectorGraphicDataArray().getConstArray();
+    int nLength = pVectorGraphicData->getVectorGraphicDataArrayLength();
+
+    auto pPdfium = vcl::pdf::PDFiumLibrary::get();
+    auto pDocument = pPdfium->openDocument(pData, nLength);
+    CPPUNIT_ASSERT(pDocument);
+
+    CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
+
+    auto pPage = pDocument->openPage(0);
+    CPPUNIT_ASSERT(pPage);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PDFiumLibraryTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index 604807524bf9..3ea7e5b49c4a 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -13,7 +13,7 @@
 #if HAVE_FEATURE_PDFIUM
 
 #include <vcl/filter/PDFiumLibrary.hxx>
-#include <fpdf_doc.h>
+#include <fpdf_edit.h>
 
 namespace vcl::pdf
 {
@@ -29,6 +29,86 @@ PDFium::PDFium()
 
 PDFium::~PDFium() { FPDF_DestroyLibrary(); }
 
+std::unique_ptr<PDFiumDocument> PDFium::openDocument(const void* pData, int nSize)
+{
+    maLastError = OUString();
+    std::unique_ptr<PDFiumDocument> pPDFiumDocument;
+
+    FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, /*password=*/nullptr);
+
+    if (!pDocument)
+    {
+        switch (FPDF_GetLastError())
+        {
+            case FPDF_ERR_SUCCESS:
+                maLastError = "Success";
+                break;
+            case FPDF_ERR_UNKNOWN:
+                maLastError = "Unknown error";
+                break;
+            case FPDF_ERR_FILE:
+                maLastError = "File not found";
+                break;
+            case FPDF_ERR_FORMAT:
+                maLastError = "Input is not a PDF format";
+                break;
+            case FPDF_ERR_PASSWORD:
+                maLastError = "Incorrect password or password is required";
+                break;
+            case FPDF_ERR_SECURITY:
+                maLastError = "Security error";
+                break;
+            case FPDF_ERR_PAGE:
+                maLastError = "Content error";
+                break;
+            default:
+                break;
+        }
+    }
+    else
+    {
+        pPDFiumDocument = std::make_unique<PDFiumDocument>(pDocument);
+    }
+
+    return pPDFiumDocument;
+}
+
+PDFiumDocument::PDFiumDocument(FPDF_DOCUMENT pPdfDocument)
+    : mpPdfDocument(pPdfDocument)
+{
+}
+
+PDFiumDocument::~PDFiumDocument()
+{
+    if (mpPdfDocument)
+        FPDF_CloseDocument(mpPdfDocument);
+}
+
+std::unique_ptr<PDFiumPage> PDFiumDocument::openPage(int nIndex)
+{
+    std::unique_ptr<PDFiumPage> pPDFiumPage;
+    FPDF_PAGE pPage = FPDF_LoadPage(mpPdfDocument, nIndex);
+    if (pPage)
+    {
+        pPDFiumPage = std::make_unique<PDFiumPage>(pPage);
+    }
+    return pPDFiumPage;
+}
+
+basegfx::B2DSize PDFiumDocument::getPageSize(int nIndex)
+{
+    basegfx::B2DSize aSize;
+    double fPageWidth = 0;
+    double fPageHeight = 0;
+    if (FPDF_GetPageSizeByIndex(mpPdfDocument, nIndex, &fPageWidth, &fPageHeight))
+    {
+        aSize = basegfx::B2DSize(fPageWidth, fPageHeight);
+    }
+    return aSize;
+}
+
+int PDFiumDocument::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
+
 } // end vcl::pdf
 
 #endif // HAVE_FEATURE_PDFIUM


More information about the Libreoffice-commits mailing list