| /* |
| * 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->drawText(fText.c_str(), fText.size(), 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); ) |