/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Benchmark.h" #include "Resources.h" #include "SkData.h" #include "SkImage.h" #include "SkPDFBitmap.h" #include "SkPDFUtils.h" #include "SkPixmap.h" #include "SkRandom.h" namespace { struct NullWStream : public SkWStream { NullWStream() : fN(0) {} bool write(const void*, size_t n) override { fN += n; return true; } size_t bytesWritten() const override { return fN; } size_t fN; }; static void test_pdf_object_serialization(SkPDFObject* object) { // SkDebugWStream wStream; NullWStream wStream; SkPDFSubstituteMap substitutes; SkPDFObjNumMap objNumMap; objNumMap.addObjectRecursively(object, substitutes); for (int i = 0; i < objNumMap.objects().count(); ++i) { SkPDFObject* object = objNumMap.objects()[i]; wStream.writeDecAsText(i + 1); wStream.writeText(" 0 obj\n"); object->emitObject(&wStream, objNumMap, substitutes); wStream.writeText("\nendobj\n"); } } class PDFImageBench : public Benchmark { public: PDFImageBench() {} virtual ~PDFImageBench() {} protected: const char* onGetName() override { return "PDFImage"; } bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } void onDelayedSetup() override { SkAutoTUnref img(GetResourceAsImage("color_wheel.png")); if (img) { // force decoding, throw away reference to encoded data. SkAutoPixmapStorage pixmap; pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions())); if (img->readPixels(pixmap, 0, 0)) { fImage.reset(SkImage::NewRasterCopy( pixmap.info(), pixmap.addr(), pixmap.rowBytes(), pixmap.ctable())); } } } void onDraw(int loops, SkCanvas*) override { if (!fImage) { return; } while (loops-- > 0) { SkAutoTUnref object( SkPDFCreateBitmapObject(fImage, nullptr)); SkASSERT(object); if (!object) { return; } test_pdf_object_serialization(object); } } private: SkAutoTUnref fImage; }; class PDFJpegImageBench : public Benchmark { public: PDFJpegImageBench() {} virtual ~PDFJpegImageBench() {} protected: const char* onGetName() override { return "PDFJpegImage"; } bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } void onDelayedSetup() override { SkAutoTUnref img( GetResourceAsImage("mandrill_512_q075.jpg")); if (!img) { return; } SkAutoTUnref encoded(img->refEncoded()); SkASSERT(encoded); if (!encoded) { return; } fImage.reset(img.release()); } void onDraw(int loops, SkCanvas*) override { if (!fImage) { SkDEBUGFAIL(""); return; } while (loops-- > 0) { SkAutoTUnref object( SkPDFCreateBitmapObject(fImage, nullptr)); SkASSERT(object); if (!object) { return; } test_pdf_object_serialization(object); } } private: SkAutoTUnref fImage; }; /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring alternate zlib settings, usage, and library versions. */ class PDFCompressionBench : public Benchmark { public: PDFCompressionBench() {} virtual ~PDFCompressionBench() {} protected: const char* onGetName() override { return "PDFCompression"; } bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } void onDelayedSetup() override { fAsset.reset(GetResourceAsStream("pdf_command_stream.txt")); } void onDraw(int loops, SkCanvas*) override { SkASSERT(fAsset); if (!fAsset) { return; } while (loops-- > 0) { SkAutoTUnref object( new SkPDFSharedStream(fAsset->duplicate())); test_pdf_object_serialization(object); } } private: SkAutoTDelete fAsset; }; // Test speed of SkPDFUtils::FloatToDecimal for typical floats that // might be found in a PDF document. struct PDFScalarBench : public Benchmark { bool isSuitableFor(Backend b) override { return b == kNonRendering_Backend; } const char* onGetName() override { return "PDFScalar"; } void onDraw(int loops, SkCanvas*) override { SkRandom random; char dst[SkPDFUtils::kMaximumFloatDecimalLength]; while (loops-- > 0) { auto f = random.nextRangeF(-500.0f, 1500.0f); (void)SkPDFUtils::FloatToDecimal(f, dst); } } }; } // namespace DEF_BENCH(return new PDFImageBench;) DEF_BENCH(return new PDFJpegImageBench;) DEF_BENCH(return new PDFCompressionBench;) DEF_BENCH(return new PDFScalarBench;)