1*834a2baaSAndroid Build Coastguard Worker /*
2*834a2baaSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*834a2baaSAndroid Build Coastguard Worker *
4*834a2baaSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*834a2baaSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*834a2baaSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*834a2baaSAndroid Build Coastguard Worker *
8*834a2baaSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*834a2baaSAndroid Build Coastguard Worker *
10*834a2baaSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*834a2baaSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*834a2baaSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*834a2baaSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*834a2baaSAndroid Build Coastguard Worker * limitations under the License.
15*834a2baaSAndroid Build Coastguard Worker */
16*834a2baaSAndroid Build Coastguard Worker
17*834a2baaSAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*834a2baaSAndroid Build Coastguard Worker
19*834a2baaSAndroid Build Coastguard Worker #include "ScriptUtils.h"
20*834a2baaSAndroid Build Coastguard Worker #include "UnicodeUtils.h"
21*834a2baaSAndroid Build Coastguard Worker
22*834a2baaSAndroid Build Coastguard Worker namespace minikin {
23*834a2baaSAndroid Build Coastguard Worker namespace {
24*834a2baaSAndroid Build Coastguard Worker
25*834a2baaSAndroid Build Coastguard Worker struct Result {
Resultminikin::__anona594ee8b0111::Result26*834a2baaSAndroid Build Coastguard Worker Result(int start, int end, hb_script_t script) : start(start), end(end), script(script) {}
27*834a2baaSAndroid Build Coastguard Worker int start;
28*834a2baaSAndroid Build Coastguard Worker int end;
29*834a2baaSAndroid Build Coastguard Worker hb_script_t script;
30*834a2baaSAndroid Build Coastguard Worker };
31*834a2baaSAndroid Build Coastguard Worker
operator ==(const Result & l,const Result & r)32*834a2baaSAndroid Build Coastguard Worker bool operator==(const Result& l, const Result& r) {
33*834a2baaSAndroid Build Coastguard Worker return l.start == r.start && l.end == r.end && l.script == r.script;
34*834a2baaSAndroid Build Coastguard Worker }
35*834a2baaSAndroid Build Coastguard Worker
operator <<(std::ostream & os,const Result & r)36*834a2baaSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const Result& r) {
37*834a2baaSAndroid Build Coastguard Worker char buf[5] = {};
38*834a2baaSAndroid Build Coastguard Worker buf[0] = static_cast<char>((r.script >> 24) & 0xFF);
39*834a2baaSAndroid Build Coastguard Worker buf[1] = static_cast<char>((r.script >> 16) & 0xFF);
40*834a2baaSAndroid Build Coastguard Worker buf[2] = static_cast<char>((r.script >> 8) & 0xFF);
41*834a2baaSAndroid Build Coastguard Worker buf[3] = static_cast<char>((r.script) & 0xFF);
42*834a2baaSAndroid Build Coastguard Worker return os << "(" << r.start << "," << r.end << "): " << buf;
43*834a2baaSAndroid Build Coastguard Worker }
44*834a2baaSAndroid Build Coastguard Worker
splitByScript(const std::vector<uint16_t> & text,uint32_t start,uint32_t end)45*834a2baaSAndroid Build Coastguard Worker std::vector<Result> splitByScript(const std::vector<uint16_t>& text, uint32_t start, uint32_t end) {
46*834a2baaSAndroid Build Coastguard Worker std::vector<Result> result;
47*834a2baaSAndroid Build Coastguard Worker for (const auto [range, script] : ScriptText(text, start, end)) {
48*834a2baaSAndroid Build Coastguard Worker result.emplace_back(range.getStart(), range.getEnd(), script);
49*834a2baaSAndroid Build Coastguard Worker }
50*834a2baaSAndroid Build Coastguard Worker return result;
51*834a2baaSAndroid Build Coastguard Worker }
52*834a2baaSAndroid Build Coastguard Worker
splitByScript(const std::string & text,uint32_t start,uint32_t end)53*834a2baaSAndroid Build Coastguard Worker std::vector<Result> splitByScript(const std::string& text, uint32_t start, uint32_t end) {
54*834a2baaSAndroid Build Coastguard Worker std::vector<uint16_t> utf16 = utf8ToUtf16(text);
55*834a2baaSAndroid Build Coastguard Worker return splitByScript(utf16, start, end);
56*834a2baaSAndroid Build Coastguard Worker }
57*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,Latin)58*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, Latin) {
59*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript("abcde", 0, 5);
60*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
61*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 5, HB_SCRIPT_LATIN), result[0]);
62*834a2baaSAndroid Build Coastguard Worker
63*834a2baaSAndroid Build Coastguard Worker result = splitByScript("abcde", 0, 3);
64*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
65*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 3, HB_SCRIPT_LATIN), result[0]);
66*834a2baaSAndroid Build Coastguard Worker
67*834a2baaSAndroid Build Coastguard Worker result = splitByScript("abcde", 2, 5);
68*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
69*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 5, HB_SCRIPT_LATIN), result[0]);
70*834a2baaSAndroid Build Coastguard Worker
71*834a2baaSAndroid Build Coastguard Worker result = splitByScript("abcde", 2, 3);
72*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
73*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 3, HB_SCRIPT_LATIN), result[0]);
74*834a2baaSAndroid Build Coastguard Worker }
75*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,Arabic)76*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, Arabic) {
77*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript("\u0645\u0631\u062D\u0628\u064B\u0627", 0, 6);
78*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
79*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 6, HB_SCRIPT_ARABIC), result[0]);
80*834a2baaSAndroid Build Coastguard Worker
81*834a2baaSAndroid Build Coastguard Worker result = splitByScript("\u0645\u0631\u062D\u0628\u064B\u0627", 0, 3);
82*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
83*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 3, HB_SCRIPT_ARABIC), result[0]);
84*834a2baaSAndroid Build Coastguard Worker
85*834a2baaSAndroid Build Coastguard Worker result = splitByScript("\u0645\u0631\u062D\u0628\u064B\u0627", 2, 5);
86*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
87*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 5, HB_SCRIPT_ARABIC), result[0]);
88*834a2baaSAndroid Build Coastguard Worker
89*834a2baaSAndroid Build Coastguard Worker result = splitByScript("\u0645\u0631\u062D\u0628\u064B\u0627", 2, 3);
90*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
91*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 3, HB_SCRIPT_ARABIC), result[0]);
92*834a2baaSAndroid Build Coastguard Worker }
93*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,Common)94*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, Common) {
95*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript(" ", 0, 5);
96*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
97*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 5, HB_SCRIPT_COMMON), result[0]);
98*834a2baaSAndroid Build Coastguard Worker
99*834a2baaSAndroid Build Coastguard Worker result = splitByScript(" ", 0, 3);
100*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
101*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 3, HB_SCRIPT_COMMON), result[0]);
102*834a2baaSAndroid Build Coastguard Worker
103*834a2baaSAndroid Build Coastguard Worker result = splitByScript(" ", 2, 5);
104*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
105*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 5, HB_SCRIPT_COMMON), result[0]);
106*834a2baaSAndroid Build Coastguard Worker
107*834a2baaSAndroid Build Coastguard Worker result = splitByScript(" ", 2, 3);
108*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
109*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 3, HB_SCRIPT_COMMON), result[0]);
110*834a2baaSAndroid Build Coastguard Worker }
111*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,InheritOrCommon)112*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, InheritOrCommon) {
113*834a2baaSAndroid Build Coastguard Worker // Parens are inherit which is inherit from the previous script. If there is no character
114*834a2baaSAndroid Build Coastguard Worker // before, use the next non-inherit type of script.
115*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript("(abc)", 0, 5);
116*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
117*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 5, HB_SCRIPT_LATIN), result[0]);
118*834a2baaSAndroid Build Coastguard Worker
119*834a2baaSAndroid Build Coastguard Worker result = splitByScript("[(b)]", 0, 5);
120*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
121*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 5, HB_SCRIPT_LATIN), result[0]);
122*834a2baaSAndroid Build Coastguard Worker
123*834a2baaSAndroid Build Coastguard Worker result = splitByScript("[(b)]", 0, 2);
124*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
125*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 2, HB_SCRIPT_COMMON), result[0]);
126*834a2baaSAndroid Build Coastguard Worker }
127*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,MultiScript_InheritOrCommon)128*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, MultiScript_InheritOrCommon) {
129*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript("a(\u0645)e", 0, 5);
130*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 2, HB_SCRIPT_LATIN), result[0]);
131*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 4, HB_SCRIPT_ARABIC), result[1]);
132*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(4, 5, HB_SCRIPT_LATIN), result[2]);
133*834a2baaSAndroid Build Coastguard Worker }
134*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,MultiScript_NoInheritOrCommon)135*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, MultiScript_NoInheritOrCommon) {
136*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript("a\u0645b\u0631c", 0, 5);
137*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 1, HB_SCRIPT_LATIN), result[0]);
138*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(1, 2, HB_SCRIPT_ARABIC), result[1]);
139*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(2, 3, HB_SCRIPT_LATIN), result[2]);
140*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(3, 4, HB_SCRIPT_ARABIC), result[3]);
141*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(4, 5, HB_SCRIPT_LATIN), result[4]);
142*834a2baaSAndroid Build Coastguard Worker }
143*834a2baaSAndroid Build Coastguard Worker
TEST(ScriptUtilsTest,SurrogatePair)144*834a2baaSAndroid Build Coastguard Worker TEST(ScriptUtilsTest, SurrogatePair) {
145*834a2baaSAndroid Build Coastguard Worker auto result = splitByScript(std::vector<uint16_t>({0xD83C, 0xDFF3, 0xD83C, 0xDFF3}), 0, 4);
146*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
147*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 4, HB_SCRIPT_COMMON), result[0]);
148*834a2baaSAndroid Build Coastguard Worker
149*834a2baaSAndroid Build Coastguard Worker result = splitByScript(std::vector<uint16_t>({0xD83C, 0xDFF3, 0xD83C, 0xDFF3}), 0, 3);
150*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
151*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(0, 3, HB_SCRIPT_COMMON), result[0]);
152*834a2baaSAndroid Build Coastguard Worker
153*834a2baaSAndroid Build Coastguard Worker result = splitByScript(std::vector<uint16_t>({0xD83C, 0xDFF3, 0xD83C, 0xDFF3}), 1, 4);
154*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
155*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(1, 4, HB_SCRIPT_COMMON), result[0]);
156*834a2baaSAndroid Build Coastguard Worker
157*834a2baaSAndroid Build Coastguard Worker result = splitByScript(std::vector<uint16_t>({0xD83C, 0xDFF3, 0xD83C, 0xDFF3}), 1, 3);
158*834a2baaSAndroid Build Coastguard Worker ASSERT_EQ(1u, result.size());
159*834a2baaSAndroid Build Coastguard Worker EXPECT_EQ(Result(1, 3, HB_SCRIPT_COMMON), result[0]);
160*834a2baaSAndroid Build Coastguard Worker }
161*834a2baaSAndroid Build Coastguard Worker } // namespace
162*834a2baaSAndroid Build Coastguard Worker } // namespace minikin
163