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 "SkSfntUtils.h" 14#include "SkString.h" 15#include "SkTemplates.h" 16 17enum FontQuality { 18 kBW, 19 kAA, 20 kLCD 21}; 22 23static const char* fontQualityName(const SkPaint& paint) { 24 if (!paint.isAntiAlias()) { 25 return "BW"; 26 } 27 if (paint.isLCDRenderText()) { 28 return "LCD"; 29 } 30 return "AA"; 31} 32 33/* Some considerations for performance: 34 short -vs- long strings (measuring overhead) 35 tiny -vs- large pointsize (measure blit -vs- overhead) 36 1 -vs- many point sizes (measure cache lookup) 37 normal -vs- subpixel -vs- lineartext (minor) 38 force purge after each draw to measure scaler 39 textencoding? 40 text -vs- postext - pathtext 41 */ 42class TextBench : public SkBenchmark { 43 SkPaint fPaint; 44 SkString fText; 45 SkString fName; 46 FontQuality fFQ; 47 bool fDoPos; 48 SkPoint* fPos; 49 enum { N = SkBENCHLOOP(800) }; 50public: 51 TextBench(void* param, const char text[], int ps, 52 SkColor color, FontQuality fq, bool doPos = false) : INHERITED(param) { 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 80protected: 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 126private: 127 typedef SkBenchmark INHERITED; 128}; 129 130/////////////////////////////////////////////////////////////////////////////// 131 132#define STR "Hamburgefons" 133 134static SkBenchmark* Fact01(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kBW); } 135static SkBenchmark* Fact02(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kBW); } 136static SkBenchmark* Fact03(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kBW); } 137 138static SkBenchmark* Fact11(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA); } 139static SkBenchmark* Fact12(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kAA); } 140static SkBenchmark* Fact13(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kAA); } 141 142static SkBenchmark* Fact21(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kLCD); } 143static SkBenchmark* Fact22(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kLCD); } 144static SkBenchmark* Fact23(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kLCD); } 145 146static SkBenchmark* Fact111(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA, true); } 147 148static BenchRegistry gReg01(Fact01); 149static BenchRegistry gReg02(Fact02); 150static BenchRegistry gReg03(Fact03); 151 152static BenchRegistry gReg11(Fact11); 153static BenchRegistry gReg12(Fact12); 154static BenchRegistry gReg13(Fact13); 155 156static BenchRegistry gReg21(Fact21); 157static BenchRegistry gReg22(Fact22); 158static BenchRegistry gReg23(Fact23); 159 160static BenchRegistry gReg111(Fact111); 161