1#include "SkBenchmark.h"
2#include "SkCanvas.h"
3#include "SkFontHost.h"
4#include "SkPaint.h"
5#include "SkRandom.h"
6#include "SkSfntUtils.h"
7#include "SkString.h"
8#include "SkTemplates.h"
9
10/*  Some considerations for performance:
11        short -vs- long strings (measuring overhead)
12        tiny -vs- large pointsize (measure blit -vs- overhead)
13        1 -vs- many point sizes (measure cache lookup)
14        normal -vs- subpixel -vs- lineartext (minor)
15        force purge after each draw to measure scaler
16        textencoding?
17        text -vs- postext - pathtext
18 */
19class TextBench : public SkBenchmark {
20    SkPaint     fPaint;
21    int         fCount;
22    SkPoint*    fPos;
23    SkString    fText;
24    SkString    fName;
25    enum { N = 300 };
26public:
27    TextBench(void* param, const char text[], int ps, bool linearText,
28              bool posText) : INHERITED(param) {
29        fText.set(text);
30
31        fPaint.setAntiAlias(true);
32        fPaint.setTextSize(SkIntToScalar(ps));
33        fPaint.setLinearText(linearText);
34
35        if (posText) {
36            SkAutoTArray<SkScalar> storage(fText.size());
37            SkScalar* widths = storage.get();
38            fCount = fPaint.getTextWidths(fText.c_str(), fText.size(), widths);
39            fPos = new SkPoint[fCount];
40            SkScalar x = 0;
41            for (int i = 0; i < fCount; i++) {
42                fPos[i].set(x, 0);
43                x += widths[i];
44            }
45        } else {
46            fCount = 0;
47            fPos = NULL;
48        }
49    }
50
51    virtual ~TextBench() {
52        delete[] fPos;
53    }
54
55protected:
56    virtual const char* onGetName() {
57        fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize()));
58        if (fPaint.isLinearText()) {
59            fName.append("_linear");
60        }
61        if (fPos) {
62            fName.append("_pos");
63        }
64        return fName.c_str();
65    }
66
67    virtual void onDraw(SkCanvas* canvas) {
68        const SkIPoint dim = this->getSize();
69        SkRandom rand;
70
71        SkPaint paint(fPaint);
72        this->setupPaint(&paint);
73
74        const SkScalar x0 = SkIntToScalar(-10);
75        const SkScalar y0 = SkIntToScalar(-10);
76        const SkColor colors[] = { SK_ColorBLACK, SK_ColorGRAY };
77
78        for (size_t j = 0; j < SK_ARRAY_COUNT(colors); j++) {
79            paint.setColor(colors[j]);
80            for (int i = 0; i < N; i++) {
81                SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
82                SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
83                if (fPos) {
84                    canvas->save(SkCanvas::kMatrix_SaveFlag);
85                    canvas->translate(x, y);
86                    canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint);
87                    canvas->restore();
88                } else {
89                    canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
90                }
91            }
92        }
93    }
94
95private:
96    typedef SkBenchmark INHERITED;
97};
98
99///////////////////////////////////////////////////////////////////////////////
100
101#define STR     "Hamburgefons"
102#define SMALL   9
103#define BIG     48
104
105static SkBenchmark* Fact0(void* p) { return new TextBench(p, STR, SMALL, false, false); }
106static SkBenchmark* Fact1(void* p) { return new TextBench(p, STR, SMALL, false, true); }
107static SkBenchmark* Fact2(void* p) { return new TextBench(p, STR, SMALL, true, false); }
108static SkBenchmark* Fact3(void* p) { return new TextBench(p, STR, SMALL, true, true); }
109static SkBenchmark* Fact4(void* p) { return new TextBench(p, STR, BIG, false, false); }
110static SkBenchmark* Fact5(void* p) { return new TextBench(p, STR, BIG, false, true); }
111static SkBenchmark* Fact6(void* p) { return new TextBench(p, STR, BIG, true, false); }
112static SkBenchmark* Fact7(void* p) { return new TextBench(p, STR, BIG, true, true); }
113
114static BenchRegistry gReg0(Fact0);
115static BenchRegistry gReg1(Fact1);
116static BenchRegistry gReg2(Fact2);
117static BenchRegistry gReg3(Fact3);
118static BenchRegistry gReg4(Fact4);
119static BenchRegistry gReg5(Fact5);
120static BenchRegistry gReg6(Fact6);
121static BenchRegistry gReg7(Fact7);
122