1 /* 2 * Copyright 2017 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 "SkCanvas.h" 10 #include "SkGlyphCache.h" 11 #include "SkPaint.h" 12 #include "SkPath.h" 13 #include "SkRandom.h" 14 15 static constexpr int kScreenWidth = 1500; 16 static constexpr int kScreenHeight = 1500; 17 18 static constexpr int kNumDraws = 2000; 19 20 // I and l are rects on OS X. 21 static constexpr char kGlyphs[] = "ABCDEFGH7JKLMNOPQRSTUVWXYZabcdefghijk1mnopqrstuvwxyz"; 22 static constexpr int kNumGlyphs = sizeof(kGlyphs) - 1; 23 static_assert(52 == kNumGlyphs, "expected 52 glyphs"); 24 25 /* 26 * This class benchmarks drawing many glyphs at random scales and rotations. 27 */ 28 class PathTextBench : public Benchmark { 29 public: 30 bool isVisual() override { return true; } 31 32 private: 33 const char* onGetName() override { 34 return "path_text"; 35 } 36 SkIPoint onGetSize() override { return SkIPoint::Make(kScreenWidth, kScreenHeight); } 37 38 void onDelayedSetup() override { 39 SkPaint defaultPaint; 40 SkAutoGlyphCache agc(defaultPaint, nullptr, &SkMatrix::I()); 41 SkGlyphCache* cache = agc.getCache(); 42 for (int i = 0; i < kNumGlyphs; ++i) { 43 SkGlyphID id = cache->unicharToGlyph(kGlyphs[i]); 44 cache->getScalerContext()->getPath(SkPackedGlyphID(id), &fGlyphs[i]); 45 } 46 47 SkRandom rand; 48 for (int i = 0; i < kNumDraws; ++i) { 49 const SkPath& glyph = fGlyphs[i % kNumGlyphs]; 50 const SkRect& bounds = glyph.getBounds(); 51 float glyphSize = SkTMax(bounds.width(), bounds.height()); 52 53 float t0 = pow(rand.nextF(), 100); 54 float size = (1 - t0) * SkTMin(kScreenWidth, kScreenHeight) / 50 + 55 t0 * SkTMin(kScreenWidth, kScreenHeight) / 3; 56 float scale = size / glyphSize; 57 float t1 = rand.nextF(), t2 = rand.nextF(); 58 fXforms[i].setTranslate((1 - t1) * sqrt(2) * scale/2 * glyphSize + 59 t1 * (kScreenWidth - sqrt(2) * scale/2 * glyphSize), 60 (1 - t2) * sqrt(2) * scale/2 * glyphSize + 61 t2 * (kScreenHeight - sqrt(2) * scale/2 * glyphSize)); 62 fXforms[i].preRotate(rand.nextF() * 360); 63 fXforms[i].preTranslate(-scale/2 * bounds.width(), -scale/2 * bounds.height()); 64 fXforms[i].preScale(scale, scale); 65 fPaints[i].setAntiAlias(true); 66 fPaints[i].setColor(rand.nextU() | 0x80808080); 67 } 68 } 69 70 void onDraw(int loops, SkCanvas* canvas) override { 71 SkAutoCanvasRestore acr(canvas, true); 72 for (int i = 0; i < kNumDraws; ++i) { 73 const SkPath& glyph = fGlyphs[i % kNumGlyphs]; 74 canvas->setMatrix(fXforms[i]); 75 canvas->drawPath(glyph, fPaints[i]); 76 } 77 } 78 79 SkPath fGlyphs[kNumGlyphs]; 80 SkPaint fPaints[kNumDraws]; 81 SkMatrix fXforms[kNumDraws]; 82 83 typedef Benchmark INHERITED; 84 }; 85 86 DEF_BENCH(return new PathTextBench;) 87