1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "bench/Benchmark.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkFont.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
12cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
13cb93a386Sopenharmony_ci#include "include/core/SkString.h"
14cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h"
15cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h"
16cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h"
17cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
18cb93a386Sopenharmony_ci#include "tools/Resources.h"
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci/*
23cb93a386Sopenharmony_ci * A trivial test which benchmarks the performance of a textblob with a single run.
24cb93a386Sopenharmony_ci */
25cb93a386Sopenharmony_ciclass SkTextBlobBench : public Benchmark {
26cb93a386Sopenharmony_cipublic:
27cb93a386Sopenharmony_ci    SkTextBlobBench() {}
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    void onDelayedSetup() override {
30cb93a386Sopenharmony_ci        fFont.setTypeface(ToolUtils::create_portable_typeface("serif", SkFontStyle()));
31cb93a386Sopenharmony_ci        fFont.setSubpixel(true);
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci        // This text seems representative in both length and letter frequency.
34cb93a386Sopenharmony_ci        const char* text = "Keep your sentences short, but not overly so.";
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci        fGlyphs.setCount(fFont.countText(text, strlen(text), SkTextEncoding::kUTF8));
37cb93a386Sopenharmony_ci        fXPos.setCount(fGlyphs.count());
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci        fFont.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, fGlyphs.begin(), fGlyphs.count());
40cb93a386Sopenharmony_ci        fFont.getXPos(&fGlyphs[0], fGlyphs.count(), fXPos.begin());
41cb93a386Sopenharmony_ci    }
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci    sk_sp<SkTextBlob> makeBlob() {
44cb93a386Sopenharmony_ci        const SkTextBlobBuilder::RunBuffer& run =
45cb93a386Sopenharmony_ci            fBuilder.allocRunPosH(fFont, fGlyphs.count(), 10, nullptr);
46cb93a386Sopenharmony_ci        memcpy(run.glyphs, &fGlyphs[0], fGlyphs.count() * sizeof(uint16_t));
47cb93a386Sopenharmony_ci        memcpy(run.pos, &fXPos[0], fXPos.count() * sizeof(SkScalar));
48cb93a386Sopenharmony_ci        return fBuilder.make();
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ciprivate:
52cb93a386Sopenharmony_ci    SkTextBlobBuilder   fBuilder;
53cb93a386Sopenharmony_ci    SkFont              fFont;
54cb93a386Sopenharmony_ci    SkTDArray<uint16_t> fGlyphs;
55cb93a386Sopenharmony_ci    SkTDArray<SkScalar> fXPos;
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
58cb93a386Sopenharmony_ci};
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciclass TextBlobCachedBench : public SkTextBlobBench {
61cb93a386Sopenharmony_ci    const char* onGetName() override {
62cb93a386Sopenharmony_ci        return "TextBlobCachedBench";
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
66cb93a386Sopenharmony_ci        SkPaint paint;
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci        auto blob = this->makeBlob();
69cb93a386Sopenharmony_ci        auto bigLoops = loops * 100;
70cb93a386Sopenharmony_ci        for (int i = 0; i < bigLoops; i++) {
71cb93a386Sopenharmony_ci            // To ensure maximum caching, we just redraw the blob at the same place everytime
72cb93a386Sopenharmony_ci            canvas->drawTextBlob(blob, 0, 0, paint);
73cb93a386Sopenharmony_ci        }
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci};
76cb93a386Sopenharmony_ciDEF_BENCH( return new TextBlobCachedBench(); )
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ciclass TextBlobFirstTimeBench : public SkTextBlobBench {
79cb93a386Sopenharmony_ci    const char* onGetName() override {
80cb93a386Sopenharmony_ci        return "TextBlobFirstTimeBench";
81cb93a386Sopenharmony_ci    }
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
84cb93a386Sopenharmony_ci        SkPaint paint;
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci        auto bigLoops = loops * 100;
87cb93a386Sopenharmony_ci        for (int i = 0; i < bigLoops; i++) {
88cb93a386Sopenharmony_ci            canvas->drawTextBlob(this->makeBlob(), 0, 0, paint);
89cb93a386Sopenharmony_ci        }
90cb93a386Sopenharmony_ci    }
91cb93a386Sopenharmony_ci};
92cb93a386Sopenharmony_ciDEF_BENCH( return new TextBlobFirstTimeBench(); )
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ciclass TextBlobMakeBench : public SkTextBlobBench {
95cb93a386Sopenharmony_ci    const char* onGetName() override {
96cb93a386Sopenharmony_ci        return "TextBlobMakeBench";
97cb93a386Sopenharmony_ci    }
98cb93a386Sopenharmony_ci
99cb93a386Sopenharmony_ci    bool isSuitableFor(Backend backend) override {
100cb93a386Sopenharmony_ci        return backend == kNonRendering_Backend;
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas*) override {
104cb93a386Sopenharmony_ci        for (int i = 0; i < loops; i++) {
105cb93a386Sopenharmony_ci            for (int inner = 0; inner < 1000; ++inner) {
106cb93a386Sopenharmony_ci                this->makeBlob();
107cb93a386Sopenharmony_ci            }
108cb93a386Sopenharmony_ci        }
109cb93a386Sopenharmony_ci    }
110cb93a386Sopenharmony_ci};
111cb93a386Sopenharmony_ciDEF_BENCH( return new TextBlobMakeBench(); )
112