1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/string_number_conversions.h"
6 #include "base/time/time.h"
7 #include "base/timer/lap_timer.h"
8 #include "build/build_config.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "testing/perf/perf_result_reporter.h"
11 #include "third_party/blink/renderer/platform/fonts/font.h"
12 #include "third_party/blink/renderer/platform/fonts/font_description.h"
13 #include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
14 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
15 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
16
17 using blink::test::CreateTestFont;
18
19 namespace blink {
20
21 static const int kTimeLimitMillis = 3000;
22 static const int kWarmupRuns = 10000;
23 static const int kTimeCheckInterval = 1000000;
24
25 namespace {
26
27 constexpr char kMetricPrefixOffsetForPosition[] = "OffsetForPosition.";
28 constexpr char kMetricPrefixCharacterRange[] = "CharacterRange.";
29 constexpr char kMetricThroughput[] = "throughput";
30
31 } // namespace
32
33 class ShapeResultPerfTest {
34 USING_FAST_MALLOC(ShapeResultPerfTest);
35
36 public:
37 enum FontName {
38 ahem,
39 amiri,
40 megalopolis,
41 roboto,
42 };
43
ShapeResultPerfTest()44 ShapeResultPerfTest()
45 : timer(kWarmupRuns,
46 base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
47 kTimeCheckInterval) {}
48
49 protected:
SetupFont(FontName font_name,const String & text,bool ltr)50 TextRun SetupFont(FontName font_name, const String& text, bool ltr) {
51 FontDescription::VariantLigatures ligatures(
52 FontDescription::kEnabledLigaturesState);
53 font = CreateTestFont(
54 "TestFont",
55 test::PlatformTestDataPath(font_path.find(font_name)->value), 100,
56 &ligatures);
57
58 return TextRun(
59 text, /* xpos */ 0, /* expansion */ 0,
60 TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
61 ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
62 }
63
ReportResult(const std::string & metric_prefix,const std::string & story_prefix)64 void ReportResult(const std::string& metric_prefix,
65 const std::string& story_prefix) {
66 std::string story = story_prefix + "_" + param_string;
67 perf_test::PerfResultReporter reporter(metric_prefix, story);
68 reporter.RegisterImportantMetric(kMetricThroughput, "runs/s");
69 reporter.AddResult(kMetricThroughput, timer.LapsPerSecond());
70 }
71
72 Font font;
73
74 HashMap<FontName, String, WTF::IntHash<FontName>> font_path = {
75 {ahem, "Ahem.woff"},
76 {amiri, "third_party/Amiri/amiri_arabic.woff2"},
77 {megalopolis, "third_party/MEgalopolis/MEgalopolisExtra.woff"},
78 {roboto, "third_party/Roboto/roboto-regular.woff2"},
79 };
80
81 base::LapTimer timer;
82 std::string param_string;
83 };
84
85 class OffsetForPositionPerfTest : public ShapeResultPerfTest,
86 public testing::TestWithParam<float> {
87 public:
OffsetForPosition(TextRun & run,IncludePartialGlyphsOption partial,BreakGlyphsOption breakopt)88 void OffsetForPosition(TextRun& run,
89 IncludePartialGlyphsOption partial,
90 BreakGlyphsOption breakopt) {
91 timer.Reset();
92 float position = GetParam();
93 param_string = base::NumberToString(position);
94 do {
95 font.OffsetForPosition(run, position, partial, breakopt);
96 timer.NextLap();
97 } while (!timer.HasTimeLimitExpired());
98 }
99
100 protected:
ReportResult(const std::string & story_prefix)101 void ReportResult(const std::string& story_prefix) {
102 ShapeResultPerfTest::ReportResult(kMetricPrefixOffsetForPosition,
103 story_prefix);
104 }
105 };
106
107 class CharacterRangePerfTest : public ShapeResultPerfTest,
108 public testing::TestWithParam<int> {
109 public:
GetCharacter(TextRun & run)110 void GetCharacter(TextRun& run) {
111 timer.Reset();
112 int endpos = GetParam();
113 param_string = base::NumberToString(endpos);
114 do {
115 font.SelectionRectForText(run, FloatPoint(), 100, 0, endpos);
116 timer.NextLap();
117 } while (!timer.HasTimeLimitExpired());
118 }
119
120 protected:
ReportResult(const std::string & story_prefix)121 void ReportResult(const std::string& story_prefix) {
122 ShapeResultPerfTest::ReportResult(kMetricPrefixCharacterRange,
123 story_prefix);
124 }
125 };
126
TEST_P(OffsetForPositionPerfTest,LTROffsetForPositionFullBreak)127 TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullBreak) {
128 TextRun run = SetupFont(ahem, "FURACOLO", true);
129 OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
130 ReportResult("LTR_full_break");
131 }
132
TEST_P(OffsetForPositionPerfTest,LTROffsetForPositionFullDontBreak)133 TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullDontBreak) {
134 TextRun run = SetupFont(ahem, "FURACOLO", true);
135 OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
136 ReportResult("LTR_full");
137 }
138
TEST_P(OffsetForPositionPerfTest,LTROffsetForPositionIncludePartialBreak)139 TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialBreak) {
140 TextRun run = SetupFont(ahem, "FURACOLO", true);
141 OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
142 ReportResult("LTR_partial_break");
143 }
144
TEST_P(OffsetForPositionPerfTest,LTROffsetForPositionIncludePartialDontBreak)145 TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialDontBreak) {
146 TextRun run = SetupFont(ahem, "FURACOLO", true);
147 OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
148 ReportResult("LTR_partial");
149 }
150
TEST_P(OffsetForPositionPerfTest,RTLOffsetForPositionFullBreak)151 TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullBreak) {
152 TextRun run = SetupFont(ahem, "OLOCARUF", false);
153 OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
154 ReportResult("RTL_full_break");
155 }
156
TEST_P(OffsetForPositionPerfTest,RTLOffsetForPositionFullDontBreak)157 TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullDontBreak) {
158 TextRun run = SetupFont(ahem, "OLOCARUF", false);
159 OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
160 ReportResult("RTL_full");
161 }
162
TEST_P(OffsetForPositionPerfTest,RTLOffsetForPositionIncludePartialBreak)163 TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialBreak) {
164 TextRun run = SetupFont(ahem, "OLOCARUF", false);
165 OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
166 ReportResult("RTL_partial_break");
167 }
168
TEST_P(OffsetForPositionPerfTest,RTLOffsetForPositionIncludePartialDontBreak)169 TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialDontBreak) {
170 TextRun run = SetupFont(ahem, "OLOCARUF", false);
171 OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
172 ReportResult("RTL_partial");
173 }
174
175 INSTANTIATE_TEST_SUITE_P(OffsetForPosition,
176 OffsetForPositionPerfTest,
177 testing::Values(0, 10, 60, 100, 200, 350));
178
TEST_P(CharacterRangePerfTest,LTRCharacterForPosition)179 TEST_P(CharacterRangePerfTest, LTRCharacterForPosition) {
180 TextRun run = SetupFont(ahem, "FURACOLO", true);
181 GetCharacter(run);
182 ReportResult("LTR");
183 }
184
TEST_P(CharacterRangePerfTest,RTLCharacterForPosition)185 TEST_P(CharacterRangePerfTest, RTLCharacterForPosition) {
186 TextRun run = SetupFont(ahem, "OLOCARUF", false);
187 GetCharacter(run);
188 ReportResult("RTL");
189 }
190
191 INSTANTIATE_TEST_SUITE_P(CharacterRange,
192 CharacterRangePerfTest,
193 testing::Values(0, 1, 2, 4, 8));
194
195 } // namespace blink
196