38 ColPartition_IT it(&parts_);
39 it.add_list_after(partitions);
44 ColPartition_IT it(&parts_);
45 it.add_after_then_move(part);
54 int num_good_cols = 0;
56 ColPartition_IT it(const_cast<ColPartition_LIST*>(&parts_));
57 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
58 if (it.data()->good_width()) ++num_good_cols;
65 ColPartition_IT it(&parts_);
67 for (
int i = 0; i < index && !it.cycled_list(); ++i, it.forward());
75 ColPartition_IT it(&parts_);
76 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
86 ColPartition_IT it(&parts_);
96 int set_size = src_sets->
size();
99 for (
int i = 0; i < set_size; ++i) {
101 if (column_set == NULL)
105 ColPartition_IT part_it(&parts_);
108 part_it.mark_cycle_pt();
109 ColPartition_IT col_it(&column_set->parts_);
110 for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) {
114 int col_left = col_part->
left_key();
118 while (!part_it.at_last() && part->
right_key() < col_left) {
121 part = part_it.data();
125 if (part_right < col_left || col_right < part_left) {
131 bool part_width_ok = cb->
Run(part->
KeyWidth(part_left, part_right));
132 if (col_left < part_left && col_left > prev_right) {
136 bool tab_width_ok = cb->
Run(part->
KeyWidth(col_left, part_right));
137 bool box_width_ok = cb->
Run(part->
KeyWidth(col_box_left, part_right));
138 if (tab_width_ok || (!part_width_ok )) {
143 }
else if (col_box_left < part_left &&
144 (box_width_ok || !part_width_ok)) {
152 if (col_right > part_right &&
153 (part_it.at_last() ||
154 part_it.data_relative(1)->left_key() > col_right)) {
157 bool tab_width_ok = cb->
Run(part->
KeyWidth(part_left, col_right));
158 bool box_width_ok = cb->
Run(part->
KeyWidth(part_left, col_box_right));
159 if (tab_width_ok || (!part_width_ok )) {
164 }
else if (col_box_right > part_right &&
165 (box_width_ok || !part_width_ok)) {
184 tprintf(
"Considering new column candidate:\n");
189 tprintf(
"Not a legal column candidate:\n");
195 for (
int i = 0; i < column_sets->
size(); ++i) {
199 bool better = good_coverage_ > columns->good_coverage_;
200 if (good_coverage_ == columns->good_coverage_) {
201 better = good_column_count_ > columns->good_column_count_;
202 if (good_column_count_ == columns->good_column_count_) {
203 better = bad_coverage_ > columns->bad_coverage_;
210 column_sets->
insert(
this, i);
230 tprintf(
"CompatibleColumns testing compatibility\n");
234 if (other->parts_.empty()) {
236 tprintf(
"CompatibleColumns true due to empty other\n");
239 ColPartition_IT it(&other->parts_);
240 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
244 tprintf(
"CompatibleColumns ignoring image partition\n");
249 int y = part->
MidY();
254 if (right_col == NULL || left_col == NULL) {
256 tprintf(
"CompatibleColumns false due to partition edge outside\n");
261 if (right_col != left_col && cb->
Run(right - left)) {
263 tprintf(
"CompatibleColumns false due to good width in multiple cols\n");
269 ColPartition_IT it2= it;
270 while (!it2.at_last()) {
276 if (next_left == right) {
281 if (right_col == next_left_col) {
291 tprintf(
"CompatibleColumns false due to 2 parts of good width\n");
292 tprintf(
"part1 %d-%d, part2 %d-%d\n",
293 left, right, next_left, next_right);
303 tprintf(
"CompatibleColumns true!\n");
312 ColPartition_IT it(&part_set->parts_);
313 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
318 int y = part->
MidY();
319 BLOBNBOX_C_IT box_it(part->
boxes());
320 for (box_it.mark_cycle_pt(); !box_it.cycled_list(); box_it.forward()) {
321 const TBOX& box = it.data()->bounding_box();
327 total_width += box.
width();
336 ColPartition_IT it(&parts_);
339 bool any_text_parts =
false;
340 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
345 any_text_parts =
true;
354 return any_text_parts;
359 ColPartition_LIST copy_parts;
360 ColPartition_IT src_it(&parts_);
361 ColPartition_IT dest_it(©_parts);
362 for (src_it.mark_cycle_pt(); !src_it.cycled_list(); src_it.forward()) {
375 ColSegment_LIST *segments) {
376 ColPartition_IT it(&parts_);
377 ColSegment_IT col_it(segments);
378 col_it.move_to_last();
379 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
384 col_seg->InsertBox(
TBOX(bot_left, top_right));
385 col_it.add_after_then_move(col_seg);
392 #ifndef GRAPHICS_DISABLED 393 ColPartition_IT it(&parts_);
394 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
399 #endif // GRAPHICS_DISABLED 416 int* first_spanned_col) {
419 *first_spanned_col = -1;
420 int margin_columns = 0;
421 ColPartition_IT it(&parts_);
423 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward(), col_index += 2) {
431 *first_col = col_index;
435 *last_col = col_index;
438 if (left_margin <= part->LeftAtY(y)) {
440 *first_spanned_col = col_index;
445 if (*first_col < 0) {
447 *first_col = col_index - 1;
449 if (right_margin >= part->
RightAtY(y)) {
451 if (margin_columns == 0)
452 *first_spanned_col = col_index;
455 *last_col = col_index;
457 }
else if (left < part->LeftAtY(y) && right > part->
RightAtY(y)) {
460 if (*first_col < 0) {
462 *first_col = col_index - 1;
464 if (margin_columns == 0)
465 *first_spanned_col = col_index;
466 *last_col = col_index;
467 }
else if (right < part->LeftAtY(y)) {
469 *last_col = col_index - 1;
470 if (*first_col < 0) {
472 *first_col = col_index - 1;
478 *first_col = col_index - 1;
480 *last_col = col_index - 1;
483 if (*first_col == *last_col && right - left <
kMinColumnWidth * resolution) {
487 }
else if (margin_columns <= 1) {
489 if (margin_columns == 1 && parts_.singleton()) {
507 ColPartition_LIST* used_parts,
508 WorkingPartSet_LIST* working_set_list) {
511 WorkingPartSet_LIST work_src;
512 WorkingPartSet_IT src_it(&work_src);
513 src_it.add_list_after(working_set_list);
514 src_it.move_to_first();
515 WorkingPartSet_IT dest_it(working_set_list);
518 BLOCK_LIST completed_blocks;
519 TO_BLOCK_LIST to_blocks;
522 ColPartition_IT col_it(&parts_);
523 for (col_it.mark_cycle_pt(); !col_it.cycled_list(); col_it.forward()) {
526 while (!src_it.empty() &&
527 ((working_set = src_it.data())->column() == NULL ||
531 used_parts, &completed_blocks,
538 dest_it.add_after_then_move(working_set);
539 if (first_new_set == NULL)
540 first_new_set = working_set;
543 working_set = src_it.empty() ? NULL : src_it.data();
544 if (working_set != NULL &&
547 dest_it.add_after_then_move(src_it.extract());
550 first_new_set = NULL;
554 dest_it.add_after_then_move(working_set);
558 while (!src_it.empty()) {
559 working_set = src_it.extract();
561 used_parts, &completed_blocks,
568 dest_it.add_after_then_move(working_set);
569 if (first_new_set == NULL)
570 first_new_set = working_set;
580 ColPartition_IT it(&parts_);
581 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
596 ColPartition_IT it(&parts_);
597 tprintf(
"Partition set of %d parts, %d good, coverage=%d+%d" 598 " (%d,%d)->(%d,%d)\n",
599 it.length(), good_column_count_, good_coverage_, bad_coverage_,
601 bounding_box_.
right(), bounding_box_.
top());
602 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
611 void ColPartitionSet::AddPartition(
ColPartition* new_part,
612 ColPartition_IT* it) {
613 AddPartitionCoverageAndBox(*new_part);
615 if (it->data()->left_key() >= new_right)
616 it->add_before_stay_put(new_part);
618 it->add_after_stay_put(new_part);
638 void ColPartitionSet::ComputeCoverage() {
640 ColPartition_IT it(&parts_);
641 good_column_count_ = 0;
644 bounding_box_ =
TBOX();
645 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
646 ColPartition* part = it.data();
647 AddPartitionCoverageAndBox(*part);
653 void ColPartitionSet::AddPartitionCoverageAndBox(
const ColPartition& part) {
654 bounding_box_ += part.bounding_box();
655 int coverage = part.ColumnWidth();
656 if (part.good_width()) {
657 good_coverage_ += coverage;
658 good_column_count_ += 2;
662 if (part.good_column())
663 ++good_column_count_;
664 bad_coverage_ += coverage;
static bool IsTextType(BlobRegionType type)
void CopyRightTab(const ColPartition &src, bool take_box)
bool CompatibleColumns(bool debug, ColPartitionSet *other, WidthCallback *cb)
bool LegalColumnCandidate()
static bool WithinTestRegion(int detail_level, int x, int y)
void insert(T t, int index)
int UnmatchedWidth(ColPartitionSet *part_set)
ColPartition * column() const
void Line(int x1, int y1, int x2, int y2)
ColumnSpanningType SpanningType(int resolution, int left, int right, int height, int y, int left_margin, int right_margin, int *first_col, int *last_col, int *first_spanned_col)
void ImproveColumnCandidate(WidthCallback *cb, PartSetVector *src_sets)
int GoodColumnCount() const
void SetColumnGoodness(WidthCallback *cb)
bool ColumnContains(int x, int y) const
void AccumulateColumnWidthsAndGaps(int *total_width, int *width_samples, int *total_gap, int *gap_samples)
void GetColumnBoxes(int y_bottom, int y_top, ColSegment_LIST *segments)
void AddToColumnSetsIfUnique(PartSetVector *column_sets, WidthCallback *cb)
void set_column(ColPartition *col)
void InsertCompletedBlocks(BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks)
void DisplayColumnEdges(int y_bottom, int y_top, ScrollView *win)
int RightAtY(int y) const
void CopyLeftTab(const ColPartition &src, bool take_box)
const double kMinColumnWidth
ColPartition * ShallowCopy() const
ColPartition * GetColumnByIndex(int index)
void ExtractCompletedBlocks(const ICOORD &bleft, const ICOORD &tright, int resolution, ColPartition_LIST *used_parts, BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks)
void ChangeWorkColumns(const ICOORD &bleft, const ICOORD &tright, int resolution, ColPartition_LIST *used_parts, WorkingPartSet_LIST *working_set)
bool MatchingColumns(const ColPartition &other) const
ColPartitionSet * Copy(bool good_only)
ColPartition * ColumnContaining(int x, int y)
int KeyWidth(int left_key, int right_key) const
const TBOX & bounding_box() const
BlobRegionType blob_type() const