From 8ecaad56e37b66f68588a3fc39e44a15131ee957 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 23 Jun 2022 11:54:10 +0200 Subject: [PATCH] Use Leptonica API to access internals of Box Signed-off-by: Stefan Weil --- src/training/pango/boxchar.cpp | 90 ++++++++++++++++++--------- src/training/pango/boxchar.h | 9 +-- src/training/pango/stringrenderer.cpp | 25 +++++--- src/training/text2image.cpp | 21 ++++--- 4 files changed, 97 insertions(+), 48 deletions(-) diff --git a/src/training/pango/boxchar.cpp b/src/training/pango/boxchar.cpp index ec16d743d4..c31eed57d9 100644 --- a/src/training/pango/boxchar.cpp +++ b/src/training/pango/boxchar.cpp @@ -84,8 +84,10 @@ void BoxChar::TranslateBoxes(int xshift, int yshift, std::vector *box for (auto &boxe : *boxes) { Box *box = boxe->box_; if (box != nullptr) { - box->x += xshift; - box->y += yshift; + int32_t box_x; + int32_t box_y; + boxGetGeometry(box, &box_x, &box_y, nullptr, nullptr); + boxSetGeometry(box, box_x + xshift, box_y + yshift, -1, -1); } } } @@ -129,10 +131,18 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vectorbox_; - int shift = box->x - prev_box->x; + int32_t prev_box_x; + int32_t prev_box_y; + int32_t prev_box_w; + int32_t prev_box_h; + boxGetGeometry(prev_box, &prev_box_x, &prev_box_y, &prev_box_w, &prev_box_h); + int shift = box_x - prev_box_x; if (vertical_rules) { - shift = box->y - prev_box->y; + shift = box_y - prev_box_y; } else if (rtl_rules) { shift = -shift; } @@ -142,15 +152,15 @@ void BoxChar::InsertNewlines(bool rtl_rules, bool vertical_rules, std::vectorx + prev_box->w; - int y = prev_box->y; + int x = prev_box_x + prev_box_w; + int y = prev_box_y; if (vertical_rules) { - x = prev_box->x; - y = prev_box->y + prev_box->h; + x = prev_box_x; + y = prev_box_y + prev_box_h; } else if (rtl_rules) { - x = prev_box->x - width; + x = prev_box_x - width; if (x < 0) { - tprintf("prev x = %d, width=%d\n", prev_box->x, width); + tprintf("prev x = %d, width=%d\n", prev_box_x, width); x = 0; } } @@ -184,27 +194,38 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vectorbox_; Box *next = (*boxes)[i + 1]->box_; + int32_t prev_x; + int32_t prev_y; + int32_t prev_w; + int32_t prev_h; + int32_t next_x; + int32_t next_y; + int32_t next_w; + int32_t next_h; ASSERT_HOST(prev != nullptr && next != nullptr); - int top = std::min(prev->y, next->y); - int bottom = std::max(prev->y + prev->h, next->y + next->h); - int left = prev->x + prev->w; - int right = next->x; + boxGetGeometry(prev, &prev_x, &prev_y, &prev_w, &prev_h); + boxGetGeometry(next, &next_x, &next_y, &next_w, &next_h); + int top = std::min(prev_y, next_y); + int bottom = std::max(prev_y + prev_h, next_y + next_h); + int left = prev_x + prev_w; + int right = next_x; if (vertical_rules) { - top = prev->y + prev->h; - bottom = next->y; - left = std::min(prev->x, next->x); - right = std::max(prev->x + prev->w, next->x + next->w); + top = prev_y + prev_h; + bottom = next_y; + left = std::min(prev_x, next_x); + right = std::max(prev_x + prev_w, next_x + next_w); } else if (rtl_rules) { // With RTL we have to account for BiDi. // Right becomes the min left of all prior boxes back to the first // space or newline. - right = prev->x; - left = next->x + next->w; + right = prev_x; + left = next_x + next_w; for (int j = i - 2; j >= 0 && (*boxes)[j]->ch_ != " " && (*boxes)[j]->ch_ != "\t"; --j) { prev = (*boxes)[j]->box_; ASSERT_HOST(prev != nullptr); - if (prev->x < right) { - right = prev->x; + boxGetGeometry(prev, &prev_x, nullptr, nullptr, nullptr); + if (prev_x < right) { + right = prev_x; } } // Left becomes the max right of all next boxes forward to the first @@ -212,8 +233,9 @@ void BoxChar::InsertSpaces(bool rtl_rules, bool vertical_rules, std::vectorsize() && (*boxes)[j]->box_ != nullptr && (*boxes)[j]->ch_ != "\t"; ++j) { next = (*boxes)[j]->box_; - if (next->x + next->w > left) { - left = next->x + next->w; + boxGetGeometry(next, &next_x, nullptr, &next_w, nullptr); + if (next_x + next_w > left) { + left = next_x + next_w; } } } @@ -275,8 +297,14 @@ bool BoxChar::MostlyVertical(const std::vector &boxes) { for (size_t i = 1; i < boxes.size(); ++i) { if (boxes[i - 1]->box_ != nullptr && boxes[i]->box_ != nullptr && boxes[i - 1]->page_ == boxes[i]->page_) { - int dx = boxes[i]->box_->x - boxes[i - 1]->box_->x; - int dy = boxes[i]->box_->y - boxes[i - 1]->box_->y; + int32_t x0; + int32_t y0; + boxGetGeometry(boxes[i]->box_, &x0, &y0, nullptr, nullptr); + int32_t x1; + int32_t y1; + boxGetGeometry(boxes[i - 1]->box_, &x1, &y1, nullptr, nullptr); + int dx = x0 - x1; + int dy = y0 - y1; if (abs(dx) > abs(dy) * kMinNewlineRatio || abs(dy) > abs(dx) * kMinNewlineRatio) { total_dx += dx * dx; total_dy += dy * dy; @@ -337,8 +365,14 @@ std::string BoxChar::GetTesseractBoxStr(int height, const std::vector tprintf("Error: Call PrepareToWrite before WriteTesseractBoxFile!!\n"); return ""; } - int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n", boxe->ch_.c_str(), box->x, - height - box->y - box->h, box->x + box->w, height - box->y, boxe->page_); + int32_t box_x; + int32_t box_y; + int32_t box_w; + int32_t box_h; + boxGetGeometry(const_cast(box), &box_x, &box_y, &box_w, &box_h); + int nbytes = snprintf(buffer, kMaxLineLength, "%s %d %d %d %d %d\n", + boxe->ch_.c_str(), box_x, height - box_y - box_h, + box_x + box_w, height - box_y, boxe->page_); output.append(buffer, nbytes); } return output; diff --git a/src/training/pango/boxchar.h b/src/training/pango/boxchar.h index 7c24ca523b..b369dacd70 100644 --- a/src/training/pango/boxchar.h +++ b/src/training/pango/boxchar.h @@ -26,9 +26,6 @@ #include #include // for Leptonica API -#if (LIBLEPT_MAJOR_VERSION == 1 && LIBLEPT_MINOR_VERSION >= 83) || LIBLEPT_MAJOR_VERSION > 1 -#include // for fast access to Box geometry -#endif #include namespace tesseract { @@ -79,7 +76,11 @@ class BoxChar { if (other.box_ == nullptr) { return false; } - return box_->x < other.box_->x; + int32_t box_x; + int32_t other_box_x; + boxGetGeometry(box_, &box_x, nullptr, nullptr, nullptr); + boxGetGeometry(other.box_, &other_box_x, nullptr, nullptr, nullptr); + return box_x < other_box_x; } // Increments *num_rtl and *num_ltr according to the directionality of // characters in the box. diff --git a/src/training/pango/stringrenderer.cpp b/src/training/pango/stringrenderer.cpp index b3f9a58d4f..4fe7952ddd 100644 --- a/src/training/pango/stringrenderer.cpp +++ b/src/training/pango/stringrenderer.cpp @@ -428,15 +428,25 @@ static void MergeBoxCharsToWords(std::vector *boxchars) { BoxChar *last_boxchar = result.back(); // Compute bounding box union const Box *box = boxchar->box(); + int32_t box_x; + int32_t box_y; + int32_t box_w; + int32_t box_h; + boxGetGeometry(const_cast(box), &box_x, &box_y, &box_w, &box_h); Box *last_box = last_boxchar->mutable_box(); - int left = std::min(last_box->x, box->x); - int right = std::max(last_box->x + last_box->w, box->x + box->w); - int top = std::min(last_box->y, box->y); - int bottom = std::max(last_box->y + last_box->h, box->y + box->h); + int32_t last_box_x; + int32_t last_box_y; + int32_t last_box_w; + int32_t last_box_h; + boxGetGeometry(last_box, &last_box_x, &last_box_y, &last_box_w, &last_box_h); + int left = std::min(last_box_x, box_x); + int right = std::max(last_box_x + last_box_w, box_x + box_w); + int top = std::min(last_box_y, box_y); + int bottom = std::max(last_box_y + last_box_h, box_y + box_h); // Conclude that the word was broken to span multiple lines based on the // size of the merged bounding box in relation to those of the individual // characters seen so far. - if (right - left > last_box->w + 5 * box->w) { + if (right - left > last_box_w + 5 * box_w) { tlog(1, "Found line break after '%s'", last_boxchar->ch().c_str()); // Insert a fake interword space and start a new word with the current // boxchar. @@ -447,10 +457,7 @@ static void MergeBoxCharsToWords(std::vector *boxchars) { } // Append to last word last_boxchar->mutable_ch()->append(boxchar->ch()); - last_box->x = left; - last_box->w = right - left; - last_box->y = top; - last_box->h = bottom - top; + boxSetGeometry(last_box, left, top, right - left, bottom - top); delete boxchar; boxchar = nullptr; } diff --git a/src/training/text2image.cpp b/src/training/text2image.cpp index c30ca33dc1..a8d318adbc 100644 --- a/src/training/text2image.cpp +++ b/src/training/text2image.cpp @@ -282,12 +282,18 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer * if (IsWhitespaceBox(boxes[b + 1])) { continue; } - int xgap = (boxes[b + 1]->box()->x - (boxes[b]->box()->x + boxes[b]->box()->w)); + int32_t box_x; + int32_t box_w; + boxGetGeometry(const_cast(boxes[b]->box()), &box_x, nullptr, &box_w, nullptr); + int32_t box1_x; + int32_t box1_w; + boxGetGeometry(const_cast(boxes[b + 1]->box()), &box1_x, nullptr, &box1_w, nullptr); + int xgap = (box1_x - (box_x + box_w)); spacing_map_it0 = spacing_map.find(ch0); int ok_count = 0; if (spacing_map_it0 == spacing_map.end() && render->font().GetSpacingProperties(ch0, &x_bearing, &x_advance)) { - spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b]->box()->w); + spacing_map[ch0] = SpacingProperties(x_bearing, x_advance - x_bearing - box_w); spacing_map_it0 = spacing_map.find(ch0); ++ok_count; } @@ -297,7 +303,7 @@ static void ExtractFontProperties(const std::string &utf8_text, StringRenderer * if (spacing_map_it1 == spacing_map.end() && render->font().GetSpacingProperties(ch1, &x_bearing, &x_advance)) { spacing_map[ch1] = - SpacingProperties(x_bearing, x_advance - x_bearing - boxes[b + 1]->box()->w); + SpacingProperties(x_bearing, x_advance - x_bearing - box1_w); spacing_map_it1 = spacing_map.find(ch1); ++ok_count; } @@ -356,10 +362,11 @@ static bool MakeIndividualGlyphs(Image pix, const std::vector &vbox, if (!b) { continue; } - const int x = b->x; - const int y = b->y; - const int w = b->w; - const int h = b->h; + int32_t x; + int32_t y; + int32_t w; + int32_t h; + boxGetGeometry(b, &x, &y, &w, &h); // Check present tiff page (for multipage tiff) if (y < y_previous - pixGetHeight(pix) / 10) { tprintf("ERROR: Wrap-around encountered, at i=%d\n", i);