1 /*
2 * Copyright 2013 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/SkTypeface.h"
12 #include "src/base/SkRandom.h"
13 #include "src/base/SkUTF.h"
14 #include "src/core/SkFontPriv.h"
15 #include "src/utils/SkCharToGlyphCache.h"
16 #include "tools/fonts/FontToolUtils.h"
17
18 enum {
19 NGLYPHS = 100
20 };
21
22 namespace {
23 struct Rec {
24 const SkCharToGlyphCache& fCache;
25 int fLoops;
26 const SkFont& fFont;
27 const SkUnichar* fText;
28 int fCount;
29 };
30 } // namespace
31
32 typedef void (*TypefaceProc)(const Rec& r);
33
textToGlyphs_proc(const Rec & r)34 static void textToGlyphs_proc(const Rec& r) {
35 uint16_t glyphs[NGLYPHS];
36 SkASSERT(r.fCount <= NGLYPHS);
37
38 for (int i = 0; i < r.fLoops; ++i) {
39 r.fFont.textToGlyphs(r.fText, r.fCount*4, SkTextEncoding::kUTF32, glyphs, NGLYPHS);
40 }
41 }
42
charsToGlyphs_proc(const Rec & r)43 static void charsToGlyphs_proc(const Rec& r) {
44 uint16_t glyphs[NGLYPHS];
45 SkASSERT(r.fCount <= NGLYPHS);
46
47 SkTypeface* face = r.fFont.getTypeface();
48 for (int i = 0; i < r.fLoops; ++i) {
49 face->unicharsToGlyphs(r.fText, r.fCount, glyphs);
50 }
51 }
52
addcache_proc(const Rec & r)53 static void addcache_proc(const Rec& r) {
54 for (int loop = 0; loop < r.fLoops; ++loop) {
55 SkCharToGlyphCache cache;
56 for (int i = 0; i < r.fCount; ++i) {
57 cache.addCharAndGlyph(r.fText[i], i);
58 }
59 }
60 }
61
findcache_proc(const Rec & r)62 static void findcache_proc(const Rec& r) {
63 for (int loop = 0; loop < r.fLoops; ++loop) {
64 for (int i = 0; i < r.fCount; ++i) {
65 r.fCache.findGlyphIndex(r.fText[i]);
66 }
67 }
68 }
69
70 class CMAPBench : public Benchmark {
71 TypefaceProc fProc;
72 SkString fName;
73 SkUnichar fText[NGLYPHS];
74 SkFont fFont;
75 SkCharToGlyphCache fCache;
76 int fCount;
77
78 public:
CMAPBench(TypefaceProc proc,const char name[],int count)79 CMAPBench(TypefaceProc proc, const char name[], int count) {
80 SkASSERT(count <= NGLYPHS);
81
82 fProc = proc;
83 fName.printf("%s_%d", name, count);
84 fCount = count;
85
86 SkRandom rand;
87 for (int i = 0; i < count; ++i) {
88 fText[i] = rand.nextU() & 0xFFFF;
89 fCache.addCharAndGlyph(fText[i], i);
90 }
91 fFont.setTypeface(ToolUtils::DefaultPortableTypeface());
92 }
93
isSuitableFor(Backend backend)94 bool isSuitableFor(Backend backend) override {
95 return backend == Backend::kNonRendering;
96 }
97
98 protected:
onGetName()99 const char* onGetName() override {
100 return fName.c_str();
101 }
102
onDraw(int loops,SkCanvas * canvas)103 void onDraw(int loops, SkCanvas* canvas) override {
104 fProc({fCache, loops, fFont, fText, fCount});
105 }
106
107 private:
108
109 using INHERITED = Benchmark;
110 };
111
112 //////////////////////////////////////////////////////////////////////////////
113
114 constexpr int SMALL = 10;
115
116 DEF_BENCH( return new CMAPBench(textToGlyphs_proc, "font_charToGlyph", SMALL); )
117 DEF_BENCH( return new CMAPBench(charsToGlyphs_proc, "face_charToGlyph", SMALL); )
118 DEF_BENCH( return new CMAPBench(addcache_proc, "addcache_charToGlyph", SMALL); )
119 DEF_BENCH( return new CMAPBench(findcache_proc, "findcache_charToGlyph", SMALL); )
120
121 constexpr int BIG = 100;
122
123 DEF_BENCH( return new CMAPBench(textToGlyphs_proc, "font_charToGlyph", BIG); )
124 DEF_BENCH( return new CMAPBench(charsToGlyphs_proc, "face_charToGlyph", BIG); )
125 DEF_BENCH( return new CMAPBench(addcache_proc, "addcache_charToGlyph", BIG); )
126 DEF_BENCH( return new CMAPBench(findcache_proc, "findcache_charToGlyph", BIG); )
127