blob: 369f4a079bf70848a84ec3e1fa8a8bef22b3a5e0 [file] [log] [blame]
Chris Daltoncb727222017-06-30 12:00:35 -06001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "bench/Benchmark.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkPaint.h"
11#include "include/core/SkPath.h"
12#include "include/utils/SkRandom.h"
Herb Derby81e84a62020-02-14 11:47:35 -050013#include "src/core/SkScalerCache.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkStrikeCache.h"
Herb Derbybaf64782019-04-17 18:01:04 -040015#include "src/core/SkStrikeSpec.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "tools/ToolUtils.h"
Chris Daltoncb727222017-06-30 12:00:35 -060017
18static constexpr int kScreenWidth = 1500;
19static constexpr int kScreenHeight = 1500;
20
21static constexpr int kNumDraws = 2000;
22
23// I and l are rects on OS X.
24static constexpr char kGlyphs[] = "ABCDEFGH7JKLMNOPQRSTUVWXYZabcdefghijk1mnopqrstuvwxyz";
25static constexpr int kNumGlyphs = sizeof(kGlyphs) - 1;
26static_assert(52 == kNumGlyphs, "expected 52 glyphs");
27
28/*
29 * This class benchmarks drawing many glyphs at random scales and rotations.
30 */
31class PathTextBench : public Benchmark {
32public:
Chris Dalton7c02cc72017-11-06 14:10:54 -070033 PathTextBench(bool clipped, bool uncached) : fClipped(clipped), fUncached(uncached) {}
Chris Daltoncb727222017-06-30 12:00:35 -060034
35private:
36 const char* onGetName() override {
Chris Dalton7c02cc72017-11-06 14:10:54 -070037 fName = "path_text";
38 if (fClipped) {
39 fName.append("_clipped");
40 }
41 if (fUncached) {
42 fName.append("_uncached");
43 }
44 return fName.c_str();
Chris Daltoncb727222017-06-30 12:00:35 -060045 }
46 SkIPoint onGetSize() override { return SkIPoint::Make(kScreenWidth, kScreenHeight); }
47
48 void onDelayedSetup() override {
Mike Reed32c60662018-11-28 10:28:07 -050049 SkFont defaultFont;
Herb Derbyac718272019-06-06 14:33:12 -040050 SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(defaultFont);
Herb Derbya64f5b22020-02-24 14:35:51 -050051 auto strike = strikeSpec.findOrCreateStrike();
Chris Daltoncb727222017-06-30 12:00:35 -060052 for (int i = 0; i < kNumGlyphs; ++i) {
Mike Reedfdb876d2019-02-01 09:55:20 -050053 SkPackedGlyphID id(defaultFont.unicharToGlyph(kGlyphs[i]));
Herb Derbya64f5b22020-02-24 14:35:51 -050054 sk_ignore_unused_variable(strike->getScalerContext()->getPath(id, &fGlyphs[i]));
Chris Dalton7c02cc72017-11-06 14:10:54 -070055 fGlyphs[i].setIsVolatile(fUncached);
Chris Daltoncb727222017-06-30 12:00:35 -060056 }
57
58 SkRandom rand;
59 for (int i = 0; i < kNumDraws; ++i) {
60 const SkPath& glyph = fGlyphs[i % kNumGlyphs];
61 const SkRect& bounds = glyph.getBounds();
Brian Osman788b9162020-02-07 10:36:46 -050062 float glyphSize = std::max(bounds.width(), bounds.height());
Chris Daltoncb727222017-06-30 12:00:35 -060063
64 float t0 = pow(rand.nextF(), 100);
Brian Osman788b9162020-02-07 10:36:46 -050065 float size = (1 - t0) * std::min(kScreenWidth, kScreenHeight) / 50 +
66 t0 * std::min(kScreenWidth, kScreenHeight) / 3;
Chris Daltoncb727222017-06-30 12:00:35 -060067 float scale = size / glyphSize;
68 float t1 = rand.nextF(), t2 = rand.nextF();
69 fXforms[i].setTranslate((1 - t1) * sqrt(2) * scale/2 * glyphSize +
70 t1 * (kScreenWidth - sqrt(2) * scale/2 * glyphSize),
71 (1 - t2) * sqrt(2) * scale/2 * glyphSize +
72 t2 * (kScreenHeight - sqrt(2) * scale/2 * glyphSize));
73 fXforms[i].preRotate(rand.nextF() * 360);
74 fXforms[i].preTranslate(-scale/2 * bounds.width(), -scale/2 * bounds.height());
75 fXforms[i].preScale(scale, scale);
76 fPaints[i].setAntiAlias(true);
77 fPaints[i].setColor(rand.nextU() | 0x80808080);
78 }
Chris Dalton7c02cc72017-11-06 14:10:54 -070079
80 if (fClipped) {
Mike Kleinea3f0142019-03-20 11:12:10 -050081 fClipPath = ToolUtils::make_star(SkRect::MakeIWH(kScreenWidth, kScreenHeight), 11, 3);
Chris Dalton7c02cc72017-11-06 14:10:54 -070082 fClipPath.setIsVolatile(fUncached);
83 }
Chris Daltoncb727222017-06-30 12:00:35 -060084 }
85
86 void onDraw(int loops, SkCanvas* canvas) override {
87 SkAutoCanvasRestore acr(canvas, true);
Chris Dalton7c02cc72017-11-06 14:10:54 -070088 if (fClipped) {
89 canvas->clipPath(fClipPath, SkClipOp::kIntersect, true);
90 }
Chris Daltoncb727222017-06-30 12:00:35 -060091 for (int i = 0; i < kNumDraws; ++i) {
92 const SkPath& glyph = fGlyphs[i % kNumGlyphs];
93 canvas->setMatrix(fXforms[i]);
94 canvas->drawPath(glyph, fPaints[i]);
95 }
96 }
97
Chris Dalton7c02cc72017-11-06 14:10:54 -070098 const bool fClipped;
99 const bool fUncached;
100 SkString fName;
Chris Daltoncb727222017-06-30 12:00:35 -0600101 SkPath fGlyphs[kNumGlyphs];
102 SkPaint fPaints[kNumDraws];
103 SkMatrix fXforms[kNumDraws];
Chris Dalton7c02cc72017-11-06 14:10:54 -0700104 SkPath fClipPath;
Chris Daltoncb727222017-06-30 12:00:35 -0600105
John Stiles7571f9e2020-09-02 22:42:33 -0400106 using INHERITED = Benchmark;
Chris Daltoncb727222017-06-30 12:00:35 -0600107};
108
Chris Dalton7c02cc72017-11-06 14:10:54 -0700109DEF_BENCH(return new PathTextBench(false, false);)
110DEF_BENCH(return new PathTextBench(false, true);)
111DEF_BENCH(return new PathTextBench(true, true);)