Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / qa / unit / SdrPdfImportTest.cxx
blob87225f66eac2d32c0a8346f215d6bb686d49fcdc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <test/unoapi_test.hxx>
12 #include <comphelper/scopeguard.hxx>
13 #include <comphelper/propertysequence.hxx>
15 #include <unotools/tempfile.hxx>
16 #include <unotools/mediadescriptor.hxx>
17 #include <svx/svdograf.hxx>
18 #include <editeng/outlobj.hxx>
19 #include <editeng/editobj.hxx>
20 #include <vcl/filter/PDFiumLibrary.hxx>
21 #include <vcl/pdf/PDFAnnotationSubType.hxx>
23 #include <DrawDocShell.hxx>
24 #include <ViewShell.hxx>
25 #include <sdpage.hxx>
26 #include <unomodel.hxx>
28 using namespace css;
30 namespace
32 class EnvVarGuard
34 public:
35 EnvVarGuard(const char* var, const char* val)
37 if (getenv(var) == nullptr)
39 sVar = var;
40 SetEnv(sVar, val);
43 ~EnvVarGuard()
45 if (sVar)
46 SetEnv(sVar, nullptr);
49 private:
50 static void SetEnv(const char* var, const char* val)
52 #ifdef _WIN32
53 if (!val)
54 val = ""; // remove
55 _putenv_s(var, val);
56 #else
57 if (val)
58 setenv(var, val, false);
59 else
60 unsetenv(var);
61 #endif
64 const char* sVar = nullptr;
68 class SdrPdfImportTest : public UnoApiTest
70 public:
71 SdrPdfImportTest()
72 : UnoApiTest("/sd/qa/unit/data/")
77 // Load the PDF in Draw, which will load the PDF as an Graphic, then
78 // mark the graphic object and trigger "break" function. This should
79 // convert the PDF content into objects/shapes.
80 CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testImportSimpleText)
82 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
83 if (!pPdfium)
85 return;
88 // We need to enable PDFium import (and make sure to disable after the test)
89 EnvVarGuard UsePDFiumGuard("LO_IMPORT_USE_PDFIUM", "1");
91 loadFromURL(u"SimplePDF.pdf");
92 auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
93 sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell();
94 CPPUNIT_ASSERT(pViewShell);
96 // Get the first page - there should be only one.
97 SdPage* pPage = pViewShell->GetActualPage();
98 CPPUNIT_ASSERT(pPage);
100 // Check there is one object on the page only
101 CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount());
103 // Get the first object - there should be only one.
104 SdrObject* pObject = pPage->GetObj(0);
105 CPPUNIT_ASSERT(pObject);
107 // Check the object is a graphic object
108 SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
109 CPPUNIT_ASSERT(pGraphicObject);
110 // Check the graphic is a vector graphic and that it is PDF
111 Graphic aGraphic = pGraphicObject->GetGraphic();
112 auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
113 CPPUNIT_ASSERT(pVectorGraphicData);
114 CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
116 // Mark the object
117 SdrView* pView = pViewShell->GetView();
118 pView->MarkObj(pObject, pView->GetSdrPageView());
120 // Execute the break operation - to turn the PDF into shapes/objects
121 pViewShell->GetDrawView()->DoImportMarkedMtf();
123 // Check there is one object on the page only
124 CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->GetObjCount());
126 // Get the object
127 SdrObject* pImportedObject = pPage->GetObj(0);
128 CPPUNIT_ASSERT(pImportedObject);
130 // Check the object position
131 CPPUNIT_ASSERT_EQUAL(tools::Rectangle(Point(2011, 2102), Size(2106 + 1, 298 + 1)),
132 pImportedObject->GetLogicRect());
134 // Object should be a text object containing one paragraph with
135 // content "This is PDF!"
137 SdrTextObj* pTextObject = DynCastSdrTextObj(pImportedObject);
138 CPPUNIT_ASSERT(pTextObject);
139 OutlinerParaObject* pOutlinerParagraphObject = pTextObject->GetOutlinerParaObject();
140 const EditTextObject& aEdit = pOutlinerParagraphObject->GetTextObject();
141 OUString sText = aEdit.GetText(0);
142 CPPUNIT_ASSERT_EQUAL(OUString("This is PDF!"), sText);
145 CPPUNIT_TEST_FIXTURE(SdrPdfImportTest, testAnnotationsImportExport)
147 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
148 if (!pPdfium)
150 return;
153 // We need to enable PDFium import (and make sure to disable after the test)
154 EnvVarGuard UsePDFiumGuard("LO_IMPORT_USE_PDFIUM", "1");
156 EnvVarGuard DisablePDFCompressionGuard("VCL_DEBUG_DISABLE_PDFCOMPRESSION", "1");
158 auto pPdfiumLibrary = vcl::pdf::PDFiumLibrary::get();
160 loadFromURL(u"PdfWithAnnotation.pdf");
161 auto pImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
162 sd::ViewShell* pViewShell = pImpressDocument->GetDocShell()->GetViewShell();
163 CPPUNIT_ASSERT(pViewShell);
165 BinaryDataContainer aContainer;
168 // Get the first page - there should be only one.
169 SdPage* pPage = pViewShell->GetActualPage();
170 CPPUNIT_ASSERT(pPage);
172 // Check the number of annotations
173 CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->getAnnotations().size());
175 // Get the first object - there should be only one.
176 SdrObject* pObject = pPage->GetObj(0);
177 CPPUNIT_ASSERT(pObject);
179 // Check the object is a graphic object
180 SdrGrafObj* pGraphicObject = dynamic_cast<SdrGrafObj*>(pObject);
181 CPPUNIT_ASSERT(pGraphicObject);
183 // Check the graphic is a vector graphic and that it is PDF
184 Graphic aGraphic = pGraphicObject->GetGraphic();
185 auto const& pVectorGraphicData = aGraphic.getVectorGraphicData();
186 CPPUNIT_ASSERT(pVectorGraphicData);
187 CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
189 // Write the PDF
190 aContainer = pVectorGraphicData->getBinaryDataContainer();
193 { // check graphic PDF has annotations
195 CPPUNIT_ASSERT_EQUAL(false, aContainer.isEmpty());
197 auto pPDFDocument
198 = pPdfiumLibrary->openDocument(aContainer.getData(), aContainer.getSize(), OString());
199 auto pPDFPage = pPDFDocument->openPage(0);
201 CPPUNIT_ASSERT_EQUAL(2, pPDFPage->getAnnotationCount());
203 auto pPDFAnnotation1 = pPDFPage->getAnnotation(0);
204 CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text,
205 pPDFAnnotation1->getSubType()); // Text annotation
207 auto pPDFAnnotation2 = pPDFPage->getAnnotation(1);
208 CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup,
209 pPDFAnnotation2->getSubType()); // Pop-up annotation
212 { // save as PDF and check annotations
213 uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
214 utl::MediaDescriptor aMediaDescriptor;
215 aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
216 uno::Sequence<beans::PropertyValue> aFilterData(
217 comphelper::InitPropertySequence({ { "ExportBookmarks", uno::Any(true) } }));
218 aMediaDescriptor["FilterData"] <<= aFilterData;
219 xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
221 // Check PDF for annotations
222 auto pPDFDocument = parsePDFExport();
223 CPPUNIT_ASSERT(pPDFDocument);
224 CPPUNIT_ASSERT_EQUAL(1, pPDFDocument->getPageCount());
226 auto pPDFPage = pPDFDocument->openPage(0);
227 CPPUNIT_ASSERT(pPDFPage);
229 CPPUNIT_ASSERT_EQUAL(2, pPDFPage->getAnnotationCount());
231 auto pPDFAnnotation1 = pPDFPage->getAnnotation(0);
232 CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text,
233 pPDFAnnotation1->getSubType()); // Text annotation
235 auto pPDFAnnotation2 = pPDFPage->getAnnotation(1);
236 CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup,
237 pPDFAnnotation2->getSubType()); // Pop-up annotation
239 // Load document again
240 mxComponent = loadFromDesktop(maTempFile.GetURL());
241 auto pNewImpressDocument = dynamic_cast<SdXImpressDocument*>(mxComponent.get());
242 sd::ViewShell* pNewViewShell = pNewImpressDocument->GetDocShell()->GetViewShell();
243 CPPUNIT_ASSERT(pNewViewShell);
245 SdPage* pPage = pNewViewShell->GetActualPage();
246 CPPUNIT_ASSERT(pPage);
248 // We expect only 1 annotation in the document because the PDF
249 // annotations are dependent on each-other:
250 // parent annotation "Text" and the child annotation "Pop-up"
252 CPPUNIT_ASSERT_EQUAL(size_t(1), pPage->getAnnotations().size());
254 // check annotation
255 auto xAnnotation = pPage->getAnnotations().at(0);
257 CPPUNIT_ASSERT_DOUBLES_EQUAL(90.33, xAnnotation->getPosition().X, 1E-3);
258 CPPUNIT_ASSERT_DOUBLES_EQUAL(12.07, xAnnotation->getPosition().Y, 1E-3);
260 CPPUNIT_ASSERT_EQUAL(OUString("TheAuthor"), xAnnotation->getAuthor());
261 CPPUNIT_ASSERT_EQUAL(OUString(), xAnnotation->getInitials());
263 auto xText = xAnnotation->getTextRange();
265 CPPUNIT_ASSERT_EQUAL(OUString("This is the annotation text!"), xText->getString());
267 auto aDateTime = xAnnotation->getDateTime();
268 CPPUNIT_ASSERT_EQUAL(sal_Int16(2020), aDateTime.Year);
269 CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), aDateTime.Month);
270 CPPUNIT_ASSERT_EQUAL(sal_uInt16(18), aDateTime.Day);
271 CPPUNIT_ASSERT_EQUAL(sal_uInt16(12), aDateTime.Hours);
272 CPPUNIT_ASSERT_EQUAL(sal_uInt16(11), aDateTime.Minutes);
273 CPPUNIT_ASSERT_EQUAL(sal_uInt16(53), aDateTime.Seconds);
274 CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aDateTime.NanoSeconds);
275 CPPUNIT_ASSERT_EQUAL(false, bool(aDateTime.IsUTC));
279 CPPUNIT_PLUGIN_IMPLEMENT();
281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */