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