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 public: 49 TextBench(const char text[], int ps, 50 SkColor color, FontQuality fq, bool doPos = false) { 51 fPos = NULL; 52 fFQ = fq; 53 fDoPos = doPos; 54 fText.set(text); 55 56 fPaint.setAntiAlias(kBW != fq); 57 fPaint.setLCDRenderText(kLCD == fq); 58 fPaint.setTextSize(SkIntToScalar(ps)); 59 fPaint.setColor(color); 60 61 if (doPos) { 62 size_t len = strlen(text); 63 SkScalar* adv = new SkScalar[len]; 64 fPaint.getTextWidths(text, len, adv); 65 fPos = new SkPoint[len]; 66 SkScalar x = 0; 67 for (size_t i = 0; i < len; ++i) { 68 fPos[i].set(x, SkIntToScalar(50)); 69 x += adv[i]; 70 } 71 delete[] adv; 72 } 73 } 74 75 virtual ~TextBench() { 76 delete[] fPos; 77 } 78 79 protected: 80 virtual const char* onGetName() { 81 fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize())); 82 if (fDoPos) { 83 fName.append("_pos"); 84 } 85 fName.appendf("_%s", fontQualityName(fPaint)); 86 if (SK_ColorBLACK != fPaint.getColor()) { 87 fName.appendf("_%02X", fPaint.getAlpha()); 88 } else { 89 fName.append("_BK"); 90 } 91 return fName.c_str(); 92 } 93 94 virtual void onDraw(const int loops, SkCanvas* canvas) { 95 const SkIPoint dim = this->getSize(); 96 SkRandom rand; 97 98 SkPaint paint(fPaint); 99 this->setupPaint(&paint); 100 // explicitly need these 101 paint.setColor(fPaint.getColor()); 102 paint.setAntiAlias(kBW != fFQ); 103 paint.setLCDRenderText(kLCD == fFQ); 104 105 const SkScalar x0 = SkIntToScalar(-10); 106 const SkScalar y0 = SkIntToScalar(-10); 107 108 if (fDoPos) { 109 // realistically, the matrix is often at least translated, so we 110 // do that since it exercises different code in drawPosText. 111 canvas->translate(SK_Scalar1, SK_Scalar1); 112 } 113 114 for (int i = 0; i < loops; i++) { 115 if (fDoPos) { 116 canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint); 117 } else { 118 SkScalar x = x0 + rand.nextUScalar1() * dim.fX; 119 SkScalar y = y0 + rand.nextUScalar1() * dim.fY; 120 canvas->drawText(fText.c_str(), fText.size(), x, y, paint); 121 } 122 } 123 } 124 125 private: 126 typedef SkBenchmark INHERITED; 127 }; 128 129 /////////////////////////////////////////////////////////////////////////////// 130 131 #define STR "Hamburgefons" 132 133 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW); ) 134 DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kBW); ) 135 DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kBW); ) 136 137 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA); ) 138 DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kAA); ) 139 DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kAA); ) 140 141 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kLCD); ) 142 DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kLCD); ) 143 DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kLCD); ) 144 145 DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA, true); ) 146