nss: upgrade to release 3.73
[LibreOffice.git] / sc / qa / extras / scpdfexport.cxx
blob7b9610061bdbce541860be94b9ca4b433f8b1aae
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 <sal/config.h>
12 #include <com/sun/star/frame/Desktop.hpp>
13 #include <com/sun/star/frame/XStorable.hpp>
14 #include <com/sun/star/lang/XComponent.hpp>
15 #include <com/sun/star/sheet/XSpreadsheet.hpp>
16 #include <com/sun/star/table/XCellRange.hpp>
17 #include <com/sun/star/view/XSelectionSupplier.hpp>
18 #include <test/bootstrapfixture.hxx>
19 #include <unotools/tempfile.hxx>
20 #include <unotest/macros_test.hxx>
21 #include <docsh.hxx>
22 #include <editutil.hxx>
23 #include <editeng/eeitem.hxx>
24 #include <editeng/fontitem.hxx>
25 #include <osl/file.hxx>
26 #include <comphelper/processfactory.hxx>
28 using namespace css::lang;
29 using namespace ::com::sun::star;
30 using namespace ::com::sun::star::uno;
32 class ScPDFExportTest : public test::BootstrapFixture, public unotest::MacrosTest
34 Reference<XComponent> mxComponent;
35 Reference<frame::XFrame> xTargetFrame;
37 public:
38 ScPDFExportTest() {}
40 virtual void setUp() override final;
41 virtual void tearDown() override final;
43 // helpers
44 private:
45 std::shared_ptr<utl::TempFile> exportToPDF(const uno::Reference<frame::XModel>& xModel,
46 const ScRange& range);
48 static bool hasTextInPdf(const std::shared_ptr<utl::TempFile>& pPDFFile, const char* sText,
49 bool& bFound);
51 void setFont(ScFieldEditEngine& rEE, sal_Int32 nStart, sal_Int32 nEnd,
52 const OUString& rFontName);
54 // unit tests
55 public:
56 void testExportRange_Tdf120161();
57 void testExportFitToPage_Tdf103516();
59 CPPUNIT_TEST_SUITE(ScPDFExportTest);
60 CPPUNIT_TEST(testExportRange_Tdf120161);
61 CPPUNIT_TEST(testExportFitToPage_Tdf103516);
62 CPPUNIT_TEST_SUITE_END();
65 void ScPDFExportTest::setUp()
67 test::BootstrapFixture::setUp();
69 mxDesktop.set(
70 css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory())));
73 uno::Reference<frame::XDesktop2> xDesktop = mxDesktop;
74 CPPUNIT_ASSERT(xDesktop.is());
76 // Create spreadsheet
77 uno::Sequence<beans::PropertyValue> args(1);
78 args[0].Name = "Hidden";
79 args[0].Value <<= true;
80 mxComponent = xDesktop->loadComponentFromURL("private:factory/scalc", "_blank", 0, args);
81 CPPUNIT_ASSERT(mxComponent.is());
83 // create a frame
84 xTargetFrame = xDesktop->findFrame("_blank", 0);
85 CPPUNIT_ASSERT(xTargetFrame.is());
87 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
88 uno::Reference<frame::XModel2> xModel2(xModel, UNO_QUERY);
89 CPPUNIT_ASSERT(xModel2.is());
91 Reference<frame::XController2> xController
92 = xModel2->createDefaultViewController(xTargetFrame);
93 CPPUNIT_ASSERT(xController.is());
95 // introduce model/view/controller to each other
96 xController->attachModel(xModel2.get());
97 xModel2->connectController(xController.get());
99 xTargetFrame->setComponent(xController->getComponentWindow(), xController.get());
100 xController->attachFrame(xTargetFrame);
102 xModel2->setCurrentController(xController.get());
106 void ScPDFExportTest::tearDown()
108 if (mxComponent.is())
109 mxComponent->dispose();
111 test::BootstrapFixture::tearDown();
114 bool ScPDFExportTest::hasTextInPdf(const std::shared_ptr<utl::TempFile>& pPDFFile,
115 const char* sText, bool& bFound)
117 SvStream* pStream = pPDFFile->GetStream(StreamMode::STD_READ);
118 CPPUNIT_ASSERT(pStream);
120 // get file size
121 pStream->Seek(STREAM_SEEK_TO_END);
122 const std::size_t nFileSize = pStream->Tell();
123 if (nFileSize == 0)
124 return false;
126 // read file content
127 char* pBuffer = new char[nFileSize];
128 pStream->Seek(STREAM_SEEK_TO_BEGIN);
129 const std::size_t nRead = pStream->ReadBytes(pBuffer, nFileSize);
130 if (nRead == nFileSize)
132 const std::string haystack(pBuffer, pBuffer + nFileSize);
133 const std::string needle(sText);
134 const std::size_t n = haystack.find(needle);
135 bFound = (n != std::string::npos);
137 delete[] pBuffer;
139 // close and return the status
140 pStream = nullptr;
141 pPDFFile->CloseStream();
142 return (nRead == nFileSize);
145 std::shared_ptr<utl::TempFile>
146 ScPDFExportTest::exportToPDF(const uno::Reference<frame::XModel>& xModel, const ScRange& range)
148 // create temp file name
149 auto pTempFile = std::make_shared<utl::TempFile>();
150 pTempFile->EnableKillingFile();
151 OUString sFileURL = pTempFile->GetURL();
152 // Note: under Windows path path should be with "/" delimiters instead of "\\"
153 // due to usage of INetURLObject() that converts "\\" to hexadecimal notation.
154 ::osl::FileBase::getFileURLFromSystemPath(sFileURL, sFileURL);
156 // get XSpreadsheet
157 uno::Reference<sheet::XSpreadsheetDocument> xDoc(xModel, uno::UNO_QUERY_THROW);
158 uno::Reference<sheet::XSpreadsheets> xSheets(xDoc->getSheets(), UNO_SET_THROW);
159 uno::Reference<container::XIndexAccess> xIndex(xSheets, uno::UNO_QUERY_THROW);
160 uno::Reference<sheet::XSpreadsheet> rSheet(xIndex->getByIndex(0), UNO_QUERY_THROW);
162 // select requested cells to print
163 // query for the XCellRange interface
164 uno::Reference<table::XCellRange> xCellRange = rSheet->getCellRangeByPosition(
165 range.aStart.Col(), range.aStart.Row(), range.aEnd.Col(), range.aEnd.Row());
167 uno::Reference<frame::XController> xController = xModel->getCurrentController();
168 CPPUNIT_ASSERT(xController.is());
170 uno::Reference<view::XSelectionSupplier> xSelection(xController, uno::UNO_QUERY_THROW);
171 CPPUNIT_ASSERT(xSelection.is());
173 uno::Any rCellRangeAny(xCellRange);
174 xSelection->select(rCellRangeAny);
177 // init special pdf export params
178 css::uno::Sequence<css::beans::PropertyValue> aFilterData(3);
179 aFilterData[0].Name = "Selection";
180 aFilterData[0].Value <<= xCellRange;
181 aFilterData[1].Name = "Printing";
182 aFilterData[1].Value <<= sal_Int32(2);
183 aFilterData[2].Name = "ViewPDFAfterExport";
184 aFilterData[2].Value <<= true;
186 // init set of params for storeToURL() call
187 css::uno::Sequence<css::beans::PropertyValue> seqArguments(3);
188 seqArguments[0].Name = "FilterData";
189 seqArguments[0].Value <<= aFilterData;
190 seqArguments[1].Name = "FilterName";
191 seqArguments[1].Value <<= OUString("calc_pdf_Export");
192 seqArguments[2].Name = "URL";
193 seqArguments[2].Value <<= sFileURL;
195 // call storeToURL()
196 uno::Reference<lang::XComponent> xComponent(mxComponent, UNO_SET_THROW);
197 uno::Reference<css::frame::XStorable> xStorable(xComponent, UNO_QUERY);
198 xStorable->storeToURL(sFileURL, seqArguments);
200 // return file object with generated PDF
201 return pTempFile;
204 void ScPDFExportTest::setFont(ScFieldEditEngine& rEE, sal_Int32 nStart, sal_Int32 nEnd,
205 const OUString& rFontName)
207 ESelection aSel;
208 aSel.nStartPara = aSel.nEndPara = 0;
209 aSel.nStartPos = nStart;
210 aSel.nEndPos = nEnd;
212 SfxItemSet aItemSet = rEE.GetEmptyItemSet();
213 SvxFontItem aItem(FAMILY_MODERN, rFontName, "", PITCH_VARIABLE, RTL_TEXTENCODING_UTF8,
214 EE_CHAR_FONTINFO);
215 aItemSet.Put(aItem);
216 rEE.QuickSetAttribs(aItemSet, aSel);
219 // Selection was not taken into account during export into PDF
220 void ScPDFExportTest::testExportRange_Tdf120161()
222 // create test document
223 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
224 uno::Reference<sheet::XSpreadsheetDocument> xDoc(xModel, uno::UNO_QUERY_THROW);
225 uno::Reference<sheet::XSpreadsheets> xSheets(xDoc->getSheets(), UNO_SET_THROW);
226 uno::Reference<container::XIndexAccess> xIndex(xSheets, uno::UNO_QUERY_THROW);
227 xSheets->insertNewByName("First Sheet", 0);
228 uno::Reference<sheet::XSpreadsheet> rSheet(xIndex->getByIndex(0), UNO_QUERY_THROW);
230 // 2. Setup data
232 SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(mxComponent);
233 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
234 ScDocShellRef xDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
235 CPPUNIT_ASSERT(xDocSh);
237 // put some content into the first row with default font
238 ScDocument& rDoc = xDocSh->GetDocument();
239 for (unsigned int r = 0; r < 1; ++r)
240 for (unsigned int c = 0; c < 14; ++c)
241 rDoc.SetValue(ScAddress(c, r, 0), (r + 1) * (c + 1));
243 // set "Text" to H1 cell with "DejaVuSans" font
244 ScFieldEditEngine& rEE = rDoc.GetEditEngine();
245 rEE.Clear();
246 rEE.SetTextCurrentDefaults("Text");
247 setFont(rEE, 0, 4, "DejaVuSans"); // set font for first 4 chars
248 rDoc.SetEditText(ScAddress(7, 0, 0), rEE.CreateTextObject());
251 // A1:G1
253 ScRange range1(0, 0, 0, 6, 0, 0);
254 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
255 bool bFound = false;
256 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "DejaVuSans", bFound));
257 CPPUNIT_ASSERT_EQUAL(false, bFound);
260 // G1:H1
262 ScRange range1(6, 0, 0, 7, 0, 0);
263 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
264 bool bFound = false;
265 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "DejaVuSans", bFound));
266 CPPUNIT_ASSERT_EQUAL(true, bFound);
269 // H1:I1
271 ScRange range1(7, 0, 0, 8, 0, 0);
272 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
273 bool bFound = false;
274 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "DejaVuSans", bFound));
275 CPPUNIT_ASSERT_EQUAL(true, bFound);
279 void ScPDFExportTest::testExportFitToPage_Tdf103516()
281 // create test document
282 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
283 uno::Reference<sheet::XSpreadsheetDocument> xDoc(xModel, uno::UNO_QUERY_THROW);
284 uno::Reference<sheet::XSpreadsheets> xSheets(xDoc->getSheets(), UNO_SET_THROW);
285 uno::Reference<container::XIndexAccess> xIndex(xSheets, uno::UNO_QUERY_THROW);
286 xSheets->insertNewByName("First Sheet", 0);
287 uno::Reference<sheet::XSpreadsheet> rSheet(xIndex->getByIndex(0), UNO_QUERY_THROW);
289 // 2. Setup data
291 SfxObjectShell* pFoundShell = SfxObjectShell::GetShellFromComponent(mxComponent);
292 CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pFoundShell);
293 ScDocShellRef xDocSh = dynamic_cast<ScDocShell*>(pFoundShell);
294 CPPUNIT_ASSERT(xDocSh);
296 // put some content into the table
297 ScDocument& rDoc = xDocSh->GetDocument();
298 for (unsigned int r = 0; r < 80; ++r)
299 for (unsigned int c = 0; c < 12; ++c)
300 rDoc.SetValue(ScAddress(c, r, 0), (r + 1) * (c + 1));
303 // A1:G50: 2-page export
305 ScRange range1(0, 0, 0, 6, 49, 0);
306 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
307 bool bFound = false;
308 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "/Count 2>>", bFound));
309 CPPUNIT_ASSERT_EQUAL(true, bFound);
312 // A1:L80: 4-page export
314 ScRange range1(0, 0, 0, 11, 79, 0);
315 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
316 bool bFound = false;
317 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "/Count 4>>", bFound));
318 CPPUNIT_ASSERT_EQUAL(true, bFound);
321 // set fit to page: width=1 page, height=0 (automatic)
322 uno::Reference<style::XStyleFamiliesSupplier> xStyleFamSupp(xDoc, UNO_QUERY_THROW);
323 uno::Reference<container::XNameAccess> xStyleFamiliesNames(xStyleFamSupp->getStyleFamilies(),
324 UNO_SET_THROW);
325 uno::Reference<container::XNameAccess> xPageStyles(xStyleFamiliesNames->getByName("PageStyles"),
326 UNO_QUERY_THROW);
327 uno::Any aDefaultStyle = xPageStyles->getByName("Default");
328 uno::Reference<beans::XPropertySet> xProp(aDefaultStyle, UNO_QUERY_THROW);
330 uno::Any aScaleX, aScaleY;
331 sal_Int16 nScale;
332 aScaleX <<= static_cast<sal_Int16>(1);
333 xProp->setPropertyValue("ScaleToPagesX", aScaleX);
334 aScaleX = xProp->getPropertyValue("ScaleToPagesX");
335 aScaleX >>= nScale;
336 CPPUNIT_ASSERT_EQUAL(sal_Int16(1), nScale);
338 aScaleY = xProp->getPropertyValue("ScaleToPagesY");
339 aScaleY >>= nScale;
340 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), nScale);
342 // A1:G50 with fit to page width=1: slightly smaller zoom results only 1-page export
344 ScRange range1(0, 0, 0, 6, 49, 0);
345 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
346 bool bFound = false;
347 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "/Count 1>>", bFound));
348 CPPUNIT_ASSERT_EQUAL(true, bFound);
351 // A1:L80 with fit to page width=1: slightly smaller zoom results only 1-page export
353 ScRange range1(0, 0, 0, 11, 79, 0);
354 std::shared_ptr<utl::TempFile> pPDFFile = exportToPDF(xModel, range1);
355 bool bFound = false;
356 CPPUNIT_ASSERT(hasTextInPdf(pPDFFile, "/Count 1>>", bFound));
357 CPPUNIT_ASSERT_EQUAL(true, bFound);
361 CPPUNIT_TEST_SUITE_REGISTRATION(ScPDFExportTest);
362 CPPUNIT_PLUGIN_IMPLEMENT();
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */