blob: 573353fcab731101f0b503627c2f3c4abf4715ce [file] [log] [blame]
halcanary1abea462016-02-24 09:25:58 -08001/*
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 "Benchmark.h"
9#include "Resources.h"
robertphillipsc5035e72016-03-17 06:58:39 -070010#include "SkAutoPixmapStorage.h"
halcanary1abea462016-02-24 09:25:58 -080011#include "SkData.h"
halcanaryd11c7262016-03-25 05:52:57 -070012#include "SkGradientShader.h"
halcanary1e440512016-02-24 15:17:19 -080013#include "SkImage.h"
halcanary1abea462016-02-24 09:25:58 -080014#include "SkPDFBitmap.h"
halcanaryd11c7262016-03-25 05:52:57 -070015#include "SkPDFDocument.h"
16#include "SkPDFShader.h"
halcanarycf430132016-03-09 10:49:23 -080017#include "SkPDFUtils.h"
halcanary1e440512016-02-24 15:17:19 -080018#include "SkPixmap.h"
halcanarycf430132016-03-09 10:49:23 -080019#include "SkRandom.h"
halcanarycbc060a2016-04-11 19:41:48 -070020#include "SkStream.h"
halcanary1abea462016-02-24 09:25:58 -080021
22namespace {
23struct NullWStream : public SkWStream {
24 NullWStream() : fN(0) {}
25 bool write(const void*, size_t n) override { fN += n; return true; }
26 size_t bytesWritten() const override { return fN; }
27 size_t fN;
28};
29
halcanarya50151d2016-03-25 11:57:49 -070030static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
halcanary1abea462016-02-24 09:25:58 -080031 // SkDebugWStream wStream;
32 NullWStream wStream;
halcanary1abea462016-02-24 09:25:58 -080033 SkPDFObjNumMap objNumMap;
halcanary530032a2016-08-18 14:22:52 -070034 objNumMap.addObjectRecursively(object.get());
halcanary1abea462016-02-24 09:25:58 -080035 for (int i = 0; i < objNumMap.objects().count(); ++i) {
halcanarybae235e2016-03-21 10:05:23 -070036 SkPDFObject* object = objNumMap.objects()[i].get();
halcanary1abea462016-02-24 09:25:58 -080037 wStream.writeDecAsText(i + 1);
38 wStream.writeText(" 0 obj\n");
halcanary530032a2016-08-18 14:22:52 -070039 object->emitObject(&wStream, objNumMap);
halcanary1abea462016-02-24 09:25:58 -080040 wStream.writeText("\nendobj\n");
41 }
42}
43
44class PDFImageBench : public Benchmark {
45public:
46 PDFImageBench() {}
47 virtual ~PDFImageBench() {}
48
49protected:
50 const char* onGetName() override { return "PDFImage"; }
51 bool isSuitableFor(Backend backend) override {
52 return backend == kNonRendering_Backend;
53 }
54 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -070055 sk_sp<SkImage> img(GetResourceAsImage("color_wheel.png"));
halcanary1abea462016-02-24 09:25:58 -080056 if (img) {
57 // force decoding, throw away reference to encoded data.
58 SkAutoPixmapStorage pixmap;
59 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
60 if (img->readPixels(pixmap, 0, 0)) {
reed9ce9d672016-03-17 10:51:11 -070061 fImage = SkImage::MakeRasterCopy(pixmap);
halcanary1abea462016-02-24 09:25:58 -080062 }
63 }
64 }
65 void onDraw(int loops, SkCanvas*) override {
66 if (!fImage) {
67 return;
68 }
69 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -070070 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -080071 SkASSERT(object);
72 if (!object) {
73 return;
74 }
75 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -080076 }
77 }
78
79private:
reed9ce9d672016-03-17 10:51:11 -070080 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -080081};
82
83class PDFJpegImageBench : public Benchmark {
84public:
85 PDFJpegImageBench() {}
86 virtual ~PDFJpegImageBench() {}
87
88protected:
89 const char* onGetName() override { return "PDFJpegImage"; }
90 bool isSuitableFor(Backend backend) override {
91 return backend == kNonRendering_Backend;
92 }
93 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -070094 sk_sp<SkImage> img(GetResourceAsImage("mandrill_512_q075.jpg"));
halcanary1abea462016-02-24 09:25:58 -080095 if (!img) { return; }
halcanarya50151d2016-03-25 11:57:49 -070096 sk_sp<SkData> encoded(img->refEncoded());
halcanary1abea462016-02-24 09:25:58 -080097 SkASSERT(encoded);
98 if (!encoded) { return; }
reed9ce9d672016-03-17 10:51:11 -070099 fImage = img;
halcanary1abea462016-02-24 09:25:58 -0800100 }
101 void onDraw(int loops, SkCanvas*) override {
102 if (!fImage) {
103 SkDEBUGFAIL("");
104 return;
105 }
106 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -0700107 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -0800108 SkASSERT(object);
109 if (!object) {
110 return;
111 }
112 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800113 }
114 }
115
116private:
reed9ce9d672016-03-17 10:51:11 -0700117 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800118};
119
halcanary1e440512016-02-24 15:17:19 -0800120/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
121 alternate zlib settings, usage, and library versions. */
122class PDFCompressionBench : public Benchmark {
123public:
124 PDFCompressionBench() {}
125 virtual ~PDFCompressionBench() {}
126
127protected:
128 const char* onGetName() override { return "PDFCompression"; }
129 bool isSuitableFor(Backend backend) override {
130 return backend == kNonRendering_Backend;
131 }
132 void onDelayedSetup() override {
133 fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
134 }
135 void onDraw(int loops, SkCanvas*) override {
136 SkASSERT(fAsset);
137 if (!fAsset) { return; }
138 while (loops-- > 0) {
halcanaryfa251062016-07-29 10:13:18 -0700139 sk_sp<SkPDFObject> object =
140 sk_make_sp<SkPDFSharedStream>(
141 std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
halcanary1e440512016-02-24 15:17:19 -0800142 test_pdf_object_serialization(object);
143 }
144 }
145
146private:
Ben Wagner145dbcd2016-11-03 14:40:50 -0400147 std::unique_ptr<SkStreamAsset> fAsset;
halcanary1e440512016-02-24 15:17:19 -0800148};
149
halcanarycf430132016-03-09 10:49:23 -0800150// Test speed of SkPDFUtils::FloatToDecimal for typical floats that
151// might be found in a PDF document.
152struct PDFScalarBench : public Benchmark {
153 bool isSuitableFor(Backend b) override {
154 return b == kNonRendering_Backend;
155 }
156 const char* onGetName() override { return "PDFScalar"; }
157 void onDraw(int loops, SkCanvas*) override {
158 SkRandom random;
159 char dst[SkPDFUtils::kMaximumFloatDecimalLength];
160 while (loops-- > 0) {
161 auto f = random.nextRangeF(-500.0f, 1500.0f);
162 (void)SkPDFUtils::FloatToDecimal(f, dst);
163 }
164 }
165};
166
halcanaryeb92cb32016-07-15 13:41:27 -0700167struct PDFColorComponentBench : public Benchmark {
168 bool isSuitableFor(Backend b) override {
169 return b == kNonRendering_Backend;
170 }
171 const char* onGetName() override { return "PDFColorComponent"; }
172 void onDraw(int loops, SkCanvas*) override {
173 char dst[5];
174 while (loops-- > 0) {
175 for (int i = 0; i < 256; ++i) {
176 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
177 }
178 }
179 }
180};
181
halcanaryd11c7262016-03-25 05:52:57 -0700182struct PDFShaderBench : public Benchmark {
183 sk_sp<SkShader> fShader;
184 const char* onGetName() final { return "PDFShader"; }
185 bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
186 void onDelayedSetup() final {
187 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
188 const SkColor colors[] = {
189 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
190 SK_ColorWHITE, SK_ColorBLACK,
191 };
192 fShader = SkGradientShader::MakeLinear(
193 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
194 SkShader::kClamp_TileMode);
195 }
196 void onDraw(int loops, SkCanvas*) final {
197 SkASSERT(fShader);
198 while (loops-- > 0) {
199 NullWStream nullStream;
halcanary4b656662016-04-27 07:45:18 -0700200 SkPDFDocument doc(&nullStream, nullptr, 72,
201 SkDocument::PDFMetadata(), nullptr, false);
halcanaryd11c7262016-03-25 05:52:57 -0700202 sk_sp<SkPDFObject> shader(
203 SkPDFShader::GetPDFShader(
reedfe630452016-03-25 09:08:00 -0700204 &doc, 72, fShader.get(), SkMatrix::I(),
halcanaryd11c7262016-03-25 05:52:57 -0700205 SkIRect::MakeWH(400,400), 72));
206 }
207 }
208};
209
halcanarycbc060a2016-04-11 19:41:48 -0700210struct WStreamWriteTextBenchmark : public Benchmark {
211 std::unique_ptr<SkWStream> fWStream;
212 WStreamWriteTextBenchmark() : fWStream(new NullWStream) {}
213 const char* onGetName() override { return "WStreamWriteText"; }
214 bool isSuitableFor(Backend backend) override {
215 return backend == kNonRendering_Backend;
216 }
217 void onDraw(int loops, SkCanvas*) override {
218 while (loops-- > 0) {
219 for (int i = 1000; i-- > 0;) {
220 fWStream->writeText("HELLO SKIA!\n");
221 }
222 }
223 }
224};
225
halcanaryee41b752016-06-23 14:08:11 -0700226struct WritePDFTextBenchmark : public Benchmark {
227 std::unique_ptr<SkWStream> fWStream;
228 WritePDFTextBenchmark() : fWStream(new NullWStream) {}
229 const char* onGetName() override { return "WritePDFText"; }
230 bool isSuitableFor(Backend backend) override {
231 return backend == kNonRendering_Backend;
232 }
233 void onDraw(int loops, SkCanvas*) override {
234 static const char kHello[] = "HELLO SKIA!\n";
235 static const char kBinary[] = "\001\002\003\004\005\006";
236 while (loops-- > 0) {
237 for (int i = 1000; i-- > 0;) {
238 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
239 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
240 }
241 }
242 }
243};
244
halcanary1abea462016-02-24 09:25:58 -0800245} // namespace
246DEF_BENCH(return new PDFImageBench;)
247DEF_BENCH(return new PDFJpegImageBench;)
halcanary1e440512016-02-24 15:17:19 -0800248DEF_BENCH(return new PDFCompressionBench;)
halcanarycf430132016-03-09 10:49:23 -0800249DEF_BENCH(return new PDFScalarBench;)
halcanaryeb92cb32016-07-15 13:41:27 -0700250DEF_BENCH(return new PDFColorComponentBench;)
halcanaryd11c7262016-03-25 05:52:57 -0700251DEF_BENCH(return new PDFShaderBench;)
halcanarycbc060a2016-04-11 19:41:48 -0700252DEF_BENCH(return new WStreamWriteTextBenchmark;)
halcanaryee41b752016-06-23 14:08:11 -0700253DEF_BENCH(return new WritePDFTextBenchmark;)