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