This file is indexed.

/usr/include/tesseract/colpartition.h is in libtesseract-dev 3.02.01-6.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
///////////////////////////////////////////////////////////////////////
// File:        colpartition.h
// Description: Class to hold partitions of the page that correspond
//              roughly to text lines.
// Author:      Ray Smith
// Created:     Thu Aug 14 10:50:01 PDT 2008
//
// (C) Copyright 2008, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////

#ifndef TESSERACT_TEXTORD_COLPARTITION_H__
#define TESSERACT_TEXTORD_COLPARTITION_H__

#include "bbgrid.h"
#include "blobbox.h"       // For BlobRegionType.
#include "ndminx.h"
#include "ocrblock.h"
#include "rect.h"           // For TBOX.
#include "scrollview.h"
#include "tabfind.h"        // For WidthCallback.
#include "tabvector.h"      // For BLOBNBOX_CLIST.

namespace tesseract {

// Number of colors in the color1, color2 arrays.
const int kRGBRMSColors = 4;

class ColPartition;
class ColPartitionSet;
class ColPartitionGrid;
class WorkingPartSet;
class WorkingPartSet_LIST;

// An enum to indicate how a partition sits on the columns.
// The order of flowing/heading/pullout must be kept consistent with
// PolyBlockType.
enum ColumnSpanningType {
  CST_NOISE,        // Strictly between columns.
  CST_FLOWING,      // Strictly within a single column.
  CST_HEADING,      // Spans multiple columns.
  CST_PULLOUT,      // Touches multiple columns, but doesn't span them.
  CST_COUNT         // Number of entries.
};

ELIST2IZEH(ColPartition)
CLISTIZEH(ColPartition)

/**
 * ColPartition is a partition of a horizontal slice of the page.
 * It starts out as a collection of blobs at a particular y-coord in the grid,
 * but ends up (after merging and uniquing) as an approximate text line.
 * ColPartitions are also used to hold a partitioning of the page into
 * columns, each representing one column. Although a ColPartition applies
 * to a given y-coordinate range, eventually, a ColPartitionSet of ColPartitions
 * emerges, which represents the columns over a wide y-coordinate range.
 */
class ColPartition : public ELIST2_LINK {
 public:
  ColPartition() {
    // This empty constructor is here only so that the class can be ELISTIZED.
    // TODO(rays) change deep_copy in elst.h line 955 to take a callback copier
    // and eliminate CLASSNAME##_copier.
  }
  /**
   * @param blob_type is the blob_region_type_ of the blobs in this partition.
   * @param vertical is the direction of logical vertical on the possibly skewed image.
   */
  ColPartition(BlobRegionType blob_type, const ICOORD& vertical);
  /**
   * Constructs a fake ColPartition with no BLOBNBOXes to represent a
   * horizontal or vertical line, given a type and a bounding box.
   */
  static ColPartition* MakeLinePartition(BlobRegionType blob_type,
                                         const ICOORD& vertical,
                                         int left, int bottom,
                                         int right, int top);

  // Constructs and returns a fake ColPartition with a single fake BLOBNBOX,
  // all made from a single TBOX.
  // WARNING: Despite being on C_LISTs, the BLOBNBOX owns the C_BLOB and
  // the ColPartition owns the BLOBNBOX!!!
  // Call DeleteBoxes before deleting the ColPartition.
  static ColPartition* FakePartition(const TBOX& box,
                                     PolyBlockType block_type,
                                     BlobRegionType blob_type,
                                     BlobTextFlowType flow);

  // Constructs and returns a ColPartition with the given real BLOBNBOX,
  // and sets it up to be a "big" partition (single-blob partition bigger
  // than the surrounding text that may be a dropcap, two or more vertically
  // touching characters, or some graphic element.
  // If the given list is not NULL, the partition is also added to the list.
  static ColPartition* MakeBigPartition(BLOBNBOX* box,
                                        ColPartition_LIST* big_part_list);

  ~ColPartition();

  // Simple accessors.
  const TBOX& bounding_box() const {
    return bounding_box_;
  }
  int left_margin() const {
    return left_margin_;
  }
  void set_left_margin(int margin) {
    left_margin_ = margin;
  }
  int right_margin() const {
    return right_margin_;
  }
  void set_right_margin(int margin) {
    right_margin_ = margin;
  }
  int median_top() const {
    return median_top_;
  }
  int median_bottom() const {
    return median_bottom_;
  }
  int median_left() const {
    return median_left_;
  }
  int median_right() const {
    return median_right_;
  }
  int median_size() const {
    return median_size_;
  }
  void set_median_size(int size) {
    median_size_ = size;
  }
  int median_width() const {
    return median_width_;
  }
  void set_median_width(int width) {
    median_width_ = width;
  }
  BlobRegionType blob_type() const {
    return blob_type_;
  }
  void set_blob_type(BlobRegionType t) {
    blob_type_ = t;
  }
  BlobTextFlowType flow() const {
    return flow_;
  }
  void set_flow(BlobTextFlowType f) {
    flow_ = f;
  }
  int good_blob_score() const {
    return good_blob_score_;
  }
  bool good_width() const {
    return good_width_;
  }
  bool good_column() const {
    return good_column_;
  }
  bool left_key_tab() const {
    return left_key_tab_;
  }
  int left_key() const {
    return left_key_;
  }
  bool right_key_tab() const {
    return right_key_tab_;
  }
  int right_key() const {
    return right_key_;
  }
  PolyBlockType type() const {
    return type_;
  }
  void set_type(PolyBlockType t) {
    type_ = t;
  }
  BLOBNBOX_CLIST* boxes() {
    return &boxes_;
  }
  int boxes_count() const {
    return boxes_.length();
  }
  void set_vertical(const ICOORD& v) {
    vertical_ = v;
  }
  ColPartition_CLIST* upper_partners() {
    return &upper_partners_;
  }
  ColPartition_CLIST* lower_partners() {
    return &lower_partners_;
  }
  void set_working_set(WorkingPartSet* working_set) {
    working_set_ = working_set;
  }
  bool block_owned() const {
    return block_owned_;
  }
  void set_block_owned(bool owned) {
    block_owned_ = owned;
  }
  bool desperately_merged() const {
    return desperately_merged_;
  }
  ColPartitionSet* column_set() const {
    return column_set_;
  }
  void set_side_step(int step) {
    side_step_ = step;
  }
  int bottom_spacing() const {
    return bottom_spacing_;
  }
  void set_bottom_spacing(int spacing) {
    bottom_spacing_ = spacing;
  }
  int top_spacing() const {
    return top_spacing_;
  }
  void set_top_spacing(int spacing) {
    top_spacing_ = spacing;
  }

  void set_table_type() {
    if (type_ != PT_TABLE) {
      type_before_table_ = type_;
      type_ = PT_TABLE;
    }
  }
  void clear_table_type() {
    if (type_ == PT_TABLE)
      type_ = type_before_table_;
  }
  bool inside_table_column() {
    return inside_table_column_;
  }
  void set_inside_table_column(bool val) {
    inside_table_column_ = val;
  }
  ColPartition* nearest_neighbor_above() const {
    return nearest_neighbor_above_;
  }
  void set_nearest_neighbor_above(ColPartition* part) {
    nearest_neighbor_above_ = part;
  }
  ColPartition* nearest_neighbor_below() const {
    return nearest_neighbor_below_;
  }
  void set_nearest_neighbor_below(ColPartition* part) {
    nearest_neighbor_below_ = part;
  }
  int space_above() const {
    return space_above_;
  }
  void set_space_above(int space) {
    space_above_ = space;
  }
  int space_below() const {
    return space_below_;
  }
  void set_space_below(int space) {
    space_below_ = space;
  }
  int space_to_left() const {
    return space_to_left_;
  }
  void set_space_to_left(int space) {
    space_to_left_ = space;
  }
  int space_to_right() const {
    return space_to_right_;
  }
  void set_space_to_right(int space) {
    space_to_right_ = space;
  }
  uinT8* color1() {
    return color1_;
  }
  uinT8* color2() {
    return color2_;
  }
  bool owns_blobs() const {
    return owns_blobs_;
  }
  void set_owns_blobs(bool owns_blobs) {
    // Do NOT change ownership flag when there are blobs in the list.
    // Immediately set the ownership flag when creating copies.
    ASSERT_HOST(boxes_.empty());
    owns_blobs_ = owns_blobs;
  }

  // Inline quasi-accessors that require some computation.

  // Returns the middle y-coord of the bounding box.
  int MidY() const {
    return (bounding_box_.top() + bounding_box_.bottom()) / 2;
  }
  // Returns the middle y-coord of the median top and bottom.
  int MedianY() const {
    return (median_top_ + median_bottom_) / 2;
  }
  // Returns the middle x-coord of the bounding box.
  int MidX() const {
    return (bounding_box_.left() + bounding_box_.right()) / 2;
  }
  // Returns the sort key at any given x,y.
  int SortKey(int x, int y) const {
    return TabVector::SortKey(vertical_, x, y);
  }
  // Returns the x corresponding to the sortkey, y pair.
  int XAtY(int sort_key, int y) const {
    return TabVector::XAtY(vertical_, sort_key, y);
  }
  // Returns the x difference between the two sort keys.
  int KeyWidth(int left_key, int right_key) const {
    return (right_key - left_key) / vertical_.y();
  }
  // Returns the column width between the left and right keys.
  int ColumnWidth() const {
    return KeyWidth(left_key_, right_key_);
  }
  // Returns the sort key of the box left edge.
  int BoxLeftKey() const {
    return SortKey(bounding_box_.left(), MidY());
  }
  // Returns the sort key of the box right edge.
  int BoxRightKey() const {
    return SortKey(bounding_box_.right(), MidY());
  }
  // Returns the left edge at the given y, using the sort key.
  int LeftAtY(int y) const {
    return XAtY(left_key_, y);
  }
  // Returns the right edge at the given y, using the sort key.
  int RightAtY(int y) const {
    return XAtY(right_key_, y);
  }
  // Returns true if the right edge of this is to the left of the right
  // edge of other.
  bool IsLeftOf(const ColPartition& other) const {
    return bounding_box_.right() < other.bounding_box_.right();
  }
  // Returns true if the partition contains the given x coordinate at the y.
  bool ColumnContains(int x, int y) const {
    return LeftAtY(y) - 1 <= x && x <= RightAtY(y) + 1;
  }
  // Returns true if there are no blobs in the list.
  bool IsEmpty() const {
    return boxes_.empty();
  }
  // Returns true if there is a single blob in the list.
  bool IsSingleton() const {
    return boxes_.singleton();
  }
  // Returns true if this and other overlap horizontally by bounding box.
  bool HOverlaps(const ColPartition& other) const {
    return bounding_box_.x_overlap(other.bounding_box_);
  }
  // Returns true if this and other's bounding boxes overlap vertically.
  // TODO(rays) Make HOverlaps and VOverlaps truly symmetric.
  bool VOverlaps(const ColPartition& other) const {
    return bounding_box_.y_gap(other.bounding_box_) < 0;
  }
  // Returns the vertical overlap (by median) of this and other.
  // WARNING! Only makes sense on horizontal partitions!
  int VCoreOverlap(const ColPartition& other) const {
    return MIN(median_top_, other.median_top_) -
           MAX(median_bottom_, other.median_bottom_);
  }
  // Returns the horizontal overlap (by median) of this and other.
  // WARNING! Only makes sense on vertical partitions!
  int HCoreOverlap(const ColPartition& other) const {
    return MIN(median_right_, other.median_right_) -
           MAX(median_left_, other.median_left_);
  }
  // Returns true if this and other overlap significantly vertically.
  // WARNING! Only makes sense on horizontal partitions!
  bool VSignificantCoreOverlap(const ColPartition& other) const {
    int overlap = VCoreOverlap(other);
    int height = MIN(median_top_ - median_bottom_,
                     other.median_top_ - other.median_bottom_);
    return overlap * 3 > height;
  }
  // Returns true if this and other can be combined without putting a
  // horizontal step in either left or right edge of the resulting block.
  bool WithinSameMargins(const ColPartition& other) const {
    return left_margin_ <= other.bounding_box_.left() &&
           bounding_box_.left() >= other.left_margin_ &&
           bounding_box_.right() <= other.right_margin_ &&
           right_margin_ >= other.bounding_box_.right();
  }
  // Returns true if the region types (aligned_text_) match.
  // Lines never match anything, as they should never be merged or chained.
  bool TypesMatch(const ColPartition& other) const {
    return TypesMatch(blob_type_, other.blob_type_);
  }
  static bool TypesMatch(BlobRegionType type1, BlobRegionType type2) {
    return (type1 == type2 || type1 == BRT_UNKNOWN || type2 == BRT_UNKNOWN) &&
           !BLOBNBOX::IsLineType(type1) && !BLOBNBOX::IsLineType(type2);
  }

  // Returns true if the types are similar to each other.
  static bool TypesSimilar(PolyBlockType type1, PolyBlockType type2) {
    return (type1 == type2 ||
            (type1 == PT_FLOWING_TEXT && type2 == PT_INLINE_EQUATION) ||
            (type2 == PT_FLOWING_TEXT && type1 == PT_INLINE_EQUATION));
  }

  // Returns true if partitions is of horizontal line type
  bool IsLineType() const {
    return PTIsLineType(type_);
  }
  // Returns true if partitions is of image type
  bool IsImageType() const {
    return PTIsImageType(type_);
  }
  // Returns true if partitions is of text type
  bool IsTextType() const {
    return PTIsTextType(type_);
  }
  // Returns true if the partition is of an exclusively vertical type.
  bool IsVerticalType() const {
    return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE;
  }
  // Returns true if the partition is of a definite horizontal type.
  bool IsHorizontalType() const {
    return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE;
  }
  // Returns true is the partition is of a type that cannot be merged.
  bool IsUnMergeableType() const {
    return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE;
  }
  // Returns true if this partition is a vertical line
  // TODO(nbeato): Use PartitionType enum when Ray's code is submitted.
  bool IsVerticalLine() const {
    return IsVerticalType() && IsLineType();
  }
  // Returns true if this partition is a horizontal line
  // TODO(nbeato): Use PartitionType enum when Ray's code is submitted.
  bool IsHorizontalLine() const {
    return IsHorizontalType() && IsLineType();
  }

  // Adds the given box to the partition, updating the partition bounds.
  // The list of boxes in the partition is updated, ensuring that no box is
  // recorded twice, and the boxes are kept in increasing left position.
  void AddBox(BLOBNBOX* box);

  // Removes the given box from the partition, updating the bounds.
  void RemoveBox(BLOBNBOX* box);

  // Returns the tallest box in the partition, as measured perpendicular to the
  // presumed flow of text.
  BLOBNBOX* BiggestBox();

  // Returns the bounding box excluding the given box.
  TBOX BoundsWithoutBox(BLOBNBOX* box);

  // Claims the boxes in the boxes_list by marking them with a this owner
  // pointer.
  void ClaimBoxes();

  // NULL the owner of the blobs in this partition, so they can be deleted
  // independently of the ColPartition.
  void DisownBoxes();

  // Delete the boxes that this partition owns.
  void DeleteBoxes();

  // Reflects the partition in the y-axis, assuming that its blobs have
  // already been done. Corrects only a limited part of the members, since
  // this function is assumed to be used shortly after initial creation, which
  // is before a lot of the members are used.
  void ReflectInYAxis();

  // Returns true if this is a legal partition - meaning that the conditions
  // left_margin <= bounding_box left
  // left_key <= bounding box left key
  // bounding box left <= bounding box right
  // and likewise for right margin and key
  // are all met.
  bool IsLegal();

  // Returns true if the left and right edges are approximately equal.
  bool MatchingColumns(const ColPartition& other) const;

  // Returns true if the colors match for two text partitions.
  bool MatchingTextColor(const ColPartition& other) const;

  // Returns true if the sizes match for two text partitions,
  // taking orientation into account
  bool MatchingSizes(const ColPartition& other) const;

  // Returns true if there is no tabstop violation in merging this and other.
  bool ConfirmNoTabViolation(const ColPartition& other) const;

  // Returns true if other has a similar stroke width to this.
  bool MatchingStrokeWidth(const ColPartition& other,
                           double fractional_tolerance,
                           double constant_tolerance) const;
  // Returns true if candidate is an acceptable diacritic base char merge
  // with this as the diacritic.
  bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const;

  // Sets the sort key using either the tab vector, or the bounding box if
  // the tab vector is NULL. If the tab_vector lies inside the bounding_box,
  // use the edge of the box as a key any way.
  void SetLeftTab(const TabVector* tab_vector);
  void SetRightTab(const TabVector* tab_vector);

  // Copies the left/right tab from the src partition, but if take_box is
  // true, copies the box instead and uses that as a key.
  void CopyLeftTab(const ColPartition& src, bool take_box);
  void CopyRightTab(const ColPartition& src, bool take_box);

  // Returns the left rule line x coord of the leftmost blob.
  int LeftBlobRule() const;
  // Returns the right rule line x coord of the rightmost blob.
  int RightBlobRule() const;

  // Returns the density value for a particular BlobSpecialTextType.
  float SpecialBlobsDensity(const BlobSpecialTextType type) const;
  // Returns the number of blobs for a  particular BlobSpecialTextType.
  int SpecialBlobsCount(const BlobSpecialTextType type);
  // Set the density value for a particular BlobSpecialTextType, should ONLY be
  // used for debugging or testing. In production code, use
  // ComputeSpecialBlobsDensity instead.
  void SetSpecialBlobsDensity(
      const BlobSpecialTextType type, const float density);
  // Compute the SpecialTextType density of blobs, where we assume
  // that the SpecialTextType in the boxes_ has been set.
  void ComputeSpecialBlobsDensity();

  // Add a partner above if upper, otherwise below.
  // Add them uniquely and keep the list sorted by box left.
  // Partnerships are added symmetrically to partner and this.
  void AddPartner(bool upper, ColPartition* partner);
  // Removes the partner from this, but does not remove this from partner.
  // This asymmetric removal is so as not to mess up the iterator that is
  // working on partner's partner list.
  void RemovePartner(bool upper, ColPartition* partner);
  // Returns the partner if the given partner is a singleton, otherwise NULL.
  ColPartition* SingletonPartner(bool upper);

  // Merge with the other partition and delete it.
  void Absorb(ColPartition* other, WidthCallback* cb);

  // Returns true if the overlap between this and the merged pair of
  // merge candidates is sufficiently trivial to be allowed.
  // The merged box can graze the edge of this by the ok_box_overlap
  // if that exceeds the margin to the median top and bottom.
  bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2,
                      int ok_box_overlap, bool debug);

  // Find the blob at which to split this to minimize the overlap with the
  // given box. Returns the first blob to go in the second partition.
  BLOBNBOX* OverlapSplitBlob(const TBOX& box);

  // Split this partition keeping the first half in this and returning
  // the second half.
  // Splits by putting the split_blob and the blobs that follow
  // in the second half, and the rest in the first half.
  ColPartition* SplitAtBlob(BLOBNBOX* split_blob);

  // Splits this partition at the given x coordinate, returning the right
  // half and keeping the left half in this.
  ColPartition* SplitAt(int split_x);

  // Recalculates all the coordinate limits of the partition.
  void ComputeLimits();

  // Returns the number of boxes that overlap the given box.
  int CountOverlappingBoxes(const TBOX& box);

  // Computes and sets the type_, first_column_, last_column_ and column_set_.
  // resolution refers to the ppi resolution of the image.
  void SetPartitionType(int resolution, ColPartitionSet* columns);

  // Returns the PartitionType from the current BlobRegionType and a column
  // flow spanning type ColumnSpanningType, generated by
  // ColPartitionSet::SpanningType, that indicates how the partition sits
  // in the columns.
  PolyBlockType PartitionType(ColumnSpanningType flow) const;

  // Returns the first and last column touched by this partition.
  // resolution refers to the ppi resolution of the image.
  void ColumnRange(int resolution, ColPartitionSet* columns,
                   int* first_col, int* last_col);

  // Sets the internal flags good_width_ and good_column_.
  void SetColumnGoodness(WidthCallback* cb);

  // Determines whether the blobs in this partition mostly represent
  // a leader (fixed pitch sequence) and sets the member blobs accordingly.
  // Note that height is assumed to have been tested elsewhere, and that this
  // function will find most fixed-pitch text as leader without a height filter.
  // Leader detection is limited to sequences of identical width objects,
  // such as .... or ----, so patterns, such as .-.-.-.-. will not be found.
  bool MarkAsLeaderIfMonospaced();
  // Given the result of TextlineProjection::EvaluateColPartition, (positive for
  // horizontal text, negative for vertical text, and near zero for non-text),
  // sets the blob_type_ and flow_ for this partition to indicate whether it
  // is strongly or weakly vertical or horizontal text, or non-text.
  void SetRegionAndFlowTypesFromProjectionValue(int value);

  // Sets all blobs with the partition blob type and flow, but never overwrite
  // leader blobs, as we need to be able to identify them later.
  void SetBlobTypes();

  // Returns true if a decent baseline can be fitted through the blobs.
  // Works for both horizontal and vertical text.
  bool HasGoodBaseline();

  // Adds this ColPartition to a matching WorkingPartSet if one can be found,
  // otherwise starts a new one in the appropriate column, ending the previous.
  void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright,
                       int resolution, ColPartition_LIST* used_parts,
                       WorkingPartSet_LIST* working_set);

  // From the given block_parts list, builds one or more BLOCKs and
  // corresponding TO_BLOCKs, such that the line spacing is uniform in each.
  // Created blocks are appended to the end of completed_blocks and to_blocks.
  // The used partitions are put onto used_parts, as they may still be referred
  // to in the partition grid. bleft, tright and resolution are the bounds
  // and resolution of the original image.
  static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright,
                                int resolution,
                                ColPartition_LIST* block_parts,
                                ColPartition_LIST* used_parts,
                                BLOCK_LIST* completed_blocks,
                                TO_BLOCK_LIST* to_blocks);
  // Constructs a block from the given list of partitions.
  // Arguments are as LineSpacingBlocks above.
  static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright,
                             ColPartition_LIST* block_parts,
                             ColPartition_LIST* used_parts);

  // Constructs a block from the given list of vertical text partitions.
  // Currently only creates rectangular blocks.
  static TO_BLOCK* MakeVerticalTextBlock(const ICOORD& bleft,
                                         const ICOORD& tright,
                                         ColPartition_LIST* block_parts,
                                         ColPartition_LIST* used_parts);


  // Returns a copy of everything except the list of boxes. The resulting
  // ColPartition is only suitable for keeping in a column candidate list.
  ColPartition* ShallowCopy() const;
  // Returns a copy of everything with a shallow copy of the blobs.
  // The blobs are still owned by their original parent, so they are
  // treated as read-only.
  ColPartition* CopyButDontOwnBlobs();

  // Provides a color for BBGrid to draw the rectangle.
  ScrollView::Color  BoxColor() const;

  // Prints debug information on this.
  void Print() const;
  // Prints debug information on the colors.
  void PrintColors();

  // Sets the types of all partitions in the run to be the max of the types.
  void SmoothPartnerRun(int working_set_count);

  // Cleans up the partners of the given type so that there is at most
  // one partner. This makes block creation simpler.
  // If get_desperate is true, goes to more desperate merge methods
  // to merge flowing text before breaking partnerships.
  void RefinePartners(PolyBlockType type, bool get_desparate,
                      ColPartitionGrid* grid);

  // Returns true if this column partition is in the same column as
  // part. This function will only work after the SetPartitionType function
  // has been called on both column partitions. This is useful for
  // doing a SideSearch when you want things in the same page column.
  bool IsInSameColumnAs(const ColPartition& part) const;

  // Sets the column bounds. Primarily used in testing.
  void set_first_column(int column) {
    first_column_ = column;
  }
  void set_last_column(int column) {
    last_column_ = column;
  }

 private:
  // enum to refer to the entries in a neigbourhood of lines.
  // Used by SmoothSpacings to test for blips with OKSpacingBlip.
  enum SpacingNeighbourhood {
    PN_ABOVE2,
    PN_ABOVE1,
    PN_UPPER,
    PN_LOWER,
    PN_BELOW1,
    PN_BELOW2,
    PN_COUNT
  };

  // Cleans up the partners above if upper is true, else below.
  // If get_desperate is true, goes to more desperate merge methods
  // to merge flowing text before breaking partnerships.
  void RefinePartnersInternal(bool upper, bool get_desperate,
                              ColPartitionGrid* grid);
  // Restricts the partners to only desirable types. For text and BRT_HLINE this
  // means the same type_ , and for image types it means any image type.
  void RefinePartnersByType(bool upper, ColPartition_CLIST* partners);
  // Remove transitive partnerships: this<->a, and a<->b and this<->b.
  // Gets rid of this<->b, leaving a clean chain.
  // Also if we have this<->a and a<->this, then gets rid of this<->a, as
  // this has multiple partners.
  void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners);
  // If multiple text partners can be merged, then do so.
  // If desperate is true, then an increase in overlap with the merge is
  // allowed. If the overlap increases, then the desperately_merged_ flag
  // is set, indicating that the textlines probably need to be regenerated
  // by aggressive line fitting/splitting, as there are probably vertically
  // joined blobs that cross textlines.
  void RefineTextPartnersByMerge(bool upper, bool desperate,
                                 ColPartition_CLIST* partners,
                                 ColPartitionGrid* grid);
  // Keep the partner with the biggest overlap.
  void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners);

  // Return true if bbox belongs better in this than other.
  bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other);

  // Smoothes the spacings in the list into groups of equal linespacing.
  // resolution is the resolution of the original image, used as a basis
  // for thresholds in change of spacing. page_height is in pixels.
  static void SmoothSpacings(int resolution, int page_height,
                             ColPartition_LIST* parts);

  // Returns true if the parts array of pointers to partitions matches the
  // condition for a spacing blip. See SmoothSpacings for what this means
  // and how it is used.
  static bool OKSpacingBlip(int resolution, int median_spacing,
                            ColPartition** parts);

  // Returns true if both the top and bottom spacings of this match the given
  // spacing to within suitable margins dictated by the image resolution.
  bool SpacingEqual(int spacing, int resolution) const;

  // Returns true if both the top and bottom spacings of this and other
  // match to within suitable margins dictated by the image resolution.
  bool SpacingsEqual(const ColPartition& other, int resolution) const;

  // Returns true if the sum spacing of this and other match the given
  // spacing (or twice the given spacing) to within a suitable margin dictated
  // by the image resolution.
  bool SummedSpacingOK(const ColPartition& other,
                       int spacing, int resolution) const;

  // Returns a suitable spacing margin that can be applied to bottoms of
  // text lines, based on the resolution and the stored side_step_.
  int BottomSpacingMargin(int resolution) const;

  // Returns a suitable spacing margin that can be applied to tops of
  // text lines, based on the resolution and the stored side_step_.
  int TopSpacingMargin(int resolution) const;

  // Returns true if the median text sizes of this and other agree to within
  // a reasonable multiplicative factor.
  bool SizesSimilar(const ColPartition& other) const;

  // Computes and returns in start, end a line segment formed from a
  // forwards-iterated group of left edges of partitions that satisfy the
  // condition that the rightmost left margin is to the left of the
  // leftmost left bounding box edge.
  // TODO(rays) Not good enough. Needs improving to tightly wrap text in both
  // directions, and to loosely wrap images.
  static void LeftEdgeRun(ColPartition_IT* part_it,
                          ICOORD* start, ICOORD* end);
  // Computes and returns in start, end a line segment formed from a
  // backwards-iterated group of right edges of partitions that satisfy the
  // condition that the leftmost right margin is to the right of the
  // rightmost right bounding box edge.
  // TODO(rays) Not good enough. Needs improving to tightly wrap text in both
  // directions, and to loosely wrap images.
  static void RightEdgeRun(ColPartition_IT* part_it,
                           ICOORD* start, ICOORD* end);

  // The margins are determined by the position of the nearest vertically
  // overlapping neighbour to the side. They indicate the maximum extent
  // that the block/column may be extended without touching something else.
  // Leftmost coordinate that the region may occupy over the y limits.
  int left_margin_;
  // Rightmost coordinate that the region may occupy over the y limits.
  int right_margin_;
  // Bounding box of all blobs in the partition.
  TBOX bounding_box_;
  // Median top and bottom of blobs in this partition.
  int median_bottom_;
  int median_top_;
  // Median height of blobs in this partition.
  // TODO(rays) rename median_height_.
  int median_size_;
  // Median left and right of blobs in this partition.
  int median_left_;
  int median_right_;
  // Median width of blobs in this partition.
  int median_width_;
  // blob_region_type_ for the blobs in this partition.
  BlobRegionType blob_type_;
  BlobTextFlowType flow_;  // Quality of text flow.
  // Total of GoodTextBlob results for all blobs in the partition.
  int good_blob_score_;
  // True if this partition has a common width.
  bool good_width_;
  // True if this is a good column candidate.
  bool good_column_;
  // True if the left_key_ is from a tab vector.
  bool left_key_tab_;
  // True if the right_key_ is from a tab vector.
  bool right_key_tab_;
  // Left and right sort keys for the edges of the partition.
  // If the respective *_key_tab_ is true then this key came from a tab vector.
  // If not, then the class promises to keep the key equal to the sort key
  // for the respective edge of the bounding box at the MidY, so that
  // LeftAtY and RightAtY always returns an x coordinate on the line parallel
  // to vertical_ through the bounding box edge at MidY.
  int left_key_;
  int right_key_;
  // Type of this partition after looking at its relation to the columns.
  PolyBlockType type_;
  // All boxes in the partition stored in increasing left edge coordinate.
  BLOBNBOX_CLIST boxes_;
  // The global vertical skew direction.
  ICOORD vertical_;
  // The partitions above that matched this.
  ColPartition_CLIST upper_partners_;
  // The partitions below that matched this.
  ColPartition_CLIST lower_partners_;
  // The WorkingPartSet it lives in while blocks are being made.
  WorkingPartSet* working_set_;
  // Flag is true when AddBox is sorting vertically, false otherwise.
  bool last_add_was_vertical_;
  // True when the partition's ownership has been taken from the grid and
  // placed in a working set, or, after that, in the good_parts_ list.
  bool block_owned_;
  // Flag to indicate that this partition was subjected to a desperate merge,
  // and therefore the textlines need rebuilding.
  bool desperately_merged_;
  // The first and last column that this partition applies to.
  // Flowing partitions (see type_) will have an equal first and last value
  // of the form 2n + 1, where n is the zero-based index into the partitions
  // in column_set_. (See ColPartitionSet::GetColumnByIndex).
  // Heading partitions will have unequal values of the same form.
  // Pullout partitions will have equal values, but may have even values,
  // indicating placement between columns.
  int first_column_;
  int last_column_;
  // Column_set_ is the column layout applicable to this ColPartition.
  ColPartitionSet* column_set_;
  // Linespacing data.
  int side_step_;       // Median y-shift to next blob on same line.
  int top_spacing_;     // Line spacing from median_top_.
  int bottom_spacing_;  // Line spacing from median_bottom_.

  // Type of this partition before considering it as a table cell. This is
  // used to revert the type if a partition is first marked as a table cell but
  // later filtering steps decide it does not belong to a table
  PolyBlockType type_before_table_;
  bool inside_table_column_;  // Check whether the current partition has been
                              // assigned to a table column
  // Nearest neighbor above with major x-overlap
  ColPartition* nearest_neighbor_above_;
  // Nearest neighbor below with major x-overlap
  ColPartition* nearest_neighbor_below_;
  int space_above_;      // Distance from nearest_neighbor_above
  int space_below_;      // Distance from nearest_neighbor_below
  int space_to_left_;    // Distance from the left edge of the column
  int space_to_right_;   // Distance from the right edge of the column
  // Color foreground/background data.
  uinT8 color1_[kRGBRMSColors];
  uinT8 color2_[kRGBRMSColors];
  bool owns_blobs_;  // Does the partition own its blobs?
  // The density of special blobs.
  float special_blobs_densities_[BSTT_COUNT];
};

// Typedef it now in case it becomes a class later.
typedef GridSearch<ColPartition,
                   ColPartition_CLIST,
                   ColPartition_C_IT> ColPartitionGridSearch;

}  // namespace tesseract.

#endif  // TESSERACT_TEXTORD_COLPARTITION_H__