summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2020-06-15 13:50:18 +0200
committerTomaž Vajngerl <quikee@gmail.com>2020-06-20 13:10:47 +0200
commit526b09604399a71c17b15ee80bab48967563bfb6 (patch)
treee6ca22f084998aa0453627ac352f4b66be421cdb
parent24ad718a94eee2103a5a5e995619a844b8670f24 (diff)
vcl: wrap PDFium types in c++ classes to ease lifecycle management
Change-Id: Idd33dfe752a22b6628750c06f02e9467a69802bc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96753 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/vcl/filter/PDFiumLibrary.hxx59
-rw-r--r--vcl/CppunitTest_vcl_pdfium_library_test.mk45
-rw-r--r--vcl/Module_vcl.mk1
-rw-r--r--vcl/qa/cppunit/PDFiumLibraryTest.cxx105
-rw-r--r--vcl/source/pdf/PDFiumLibrary.cxx81
5 files changed, 288 insertions, 3 deletions
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 aaa05759d39d..08704e2b6254 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -207,6 +207,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
CppunitTest_vcl_backend_test \
CppunitTest_vcl_blocklistparser_test \
CppunitTest_vcl_type_serializer_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..edd7fe9f5283 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,85 @@ 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;
+ FS_SIZEF aPDFSize;
+ if (FPDF_GetPageSizeByIndexF(mpPdfDocument, nIndex, &aPDFSize))
+ {
+ aSize = basegfx::B2DSize(aPDFSize.width, aPDFSize.height);
+ }
+ return aSize;
+}
+
+int PDFiumDocument::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
+
} // end vcl::pdf
#endif // HAVE_FEATURE_PDFIUM