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