blob: 5b33e8ca152d2d1c9b4d8bf3e2c61819e1c76ae9 [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;
33 SkPDFSubstituteMap substitutes;
34 SkPDFObjNumMap objNumMap;
halcanarya50151d2016-03-25 11:57:49 -070035 objNumMap.addObjectRecursively(object.get(), substitutes);
halcanary1abea462016-02-24 09:25:58 -080036 for (int i = 0; i < objNumMap.objects().count(); ++i) {
halcanarybae235e2016-03-21 10:05:23 -070037 SkPDFObject* object = objNumMap.objects()[i].get();
halcanary1abea462016-02-24 09:25:58 -080038 wStream.writeDecAsText(i + 1);
39 wStream.writeText(" 0 obj\n");
40 object->emitObject(&wStream, objNumMap, substitutes);
41 wStream.writeText("\nendobj\n");
42 }
43}
44
45class PDFImageBench : public Benchmark {
46public:
47 PDFImageBench() {}
48 virtual ~PDFImageBench() {}
49
50protected:
51 const char* onGetName() override { return "PDFImage"; }
52 bool isSuitableFor(Backend backend) override {
53 return backend == kNonRendering_Backend;
54 }
55 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -070056 sk_sp<SkImage> img(GetResourceAsImage("color_wheel.png"));
halcanary1abea462016-02-24 09:25:58 -080057 if (img) {
58 // force decoding, throw away reference to encoded data.
59 SkAutoPixmapStorage pixmap;
60 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
61 if (img->readPixels(pixmap, 0, 0)) {
reed9ce9d672016-03-17 10:51:11 -070062 fImage = SkImage::MakeRasterCopy(pixmap);
halcanary1abea462016-02-24 09:25:58 -080063 }
64 }
65 }
66 void onDraw(int loops, SkCanvas*) override {
67 if (!fImage) {
68 return;
69 }
70 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -070071 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -080072 SkASSERT(object);
73 if (!object) {
74 return;
75 }
76 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -080077 }
78 }
79
80private:
reed9ce9d672016-03-17 10:51:11 -070081 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -080082};
83
84class PDFJpegImageBench : public Benchmark {
85public:
86 PDFJpegImageBench() {}
87 virtual ~PDFJpegImageBench() {}
88
89protected:
90 const char* onGetName() override { return "PDFJpegImage"; }
91 bool isSuitableFor(Backend backend) override {
92 return backend == kNonRendering_Backend;
93 }
94 void onDelayedSetup() override {
reed9ce9d672016-03-17 10:51:11 -070095 sk_sp<SkImage> img(GetResourceAsImage("mandrill_512_q075.jpg"));
halcanary1abea462016-02-24 09:25:58 -080096 if (!img) { return; }
halcanarya50151d2016-03-25 11:57:49 -070097 sk_sp<SkData> encoded(img->refEncoded());
halcanary1abea462016-02-24 09:25:58 -080098 SkASSERT(encoded);
99 if (!encoded) { return; }
reed9ce9d672016-03-17 10:51:11 -0700100 fImage = img;
halcanary1abea462016-02-24 09:25:58 -0800101 }
102 void onDraw(int loops, SkCanvas*) override {
103 if (!fImage) {
104 SkDEBUGFAIL("");
105 return;
106 }
107 while (loops-- > 0) {
halcanarya50151d2016-03-25 11:57:49 -0700108 auto object = SkPDFCreateBitmapObject(fImage, nullptr);
halcanary1e440512016-02-24 15:17:19 -0800109 SkASSERT(object);
110 if (!object) {
111 return;
112 }
113 test_pdf_object_serialization(object);
halcanary1abea462016-02-24 09:25:58 -0800114 }
115 }
116
117private:
reed9ce9d672016-03-17 10:51:11 -0700118 sk_sp<SkImage> fImage;
halcanary1abea462016-02-24 09:25:58 -0800119};
120
halcanary1e440512016-02-24 15:17:19 -0800121/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
122 alternate zlib settings, usage, and library versions. */
123class PDFCompressionBench : public Benchmark {
124public:
125 PDFCompressionBench() {}
126 virtual ~PDFCompressionBench() {}
127
128protected:
129 const char* onGetName() override { return "PDFCompression"; }
130 bool isSuitableFor(Backend backend) override {
131 return backend == kNonRendering_Backend;
132 }
133 void onDelayedSetup() override {
134 fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
135 }
136 void onDraw(int loops, SkCanvas*) override {
137 SkASSERT(fAsset);
138 if (!fAsset) { return; }
139 while (loops-- > 0) {
halcanaryfa251062016-07-29 10:13:18 -0700140 sk_sp<SkPDFObject> object =
141 sk_make_sp<SkPDFSharedStream>(
142 std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
halcanary1e440512016-02-24 15:17:19 -0800143 test_pdf_object_serialization(object);
144 }
145 }
146
147private:
148 SkAutoTDelete<SkStreamAsset> fAsset;
149};
150
halcanarycf430132016-03-09 10:49:23 -0800151// Test speed of SkPDFUtils::FloatToDecimal for typical floats that
152// might be found in a PDF document.
153struct PDFScalarBench : public Benchmark {
154 bool isSuitableFor(Backend b) override {
155 return b == kNonRendering_Backend;
156 }
157 const char* onGetName() override { return "PDFScalar"; }
158 void onDraw(int loops, SkCanvas*) override {
159 SkRandom random;
160 char dst[SkPDFUtils::kMaximumFloatDecimalLength];
161 while (loops-- > 0) {
162 auto f = random.nextRangeF(-500.0f, 1500.0f);
163 (void)SkPDFUtils::FloatToDecimal(f, dst);
164 }
165 }
166};
167
halcanaryeb92cb32016-07-15 13:41:27 -0700168struct PDFColorComponentBench : public Benchmark {
169 bool isSuitableFor(Backend b) override {
170 return b == kNonRendering_Backend;
171 }
172 const char* onGetName() override { return "PDFColorComponent"; }
173 void onDraw(int loops, SkCanvas*) override {
174 char dst[5];
175 while (loops-- > 0) {
176 for (int i = 0; i < 256; ++i) {
177 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
178 }
179 }
180 }
181};
182
halcanaryd11c7262016-03-25 05:52:57 -0700183struct PDFShaderBench : public Benchmark {
184 sk_sp<SkShader> fShader;
185 const char* onGetName() final { return "PDFShader"; }
186 bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
187 void onDelayedSetup() final {
188 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
189 const SkColor colors[] = {
190 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
191 SK_ColorWHITE, SK_ColorBLACK,
192 };
193 fShader = SkGradientShader::MakeLinear(
194 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
195 SkShader::kClamp_TileMode);
196 }
197 void onDraw(int loops, SkCanvas*) final {
198 SkASSERT(fShader);
199 while (loops-- > 0) {
200 NullWStream nullStream;
halcanary4b656662016-04-27 07:45:18 -0700201 SkPDFDocument doc(&nullStream, nullptr, 72,
202 SkDocument::PDFMetadata(), nullptr, false);
halcanaryd11c7262016-03-25 05:52:57 -0700203 sk_sp<SkPDFObject> shader(
204 SkPDFShader::GetPDFShader(
reedfe630452016-03-25 09:08:00 -0700205 &doc, 72, fShader.get(), SkMatrix::I(),
halcanaryd11c7262016-03-25 05:52:57 -0700206 SkIRect::MakeWH(400,400), 72));
207 }
208 }
209};
210
halcanarycbc060a2016-04-11 19:41:48 -0700211struct WStreamWriteTextBenchmark : public Benchmark {
212 std::unique_ptr<SkWStream> fWStream;
213 WStreamWriteTextBenchmark() : fWStream(new NullWStream) {}
214 const char* onGetName() override { return "WStreamWriteText"; }
215 bool isSuitableFor(Backend backend) override {
216 return backend == kNonRendering_Backend;
217 }
218 void onDraw(int loops, SkCanvas*) override {
219 while (loops-- > 0) {
220 for (int i = 1000; i-- > 0;) {
221 fWStream->writeText("HELLO SKIA!\n");
222 }
223 }
224 }
225};
226
halcanaryee41b752016-06-23 14:08:11 -0700227struct WritePDFTextBenchmark : public Benchmark {
228 std::unique_ptr<SkWStream> fWStream;
229 WritePDFTextBenchmark() : fWStream(new NullWStream) {}
230 const char* onGetName() override { return "WritePDFText"; }
231 bool isSuitableFor(Backend backend) override {
232 return backend == kNonRendering_Backend;
233 }
234 void onDraw(int loops, SkCanvas*) override {
235 static const char kHello[] = "HELLO SKIA!\n";
236 static const char kBinary[] = "\001\002\003\004\005\006";
237 while (loops-- > 0) {
238 for (int i = 1000; i-- > 0;) {
239 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
240 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
241 }
242 }
243 }
244};
245
halcanary1abea462016-02-24 09:25:58 -0800246} // namespace
247DEF_BENCH(return new PDFImageBench;)
248DEF_BENCH(return new PDFJpegImageBench;)
halcanary1e440512016-02-24 15:17:19 -0800249DEF_BENCH(return new PDFCompressionBench;)
halcanarycf430132016-03-09 10:49:23 -0800250DEF_BENCH(return new PDFScalarBench;)
halcanaryeb92cb32016-07-15 13:41:27 -0700251DEF_BENCH(return new PDFColorComponentBench;)
halcanaryd11c7262016-03-25 05:52:57 -0700252DEF_BENCH(return new PDFShaderBench;)
halcanarycbc060a2016-04-11 19:41:48 -0700253DEF_BENCH(return new WStreamWriteTextBenchmark;)
halcanaryee41b752016-06-23 14:08:11 -0700254DEF_BENCH(return new WritePDFTextBenchmark;)