void make_single_word(bool one_blob, TO_ROW_LIST *rows, ROW_LIST* real_rows) { TO_ROW_IT to_row_it(rows); TO_ROW* row = to_row_it.data(); // The blobs have to come out of the BLOBNBOX into the C_BLOB_LIST ready // to create the word. C_BLOB_LIST cblobs; C_BLOB_IT cblob_it(&cblobs); BLOBNBOX_IT box_it(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(row, static_cast<inT16>(row->kern_size), static_cast<inT16>(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_it.add_after_then_move(word); ROW_IT row_it(real_rows); row_it.add_after_then_move(real_row); }
//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; }
void show_point(PAGE_RES* page_res, float x, float y) { FCOORD pt(x, y); PAGE_RES_IT pr_it(page_res); const int kBufsize = 512; char msg[kBufsize]; char *msg_ptr = msg; msg_ptr += sprintf(msg_ptr, "Pt:(%0.3f, %0.3f) ", x, y); for (WERD_RES* word = pr_it.word(); word != NULL; word = pr_it.forward()) { if (pr_it.row() != pr_it.prev_row() && pr_it.row()->row->bounding_box().contains(pt)) { msg_ptr += sprintf(msg_ptr, "BL(x)=%0.3f ", pr_it.row()->row->base_line(x)); } if (word->word->bounding_box().contains(pt)) { TBOX box = word->word->bounding_box(); msg_ptr += sprintf(msg_ptr, "Wd(%d, %d)/(%d, %d) ", box.left(), box.bottom(), box.right(), box.top()); C_BLOB_IT cblob_it(word->word->cblob_list()); for (cblob_it.mark_cycle_pt(); !cblob_it.cycled_list(); cblob_it.forward()) { C_BLOB* cblob = cblob_it.data(); box = cblob->bounding_box(); if (box.contains(pt)) { msg_ptr += sprintf(msg_ptr, "CBlb(%d, %d)/(%d, %d) ", box.left(), box.bottom(), box.right(), box.top()); } } } } image_win->AddMessage(msg); }
// Compute the distance from the left and right ends of each row to the // left and right edges of the block's polyblock. Illustration: // ____________________________ _______________________ // | Howdy neighbor! | |rectangular blocks look| // | This text is written to| |more like stacked pizza| // |illustrate how useful poly- |boxes. | // |blobs are in ----------- ------ The polyblob| // |dealing with| _________ |for a BLOCK rec-| // |harder layout| /===========\ |ords the possibly| // |issues. | | _ _ | |skewed pseudo-| // | You see this| | |_| \|_| | |rectangular | // |text is flowed| | } | |boundary that| // |around a mid-| \ ____ | |forms the ideal-| // |cloumn portrait._____ \ / __|ized text margin| // | Polyblobs exist| \ / |from which we should| // |to account for insets| | | |measure paragraph| // |which make otherwise| ----- |indentation. | // ----------------------- ---------------------- // // If we identify a drop-cap, we measure the left margin for the lines // below the first line relative to one space past the drop cap. The // first line's margin and those past the drop cap area are measured // relative to the enclosing polyblock. // // TODO(rays): Before this will work well, we'll need to adjust the // polyblob tighter around the text near images, as in: // UNLV_AUTO:mag.3G0 page 2 // UNLV_AUTO:mag.3G4 page 16 void BLOCK::compute_row_margins() { if (row_list()->empty() || row_list()->singleton()) { return; } // If Layout analysis was not called, default to this. POLY_BLOCK rect_block(bounding_box(), PT_FLOWING_TEXT); POLY_BLOCK *pblock = &rect_block; if (poly_block() != NULL) { pblock = poly_block(); } // Step One: Determine if there is a drop-cap. // TODO(eger): Fix up drop cap code for RTL languages. ROW_IT r_it(row_list()); ROW *first_row = r_it.data(); ROW *second_row = r_it.data_relative(1); // initialize the bottom of a fictitious drop cap far above the first line. int drop_cap_bottom = first_row->bounding_box().top() + first_row->bounding_box().height(); int drop_cap_right = first_row->bounding_box().left(); int mid_second_line = second_row->bounding_box().top() - second_row->bounding_box().height() / 2; WERD_IT werd_it(r_it.data()->word_list()); // words of line one if (!werd_it.empty()) { C_BLOB_IT cblob_it(werd_it.data()->cblob_list()); for (cblob_it.mark_cycle_pt(); !cblob_it.cycled_list(); cblob_it.forward()) { TBOX bbox = cblob_it.data()->bounding_box(); if (bbox.bottom() <= mid_second_line) { // we found a real drop cap first_row->set_has_drop_cap(true); if (drop_cap_bottom > bbox.bottom()) drop_cap_bottom = bbox.bottom(); if (drop_cap_right < bbox.right()) drop_cap_right = bbox.right(); } } } // Step Two: Calculate the margin from the text of each row to the block // (or drop-cap) boundaries. PB_LINE_IT lines(pblock); r_it.set_to_list(row_list()); for (r_it.mark_cycle_pt(); !r_it.cycled_list(); r_it.forward()) { ROW *row = r_it.data(); TBOX row_box = row->bounding_box(); int left_y = row->base_line(row_box.left()) + row->x_height(); int left_margin; ICOORDELT_LIST *segments = lines.get_line(left_y); LeftMargin(segments, row_box.left(), &left_margin); delete segments; if (row_box.top() >= drop_cap_bottom) { int drop_cap_distance = row_box.left() - row->space() - drop_cap_right; if (drop_cap_distance < 0) drop_cap_distance = 0; if (drop_cap_distance < left_margin) left_margin = drop_cap_distance; } int right_y = row->base_line(row_box.right()) + row->x_height(); int right_margin; segments = lines.get_line(right_y); RightMargin(segments, row_box.right(), &right_margin); delete segments; row->set_lmargin(left_margin); row->set_rmargin(right_margin); } }
void WERD::move(const ICOORD vec) { C_BLOB_IT cblob_it(&cblobs); // cblob iterator for (cblob_it.mark_cycle_pt(); !cblob_it.cycled_list(); cblob_it.forward()) cblob_it.data()->move(vec); }