1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
19 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
20 #include <LibreOfficeKit/LibreOfficeKitInit.h>
21 #include <LibreOfficeKit/LibreOfficeKit.hxx>
27 fprintf( stderr
, "Usage: tilebench <absolute-path-to-libreoffice-install> [path to document] [max parts|-1] [max tiles|-1]\n" );
28 fprintf( stderr
, "renders a selection of small tiles from the document, checksums them and times the process\n" );
32 static double getTimeNow()
35 osl_getSystemTime(&aValue
);
36 return static_cast<double>(aValue
.Seconds
) +
37 static_cast<double>(aValue
.Nanosec
) / (1000*1000*1000);
40 /// Dump an array of RGBA or BGRA to an RGB PPM file.
41 static void dumpTile(const int nWidth
, const int nHeight
, const int mode
, const char* pBuffer
)
43 std::ofstream
ofs("/tmp/dump_tile.ppm");
49 for (int y
= 0; y
< nHeight
; ++y
)
51 const char* row
= pBuffer
+ y
* nWidth
* 4;
52 for (int x
= 0; x
< nWidth
; ++x
)
54 const char* pixel
= row
+ x
* 4;
55 if (mode
== LOK_TILEMODE_RGBA
)
57 ofs
.write(pixel
, 3); // Skip alpha
59 else if (mode
== LOK_TILEMODE_BGRA
)
61 const int alpha
= *(pixel
+ 3);
71 buf
[0] = (*(pixel
+ 2) * 255 + alpha
/ 2) / alpha
;
72 buf
[1] = (*(pixel
+ 1) * 255 + alpha
/ 2) / alpha
;
73 buf
[2] = (*(pixel
+ 0) * 255 + alpha
/ 2) / alpha
;
82 int main( int argc
, char* argv
[] )
84 static const double origin
= getTimeNow();
89 TimeRecord() : mpName(nullptr), mfTime(getTimeNow()) { }
90 explicit TimeRecord(const char *pName
) :
91 mpName(pName
), mfTime(getTimeNow())
93 fprintf(stderr
, "%3.3fs - %s\n", (mfTime
- origin
), mpName
);
96 std::vector
< TimeRecord
> aTimes
;
98 ( argc
> 1 && ( !strcmp( argv
[1], "--help" ) || !strcmp( argv
[1], "-h" ) ) ) )
101 if ( argv
[1][0] != '/' )
103 fprintf(stderr
, "Absolute path required to libreoffice install\n");
107 aTimes
.emplace_back("initialization");
108 // coverity[tainted_string] - build time test tool
109 Office
*pOffice
= lok_cpp_init(argv
[1]);
110 if (pOffice
== nullptr)
112 fprintf(stderr
, "Failed to initialize Office from %s\n", argv
[1]);
116 aTimes
.emplace_back();
118 const int max_parts
= (argc
> 3 ? atoi(argv
[3]) : -1);
119 int max_tiles
= (argc
> 4 ? atoi(argv
[4]) : -1);
120 const bool dump
= true;
122 if (argv
[2] != nullptr)
124 aTimes
.emplace_back("load document");
125 Document
*pDocument(pOffice
->documentLoad(argv
[2]));
126 aTimes
.emplace_back();
127 const int mode
= pDocument
->getTileMode();
129 aTimes
.emplace_back("getparts");
130 const int nOriginalPart
= (pDocument
->getDocumentType() == LOK_DOCTYPE_TEXT
? 1 : pDocument
->getPart());
131 // Writer really has 1 part (the full doc).
132 const int nTotalParts
= (pDocument
->getDocumentType() == LOK_DOCTYPE_TEXT
? 1 : pDocument
->getParts());
133 const int nParts
= (max_parts
< 0 ? nTotalParts
: std::min(max_parts
, nTotalParts
));
134 aTimes
.emplace_back();
136 aTimes
.emplace_back("get size of parts");
139 for (int n
= 0; n
< nParts
; ++n
)
141 const int nPart
= (nOriginalPart
+ n
) % nTotalParts
;
142 char* pName
= pDocument
->getPartName(nPart
);
143 pDocument
->setPart(nPart
);
144 pDocument
->getDocumentSize(&nWidth
, &nHeight
);
145 fprintf (stderr
, " '%s' -> %ld, %ld\n", pName
, nWidth
, nHeight
);
148 aTimes
.emplace_back();
150 // Use realistic dimensions, similar to the Online client.
151 long nTilePixelWidth
= 512;
152 long nTilePixelHeight
= 512;
153 long nTileTwipWidth
= 3840;
154 long nTileTwipHeight
= 3840;
156 // Estimate the maximum tiles based on the number of parts requested, if Writer.
157 if (pDocument
->getDocumentType() == LOK_DOCTYPE_TEXT
)
158 max_tiles
= static_cast<int>(ceil(max_parts
* 16128. / nTilePixelHeight
) * ceil(static_cast<double>(nWidth
) / nTilePixelWidth
));
159 fprintf(stderr
, "Parts to render: %d, Total Parts: %d, Max parts: %d, Max tiles: %d\n", nParts
, nTotalParts
, max_parts
, max_tiles
);
161 std::vector
<unsigned char> vBuffer(nTilePixelWidth
* nTilePixelHeight
* 4);
162 unsigned char* pPixels
= &vBuffer
[0];
164 for (int n
= 0; n
< nParts
; ++n
)
166 const int nPart
= (nOriginalPart
+ n
) % nTotalParts
;
167 char* pName
= pDocument
->getPartName(nPart
);
168 pDocument
->setPart(nPart
);
169 pDocument
->getDocumentSize(&nWidth
, &nHeight
);
170 fprintf (stderr
, "render '%s' -> %ld, %ld\n", pName
, nWidth
, nHeight
);
173 if (dump
|| pDocument
->getDocumentType() != LOK_DOCTYPE_TEXT
)
175 // whole part; meaningful only for non-writer documents.
176 aTimes
.emplace_back("render whole part");
177 pDocument
->paintTile(pPixels
, nTilePixelWidth
, nTilePixelHeight
,
178 nWidth
/2, 2000, 1000, 1000); // not square
179 aTimes
.emplace_back();
181 dumpTile(nTilePixelWidth
, nTilePixelHeight
, mode
, reinterpret_cast<char*>(pPixels
));
185 aTimes
.emplace_back("render sub-region at 1:1");
186 // Estimate the maximum tiles based on the number of parts requested, if Writer.
187 int nMaxTiles
= max_tiles
;
189 for (int nY
= 0; nY
< nHeight
- 1; nY
+= nTilePixelHeight
)
191 for (int nX
= 0; nX
< nWidth
- 1; nX
+= nTilePixelWidth
)
193 if (nMaxTiles
>= 0 && nTiles
>= nMaxTiles
)
199 pDocument
->paintTile(pPixels
, nTilePixelWidth
, nTilePixelHeight
,
200 nX
, nY
, nTilePixelWidth
, nTilePixelHeight
);
202 fprintf (stderr
, " rendered 1:1 tile %d at %d, %d\n",
206 aTimes
.emplace_back();
210 aTimes
.emplace_back("render sub-regions at scale");
211 int nMaxTiles
= max_tiles
;
212 if (pDocument
->getDocumentType() == LOK_DOCTYPE_TEXT
)
213 nMaxTiles
= static_cast<int>(ceil(max_parts
* 16128. / nTileTwipHeight
) * ceil(static_cast<double>(nWidth
) / nTileTwipWidth
));
215 for (int nY
= 0; nY
< nHeight
- 1; nY
+= nTileTwipHeight
)
217 for (int nX
= 0; nX
< nWidth
- 1; nX
+= nTileTwipWidth
)
219 if (nMaxTiles
>= 0 && nTiles
>= nMaxTiles
)
225 pDocument
->paintTile(pPixels
, nTilePixelWidth
, nTilePixelHeight
,
226 nX
, nY
, nTileTwipWidth
, nTileTwipHeight
);
228 fprintf (stderr
, " rendered scaled tile %d at %d, %d\n",
232 aTimes
.emplace_back();
236 aTimes
.emplace_back("destroy document");
238 aTimes
.emplace_back();
244 fprintf (stderr
, "profile run:\n");
245 for (size_t i
= 0; i
< aTimes
.size() - 1; i
++)
247 const double nDelta
= aTimes
[i
+1].mfTime
- aTimes
[i
].mfTime
;
248 fprintf (stderr
, " %s - %2.4f(ms)\n", aTimes
[i
].mpName
, nDelta
* 1000.0);
249 if (aTimes
[i
+1].mpName
== nullptr)
253 fprintf (stderr
, "Total: %2.4f(s)\n", nTotal
);
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */