本文整理汇总了C++中BLOBNBOX::cblob方法的典型用法代码示例。如果您正苦于以下问题:C++ BLOBNBOX::cblob方法的具体用法?C++ BLOBNBOX::cblob怎么用?C++ BLOBNBOX::cblob使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BLOBNBOX
的用法示例。
在下文中一共展示了BLOBNBOX::cblob方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: getColPartImCoords
BOX* M_Utils::getColPartImCoords(ColPartition* cp, PIX* im) {
BLOBNBOX_CLIST* blobnboxes = cp->boxes();
CLIST_ITERATOR bbox_it(blobnboxes);
l_int32 height = (l_int32)im->h;
l_int32 left = INT_MAX;
l_int32 right = INT_MIN;
l_int32 top = INT_MAX;
l_int32 bottom = INT_MIN;
l_int32 l, r, t, b;
for (bbox_it.mark_cycle_pt (); !bbox_it.cycled_list();
bbox_it.forward()) {
BLOBNBOX* blobnbox = (BLOBNBOX*)bbox_it.data();
l = (l_int32)blobnbox->cblob()->bounding_box().left();
r = (l_int32)blobnbox->cblob()->bounding_box().right();
t = height - (l_int32)blobnbox->cblob()->bounding_box().top();
b = height - (l_int32)blobnbox->cblob()->bounding_box().bottom();
if(l < left)
left = l;
if(r > right)
right = r;
if(t < top)
top = t;
if(b > bottom)
bottom = b;
}
BOX* boxret = boxCreate(left, top, right-left, bottom-top);
return boxret;
}
示例2: ComputeEdgeOffsets
// Helper to compute edge offsets for all the blobs on the list.
// See coutln.h for an explanation of edge offsets.
void BLOBNBOX::ComputeEdgeOffsets(Pix* thresholds, Pix* grey,
BLOBNBOX_LIST* blobs) {
int grey_height = 0;
int thr_height = 0;
int scale_factor = 1;
if (thresholds != NULL && grey != NULL) {
grey_height = pixGetHeight(grey);
thr_height = pixGetHeight(thresholds);
scale_factor =
IntCastRounded(static_cast<double>(grey_height) / thr_height);
}
BLOBNBOX_IT blob_it(blobs);
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
BLOBNBOX* blob = blob_it.data();
if (blob->cblob() != NULL) {
// Get the threshold that applies to this blob.
l_uint32 threshold = 128;
if (thresholds != NULL && grey != NULL) {
const TBOX& box = blob->cblob()->bounding_box();
// Transform the coordinates if required.
TPOINT pt((box.left() + box.right()) / 2,
(box.top() + box.bottom()) / 2);
pixGetPixel(thresholds, pt.x / scale_factor,
thr_height - 1 - pt.y / scale_factor, &threshold);
}
blob->cblob()->ComputeEdgeOffsets(threshold, grey);
}
}
}
示例3: TAL_make_single_word
//yangjing01 modified :
bool TAL_make_single_word(bool one_blob, TO_ROW_LIST* rows, ROW_LIST* real_rows)
{
TO_ROW_IT to_row_it(rows);
ROW_IT row_it(real_rows);
//to_real_row is the real row information of single row or single char mode
TO_ROW* real_to_row = NULL;
float row_max_height = 0.0;
for (to_row_it.mark_cycle_pt();
!to_row_it.cycled_list(); to_row_it.forward()){
TO_ROW* row = to_row_it.data();
float row_min_y = row->min_y();
float row_max_y = row->max_y();
float row_height = abs(row_max_y - row_min_y);
if (real_to_row == NULL
|| row_height > row_max_height
|| fabs(row_height - row_max_height) < 1.0f){
row_max_height = row_height;
real_to_row = row;
}
}
if (real_to_row == NULL){
return false;
}
C_BLOB_LIST cblobs;
C_BLOB_IT cblob_it(&cblobs);
BLOBNBOX_IT box_it(real_to_row->blob_list());
for (; !box_it.empty(); box_it.forward()){
BLOBNBOX* bblob = box_it.extract();
if (bblob->joined_to_prev() || (one_blob && !cblob_it.empty())) {
if (bblob->cblob() != NULL){
C_OUTLINE_IT cout_it(cblob_it.data()->out_list());
cout_it.move_to_last();
cout_it.add_list_after(bblob->cblob()->out_list());
delete bblob->cblob();
}
}
else {
if (bblob->cblob() != NULL)
cblob_it.add_after_then_move(bblob->cblob());
}
delete bblob;
}
// Convert the TO_ROW to a ROW.
ROW* real_row = new ROW(real_to_row, static_cast<inT16>(real_to_row->kern_size),
static_cast<inT16>(real_to_row->space_size));
WERD_IT word_it(real_row->word_list());
WERD* word = new WERD(&cblobs, 0, NULL);
word->set_flag(W_BOL, TRUE);
word->set_flag(W_EOL, TRUE);
word->set_flag(W_DONT_CHOP, one_blob);
word_it.add_after_then_move(word);
row_it.add_after_then_move(real_row);
return true;
}
示例4: if
WERD *make_real_word(BLOBNBOX_IT *box_it, //iterator
inT32 blobcount, //no of blobs to use
BOOL8 bol, //start of line
uinT8 blanks //no of blanks
) {
OUTLINE_IT out_it; // outlines
C_OUTLINE_IT cout_it;
PBLOB_LIST blobs; // blobs in word
C_BLOB_LIST cblobs;
PBLOB_IT blob_it = &blobs; // iterator
C_BLOB_IT cblob_it = &cblobs;
WERD *word; // new word
BLOBNBOX *bblob; // current blob
inT32 blobindex; // in row
for (blobindex = 0; blobindex < blobcount; blobindex++) {
bblob = box_it->extract();
if (bblob->joined_to_prev()) {
if (bblob->blob() != NULL) {
out_it.set_to_list(blob_it.data()->out_list());
out_it.move_to_last();
out_it.add_list_after(bblob->blob()->out_list());
delete bblob->blob();
}
else if (bblob->cblob() != NULL) {
cout_it.set_to_list(cblob_it.data()->out_list());
cout_it.move_to_last();
cout_it.add_list_after(bblob->cblob()->out_list());
delete bblob->cblob();
}
}
else {
if (bblob->blob() != NULL)
blob_it.add_after_then_move(bblob->blob());
else if (bblob->cblob() != NULL)
cblob_it.add_after_then_move(bblob->cblob());
}
delete bblob;
box_it->forward(); // next one
}
if (blanks < 1)
blanks = 1;
if (blob_it.empty())
word = new WERD(&cblobs, blanks, NULL);
else
word = new WERD(&blobs, blanks, NULL);
if (bol)
word->set_flag(W_BOL, TRUE);
if (box_it->at_first())
word->set_flag(W_EOL, TRUE); // at end of line
return word;
}
示例5: clear_blobnboxes
static void clear_blobnboxes(BLOBNBOX_LIST* boxes) {
BLOBNBOX_IT it = boxes;
// A BLOBNBOX generally doesn't own its blobs, so if they do, you
// have to delete them explicitly.
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
BLOBNBOX* box = it.data();
if (box->cblob() != NULL)
delete box->cblob();
}
}
示例6: MarkAndDeleteNonTextBlobs
// Tests each blob in the list to see if it is certain non-text using 2
// conditions:
// 1. blob overlaps a cell with high value in noise_density_ (previously set
// by ComputeNoiseDensity).
// OR 2. The blob overlaps more than max_blob_overlaps in *this grid. This
// condition is disabled with max_blob_overlaps == -1.
// If it does, the blob is declared non-text, and is used to mark up the
// nontext_mask. Such blobs are fully deleted, and non-noise blobs have their
// neighbours reset, as they may now point to deleted data.
// WARNING: The blobs list blobs may be in the *this grid, but they are
// not removed. If any deleted blobs might be in *this, then this must be
// Clear()ed immediately after MarkAndDeleteNonTextBlobs is called.
// If the win is not NULL, deleted blobs are drawn on it in red, and kept
// blobs are drawn on it in ok_color.
void CCNonTextDetect::MarkAndDeleteNonTextBlobs(BLOBNBOX_LIST* blobs,
int max_blob_overlaps,
ScrollView* win,
ScrollView::Color ok_color,
Pix* nontext_mask) {
int imageheight = tright().y() - bleft().x();
BLOBNBOX_IT blob_it(blobs);
BLOBNBOX_LIST dead_blobs;
BLOBNBOX_IT dead_it(&dead_blobs);
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
BLOBNBOX* blob = blob_it.data();
TBOX box = blob->bounding_box();
if (!noise_density_->RectMostlyOverThreshold(box, max_noise_count_) &&
(max_blob_overlaps < 0 ||
!BlobOverlapsTooMuch(blob, max_blob_overlaps))) {
blob->ClearNeighbours();
#ifndef GRAPHICS_DISABLED
if (win != NULL)
blob->plot(win, ok_color, ok_color);
#endif // GRAPHICS_DISABLED
} else {
if (noise_density_->AnyZeroInRect(box)) {
// There is a danger that the bounding box may overlap real text, so
// we need to render the outline.
Pix* blob_pix = blob->cblob()->render_outline();
pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
box.width(), box.height(), PIX_SRC | PIX_DST,
blob_pix, 0, 0);
pixDestroy(&blob_pix);
} else {
if (box.area() < gridsize() * gridsize()) {
// It is a really bad idea to make lots of small components in the
// photo mask, so try to join it to a bigger area by expanding the
// box in a way that does not touch any zero noise density cell.
box = AttemptBoxExpansion(box, *noise_density_, gridsize());
}
// All overlapped cells are non-zero, so just mark the rectangle.
pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
box.width(), box.height(), PIX_SET, NULL, 0, 0);
}
#ifndef GRAPHICS_DISABLED
if (win != NULL)
blob->plot(win, ScrollView::RED, ScrollView::RED);
#endif // GRAPHICS_DISABLED
// It is safe to delete the cblob now, as it isn't used by the grid
// or BlobOverlapsTooMuch, and the BLOBNBOXes will go away with the
// dead_blobs list.
// TODO(rays) delete the delete when the BLOBNBOX destructor deletes
// the cblob.
delete blob->cblob();
dead_it.add_to_end(blob_it.extract());
}
}
}
示例7: HandleClick
/** Handles a click event in a display window. */
void StrokeWidth::HandleClick(int x, int y) {
BBGrid<BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT>::HandleClick(x, y);
// Run a radial search for blobs that overlap.
BlobGridSearch radsearch(this);
radsearch.StartRadSearch(x, y, 1);
BLOBNBOX* neighbour;
FCOORD click(static_cast<float>(x), static_cast<float>(y));
while ((neighbour = radsearch.NextRadSearch()) != NULL) {
TBOX nbox = neighbour->bounding_box();
if (nbox.contains(click) && neighbour->cblob() != NULL) {
PrintBoxWidths(neighbour);
if (neighbour->neighbour(BND_LEFT) != NULL)
PrintBoxWidths(neighbour->neighbour(BND_LEFT));
if (neighbour->neighbour(BND_RIGHT) != NULL)
PrintBoxWidths(neighbour->neighbour(BND_RIGHT));
if (neighbour->neighbour(BND_ABOVE) != NULL)
PrintBoxWidths(neighbour->neighbour(BND_ABOVE));
if (neighbour->neighbour(BND_BELOW) != NULL)
PrintBoxWidths(neighbour->neighbour(BND_BELOW));
int gaps[BND_COUNT];
neighbour->NeighbourGaps(gaps);
tprintf("Left gap=%d, right=%d, above=%d, below=%d, horz=%d, vert=%d\n"
"Good= %d %d %d %d\n",
gaps[BND_LEFT], gaps[BND_RIGHT],
gaps[BND_ABOVE], gaps[BND_BELOW],
neighbour->horz_possible(),
neighbour->vert_possible(),
neighbour->good_stroke_neighbour(BND_LEFT),
neighbour->good_stroke_neighbour(BND_RIGHT),
neighbour->good_stroke_neighbour(BND_ABOVE),
neighbour->good_stroke_neighbour(BND_BELOW));
break;
}
}
}
示例8: box_next
TBOX box_next( //get bounding box
BLOBNBOX_IT *it //iterator to blobds
) {
BLOBNBOX *blob; //current blob
TBOX result; //total box
blob = it->data ();
result = blob->bounding_box ();
do {
it->forward ();
blob = it->data ();
if (blob->cblob() == NULL)
//was pre-chopped
result += blob->bounding_box ();
}
//until next real blob
while ((blob->cblob() == NULL) || blob->joined_to_prev());
return result;
}
示例9: DeleteNoiseBlobs
// Helper to delete all the deletable blobs on the list.
void BLOBNBOX::DeleteNoiseBlobs(BLOBNBOX_LIST* blobs) {
BLOBNBOX_IT blob_it(blobs);
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
BLOBNBOX* blob = blob_it.data();
if (blob->DeletableNoise()) {
delete blob->cblob();
delete blob_it.extract();
}
}
}
示例10: WERD
WERD *make_real_word(BLOBNBOX_IT *box_it, //iterator
int32_t blobcount, //no of blobs to use
bool bol, //start of line
uint8_t blanks //no of blanks
) {
C_OUTLINE_IT cout_it;
C_BLOB_LIST cblobs;
C_BLOB_IT cblob_it = &cblobs;
WERD *word; // new word
BLOBNBOX *bblob; // current blob
int32_t blobindex; // in row
for (blobindex = 0; blobindex < blobcount; blobindex++) {
bblob = box_it->extract();
if (bblob->joined_to_prev()) {
if (bblob->cblob() != nullptr) {
cout_it.set_to_list(cblob_it.data()->out_list());
cout_it.move_to_last();
cout_it.add_list_after(bblob->cblob()->out_list());
delete bblob->cblob();
}
}
else {
if (bblob->cblob() != nullptr)
cblob_it.add_after_then_move(bblob->cblob());
}
delete bblob;
box_it->forward(); // next one
}
if (blanks < 1)
blanks = 1;
word = new WERD(&cblobs, blanks, nullptr);
if (bol)
word->set_flag(W_BOL, true);
if (box_it->at_first())
word->set_flag(W_EOL, true); // at end of line
return word;
}
示例11: compute_vertical_projection
void TO_ROW::compute_vertical_projection() { //project whole row
TBOX row_box; //bound of row
BLOBNBOX *blob; //current blob
TBOX blob_box; //bounding box
BLOBNBOX_IT blob_it = blob_list ();
if (blob_it.empty ())
return;
row_box = blob_it.data ()->bounding_box ();
for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ())
row_box += blob_it.data ()->bounding_box ();
projection.set_range (row_box.left () - PROJECTION_MARGIN,
row_box.right () + PROJECTION_MARGIN);
projection_left = row_box.left () - PROJECTION_MARGIN;
projection_right = row_box.right () + PROJECTION_MARGIN;
for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {
blob = blob_it.data();
if (blob->cblob() != NULL)
vertical_cblob_projection(blob->cblob(), &projection);
}
}
示例12: TransferDiacriticsToWords
// Places a copy of blobs that are near a word (after applying rotation to the
// blob) in the most appropriate word, unless there is doubt, in which case a
// blob can end up in two words. Source blobs are not touched.
void Textord::TransferDiacriticsToWords(BLOBNBOX_LIST* diacritic_blobs,
const FCOORD& rotation,
WordGrid* word_grid) {
WordSearch ws(word_grid);
BLOBNBOX_IT b_it(diacritic_blobs);
// Apply rotation to each blob before finding the nearest words. The rotation
// allows us to only consider above/below placement and not left/right on
// vertical text, because all text is horizontal here.
for (b_it.mark_cycle_pt(); !b_it.cycled_list(); b_it.forward()) {
BLOBNBOX* blobnbox = b_it.data();
TBOX blob_box = blobnbox->bounding_box();
blob_box.rotate(rotation);
ws.StartRectSearch(blob_box);
// Above/below refer to word position relative to diacritic. Since some
// scripts eg Kannada/Telugu habitually put diacritics below words, and
// others eg Thai/Vietnamese/Latin put most diacritics above words, try
// for both if there isn't much in it.
WordWithBox* best_above_word = nullptr;
WordWithBox* best_below_word = nullptr;
int best_above_distance = 0;
int best_below_distance = 0;
for (WordWithBox* word = ws.NextRectSearch(); word != nullptr;
word = ws.NextRectSearch()) {
if (word->word()->flag(W_REP_CHAR)) continue;
TBOX word_box = word->true_bounding_box();
int x_distance = blob_box.x_gap(word_box);
int y_distance = blob_box.y_gap(word_box);
if (x_distance > 0) {
// Arbitrarily divide x-distance by 2 if there is a major y overlap,
// and the word is to the left of the diacritic. If the
// diacritic is a dropped broken character between two words, this will
// help send all the pieces to a single word, instead of splitting them
// over the 2 words.
if (word_box.major_y_overlap(blob_box) &&
blob_box.left() > word_box.right()) {
x_distance /= 2;
}
y_distance += x_distance;
}
if (word_box.y_middle() > blob_box.y_middle() &&
(best_above_word == nullptr || y_distance < best_above_distance)) {
best_above_word = word;
best_above_distance = y_distance;
}
if (word_box.y_middle() <= blob_box.y_middle() &&
(best_below_word == nullptr || y_distance < best_below_distance)) {
best_below_word = word;
best_below_distance = y_distance;
}
}
bool above_good =
best_above_word != nullptr &&
(best_below_word == nullptr ||
best_above_distance < best_below_distance + blob_box.height());
bool below_good =
best_below_word != nullptr && best_below_word != best_above_word &&
(best_above_word == nullptr ||
best_below_distance < best_above_distance + blob_box.height());
if (below_good) {
C_BLOB* copied_blob = C_BLOB::deep_copy(blobnbox->cblob());
copied_blob->rotate(rotation);
// Put the blob into the word's reject blobs list.
C_BLOB_IT blob_it(best_below_word->RejBlobs());
blob_it.add_to_end(copied_blob);
}
if (above_good) {
C_BLOB* copied_blob = C_BLOB::deep_copy(blobnbox->cblob());
copied_blob->rotate(rotation);
// Put the blob into the word's reject blobs list.
C_BLOB_IT blob_it(best_above_word->RejBlobs());
blob_it.add_to_end(copied_blob);
}
}
}
示例13: ComputeNonTextMask
// Creates and returns a Pix with the same resolution as the original
// in which 1 (black) pixels represent likely non text (photo, line drawing)
// areas of the page, deleting from the blob_block the blobs that were
// determined to be non-text.
// The photo_map is used to bias the decision towards non-text, rather than
// supplying definite decision.
// The blob_block is the usual result of connected component analysis,
// holding the detected blobs.
// The returned Pix should be PixDestroyed after use.
Pix* CCNonTextDetect::ComputeNonTextMask(bool debug, Pix* photo_map,
TO_BLOCK* blob_block) {
// Insert the smallest blobs into the grid.
InsertBlobList(&blob_block->small_blobs);
InsertBlobList(&blob_block->noise_blobs);
// Add the medium blobs that don't have a good strokewidth neighbour.
// Those that do go into good_grid as an antidote to spreading beyond the
// real reaches of a noise region.
BlobGrid good_grid(gridsize(), bleft(), tright());
BLOBNBOX_IT blob_it(&blob_block->blobs);
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
BLOBNBOX* blob = blob_it.data();
double perimeter_area_ratio = blob->cblob()->perimeter() / 4.0;
perimeter_area_ratio *= perimeter_area_ratio / blob->enclosed_area();
if (blob->GoodTextBlob() == 0 || perimeter_area_ratio < kMinGoodTextPARatio)
InsertBBox(true, true, blob);
else
good_grid.InsertBBox(true, true, blob);
}
noise_density_ = ComputeNoiseDensity(debug, photo_map, &good_grid);
good_grid.Clear(); // Not needed any more.
Pix* pix = noise_density_->ThresholdToPix(max_noise_count_);
if (debug) {
pixWrite("junknoisemask.png", pix, IFF_PNG);
}
ScrollView* win = NULL;
#ifndef GRAPHICS_DISABLED
if (debug) {
win = MakeWindow(0, 400, "Photo Mask Blobs");
}
#endif // GRAPHICS_DISABLED
// Large and medium blobs are not text if they overlap with "a lot" of small
// blobs.
MarkAndDeleteNonTextBlobs(&blob_block->large_blobs,
kMaxLargeOverlapsWithSmall,
win, ScrollView::DARK_GREEN, pix);
MarkAndDeleteNonTextBlobs(&blob_block->blobs, kMaxMediumOverlapsWithSmall,
win, ScrollView::WHITE, pix);
// Clear the grid of small blobs and insert the medium blobs.
Clear();
InsertBlobList(&blob_block->blobs);
MarkAndDeleteNonTextBlobs(&blob_block->large_blobs,
kMaxLargeOverlapsWithMedium,
win, ScrollView::DARK_GREEN, pix);
// Clear again before we start deleting the blobs in the grid.
Clear();
MarkAndDeleteNonTextBlobs(&blob_block->noise_blobs, -1,
win, ScrollView::CORAL, pix);
MarkAndDeleteNonTextBlobs(&blob_block->small_blobs, -1,
win, ScrollView::GOLDENROD, pix);
MarkAndDeleteNonTextBlobs(&blob_block->blobs, -1,
win, ScrollView::WHITE, pix);
if (debug) {
#ifndef GRAPHICS_DISABLED
win->Update();
#endif // GRAPHICS_DISABLED
pixWrite("junkccphotomask.png", pix, IFF_PNG);
#ifndef GRAPHICS_DISABLED
delete win->AwaitEvent(SVET_DESTROY);
delete win;
#endif // GRAPHICS_DISABLED
}
return pix;
}
示例14: plot_word_decisions
void plot_word_decisions( //draw words
ScrollView *win, //window tro draw in
inT16 pitch, //of block
TO_ROW *row //row to draw
) {
ScrollView::Color colour = ScrollView::MAGENTA; //current colour
ScrollView::Color rect_colour; //fuzzy colour
inT32 prev_x; //end of prev blob
inT16 blob_count; //blobs in word
BLOBNBOX *blob; //current blob
TBOX blob_box; //bounding box
//iterator
BLOBNBOX_IT blob_it = row->blob_list();
BLOBNBOX_IT start_it = blob_it;//word start
rect_colour = ScrollView::BLACK;
prev_x = -MAX_INT16;
blob_count = 0;
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
blob = blob_it.data();
blob_box = blob->bounding_box();
if (!blob->joined_to_prev()
&& blob_box.left() - prev_x > row->max_nonspace) {
if ((blob_box.left() - prev_x >= row->min_space
|| blob_box.left() - prev_x > row->space_threshold)
&& blob_count > 0) {
if (pitch > 0 && textord_show_fixed_cuts)
plot_fp_cells(win, colour, &start_it, pitch, blob_count,
&row->projection, row->projection_left,
row->projection_right,
row->xheight * textord_projection_scale);
blob_count = 0;
start_it = blob_it;
}
if (colour == ScrollView::MAGENTA)
colour = ScrollView::RED;
else
colour = (ScrollView::Color)(colour + 1);
if (blob_box.left() - prev_x < row->min_space) {
if (blob_box.left() - prev_x > row->space_threshold)
rect_colour = ScrollView::GOLDENROD;
else
rect_colour = ScrollView::CORAL;
//fill_color_index(win, rect_colour);
win->Brush(rect_colour);
win->Rectangle(prev_x, blob_box.bottom(),
blob_box.left(), blob_box.top());
}
}
if (!blob->joined_to_prev())
prev_x = blob_box.right();
if (blob->cblob() != NULL)
blob->cblob()->plot(win, colour, colour);
if (!blob->joined_to_prev() && blob->cblob() != NULL)
blob_count++;
}
if (pitch > 0 && textord_show_fixed_cuts && blob_count > 0)
plot_fp_cells(win, colour, &start_it, pitch, blob_count,
&row->projection, row->projection_left,
row->projection_right,
row->xheight * textord_projection_scale);
}