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 #include "Resources.h"
10 #include "SkData.h"
11 #include "SkImage.h"
12 #include "SkPDFBitmap.h"
13 #include "SkPixmap.h"
14 
15 namespace {
16 struct NullWStream : public SkWStream {
NullWStream__anon0b7e5f620111::NullWStream17     NullWStream() : fN(0) {}
write__anon0b7e5f620111::NullWStream18     bool write(const void*, size_t n) override { fN += n; return true; }
bytesWritten__anon0b7e5f620111::NullWStream19     size_t bytesWritten() const override { return fN; }
20     size_t fN;
21 };
22 
test_pdf_object_serialization(SkPDFObject * object)23 static void test_pdf_object_serialization(SkPDFObject* object) {
24     // SkDebugWStream wStream;
25     NullWStream wStream;
26     SkPDFSubstituteMap substitutes;
27     SkPDFObjNumMap objNumMap;
28     objNumMap.addObjectRecursively(object, substitutes);
29     for (int i = 0; i < objNumMap.objects().count(); ++i) {
30         SkPDFObject* object = objNumMap.objects()[i];
31         wStream.writeDecAsText(i + 1);
32         wStream.writeText(" 0 obj\n");
33         object->emitObject(&wStream, objNumMap, substitutes);
34         wStream.writeText("\nendobj\n");
35     }
36 }
37 
38 class PDFImageBench : public Benchmark {
39 public:
PDFImageBench()40     PDFImageBench() {}
~PDFImageBench()41     virtual ~PDFImageBench() {}
42 
43 protected:
onGetName()44     const char* onGetName() override { return "PDFImage"; }
isSuitableFor(Backend backend)45     bool isSuitableFor(Backend backend) override {
46         return backend == kNonRendering_Backend;
47     }
onDelayedSetup()48     void onDelayedSetup() override {
49         SkAutoTUnref<SkImage> img(GetResourceAsImage("color_wheel.png"));
50         if (img) {
51             // force decoding, throw away reference to encoded data.
52             SkAutoPixmapStorage pixmap;
53             pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
54             if (img->readPixels(pixmap, 0, 0)) {
55                 fImage.reset(SkImage::NewRasterCopy(
56                                      pixmap.info(), pixmap.addr(),
57                                      pixmap.rowBytes(), pixmap.ctable()));
58             }
59         }
60     }
onDraw(int loops,SkCanvas *)61     void onDraw(int loops, SkCanvas*) override {
62         if (!fImage) {
63             return;
64         }
65         while (loops-- > 0) {
66             SkAutoTUnref<SkPDFObject> object(
67                     SkPDFCreateBitmapObject(fImage, nullptr));
68             SkASSERT(object);
69             if (!object) {
70                 return;
71             }
72             test_pdf_object_serialization(object);
73         }
74     }
75 
76 private:
77     SkAutoTUnref<SkImage> fImage;
78 };
79 
80 class PDFJpegImageBench : public Benchmark {
81 public:
PDFJpegImageBench()82     PDFJpegImageBench() {}
~PDFJpegImageBench()83     virtual ~PDFJpegImageBench() {}
84 
85 protected:
onGetName()86     const char* onGetName() override { return "PDFJpegImage"; }
isSuitableFor(Backend backend)87     bool isSuitableFor(Backend backend) override {
88         return backend == kNonRendering_Backend;
89     }
onDelayedSetup()90     void onDelayedSetup() override {
91         SkAutoTUnref<SkImage> img(
92                 GetResourceAsImage("mandrill_512_q075.jpg"));
93         if (!img) { return; }
94         SkAutoTUnref<SkData> encoded(img->refEncoded());
95         SkASSERT(encoded);
96         if (!encoded) { return; }
97         fImage.reset(img.release());
98     }
onDraw(int loops,SkCanvas *)99     void onDraw(int loops, SkCanvas*) override {
100         if (!fImage) {
101             SkDEBUGFAIL("");
102             return;
103         }
104         while (loops-- > 0) {
105             SkAutoTUnref<SkPDFObject> object(
106                     SkPDFCreateBitmapObject(fImage, nullptr));
107             SkASSERT(object);
108             if (!object) {
109                 return;
110             }
111             test_pdf_object_serialization(object);
112         }
113     }
114 
115 private:
116     SkAutoTUnref<SkImage> fImage;
117 };
118 
119 /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
120     alternate zlib settings, usage, and library versions. */
121 class PDFCompressionBench : public Benchmark {
122 public:
PDFCompressionBench()123     PDFCompressionBench() {}
~PDFCompressionBench()124     virtual ~PDFCompressionBench() {}
125 
126 protected:
onGetName()127     const char* onGetName() override { return "PDFCompression"; }
isSuitableFor(Backend backend)128     bool isSuitableFor(Backend backend) override {
129         return backend == kNonRendering_Backend;
130     }
onDelayedSetup()131     void onDelayedSetup() override {
132         fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
133     }
onDraw(int loops,SkCanvas *)134     void onDraw(int loops, SkCanvas*) override {
135         SkASSERT(fAsset);
136         if (!fAsset) { return; }
137         while (loops-- > 0) {
138             SkAutoTUnref<SkPDFObject> object(
139                     new SkPDFSharedStream(fAsset->duplicate()));
140             test_pdf_object_serialization(object);
141         }
142     }
143 
144 private:
145     SkAutoTDelete<SkStreamAsset> fAsset;
146 };
147 
148 }  // namespace
149 DEF_BENCH(return new PDFImageBench;)
150 DEF_BENCH(return new PDFJpegImageBench;)
151 DEF_BENCH(return new PDFCompressionBench;)
152