21 #include "config_auto.h"    74                                      int height, 
int v_gap_multiple,
   145   : 
BlobGrid(gridsize, bleft, tright) {
   163 #ifndef GRAPHICS_DISABLED   172     int left_x = box.
left();
   173     int right_x = box.
right();
   174     int top_y = box.
top();
   175     int bottom_y = box.
bottom();
   186       tab_win->
Line(left_x, top_y, left_x, bottom_y);
   198       tab_win->
Line(right_x, top_y, right_x, bottom_y);
   208 static bool AtLeast2LineCrossings(BLOBNBOX_CLIST* blobs) {
   209   BLOBNBOX_C_IT it(blobs);
   210   int total_crossings = 0;
   211   for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
   212     total_crossings += it.data()->line_crossings();
   214   return total_crossings >= 2;
   227   int ext_start_y, ext_end_y;
   228   BLOBNBOX_CLIST good_points;
   232   int pt_count = AlignTabs(align_params, 
false, bbox, &good_points, &ext_end_y);
   233   pt_count += AlignTabs(align_params, 
true, bbox, &good_points, &ext_start_y);
   234   BLOBNBOX_C_IT it(&good_points);
   236   box = it.data()->bounding_box();
   237   int end_y = box.
top();
   240   box = it.data()->bounding_box();
   242   int start_y = box.
bottom();
   248   bool at_least_2_crossings = AtLeast2LineCrossings(&good_points);
   252           end_y - start_y >= abs(end_x - start_x) * kMinTabGradient)) ||
   253       at_least_2_crossings) {
   254     int confirmed_points = 0;
   256     for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
   267     if (!align_params.
ragged ||
   268         confirmed_points + confirmed_points < pt_count) {
   271         tprintf(
"Confirming tab vector of %d pts starting at %d,%d\n",
   275       for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
   289                                                ext_start_y, ext_end_y,
   291                                                vertical_x, vertical_y);
   295         result->
Print(
"After fitting");
   299       tprintf(
"Ragged tab used too many used points: %d out of %d\n",
   300               confirmed_points, pt_count);
   303     tprintf(
"Tab vector failed basic tests: pt count %d vs min %d, "   304             "length %d vs min %d, min grad %g\n",
   305             pt_count, align_params.
min_points, end_y - start_y,
   306             align_params.
min_length, abs(end_x - start_x) * kMinTabGradient);
   317                            BLOBNBOX_CLIST* good_points, 
int* end_y) {
   319   BLOBNBOX_C_IT it(good_points);
   324     tprintf(
"Starting alignment run at blob:");
   328   while (bbox != NULL) {
   334         (it.empty() || it.data() != bbox)) {
   336         it.add_before_then_move(bbox);
   338         it.add_after_then_move(bbox);
   345     bbox = FindAlignedBlob(params, top_to_bottom, bbox, x_start, end_y);
   353     tprintf(
"Alignment run ended with %d pts at blob:", ptcount);
   368                                        int x_start, 
int* end_y) {
   371   int left_column_edge = bbox->
left_rule();
   376   int start_y = top_to_bottom ? box.
bottom() : box.
top();
   378     tprintf(
"Column edges for blob at (%d,%d)->(%d,%d) are [%d, %d]\n",
   380             left_column_edge, right_column_edge);
   397   int xmin = 
MIN(x_start, x2) - skew_tolerance;
   398   int xmax = 
MAX(x_start, x2) + skew_tolerance;
   410     tprintf(
"Starting %s %s search at %d-%d,%d, search_size=%d, gutter=%d\n",
   422     if (neighbour == bbox)
   425     int n_y = (nbox.
top() + nbox.
bottom()) / 2;
   426     if ((!top_to_bottom && n_y > start_y + p.
max_v_gap) ||
   427         (top_to_bottom && n_y < start_y - p.
max_v_gap)) {
   429         tprintf(
"Neighbour too far at (%d,%d)->(%d,%d)\n",
   438     if ((n_y < start_y) != top_to_bottom || nbox.
y_overlap(box))
   442     if (backup_result != NULL && p.
ragged && result == NULL &&
   444       return backup_result;  
   449     if (x_at_n_y < neighbour->left_crossing_rule() ||
   452     int n_left = nbox.
left();
   453     int n_right = nbox.
right();
   454     int n_x = p.
right_tab ? n_right : n_left;
   456       tprintf(
"neighbour at (%d,%d)->(%d,%d), n_x=%d, n_y=%d, xatn=%d\n",
   466       *end_y = top_to_bottom ? nbox.
top() : nbox.
bottom();
   478       *end_y = top_to_bottom ? nbox.
top() : nbox.
bottom();
   491         tprintf(
"aligned, seeking%d, l=%d, r=%d\n",
   497         if (result == NULL) {
   505           int y_diff = (old_box.
top() + old_box.
bottom()) / 2 - start_y;
   506           int old_dist = x_diff * x_diff + y_diff * y_diff;
   507           x_diff = n_x - x_at_n_y;
   508           y_diff = n_y - start_y;
   509           int new_dist = x_diff * x_diff + y_diff * y_diff;
   510           if (new_dist < old_dist)
   513       } 
else if (backup_result == NULL) {
   516         backup_result = neighbour;
   523           backup_result = neighbour;
   528   return result != NULL ? result : backup_result;
 
void Line(int x1, int y1, int x2, int y2)
int textord_testregion_right
int textord_testregion_bottom
bool y_overlap(const TBOX &box) const
bool textord_debug_printable
void set_right_tab_type(TabType new_type)
int textord_testregion_left
void set_x(inT16 xin)
rewrite function 
int right_crossing_rule() const
AlignedBlobParams(int vertical_x, int vertical_y, int height, int v_gap_multiple, int min_gutter_width, int resolution, TabAlignment alignment0)
ScrollView * MakeWindow(int x, int y, const char *window_name)
inT16 x() const
access function 
void set_intersects_other_lines(bool value)
const int kVLineSearchSize
const int kVLineAlignment
#define BOOL_VAR(name, val, comment)
void set_vertical(int vertical_x, int vertical_y)
int textord_testregion_top
TabType left_tab_type() const
const double kAlignedFraction
void StartVerticalSearch(int xmin, int xmax, int y)
int y_gap(const TBOX &box) const
int textord_debug_tabfind
bool leader_on_left() const
TabType right_tab_type() const
inT16 y() const
access_function 
#define INT_VAR(name, val, comment)
bool leader_on_right() const
static bool WithinTestRegion(int detail_level, int x, int y)
const int kVLineMinLength
BBC * NextVerticalSearch(bool top_to_bottom)
static TabVector * FitVector(TabAlignment alignment, ICOORD vertical, int extended_start_y, int extended_end_y, BLOBNBOX_CLIST *good_points, int *vertical_x, int *vertical_y)
AlignedBlob(int gridsize, const ICOORD &bleft, const ICOORD &tright)
const double kAlignedGapFraction
ScrollView * DisplayTabs(const char *window_name, ScrollView *tab_win)
const int kMinAlignedTabs
const double kMinTabGradient
void Print(const char *prefix)
const double kRaggedGapFraction
const double kRaggedFraction
void set_left_tab_type(TabType new_type)
const TBOX & bounding_box() const
void set_y(inT16 yin)
rewrite function 
TabVector * FindVerticalAlignment(AlignedBlobParams align_params, BLOBNBOX *bbox, int *vertical_x, int *vertical_y)