This function is called if strong textual clues were not available, but the caller hopes that the paragraph breaks will be super obvious just by the outline of the text. The particularly difficult case is figuring out what's going on if you don't have enough short paragraph end lines to tell us what's going on. For instance, let's say you have the following outline: (A1) xxxxxxxxxxxxxxxxxxxxxx
| 1075 | // it's worth guessing that (A1b) is the correct interpretation if there are |
| 1076 | // far more "full" lines than "short" lines. |
| 1077 | void GeometricClassify(int debug_level, |
| 1078 | GenericVector<RowScratchRegisters> *rows, |
| 1079 | int row_start, int row_end, |
| 1080 | ParagraphTheory *theory) { |
| 1081 | if (!AcceptableRowArgs(debug_level, 4, __func__, rows, row_start, row_end)) |
| 1082 | return; |
| 1083 | if (debug_level > 1) { |
| 1084 | tprintf("###############################################\n"); |
| 1085 | tprintf("##### GeometricClassify( rows[%d:%d) ) ####\n", |
| 1086 | row_start, row_end); |
| 1087 | tprintf("###############################################\n"); |
| 1088 | } |
| 1089 | RecomputeMarginsAndClearHypotheses(rows, row_start, row_end, 10); |
| 1090 | |
| 1091 | GeometricClassifierState s(debug_level, rows, row_start, row_end); |
| 1092 | if (s.left_tabs.size() > 2 && s.right_tabs.size() > 2) { |
| 1093 | s.Fail(2, "Too much variety for simple outline classification."); |
| 1094 | return; |
| 1095 | } |
| 1096 | if (s.left_tabs.size() <= 1 && s.right_tabs.size() <= 1) { |
| 1097 | s.Fail(1, "Not enough variety for simple outline classification."); |
| 1098 | return; |
| 1099 | } |
| 1100 | if (s.left_tabs.size() + s.right_tabs.size() == 3) { |
| 1101 | GeometricClassifyThreeTabStopTextBlock(debug_level, s, theory); |
| 1102 | return; |
| 1103 | } |
| 1104 | |
| 1105 | // At this point, we know that one side has at least two tab stops, and the |
| 1106 | // other side has one or two tab stops. |
| 1107 | // Left to determine: |
| 1108 | // (1) Which is the body indent and which is the first line indent? |
| 1109 | // (2) Is the text fully justified? |
| 1110 | |
| 1111 | // If one side happens to have three or more tab stops, assume that side |
| 1112 | // is opposite of the aligned side. |
| 1113 | if (s.right_tabs.size() > 2) { |
| 1114 | s.AssumeLeftJustification(); |
| 1115 | } else if (s.left_tabs.size() > 2) { |
| 1116 | s.AssumeRightJustification(); |
| 1117 | } else if (s.ltr) { // guess based on script direction |
| 1118 | s.AssumeLeftJustification(); |
| 1119 | } else { |
| 1120 | s.AssumeRightJustification(); |
| 1121 | } |
| 1122 | |
| 1123 | if (s.AlignTabs().size() == 2) { |
| 1124 | // For each tab stop on the aligned side, how many of them appear |
| 1125 | // to be paragraph start lines? [first lines] |
| 1126 | int firsts[2] = {0, 0}; |
| 1127 | // Count the first line as a likely paragraph start line. |
| 1128 | firsts[s.AlignsideTabIndex(s.row_start)]++; |
| 1129 | // For each line, if the first word would have fit on the previous |
| 1130 | // line count it as a likely paragraph start line. |
| 1131 | bool jam_packed = true; |
| 1132 | for (int i = s.row_start + 1; i < s.row_end; i++) { |
| 1133 | if (s.FirstWordWouldHaveFit(i - 1, i)) { |
| 1134 | firsts[s.AlignsideTabIndex(i)]++; |
no test coverage detected