/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Benchmark.h" #include "Resources.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkRandom.h" #include "SkStream.h" #include "SkString.h" #include "SkTemplates.h" #include "SkTypeface.h" enum FontQuality { kBW, kAA, kLCD, }; static const char* fontQualityName(const SkPaint& paint) { if (!paint.isAntiAlias()) { return "BW"; } if (paint.isLCDRenderText()) { return "LCD"; } return "AA"; } /* Some considerations for performance: short -vs- long strings (measuring overhead) tiny -vs- large pointsize (measure blit -vs- overhead) 1 -vs- many point sizes (measure cache lookup) normal -vs- subpixel -vs- lineartext (minor) force purge after each draw to measure scaler textencoding? text -vs- postext - pathtext */ class TextBench : public Benchmark { SkPaint fPaint; SkString fText; SkString fName; FontQuality fFQ; bool fDoPos; bool fDoColorEmoji; sk_sp<SkTypeface> fColorEmojiTypeface; SkPoint* fPos; public: TextBench(const char text[], int ps, SkColor color, FontQuality fq, bool doColorEmoji = false, bool doPos = false) : fText(text) , fFQ(fq) , fDoPos(doPos) , fDoColorEmoji(doColorEmoji) , fPos(nullptr) { fPaint.setAntiAlias(kBW != fq); fPaint.setLCDRenderText(kLCD == fq); fPaint.setTextSize(SkIntToScalar(ps)); fPaint.setColor(color); } ~TextBench() override { delete[] fPos; } protected: void onDelayedSetup() override { if (fDoColorEmoji) { SkASSERT(kBW == fFQ); fColorEmojiTypeface = MakeResourceAsTypeface("fonts/Funkster.ttf"); } if (fDoPos) { size_t len = fText.size(); SkScalar* adv = new SkScalar[len]; fPaint.getTextWidths(fText.c_str(), len, adv); fPos = new SkPoint[len]; SkScalar x = 0; for (size_t i = 0; i < len; ++i) { fPos[i].set(x, SkIntToScalar(50)); x += adv[i]; } delete[] adv; } } const char* onGetName() override { fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize())); if (fDoPos) { fName.append("_pos"); } fName.appendf("_%s", fontQualityName(fPaint)); if (SK_ColorBLACK == fPaint.getColor()) { fName.append("_BK"); } else if (SK_ColorWHITE == fPaint.getColor()) { fName.append("_WT"); } else { fName.appendf("_%02X", fPaint.getAlpha()); } if (fDoColorEmoji) { fName.append("_ColorEmoji"); } return fName.c_str(); } void onDraw(int loops, SkCanvas* canvas) override { const SkIPoint dim = this->getSize(); SkRandom rand; SkPaint paint(fPaint); this->setupPaint(&paint); // explicitly need these paint.setColor(fPaint.getColor()); paint.setAntiAlias(kBW != fFQ); paint.setLCDRenderText(kLCD == fFQ); if (fDoColorEmoji && fColorEmojiTypeface) { paint.setTypeface(fColorEmojiTypeface); } const SkScalar x0 = SkIntToScalar(-10); const SkScalar y0 = SkIntToScalar(-10); if (fDoPos) { // realistically, the matrix is often at least translated, so we // do that since it exercises different code in drawPosText. canvas->translate(SK_Scalar1, SK_Scalar1); } for (int i = 0; i < loops; i++) { if (fDoPos) { canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint); } else { SkScalar x = x0 + rand.nextUScalar1() * dim.fX; SkScalar y = y0 + rand.nextUScalar1() * dim.fY; canvas->drawString(fText, x, y, paint); } } } private: typedef Benchmark INHERITED; }; /////////////////////////////////////////////////////////////////////////////// #define STR "Hamburgefons" DEF_BENCH( return new TextBench(STR, 16, 0xFFFFFFFF, kBW); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kBW); ) DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kBW); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFFFFFF, kAA); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kAA); ) DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kAA); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFFFFFF, kLCD); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kLCD); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kLCD); ) DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kLCD); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFFFFFF, kBW, true); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW, true); ) DEF_BENCH( return new TextBench(STR, 16, 0xFFFF0000, kBW, true); ) DEF_BENCH( return new TextBench(STR, 16, 0x88FF0000, kBW, true); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kBW, true, true); ) DEF_BENCH( return new TextBench(STR, 16, 0xFF000000, kAA, false, true); )