1
2 /*
3 * Copyright 2023 Google LLC
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "include/core/SkEncodedImageFormat.h"
9 #include "include/core/SkSpan.h"
10 #include "include/core/SkStream.h"
11 #include "include/core/SkString.h"
12 #include "include/core/SkTypeface.h"
13 #include "modules/skunicode/include/SkUnicode.h"
14 #include "tests/Test.h"
15
16 #include <vector>
17
18 using namespace skia_private;
19
20 #ifdef SK_UNICODE_CLIENT_IMPLEMENTATION
UNIX_ONLY_TEST(SkUnicode_Client, reporter)21 UNIX_ONLY_TEST(SkUnicode_Client, reporter) {
22 std::u16string text = u"\U000f2008";
23 auto utf8 = SkUnicode::convertUtf16ToUtf8(text.data(), text.size());
24 auto client = SkUnicode::MakeClientBasedUnicode
25 (SkSpan<char>(&utf8[0], utf8.size()), {}, {}, {});
26 skia_private::TArray<SkUnicode::CodeUnitFlags, true> results;
27 client->computeCodeUnitFlags(utf8.data(), utf8.size(), false, &results);
28
29 for (auto flag : results) {
30 REPORTER_ASSERT(reporter, !SkUnicode::isPartOfWhiteSpaceBreak(flag));
31 }
32 }
33 #endif
34 #ifdef SK_UNICODE_ICU_IMPLEMENTATION
UNIX_ONLY_TEST(SkUnicode_Native, reporter)35 UNIX_ONLY_TEST(SkUnicode_Native, reporter) {
36 std::u16string text = u"\U000f2008";
37 auto utf8 = SkUnicode::convertUtf16ToUtf8(text.data(), text.size());
38 auto icu = SkUnicode::Make();
39 skia_private::TArray<SkUnicode::CodeUnitFlags, true> results;
40 icu->computeCodeUnitFlags(utf8.data(), utf8.size(), false, &results);
41 for (auto flag : results) {
42 REPORTER_ASSERT(reporter, !SkUnicode::isPartOfWhiteSpaceBreak(flag));
43 }
44 }
45 #endif
UNIX_ONLY_TEST(SkUnicode_GetWords, reporter)46 UNIX_ONLY_TEST(SkUnicode_GetWords, reporter) {
47 SkString text("1 22 333 4444 55555 666666 7777777");
48 std::vector<SkUnicode::Position> expected = { 0, 1, 2, 4, 5, 8, 9, 13, 14, 19, 20, 26, 27, 34 };
49 auto icu = SkUnicode::Make();
50 std::vector<SkUnicode::Position> results;
51 auto result = icu->getWords(text.data(), text.size(), "en", &results);
52 REPORTER_ASSERT(reporter, result);
53 REPORTER_ASSERT(reporter, results.size() == expected.size());
54 for (auto i = 0ul; i < results.size(); ++i) {
55 REPORTER_ASSERT(reporter, results[i] == expected[i]);
56 }
57 }
58
UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsLTR, reporter)59 UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsLTR, reporter) {
60 SkString text("1 22 333 4444 55555 666666 7777777");
61 auto icu = SkUnicode::Make();
62 std::vector<SkUnicode::BidiRegion> results;
63 auto result = icu->getBidiRegions(text.data(),
64 text.size(),
65 SkUnicode::TextDirection::kLTR,
66 &results);
67 REPORTER_ASSERT(reporter, result);
68 REPORTER_ASSERT(reporter, results.size() == 1);
69 REPORTER_ASSERT(reporter, results[0].start == 0 &&
70 results[0].end == text.size() &&
71 results[0].level == 0);
72 }
UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsRTL, reporter)73 UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsRTL, reporter) {
74 SkString text("الهيمنة على العالم عبارة قبيحة ، أفضل أن أسميها تحسين العالم.");
75 auto icu = SkUnicode::Make();
76 std::vector<SkUnicode::BidiRegion> results;
77 auto result = icu->getBidiRegions(text.data(),
78 text.size(),
79 SkUnicode::TextDirection::kRTL,
80 &results);
81 REPORTER_ASSERT(reporter, result);
82 REPORTER_ASSERT(reporter, results.size() == 1);
83 REPORTER_ASSERT(reporter, results[0].start == 0 &&
84 results[0].end == text.size() &&
85 results[0].level == 1);
86 }
87
UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsMix1, reporter)88 UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsMix1, reporter) {
89 // Spaces become Arabic (RTL) but numbers remain English (LTR)
90 SkString text("1 22 333 4444 55555 666666 7777777");
91 std::vector<SkUnicode::BidiRegion> expected = {
92 {0, 1, 2},
93 {1, 2, 1},
94 {2, 4, 2},
95 {4, 5, 1},
96 {5, 8, 2},
97 {8, 9, 1},
98 {9, 13, 2},
99 {13, 14, 1},
100 {14, 19, 2},
101 {19, 20, 1},
102 {20, 26, 2},
103 {26, 27, 1},
104 {27, 34, 2},
105 };
106 auto icu = SkUnicode::Make();
107 std::vector<SkUnicode::BidiRegion> results;
108 auto result = icu->getBidiRegions(text.data(),
109 text.size(),
110 SkUnicode::TextDirection::kRTL,
111 &results);
112 REPORTER_ASSERT(reporter, result);
113 REPORTER_ASSERT(reporter, results.size() == expected.size());
114 for (auto i = 0ul; i < results.size(); ++i) {
115 REPORTER_ASSERT(reporter, results[i].start == expected[i].start &&
116 results[i].end == expected[i].end &&
117 results[i].level == expected[i].level);
118 }
119 }
120
UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsMix2, reporter)121 UNIX_ONLY_TEST(SkUnicode_GetBidiRegionsMix2, reporter) {
122 // Few Russian/English words (ЛТР) in the mix
123 SkString text("World ЛТР Domination هي عبارة قبيحة ، أفضل أن أسميها World ЛТР Optimization.");
124 std::vector<SkUnicode::BidiRegion> expected = {
125 { 0, 24, 0},
126 { 24, 80, 1},
127 { 80, 107, 0},
128 };
129 auto icu = SkUnicode::Make();
130 std::vector<SkUnicode::BidiRegion> results;
131 auto result = icu->getBidiRegions(text.data(),
132 text.size(),
133 SkUnicode::TextDirection::kLTR,
134 &results);
135 REPORTER_ASSERT(reporter, result);
136 REPORTER_ASSERT(reporter, results.size() == expected.size());
137 for (auto i = 0ul; i < results.size(); ++i) {
138 REPORTER_ASSERT(reporter, results[i].start == expected[i].start &&
139 results[i].end == expected[i].end &&
140 results[i].level == expected[i].level);
141 }
142 }
143
UNIX_ONLY_TEST(SkUnicode_ToUpper, reporter)144 UNIX_ONLY_TEST(SkUnicode_ToUpper, reporter) {
145 SkString lower("abcdefghijklmnopqrstuvwxyz");
146 SkString upper("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
147 auto icu = SkUnicode::Make();
148 auto icu_result1 = icu->toUpper(lower);
149 REPORTER_ASSERT(reporter, icu_result1.equals(upper));
150 auto icu_result2 = icu->toUpper(upper);
151 REPORTER_ASSERT(reporter, icu_result2.equals(upper));
152 }
153
UNIX_ONLY_TEST(SkUnicode_ComputeCodeUnitFlags, reporter)154 UNIX_ONLY_TEST(SkUnicode_ComputeCodeUnitFlags, reporter) {
155 //SkString text("World domination is such an ugly phrase - I prefer to call it world optimisation");
156 SkString text("1\n22 333 4444 55555 666666 7777777");
157 // 4 8 13 19 24
158 auto icu = SkUnicode::Make();
159 TArray<SkUnicode::CodeUnitFlags> results;
160 auto result = icu->computeCodeUnitFlags(text.data(),
161 text.size(),
162 /*replaceTabs=*/true,
163 &results);
164 REPORTER_ASSERT(reporter, result);
165 REPORTER_ASSERT(reporter, results.size() == SkToS16(text.size() + 1));
166 for (auto i = 0; i < results.size(); ++i) {
167 auto flags = results[i];
168 auto expected = SkUnicode::CodeUnitFlags::kGraphemeStart;
169 if (i == 1) {
170 expected |= SkUnicode::CodeUnitFlags::kControl;
171 }
172 if (i == 2) {
173 expected |= SkUnicode::CodeUnitFlags::kHardLineBreakBefore;
174 }
175 if (i == 1 || i == 4 || i == 8 || i == 13 || i == 19 || i == 26) {
176 expected |= SkUnicode::CodeUnitFlags::kPartOfWhiteSpaceBreak;
177 expected |= SkUnicode::CodeUnitFlags::kPartOfIntraWordBreak;
178 }
179 if (i == 0 || i == 2 || i == 5 || i == 9 || i == 14 || i == 20
180 || i == 27 || i == 34) {
181 expected |= SkUnicode::CodeUnitFlags::kSoftLineBreakBefore;
182 }
183 REPORTER_ASSERT(reporter, flags == expected);
184 }
185 }
186
UNIX_ONLY_TEST(SkUnicode_ReorderVisual, reporter)187 UNIX_ONLY_TEST(SkUnicode_ReorderVisual, reporter) {
188 auto icu = SkUnicode::Make();
189 auto reorder = [&](std::vector<SkUnicode::BidiLevel> levels,
190 std::vector<int32_t> expected) {
191 std::vector<int32_t> logicalOrder(levels.size());
192 icu->reorderVisual(levels.data(), levels.size(), logicalOrder.data());
193 for (auto i = 0ul; i < levels.size(); ++i) {
194 REPORTER_ASSERT(reporter, expected[i] == logicalOrder[i]);
195 }
196 };
197 reorder({}, {});
198 reorder({0}, {0});
199 reorder({1}, {0});
200 reorder({0, 1, 0, 1}, {0, 1, 2, 3});
201 }
202