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());
109 : flags(clone->flags),
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);
293 auto next = static_cast<ScrollView::Color>(colour + 1);
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->correct = correct;
351 blanks = source.blanks;
352 flags = source.flags;
353 script_id_ = source.script_id_;
354 correct = source.correct;
355 if (!cblobs.empty()) cblobs.clear();
358 if (!rej_cblobs.empty()) rej_cblobs.clear();
371 const WERD* word1 = *reinterpret_cast<const WERD* const*>(word1p);
372 const WERD* word2 = *reinterpret_cast<const WERD* const*>(word2p);
389 C_BLOB_LIST* orphan_blobs) {
390 C_BLOB_LIST current_blob_list;
391 C_BLOB_IT werd_blobs_it(¤t_blob_list);
396 C_BLOB_LIST new_werd_blobs;
397 C_BLOB_IT new_blobs_it(&new_werd_blobs);
401 C_BLOB_LIST not_found_blobs;
402 C_BLOB_IT not_found_it(¬_found_blobs);
403 not_found_it.move_to_last();
405 werd_blobs_it.move_to_first();
406 for (werd_blobs_it.mark_cycle_pt(); !werd_blobs_it.cycled_list();
407 werd_blobs_it.forward()) {
408 C_BLOB* werd_blob = werd_blobs_it.extract();
414 C_BLOB_IT all_blobs_it(all_blobs);
415 for (all_blobs_it.mark_cycle_pt(); !all_blobs_it.cycled_list();
416 all_blobs_it.forward()) {
417 C_BLOB* a_blob = all_blobs_it.data();
422 tprintf(
"Bounding box couldn't be ascertained\n");
424 if (werd_blob_box.
contains(a_blob_box) ||
429 all_blobs_it.extract();
430 new_blobs_it.add_after_then_move(a_blob);
435 not_found_it.add_after_then_move(werd_blob);
443 not_found_it.move_to_first();
444 for (not_found_it.mark_cycle_pt(); !not_found_it.cycled_list();
445 not_found_it.forward()) {
446 C_BLOB* not_found = not_found_it.data();
448 C_BLOB_IT existing_blobs_it(new_blobs_it);
449 for (existing_blobs_it.mark_cycle_pt(); !existing_blobs_it.cycled_list();
450 existing_blobs_it.forward()) {
451 C_BLOB* a_blob = existing_blobs_it.data();
457 delete not_found_it.extract();
463 C_BLOB_IT orphan_blobs_it(orphan_blobs);
464 orphan_blobs_it.move_to_last();
465 orphan_blobs_it.add_list_after(¬_found_blobs);
469 WERD* new_werd =
nullptr;
470 if (!new_werd_blobs.empty()) {
471 new_werd =
new WERD(&new_werd_blobs,
this);
475 this_list_it.add_list_after(¬_found_blobs);
483 C_BLOB_IT blob_it(&cblobs);
484 C_BLOB_IT rej_it(&rej_cblobs);
485 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
486 C_BLOB* blob = blob_it.data();
487 C_OUTLINE_IT ol_it(blob->
out_list());
488 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);
500 if (blob->
out_list()->empty())
delete blob_it.extract();
507 C_BLOB_IT rej_it(&rej_cblobs);
508 for (rej_it.mark_cycle_pt(); !rej_it.empty(); rej_it.forward()) {
509 C_BLOB* blob = rej_it.extract();
510 C_OUTLINE_IT ol_it(blob->
out_list());
527 bool* make_next_word_fuzzy) {
528 bool outline_added_to_start =
false;
529 if (make_next_word_fuzzy !=
nullptr) *make_next_word_fuzzy =
false;
530 C_BLOB_IT rej_it(&rej_cblobs);
531 for (
int i = 0; i < outlines.
size(); ++i) {
533 if (outline ==
nullptr)
continue;
535 C_BLOB* target_blob = target_blobs[i];
537 if (target_blob ==
nullptr) {
538 target_blob =
new C_BLOB(outline);
540 C_BLOB_IT blob_it(&cblobs);
541 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list();
543 C_BLOB* blob = blob_it.data();
545 if (blob_box.
left() > noise_box.
left()) {
548 outline_added_to_start =
true;
550 blob_it.add_before_stay_put(target_blob);
554 if (blob_it.cycled_list()) {
555 blob_it.add_to_end(target_blob);
556 if (make_next_word_fuzzy !=
nullptr) *make_next_word_fuzzy =
true;
559 C_OUTLINE_IT ol_it(target_blob->
out_list());
560 while (i + 1 < outlines.
size() && wanted[i + 1] &&
561 target_blobs[i + 1] ==
nullptr) {
563 ol_it.add_to_end(outlines[i]);
567 C_OUTLINE_IT ol_it(target_blob->
out_list());
568 ol_it.add_to_end(outline);
572 rej_it.add_to_end(
new C_BLOB(outline));
575 return outline_added_to_start;