• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Benchmark.h"
9 
10 #include "Resources.h"
11 #include "SkAutoPixmapStorage.h"
12 #include "SkData.h"
13 #include "SkGradientShader.h"
14 #include "SkImage.h"
15 #include "SkPixmap.h"
16 #include "SkRandom.h"
17 #include "SkStream.h"
18 
19 namespace {
20 struct WStreamWriteTextBenchmark : public Benchmark {
21     std::unique_ptr<SkWStream> fWStream;
WStreamWriteTextBenchmark__anon23e44b610111::WStreamWriteTextBenchmark22     WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anon23e44b610111::WStreamWriteTextBenchmark23     const char* onGetName() override { return "WStreamWriteText"; }
isSuitableFor__anon23e44b610111::WStreamWriteTextBenchmark24     bool isSuitableFor(Backend backend) override {
25         return backend == kNonRendering_Backend;
26     }
onDraw__anon23e44b610111::WStreamWriteTextBenchmark27     void onDraw(int loops, SkCanvas*) override {
28         while (loops-- > 0) {
29             for (int i = 1000; i-- > 0;) {
30                 fWStream->writeText("HELLO SKIA!\n");
31             }
32         }
33     }
34 };
35 }  // namespace
36 
37 DEF_BENCH(return new WStreamWriteTextBenchmark;)
38 
39 #ifdef SK_SUPPORT_PDF
40 
41 #include "SkPDFBitmap.h"
42 #include "SkPDFDocument.h"
43 #include "SkPDFShader.h"
44 #include "SkPDFUtils.h"
45 
46 namespace {
test_pdf_object_serialization(const sk_sp<SkPDFObject> object)47 static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
48     // SkDebugWStream wStream;
49     SkNullWStream wStream;
50     SkPDFObjNumMap objNumMap;
51     objNumMap.addObjectRecursively(object.get());
52     for (int i = 0; i < objNumMap.objects().count(); ++i) {
53         SkPDFObject* object = objNumMap.objects()[i].get();
54         wStream.writeDecAsText(i + 1);
55         wStream.writeText(" 0 obj\n");
56         object->emitObject(&wStream, objNumMap);
57         wStream.writeText("\nendobj\n");
58     }
59 }
60 
61 class PDFImageBench : public Benchmark {
62 public:
PDFImageBench()63     PDFImageBench() {}
~PDFImageBench()64     ~PDFImageBench() override {}
65 
66 protected:
onGetName()67     const char* onGetName() override { return "PDFImage"; }
isSuitableFor(Backend backend)68     bool isSuitableFor(Backend backend) override {
69         return backend == kNonRendering_Backend;
70     }
onDelayedSetup()71     void onDelayedSetup() override {
72         sk_sp<SkImage> img(GetResourceAsImage("color_wheel.png"));
73         if (img) {
74             // force decoding, throw away reference to encoded data.
75             SkAutoPixmapStorage pixmap;
76             pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
77             if (img->readPixels(pixmap, 0, 0)) {
78                 fImage = SkImage::MakeRasterCopy(pixmap);
79             }
80         }
81     }
onDraw(int loops,SkCanvas *)82     void onDraw(int loops, SkCanvas*) override {
83         if (!fImage) {
84             return;
85         }
86         while (loops-- > 0) {
87             auto object = SkPDFCreateBitmapObject(fImage, nullptr);
88             SkASSERT(object);
89             if (!object) {
90                 return;
91             }
92             test_pdf_object_serialization(object);
93         }
94     }
95 
96 private:
97     sk_sp<SkImage> fImage;
98 };
99 
100 class PDFJpegImageBench : public Benchmark {
101 public:
PDFJpegImageBench()102     PDFJpegImageBench() {}
~PDFJpegImageBench()103     ~PDFJpegImageBench() override {}
104 
105 protected:
onGetName()106     const char* onGetName() override { return "PDFJpegImage"; }
isSuitableFor(Backend backend)107     bool isSuitableFor(Backend backend) override {
108         return backend == kNonRendering_Backend;
109     }
onDelayedSetup()110     void onDelayedSetup() override {
111         sk_sp<SkImage> img(GetResourceAsImage("mandrill_512_q075.jpg"));
112         if (!img) { return; }
113         sk_sp<SkData> encoded = img->refEncodedData();
114         SkASSERT(encoded);
115         if (!encoded) { return; }
116         fImage = img;
117     }
onDraw(int loops,SkCanvas *)118     void onDraw(int loops, SkCanvas*) override {
119         if (!fImage) {
120             SkDEBUGFAIL("");
121             return;
122         }
123         while (loops-- > 0) {
124             auto object = SkPDFCreateBitmapObject(fImage, nullptr);
125             SkASSERT(object);
126             if (!object) {
127                 return;
128             }
129             test_pdf_object_serialization(object);
130         }
131     }
132 
133 private:
134     sk_sp<SkImage> fImage;
135 };
136 
137 /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
138     alternate zlib settings, usage, and library versions. */
139 class PDFCompressionBench : public Benchmark {
140 public:
PDFCompressionBench()141     PDFCompressionBench() {}
~PDFCompressionBench()142     ~PDFCompressionBench() override {}
143 
144 protected:
onGetName()145     const char* onGetName() override { return "PDFCompression"; }
isSuitableFor(Backend backend)146     bool isSuitableFor(Backend backend) override {
147         return backend == kNonRendering_Backend;
148     }
onDelayedSetup()149     void onDelayedSetup() override {
150         fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
151     }
onDraw(int loops,SkCanvas *)152     void onDraw(int loops, SkCanvas*) override {
153         SkASSERT(fAsset);
154         if (!fAsset) { return; }
155         while (loops-- > 0) {
156             sk_sp<SkPDFObject> object =
157                 sk_make_sp<SkPDFSharedStream>(
158                         std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
159             test_pdf_object_serialization(object);
160         }
161     }
162 
163 private:
164     std::unique_ptr<SkStreamAsset> fAsset;
165 };
166 
167 // Test speed of SkPDFUtils::FloatToDecimal for typical floats that
168 // might be found in a PDF document.
169 struct PDFScalarBench : public Benchmark {
isSuitableFor__anon23e44b610211::PDFScalarBench170     bool isSuitableFor(Backend b) override {
171         return b == kNonRendering_Backend;
172     }
onGetName__anon23e44b610211::PDFScalarBench173     const char* onGetName() override { return "PDFScalar"; }
onDraw__anon23e44b610211::PDFScalarBench174     void onDraw(int loops, SkCanvas*) override {
175         SkRandom random;
176         char dst[SkPDFUtils::kMaximumFloatDecimalLength];
177         while (loops-- > 0) {
178             auto f = random.nextRangeF(-500.0f, 1500.0f);
179             (void)SkPDFUtils::FloatToDecimal(f, dst);
180         }
181     }
182 };
183 
184 struct PDFColorComponentBench : public Benchmark {
isSuitableFor__anon23e44b610211::PDFColorComponentBench185     bool isSuitableFor(Backend b) override {
186         return b == kNonRendering_Backend;
187     }
onGetName__anon23e44b610211::PDFColorComponentBench188     const char* onGetName() override { return "PDFColorComponent"; }
onDraw__anon23e44b610211::PDFColorComponentBench189     void onDraw(int loops, SkCanvas*) override {
190         char dst[5];
191         while (loops-- > 0) {
192             for (int i = 0; i < 256; ++i) {
193                 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
194             }
195         }
196     }
197 };
198 
199 struct PDFShaderBench : public Benchmark {
200     sk_sp<SkShader> fShader;
onGetName__anon23e44b610211::PDFShaderBench201     const char* onGetName() final { return "PDFShader"; }
isSuitableFor__anon23e44b610211::PDFShaderBench202     bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
onDelayedSetup__anon23e44b610211::PDFShaderBench203     void onDelayedSetup() final {
204         const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
205         const SkColor colors[] = {
206             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
207             SK_ColorWHITE, SK_ColorBLACK,
208         };
209         fShader = SkGradientShader::MakeLinear(
210                 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
211                 SkShader::kClamp_TileMode);
212     }
onDraw__anon23e44b610211::PDFShaderBench213     void onDraw(int loops, SkCanvas*) final {
214         SkASSERT(fShader);
215         while (loops-- > 0) {
216             SkNullWStream nullStream;
217             SkPDFDocument doc(&nullStream, nullptr, 72,
218                               SkDocument::PDFMetadata(), nullptr, false);
219             sk_sp<SkPDFObject> shader =
220                     SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(), {0, 0, 400,400});
221         }
222     }
223 };
224 
225 struct WritePDFTextBenchmark : public Benchmark {
226     std::unique_ptr<SkWStream> fWStream;
WritePDFTextBenchmark__anon23e44b610211::WritePDFTextBenchmark227     WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anon23e44b610211::WritePDFTextBenchmark228     const char* onGetName() override { return "WritePDFText"; }
isSuitableFor__anon23e44b610211::WritePDFTextBenchmark229     bool isSuitableFor(Backend backend) override {
230         return backend == kNonRendering_Backend;
231     }
onDraw__anon23e44b610211::WritePDFTextBenchmark232     void onDraw(int loops, SkCanvas*) override {
233         static const char kHello[] = "HELLO SKIA!\n";
234         static const char kBinary[] = "\001\002\003\004\005\006";
235         while (loops-- > 0) {
236             for (int i = 1000; i-- > 0;) {
237                 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
238                 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
239             }
240         }
241     }
242 };
243 
244 }  // namespace
245 DEF_BENCH(return new PDFImageBench;)
246 DEF_BENCH(return new PDFJpegImageBench;)
247 DEF_BENCH(return new PDFCompressionBench;)
248 DEF_BENCH(return new PDFScalarBench;)
249 DEF_BENCH(return new PDFColorComponentBench;)
250 DEF_BENCH(return new PDFShaderBench;)
251 DEF_BENCH(return new WritePDFTextBenchmark;)
252 
253 #endif
254 
255