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.vajng...@collabora.co.uk> AuthorDate: Mon Jun 15 13:50:18 2020 +0200 Commit: Tomaž Vajngerl <qui...@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 <qui...@gmail.com> (cherry picked from commit 526b09604399a71c17b15ee80bab48967563bfb6) Change-Id: Idd33dfe752a22b6628750c06f02e9467a69802bc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97435 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@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 _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits