24 #include "config_auto.h"
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()];
int CountFilledCellsInRow(int row)
GenericVectorEqEq< int > cell_x_
int CountFilledCellsInColumn(int column)
const double kGoodRowNumberOfColumnsSmall[]
bool HasSignificantLines(const TBOX &guess)
double CalculateCellFilledPercentage(int row, int column)
bool IsHorizontalType() const
const int kGoodRowNumberOfColumnsSmallSize
int NextHorizontalSplit(int left, int right, int y, bool top_to_bottom)
BBC * NextVerticalSearch(bool top_to_bottom)
ColPartitionGrid * text_grid_
const int kLinedTableMinVerticalLines
const TBOX & bounding_box() const
bool FindWhitespacedStructure()
const double kMarginFactor
bool DoesPartitionFit(const ColPartition &part) const
int FindVerticalMargin(ColPartitionGrid *grid, int start_x, bool decrease) const
static void FindCellSplitLocations(const GenericVector< int > &min_list, const GenericVector< int > &max_list, int max_merged, GenericVector< int > *locations)
void add(inT32 value, inT32 count)
void set_bounding_box(const TBOX &box)
GenericVectorEqEq< int > cell_y_
bool FindLinesBoundingBox(TBOX *bounding_box)
BBC * NextSideSearch(bool right_to_left)
ColPartitionGrid * line_grid_
bool RecognizeWhitespacedTable(const TBOX &guess_box, StructuredTable *table)
void set_max_text_height(int height)
int CountVerticalIntersections(int x)
const double kVerticalSpacing
const TBOX & bounding_box() const
void SetUniqueMode(bool mode)
bool FindLinedStructure()
int FindHorizontalMargin(ColPartitionGrid *grid, int start_y, bool decrease) const
const double kGoodRowNumberOfColumnsLarge
void set_line_grid(ColPartitionGrid *lines)
const int kCellSplitColumnThreshold
bool IsHorizontalLine() const
bool VerifyLinedTableCells()
bool RecognizeLinedTable(const TBOX &guess_box, StructuredTable *table)
ColPartitionGrid * line_grid_
void set_line_grid(ColPartitionGrid *lines)
void set_min_height(int height)
void set_min_width(int width)
bool FindLinesBoundingBoxIteration(TBOX *bounding_box)
void StartSideSearch(int x, int ymin, int ymax)
void set_text_grid(ColPartitionGrid *text)
void set_text_grid(ColPartitionGrid *text)
void StartRectSearch(const TBOX &rect)
void UpdateMargins(ColPartitionGrid *grid)
int column_width(int column) const
TBOX intersection(const TBOX &box) const
static bool IsWeakTableRow(StructuredTable *table, int row)
void set_max_text_height(int height)
const double kRequiredColumns
int row_height(int row) const
void FindWhitespacedRows()
StructuredTable * RecognizeTable(const TBOX &guess_box)
int CountHorizontalIntersections(int y)
void Rectangle(int x1, int y1, int x2, int y2)
const double kHorizontalSpacing
bool VerifyRowFilled(int row)
const int kCellSplitRowThreshold
const int kLinedTableMinHorizontalLines
const double kMinFilledArea
bool IsVerticalLine() const
void Line(int x1, int y1, int x2, int y2)
void Display(ScrollView *window, ScrollView::Color color)
int CountPartitions(const TBOX &box)
bool VerifyWhitespacedTable()
ColPartitionGrid * text_grid_
void FindWhitespacedColumns()
void StartVerticalSearch(int xmin, int xmax, int y)