11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
87cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkBenchmark.h"
97cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkCanvas.h"
107cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkFontHost.h"
117cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkPaint.h"
127cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkRandom.h"
137cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkSfntUtils.h"
147cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkString.h"
157cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#include "SkTemplates.h"
167cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerenum FontQuality {
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kBW,
191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kAA,
201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    kLCD
211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic const char* fontQualityName(const SkPaint& paint) {
241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (!paint.isAntiAlias()) {
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return "BW";
261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.isLCDRenderText()) {
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return "LCD";
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return "AA";
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
337cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed/*  Some considerations for performance:
347cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        short -vs- long strings (measuring overhead)
357cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        tiny -vs- large pointsize (measure blit -vs- overhead)
367cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        1 -vs- many point sizes (measure cache lookup)
377cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        normal -vs- subpixel -vs- lineartext (minor)
387cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        force purge after each draw to measure scaler
397cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        textencoding?
407cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        text -vs- postext - pathtext
417cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed */
427cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reedclass TextBench : public SkBenchmark {
437cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    SkPaint     fPaint;
447cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    SkString    fText;
457cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    SkString    fName;
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    FontQuality fFQ;
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool        fDoPos;
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkPoint*    fPos;
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    enum { N = SkBENCHLOOP(800) };
507cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reedpublic:
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    TextBench(void* param, const char text[], int ps,
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger              SkColor color, FontQuality fq, bool doPos = false) : INHERITED(param) {
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fFQ = fq;
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fDoPos = doPos;
557cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        fText.set(text);
567cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fPaint.setAntiAlias(kBW != fq);
581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fPaint.setLCDRenderText(kLCD == fq);
597cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        fPaint.setTextSize(SkIntToScalar(ps));
6040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fPaint.setColor(color);
617cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (doPos) {
631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            size_t len = strlen(text);
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkScalar* adv = new SkScalar[len];
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fPaint.getTextWidths(text, len, adv);
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            fPos = new SkPoint[len];
677cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed            SkScalar x = 0;
681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            for (size_t i = 0; i < len; ++i) {
691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                fPos[i].set(x, SkIntToScalar(50));
701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += adv[i];
717cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed            }
721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            delete[] adv;
737cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        }
747cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    }
7540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
767cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    virtual ~TextBench() {
777cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        delete[] fPos;
787cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    }
797cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
807cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reedprotected:
817cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    virtual const char* onGetName() {
827cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize()));
831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (fDoPos) {
844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fName.append("_pos");
857cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        }
861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fName.appendf("_%s", fontQualityName(fPaint));
8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (SK_ColorBLACK != fPaint.getColor()) {
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            fName.appendf("_%02X", fPaint.getAlpha());
891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else {
904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fName.append("_BK");
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
927cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        return fName.c_str();
937cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    }
947cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
957cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    virtual void onDraw(SkCanvas* canvas) {
967cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        const SkIPoint dim = this->getSize();
977cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        SkRandom rand;
987cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
997cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        SkPaint paint(fPaint);
1007cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        this->setupPaint(&paint);
1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // explicitly need these
1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setColor(fPaint.getColor());
1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setAntiAlias(kBW != fFQ);
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        paint.setLCDRenderText(kLCD == fFQ);
1057cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
1067cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        const SkScalar x0 = SkIntToScalar(-10);
1077cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        const SkScalar y0 = SkIntToScalar(-10);
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (fDoPos) {
1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // realistically, the matrix is often at least translated, so we
1111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // do that since it exercises different code in drawPosText.
1121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            canvas->translate(SK_Scalar1, SK_Scalar1);
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = 0; i < N; i++) {
1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (fDoPos) {
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint);
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            } else {
1191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
1227cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed            }
1237cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed        }
1247cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    }
1257cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
1267cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reedprivate:
1277cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed    typedef SkBenchmark INHERITED;
1287cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed};
1297cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
1307cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed///////////////////////////////////////////////////////////////////////////////
1317cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
1327cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed#define STR     "Hamburgefons"
1337cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact01(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kBW); }
1351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact02(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kBW); }
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact03(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kBW); }
13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact11(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA); }
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact12(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kAA); }
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact13(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kAA); }
14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact21(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kLCD); }
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact22(void* p) { return new TextBench(p, STR, 16, 0xFFFF0000, kLCD); }
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact23(void* p) { return new TextBench(p, STR, 16, 0x88FF0000, kLCD); }
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkBenchmark* Fact111(void* p) { return new TextBench(p, STR, 16, 0xFF000000, kAA, true); }
1477cc0a6ac7b817b217dd614cba96fc533b32d505dMike Reed
14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic BenchRegistry gReg01(Fact01);
14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic BenchRegistry gReg02(Fact02);
1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg03(Fact03);
1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg11(Fact11);
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg12(Fact12);
1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg13(Fact13);
1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg21(Fact21);
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg22(Fact22);
1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg23(Fact23);
15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic BenchRegistry gReg111(Fact111);
161