// Return a copy of this. If good_only will only copy the Good ColPartitions. ColPartitionSet* ColPartitionSet::Copy(bool good_only) { ColPartition_LIST copy_parts; ColPartition_IT src_it(&parts_); ColPartition_IT dest_it(©_parts); for (src_it.mark_cycle_pt(); !src_it.cycled_list(); src_it.forward()) { ColPartition* part = src_it.data(); if (BLOBNBOX::IsTextType(part->blob_type()) && (!good_only || part->good_width() || part->good_column())) dest_it.add_after_then_move(part->ShallowCopy()); } if (dest_it.empty()) return NULL; return new ColPartitionSet(©_parts); }
// Adds the coverage, column count and box for a single partition, // without adding it to the list. (Helper factored from ComputeCoverage.) void ColPartitionSet::AddPartitionCoverageAndBox(const ColPartition& part) { bounding_box_ += part.bounding_box(); int coverage = part.ColumnWidth(); if (part.good_width()) { good_coverage_ += coverage; good_column_count_ += 2; } else { if (part.blob_type() < BRT_UNKNOWN) coverage /= 2; if (part.good_column()) ++good_column_count_; bad_coverage_ += coverage; } }
// Return true if the partitions in other are all compatible with the columns // in this. bool ColPartitionSet::CompatibleColumns(bool debug, ColPartitionSet* other, WidthCallback* cb) { if (debug) { tprintf("CompatibleColumns testing compatibility\n"); Print(); other->Print(); } if (other->parts_.empty()) { if (debug) tprintf("CompatibleColumns true due to empty other\n"); return true; } ColPartition_IT it(&other->parts_); for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) { ColPartition* part = it.data(); if (part->blob_type() < BRT_UNKNOWN) { if (debug) { tprintf("CompatibleColumns ignoring image partition\n"); part->Print(); } continue; // Image partitions are irrelevant to column compatibility. } int y = part->MidY(); int left = part->bounding_box().left(); int right = part->bounding_box().right(); ColPartition* left_col = ColumnContaining(left, y); ColPartition* right_col = ColumnContaining(right, y); if (right_col == NULL || left_col == NULL) { if (debug) { tprintf("CompatibleColumns false due to partition edge outside\n"); part->Print(); } return false; // A partition edge lies outside of all columns } if (right_col != left_col && cb->Run(right - left)) { if (debug) { tprintf("CompatibleColumns false due to good width in multiple cols\n"); part->Print(); } return false; // Partition with a good width must be in a single column. } ColPartition_IT it2= it; while (!it2.at_last()) { it2.forward(); ColPartition* next_part = it2.data(); if (!BLOBNBOX::IsTextType(next_part->blob_type())) continue; // Non-text partitions are irrelevant. int next_left = next_part->bounding_box().left(); if (next_left == right) { break; // They share the same edge, so one must be a pull-out. } // Search to see if right and next_left fall within a single column. ColPartition* next_left_col = ColumnContaining(next_left, y); if (right_col == next_left_col) { // There is a column break in this column. // This can be due to a figure caption within a column, a pull-out // block, or a simple broken textline that remains to be merged: // all allowed, or a change in column layout: not allowed. // If both partitions are of good width, then it is likely // a change in column layout, otherwise probably an allowed situation. if (part->good_width() && next_part->good_width()) { if (debug) { int next_right = next_part->bounding_box().right(); tprintf("CompatibleColumns false due to 2 parts of good width\n"); tprintf("part1 %d-%d, part2 %d-%d\n", left, right, next_left, next_right); right_col->Print(); } return false; } } break; } } if (debug) tprintf("CompatibleColumns true!\n"); return true; }