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