14 #include <pango/pango.h>
19 #include "absl/strings/str_cat.h"
20 #include "gmock/gmock-matchers.h"
34 const char* kExpectedFontNames[] = {
37 "DejaVu Sans Ultra-Light",
39 #if PANGO_VERSION <= 12005
49 const char kArabicText[] =
"والفكر والصراع 1234,\nوالفكر والصراع";
50 const char kEngText[] =
"the quick brown fox jumps over the lazy dog";
51 const char kHinText[] =
"पिताने विवाह की | हो गई उद्विग्न वह सोचा";
52 const char kKorText[] =
"이는 것으로";
54 const char* kBadlyFormedHinWords[] = {
55 #if PANGO_VERSION <= 12005
56 "उपयोक्ताो",
"नहीें",
"कहीअे",
"पत्रिाका",
"छह्णाीस",
62 class PangoFontInfoTest :
public ::testing::Test {
64 void SetUp()
override {
65 static std::locale system_locale(
"");
66 std::locale::global(system_locale);
71 static void SetUpTestCase() {
72 FLAGS_fonts_dir = TESTING_DIR;
74 #ifdef GOOGLE_TESSERACT
75 FLAGS_use_only_legacy_fonts =
false;
79 PangoFontInfo font_info_;
82 TEST_F(PangoFontInfoTest, TestNonDefaultConstructor) {
83 PangoFontInfo font(
"Arial Bold Italic 12");
84 EXPECT_EQ(12, font.font_size());
85 EXPECT_EQ(
"Arial", font.family_name());
88 TEST_F(PangoFontInfoTest, DoesParseFontDescriptionName) {
89 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"Arial Bold Italic 12"));
90 EXPECT_EQ(12, font_info_.font_size());
91 EXPECT_EQ(
"Arial", font_info_.family_name());
93 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"Verdana 10"));
94 EXPECT_EQ(10, font_info_.font_size());
95 EXPECT_EQ(
"Verdana", font_info_.family_name());
97 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"DejaVu Sans Ultra-Light"));
98 EXPECT_EQ(
"DejaVu Sans", font_info_.family_name());
101 TEST_F(PangoFontInfoTest, DoesParseMissingFonts) {
103 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"Arial Italic 12"));
104 EXPECT_EQ(12, font_info_.font_size());
105 EXPECT_EQ(
"Arial", font_info_.family_name());
110 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"Georgia 10"));
111 EXPECT_EQ(10, font_info_.font_size());
112 EXPECT_EQ(
"Georgia", font_info_.family_name());
115 TEST_F(PangoFontInfoTest, DoesGetSpacingProperties) {
116 EXPECT_TRUE(font_info_.ParseFontDescriptionName(
"Arial Italic 12"));
117 int x_bearing, x_advance;
118 EXPECT_TRUE(font_info_.GetSpacingProperties(
"A", &x_bearing, &x_advance));
119 EXPECT_GT(x_advance, 0);
120 EXPECT_TRUE(font_info_.GetSpacingProperties(
"a", &x_bearing, &x_advance));
121 EXPECT_GT(x_advance, 0);
124 TEST_F(PangoFontInfoTest, CanRenderString) {
125 font_info_.ParseFontDescriptionName(
"Verdana 12");
126 EXPECT_TRUE(font_info_.CanRenderString(kEngText, strlen(kEngText)));
128 font_info_.ParseFontDescriptionName(
"UnBatang 12");
129 EXPECT_TRUE(font_info_.CanRenderString(kKorText, strlen(kKorText)));
131 font_info_.ParseFontDescriptionName(
"Lohit Hindi 12");
132 EXPECT_TRUE(font_info_.CanRenderString(kHinText, strlen(kHinText)));
135 TEST_F(PangoFontInfoTest, CanRenderLigature) {
136 font_info_.ParseFontDescriptionName(
"Arab 12");
137 const char kArabicLigature[] =
"لا";
139 font_info_.CanRenderString(kArabicLigature, strlen(kArabicLigature)));
141 printf(
"Next word\n");
142 EXPECT_TRUE(font_info_.CanRenderString(kArabicText, strlen(kArabicText)));
145 TEST_F(PangoFontInfoTest, CannotRenderUncoveredString) {
146 font_info_.ParseFontDescriptionName(
"Verdana 12");
147 EXPECT_FALSE(font_info_.CanRenderString(kKorText, strlen(kKorText)));
150 TEST_F(PangoFontInfoTest, CannotRenderInvalidString) {
151 font_info_.ParseFontDescriptionName(
"Lohit Hindi 12");
152 for (
int i = 0; kBadlyFormedHinWords[i] !=
nullptr; ++i) {
153 EXPECT_FALSE(font_info_.CanRenderString(kBadlyFormedHinWords[i],
154 strlen(kBadlyFormedHinWords[i])))
155 <<
"Can render " << kBadlyFormedHinWords[i];
159 TEST_F(PangoFontInfoTest, CanDropUncoveredChars) {
160 font_info_.ParseFontDescriptionName(
"Verdana 12");
163 EXPECT_EQ(1, font_info_.DropUncoveredChars(&word));
164 EXPECT_EQ(
"oice", word);
167 const char* kJoiners[] = {
172 for (
size_t i = 0; i <
ARRAYSIZE(kJoiners); ++i) {
174 EXPECT_EQ(0, font_info_.DropUncoveredChars(&word));
175 EXPECT_STREQ(kJoiners[i], word.c_str());
181 class FontUtilsTest :
public ::testing::Test {
185 static void SetUpTestCase() {
186 FLAGS_fonts_dir = TESTING_DIR;
190 void CountUnicodeChars(
const char* utf8_text,
191 std::unordered_map<char32, int64_t>* ch_map) {
199 if (std::isspace(*it))
continue;
206 TEST_F(FontUtilsTest, DoesFindAvailableFonts) {
207 EXPECT_TRUE(FontUtils::IsAvailableFont(
"Arial Bold Italic"));
208 EXPECT_TRUE(FontUtils::IsAvailableFont(
"Verdana"));
209 EXPECT_TRUE(FontUtils::IsAvailableFont(
"DejaVu Sans Ultra-Light"));
213 EXPECT_TRUE(FontUtils::IsAvailableFont(
"Times New Roman,"));
216 TEST_F(FontUtilsTest, DoesDetectMissingFonts) {
218 EXPECT_FALSE(FontUtils::IsAvailableFont(
"Arial"));
220 EXPECT_FALSE(FontUtils::IsAvailableFont(
"Courier"));
223 EXPECT_FALSE(FontUtils::IsAvailableFont(
"Verdana Italic"));
225 EXPECT_FALSE(FontUtils::IsAvailableFont(
"DejaVu Sans"));
228 TEST_F(FontUtilsTest, DoesListAvailableFonts) {
229 const std::vector<std::string>& fonts = FontUtils::ListAvailableFonts();
230 EXPECT_THAT(fonts, ::testing::ElementsAreArray(kExpectedFontNames));
231 for (
auto& font : fonts) {
232 PangoFontInfo font_info;
233 EXPECT_TRUE(font_info.ParseFontDescriptionName(font));
237 TEST_F(FontUtilsTest, DoesFindBestFonts) {
239 std::unordered_map<char32, int64_t> ch_map;
240 CountUnicodeChars(kEngText, &ch_map);
241 EXPECT_EQ(26, ch_map.size());
242 std::vector<std::pair<const char*, std::vector<bool> > > font_flags;
243 std::string best_list = FontUtils::BestFonts(ch_map, &font_flags);
244 EXPECT_TRUE(best_list.size());
246 EXPECT_EQ(
ARRAYSIZE(kExpectedFontNames) - 1, font_flags.size());
248 CountUnicodeChars(kKorText, &ch_map);
249 best_list = FontUtils::BestFonts(ch_map, &font_flags);
250 EXPECT_TRUE(best_list.size());
252 EXPECT_EQ(1, font_flags.size());
253 EXPECT_STREQ(
"UnBatang", font_flags[0].first);
256 TEST_F(FontUtilsTest, DoesSelectFont) {
257 const char* kLangText[] = {kArabicText, kEngText, kHinText, kKorText,
nullptr};
258 const char* kLangNames[] = {
"Arabic",
"English",
"Hindi",
"Korean",
nullptr};
259 for (
int i = 0; kLangText[i] !=
nullptr; ++i) {
260 SCOPED_TRACE(kLangNames[i]);
261 std::vector<std::string> graphemes;
263 EXPECT_TRUE(FontUtils::SelectFont(kLangText[i], strlen(kLangText[i]),
264 &selected_font, &graphemes));
265 EXPECT_TRUE(selected_font.size());
266 EXPECT_TRUE(graphemes.size());
270 TEST_F(FontUtilsTest, DoesFailToSelectFont) {
271 const char kMixedScriptText[] =
"पिताने विवाह की | والفكر والصراع";
272 std::vector<std::string> graphemes;
274 EXPECT_FALSE(FontUtils::SelectFont(kMixedScriptText, strlen(kMixedScriptText),
275 &selected_font, &graphemes));
278 TEST_F(FontUtilsTest, GetAllRenderableCharacters) {
279 const int32_t kHindiChar = 0x0905;
280 const int32_t kArabicChar = 0x0623;
281 const int32_t kMongolianChar = 0x180E;
282 const int32_t kOghamChar = 0x1680;
283 std::vector<bool> unicode_mask;
284 FontUtils::GetAllRenderableCharacters(&unicode_mask);
285 EXPECT_TRUE(unicode_mask[
'A']);
286 EXPECT_TRUE(unicode_mask[
'1']);
287 EXPECT_TRUE(unicode_mask[kHindiChar]);
288 EXPECT_TRUE(unicode_mask[kArabicChar]);
289 EXPECT_FALSE(unicode_mask[kMongolianChar]);
290 #if 0 // TODO: check fails because DejaVu Sans Ultra-Light supports ogham
291 EXPECT_FALSE(unicode_mask[kOghamChar]);
293 unicode_mask.clear();
295 std::vector<std::string> selected_fonts;
296 selected_fonts.push_back(
"Lohit Hindi");
297 FontUtils::GetAllRenderableCharacters(selected_fonts, &unicode_mask);
298 EXPECT_TRUE(unicode_mask[
'1']);
299 EXPECT_TRUE(unicode_mask[kHindiChar]);
300 EXPECT_FALSE(unicode_mask[
'A']);
301 EXPECT_FALSE(unicode_mask[kArabicChar]);
302 EXPECT_FALSE(unicode_mask[kMongolianChar]);
303 EXPECT_FALSE(unicode_mask[kOghamChar]);
304 unicode_mask.clear();
308 for (
size_t f = 0; f <
ARRAYSIZE(kExpectedFontNames); ++f) {
309 SCOPED_TRACE(absl::StrCat(
"Testing ", kExpectedFontNames[f]));
310 FontUtils::GetAllRenderableCharacters(kExpectedFontNames[f], &unicode_mask);
311 #if 0 // TODO: check fails because DejaVu Sans Ultra-Light supports ogham
312 EXPECT_FALSE(unicode_mask[kOghamChar]);
314 EXPECT_FALSE(unicode_mask[kMongolianChar]);
315 unicode_mask.clear();