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 18using namespace skia_private; 19 20#ifdef SK_UNICODE_CLIENT_IMPLEMENTATION 21UNIX_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 35UNIX_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 46UNIX_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 59UNIX_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} 73UNIX_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 88UNIX_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 121UNIX_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 144UNIX_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 154UNIX_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 187UNIX_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