Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
PDFBench.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "bench/Benchmark.h"
9
11#include "include/core/SkData.h"
18#include "src/base/SkRandom.h"
20#include "src/pdf/SkPDFUnion.h"
22#include "tools/DecodeUtils.h"
23#include "tools/Resources.h"
25
26namespace {
27struct WStreamWriteTextBenchmark : public Benchmark {
28 std::unique_ptr<SkWStream> fWStream;
29 WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
30 const char* onGetName() override { return "WStreamWriteText"; }
31 bool isSuitableFor(Backend backend) override {
33 }
34 void onDraw(int loops, SkCanvas*) override {
35 while (loops-- > 0) {
36 for (int i = 1000; i-- > 0;) {
37 fWStream->writeText("HELLO SKIA!\n");
38 }
39 }
40 }
41};
42} // namespace
43
44DEF_BENCH(return new WStreamWriteTextBenchmark;)
45
46// Test speed of SkFloatToDecimal for typical floats that
47// might be found in a PDF document.
48struct PDFScalarBench : public Benchmark {
49 PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
50 const char* fName;
51 float (*fNextFloat)(SkRandom*);
52 bool isSuitableFor(Backend b) override {
53 return b == Backend::kNonRendering;
54 }
55 const char* onGetName() override { return fName; }
56 void onDraw(int loops, SkCanvas*) override {
57 SkRandom random;
59 while (loops-- > 0) {
60 auto f = fNextFloat(&random);
61 (void)SkFloatToDecimal(f, dst);
62 }
63 }
64};
65
66float next_common(SkRandom* random) {
67 return random->nextRangeF(-500.0f, 1500.0f);
68}
69float next_any(SkRandom* random) {
70 union { uint32_t u; float f; };
71 u = random->nextU();
72 static_assert(sizeof(float) == sizeof(uint32_t), "");
73 return f;
74}
75
76DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
77DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)
78
79#ifdef SK_SUPPORT_PDF
80
81#include "src/pdf/SkPDFBitmap.h"
82#include "src/pdf/SkPDFDocumentPriv.h"
83#include "src/pdf/SkPDFShader.h"
84#include "src/pdf/SkPDFUtils.h"
85
86namespace {
87class PDFImageBench : public Benchmark {
88public:
89 PDFImageBench() {}
90 ~PDFImageBench() override {}
91
92protected:
93 const char* onGetName() override { return "PDFImage"; }
94 bool isSuitableFor(Backend backend) override {
96 }
97 void onDelayedSetup() override {
98 sk_sp<SkImage> img(ToolUtils::GetResourceAsImage("images/color_wheel.png"));
99 if (img) {
100 // force decoding, throw away reference to encoded data.
101 SkAutoPixmapStorage pixmap;
102 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
103 if (img->readPixels(nullptr, pixmap, 0, 0)) {
104 fImage = SkImages::RasterFromPixmapCopy(pixmap);
105 }
106 }
107 }
108 void onDraw(int loops, SkCanvas*) override {
109 if (!fImage) {
110 return;
111 }
112 while (loops-- > 0) {
113 SkNullWStream nullStream;
114 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
115 doc.beginPage(256, 256);
116 (void)SkPDFSerializeImage(fImage.get(), &doc);
117 }
118 }
119
120private:
121 sk_sp<SkImage> fImage;
122};
123
124class PDFJpegImageBench : public Benchmark {
125public:
126 PDFJpegImageBench() {}
127 ~PDFJpegImageBench() override {}
128
129protected:
130 const char* onGetName() override { return "PDFJpegImage"; }
131 bool isSuitableFor(Backend backend) override {
133 }
134 void onDelayedSetup() override {
135 sk_sp<SkImage> img(ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg"));
136 if (!img) { return; }
137 sk_sp<SkData> encoded = img->refEncodedData();
138 SkASSERT(encoded);
139 if (!encoded) { return; }
140 fImage = img;
141 }
142 void onDraw(int loops, SkCanvas*) override {
143 if (!fImage) {
144 SkDEBUGFAIL("");
145 return;
146 }
147 while (loops-- > 0) {
148 SkNullWStream nullStream;
149 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
150 doc.beginPage(256, 256);
151 (void)SkPDFSerializeImage(fImage.get(), &doc);
152 }
153 }
154
155private:
156 sk_sp<SkImage> fImage;
157};
158
159/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
160 alternate zlib settings, usage, and library versions. */
161class PDFCompressionBench : public Benchmark {
162public:
163 PDFCompressionBench() {}
164 ~PDFCompressionBench() override {}
165
166protected:
167 const char* onGetName() override { return "PDFCompression"; }
168 bool isSuitableFor(Backend backend) override {
170 }
171 void onDelayedSetup() override {
172 fAsset = GetResourceAsStream("pdf_command_stream.txt");
173 }
174 void onDraw(int loops, SkCanvas*) override {
175 SkASSERT(fAsset);
176 if (!fAsset) { return; }
177 while (loops-- > 0) {
178 SkNullWStream wStream;
179 SkPDFDocument doc(&wStream, SkPDF::Metadata());
180 doc.beginPage(256, 256);
181 (void)SkPDFStreamOut(nullptr, fAsset->duplicate(),
183 }
184 }
185
186private:
187 std::unique_ptr<SkStreamAsset> fAsset;
188};
189
190struct PDFColorComponentBench : public Benchmark {
191 bool isSuitableFor(Backend b) override {
192 return b == Backend::kNonRendering;
193 }
194 const char* onGetName() override { return "PDFColorComponent"; }
195 void onDraw(int loops, SkCanvas*) override {
196 char dst[5];
197 while (loops-- > 0) {
198 for (int i = 0; i < 256; ++i) {
200 }
201 }
202 }
203};
204
205struct PDFShaderBench : public Benchmark {
206 sk_sp<SkShader> fShader;
207 const char* onGetName() final { return "PDFShader"; }
208 bool isSuitableFor(Backend b) final { return b == Backend::kNonRendering; }
209 void onDelayedSetup() final {
210 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
211 const SkColor colors[] = {
214 };
216 pts, colors, nullptr, std::size(colors),
218 }
219 void onDraw(int loops, SkCanvas*) final {
220 SkASSERT(fShader);
221 while (loops-- > 0) {
222 SkNullWStream nullStream;
223 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
224 doc.beginPage(256, 256);
225 (void) SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
226 {0, 0, 400, 400}, SkColors::kBlack);
227 }
228 }
229};
230
231struct WritePDFTextBenchmark : public Benchmark {
232 std::unique_ptr<SkWStream> fWStream;
233 WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
234 const char* onGetName() override { return "WritePDFText"; }
235 bool isSuitableFor(Backend backend) override {
237 }
238 void onDraw(int loops, SkCanvas*) override {
239 static const char kHello[] = "HELLO SKIA!\n";
240 static const char kBinary[] = "\001\002\003\004\005\006";
241 while (loops-- > 0) {
242 for (int i = 1000; i-- > 0;) {
243 SkPDFWriteTextString(fWStream.get(), kHello, strlen(kHello));
244 SkPDFWriteByteString(fWStream.get(), kBinary, strlen(kBinary));
245 }
246 }
247 }
248};
249
250// Test for regression chromium:947381
251// with 5c83ae81aa : 2364.99 microsec
252// without 5c83ae81aa : 302821.78 microsec
253struct PDFClipPathBenchmark : public Benchmark {
255 void onDelayedSetup() override {
257 bitmap.allocN32Pixels(256, 256);
258 bitmap.eraseColor(SK_ColorWHITE);
259 {
260 SkCanvas tmp(bitmap);
262 paint.setAntiAlias(false);
264 paint.setStrokeWidth(10);
265 for (int r : {20, 40, 60, 80, 100, 120}) {
266 tmp.drawCircle(128, 128, (float)r, paint);
267 }
268 }
269 fPath.reset();
270 for (int y = 0; y < 256; ++y) {
271 SkColor current = bitmap.getColor(0, y);
272 int start = 0;
273 for (int x = 0; x < 256; ++x) {
274 SkColor color = bitmap.getColor(x, y);
275 if (color == current) {
276 continue;
277 }
278 if (color == SK_ColorBLACK) {
279 start = x;
280 } else {
282 }
283 current = color;
284 }
285 if (current == SK_ColorBLACK) {
286 fPath.addRect(SkRect::Make(SkIRect{start, y, 256, y + 1}));
287 }
288 }
289 }
290 const char* onGetName() override { return "PDFClipPath"; }
291 bool isSuitableFor(Backend backend) override {
293 }
294 void onDraw(int loops, SkCanvas*) override {
295 while (loops-- > 0) {
296 SkNullWStream wStream;
297 SkPDFDocument doc(&wStream, SkPDF::Metadata());
298 SkCanvas* canvas = doc.beginPage(256, 256);
299 canvas->clipPath(fPath);
300 canvas->translate(4.0f/3, 4.0f/3);
301 canvas->clipPath(fPath);
302 canvas->clear(SK_ColorRED);
303 doc.endPage();
304 }
305 }
306};
307
308} // namespace
309DEF_BENCH(return new PDFImageBench;)
310DEF_BENCH(return new PDFJpegImageBench;)
311DEF_BENCH(return new PDFCompressionBench;)
312DEF_BENCH(return new PDFColorComponentBench;)
313DEF_BENCH(return new PDFShaderBench;)
314DEF_BENCH(return new WritePDFTextBenchmark;)
315DEF_BENCH(return new PDFClipPathBenchmark;)
316
317#ifdef SK_PDF_ENABLE_SLOW_TESTS
318#include "include/core/SkExecutor.h"
319namespace {
320void big_pdf_test(SkDocument* doc, const SkBitmap& background) {
321 static const char* kText[] = {
322 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do",
323 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
324 "minim veniam, quis nostrud exercitation ullamco laboris nisi ut",
325 "aliquip ex ea commodo consequat. Duis aute irure dolor in",
326 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla",
327 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in",
328 "culpa qui officia deserunt mollit anim id est laborum.",
329 "",
330 "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
331 "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
332 "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
333 "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
334 "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
335 "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
336 "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
337 "sed quia non numquam do eius modi tempora incididunt, ut labore et",
338 "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
339 "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
340 "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
341 "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
342 "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
343 "pariatur?",
344 "",
345 "At vero eos et accusamus et iusto odio dignissimos ducimus, qui",
346 "blanditiis praesentium voluptatum deleniti atque corrupti, quos",
347 "dolores et quas molestias excepturi sint, obcaecati cupiditate non",
348 "provident, similique sunt in culpa, qui officia deserunt mollitia",
349 "animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis",
350 "est et expedita distinctio. Nam libero tempore, cum soluta nobis est",
351 "eligendi optio, cumque nihil impedit, quo minus id, quod maxime",
352 "placeat, facere possimus, omnis voluptas assumenda est, omnis dolor",
353 "repellendus. Temporibus autem quibusdam et aut officiis debitis aut",
354 "rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint",
355 "et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente",
356 "delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut",
357 "perferendis doloribus asperiores repellat",
358 "",
359 "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
360 "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
361 "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
362 "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
363 "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
364 "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
365 "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
366 "sed quia non numquam do eius modi tempora incididunt, ut labore et",
367 "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
368 "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
369 "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
370 "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
371 "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
372 "pariatur?",
373 "",
374 };
375 SkCanvas* canvas = nullptr;
376 float x = 36;
377 float y = 36;
378 constexpr size_t kLineCount = std::size(kText);
379 constexpr int kLoopCount = 200;
382 for (int loop = 0; loop < kLoopCount; ++loop) {
383 for (size_t line = 0; line < kLineCount; ++line) {
384 y += font.getSpacing();
385 if (!canvas || y > 792 - 36) {
386 y = 36 + font.getSpacing();
387 canvas = doc->beginPage(612, 792);
388 background.notifyPixelsChanged();
389 canvas->drawBitmap(background, 0, 0);
390 }
391 canvas->drawString(kText[line], x, y, font, paint);
392 }
393 }
394}
395
396SkBitmap make_background() {
397 SkBitmap background;
399 bitmap.allocN32Pixels(32, 32);
400 bitmap.eraseColor(SK_ColorWHITE);
401 SkCanvas tmp(bitmap);
402 SkPaint gray;
403 gray.setColor(SkColorSetARGB(0xFF, 0xEE, 0xEE, 0xEE));
404 tmp.drawRect({0,0,16,16}, gray);
405 tmp.drawRect({16,16,32,32}, gray);
406 SkPaint shader;
407 shader.setShader(
408 SkShader::MakeBitmapShader(
409 bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
410 background.allocN32Pixels(612, 792);
411 SkCanvas tmp2(background);
412 tmp2.drawPaint(shader);
413 return background;
414}
415
416struct PDFBigDocBench : public Benchmark {
417 bool fFast;
418 SkBitmap fBackground;
419 std::unique_ptr<SkExecutor> fExecutor;
420 PDFBigDocBench(bool fast) : fFast(fast) {}
421 void onDelayedSetup() override {
422 fBackground = make_background();
423 fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
424 }
425 const char* onGetName() override {
426 static const char kNameFast[] = "PDFBigDocBench_fast";
427 static const char kNameSlow[] = "PDFBigDocBench_slow";
428 return fFast ? kNameFast : kNameSlow;
429 }
430 bool isSuitableFor(Backend backend) override { return backend == Backend::kNonRendering; }
431 void onDraw(int loops, SkCanvas*) override {
432 while (loops-- > 0) {
433 #ifdef SK_PDF_TEST_BIGDOCBENCH_OUTPUT
434 SkFILEWStream wStream("/tmp/big_pdf.pdf");
435 #else
436 SkNullWStream wStream;
437 #endif
438 SkPDF::Metadata metadata;
439 metadata.fExecutor = fExecutor.get();
440 auto doc = SkPDF::MakeDocument(&wStream, metadata);
441 big_pdf_test(doc.get(), fBackground);
442 }
443 }
444};
445} // namespace
446DEF_BENCH(return new PDFBigDocBench(false);)
447DEF_BENCH(return new PDFBigDocBench(true);)
448#endif
449
450#endif // SK_SUPPORT_PDF
SkPath fPath
#define DEF_BENCH(code)
Definition Benchmark.h:20
const char * backend
const char * fName
SkColor4f color
float next_any(SkRandom *random)
Definition PDFBench.cpp:69
float next_common(SkRandom *random)
Definition PDFBench.cpp:66
std::unique_ptr< SkStreamAsset > GetResourceAsStream(const char *resource, bool useFileStream)
Definition Resources.cpp:31
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
uint32_t SkColor
Definition SkColor.h:37
constexpr SkColor SK_ColorBLUE
Definition SkColor.h:135
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
unsigned SkFloatToDecimal(float value, char output[kMaximumSkFloatToDecimalLength])
constexpr unsigned kMaximumSkFloatToDecimalLength
SkPDFIndirectReference SkPDFSerializeImage(const SkImage *img, SkPDFDocument *doc, int encodingQuality)
SkPDFIndirectReference SkPDFMakeShader(SkPDFDocument *doc, SkShader *shader, const SkMatrix &canvasTransform, const SkIRect &surfaceBBox, SkColor4f paintColor)
void SkPDFWriteByteString(SkWStream *wStream, const char *cin, size_t len)
void SkPDFWriteTextString(SkWStream *wStream, const char *cin, size_t len)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22
virtual void onDraw(int loops, SkCanvas *)=0
virtual bool isSuitableFor(Backend backend)
Definition Benchmark.h:55
virtual void onDelayedSetup()
Definition Benchmark.h:101
virtual const char * onGetName()=0
void alloc(const SkImageInfo &)
void notifyPixelsChanged() const
Definition SkBitmap.cpp:365
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition SkBitmap.cpp:232
void translate(SkScalar dx, SkScalar dy)
void clear(SkColor color)
Definition SkCanvas.h:1199
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition SkCanvas.h:1803
SkCanvas * beginPage(SkScalar width, SkScalar height, const SkRect *content=nullptr)
static std::unique_ptr< SkExecutor > MakeFIFOThreadPool(int threads=0, bool allowBorrowing=true)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static const SkMatrix & I()
void setColor(SkColor color)
Definition SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
void setShader(sk_sp< SkShader > shader)
SkPath & reset()
Definition SkPath.cpp:360
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition SkPath.cpp:854
uint32_t nextU()
Definition SkRandom.h:42
float nextRangeF(float min, float max)
Definition SkRandom.h:64
T * get() const
Definition SkRefCnt.h:303
const Paint & paint
static bool b
constexpr char kText[]
Definition glyph_pos.cpp:28
double y
double x
constexpr SkColor4f kBlack
Definition SkColor.h:435
SK_API sk_sp< SkImage > RasterFromPixmapCopy(const SkPixmap &pixmap)
size_t ColorToDecimal(uint8_t value, char result[5])
SK_API sk_sp< SkDocument > MakeDocument(SkWStream *stream, const Metadata &metadata)
PODArray< SkColor > colors
Definition SkRecords.h:276
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition DecodeUtils.h:25
SkFont DefaultFont()
font
Font Metadata and Metrics.
dst
Definition cp.py:12
const char * onGetName() override
Definition PDFBench.cpp:55
void onDraw(int loops, SkCanvas *) override
Definition PDFBench.cpp:56
const char * fName
Definition PDFBench.cpp:50
bool isSuitableFor(Backend b) override
Definition PDFBench.cpp:52
static SkImageInfo MakeN32Premul(int width, int height)
SkExecutor * fExecutor
static SkRect Make(const SkISize &size)
Definition SkRect.h:669