908 {
909 TBOX best_box = guess_box;
910 int best_below = 0;
911 int best_above = 0;
912 TBOX adjusted = guess_box;
913
914
915
916
917 const int kMidGuessY = (guess_box.bottom() + guess_box.top()) / 2;
918
919
920 unsigned best_cols = 0;
921
922 bool found_good_border = false;
923
924
925
926
927 int last_bottom = INT32_MAX;
928 int bottom =
930 int top =
932 adjusted.set_top(top);
933
934
935
936
937 int previous_below = 0;
938 const int kMaxChances = 10;
939 int chances = kMaxChances;
940 while (bottom != last_bottom) {
941 adjusted.set_bottom(bottom);
942
944
945
946 table->set_bounding_box(adjusted);
947 if (table->FindWhitespacedStructure() &&
949 if (false && IsWeakTableRow(table, 0)) {
950
951 --chances;
952 } else {
953
954
955
956
957
958
959
960 chances = kMaxChances;
961 double max_row_height =
kMaxRowSize * table->median_cell_height();
963 table->space_below() >= previous_below) ||
964 (table->CountFilledCellsInRow(0) > 1 && table->row_height(0) < max_row_height)) {
965 best_box.set_bottom(bottom);
966 best_below = table->space_below();
967 best_cols = std::max(table->column_count(), best_cols);
968 found_good_border = true;
969 }
970 }
971 previous_below = table->space_below();
972 } else {
973 --chances;
974 }
975 }
976 if (chances <= 0) {
977 break;
978 }
979
980 last_bottom = bottom;
982 }
983 if (!found_good_border) {
984 return false;
985 }
986
987
988 found_good_border = false;
989 int last_top = INT32_MIN;
990 top =
992 int previous_above = 0;
993 chances = kMaxChances;
994
995 adjusted.set_bottom(best_box.bottom());
996 while (last_top != top) {
997 adjusted.set_top(top);
999 table->set_bounding_box(adjusted);
1000 if (table->FindWhitespacedStructure() &&
1002 int last_row = table->row_count() - 1;
1003 if (false && IsWeakTableRow(table, last_row)) {
1004
1005 --chances;
1006 } else {
1007 chances = kMaxChances;
1008 double max_row_height =
kMaxRowSize * table->median_cell_height();
1010 table->space_above() >= previous_above) ||
1011 (table->CountFilledCellsInRow(last_row) > 1 &&
1012 table->row_height(last_row) < max_row_height)) {
1013 best_box.set_top(top);
1014 best_above = table->space_above();
1015 best_cols = std::max(table->column_count(), best_cols);
1016 found_good_border = true;
1017 }
1018 }
1019 previous_above = table->space_above();
1020 } else {
1021 --chances;
1022 }
1023 }
1024 if (chances <= 0) {
1025 break;
1026 }
1027
1028 last_top = top;
1030 }
1031
1032 if (!found_good_border) {
1033 return false;
1034 }
1035
1036
1037
1038 if (best_box.null_box()) {
1039 return false;
1040 }
1041
1042
1043 table->set_bounding_box(best_box);
1044 return table->FindWhitespacedStructure();
1045}
const double kRequiredColumns
const double kMarginFactor
int NextHorizontalSplit(int left, int right, int y, bool top_to_bottom)