21# include "config_auto.h"
32#define FIRST_COLOUR ScrollView::RED
33#define LAST_COLOUR ScrollView::AQUAMARINE
34#define CHILD_COLOUR ScrollView::BROWN
45WERD::WERD(C_BLOB_LIST *blob_list, uint8_t blank_count,
const char *text)
46 : blanks(blank_count), flags(0), script_id_(0), correct(text ? text :
"") {
47 C_BLOB_IT start_it = &cblobs;
48 C_BLOB_IT rej_cblob_it = &rej_cblobs;
49 C_OUTLINE_IT c_outline_it;
50 int16_t inverted_vote = 0;
51 int16_t non_inverted_vote = 0;
54 start_it.add_list_after(blob_list);
69 start_it.set_to_list(&cblobs);
70 if (start_it.empty()) {
73 for (start_it.mark_cycle_pt(); !start_it.cycled_list(); start_it.forward()) {
74 bool reject_blob =
false;
77 c_outline_it.set_to_list(start_it.data()->out_list());
79 for (c_outline_it.mark_cycle_pt(); !c_outline_it.cycled_list() && !reject_blob;
80 c_outline_it.forward()) {
81 reject_blob = c_outline_it.data()->flag(
COUT_INVERSE) != blob_inverted;
84 rej_cblob_it.add_after_then_move(start_it.extract());
94 flags.set(
W_INVERSE, (inverted_vote > non_inverted_vote));
96 start_it.set_to_list(&cblobs);
97 if (start_it.empty()) {
100 for (start_it.mark_cycle_pt(); !start_it.cycled_list(); start_it.forward()) {
101 c_outline_it.set_to_list(start_it.data()->out_list());
103 rej_cblob_it.add_after_then_move(start_it.extract());
117 : flags(clone->flags), script_id_(clone->script_id_), correct(clone->correct) {
118 C_BLOB_IT start_it = blob_list;
119 C_BLOB_IT end_it = blob_list;
121 while (!end_it.at_last()) {
124 cblobs.assign_to_sublist(&start_it, &end_it);
126 blanks = clone->blanks;
133 C_BLOB_LIST temp_blobs;
134 C_BLOB_IT temp_it(&temp_blobs);
135 temp_it.add_after_then_move(blob);
136 WERD *blob_word =
new WERD(&temp_blobs,
this);
163 int bottom = box.
bottom();
166 C_BLOB_IT it(
const_cast<C_BLOB_LIST *
>(&rej_cblobs));
167 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
168 TBOX dot_box = it.data()->bounding_box();
169 if ((upper_dots || dot_box.
bottom() <= top) && (lower_dots || dot_box.
top() >= bottom)) {
180 C_BLOB_IT it(
const_cast<C_BLOB_LIST *
>(&cblobs));
181 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
182 box += it.data()->bounding_box();
195 C_BLOB_IT cblob_it(&cblobs);
197 for (cblob_it.mark_cycle_pt(); !cblob_it.cycled_list(); cblob_it.forward()) {
198 cblob_it.data()->move(vec);
209 C_BLOB_IT blob_it(&cblobs);
210 C_BLOB_IT src_it(&other->cblobs);
211 C_BLOB_IT rej_cblob_it(&rej_cblobs);
212 C_BLOB_IT src_rej_it(&other->rej_cblobs);
214 while (!src_it.empty()) {
215 blob_it.add_to_end(src_it.extract());
218 while (!src_rej_it.empty()) {
219 rej_cblob_it.add_to_end(src_rej_it.extract());
220 src_rej_it.forward();
232 C_BLOB_IT c_blob_it(&cblobs);
237 c_blob_it.add_list_before(&c_blobs);
239 c_blob_it.move_to_last();
240 c_blob_it.add_list_after(&c_blobs);
242 if (!other->rej_cblobs.empty()) {
243 C_BLOB_IT rej_c_blob_it(&rej_cblobs);
244 C_BLOB_LIST new_rej_c_blobs;
248 rej_c_blob_it.add_list_before(&new_rej_c_blobs);
250 rej_c_blob_it.move_to_last();
251 rej_c_blob_it.add_list_after(&new_rej_c_blobs);
263 tprintf(
"Blanks= %d\n", blanks);
265 tprintf(
"Flags = %lu = 0%lo\n", flags.to_ulong(), flags.to_ulong());
268 tprintf(
" W_BOL = %s\n", flags[
W_BOL] ?
"TRUE" :
"FALSE");
269 tprintf(
" W_EOL = %s\n", flags[
W_EOL] ?
"TRUE" :
"FALSE");
277 tprintf(
"Correct= %s\n", correct.c_str());
278 tprintf(
"Rejected cblob count = %d\n", rej_cblobs.length());
279 tprintf(
"Script = %d\n", script_id_);
288#ifndef GRAPHICS_DISABLED
290 C_BLOB_IT it = &cblobs;
291 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
292 it.data()->plot(window, colour, colour);
314 C_BLOB_IT it = &cblobs;
315 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
329 C_BLOB_IT it = &rej_cblobs;
330 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
345 new_word->blanks = blanks;
346 new_word->flags = flags;
347 new_word->correct = correct;
359 blanks = source.blanks;
360 flags = source.flags;
361 script_id_ = source.script_id_;
362 correct = source.correct;
378 const WERD *word1 = *
reinterpret_cast<const WERD *
const *
>(word1p);
379 const WERD *word2 = *
reinterpret_cast<const WERD *
const *
>(word2p);
396 C_BLOB_LIST current_blob_list;
397 C_BLOB_IT werd_blobs_it(¤t_blob_list);
402 C_BLOB_LIST new_werd_blobs;
403 C_BLOB_IT new_blobs_it(&new_werd_blobs);
407 C_BLOB_LIST not_found_blobs;
408 C_BLOB_IT not_found_it(¬_found_blobs);
409 not_found_it.move_to_last();
411 werd_blobs_it.move_to_first();
412 for (werd_blobs_it.mark_cycle_pt(); !werd_blobs_it.cycled_list(); werd_blobs_it.forward()) {
413 C_BLOB *werd_blob = werd_blobs_it.extract();
419 C_BLOB_IT all_blobs_it(all_blobs);
420 for (all_blobs_it.mark_cycle_pt(); !all_blobs_it.cycled_list(); all_blobs_it.forward()) {
421 C_BLOB *a_blob = all_blobs_it.data();
426 tprintf(
"Bounding box couldn't be ascertained\n");
432 all_blobs_it.extract();
433 new_blobs_it.add_after_then_move(a_blob);
438 not_found_it.add_after_then_move(werd_blob);
446 not_found_it.move_to_first();
447 for (not_found_it.mark_cycle_pt(); !not_found_it.cycled_list(); 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();
458 delete not_found_it.extract();
464 C_BLOB_IT orphan_blobs_it(orphan_blobs);
465 orphan_blobs_it.move_to_last();
466 orphan_blobs_it.add_list_after(¬_found_blobs);
470 WERD *new_werd =
nullptr;
471 if (!new_werd_blobs.empty()) {
472 new_werd =
new WERD(&new_werd_blobs,
this);
476 this_list_it.add_list_after(¬_found_blobs);
484 C_BLOB_IT blob_it(&cblobs);
485 C_BLOB_IT rej_it(&rej_cblobs);
486 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
487 C_BLOB *blob = blob_it.data();
488 C_OUTLINE_IT ol_it(blob->
out_list());
489 for (ol_it.mark_cycle_pt(); !ol_it.cycled_list(); ol_it.forward()) {
493 if (ol_size < size_threshold) {
496 auto *rej_blob =
new C_BLOB(ol_it.extract());
497 rej_it.add_after_then_move(rej_blob);
501 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());
513 outlines->push_back(ol_it.extract());
527 const std::vector<C_BLOB *> &target_blobs,
528 const std::vector<C_OUTLINE *> &outlines,
529 bool *make_next_word_fuzzy) {
530 bool outline_added_to_start =
false;
531 if (make_next_word_fuzzy !=
nullptr) {
532 *make_next_word_fuzzy =
false;
534 C_BLOB_IT rej_it(&rej_cblobs);
535 for (
unsigned i = 0;
i < outlines.size(); ++
i) {
537 if (outline ==
nullptr) {
541 C_BLOB *target_blob = target_blobs[
i];
543 if (target_blob ==
nullptr) {
544 target_blob =
new C_BLOB(outline);
546 C_BLOB_IT blob_it(&cblobs);
547 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
548 C_BLOB *blob = blob_it.data();
550 if (blob_box.
left() > noise_box.
left()) {
553 outline_added_to_start =
true;
555 blob_it.add_before_stay_put(target_blob);
559 if (blob_it.cycled_list()) {
560 blob_it.add_to_end(target_blob);
561 if (make_next_word_fuzzy !=
nullptr) {
562 *make_next_word_fuzzy =
true;
566 C_OUTLINE_IT ol_it(target_blob->
out_list());
567 while (
i + 1 < outlines.size() && wanted[
i + 1] && target_blobs[
i + 1] ==
nullptr) {
569 ol_it.add_to_end(outlines[
i]);
573 C_OUTLINE_IT ol_it(target_blob->
out_list());
574 ol_it.add_to_end(outline);
578 rej_it.add_to_end(
new C_BLOB(outline));
581 return outline_added_to_start;
#define FIRST_COLOUR
first rainbow colour
#define CHILD_COLOUR
colour of children
#define LAST_COLOUR
last rainbow colour
@ W_SEGMENTED
correctly segmented
@ W_INVERSE
white on black
@ W_SCRIPT_HAS_XHEIGHT
x-height concept makes sense.
@ W_SCRIPT_IS_LATIN
Special case latin for y. splitting.
@ W_DONT_CHOP
fixed pitch chopped
@ W_REP_CHAR
repeated character
@ W_FUZZY_NON
fuzzy nonspace
void tprintf(const char *format,...)
int word_comparator(const void *word1p, const void *word2p)
const TBOX & bounding_box() const
TDimension height() const
double y_overlap_fraction(const TBOX &box) const
TDimension bottom() const
bool contains(const FCOORD pt) const
bool major_overlap(const TBOX &box) const
C_OUTLINE_LIST * out_list()
TBOX bounding_box() const
static C_BLOB * deep_copy(const C_BLOB *src)
WERD * ConstructWerdWithNewBlobs(C_BLOB_LIST *all_blobs, C_BLOB_LIST *orphan_blobs)
bool flag(WERD_FLAGS mask) const
void plot_rej_blobs(ScrollView *window)
void GetNoiseOutlines(std::vector< C_OUTLINE * > *outlines)
void set_flag(WERD_FLAGS mask, bool value)
void copy_on(WERD *other)
static ScrollView::Color NextColor(ScrollView::Color colour)
WERD * ConstructFromSingleBlob(bool bol, bool eol, C_BLOB *blob)
TBOX bounding_box() const
void CleanNoise(float size_threshold)
bool AddSelectedOutlines(const std::vector< bool > &wanted, const std::vector< C_BLOB * > &target_blobs, const std::vector< C_OUTLINE * > &outlines, bool *make_next_word_fuzzy)
TBOX true_bounding_box() const
void join_on(WERD *other)
void move(const ICOORD vec)
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
void plot(ScrollView *window, ScrollView::Color colour)
WERD & operator=(const WERD &source)
C_BLOB_LIST * cblob_list()
void operator=(const ELIST2_LINK &)