1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkBenchmark.h" 9 #include "SkCanvas.h" 10 #include "SkFontHost.h" 11 #include "SkPaint.h" 12 #include "SkRandom.h" 13 #include "SkString.h" 14 #include "SkTemplates.h" 15 16 enum FontQuality { 17 kBW, 18 kAA, 19 kLCD 20 }; 21 22 static const char* fontQualityName(const SkPaint& paint) { 23 if (!paint.isAntiAlias()) { 24 return "BW"; 25 } 26 if (paint.isLCDRenderText()) { 27 return "LCD"; 28 } 29 return "AA"; 30 } 31 32 /* Some considerations for performance: 33 short -vs- long strings (measuring overhead) 34 tiny -vs- large pointsize (measure blit -vs- overhead) 35 1 -vs- many point sizes (measure cache lookup) 36 normal -vs- subpixel -vs- lineartext (minor) 37 force purge after each draw to measure scaler 38 textencoding? 39 text -vs- postext - pathtext 40 */ 41 class TextBench : public SkBenchmark { 42 SkPaint fPaint; 43 SkString fText; 44 SkString fName; 45 FontQuality fFQ; 46 bool fDoPos; 47 SkPoint* fPos; 48 enum { N = SkBENCHLOOP(800) }; 49 public: 50 TextBench(void* param, const char text[], int ps, 51 SkColor color, FontQuality fq, bool doPos = false) : INHERITED(param) { 52 fPos = NULL; 53 fFQ = fq; 54 fDoPos = doPos; 55 fText.set(text); 56 57 fPaint.setAntiAlias(kBW != fq); 58 fPaint.setLCDRenderText(kLCD == fq); 59 fPaint.setTextSize(SkIntToScalar(ps)); 60 fPaint.setColor(color); 61 62 if (doPos) { 63 size_t len = strlen(text); 64 SkScalar* adv = new SkScalar[len]; 65 fPaint.getTextWidths(text, len, adv); 66 fPos = new SkPoint[len]; 67 SkScalar x = 0; 68 for (size_t i = 0; i < len; ++i) { 69 fPos[i].set(x, SkIntToScalar(50)); 70 x += adv[i]; 71 } 72 delete[] adv; 73 } 74 } 75 76 virtual ~TextBench() { 77 delete[] fPos; 78 } 79 80 protected: 81 virtual const char* onGetName() { 82 fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize())); 83 if (fDoPos) { 84 fName.append("_pos"); 85 } 86 fName.appendf("_%s", fontQualityName(fPaint)); 87 if (SK_ColorBLACK != fPaint.getColor()) { 88 fName.appendf("_%02X", fPaint.getAlpha()); 89 } else { 90 fName.append("_BK"); 91 } 92 return fName.c_str(); 93 } 94 95 virtual void onDraw(SkCanvas* canvas) { 96 const SkIPoint dim = this->getSize(); 97 SkRandom rand; 98 99 SkPaint paint(fPaint); 100 this->setupPaint(&paint); 101 // explicitly need these 102 paint.setColor(fPaint.getColor()); 103 paint.setAntiAlias(kBW != fFQ); 104 paint.setLCDRenderText(kLCD == fFQ); 105 106 const SkScalar x0 = SkIntToScalar(-10); 107 const SkScalar y0 = SkIntToScalar(-10); 108 109 if (fDoPos) { 110 // realistically, the matrix is often at least translated, so we 111 // do that since it exercises different code in drawPosText. 112 canvas->translate(SK_Scalar1, SK_Scalar1); 113 } 114 115 for (int i = 0; i < N; i++) { 116 if (fDoPos) { 117 canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint); 118 } else { 119 SkScalar x = x0 + rand.nextUScalar1() * dim.fX; 120 SkScalar y = y0 + rand.nextUScalar1() * dim.fY; 121 canvas->drawText(fText.c_str(), fText.size(), x, y, paint); 122 } 123 } 124 } 125 126 private: 127 typedef SkBenchmark INHERITED; 128 }; 129 130 /////////////////////////////////////////////////////////////////////////////// 131 132 #define STR "Hamburgefons" 133 134 static SkBenchmark* Fact01(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kBW); } 135 static SkBenchmark* Fact02(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kBW); } 136 static SkBenchmark* Fact03(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kBW); } 137 138 static SkBenchmark* Fact11(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA); } 139 static SkBenchmark* Fact12(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kAA); } 140 static SkBenchmark* Fact13(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kAA); } 141 142 static SkBenchmark* Fact21(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kLCD); } 143 static SkBenchmark* Fact22(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kLCD); } 144 static SkBenchmark* Fact23(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kLCD); } 145 146 static SkBenchmark* Fact111(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA, true); } 147 148 static BenchRegistry gReg01(Fact01); 149 static BenchRegistry gReg02(Fact02); 150 static BenchRegistry gReg03(Fact03); 151 152 static BenchRegistry gReg11(Fact11); 153 static BenchRegistry gReg12(Fact12); 154 static BenchRegistry gReg13(Fact13); 155 156 static BenchRegistry gReg21(Fact21); 157 static BenchRegistry gReg22(Fact22); 158 static BenchRegistry gReg23(Fact23); 159 160 static BenchRegistry gReg111(Fact111); 161