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