tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / libreofficekit / qa / tilebench / tilebench.cxx
blobffcdcefa009fc0cbee858ef8d1721f5c31a46872
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 <stdio.h>
11 #include <string.h>
12 #include <cmath>
14 #include <vector>
15 #include <atomic>
16 #include <iostream>
17 #include <osl/time.h>
19 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
20 #include <LibreOfficeKit/LibreOfficeKitInit.h>
21 #include <LibreOfficeKit/LibreOfficeKit.hxx>
23 #ifdef IOS
24 #include <vcl/svapp.hxx>
25 #endif
27 #include <boost/property_tree/json_parser.hpp>
29 using namespace lok;
31 static int help( const char *error = nullptr )
33 if (error)
34 fprintf (stderr, "Error: %s\n\n", error);
35 fprintf( stderr, "Usage: tilebench <absolute-path-to-libreoffice-install> [path to document] [--preinit] [--save <path>] <options>\n");
36 fprintf( stderr, "\trenders a selection of small tiles from the document, checksums them and times the process based on options:\n" );
37 fprintf( stderr, "\t--tile\t[max parts|-1] [max tiles|-1]\n" );
38 fprintf( stderr, "\t--dialog\t<.uno:Command>\n" );
39 fprintf( stderr, "\t--join\trun tile joining tests\n" );
40 return 1;
43 static double getTimeNow()
45 TimeValue aValue;
46 osl_getSystemTime(&aValue);
47 return static_cast<double>(aValue.Seconds) +
48 static_cast<double>(aValue.Nanosec) / (1000*1000*1000);
51 static double origin;
53 namespace {
55 struct TimeRecord {
56 const char *mpName;
57 double mfTime;
59 TimeRecord() : mpName(nullptr), mfTime(getTimeNow()) { }
60 explicit TimeRecord(const char *pName) :
61 mpName(pName), mfTime(getTimeNow())
63 fprintf(stderr, "%3.3fs - %s\n", (mfTime - origin), mpName);
69 static std::vector< TimeRecord > aTimes;
71 /// Dump an array (or sub-array) of RGBA or BGRA to an RGB PPM file.
72 static void dumpTile(const char *pNameStem,
73 const int nWidth, const int nHeight,
74 const int mode, const unsigned char* pBufferU,
75 const int nOffX = 0, const int nOffY = 0,
76 int nTotalWidth = -1)
78 if (nTotalWidth < 0)
79 nTotalWidth = nWidth;
81 auto pBuffer = reinterpret_cast<const char *>(pBufferU);
82 static int counter = 0;
83 std::string aName = "/tmp/dump_tile";
84 aName += pNameStem;
85 aName += "_" + std::to_string(counter);
86 aName += ".ppm";
87 #ifndef IOS
88 std::ofstream ofs(aName);
89 #else
90 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
91 NSString *documentsDirectory = [paths objectAtIndex:0];
92 NSString *path = [NSString stringWithFormat:@"%@/dump_tile_%d.ppm", documentsDirectory, counter];
93 std::ofstream ofs([path UTF8String]);
94 std::cerr << "---> Dumping tile\n";
95 #endif
96 counter++;
97 ofs << "P6\n"
98 << nWidth << " "
99 << nHeight << "\n"
100 << 255 << "\n" ;
102 const bool dumpText = false;
104 if (dumpText)
105 fprintf(stderr, "Stream %s - %dx%d:\n", pNameStem, nWidth, nHeight);
107 for (int y = 0; y < nHeight; ++y)
109 const char* row = pBuffer + (y + nOffY) * nTotalWidth * 4 + nOffX * 4;
110 for (int x = 0; x < nWidth; ++x)
112 const char* pixel = row + x * 4;
114 const int alpha = *(pixel + 3);
115 char buf[3];
116 if (alpha == 0)
118 buf[0] = 0;
119 buf[1] = 0;
120 buf[2] = 0;
122 else
124 switch (mode)
126 case LOK_TILEMODE_RGBA:
127 buf[0] = (*(pixel + 0) * 255 + alpha / 2) / alpha;
128 buf[1] = (*(pixel + 1) * 255 + alpha / 2) / alpha;
129 buf[2] = (*(pixel + 2) * 255 + alpha / 2) / alpha;
130 break;
131 case LOK_TILEMODE_BGRA:
132 buf[0] = (*(pixel + 2) * 255 + alpha / 2) / alpha;
133 buf[1] = (*(pixel + 1) * 255 + alpha / 2) / alpha;
134 buf[2] = (*(pixel + 0) * 255 + alpha / 2) / alpha;
135 break;
136 default:
137 assert(false && "unhandled LibreOfficeKitTileMode");
138 break;
142 ofs.write(buf, 3);
143 if (dumpText)
145 int lowResI = (pixel[0] + pixel[1] + pixel[2])/(3*16);
146 fprintf(stderr,"%1x", lowResI);
149 if (dumpText)
150 fprintf(stderr,"\n");
152 ofs.close();
155 static void testTile( Document *pDocument, int max_parts,
156 int max_tiles, bool dump )
158 const int mode = pDocument->getTileMode();
160 aTimes.emplace_back("getparts");
161 const int nOriginalPart = (pDocument->getDocumentType() == LOK_DOCTYPE_TEXT ? 1 : pDocument->getPart());
162 // Writer really has 1 part (the full doc).
163 const int nTotalParts = (pDocument->getDocumentType() == LOK_DOCTYPE_TEXT ? 1 : pDocument->getParts());
164 const int nParts = (max_parts < 0 ? nTotalParts : std::min(max_parts, nTotalParts));
165 aTimes.emplace_back();
167 aTimes.emplace_back("get size of parts");
168 long nWidth = 0;
169 long nHeight = 0;
170 for (int n = 0; n < nParts; ++n)
172 const int nPart = (nOriginalPart + n) % nTotalParts;
173 char* pName = pDocument->getPartName(nPart);
174 pDocument->setPart(nPart);
175 pDocument->getDocumentSize(&nWidth, &nHeight);
176 fprintf (stderr, " '%s' -> %ld, %ld\n", pName, nWidth, nHeight);
177 free (pName);
179 aTimes.emplace_back();
181 // Use realistic dimensions, similar to the Online client.
182 long const nTilePixelWidth = 512;
183 long const nTilePixelHeight = 512;
184 long const nTileTwipWidth = 3840;
185 long const nTileTwipHeight = 3840;
187 // Estimate the maximum tiles based on the number of parts requested, if Writer.
188 if (pDocument->getDocumentType() == LOK_DOCTYPE_TEXT)
189 max_tiles = static_cast<int>(ceil(max_parts * 16128. / nTilePixelHeight) * ceil(static_cast<double>(nWidth) / nTilePixelWidth));
190 fprintf(stderr, "Parts to render: %d, Total Parts: %d, Max parts: %d, Max tiles: %d\n", nParts, nTotalParts, max_parts, max_tiles);
192 std::vector<unsigned char> vBuffer(nTilePixelWidth * nTilePixelHeight * 4);
193 unsigned char* pPixels = vBuffer.data();
195 for (int n = 0; n < nParts; ++n)
197 const int nPart = (nOriginalPart + n) % nTotalParts;
198 char* pName = pDocument->getPartName(nPart);
199 pDocument->setPart(nPart);
200 pDocument->getDocumentSize(&nWidth, &nHeight);
201 fprintf (stderr, "render '%s' -> %ld, %ld\n", pName, nWidth, nHeight);
202 free (pName);
204 if (dump || pDocument->getDocumentType() != LOK_DOCTYPE_TEXT)
206 // whole part; meaningful only for non-writer documents.
207 aTimes.emplace_back("render whole part");
208 pDocument->paintTile(pPixels, nTilePixelWidth, nTilePixelHeight,
209 nWidth/2, 2000, 1000, 1000);
210 aTimes.emplace_back();
211 if (dump)
212 dumpTile("tile", nTilePixelWidth, nTilePixelHeight, mode, pPixels);
215 { // 1:1
216 aTimes.emplace_back("render sub-region at 1:1");
217 // Estimate the maximum tiles based on the number of parts requested, if Writer.
218 int nMaxTiles = max_tiles;
219 int nTiles = 0;
220 for (long nY = 0; nY < nHeight - 1; nY += nTilePixelHeight)
222 for (long nX = 0; nX < nWidth - 1; nX += nTilePixelWidth)
224 if (nMaxTiles >= 0 && nTiles >= nMaxTiles)
226 nY = nHeight;
227 break;
229 pDocument->paintTile(pPixels, nTilePixelWidth, nTilePixelHeight,
230 nX, nY, nTilePixelWidth, nTilePixelHeight);
231 nTiles++;
232 fprintf (stderr, " rendered 1:1 tile %d at %ld, %ld\n",
233 nTiles, nX, nY);
236 aTimes.emplace_back();
239 { // scaled
240 aTimes.emplace_back("render sub-regions at scale");
241 int nMaxTiles = max_tiles;
242 if (pDocument->getDocumentType() == LOK_DOCTYPE_TEXT)
243 nMaxTiles = static_cast<int>(ceil(max_parts * 16128. / nTileTwipHeight) * ceil(static_cast<double>(nWidth) / nTileTwipWidth));
244 int nTiles = 0;
245 for (long nY = 0; nY < nHeight - 1; nY += nTileTwipHeight)
247 for (long nX = 0; nX < nWidth - 1; nX += nTileTwipWidth)
249 if (nMaxTiles >= 0 && nTiles >= nMaxTiles)
251 nY = nHeight;
252 break;
254 pDocument->paintTile(pPixels, nTilePixelWidth, nTilePixelHeight,
255 nX, nY, nTileTwipWidth, nTileTwipHeight);
256 nTiles++;
257 fprintf (stderr, " rendered scaled tile %d at %ld, %ld\n",
258 nTiles, nX, nY);
261 aTimes.emplace_back();
266 static uint32_t fade(uint32_t col)
268 uint8_t a = (col >> 24) & 0xff;
269 uint8_t b = (col >> 16) & 0xff;
270 uint8_t g = (col >> 8) & 0xff;
271 uint8_t r = (col >> 0) & 0xff;
272 uint8_t grey = (r+g+b)/6;
273 return (a<<24) + (grey<<16) + (grey<<8) + grey;
276 static bool sloppyEqual(uint32_t pixA, uint32_t pixB)
278 uint8_t a[4], b[4];
280 a[0] = (pixA >> 24) & 0xff;
281 a[1] = (pixA >> 16) & 0xff;
282 a[2] = (pixA >> 8) & 0xff;
283 a[3] = (pixA >> 0) & 0xff;
285 b[0] = (pixB >> 24) & 0xff;
286 b[1] = (pixB >> 16) & 0xff;
287 b[2] = (pixB >> 8) & 0xff;
288 b[3] = (pixB >> 0) & 0xff;
290 for (int i = 0; i < 4; ++i)
292 int delta = a[i];
293 delta -= b[i];
294 // tolerate small differences
295 if (delta < -4 || delta > 4)
296 return false;
298 return true;
301 // Count and build a picture of any differences into rDiff
302 static int diffTiles( const std::vector<unsigned char> &vBase,
303 long nBaseRowPixelWidth,
304 const std::vector<unsigned char> &vCompare,
305 long nCompareRowPixelWidth,
306 long nTilePixelHeight,
307 long nPosX, long nPosY,
308 std::vector<unsigned char> &rDiff )
310 int nDifferent = 0;
311 const uint32_t *pBase = reinterpret_cast<const uint32_t *>(vBase.data());
312 const uint32_t *pCompare = reinterpret_cast<const uint32_t *>(vCompare.data());
313 uint32_t *pDiff = reinterpret_cast<uint32_t *>(rDiff.data());
314 long left = 0, mid = nCompareRowPixelWidth, right = nCompareRowPixelWidth*2;
315 for (long y = 0; y < nTilePixelHeight; ++y)
317 long nBaseOffset = nBaseRowPixelWidth * (y + nPosY) + nPosX * nCompareRowPixelWidth;
318 long nCompareOffset = nCompareRowPixelWidth * y;
319 long nDiffRowStart = nCompareOffset * 3;
320 for (long x = 0; x < nCompareRowPixelWidth; ++x)
322 pDiff[nDiffRowStart + left + x] = pBase[nBaseOffset + x];
323 pDiff[nDiffRowStart + mid + x] = pCompare[nCompareOffset + x];
324 pDiff[nDiffRowStart + right + x] = fade(pBase[nBaseOffset + x]);
325 if (!sloppyEqual(pBase[nBaseOffset + x], pCompare[nCompareOffset + x]))
327 pDiff[nDiffRowStart + right + x] = 0xffff00ff;
328 if (!nDifferent)
329 fprintf (stderr, "First mismatching pixel at %ld (pixels) into row %ld\n", x, y);
330 nDifferent++;
334 return nDifferent;
337 static std::vector<unsigned char> paintTile( Document *pDocument,
338 long nX, long nY,
339 long const nTilePixelWidth,
340 long const nTilePixelHeight,
341 long const nTileTwipWidth,
342 long const nTileTwipHeight )
344 // long e = 0; // tweak if we suspect an overlap / visibility issue.
345 // pDocument->setClientVisibleArea( nX - e, nY - e, nTileTwipWidth + e, nTileTwipHeight + e );
346 std::vector<unsigned char> vData( nTilePixelWidth * nTilePixelHeight * 4 );
347 pDocument->paintTile( vData.data(), nTilePixelWidth, nTilePixelHeight,
348 nX, nY, nTileTwipWidth, nTileTwipHeight );
349 return vData;
352 static int testJoinsAt( Document *pDocument, long nX, long nY,
353 long const nTilePixelSize,
354 long const nTileTwipSize )
356 const int mode = pDocument->getTileMode();
358 long const nTilePixelWidth = nTilePixelSize;
359 long const nTilePixelHeight = nTilePixelSize;
360 long const nTileTwipWidth = nTileTwipSize;
361 long const nTileTwipHeight = nTileTwipSize;
363 long initPosX = nX * nTileTwipWidth, initPosY = nY * nTileTwipHeight;
365 // Calc has to do significant work on changing zoom ...
366 pDocument->setClientZoom( nTilePixelWidth, nTilePixelHeight,
367 nTileTwipWidth, nTileTwipHeight );
369 // Unfortunately without getting this nothing renders ...
370 std::stringstream aForceHeaders;
371 aForceHeaders << ".uno:ViewRowColumnHeaders?x=" << initPosX << "&y=" << initPosY <<
372 "&width=" << (nTileTwipWidth * 2) << "&height=" << (nTileTwipHeight * 2);
373 std::string cmd = aForceHeaders.str();
374 char* pJSON = pDocument->getCommandValues(cmd.c_str());
375 fprintf(stderr, "command: '%s' values '%s'\n", cmd.c_str(), pJSON);
376 free(pJSON);
378 // Get a base image 4x the size
379 std::vector<unsigned char> vBase(
380 paintTile(pDocument, initPosX, initPosY,
381 nTilePixelWidth * 2, nTilePixelHeight * 2,
382 nTileTwipWidth * 2, nTileTwipHeight * 2));
384 const struct {
385 long X;
386 long Y;
387 } aCompare[] = {
388 { 0, 0 },
389 { 1, 0 },
390 { 0, 1 },
391 { 1, 1 }
394 int nDifferences = 0;
395 // Compare each of the 4x tiles with a sub-tile of the larger image
396 for( auto &rPos : aCompare )
398 std::vector<unsigned char> vCompare(
399 paintTile(pDocument,
400 initPosX + rPos.X * nTileTwipWidth,
401 initPosY + rPos.Y * nTileTwipHeight,
402 nTilePixelWidth, nTilePixelHeight,
403 nTileTwipWidth, nTileTwipHeight));
405 std::vector<unsigned char> vDiff( nTilePixelWidth * 3 * nTilePixelHeight * 4 );
406 int nDiffs = diffTiles( vBase, nTilePixelWidth * 2,
407 vCompare, nTilePixelWidth,
408 nTilePixelHeight,
409 rPos.X, rPos.Y * nTilePixelHeight,
410 vDiff );
411 if ( nDiffs > 0 )
413 fprintf( stderr, " %d differences in sub-tile pixel mismatch at %ld, %ld at offset %ld, %ld (twips) size %ld\n",
414 nDiffs, rPos.X, rPos.Y, initPosX, initPosY,
415 nTileTwipWidth);
416 dumpTile("_base", nTilePixelWidth * 2, nTilePixelHeight * 2,
417 mode, vBase.data());
418 /* dumpTile("_sub", nTilePixelWidth, nTilePixelHeight,
419 mode, vBase.data(),
420 rPos.X*nTilePixelWidth, rPos.Y*nTilePixelHeight,
421 nTilePixelWidth * 2);
422 dumpTile("_compare", nTilePixelWidth, nTilePixelHeight,
423 mode, vCompare.data());*/
424 dumpTile("_diff", nTilePixelWidth * 3, nTilePixelHeight, mode, vDiff.data());
426 nDifferences += nDiffs;
429 return nDifferences;
432 // Check that our tiles join nicely ...
433 static int testJoin( Document *pDocument)
435 // Ignore parts - just the first for now ...
436 long nWidth = 0, nHeight = 0;
437 pDocument->getDocumentSize(&nWidth, &nHeight);
438 fprintf (stderr, "Width is %ld, %ld (twips)\n", nWidth, nHeight);
440 // Use realistic dimensions, similar to the Online client.
441 long const nTilePixelSize = 256;
442 long const nTileTwipSize = 3840;
443 double fZooms[] = {
444 0.5,
445 0.6, 0.7, 0.85,
446 1.0,
447 1.2, 1.5, 1.75,
450 long nFails = 0;
451 std::stringstream results;
453 for( auto z : fZooms )
455 long nBad = 0;
456 long nDifferences = 0;
457 for( long y = 0; y < 8; ++y )
459 for( long x = 0; x < 8; ++x )
461 int nDiffs = testJoinsAt( pDocument, x, y, nTilePixelSize, nTileTwipSize * z );
462 if (nDiffs)
463 nBad++;
464 nDifferences += nDiffs;
467 if (nBad > 0)
468 results << "\tZoom " << z << " bad tiles: " << nBad << " with " << nDifferences << " mismatching pixels\n";
469 nFails += nBad;
472 if (nFails > 0)
473 fprintf( stderr, "Failed %ld joins\n", nFails );
474 else
475 fprintf( stderr, "All joins compared correctly\n" );
477 fprintf(stderr, "%s\n", results.str().c_str());
479 return nFails;
482 static std::atomic<bool> bDialogRendered(false);
483 static std::atomic<int> nDialogId(-1);
485 static void kitCallback(int nType, const char* pPayload, void* pData)
487 Document *pDocument = static_cast<Document *>(pData);
489 if (nType != LOK_CALLBACK_WINDOW)
490 return;
492 std::stringstream aStream(pPayload);
493 boost::property_tree::ptree aRoot;
494 boost::property_tree::read_json(aStream, aRoot);
495 nDialogId = aRoot.get<unsigned>("id");
496 const std::string aAction = aRoot.get<std::string>("action");
498 if (aAction != "created")
499 return;
501 const std::string aType = aRoot.get<std::string>("type");
502 const std::string aSize = aRoot.get<std::string>("size");
503 int nWidth = atoi(aSize.c_str());
504 int nHeight = 400;
505 const char *pComma = strstr(aSize.c_str(), ", ");
506 if (pComma)
507 nHeight = atoi(pComma + 2);
508 std::cerr << "Size " << aSize << " is " << nWidth << ", " << nHeight << "\n";
510 if (aType != "dialog")
511 return;
513 aTimes.emplace_back(); // complete wait for dialog
515 unsigned char *pBuffer = new unsigned char[nWidth * nHeight * 4];
517 aTimes.emplace_back("render dialog");
518 pDocument->paintWindow(nDialogId, pBuffer, 0, 0, nWidth, nHeight);
519 dumpTile("dialog", nWidth, nHeight, pDocument->getTileMode(), pBuffer);
520 aTimes.emplace_back();
522 delete[] pBuffer;
524 bDialogRendered = true;
527 static void testDialog( Document *pDocument, const char *uno_cmd )
529 int view = pDocument->createView();
530 pDocument->setView(view);
531 pDocument->registerCallback(kitCallback, pDocument);
533 aTimes.emplace_back("open dialog");
534 pDocument->postUnoCommand(uno_cmd, nullptr, true);
535 aTimes.emplace_back();
537 aTimes.emplace_back("wait for dialog");
538 while (!bDialogRendered)
540 usleep (1000);
543 aTimes.emplace_back("post close dialog");
544 pDocument->postWindow(nDialogId, LOK_WINDOW_CLOSE);
545 aTimes.emplace_back();
547 pDocument->destroyView(view);
550 static void documentCallback(const int type, const char* p, void*)
552 std::cerr << "Document callback " << type << ": " << (p ? p : "(null)") << "\n";
555 // Avoid excessive dbgutil churn.
556 static void ignoreCallback(const int /*type*/, const char* /*p*/, void* /*data*/)
560 int main( int argc, char* argv[] )
562 int arg = 2;
563 origin = getTimeNow();
565 #ifndef IOS
566 // avoid X oddness etc.
567 unsetenv("DISPLAY");
569 if( argc < 4 ||
570 ( argc > 1 && ( !strcmp( argv[1], "--help" ) || !strcmp( argv[1], "-h" ) ) ) )
571 return help();
573 if ( argv[1][0] != '/' )
575 fprintf(stderr, "Absolute path required to libreoffice install\n");
576 return 1;
579 const char *doc_url = argv[arg++];
580 const char *mode = argv[arg++];
582 bool pre_init = false;
583 if (!strcmp(mode, "--preinit"))
585 pre_init = true;
586 mode = argv[arg++];
589 const char *saveToPath = nullptr;
590 if (!strcmp (mode, "--save"))
592 pre_init = true;
593 saveToPath = argv[arg++];
594 mode = argv[arg++];
597 std::string user_url("file:///");
598 user_url.append(argv[1]);
599 user_url.append("../user");
601 if (pre_init)
603 aTimes.emplace_back("pre-initialization");
604 setenv("LOK_ALLOWLIST_LANGUAGES", "en_US", 0);
605 // coverity[tainted_string] - build time test tool
606 lok_preinit(argv[1], user_url.c_str());
607 aTimes.emplace_back();
609 const char *install_path = argv[1];
610 const char *user_profile = user_url.c_str();
611 #else
612 const char *install_path = nullptr;
613 const char *user_profile = nullptr;
614 const char *doc_url = strdup([[[[[NSBundle mainBundle] bundleURL] absoluteString] stringByAppendingString:@"/test.odt"] UTF8String]);
615 const char *mode = "--tile";
616 const char *saveToPath = nullptr;
617 #endif
619 aTimes.emplace_back("initialization");
620 // coverity[tainted_string] - build time test tool
621 std::unique_ptr<Office> pOffice( lok_cpp_init(install_path, user_profile) );
622 if (pOffice == nullptr)
624 fprintf(stderr, "Failed to initialize Office from %s\n", argv[1]);
625 return 1;
627 aTimes.emplace_back();
628 pOffice->registerCallback(ignoreCallback, nullptr);
630 std::unique_ptr<Document> pDocument;
632 pOffice->setOptionalFeatures(LOK_FEATURE_NO_TILED_ANNOTATIONS);
634 aTimes.emplace_back("load document");
635 if (doc_url != nullptr)
636 pDocument.reset(pOffice->documentLoad(doc_url));
637 aTimes.emplace_back();
639 if (pDocument)
641 pDocument->initializeForRendering("{\".uno:Author\":{\"type\":\"string\",\"value\":\"Local Host #0\"}}");
642 pDocument->registerCallback(documentCallback, nullptr);
643 if (!strcmp(mode, "--tile"))
645 const int max_parts = (argc > arg ? atoi(argv[arg++]) : -1);
646 int max_tiles = (argc > arg ? atoi(argv[arg++]) : -1);
647 const bool dump = true;
649 // coverity[tainted_data] - we trust the contents of this variable
650 testTile (pDocument.get(), max_parts, max_tiles, dump);
652 else if (!strcmp(mode, "--join"))
654 return testJoin (pDocument.get());
656 else if (!strcmp (mode, "--dialog"))
658 const char *uno_cmd = argc > arg ? argv[arg++] : nullptr;
659 if (!uno_cmd)
661 switch (pDocument->getDocumentType())
663 case LOK_DOCTYPE_SPREADSHEET:
664 uno_cmd = ".uno:FormatCellDialog";
665 break;
666 case LOK_DOCTYPE_TEXT:
667 case LOK_DOCTYPE_PRESENTATION:
668 case LOK_DOCTYPE_DRAWING:
669 case LOK_DOCTYPE_OTHER:
670 return help("missing argument to --dialog and no default");
673 testDialog (pDocument.get(), uno_cmd);
675 else
676 return help ("unknown parameter");
678 if (saveToPath != nullptr)
680 aTimes.emplace_back("save");
681 pDocument->saveAs(saveToPath);
682 aTimes.emplace_back();
684 } else
685 fprintf(stderr, "Failed to load document '%s'\n",
686 (doc_url ? doc_url : "<null>"));
688 #ifdef IOS
689 Application::Quit();
690 #endif
691 aTimes.emplace_back("destroy document");
692 pDocument.reset();
693 aTimes.emplace_back();
695 pOffice.reset();
697 double nTotal = 0.0;
698 fprintf (stderr, "profile run:\n");
699 for (size_t i = 0; i < aTimes.size() - 1; i++)
701 const double nDelta = aTimes[i+1].mfTime - aTimes[i].mfTime;
702 fprintf (stderr, " %s - %2.4f(ms)\n", aTimes[i].mpName, nDelta * 1000.0);
703 if (aTimes[i+1].mpName == nullptr)
704 i++; // skip it.
705 nTotal += nDelta;
707 fprintf (stderr, "Total: %2.4f(s)\n", nTotal);
708 return 0;
711 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */