summaryrefslogtreecommitdiffstats
path: root/sd/qa/unit/SdrPdfImportTest.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sd/qa/unit/SdrPdfImportTest.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.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.cxx311
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: */