/********************************************************************** * junk_worst_seam * * Delete the worst seam from the queue because it is full. **********************************************************************/ void junk_worst_seam(SEAM_QUEUE seams, SEAM *new_seam, float new_priority) { SEAM *seam; float priority; HeapPopWorst(seams, &priority, &seam); if (priority > new_priority) { delete_seam(seam); /*get rid of it */ HeapPush (seams, new_priority, (char *) new_seam); } else { delete_seam(new_seam); HeapPush (seams, priority, (char *) seam); } }
/********************************************************************** * attempt_blob_chop * * Try to split the this blob after this one. Check to make sure that * it was successful. **********************************************************************/ SEAM *attempt_blob_chop(TWERD *word, INT32 blob_number, SEAMS seam_list) { TBLOB *blob; TBLOB *other_blob; SEAM *seam; TBLOB *last_blob; TBLOB *next_blob; INT16 x; if (first_pass) chops_attempted1++; else chops_attempted2++; last_blob = NULL; blob = word->blobs; for (x = 0; x < blob_number; x++) { last_blob = blob; blob = blob->next; } next_blob = blob->next; if (repair_unchopped_blobs) preserve_outline_tree (blob->outlines); other_blob = newblob (); /* Make new blob */ other_blob->next = blob->next; other_blob->outlines = NULL; blob->next = other_blob; seam = pick_good_seam (blob); if (chop_debug) { if (seam != NULL) { print_seam ("Good seam picked=", seam); } else cprintf ("\n** no seam picked *** \n"); } if (seam) { apply_seam(blob, other_blob, seam); } if ((seam == NULL) || (blob->outlines == NULL) || (other_blob->outlines == NULL) || total_containment (blob, other_blob) || check_blob (other_blob) || !(check_seam_order (blob, seam) && check_seam_order (other_blob, seam)) || any_shared_split_points (seam_list, seam) || !test_insert_seam(seam_list, blob_number, blob, word->blobs)) { blob->next = next_blob; if (seam) { undo_seam(blob, other_blob, seam); delete_seam(seam); #ifndef GRAPHICS_DISABLED if (chop_debug) { display_blob(blob, Red); cprintf ("\n** seam being removed ** \n"); } #endif } else { oldblob(other_blob); } if (repair_unchopped_blobs) restore_outline_tree (blob->outlines); return (NULL); } return (seam); }
SEAM *Wordrec::attempt_blob_chop(TWERD *word, inT32 blob_number, bool italic_blob, SEAMS seam_list) { TBLOB *blob; TBLOB *other_blob; SEAM *seam; TBLOB *last_blob; TBLOB *next_blob; inT16 x; last_blob = NULL; blob = word->blobs; for (x = 0; x < blob_number; x++) { last_blob = blob; blob = blob->next; } next_blob = blob->next; if (repair_unchopped_blobs) preserve_outline_tree (blob->outlines); other_blob = new TBLOB; /* Make new blob */ other_blob->next = blob->next; other_blob->outlines = NULL; blob->next = other_blob; seam = pick_good_seam(blob); if (seam == NULL && word->latin_script) { // If the blob can simply be divided into outlines, then do that. TPOINT location; if (divisible_blob(blob, italic_blob, &location)) { seam = new_seam(0.0f, location, NULL, NULL, NULL); } } if (chop_debug) { if (seam != NULL) { print_seam ("Good seam picked=", seam); } else cprintf ("\n** no seam picked *** \n"); } if (seam) { apply_seam(blob, other_blob, italic_blob, seam); } if ((seam == NULL) || (blob->outlines == NULL) || (other_blob->outlines == NULL) || total_containment (blob, other_blob) || check_blob (other_blob) || !(check_seam_order (blob, seam) && check_seam_order (other_blob, seam)) || any_shared_split_points (seam_list, seam) || !test_insert_seam(seam_list, blob_number, blob, word->blobs)) { blob->next = next_blob; if (seam) { undo_seam(blob, other_blob, seam); delete_seam(seam); #ifndef GRAPHICS_DISABLED if (chop_debug) { if (chop_debug >2) display_blob(blob, Red); cprintf ("\n** seam being removed ** \n"); } #endif } else { delete other_blob; } if (repair_unchopped_blobs) restore_outline_tree (blob->outlines); return (NULL); } return (seam); }
/********************************************************************** * choose_best_seam * * Choose the best seam that can be created by assembling this a * collection of splits. A queue of all the possible seams is * maintained. Each new split received is placed in that queue with * its partial priority value. These values in the seam queue are * evaluated and combined until a good enough seam is found. If no * further good seams are being found then this function returns to the * caller, who will send more splits. If this function is called with * a split of NULL, then no further splits can be supplied by the * caller. **********************************************************************/ void choose_best_seam(SEAM_QUEUE seam_queue, SEAM_PILE *seam_pile, SPLIT *split, PRIORITY priority, SEAM **seam_result, TBLOB *blob) { SEAM *seam; TPOINT topleft; TPOINT botright; char str[80]; float my_priority; /* Add seam of split */ my_priority = priority; if (split != NULL) { seam = new_seam (my_priority, (split->point1->pos.x + split->point1->pos.x) / 2, split, NULL, NULL); if (chop_debug > 1) print_seam ("Partial priority ", seam); add_seam_to_queue (seam_queue, seam, (float) my_priority); if (my_priority > chop_good_split) return; } blob_bounding_box(blob, &topleft, &botright); /* Queue loop */ while (pop_next_seam (seam_queue, seam, my_priority)) { /* Set full priority */ my_priority = seam_priority (seam, topleft.x, botright.x); if (chop_debug) { sprintf (str, "Full my_priority %0.0f, ", my_priority); print_seam(str, seam); } if ((*seam_result == NULL || /* Replace answer */ (*seam_result)->priority > my_priority) && my_priority < chop_ok_split) { /* No crossing */ if (constrained_split (seam->split1, blob)) { delete_seam(*seam_result); clone_seam(*seam_result, seam); (*seam_result)->priority = my_priority; } else { delete_seam(seam); seam = NULL; my_priority = BAD_PRIORITY; } } if (my_priority < chop_good_split) { if (seam) delete_seam(seam); return; /* Made good answer */ } if (seam) { /* Combine with others */ if (array_count (*seam_pile) < MAX_NUM_SEAMS /*|| tessedit_truncate_chopper==0 */ ) { combine_seam(seam_queue, *seam_pile, seam); *seam_pile = array_push (*seam_pile, seam); } else delete_seam(seam); } my_priority = best_seam_priority (seam_queue); if ((my_priority > chop_ok_split) || (my_priority > chop_good_split && split)) return; } }
/** * @name free_seam_list * * Free all the seams that have been allocated in this list. Reclaim * the memory for each of the splits as well. */ void free_seam_list(SEAMS seam_list) { int x; array_loop(seam_list, x) delete_seam(array_value (seam_list, x)); array_free(seam_list); }