/* * Copyright 2015 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 "SkCanvas.h" #include "SkFont.h" #include "SkPaint.h" #include "SkRandom.h" #include "SkStream.h" #include "SkString.h" #include "SkTemplates.h" #include "SkTextBlob.h" #include "SkTypeface.h" #include "sk_tool_utils.h" /* * A trivial test which benchmarks the performance of a textblob with a single run. */ class SkTextBlobBench : public Benchmark { public: SkTextBlobBench() {} void onDelayedSetup() override { fFont.setTypeface(sk_tool_utils::create_portable_typeface("serif", SkFontStyle())); fFont.setSubpixel(true); // This text seems representative in both length and letter frequency. const char* text = "Keep your sentences short, but not overly so."; fGlyphs.setCount(fFont.countText(text, strlen(text), kUTF8_SkTextEncoding)); fXPos.setCount(fGlyphs.count()); fFont.textToGlyphs(text, strlen(text), kUTF8_SkTextEncoding, fGlyphs.begin(), fGlyphs.count()); fFont.getXPos(&fGlyphs[0], fGlyphs.count(), fXPos.begin()); } sk_sp makeBlob() { const SkTextBlobBuilder::RunBuffer& run = fBuilder.allocRunPosH(fFont, fGlyphs.count(), 10, nullptr); memcpy(run.glyphs, &fGlyphs[0], fGlyphs.count() * sizeof(uint16_t)); memcpy(run.pos, &fXPos[0], fXPos.count() * sizeof(SkScalar)); return fBuilder.make(); } private: SkTextBlobBuilder fBuilder; SkFont fFont; SkTDArray fGlyphs; SkTDArray fXPos; typedef Benchmark INHERITED; }; class TextBlobCachedBench : public SkTextBlobBench { const char* onGetName() override { return "TextBlobCachedBench"; } void onDraw(int loops, SkCanvas* canvas) override { SkPaint paint; auto blob = this->makeBlob(); auto bigLoops = loops * 100; for (int i = 0; i < bigLoops; i++) { // To ensure maximum caching, we just redraw the blob at the same place everytime canvas->drawTextBlob(blob, 0, 0, paint); } } }; DEF_BENCH( return new TextBlobCachedBench(); ) class TextBlobFirstTimeBench : public SkTextBlobBench { const char* onGetName() override { return "TextBlobFirstTimeBench"; } void onDraw(int loops, SkCanvas* canvas) override { SkPaint paint; auto bigLoops = loops * 100; for (int i = 0; i < bigLoops; i++) { canvas->drawTextBlob(this->makeBlob(), 0, 0, paint); } } }; DEF_BENCH( return new TextBlobFirstTimeBench(); ) class TextBlobMakeBench : public SkTextBlobBench { const char* onGetName() override { return "TextBlobMakeBench"; } bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; } void onDraw(int loops, SkCanvas*) override { for (int i = 0; i < loops; i++) { for (int inner = 0; inner < 1000; ++inner) { this->makeBlob(); } } } }; DEF_BENCH( return new TextBlobMakeBench(); )