875 {
876 TBOX best_box = guess_box;
877 int best_below = 0;
878 int best_above = 0;
879 TBOX adjusted = guess_box;
880
881
882
883
884 const int kMidGuessY = (guess_box.
bottom() + guess_box.
top()) / 2;
885
886
887 int best_cols = 0;
888
889 bool found_good_border = false;
890
891
892
893
894 int last_bottom = INT32_MAX;
900
901
902
903
904 int previous_below = 0;
905 const int kMaxChances = 10;
906 int chances = kMaxChances;
907 while (bottom != last_bottom) {
909
911
912
913 table->set_bounding_box(adjusted);
914 if (table->FindWhitespacedStructure() &&
917
918 --chances;
919 } else {
920
921
922
923
924
925
926
927 chances = kMaxChances;
928 double max_row_height =
kMaxRowSize * table->median_cell_height();
930 table->space_below() >= previous_below) ||
931 (table->CountFilledCellsInRow(0) > 1 &&
932 table->row_height(0) < max_row_height)) {
934 best_below = table->space_below();
935 best_cols = std::max(table->column_count(), best_cols);
936 found_good_border = true;
937 }
938 }
939 previous_below = table->space_below();
940 } else {
941 --chances;
942 }
943 }
944 if (chances <= 0)
945 break;
946
947 last_bottom = bottom;
949 last_bottom, true);
950 }
951 if (!found_good_border)
952 return false;
953
954
955 found_good_border = false;
956 int last_top = INT32_MIN;
959 int previous_above = 0;
960 chances = kMaxChances;
961
963 while (last_top != top) {
966 table->set_bounding_box(adjusted);
967 if (table->FindWhitespacedStructure() &&
969 int last_row = table->row_count() - 1;
971
972 --chances;
973 } else {
974 chances = kMaxChances;
975 double max_row_height =
kMaxRowSize * table->median_cell_height();
977 table->space_above() >= previous_above) ||
978 (table->CountFilledCellsInRow(last_row) > 1 &&
979 table->row_height(last_row) < max_row_height)) {
981 best_above = table->space_above();
982 best_cols = std::max(table->column_count(), best_cols);
983 found_good_border = true;
984 }
985 }
986 previous_above = table->space_above();
987 } else {
988 --chances;
989 }
990 }
991 if (chances <= 0)
992 break;
993
994 last_top = top;
996 last_top, false);
997 }
998
999 if (!found_good_border)
1000 return false;
1001
1002
1003
1005 return false;
1006
1007
1008 table->set_bounding_box(best_box);
1009 return table->FindWhitespacedStructure();
1010}
const double kRequiredColumns
const double kMarginFactor
static bool IsWeakTableRow(StructuredTable *table, int row)
int NextHorizontalSplit(int left, int right, int y, bool top_to_bottom)