25 # include "config_auto.h" 28 #define FIRST_COLOUR ScrollView::RED 29 #define LAST_COLOUR ScrollView::AQUAMARINE 30 #define CHILD_COLOUR ScrollView::BROWN 43 WERD::
WERD(C_BLOB_LIST* blob_list, uint8_t blank_count, const
char* text)
44 : blanks(blank_count),
flags(0), script_id_(0), correct(text) {
45 C_BLOB_IT start_it = &cblobs;
46 C_BLOB_IT rej_cblob_it = &rej_cblobs;
47 C_OUTLINE_IT c_outline_it;
48 int16_t inverted_vote = 0;
49 int16_t non_inverted_vote = 0;
52 start_it.add_list_after(blob_list);
67 start_it.set_to_list(&cblobs);
68 if (start_it.empty())
return;
69 for (start_it.mark_cycle_pt(); !start_it.cycled_list(); start_it.forward()) {
70 bool reject_blob =
false;
73 c_outline_it.set_to_list(start_it.data()->out_list());
75 for (c_outline_it.mark_cycle_pt();
76 !c_outline_it.cycled_list() && !reject_blob; c_outline_it.forward()) {
77 reject_blob = c_outline_it.data()->flag(
COUT_INVERSE) != blob_inverted;
80 rej_cblob_it.add_after_then_move(start_it.extract());
89 flags.set_bit(
W_INVERSE, (inverted_vote > non_inverted_vote));
91 start_it.set_to_list(&cblobs);
92 if (start_it.empty())
return;
93 for (start_it.mark_cycle_pt(); !start_it.cycled_list(); start_it.forward()) {
94 c_outline_it.set_to_list(start_it.data()->out_list());
96 rej_cblob_it.add_after_then_move(start_it.extract());
110 script_id_(clone->script_id_),
111 correct(clone->correct) {
112 C_BLOB_IT start_it = blob_list;
113 C_BLOB_IT end_it = blob_list;
115 while (!end_it.at_last()) end_it.forward();
116 (
reinterpret_cast<C_BLOB_LIST*
>(&cblobs))
117 ->assign_to_sublist(&start_it, &end_it);
119 blanks = clone->blanks;
126 C_BLOB_LIST temp_blobs;
127 C_BLOB_IT temp_it(&temp_blobs);
128 temp_it.add_after_then_move(blob);
129 WERD* blob_word =
new WERD(&temp_blobs,
this);
154 int bottom = box.
bottom();
157 C_BLOB_IT it(const_cast<C_BLOB_LIST*>(&rej_cblobs));
158 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
159 TBOX dot_box = it.data()->bounding_box();
160 if ((upper_dots || dot_box.
bottom() <= top) &&
161 (lower_dots || dot_box.
top() >= bottom)) {
172 C_BLOB_IT it(const_cast<C_BLOB_LIST*>(&cblobs));
173 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
174 box += it.data()->bounding_box();
187 C_BLOB_IT cblob_it(&cblobs);
189 for (cblob_it.mark_cycle_pt(); !cblob_it.cycled_list(); cblob_it.forward())
190 cblob_it.data()->move(vec);
200 C_BLOB_IT blob_it(&cblobs);
201 C_BLOB_IT src_it(&other->cblobs);
202 C_BLOB_IT rej_cblob_it(&rej_cblobs);
203 C_BLOB_IT src_rej_it(&other->rej_cblobs);
205 while (!src_it.empty()) {
206 blob_it.add_to_end(src_it.extract());
209 while (!src_rej_it.empty()) {
210 rej_cblob_it.add_to_end(src_rej_it.extract());
211 src_rej_it.forward();
223 C_BLOB_IT c_blob_it(&cblobs);
228 c_blob_it.add_list_before(&c_blobs);
230 c_blob_it.move_to_last();
231 c_blob_it.add_list_after(&c_blobs);
233 if (!other->rej_cblobs.empty()) {
234 C_BLOB_IT rej_c_blob_it(&rej_cblobs);
235 C_BLOB_LIST new_rej_c_blobs;
239 rej_c_blob_it.add_list_before(&new_rej_c_blobs);
241 rej_c_blob_it.move_to_last();
242 rej_c_blob_it.add_list_after(&new_rej_c_blobs);
254 tprintf(
"Blanks= %d\n", blanks);
261 tprintf(
" W_NORMALIZED = %s\n",
263 tprintf(
" W_SCRIPT_HAS_XHEIGHT = %s\n",
265 tprintf(
" W_SCRIPT_IS_LATIN = %s\n",
272 tprintf(
"Rejected cblob count = %d\n", rej_cblobs.length());
273 tprintf(
"Script = %d\n", script_id_);
282 #ifndef GRAPHICS_DISABLED 284 C_BLOB_IT it = &cblobs;
285 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
286 it.data()->plot(window, colour, colour);
306 C_BLOB_IT it = &cblobs;
307 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
321 C_BLOB_IT it = &rej_cblobs;
322 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
326 #endif // GRAPHICS_DISABLED 337 new_word->blanks = blanks;
338 new_word->flags =
flags;
339 new_word->dummy = dummy;
340 new_word->correct = correct;
352 blanks = source.blanks;
353 flags = source.flags;
354 script_id_ = source.script_id_;
355 dummy = source.dummy;
356 correct = source.correct;
357 if (!cblobs.empty()) cblobs.clear();
360 if (!rej_cblobs.empty()) rej_cblobs.clear();
373 const WERD* word1 = *
reinterpret_cast<const WERD* const*
>(word1p);
374 const WERD* word2 = *
reinterpret_cast<const WERD* const*
>(word2p);
391 C_BLOB_LIST* orphan_blobs) {
392 C_BLOB_LIST current_blob_list;
393 C_BLOB_IT werd_blobs_it(¤t_blob_list);
398 C_BLOB_LIST new_werd_blobs;
399 C_BLOB_IT new_blobs_it(&new_werd_blobs);
403 C_BLOB_LIST not_found_blobs;
404 C_BLOB_IT not_found_it(¬_found_blobs);
405 not_found_it.move_to_last();
407 werd_blobs_it.move_to_first();
408 for (werd_blobs_it.mark_cycle_pt(); !werd_blobs_it.cycled_list();
409 werd_blobs_it.forward()) {
410 C_BLOB* werd_blob = werd_blobs_it.extract();
416 C_BLOB_IT all_blobs_it(all_blobs);
417 for (all_blobs_it.mark_cycle_pt(); !all_blobs_it.cycled_list();
418 all_blobs_it.forward()) {
419 C_BLOB* a_blob = all_blobs_it.data();
424 tprintf(
"Bounding box couldn't be ascertained\n");
426 if (werd_blob_box.
contains(a_blob_box) ||
431 all_blobs_it.extract();
432 new_blobs_it.add_after_then_move(a_blob);
437 not_found_it.add_after_then_move(werd_blob);
445 not_found_it.move_to_first();
446 for (not_found_it.mark_cycle_pt(); !not_found_it.cycled_list();
447 not_found_it.forward()) {
448 C_BLOB* not_found = not_found_it.data();
450 C_BLOB_IT existing_blobs_it(new_blobs_it);
451 for (existing_blobs_it.mark_cycle_pt(); !existing_blobs_it.cycled_list();
452 existing_blobs_it.forward()) {
453 C_BLOB* a_blob = existing_blobs_it.data();
459 delete not_found_it.extract();
465 C_BLOB_IT orphan_blobs_it(orphan_blobs);
466 orphan_blobs_it.move_to_last();
467 orphan_blobs_it.add_list_after(¬_found_blobs);
471 WERD* new_werd =
nullptr;
472 if (!new_werd_blobs.empty()) {
473 new_werd =
new WERD(&new_werd_blobs,
this);
477 this_list_it.add_list_after(¬_found_blobs);
485 C_BLOB_IT blob_it(&cblobs);
486 C_BLOB_IT rej_it(&rej_cblobs);
487 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
488 C_BLOB* blob = blob_it.data();
489 C_OUTLINE_IT ol_it(blob->
out_list());
490 for (ol_it.mark_cycle_pt(); !ol_it.cycled_list(); ol_it.forward()) {
495 if (ol_size < size_threshold) {
498 auto* rej_blob =
new C_BLOB(ol_it.extract());
499 rej_it.add_after_then_move(rej_blob);
502 if (blob->
out_list()->empty())
delete blob_it.extract();
509 C_BLOB_IT rej_it(&rej_cblobs);
510 for (rej_it.mark_cycle_pt(); !rej_it.empty(); rej_it.forward()) {
511 C_BLOB* blob = rej_it.extract();
512 C_OUTLINE_IT ol_it(blob->
out_list());
529 bool* make_next_word_fuzzy) {
530 bool outline_added_to_start =
false;
531 if (make_next_word_fuzzy !=
nullptr) *make_next_word_fuzzy =
false;
532 C_BLOB_IT rej_it(&rej_cblobs);
533 for (
int i = 0; i < outlines.
size(); ++i) {
535 if (outline ==
nullptr)
continue;
537 C_BLOB* target_blob = target_blobs[i];
539 if (target_blob ==
nullptr) {
540 target_blob =
new C_BLOB(outline);
542 C_BLOB_IT blob_it(&cblobs);
543 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list();
545 C_BLOB* blob = blob_it.data();
547 if (blob_box.
left() > noise_box.
left()) {
550 outline_added_to_start =
true;
552 blob_it.add_before_stay_put(target_blob);
556 if (blob_it.cycled_list()) {
557 blob_it.add_to_end(target_blob);
558 if (make_next_word_fuzzy !=
nullptr) *make_next_word_fuzzy =
true;
561 C_OUTLINE_IT ol_it(target_blob->
out_list());
562 while (i + 1 < outlines.
size() && wanted[i + 1] &&
563 target_blobs[i + 1] ==
nullptr) {
565 ol_it.add_to_end(outlines[i]);
569 C_OUTLINE_IT ol_it(target_blob->
out_list());
570 ol_it.add_to_end(outline);
574 rej_it.add_to_end(
new C_BLOB(outline));
577 return outline_added_to_start;
void GetNoiseOutlines(GenericVector< C_OUTLINE * > *outlines)
void CleanNoise(float size_threshold)
C_OUTLINE_LIST * out_list()
Special case latin for y. splitting.
bool major_overlap(const TBOX &box) const
#define FIRST_COLOUR
first rainbow colour
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
const TBOX & bounding_box() const
#define CHILD_COLOUR
colour of children
static ScrollView::Color NextColor(ScrollView::Color colour)
bool contains(const FCOORD pt) const
bool AddSelectedOutlines(const GenericVector< bool > &wanted, const GenericVector< C_BLOB * > &target_blobs, const GenericVector< C_OUTLINE * > &outlines, bool *make_next_word_fuzzy)
TBOX bounding_box() const
void copy_on(WERD *other)
void plot_rej_blobs(ScrollView *window)
double y_overlap_fraction(const TBOX &box) const
const char * string() const
DLLSYM void tprintf(const char *format,...)
#define LAST_COLOUR
last rainbow colour
void move(const ICOORD vec)
TBOX bounding_box() const
void plot(ScrollView *window, ScrollView::Color colour)
WERD * ConstructFromSingleBlob(bool bol, bool eol, C_BLOB *blob)
int word_comparator(const void *word1p, const void *word2p)
TBOX true_bounding_box() const
WERD * ConstructWerdWithNewBlobs(C_BLOB_LIST *all_blobs, C_BLOB_LIST *orphan_blobs)
bool flag(WERD_FLAGS mask) const
void operator=(const ELIST2_LINK &)
WERD & operator=(const WERD &source)
static C_BLOB * deep_copy(const C_BLOB *src)
#define ELIST2IZE(CLASSNAME)
x-height concept makes sense.
void join_on(WERD *other)
void set_flag(WERD_FLAGS mask, bool value)
C_BLOB_LIST * cblob_list()