1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 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/SkPaint.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
12cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h"
13cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h"
14cb93a386Sopenharmony_ci#include "src/core/SkStrikeCache.h"
15cb93a386Sopenharmony_ci#include "src/core/SkStrikeSpec.h"
16cb93a386Sopenharmony_ci#include "tools/ToolUtils.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cistatic constexpr int kScreenWidth = 1500;
19cb93a386Sopenharmony_cistatic constexpr int kScreenHeight = 1500;
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cistatic constexpr int kNumDraws = 2000;
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci// I and l are rects on OS X.
24cb93a386Sopenharmony_cistatic constexpr char kGlyphs[] =  "ABCDEFGH7JKLMNOPQRSTUVWXYZabcdefghijk1mnopqrstuvwxyz";
25cb93a386Sopenharmony_cistatic constexpr int kNumGlyphs = sizeof(kGlyphs) - 1;
26cb93a386Sopenharmony_cistatic_assert(52 == kNumGlyphs, "expected 52 glyphs");
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci/*
29cb93a386Sopenharmony_ci * This class benchmarks drawing many glyphs at random scales and rotations.
30cb93a386Sopenharmony_ci */
31cb93a386Sopenharmony_ciclass PathTextBench : public Benchmark {
32cb93a386Sopenharmony_cipublic:
33cb93a386Sopenharmony_ci    PathTextBench(bool clipped, bool uncached) : fClipped(clipped), fUncached(uncached) {}
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ciprivate:
36cb93a386Sopenharmony_ci    const char* onGetName() override {
37cb93a386Sopenharmony_ci        fName = "path_text";
38cb93a386Sopenharmony_ci        if (fClipped) {
39cb93a386Sopenharmony_ci            fName.append("_clipped");
40cb93a386Sopenharmony_ci        }
41cb93a386Sopenharmony_ci        if (fUncached) {
42cb93a386Sopenharmony_ci            fName.append("_uncached");
43cb93a386Sopenharmony_ci        }
44cb93a386Sopenharmony_ci        return fName.c_str();
45cb93a386Sopenharmony_ci    }
46cb93a386Sopenharmony_ci    SkIPoint onGetSize() override { return SkIPoint::Make(kScreenWidth, kScreenHeight); }
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    void onDelayedSetup() override {
49cb93a386Sopenharmony_ci        SkFont defaultFont;
50cb93a386Sopenharmony_ci        SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(defaultFont);
51cb93a386Sopenharmony_ci        auto strike = strikeSpec.findOrCreateStrike();
52cb93a386Sopenharmony_ci        for (int i = 0; i < kNumGlyphs; ++i) {
53cb93a386Sopenharmony_ci            SkPackedGlyphID id(defaultFont.unicharToGlyph(kGlyphs[i]));
54cb93a386Sopenharmony_ci            sk_ignore_unused_variable(strike->getScalerContext()->getPath(id, &fGlyphs[i]));
55cb93a386Sopenharmony_ci            fGlyphs[i].setIsVolatile(fUncached);
56cb93a386Sopenharmony_ci        }
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci        SkRandom rand;
59cb93a386Sopenharmony_ci        for (int i = 0; i < kNumDraws; ++i) {
60cb93a386Sopenharmony_ci            const SkPath& glyph = fGlyphs[i % kNumGlyphs];
61cb93a386Sopenharmony_ci            const SkRect& bounds = glyph.getBounds();
62cb93a386Sopenharmony_ci            float glyphSize = std::max(bounds.width(), bounds.height());
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci            float t0 = pow(rand.nextF(), 100);
65cb93a386Sopenharmony_ci            float size = (1 - t0) * std::min(kScreenWidth, kScreenHeight) / 50 +
66cb93a386Sopenharmony_ci                         t0 * std::min(kScreenWidth, kScreenHeight) / 3;
67cb93a386Sopenharmony_ci            float scale = size / glyphSize;
68cb93a386Sopenharmony_ci            float t1 = rand.nextF(), t2 = rand.nextF();
69cb93a386Sopenharmony_ci            fXforms[i].setTranslate((1 - t1) * sqrt(2) * scale/2 * glyphSize +
70cb93a386Sopenharmony_ci                                     t1 * (kScreenWidth - sqrt(2) * scale/2 * glyphSize),
71cb93a386Sopenharmony_ci                                     (1 - t2) * sqrt(2) * scale/2 * glyphSize +
72cb93a386Sopenharmony_ci                                     t2 * (kScreenHeight - sqrt(2) * scale/2 * glyphSize));
73cb93a386Sopenharmony_ci            fXforms[i].preRotate(rand.nextF() * 360);
74cb93a386Sopenharmony_ci            fXforms[i].preTranslate(-scale/2 * bounds.width(), -scale/2 * bounds.height());
75cb93a386Sopenharmony_ci            fXforms[i].preScale(scale, scale);
76cb93a386Sopenharmony_ci            fPaints[i].setAntiAlias(true);
77cb93a386Sopenharmony_ci            fPaints[i].setColor(rand.nextU() | 0x80808080);
78cb93a386Sopenharmony_ci        }
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ci        if (fClipped) {
81cb93a386Sopenharmony_ci            fClipPath = ToolUtils::make_star(SkRect::MakeIWH(kScreenWidth, kScreenHeight), 11, 3);
82cb93a386Sopenharmony_ci            fClipPath.setIsVolatile(fUncached);
83cb93a386Sopenharmony_ci        }
84cb93a386Sopenharmony_ci    }
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    void onDraw(int loops, SkCanvas* canvas) override {
87cb93a386Sopenharmony_ci        SkAutoCanvasRestore acr(canvas, true);
88cb93a386Sopenharmony_ci        if (fClipped) {
89cb93a386Sopenharmony_ci            canvas->clipPath(fClipPath, SkClipOp::kIntersect, true);
90cb93a386Sopenharmony_ci        }
91cb93a386Sopenharmony_ci        for (int i = 0; i < kNumDraws; ++i) {
92cb93a386Sopenharmony_ci            const SkPath& glyph = fGlyphs[i % kNumGlyphs];
93cb93a386Sopenharmony_ci            canvas->setMatrix(fXforms[i]);
94cb93a386Sopenharmony_ci            canvas->drawPath(glyph, fPaints[i]);
95cb93a386Sopenharmony_ci        }
96cb93a386Sopenharmony_ci    }
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    const bool fClipped;
99cb93a386Sopenharmony_ci    const bool fUncached;
100cb93a386Sopenharmony_ci    SkString fName;
101cb93a386Sopenharmony_ci    SkPath fGlyphs[kNumGlyphs];
102cb93a386Sopenharmony_ci    SkPaint fPaints[kNumDraws];
103cb93a386Sopenharmony_ci    SkMatrix fXforms[kNumDraws];
104cb93a386Sopenharmony_ci    SkPath fClipPath;
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    using INHERITED = Benchmark;
107cb93a386Sopenharmony_ci};
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ciDEF_BENCH(return new PathTextBench(false, false);)
110cb93a386Sopenharmony_ciDEF_BENCH(return new PathTextBench(false, true);)
111cb93a386Sopenharmony_ciDEF_BENCH(return new PathTextBench(true, true);)
112