1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "bench/Benchmark.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h" 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker /* 23*c8dee2aaSAndroid Build Coastguard Worker * A trivial test which benchmarks the performance of a textblob with a single run. 24*c8dee2aaSAndroid Build Coastguard Worker */ 25*c8dee2aaSAndroid Build Coastguard Worker class SkTextBlobBench : public Benchmark { 26*c8dee2aaSAndroid Build Coastguard Worker public: SkTextBlobBench()27*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobBench() {} 28*c8dee2aaSAndroid Build Coastguard Worker onDelayedSetup()29*c8dee2aaSAndroid Build Coastguard Worker void onDelayedSetup() override { 30*c8dee2aaSAndroid Build Coastguard Worker fFont.setTypeface(ToolUtils::CreatePortableTypeface("serif", SkFontStyle())); 31*c8dee2aaSAndroid Build Coastguard Worker fFont.setSubpixel(true); 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker // This text seems representative in both length and letter frequency. 34*c8dee2aaSAndroid Build Coastguard Worker const char* text = "Keep your sentences short, but not overly so."; 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker fGlyphs.resize(fFont.countText(text, strlen(text), SkTextEncoding::kUTF8)); 37*c8dee2aaSAndroid Build Coastguard Worker fXPos.resize(fGlyphs.size()); 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Worker fFont.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphs.size()); 40*c8dee2aaSAndroid Build Coastguard Worker fFont.getXPos(&fGlyphs[0], fGlyphs.size(), fXPos.begin()); 41*c8dee2aaSAndroid Build Coastguard Worker } 42*c8dee2aaSAndroid Build Coastguard Worker makeBlob()43*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkTextBlob> makeBlob() { 44*c8dee2aaSAndroid Build Coastguard Worker const SkTextBlobBuilder::RunBuffer& run = 45*c8dee2aaSAndroid Build Coastguard Worker fBuilder.allocRunPosH(fFont, fGlyphs.size(), 10, nullptr); 46*c8dee2aaSAndroid Build Coastguard Worker memcpy(run.glyphs, &fGlyphs[0], fGlyphs.size() * sizeof(uint16_t)); 47*c8dee2aaSAndroid Build Coastguard Worker memcpy(run.pos, &fXPos[0], fXPos.size() * sizeof(SkScalar)); 48*c8dee2aaSAndroid Build Coastguard Worker return fBuilder.make(); 49*c8dee2aaSAndroid Build Coastguard Worker } 50*c8dee2aaSAndroid Build Coastguard Worker 51*c8dee2aaSAndroid Build Coastguard Worker private: 52*c8dee2aaSAndroid Build Coastguard Worker SkTextBlobBuilder fBuilder; 53*c8dee2aaSAndroid Build Coastguard Worker SkFont fFont; 54*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<uint16_t> fGlyphs; 55*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkScalar> fXPos; 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 58*c8dee2aaSAndroid Build Coastguard Worker }; 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker class TextBlobCachedBench : public SkTextBlobBench { onGetName()61*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 62*c8dee2aaSAndroid Build Coastguard Worker return "TextBlobCachedBench"; 63*c8dee2aaSAndroid Build Coastguard Worker } 64*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)65*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 66*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker auto blob = this->makeBlob(); 69*c8dee2aaSAndroid Build Coastguard Worker auto bigLoops = loops * 100; 70*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < bigLoops; i++) { 71*c8dee2aaSAndroid Build Coastguard Worker // To ensure maximum caching, we just redraw the blob at the same place everytime 72*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(blob, 0, 0, paint); 73*c8dee2aaSAndroid Build Coastguard Worker } 74*c8dee2aaSAndroid Build Coastguard Worker } 75*c8dee2aaSAndroid Build Coastguard Worker }; 76*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new TextBlobCachedBench(); ) 77*c8dee2aaSAndroid Build Coastguard Worker 78*c8dee2aaSAndroid Build Coastguard Worker class TextBlobFirstTimeBench : public SkTextBlobBench { onGetName()79*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 80*c8dee2aaSAndroid Build Coastguard Worker return "TextBlobFirstTimeBench"; 81*c8dee2aaSAndroid Build Coastguard Worker } 82*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)83*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 84*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint; 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker auto bigLoops = loops * 100; 87*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < bigLoops; i++) { 88*c8dee2aaSAndroid Build Coastguard Worker canvas->drawTextBlob(this->makeBlob(), 0, 0, paint); 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker } 91*c8dee2aaSAndroid Build Coastguard Worker }; 92*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new TextBlobFirstTimeBench(); ) 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker class TextBlobMakeBench : public SkTextBlobBench { onGetName()95*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 96*c8dee2aaSAndroid Build Coastguard Worker return "TextBlobMakeBench"; 97*c8dee2aaSAndroid Build Coastguard Worker } 98*c8dee2aaSAndroid Build Coastguard Worker isSuitableFor(Backend backend)99*c8dee2aaSAndroid Build Coastguard Worker bool isSuitableFor(Backend backend) override { 100*c8dee2aaSAndroid Build Coastguard Worker return backend == Backend::kNonRendering; 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas *)103*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas*) override { 104*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < loops; i++) { 105*c8dee2aaSAndroid Build Coastguard Worker for (int inner = 0; inner < 1000; ++inner) { 106*c8dee2aaSAndroid Build Coastguard Worker this->makeBlob(); 107*c8dee2aaSAndroid Build Coastguard Worker } 108*c8dee2aaSAndroid Build Coastguard Worker } 109*c8dee2aaSAndroid Build Coastguard Worker } 110*c8dee2aaSAndroid Build Coastguard Worker }; 111*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH( return new TextBlobMakeBench(); ) 112