1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2023 The Chromium Authors. All rights reserved.
2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*c8dee2aaSAndroid Build Coastguard Worker // found in the LICENSE file.
4*c8dee2aaSAndroid Build Coastguard Worker
5*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
6*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
7*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skunicode/include/SkUnicode.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkBitmaskEnum.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTime.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "tools/unicode_comparison/cpp/bridge.h"
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker namespace {
13*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkUnicode> gUnicode = nullptr;
14*c8dee2aaSAndroid Build Coastguard Worker static skia_private::TArray<SkUnicode::CodeUnitFlags, true> gCodeUnitFlags;
15*c8dee2aaSAndroid Build Coastguard Worker static std::vector<SkUnicode::Position> gSentences;
16*c8dee2aaSAndroid Build Coastguard Worker static std::vector<SkUnicode::Position> gWords;
17*c8dee2aaSAndroid Build Coastguard Worker }
18*c8dee2aaSAndroid Build Coastguard Worker
init_skunicode_impl(char * impl)19*c8dee2aaSAndroid Build Coastguard Worker bool init_skunicode_impl(char* impl) {
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker SkString unicodeName(impl);
22*c8dee2aaSAndroid Build Coastguard Worker if (unicodeName.equals("icu")) {
23*c8dee2aaSAndroid Build Coastguard Worker gUnicode = SkUnicode::ICU::Make();
24*c8dee2aaSAndroid Build Coastguard Worker } else if (unicodeName.equals("icu4x")) {
25*c8dee2aaSAndroid Build Coastguard Worker gUnicode = SkUnicode::ICU4X::Make();
26*c8dee2aaSAndroid Build Coastguard Worker } else if (unicodeName.equals("libgrapheme")) {
27*c8dee2aaSAndroid Build Coastguard Worker gUnicode = SkUnicode::Libgrapheme::Make();
28*c8dee2aaSAndroid Build Coastguard Worker } else {
29*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Implementation '%s' not supported\n", impl);
30*c8dee2aaSAndroid Build Coastguard Worker return false;
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker auto ptr = reinterpret_cast<void*>(gUnicode.get());
33*c8dee2aaSAndroid Build Coastguard Worker if (ptr == nullptr) {
34*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Could not create Unicode object\n");
35*c8dee2aaSAndroid Build Coastguard Worker return false;
36*c8dee2aaSAndroid Build Coastguard Worker }
37*c8dee2aaSAndroid Build Coastguard Worker return true;
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker
cleanup_unicode_impl()40*c8dee2aaSAndroid Build Coastguard Worker void cleanup_unicode_impl() {
41*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
42*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Unicode object does not exist\n");
43*c8dee2aaSAndroid Build Coastguard Worker return;
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker delete gUnicode.get();
46*c8dee2aaSAndroid Build Coastguard Worker }
47*c8dee2aaSAndroid Build Coastguard Worker
perf_compute_codeunit_flags(char * text)48*c8dee2aaSAndroid Build Coastguard Worker double perf_compute_codeunit_flags(char* text) {
49*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
50*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Unicode object does not exist\n");
51*c8dee2aaSAndroid Build Coastguard Worker return -1;
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker double time = SkTime::GetNSecs();
54*c8dee2aaSAndroid Build Coastguard Worker gUnicode->computeCodeUnitFlags(text, strlen(text), false, &gCodeUnitFlags);
55*c8dee2aaSAndroid Build Coastguard Worker if (gCodeUnitFlags.size() < strlen(text)) {
56*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("computeCodeUnitFlags failed: %d < %zu\n%s\n\n\n", gCodeUnitFlags.size(), strlen(text), text);
57*c8dee2aaSAndroid Build Coastguard Worker return -1;
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkUnicode::Position> positions;
60*c8dee2aaSAndroid Build Coastguard Worker gUnicode->getUtf8Words(text, strlen(text), nullptr, &positions);
61*c8dee2aaSAndroid Build Coastguard Worker double result = SkTime::GetNSecs() - time;
62*c8dee2aaSAndroid Build Coastguard Worker for (auto pos : positions) {
63*c8dee2aaSAndroid Build Coastguard Worker gCodeUnitFlags[pos] |= SkUnicode::CodeUnitFlags::kWordBreak;
64*c8dee2aaSAndroid Build Coastguard Worker }
65*c8dee2aaSAndroid Build Coastguard Worker return result;
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker
getFlags(int index)68*c8dee2aaSAndroid Build Coastguard Worker int getFlags(int index) {
69*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
70*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Unicode object does not exist");
71*c8dee2aaSAndroid Build Coastguard Worker } else if (gCodeUnitFlags.size() == 0) {
72*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Unicode object is empty or not initialized\n");
73*c8dee2aaSAndroid Build Coastguard Worker } else if (index < 0 || index >= gCodeUnitFlags.size()) {
74*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Index value %d outside of valid range [%d:%d)\n", index, 0, gCodeUnitFlags.size());
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker return gCodeUnitFlags[index];
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker
getSentences(char * text,int * length)79*c8dee2aaSAndroid Build Coastguard Worker void* getSentences(char* text, int* length) {
80*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
81*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Unicode object does not exist");
82*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
83*c8dee2aaSAndroid Build Coastguard Worker }
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker gSentences.clear();
86*c8dee2aaSAndroid Build Coastguard Worker gUnicode->getSentences(text, strlen(text), nullptr, &gSentences);
87*c8dee2aaSAndroid Build Coastguard Worker *length = gSentences.size();
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<SkUnicode::Position*>(gSentences.data());
90*c8dee2aaSAndroid Build Coastguard Worker }
91*c8dee2aaSAndroid Build Coastguard Worker
trimSentence(char * text,int * sentence,int wordLimit)92*c8dee2aaSAndroid Build Coastguard Worker bool trimSentence(char* text, int* sentence, int wordLimit) {
93*c8dee2aaSAndroid Build Coastguard Worker *sentence = 0;
94*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
95*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Unicode object does not exist");
96*c8dee2aaSAndroid Build Coastguard Worker return true;
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker
99*c8dee2aaSAndroid Build Coastguard Worker gWords.clear();
100*c8dee2aaSAndroid Build Coastguard Worker gUnicode->getUtf8Words(text, strlen(text), nullptr, &gWords);
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker for (auto word : gWords) {
103*c8dee2aaSAndroid Build Coastguard Worker if (word > wordLimit) {
104*c8dee2aaSAndroid Build Coastguard Worker return true;
105*c8dee2aaSAndroid Build Coastguard Worker } else {
106*c8dee2aaSAndroid Build Coastguard Worker *sentence = word;
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker }
109*c8dee2aaSAndroid Build Coastguard Worker if (strlen(text) <= wordLimit) {
110*c8dee2aaSAndroid Build Coastguard Worker *sentence = strlen(text);
111*c8dee2aaSAndroid Build Coastguard Worker return false;
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker return true;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker
toUpper(char * str)117*c8dee2aaSAndroid Build Coastguard Worker void* toUpper(char* str) {
118*c8dee2aaSAndroid Build Coastguard Worker if (gUnicode == nullptr) {
119*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("Unicode object does not exist");
120*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
121*c8dee2aaSAndroid Build Coastguard Worker }
122*c8dee2aaSAndroid Build Coastguard Worker auto res = new SkString(gUnicode->toUpper(SkString(str)));
123*c8dee2aaSAndroid Build Coastguard Worker return reinterpret_cast<void*>(res);
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker
print(void * str)126*c8dee2aaSAndroid Build Coastguard Worker void print(void* str) {
127*c8dee2aaSAndroid Build Coastguard Worker auto ptr = reinterpret_cast<SkString*>(str);
128*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("%s\n", ptr->c_str());
129*c8dee2aaSAndroid Build Coastguard Worker }
130