75 median_cell_height_(0),
76 median_cell_width_(0),
234 int column_start,
int column_end) {
236 ASSERT_HOST(0 <= column_start && column_start <= column_end &&
240 for (
int row = row_start; row <= row_end; ++row) {
243 for (
int col = column_start; col <= column_end; ++col) {
259 if (area_filled >= kMinFilledArea)
275 gsearch.SetUniqueMode(
true);
276 gsearch.StartRectSearch(kCellBox);
277 double area_covered = 0;
279 while ((text = gsearch.NextRectSearch()) != NULL) {
283 const inT32 current_area = kCellBox.
area();
284 if (current_area == 0) {
287 return MIN(1.0, area_covered / current_area);
291 #ifndef GRAPHICS_DISABLED 373 kHorizontalSpacing / 2.0 + 0.5);
378 if (left_sides.
length() == 0 || right_sides.
length() == 0)
431 kVerticalSpacing / 2.0 + 0.5);
444 if (bottom_sides.
length() == 0 || top_sides.
length() == 0)
486 bool decrease)
const {
503 bool decrease)
const {
520 const int kMaxCellHeight = 1000;
521 const int kMaxCellWidth = 1000;
522 STATS height_stats(0, kMaxCellHeight + 1);
523 STATS width_stats(0, kMaxCellWidth + 1);
599 if (min_list.
length() == 0)
608 int stacked_partitions = 0;
613 while (min_index < min_list.
length()) {
615 if (min_list[min_index] < max_list[max_index]) {
616 ++stacked_partitions;
618 stacked_partitions > max_merged) {
619 int mid = (last_cross_position + min_list[min_index]) / 2;
626 --stacked_partitions;
628 stacked_partitions <= max_merged) {
629 last_cross_position = max_list[max_index];
644 vertical_box.
set_left(x - kGridSize);
669 horizontal_box.
set_top(y + kGridSize);
763 TBOX line_bound = guess_box;
781 int vertical_count = 0;
782 int horizontal_count = 0;
791 return vertical_count >= kLinedTableMinVerticalLines &&
826 int old_area = bounding_box->
area();
831 changed = (bounding_box->
area() > old_area);
843 bool first_line =
true;
877 TBOX best_box = guess_box;
880 TBOX adjusted = guess_box;
885 const int kMidGuessY = (guess_box.
bottom() + guess_box.
top()) / 2;
890 bool found_good_border =
false;
905 int previous_below = 0;
906 const int kMaxChances = 10;
907 int chances = kMaxChances;
908 while (bottom != last_bottom) {
928 chances = kMaxChances;
930 if ((table->
space_below() * kMarginFactor >= best_below &&
937 found_good_border =
true;
948 last_bottom = bottom;
952 if (!found_good_border)
956 found_good_border =
false;
960 int previous_above = 0;
961 chances = kMaxChances;
964 while (last_top != top) {
975 chances = kMaxChances;
977 if ((table->
space_above() * kMarginFactor >= best_above &&
980 table->
row_height(last_row) < max_row_height)) {
984 found_good_border =
true;
1000 if (!found_good_border)
1020 bool top_to_bottom) {
1033 if (top_to_bottom && (last_y >= y || last_y <= text_box.
top())) {
1034 last_y =
MIN(last_y, text_box.
bottom());
1037 if (!top_to_bottom && (last_y <= y || last_y >= text_box.
bottom())) {
1038 last_y =
MAX(last_y, text_box.
top());
1057 double threshold = 0.0;
1061 threshold = kGoodRowNumberOfColumnsSmall[table->
column_count()];
const double kMarginFactor
int column_width(int column) const
void set_max_text_height(int height)
void StartVerticalSearch(int xmin, int xmax, int y)
BBC * NextSideSearch(bool right_to_left)
bool VerifyWhitespacedTable()
const int kGoodRowNumberOfColumnsSmallSize
bool HasSignificantLines(const TBOX &guess)
const int kLinedTableMinVerticalLines
void set_min_height(int height)
const TBOX & bounding_box() const
ColPartitionGrid * line_grid_
void FindWhitespacedColumns()
BBC * NextVerticalSearch(bool top_to_bottom)
bool DoesPartitionFit(const ColPartition &part) const
bool IsHorizontalLine() const
int FindHorizontalMargin(ColPartitionGrid *grid, int start_y, bool decrease) const
bool VerifyLinedTableCells()
ColPartitionGrid * line_grid_
bool FindLinesBoundingBox(TBOX *bounding_box)
void SetUniqueMode(bool mode)
void set_line_grid(ColPartitionGrid *lines)
void set_line_grid(ColPartitionGrid *lines)
int CountFilledCellsInRow(int row)
static void FindCellSplitLocations(const GenericVector< int > &min_list, const GenericVector< int > &max_list, int max_merged, GenericVector< int > *locations)
int CountVerticalIntersections(int x)
void UpdateMargins(ColPartitionGrid *grid)
const double kRequiredColumns
bool IsHorizontalType() const
void Display(ScrollView *window, ScrollView::Color color)
int row_height(int row) const
TBOX intersection(const TBOX &box) const
void Rectangle(int x1, int y1, int x2, int y2)
int CountHorizontalIntersections(int y)
const double kGoodRowNumberOfColumnsLarge
bool RecognizeLinedTable(const TBOX &guess_box, StructuredTable *table)
void set_bounding_box(const TBOX &box)
bool IsVerticalLine() const
const int kCellSplitRowThreshold
StructuredTable * RecognizeTable(const TBOX &guess_box)
const int kLinedTableMinHorizontalLines
bool FindLinesBoundingBoxIteration(TBOX *bounding_box)
void set_text_grid(ColPartitionGrid *text)
void Line(int x1, int y1, int x2, int y2)
const double kHorizontalSpacing
const double kVerticalSpacing
void StartSideSearch(int x, int ymin, int ymax)
void add(inT32 value, inT32 count)
bool FindLinedStructure()
int NextHorizontalSplit(int left, int right, int y, bool top_to_bottom)
double CalculateCellFilledPercentage(int row, int column)
void FindWhitespacedRows()
int CountPartitions(const TBOX &box)
const double kGoodRowNumberOfColumnsSmall[]
const int kCellSplitColumnThreshold
ColPartitionGrid * text_grid_
bool FindWhitespacedStructure()
const double kMinFilledArea
ColPartitionGrid * text_grid_
void set_max_text_height(int height)
GenericVectorEqEq< int > cell_x_
GenericVectorEqEq< int > cell_y_
int CountFilledCellsInColumn(int column)
const TBOX & bounding_box() const
bool VerifyRowFilled(int row)
bool RecognizeWhitespacedTable(const TBOX &guess_box, StructuredTable *table)
static bool IsWeakTableRow(StructuredTable *table, int row)
void set_text_grid(ColPartitionGrid *text)
int FindVerticalMargin(ColPartitionGrid *grid, int start_x, bool decrease) const
void StartRectSearch(const TBOX &rect)
void set_min_width(int width)