15 #include "absl/strings/str_split.h"
17 #include "allheaders.h"
35 const char kEngText[] =
"the quick brown fox jumps over the lazy dog";
36 const char kHinText[] =
"पिताने विवाह की | हो गई उद्विग्न वह सोचा";
38 const char kKorText[] =
"이는 것으로 다시 넣을 1234 수는 있지만 선택의 의미는";
39 const char kArabicText[] =
40 "والفكر والصراع ، بالتأمل والفهم والتحليل ، "
41 "بالعلم والفن ، وأخيرا بالضحك أوبالبكاء ، ";
42 const char kMixedText[] =
"والفكر 123 والصراع abc";
44 const char kEngNonLigatureText[] =
"fidelity";
46 const char kEngLigatureText[] =
"fidelity";
51 class StringRendererTest :
public ::testing::Test {
53 void SetUp()
override {
54 static std::locale system_locale(
"");
55 std::locale::global(system_locale);
58 static void SetUpTestCase() {
59 l_chooseDisplayProg(L_DISPLAY_WITH_XZGV);
60 FLAGS_fonts_dir = TESTING_DIR;
62 #ifdef GOOGLE_TESSERACT
63 FLAGS_use_only_legacy_fonts =
false;
65 FLAGS_heap_check_max_pointer_offset = -1;
69 void DisplayClusterBoxes(Pix* pix) {
70 if (!FLAGS_display)
return;
71 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
72 Boxa* boxes = boxaCreate(0);
73 for (
const auto& boxchar : boxchars) {
75 boxaAddBox(boxes, const_cast<Box*>(boxchar->box()), L_CLONE);
77 Pix* box_pix = pixDrawBoxaRandom(pix, boxes, 1);
79 pixDisplay(box_pix, 0, 0);
82 std::unique_ptr<StringRenderer> renderer_;
85 TEST_F(StringRendererTest, DoesRenderToImage) {
86 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
88 EXPECT_EQ(strlen(kEngText),
89 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
90 EXPECT_TRUE(pix !=
nullptr);
91 EXPECT_GT(renderer_->GetBoxes().size(), 0);
92 DisplayClusterBoxes(pix);
95 renderer_.reset(
new StringRenderer(
"UnBatang 10", 600, 600));
96 EXPECT_EQ(strlen(kKorText),
97 renderer_->RenderToImage(kKorText, strlen(kKorText), &pix));
98 EXPECT_GT(renderer_->GetBoxes().size(), 0);
99 DisplayClusterBoxes(pix);
102 renderer_.reset(
new StringRenderer(
"Lohit Hindi 10", 600, 600));
103 EXPECT_EQ(strlen(kHinText),
104 renderer_->RenderToImage(kHinText, strlen(kHinText), &pix));
105 EXPECT_GT(renderer_->GetBoxes().size(), 0);
106 DisplayClusterBoxes(pix);
110 renderer_.reset(
new StringRenderer(
"Arab 10", 600, 600));
111 EXPECT_EQ(strlen(kArabicText),
112 renderer_->RenderToImage(kArabicText, strlen(kArabicText), &pix));
113 EXPECT_TRUE(pix !=
nullptr);
114 EXPECT_GT(renderer_->GetBoxes().size(), 0);
115 DisplayClusterBoxes(pix);
119 renderer_.reset(
new StringRenderer(
"Arab 10", 600, 600));
120 EXPECT_EQ(strlen(kMixedText),
121 renderer_->RenderToImage(kMixedText, strlen(kMixedText), &pix));
122 EXPECT_TRUE(pix !=
nullptr);
123 EXPECT_GT(renderer_->GetBoxes().size(), 0);
124 DisplayClusterBoxes(pix);
128 TEST_F(StringRendererTest, DoesRenderToImageWithUnderline) {
129 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
131 renderer_->set_underline_start_prob(1.0);
132 renderer_->set_underline_continuation_prob(0);
134 EXPECT_EQ(strlen(kEngText),
135 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
136 EXPECT_TRUE(pix !=
nullptr);
137 EXPECT_GT(renderer_->GetBoxes().size(), 0);
138 DisplayClusterBoxes(pix);
140 renderer_->ClearBoxes();
143 renderer_->set_underline_start_prob(1.0);
144 renderer_->set_underline_continuation_prob(1.0);
145 EXPECT_EQ(strlen(kEngText),
146 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
147 EXPECT_TRUE(pix !=
nullptr);
148 EXPECT_GT(renderer_->GetBoxes().size(), 0);
149 DisplayClusterBoxes(pix);
151 renderer_->ClearBoxes();
154 renderer_->set_underline_start_prob(0.5);
155 renderer_->set_underline_continuation_prob(0.5);
156 EXPECT_EQ(strlen(kEngText),
157 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
158 EXPECT_TRUE(pix !=
nullptr);
159 EXPECT_GT(renderer_->GetBoxes().size(), 0);
160 DisplayClusterBoxes(pix);
164 TEST_F(StringRendererTest, DoesHandleNewlineCharacters) {
165 const char kRawText[] =
"\n\n\n A \nB \nC \n\n\n";
166 const char kStrippedText[] =
" A B C ";
167 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
169 EXPECT_EQ(strlen(kRawText),
170 renderer_->RenderToImage(kRawText, strlen(kRawText), &pix));
171 EXPECT_TRUE(pix !=
nullptr);
172 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
174 EXPECT_EQ(7, boxchars.size());
175 if (boxchars.size() == 7) {
177 for (
size_t i = 0; i < boxchars.size(); ++i) {
178 EXPECT_EQ(
std::string(1, kStrippedText[i]), boxchars[i]->ch());
181 DisplayClusterBoxes(pix);
185 TEST_F(StringRendererTest, DoesRenderLigatures) {
186 renderer_.reset(
new StringRenderer(
"Arab 12", 600, 250));
187 const char kArabicLigature[] =
"لا";
191 strlen(kArabicLigature),
192 renderer_->RenderToImage(kArabicLigature, strlen(kArabicLigature), &pix));
193 EXPECT_TRUE(pix !=
nullptr);
194 EXPECT_GT(renderer_->GetBoxes().size(), 0);
195 const std::vector<BoxChar*>& boxes = renderer_->GetBoxes();
196 EXPECT_EQ(1, boxes.size());
197 EXPECT_TRUE(boxes[0]->box() !=
nullptr);
198 EXPECT_STREQ(kArabicLigature, boxes[0]->ch().c_str());
199 DisplayClusterBoxes(pix);
202 renderer_.reset(
new StringRenderer(
"Arab 12", 600, 250));
203 const char kArabicMixedText[] =
"والفكر والصراع 1234,\nوالفكر لا والصراع";
204 renderer_->RenderToImage(kArabicMixedText, strlen(kArabicMixedText), &pix);
205 DisplayClusterBoxes(pix);
209 static int FindBoxCharXCoord(
const std::vector<BoxChar*>& boxchars,
211 for (
const auto& boxchar : boxchars) {
212 if (boxchar->ch() == ch)
return boxchar->box()->x;
217 TEST_F(StringRendererTest, ArabicBoxcharsInLTROrder) {
218 renderer_.reset(
new StringRenderer(
"Arab 10", 600, 600));
221 const char kArabicWord[] =
"\u0644\u0627\u0641\u0643\u0631";
222 const std::string kRevWord =
"\u0631\u0643\u0641\u0627\u0644";
223 renderer_->RenderToImage(kArabicWord, strlen(kArabicWord), &pix);
226 EXPECT_FALSE(boxes_str.empty());
228 EXPECT_TRUE(
ReadMemBoxes(0,
false, boxes_str.c_str(),
false,
nullptr, &texts,
231 for (
int i = 0; i < texts.size(); ++i) {
232 ltr_str += texts[i].c_str();
236 EXPECT_EQ(ltr_str, kRevWord);
239 EXPECT_LT(texts.size(), 5);
243 TEST_F(StringRendererTest, DoesOutputBoxcharsInReadingOrder) {
244 renderer_.reset(
new StringRenderer(
"Arab 10", 600, 600));
247 const char kArabicWord[] =
"والفكر";
248 renderer_->RenderToImage(kArabicWord, strlen(kArabicWord), &pix);
249 EXPECT_GT(renderer_->GetBoxes().size(), 0);
250 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
251 for (
size_t i = 1; i < boxchars.size(); ++i) {
252 EXPECT_GT(boxchars[i - 1]->box()->x, boxchars[i]->box()->x)
253 << boxchars[i - 1]->ch();
258 const char kEnglishWord[] =
"Google";
259 renderer_->ClearBoxes();
260 renderer_->RenderToImage(kEnglishWord, strlen(kEnglishWord), &pix);
261 EXPECT_EQ(boxchars.size(), strlen(kEnglishWord));
262 for (
size_t i = 1; i < boxchars.size(); ++i) {
263 EXPECT_LT(boxchars[i - 1]->box()->x, boxchars[i]->box()->x)
264 << boxchars[i - 1]->ch();
269 renderer_->ClearBoxes();
270 renderer_->RenderToImage(kMixedText, strlen(kMixedText), &pix);
271 EXPECT_LT(FindBoxCharXCoord(boxchars,
"a"), FindBoxCharXCoord(boxchars,
"b"));
272 EXPECT_LT(FindBoxCharXCoord(boxchars,
"1"), FindBoxCharXCoord(boxchars,
"2"));
273 EXPECT_GT(FindBoxCharXCoord(boxchars,
"و"), FindBoxCharXCoord(boxchars,
"ر"));
277 TEST_F(StringRendererTest, DoesRenderVerticalText) {
279 renderer_.reset(
new StringRenderer(
"UnBatang 10", 600, 600));
280 renderer_->set_vertical_text(
true);
281 EXPECT_EQ(strlen(kKorText),
282 renderer_->RenderToImage(kKorText, strlen(kKorText), &pix));
283 EXPECT_GT(renderer_->GetBoxes().size(), 0);
284 DisplayClusterBoxes(pix);
290 TEST_F(StringRendererTest, DoesKeepAllImageBoxes) {
291 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
293 int num_boxes_per_page = 0;
294 const int kNumTrials = 2;
295 for (
int i = 0; i < kNumTrials; ++i) {
296 EXPECT_EQ(strlen(kEngText),
297 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
298 EXPECT_TRUE(pix !=
nullptr);
300 EXPECT_GT(renderer_->GetBoxes().size(), 0);
301 if (!num_boxes_per_page) {
302 num_boxes_per_page = renderer_->GetBoxes().size();
304 EXPECT_EQ((i + 1) * num_boxes_per_page, renderer_->GetBoxes().size());
306 for (
int j = i * num_boxes_per_page; j < (i + 1) * num_boxes_per_page;
308 EXPECT_EQ(i, renderer_->GetBoxes()[j]->page());
313 TEST_F(StringRendererTest, DoesClearBoxes) {
314 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
316 EXPECT_EQ(strlen(kEngText),
317 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
319 EXPECT_GT(renderer_->GetBoxes().size(), 0);
320 const int num_boxes_per_page = renderer_->GetBoxes().size();
322 renderer_->ClearBoxes();
323 EXPECT_EQ(strlen(kEngText),
324 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
326 EXPECT_EQ(num_boxes_per_page, renderer_->GetBoxes().size());
329 TEST_F(StringRendererTest, DoesLigatureTextForRendering) {
330 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
331 renderer_->set_add_ligatures(
true);
333 EXPECT_EQ(strlen(kEngNonLigatureText),
334 renderer_->RenderToImage(kEngNonLigatureText,
335 strlen(kEngNonLigatureText), &pix));
338 EXPECT_EQ(strlen(kEngNonLigatureText) - 1, renderer_->GetBoxes().size());
340 EXPECT_STREQ(
"fi", renderer_->GetBoxes()[0]->ch().c_str());
343 TEST_F(StringRendererTest, DoesRetainInputLigatureForRendering) {
344 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
346 EXPECT_EQ(strlen(kEngLigatureText),
347 renderer_->RenderToImage(kEngLigatureText, strlen(kEngLigatureText),
351 EXPECT_EQ(strlen(kEngNonLigatureText) - 1, renderer_->GetBoxes().size());
353 EXPECT_STREQ(
"\uFB01", renderer_->GetBoxes()[0]->ch().c_str());
356 TEST_F(StringRendererTest, DoesStripUnrenderableWords) {
359 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
361 EXPECT_GT(renderer_->StripUnrenderableWords(&text), 0);
362 EXPECT_EQ(
" 123 abc", text);
365 TEST_F(StringRendererTest, DoesRenderWordBoxes) {
366 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
367 renderer_->set_output_word_boxes(
true);
369 EXPECT_EQ(strlen(kEngText),
370 renderer_->RenderToImage(kEngText, strlen(kEngText), &pix));
373 std::vector<std::string> words =
374 absl::StrSplit(kEngText,
' ', absl::SkipEmpty());
375 const int kNumSpaces = words.size() - 1;
376 const int kExpectedNumBoxes = words.size() + kNumSpaces;
377 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
378 EXPECT_EQ(kExpectedNumBoxes, boxchars.size());
380 for (
size_t i = 0; i < boxchars.size(); i += 2) {
381 EXPECT_EQ(words[i / 2], boxchars[i]->ch());
382 if (i < boxchars.size() - 1) {
383 EXPECT_EQ(
" ", boxchars[i + 1]->ch());
384 EXPECT_TRUE(boxchars[i + 1]->box() ==
nullptr);
389 TEST_F(StringRendererTest, DoesRenderWordBoxesFromMultiLineText) {
390 renderer_.reset(
new StringRenderer(
"Verdana 10", 600, 600));
391 renderer_->set_output_word_boxes(
true);
393 const char kMultlineText[] =
"the quick brown fox\njumps over the lazy dog";
394 EXPECT_EQ(strlen(kMultlineText),
395 renderer_->RenderToImage(kMultlineText, strlen(kEngText), &pix));
398 std::vector<std::string> words =
399 absl::StrSplit(kMultlineText, absl::ByAnyChar(
" \n"), absl::SkipEmpty());
400 const int kNumSeparators = words.size() - 1;
401 const int kExpectedNumBoxes = words.size() + kNumSeparators;
402 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
403 EXPECT_EQ(kExpectedNumBoxes, boxchars.size());
405 for (
size_t i = 0; i < boxchars.size(); i += 2) {
406 EXPECT_EQ(words[i / 2], boxchars[i]->ch());
407 if (i + 1 < boxchars.size()) {
408 EXPECT_EQ(
" ", boxchars[i + 1]->ch());
409 EXPECT_TRUE(boxchars[i + 1]->box() ==
nullptr);
414 TEST_F(StringRendererTest, DoesRenderAllFontsToImage) {
415 renderer_.reset(
new StringRenderer(
"Verdana 10", 1200, 1200));
421 offset += renderer_->RenderAllFontsToImage(
422 1.0, kEngText + offset, strlen(kEngText + offset), &font_used, &pix);
423 if (offset < strlen(kEngText)) {
424 EXPECT_TRUE(pix !=
nullptr);
425 EXPECT_STRNE(
"", font_used.c_str());
427 if (FLAGS_display) pixDisplay(pix, 0, 0);
429 }
while (offset < strlen(kEngText));
432 TEST_F(StringRendererTest, DoesNotRenderWordJoiner) {
433 renderer_.reset(
new StringRenderer(
"Verdana 10", 500, 200));
435 const std::string joined_word = StringRenderer::InsertWordJoiners(word);
437 renderer_->RenderToImage(joined_word.c_str(), joined_word.length(), &pix);
439 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
441 ASSERT_EQ(word.length(), boxchars.size());
442 for (
size_t i = 0; i < boxchars.size(); ++i) {
443 EXPECT_NE(kWordJoinerUTF8, boxchars[i]->ch());
444 EXPECT_EQ(word.substr(i, 1), boxchars[i]->ch());
448 TEST_F(StringRendererTest, DISABLED_DoesDropUncoveredChars) {
449 renderer_.reset(
new StringRenderer(
"Verdana 10", 500, 200));
450 renderer_->set_drop_uncovered_chars(
true);
455 renderer_->font().CanRenderString(kWord.c_str(), kWord.length()));
456 EXPECT_FALSE(renderer_->font().CoversUTF8Text(kWord.c_str(), kWord.length()));
457 int offset = renderer_->RenderToImage(kWord.c_str(), kWord.length(), &pix);
459 const std::vector<BoxChar*>& boxchars = renderer_->GetBoxes();
460 EXPECT_EQ(kWord.length(), offset);
461 ASSERT_EQ(kCleanWord.length(), boxchars.size());
462 for (
size_t i = 0; i < boxchars.size(); ++i) {
463 EXPECT_EQ(kCleanWord.substr(i, 1), boxchars[i]->ch());
469 TEST(ConvertBasicLatinToFullwidthLatinTest, DoesConvertBasicLatin) {
472 EXPECT_EQ(kFullAlpha,
473 StringRenderer::ConvertBasicLatinToFullwidthLatin(kHalfAlpha));
477 EXPECT_EQ(kFullDigit,
478 StringRenderer::ConvertBasicLatinToFullwidthLatin(kHalfDigit));
483 StringRenderer::ConvertBasicLatinToFullwidthLatin(kHalfSym));
486 TEST(ConvertBasicLatinToFullwidthLatinTest, DoesNotConvertFullwidthLatin) {
488 EXPECT_EQ(kFullAlpha,
489 StringRenderer::ConvertBasicLatinToFullwidthLatin(kFullAlpha));
492 EXPECT_EQ(kFullDigit,
493 StringRenderer::ConvertBasicLatinToFullwidthLatin(kFullDigit));
497 StringRenderer::ConvertBasicLatinToFullwidthLatin(kFullSym));
500 TEST(ConvertBasicLatinToFullwidthLatinTest, DoesNotConvertNonLatin) {
504 StringRenderer::ConvertBasicLatinToFullwidthLatin(kHalfKana));
506 StringRenderer::ConvertBasicLatinToFullwidthLatin(kFullKana));
509 TEST(ConvertBasicLatinToFullwidthLatinTest, DoesNotConvertSpace) {
512 EXPECT_EQ(kHalfSpace,
513 StringRenderer::ConvertBasicLatinToFullwidthLatin(kHalfSpace));
514 EXPECT_EQ(kFullSpace,
515 StringRenderer::ConvertBasicLatinToFullwidthLatin(kFullSpace));
520 TEST(ConvertFullwidthLatinToBasicLatinTest, DoesConvertFullwidthLatin) {
523 EXPECT_EQ(kHalfAlpha,
524 StringRenderer::ConvertFullwidthLatinToBasicLatin(kFullAlpha));
528 EXPECT_EQ(kHalfDigit,
529 StringRenderer::ConvertFullwidthLatinToBasicLatin(kFullDigit));
534 StringRenderer::ConvertFullwidthLatinToBasicLatin(kFullSym));
537 TEST(ConvertFullwidthLatinToBasicLatinTest, DoesNotConvertBasicLatin) {
539 EXPECT_EQ(kHalfAlpha,
540 StringRenderer::ConvertFullwidthLatinToBasicLatin(kHalfAlpha));
543 EXPECT_EQ(kHalfDigit,
544 StringRenderer::ConvertFullwidthLatinToBasicLatin(kHalfDigit));
548 StringRenderer::ConvertFullwidthLatinToBasicLatin(kHalfSym));
551 TEST(ConvertFullwidthLatinToBasicLatinTest, DoesNotConvertNonLatin) {
555 StringRenderer::ConvertFullwidthLatinToBasicLatin(kHalfKana));
557 StringRenderer::ConvertFullwidthLatinToBasicLatin(kFullKana));
560 TEST(ConvertFullwidthLatinToBasicLatinTest, DoesNotConvertSpace) {
563 EXPECT_EQ(kHalfSpace,
564 StringRenderer::ConvertFullwidthLatinToBasicLatin(kHalfSpace));
565 EXPECT_EQ(kFullSpace,
566 StringRenderer::ConvertFullwidthLatinToBasicLatin(kFullSpace));