diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2020-06-15 13:50:18 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2020-06-20 13:10:47 +0200 |
commit | 526b09604399a71c17b15ee80bab48967563bfb6 (patch) | |
tree | e6ca22f084998aa0453627ac352f4b66be421cdb | |
parent | 24ad718a94eee2103a5a5e995619a844b8670f24 (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.hxx | 59 | ||||
-rw-r--r-- | vcl/CppunitTest_vcl_pdfium_library_test.mk | 45 | ||||
-rw-r--r-- | vcl/Module_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/qa/cppunit/PDFiumLibraryTest.cxx | 105 | ||||
-rw-r--r-- | vcl/source/pdf/PDFiumLibrary.cxx | 81 |
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 |