1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 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/SkPath.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkRandom.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrike.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrikeCache.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStrikeSpec.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h" 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kScreenWidth = 1500; 21*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kScreenHeight = 1500; 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumDraws = 2000; 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker // I and l are rects on OS X. 26*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kGlyphs[] = "ABCDEFGH7JKLMNOPQRSTUVWXYZabcdefghijk1mnopqrstuvwxyz"; 27*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kNumGlyphs = sizeof(kGlyphs) - 1; 28*c8dee2aaSAndroid Build Coastguard Worker static_assert(52 == kNumGlyphs, "expected 52 glyphs"); 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker /* 31*c8dee2aaSAndroid Build Coastguard Worker * This class benchmarks drawing many glyphs at random scales and rotations. 32*c8dee2aaSAndroid Build Coastguard Worker */ 33*c8dee2aaSAndroid Build Coastguard Worker class PathTextBench : public Benchmark { 34*c8dee2aaSAndroid Build Coastguard Worker public: PathTextBench(bool clipped,bool uncached)35*c8dee2aaSAndroid Build Coastguard Worker PathTextBench(bool clipped, bool uncached) : fClipped(clipped), fUncached(uncached) {} 36*c8dee2aaSAndroid Build Coastguard Worker 37*c8dee2aaSAndroid Build Coastguard Worker private: onGetName()38*c8dee2aaSAndroid Build Coastguard Worker const char* onGetName() override { 39*c8dee2aaSAndroid Build Coastguard Worker fName = "path_text"; 40*c8dee2aaSAndroid Build Coastguard Worker if (fClipped) { 41*c8dee2aaSAndroid Build Coastguard Worker fName.append("_clipped"); 42*c8dee2aaSAndroid Build Coastguard Worker } 43*c8dee2aaSAndroid Build Coastguard Worker if (fUncached) { 44*c8dee2aaSAndroid Build Coastguard Worker fName.append("_uncached"); 45*c8dee2aaSAndroid Build Coastguard Worker } 46*c8dee2aaSAndroid Build Coastguard Worker return fName.c_str(); 47*c8dee2aaSAndroid Build Coastguard Worker } onGetSize()48*c8dee2aaSAndroid Build Coastguard Worker SkISize onGetSize() override { return SkISize::Make(kScreenWidth, kScreenHeight); } 49*c8dee2aaSAndroid Build Coastguard Worker onDelayedSetup()50*c8dee2aaSAndroid Build Coastguard Worker void onDelayedSetup() override { 51*c8dee2aaSAndroid Build Coastguard Worker SkFont defaultFont = ToolUtils::DefaultFont(); 52*c8dee2aaSAndroid Build Coastguard Worker SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(defaultFont); 53*c8dee2aaSAndroid Build Coastguard Worker SkBulkGlyphMetricsAndPaths pathMaker{strikeSpec}; 54*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumGlyphs; ++i) { 55*c8dee2aaSAndroid Build Coastguard Worker SkGlyphID id(defaultFont.unicharToGlyph(kGlyphs[i])); 56*c8dee2aaSAndroid Build Coastguard Worker const SkGlyph* glyph = pathMaker.glyph(id); 57*c8dee2aaSAndroid Build Coastguard Worker if (glyph->path()) { 58*c8dee2aaSAndroid Build Coastguard Worker fGlyphs[i] = *glyph->path(); 59*c8dee2aaSAndroid Build Coastguard Worker } 60*c8dee2aaSAndroid Build Coastguard Worker fGlyphs[i].setIsVolatile(fUncached); 61*c8dee2aaSAndroid Build Coastguard Worker } 62*c8dee2aaSAndroid Build Coastguard Worker 63*c8dee2aaSAndroid Build Coastguard Worker SkRandom rand; 64*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumDraws; ++i) { 65*c8dee2aaSAndroid Build Coastguard Worker const SkPath& glyph = fGlyphs[i % kNumGlyphs]; 66*c8dee2aaSAndroid Build Coastguard Worker const SkRect& bounds = glyph.getBounds(); 67*c8dee2aaSAndroid Build Coastguard Worker float glyphSize = std::max(bounds.width(), bounds.height()); 68*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(glyphSize > 0); 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker float t0 = pow(rand.nextF(), 100); 71*c8dee2aaSAndroid Build Coastguard Worker float size = (1 - t0) * std::min(kScreenWidth, kScreenHeight) / 50 + 72*c8dee2aaSAndroid Build Coastguard Worker t0 * std::min(kScreenWidth, kScreenHeight) / 3; 73*c8dee2aaSAndroid Build Coastguard Worker float scale = size / glyphSize; 74*c8dee2aaSAndroid Build Coastguard Worker float t1 = rand.nextF(), t2 = rand.nextF(); 75*c8dee2aaSAndroid Build Coastguard Worker fXforms[i].setTranslate((1 - t1) * sqrt(2) * scale/2 * glyphSize + 76*c8dee2aaSAndroid Build Coastguard Worker t1 * (kScreenWidth - sqrt(2) * scale/2 * glyphSize), 77*c8dee2aaSAndroid Build Coastguard Worker (1 - t2) * sqrt(2) * scale/2 * glyphSize + 78*c8dee2aaSAndroid Build Coastguard Worker t2 * (kScreenHeight - sqrt(2) * scale/2 * glyphSize)); 79*c8dee2aaSAndroid Build Coastguard Worker fXforms[i].preRotate(rand.nextF() * 360); 80*c8dee2aaSAndroid Build Coastguard Worker fXforms[i].preTranslate(-scale/2 * bounds.width(), -scale/2 * bounds.height()); 81*c8dee2aaSAndroid Build Coastguard Worker fXforms[i].preScale(scale, scale); 82*c8dee2aaSAndroid Build Coastguard Worker fPaints[i].setAntiAlias(true); 83*c8dee2aaSAndroid Build Coastguard Worker fPaints[i].setColor(rand.nextU() | 0x80808080); 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker if (fClipped) { 87*c8dee2aaSAndroid Build Coastguard Worker fClipPath = ToolUtils::make_star(SkRect::MakeIWH(kScreenWidth, kScreenHeight), 11, 3); 88*c8dee2aaSAndroid Build Coastguard Worker fClipPath.setIsVolatile(fUncached); 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker } 91*c8dee2aaSAndroid Build Coastguard Worker onDraw(int loops,SkCanvas * canvas)92*c8dee2aaSAndroid Build Coastguard Worker void onDraw(int loops, SkCanvas* canvas) override { 93*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true); 94*c8dee2aaSAndroid Build Coastguard Worker if (fClipped) { 95*c8dee2aaSAndroid Build Coastguard Worker canvas->clipPath(fClipPath, SkClipOp::kIntersect, true); 96*c8dee2aaSAndroid Build Coastguard Worker } 97*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < kNumDraws; ++i) { 98*c8dee2aaSAndroid Build Coastguard Worker const SkPath& glyph = fGlyphs[i % kNumGlyphs]; 99*c8dee2aaSAndroid Build Coastguard Worker canvas->setMatrix(fXforms[i]); 100*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(glyph, fPaints[i]); 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker } 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker const bool fClipped; 105*c8dee2aaSAndroid Build Coastguard Worker const bool fUncached; 106*c8dee2aaSAndroid Build Coastguard Worker SkString fName; 107*c8dee2aaSAndroid Build Coastguard Worker SkPath fGlyphs[kNumGlyphs]; 108*c8dee2aaSAndroid Build Coastguard Worker SkPaint fPaints[kNumDraws]; 109*c8dee2aaSAndroid Build Coastguard Worker SkMatrix fXforms[kNumDraws]; 110*c8dee2aaSAndroid Build Coastguard Worker SkPath fClipPath; 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = Benchmark; 113*c8dee2aaSAndroid Build Coastguard Worker }; 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new PathTextBench(false, false);) 116*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new PathTextBench(false, true);) 117*c8dee2aaSAndroid Build Coastguard Worker DEF_BENCH(return new PathTextBench(true, true);) 118