diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/qa/unit/SdrPdfImportTest.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | sd/qa/unit/SdrPdfImportTest.cxx | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/sd/qa/unit/SdrPdfImportTest.cxx b/sd/qa/unit/SdrPdfImportTest.cxx new file mode 100644 index 000000000..ba3c42e92 --- /dev/null +++ b/sd/qa/unit/SdrPdfImportTest.cxx @@ -0,0 +1,311 @@ +/* -*- 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 <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> + +#include <comphelper/scopeguard.hxx> +#include <comphelper/propertysequence.hxx> + +#include <unotools/tempfile.hxx> +#include <unotools/mediadescriptor.hxx> +#include <tools/stream.hxx> +#include <svx/svdograf.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> +#include <vcl/pdf/PDFAnnotationSubType.hxx> + +#include <DrawDocShell.hxx> +#include <ViewShell.hxx> +#include <sdpage.hxx> +#include <unomodel.hxx> + +#include <com/sun/star/frame/Desktop.hpp> + +using namespace css; + +namespace +{ +class EnvVarGuard +{ +public: + EnvVarGuard(const char* var, const char* val) + { + if (getenv(var) == nullptr) + { + sVar = var; + SetEnv(sVar, val); + } + } + ~EnvVarGuard() + { + if (sVar) + SetEnv(sVar, nullptr); + } + +private: + static void SetEnv(const char* var, const char* val) + { +#ifdef _WIN32 + if (!val) + val = ""; // remove + _putenv_s(var, val); +#else + if (val) + setenv(var, val, false); + else + unsetenv(var); +#endif + } + + const char* sVar = nullptr; +}; +} + +class SdrPdfImportTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +protected: + uno::Reference<lang::XComponent> mxComponent; + +public: + virtual void setUp() override; + virtual void tearDown() override; +}; + +void SdrPdfImportTest::setUp() +{ + test::BootstrapFixture::setUp(); + + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void SdrPdfImportTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + test::BootstrapFixture::tearDown(); +} + +// Load the PDF in Draw, which will load the PDF as an Graphic, then +// mark the graphic object and trigger "break" function. This should +// convert the PDF content into objects/shapes. +CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportSimpleText) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return; + } + + // We need to enable PDFium import (and make sure to disable after the test) + EnvVarGuard UsePDFiumGuard("LO_IMPORT_USE_PDFIUM", "1"); + + mxComponent = loadFromDesktop(m_directories.getURLFromSrc(u"sd/qa/unit/data/SimplePDF.pdf")); + auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get()); + sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + + // Get the first page - there should be only one. + SdPage* pPage = pViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + + // Check there is one object on the page only + CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount()); + + // Get the first object - there should be only one. + SdrObject* pObject = pPage->GetObj(0); + CPPUNIT_ASSERT(pObject); + + // Check the object is a graphic object + SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject); + CPPUNIT_ASSERT(pGraphicObject); + // Check the graphic is a vector graphic and that it is PDF + Graphic aGraphic = pGraphicObject->GetGraphic(); + auto const& pVectorGraphicData = aGraphic.getVectorGraphicData(); + CPPUNIT_ASSERT(pVectorGraphicData); + CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType()); + + // Mark the object + SdrView* pView = pViewShell->GetView(); + pView->MarkObj(pObject, pView->GetSdrPageView()); + + // Execute the break operation - to turn the PDF into shapes/objects + pViewShell->GetDrawView()->DoImportMarkedMtf(); + + // Check there is one object on the page only + CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount()); + + // Get the object + SdrObject* pImportedObject = pPage->GetObj(0); + CPPUNIT_ASSERT(pImportedObject); + + // Check the object position + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(2011, 2102), Size(2106 + 1, 298 + 1)), + pImportedObject->GetLogicRect()); + + // Object should be a text object containing one paragraph with + // content "This is PDF!" + + SdrTextObj* pTextObject = dynamic_cast<SdrTextObj*>(pImportedObject); + CPPUNIT_ASSERT(pTextObject); + OutlinerParaObject* pOutlinerParagraphObject = pTextObject->GetOutlinerParaObject(); + const EditTextObject& aEdit = pOutlinerParagraphObject->GetTextObject(); + OUString sText = aEdit.GetText(0); + CPPUNIT_ASSERT_EQUAL(OUString("This is PDF!"), sText); +} + +CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testAnnotationsImportExport) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return; + } + + // We need to enable PDFium import (and make sure to disable after the test) + EnvVarGuard UsePDFiumGuard("LO_IMPORT_USE_PDFIUM", "1"); + + EnvVarGuard DisablePDFCompressionGuard("VCL_DEBUG_DISABLE_PDFCOMPRESSION", "1"); + + auto pPdfiumLibrary = vcl::pdf::PDFiumLibrary::get(); + + mxComponent + = loadFromDesktop(m_directories.getURLFromSrc(u"sd/qa/unit/data/PdfWithAnnotation.pdf")); + auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get()); + sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pViewShell); + + BinaryDataContainer aContainer; + + { + // Get the first page - there should be only one. + SdPage* pPage = pViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + + // Check the number of annotations + CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->getAnnotations().size()); + + // Get the first object - there should be only one. + SdrObject* pObject = pPage->GetObj(0); + CPPUNIT_ASSERT(pObject); + + // Check the object is a graphic object + SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject); + CPPUNIT_ASSERT(pGraphicObject); + + // Check the graphic is a vector graphic and that it is PDF + Graphic aGraphic = pGraphicObject->GetGraphic(); + auto const& pVectorGraphicData = aGraphic.getVectorGraphicData(); + CPPUNIT_ASSERT(pVectorGraphicData); + CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType()); + + // Write the PDF + aContainer = pVectorGraphicData->getBinaryDataContainer(); + } + + { // check graphic PDF has annotations + + CPPUNIT_ASSERT_EQUAL(false, aContainer.isEmpty()); + + auto pPDFDocument + = pPdfiumLibrary->openDocument(aContainer.getData(), aContainer.getSize(), OString()); + auto pPDFPage = pPDFDocument->openPage(0); + + CPPUNIT_ASSERT_EQUAL(2, pPDFPage->getAnnotationCount()); + + auto pPDFAnnotation1 = pPDFPage->getAnnotation(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, + pPDFAnnotation1->getSubType()); // Text annotation + + auto pPDFAnnotation2 = pPDFPage->getAnnotation(1); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, + pPDFAnnotation2->getSubType()); // Pop-up annotation + } + + { // save as PDF and check annotations + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence<beans::PropertyValue> aFilterData( + comphelper::InitPropertySequence({ { "ExportBookmarks", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + mxComponent->dispose(); + + SvFileStream aFile(aTempFile.GetURL(), StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFile); + + // Check PDF for annotations + auto pPDFDocument + = pPdfiumLibrary->openDocument(aMemory.GetData(), aMemory.GetSize(), OString()); + CPPUNIT_ASSERT(pPDFDocument); + CPPUNIT_ASSERT_EQUAL(1, pPDFDocument->getPageCount()); + + auto pPDFPage = pPDFDocument->openPage(0); + CPPUNIT_ASSERT(pPDFPage); + + CPPUNIT_ASSERT_EQUAL(2, pPDFPage->getAnnotationCount()); + + auto pPDFAnnotation1 = pPDFPage->getAnnotation(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, + pPDFAnnotation1->getSubType()); // Text annotation + + auto pPDFAnnotation2 = pPDFPage->getAnnotation(1); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, + pPDFAnnotation2->getSubType()); // Pop-up annotation + + // Load document again + mxComponent = loadFromDesktop(aTempFile.GetURL()); + auto pNewImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get()); + sd::ViewShell* pNewViewShell = pNewImpressDocument->GetDocShell()->GetViewShell(); + CPPUNIT_ASSERT(pNewViewShell); + + SdPage* pPage = pNewViewShell->GetActualPage(); + CPPUNIT_ASSERT(pPage); + + // We expect only 1 annotation in the document because the PDF + // annotations are dependent on each-other: + // parent annotation "Text" and the child annotation "Pop-up" + + CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->getAnnotations().size()); + + // check annotation + auto xAnnotation = pPage->getAnnotations().at(0); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(90.33, xAnnotation->getPosition().X, 1E-3); + CPPUNIT_ASSERT_DOUBLES_EQUAL(12.07, xAnnotation->getPosition().Y, 1E-3); + + CPPUNIT_ASSERT_EQUAL(OUString("TheAuthor"), xAnnotation->getAuthor()); + CPPUNIT_ASSERT_EQUAL(OUString(), xAnnotation->getInitials()); + + auto xText = xAnnotation->getTextRange(); + + CPPUNIT_ASSERT_EQUAL(OUString("This is the annotation text!"), xText->getString()); + + auto aDateTime = xAnnotation->getDateTime(); + CPPUNIT_ASSERT_EQUAL(sal_Int16(2020), aDateTime.Year); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), aDateTime.Month); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(18), aDateTime.Day); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(12), aDateTime.Hours); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(11), aDateTime.Minutes); + CPPUNIT_ASSERT_EQUAL(sal_uInt16(53), aDateTime.Seconds); + CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aDateTime.NanoSeconds); + CPPUNIT_ASSERT_EQUAL(false, bool(aDateTime.IsUTC)); + } +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |