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