00001
00020 #include "mfcpch.h"
00021 #ifdef __UNIX__
00022 #include <assert.h>
00023 #endif
00024 #include "stderr.h"
00025 #include "blobbox.h"
00026 #include "lmedsq.h"
00027 #include "statistc.h"
00028 #include "drawtord.h"
00029 #include "tovars.h"
00030 #include "topitch.h"
00031 #include "fpchop.h"
00032 #include "notdll.h"
00033
00034 #define EXTERN
00035
00038 EXTERN INT_VAR (textord_fp_chop_error, 2,
00039 "Max allowed bending of chop cells");
00040 EXTERN double_VAR (textord_fp_chop_snap, 0.5,
00041 "Max distance of chop pt from vertex");
00044 ELISTIZE (OUTLINE_FRAG) ELISTIZE (C_OUTLINE_FRAG)
00045
00046
00047
00048
00054 ROW *fixed_pitch_words(
00055 TO_ROW *row,
00056 FCOORD rotation
00057 ) {
00058 BOOL8 bol;
00059 UINT8 blanks;
00060 UINT8 new_blanks;
00061 INT16 chop_coord;
00062 INT16 prev_chop_coord;
00063 INT16 rep_left;
00064 ROW *real_row;
00065 OUTLINE_LIST left_outlines;
00066 OUTLINE_LIST right_outlines;
00067 C_OUTLINE_LIST left_coutlines;
00068 C_OUTLINE_LIST right_coutlines;
00069 PBLOB_LIST blobs;
00070 C_BLOB_LIST cblobs;
00071 PBLOB_IT blob_it = &blobs;
00072 C_BLOB_IT cblob_it = &cblobs;
00073 WERD_LIST words;
00074 WERD_IT word_it = &words;
00075
00076 WERD_IT rep_it = &row->rep_words;
00077 WERD *word;
00078 INT32 xstarts[2];
00079 double coeffs[3];
00080 INT32 prev_x;
00081
00082 BLOBNBOX_IT box_it = row->blob_list ();
00083
00084 ICOORDELT_IT cell_it = &row->char_cells;
00085
00086 #ifndef GRAPHICS_DISABLED
00087 if (textord_show_page_cuts && to_win != NO_WINDOW) {
00088 plot_row_cells (to_win, RED, row, 0, &row->char_cells);
00089 }
00090 #endif
00091
00092 prev_x = -MAX_INT16;
00093 bol = TRUE;
00094 blanks = 0;
00095 if (rep_it.empty ())
00096 rep_left = MAX_INT16;
00097 else
00098 rep_left = rep_it.data ()->bounding_box ().left ();
00099 if (box_it.empty ())
00100 return NULL;
00101 xstarts[0] = box_it.data ()->bounding_box ().left ();
00102 if (rep_left < xstarts[0]) {
00103 xstarts[0] = rep_left;
00104 }
00105 if (cell_it.empty () || row->char_cells.singleton ()) {
00106 tprintf ("Row without enough char cells!\n");
00107 tprintf ("Leftmost blob is at (%d,%d)\n",
00108 box_it.data ()->bounding_box ().left (),
00109 box_it.data ()->bounding_box ().bottom ());
00110 return NULL;
00111 }
00112 ASSERT_HOST (!cell_it.empty () && !row->char_cells.singleton ());
00113 prev_chop_coord = cell_it.data ()->x ();
00114 word = NULL;
00115 while (rep_left < cell_it.data ()->x ()) {
00116 word = add_repeated_word (&rep_it, rep_left, prev_chop_coord,
00117 blanks, row->fixed_pitch, &word_it);
00118 }
00119 cell_it.mark_cycle_pt ();
00120 if (prev_chop_coord >= cell_it.data ()->x ())
00121 cell_it.forward ();
00122 for (; !cell_it.cycled_list (); cell_it.forward ()) {
00123 chop_coord = cell_it.data ()->x ();
00124 while (!box_it.empty ()
00125 && box_it.data ()->bounding_box ().left () <= chop_coord) {
00126 if (box_it.data ()->bounding_box ().right () > prev_x)
00127 prev_x = box_it.data ()->bounding_box ().right ();
00128 split_to_blob (box_it.extract (), chop_coord,
00129 textord_fp_chop_error + 0.5f,
00130 &left_outlines, &left_coutlines,
00131 &right_outlines, &right_coutlines);
00132 box_it.forward ();
00133 while (!box_it.empty ()
00134 && box_it.data ()->blob () == NULL
00135 && box_it.data ()->cblob () == NULL) {
00136 delete box_it.extract ();
00137 box_it.forward ();
00138 }
00139 }
00140 if ((!right_outlines.empty () || !right_coutlines.empty ())
00141 && left_outlines.empty () && left_coutlines.empty ())
00142 split_to_blob (NULL, chop_coord,
00143 textord_fp_chop_error + 0.5f,
00144 &left_outlines, &left_coutlines,
00145 &right_outlines, &right_coutlines);
00146 if (!left_outlines.empty ())
00147 blob_it.add_after_then_move (new PBLOB (&left_outlines));
00148 else if (!left_coutlines.empty ())
00149 cblob_it.add_after_then_move (new C_BLOB (&left_coutlines));
00150 else {
00151 if (rep_left < chop_coord) {
00152 if (rep_left > prev_chop_coord)
00153 new_blanks = (UINT8) floor ((rep_left - prev_chop_coord)
00154 / row->fixed_pitch + 0.5);
00155 else
00156 new_blanks = 0;
00157 }
00158 else {
00159 if (chop_coord > prev_chop_coord)
00160 new_blanks = (UINT8) floor ((chop_coord - prev_chop_coord)
00161 / row->fixed_pitch + 0.5);
00162 else
00163 new_blanks = 0;
00164 }
00165 if (!blob_it.empty () || !cblob_it.empty ()) {
00166 if (blanks < 1 && word != NULL && !word->flag (W_REP_CHAR))
00167 blanks = 1;
00168 if (!blob_it.empty ()) {
00169
00170 word = new WERD (&blobs, blanks, NULL);
00171 blob_it.set_to_list (&blobs);
00172 }
00173 else {
00174 word = new WERD (&cblobs, blanks, NULL);
00175 cblob_it.set_to_list (&cblobs);
00176 }
00177 word->set_flag (W_DONT_CHOP, TRUE);
00178 word_it.add_after_then_move (word);
00179 if (bol) {
00180 word->set_flag (W_BOL, TRUE);
00181 bol = FALSE;
00182 }
00183 blanks = new_blanks;
00184 }
00185 else
00186 blanks += new_blanks;
00187 while (rep_left < chop_coord) {
00188 word = add_repeated_word (&rep_it, rep_left, prev_chop_coord,
00189 blanks, row->fixed_pitch, &word_it);
00190 }
00191 }
00192 if (prev_chop_coord < chop_coord)
00193 prev_chop_coord = chop_coord;
00194 }
00195 if (!blob_it.empty () || !cblob_it.empty ()) {
00196 if (!blob_it.empty ())
00197
00198 word = new WERD (&blobs, blanks, NULL);
00199 else
00200 word = new WERD (&cblobs, blanks, NULL);
00201 word->set_flag (W_DONT_CHOP, TRUE);
00202 word_it.add_after_then_move (word);
00203 if (bol)
00204 word->set_flag (W_BOL, TRUE);
00205 }
00206 ASSERT_HOST (word != NULL);
00207 while (!rep_it.empty ()) {
00208 add_repeated_word (&rep_it, rep_left, prev_chop_coord,
00209 blanks, row->fixed_pitch, &word_it);
00210 }
00211
00212 word_it.data ()->set_flag (W_EOL, TRUE);
00213 if (prev_chop_coord > prev_x)
00214 prev_x = prev_chop_coord;
00215 xstarts[1] = prev_x + 1;
00216 coeffs[0] = 0;
00217 coeffs[1] = row->line_m ();
00218 coeffs[2] = row->line_c ();
00219 real_row = new ROW (row, (INT16) row->kern_size, (INT16) row->space_size);
00220 word_it.set_to_list (real_row->word_list ());
00221
00222 word_it.add_list_after (&words);
00223 real_row->recalc_bounding_box ();
00224 return real_row;
00225 }
00226
00227
00228
00234 WERD *add_repeated_word(
00235 WERD_IT *rep_it,
00236 INT16 &rep_left,
00237 INT16 &prev_chop_coord,
00238 UINT8 &blanks,
00239 float pitch,
00240 WERD_IT *word_it
00241 ) {
00242 WERD *word;
00243 INT16 new_blanks;
00244
00245 if (rep_left > prev_chop_coord) {
00246 new_blanks = (UINT8) floor ((rep_left - prev_chop_coord) / pitch + 0.5);
00247 blanks += new_blanks;
00248 }
00249 word = rep_it->extract ();
00250 prev_chop_coord = word->bounding_box ().right ();
00251 word_it->add_after_then_move (word);
00252 word->set_blanks (blanks);
00253 rep_it->forward ();
00254 if (rep_it->empty ())
00255 rep_left = MAX_INT16;
00256 else
00257 rep_left = rep_it->data ()->bounding_box ().left ();
00258 blanks = 0;
00259 return word;
00260 }
00261
00262
00263
00270 void split_to_blob(
00271 BLOBNBOX *blob,
00272 INT16 chop_coord,
00273 float pitch_error,
00274 OUTLINE_LIST *left_outlines,
00275 C_OUTLINE_LIST *left_coutlines,
00276 OUTLINE_LIST *right_outlines,
00277 C_OUTLINE_LIST *right_coutlines) {
00278 PBLOB *real_blob;
00279 C_BLOB *real_cblob;
00280
00281 if (blob != NULL) {
00282 real_blob = blob->blob ();
00283 real_cblob = blob->cblob ();
00284 }
00285 else {
00286 real_blob = NULL;
00287 real_cblob = NULL;
00288 }
00289 if (!right_outlines->empty () || real_blob != NULL)
00290 fixed_chop_blob(real_blob,
00291 chop_coord,
00292 pitch_error,
00293 left_outlines,
00294 right_outlines);
00295 else if (!right_coutlines->empty () || real_cblob != NULL)
00296 fixed_chop_cblob(real_cblob,
00297 chop_coord,
00298 pitch_error,
00299 left_coutlines,
00300 right_coutlines);
00301 if (blob != NULL)
00302 delete blob;
00303 }
00304
00305
00306
00313 void fixed_chop_blob(
00314 PBLOB *blob,
00315 INT16 chop_coord,
00316 float pitch_error,
00317 OUTLINE_LIST *left_outlines,
00318 OUTLINE_LIST *right_outlines
00319 ) {
00320 OUTLINE *old_right;
00321 OUTLINE_LIST new_outlines;
00322
00323 OUTLINE_IT left_it = left_outlines;
00324
00325 OUTLINE_IT right_it = right_outlines;
00326 OUTLINE_IT new_it = &new_outlines;
00327 OUTLINE_IT blob_it;
00328
00329 if (!right_it.empty ()) {
00330 while (!right_it.empty ()) {
00331 old_right = right_it.extract ();
00332 right_it.forward ();
00333 fixed_split_outline(old_right,
00334 chop_coord,
00335 pitch_error,
00336 &left_it,
00337 &new_it);
00338 }
00339 right_it.add_list_before (&new_outlines);
00340 }
00341 if (blob != NULL) {
00342 blob_it.set_to_list (blob->out_list ());
00343 for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00344 blob_it.forward ())
00345 fixed_split_outline (blob_it.extract (), chop_coord, pitch_error,
00346 &left_it, &right_it);
00347 delete blob;
00348 }
00349 }
00350
00351
00352
00359 void fixed_split_outline(
00360 OUTLINE *srcline,
00361 INT16 chop_coord,
00362 float pitch_error,
00363 OUTLINE_IT *left_it,
00364 OUTLINE_IT *right_it
00365 ) {
00366 OUTLINE *child;
00367 BOX srcbox;
00368 OUTLINE_LIST left_ch;
00369 OUTLINE_LIST right_ch;
00370 OUTLINE_FRAG_LIST left_frags;
00371 OUTLINE_FRAG_LIST right_frags;;
00372 OUTLINE_IT left_ch_it = &left_ch;
00373
00374 OUTLINE_IT right_ch_it = &right_ch;
00375
00376 OUTLINE_IT child_it = srcline->child ();
00377
00378 srcbox = srcline->bounding_box ();
00379
00380 if (srcbox.left () + srcbox.right () <= chop_coord * 2
00381
00382 && srcbox.right () < chop_coord + pitch_error)
00383
00384 left_it->add_after_then_move (srcline);
00385 else if (srcbox.left () + srcbox.right () > chop_coord * 2
00386 && srcbox.left () > chop_coord - pitch_error)
00387
00388 right_it->add_before_stay_put (srcline);
00389 else {
00390
00391 if (fixed_chop_outline (srcline, chop_coord, pitch_error,
00392 &left_frags, &right_frags)) {
00393 for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00394 child_it.forward ()) {
00395 child = child_it.extract ();
00396 srcbox = child->bounding_box ();
00397 if (srcbox.right () < chop_coord)
00398 left_ch_it.add_after_then_move (child);
00399 else if (srcbox.left () > chop_coord)
00400 right_ch_it.add_after_then_move (child);
00401 else {
00402 if (fixed_chop_outline (child, chop_coord, pitch_error,
00403 &left_frags, &right_frags))
00404 delete child;
00405 else {
00406 if (srcbox.left () + srcbox.right () <= chop_coord * 2)
00407 left_ch_it.add_after_then_move (child);
00408 else
00409 right_ch_it.add_after_then_move (child);
00410 }
00411 }
00412 }
00413 close_chopped_fragments(&left_frags, &left_ch, left_it);
00414 close_chopped_fragments(&right_frags, &right_ch, right_it);
00415 ASSERT_HOST (left_ch.empty () && right_ch.empty ());
00416
00417 delete srcline;
00418 }
00419 else {
00420 if (srcbox.left () + srcbox.right () <= chop_coord * 2)
00421
00422 left_it->add_after_then_move (srcline);
00423 else
00424 right_it->add_before_stay_put (srcline);
00425 }
00426 }
00427 }
00428
00429
00430
00439 BOOL8 fixed_chop_outline(
00440 OUTLINE *srcline,
00441 INT16 chop_coord,
00442 float pitch_error,
00443 OUTLINE_FRAG_LIST *left_frags,
00444 OUTLINE_FRAG_LIST *right_frags
00445 ) {
00446 BOOL8 not_first;
00447 BOOL8 test_valid;
00448 float left_edge;
00449 FCOORD chop_pos;
00450 float chop_starty;
00451 POLYPT *startpt;
00452
00453 POLYPT_IT poly_it = srcline->polypts ();
00454 POLYPT_IT head_it;
00455 POLYPT_IT tail_it;
00456 POLYPT_IT test_tail;
00457
00458 left_edge = poly_it.data ()->pos.x ();
00459 tail_it = poly_it;
00460 for (poly_it.mark_cycle_pt (); !poly_it.cycled_list (); poly_it.forward ()) {
00461 if (poly_it.data ()->pos.x () < left_edge) {
00462 left_edge = poly_it.data ()->pos.x ();
00463 tail_it = poly_it;
00464 }
00465 }
00466 if (left_edge >= chop_coord - pitch_error)
00467 return FALSE;
00468
00469 startpt = tail_it.data ();
00470 not_first = FALSE;
00471 head_it = tail_it;
00472 chop_starty = tail_it.data ()->pos.y ();
00473 do {
00474 test_valid = FALSE;
00475 do {
00476 tail_it.forward ();
00477 if (test_valid
00478 && tail_it.data ()->pos.x () >= chop_coord
00479 && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () <=
00480 chop_coord) {
00481 chop_pos = find_chop_coords (&tail_it, chop_coord);
00482 if (chop_pos.y () >= chop_starty)
00483 test_valid = FALSE;
00484 else {
00485 tail_it = test_tail;
00486 break;
00487 }
00488 }
00489 if (tail_it.data ()->pos.x () <= chop_coord
00490 && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () >=
00491 chop_coord) {
00492 chop_pos = find_chop_coords (&tail_it, chop_coord);
00493 chop_starty = chop_pos.y ();
00494 test_tail = tail_it;
00495 test_valid = TRUE;
00496 if (tail_it.data ()->vec.x () == 0
00497 && tail_it.data ()->vec.y () < 0)
00498 break;
00499 }
00500 }
00501 while (tail_it.data () != startpt
00502 && tail_it.data ()->pos.x () < chop_coord + pitch_error);
00503
00504 if (tail_it.data () == startpt) {
00505 if (not_first)
00506 break;
00507 else
00508 return FALSE;
00509 }
00510 while (tail_it.data ()->pos.x () > chop_coord)
00511 tail_it.backward ();
00512 if (head_it.data () == tail_it.data ())
00513 insert_extra_pt(&tail_it);
00514 insert_chop_pt(&tail_it, chop_coord);
00515 if (not_first) {
00516 save_chop_fragment(&head_it, &tail_it, left_frags);
00517 }
00518 else {
00519 tail_it.forward ();
00520 head_it = tail_it;
00521 }
00522 test_valid = FALSE;
00523 do {
00524 tail_it.forward ();
00525 if (test_valid
00526 && tail_it.data ()->pos.x () <= chop_coord
00527 && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () >=
00528 chop_coord) {
00529 chop_pos = find_chop_coords (&tail_it, chop_coord);
00530 if (chop_pos.y () <= chop_starty)
00531 test_valid = FALSE;
00532 else {
00533 tail_it = test_tail;
00534 break;
00535 }
00536 }
00537 if (tail_it.data ()->pos.x () >= chop_coord
00538 && tail_it.data ()->pos.x () + tail_it.data ()->vec.x () <=
00539 chop_coord) {
00540 chop_pos = find_chop_coords (&tail_it, chop_coord);
00541 chop_starty = chop_pos.y ();
00542 test_tail = tail_it;
00543 test_valid = TRUE;
00544 if (tail_it.data ()->vec.x () == 0
00545 && tail_it.data ()->vec.y () > 0)
00546 break;
00547 }
00548 }
00549 while (tail_it.data () != startpt
00550 && tail_it.data ()->pos.x () > chop_coord - pitch_error);
00551 while (tail_it.data ()->pos.x () < chop_coord)
00552 tail_it.backward ();
00553 if (head_it.data () == tail_it.data ())
00554 insert_extra_pt(&tail_it);
00555 insert_chop_pt(&tail_it, chop_coord);
00556 save_chop_fragment(&head_it, &tail_it, right_frags);
00557 not_first = TRUE;
00558 }
00559 while (tail_it.data () != startpt);
00560 startpt = head_it.data_relative (-1);
00561 while (tail_it.data () != startpt)
00562 tail_it.forward ();
00563 save_chop_fragment(&head_it, &tail_it, left_frags);
00564 return TRUE;
00565 }
00566
00567
00568
00574 void save_chop_fragment(
00575 POLYPT_IT *head_it,
00576 POLYPT_IT *tail_it,
00577 OUTLINE_FRAG_LIST *frags
00578 ) {
00579 OUTLINE_FRAG *head;
00580 OUTLINE_FRAG *tail;
00581 float tail_y;
00582
00583 tail_y = tail_it->data ()->pos.y ();
00584 head = new OUTLINE_FRAG (head_it, tail_it);
00585 tail = new OUTLINE_FRAG (head, tail_y);
00586 head->other_end = tail;
00587 add_frag_to_list(head, frags);
00588 add_frag_to_list(tail, frags);
00589 head_it->forward ();
00590 tail_it->forward ();
00591 }
00592
00593
00594
00600 OUTLINE_FRAG::OUTLINE_FRAG(
00601 POLYPT_IT *head_it,
00602 POLYPT_IT *tail_it
00603 ) {
00604 ycoord = head_it->data ()->pos.y ();
00605 other_end = NULL;
00606 polypts.assign_to_sublist (head_it, tail_it);
00607 }
00608
00609
00610 OUTLINE_FRAG::OUTLINE_FRAG(
00611 OUTLINE_FRAG *head,
00612 float tail_y) {
00613 ycoord = tail_y;
00614 other_end = head;
00615 }
00616
00617
00618
00625 void add_frag_to_list(
00626 OUTLINE_FRAG *frag,
00627 OUTLINE_FRAG_LIST *frags
00628 ) {
00629
00630 OUTLINE_FRAG_IT frag_it = frags;
00631
00632 if (!frags->empty ()) {
00633 for (frag_it.mark_cycle_pt (); !frag_it.cycled_list ();
00634 frag_it.forward ()) {
00635 if (frag_it.data ()->ycoord >= frag->ycoord) {
00636 frag_it.add_before_then_move (frag);
00637 return;
00638 }
00639 }
00640 }
00641 frag_it.add_to_end (frag);
00642 }
00643
00644
00645
00653 void insert_chop_pt(
00654 POLYPT_IT *it,
00655 INT16 chop_coord
00656 ) {
00657 POLYPT *prev_pt;
00658 POLYPT *chop_pt;
00659 FCOORD chop_pos;
00660 FCOORD chop_vec;
00661
00662 prev_pt = it->data ();
00663 if (prev_pt->pos.x () + textord_fp_chop_snap >= chop_coord
00664 && prev_pt->pos.x () - textord_fp_chop_snap <= chop_coord) {
00665 chop_pt = new POLYPT (prev_pt->pos, prev_pt->vec);
00666 }
00667 else {
00668 chop_pos = FCOORD (chop_coord, prev_pt->pos.y ()
00669 + prev_pt->vec.y () * (chop_coord -
00670 prev_pt->pos.x ()) /
00671 prev_pt->vec.x ());
00672 chop_vec = it->data_relative (1)->pos - chop_pos;
00673 chop_pt = new POLYPT (chop_pos, chop_vec);
00674 it->add_after_then_move (chop_pt);
00675 chop_pt = new POLYPT (chop_pos, chop_vec);
00676 }
00677 it->add_after_stay_put (chop_pt);
00678 }
00679
00680
00681
00689 FCOORD find_chop_coords(
00690 POLYPT_IT *it,
00691 INT16 chop_coord
00692 ) {
00693 POLYPT *prev_pt;
00694 FCOORD chop_pos;
00695
00696 prev_pt = it->data ();
00697 if (prev_pt->pos.x () + textord_fp_chop_snap >= chop_coord
00698 && prev_pt->pos.x () - textord_fp_chop_snap <= chop_coord) {
00699 chop_pos = prev_pt->pos;
00700 }
00701 else {
00702 chop_pos = FCOORD (chop_coord, prev_pt->pos.y ()
00703 + prev_pt->vec.y () * (chop_coord -
00704 prev_pt->pos.x ()) /
00705 prev_pt->vec.x ());
00706 }
00707 return chop_pos;
00708 }
00709
00710
00711
00717 void insert_extra_pt(
00718 POLYPT_IT *it
00719 ) {
00720 POLYPT *prev_pt;
00721 POLYPT *chop_pt;
00722 FCOORD chop_pos;
00723 FCOORD chop_vec;
00724
00725 prev_pt = it->data ();
00726 if (it->data_relative (1)->pos.y () > it->data_relative (-1)->pos.y ()) {
00727 chop_pos = prev_pt->pos + FCOORD (0.0f,
00728 static_cast<float>(textord_fp_chop_snap));
00729 }
00730 else {
00731 chop_pos = prev_pt->pos - FCOORD (0.0f,
00732 static_cast<float>(textord_fp_chop_snap));
00733 }
00734 chop_vec = it->data_relative (1)->pos - chop_pos;
00735 prev_pt->vec = chop_pos - prev_pt->pos;
00736 chop_pt = new POLYPT (chop_pos, chop_vec);
00737 it->add_after_then_move (chop_pt);
00738 }
00739
00740
00741
00748 void close_chopped_fragments(
00749 OUTLINE_FRAG_LIST *frags,
00750 OUTLINE_LIST *children,
00751 OUTLINE_IT *dest_it
00752 ) {
00753
00754 OUTLINE_FRAG_IT frag_it = frags;
00755 OUTLINE_FRAG *bottom_frag;
00756 OUTLINE_FRAG *top_frag;
00757 OUTLINE *outline;
00758 OUTLINE *child;
00759 OUTLINE_IT child_it = children;
00760 OUTLINE_IT olchild_it;
00761 POLYPT_IT poly_it;
00762
00763 while (!frag_it.empty ()) {
00764 frag_it.move_to_first ();
00765
00766 bottom_frag = frag_it.extract ();
00767 frag_it.forward ();
00768
00769 top_frag = frag_it.extract ();
00770 while (top_frag->other_end != bottom_frag) {
00771 do {
00772 frag_it.forward ();
00773 }
00774
00775 while (frag_it.data () != top_frag->other_end);
00776 join_chopped_fragments(bottom_frag, top_frag);
00777 delete top_frag;
00778 delete frag_it.extract ();
00779 frag_it.forward ();
00780 top_frag = frag_it.extract ();
00781 }
00782 join_chopped_fragments(bottom_frag, top_frag);
00783 if (bottom_frag->polypts.empty ())
00784 poly_it.set_to_list (&top_frag->polypts);
00785 else
00786 poly_it.set_to_list (&bottom_frag->polypts);
00787 outline = new OUTLINE (&poly_it);
00788 olchild_it.set_to_list (outline->child ());
00789 for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00790 child_it.forward ()) {
00791 child = child_it.data ();
00792 if (*child < *outline)
00793 olchild_it.add_to_end (child_it.extract ());
00794 }
00795 dest_it->add_after_then_move (outline);
00796 }
00797 while (!child_it.empty ()) {
00798 dest_it->add_after_then_move (child_it.extract ());
00799 child_it.forward ();
00800 }
00801 }
00802
00803
00804
00811 void join_chopped_fragments(
00812 OUTLINE_FRAG *bottom,
00813 OUTLINE_FRAG *top
00814 ) {
00815 POLYPT_IT master_it;
00816 POLYPT_IT slave_it;
00817 POLYPT *cutpt;
00818 POLYPT *nextpt;
00819
00820 if (bottom->polypts.empty ()) {
00821 master_it.set_to_list (&bottom->other_end->polypts);
00822 cutpt = master_it.data_relative (-1);
00823 ASSERT_HOST (!top->polypts.empty ());
00824 slave_it.set_to_list (&top->polypts);
00825 nextpt = slave_it.data ();
00826 if (bottom->other_end != top) {
00827 master_it.move_to_last ();
00828 master_it.add_list_after (&top->polypts);
00829 }
00830 }
00831 else {
00832 master_it.set_to_list (&bottom->polypts);
00833 ASSERT_HOST (top->polypts.empty ());
00834 slave_it.set_to_list (&top->other_end->polypts);
00835 cutpt = slave_it.data_relative (-1);
00836 nextpt = master_it.data ();
00837 if (bottom->other_end != top)
00838 master_it.add_list_before (&top->other_end->polypts);
00839 }
00840 cutpt->vec = nextpt->pos - cutpt->pos;
00841 }
00842
00843
00844
00851 void fixed_chop_cblob(
00852 C_BLOB *blob,
00853 INT16 chop_coord,
00854 float pitch_error,
00855 C_OUTLINE_LIST *left_outlines,
00856 C_OUTLINE_LIST *right_outlines
00857 ) {
00858 C_OUTLINE *old_right;
00859 C_OUTLINE_LIST new_outlines;
00860
00861 C_OUTLINE_IT left_it = left_outlines;
00862
00863 C_OUTLINE_IT right_it = right_outlines;
00864 C_OUTLINE_IT new_it = &new_outlines;
00865 C_OUTLINE_IT blob_it;
00866
00867 if (!right_it.empty ()) {
00868 while (!right_it.empty ()) {
00869 old_right = right_it.extract ();
00870 right_it.forward ();
00871 fixed_split_coutline(old_right,
00872 chop_coord,
00873 pitch_error,
00874 &left_it,
00875 &new_it);
00876 }
00877 right_it.add_list_before (&new_outlines);
00878 }
00879 if (blob != NULL) {
00880 blob_it.set_to_list (blob->out_list ());
00881 for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
00882 blob_it.forward ())
00883 fixed_split_coutline (blob_it.extract (), chop_coord, pitch_error,
00884 &left_it, &right_it);
00885 delete blob;
00886 }
00887 }
00888
00889
00890
00897 void fixed_split_coutline(
00898 C_OUTLINE *srcline,
00899 INT16 chop_coord,
00900 float pitch_error,
00901 C_OUTLINE_IT *left_it,
00902 C_OUTLINE_IT *right_it
00903 ) {
00904 C_OUTLINE *child;
00905 BOX srcbox;
00906 C_OUTLINE_LIST left_ch;
00907 C_OUTLINE_LIST right_ch;
00908 C_OUTLINE_FRAG_LIST left_frags;
00909 C_OUTLINE_FRAG_LIST right_frags;;
00910 C_OUTLINE_IT left_ch_it = &left_ch;
00911
00912 C_OUTLINE_IT right_ch_it = &right_ch;
00913
00914 C_OUTLINE_IT child_it = srcline->child ();
00915
00916 srcbox = srcline->bounding_box ();
00917
00918 if (srcbox.left () + srcbox.right () <= chop_coord * 2
00919
00920 && srcbox.right () < chop_coord + pitch_error)
00921
00922 left_it->add_after_then_move (srcline);
00923 else if (srcbox.left () + srcbox.right () > chop_coord * 2
00924 && srcbox.left () > chop_coord - pitch_error)
00925
00926 right_it->add_before_stay_put (srcline);
00927 else {
00928
00929 if (fixed_chop_coutline (srcline, chop_coord, pitch_error,
00930 &left_frags, &right_frags)) {
00931 for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
00932 child_it.forward ()) {
00933 child = child_it.extract ();
00934 srcbox = child->bounding_box ();
00935 if (srcbox.right () < chop_coord)
00936 left_ch_it.add_after_then_move (child);
00937 else if (srcbox.left () > chop_coord)
00938 right_ch_it.add_after_then_move (child);
00939 else {
00940 if (fixed_chop_coutline (child, chop_coord, pitch_error,
00941 &left_frags, &right_frags))
00942 delete child;
00943 else {
00944 if (srcbox.left () + srcbox.right () <= chop_coord * 2)
00945 left_ch_it.add_after_then_move (child);
00946 else
00947 right_ch_it.add_after_then_move (child);
00948 }
00949 }
00950 }
00951 close_chopped_cfragments(&left_frags, &left_ch, pitch_error, left_it);
00952 close_chopped_cfragments(&right_frags, &right_ch, pitch_error, right_it);
00953 ASSERT_HOST (left_ch.empty () && right_ch.empty ());
00954
00955 delete srcline;
00956 }
00957 else {
00958 if (srcbox.left () + srcbox.right () <= chop_coord * 2)
00959
00960 left_it->add_after_then_move (srcline);
00961 else
00962 right_it->add_before_stay_put (srcline);
00963 }
00964 }
00965 }
00966
00967
00968
00980 BOOL8 fixed_chop_coutline(
00981 C_OUTLINE *srcline,
00982 INT16 chop_coord,
00983 float pitch_error,
00984 C_OUTLINE_FRAG_LIST *left_frags,
00985 C_OUTLINE_FRAG_LIST *right_frags
00986 ) {
00987 BOOL8 first_frag;
00988 BOOL8 anticlock;
00989 INT16 left_edge;
00990 INT16 startindex;
00991 INT32 length;
00992 INT16 stepindex;
00993 INT16 head_index;
00994 ICOORD head_pos;
00995 INT16 tail_index;
00996 ICOORD tail_pos;
00997 ICOORD pos;
00998 INT16 first_index = 0;
00999 ICOORD first_pos;
01000
01001 length = srcline->pathlength ();
01002 pos = srcline->start_pos ();
01003 anticlock = srcline->turn_direction () > 0;
01004 left_edge = pos.x ();
01005 tail_index = 0;
01006 tail_pos = pos;
01007 for (stepindex = 0; stepindex < length; stepindex++) {
01008 if (pos.x () < left_edge) {
01009 left_edge = pos.x ();
01010 tail_index = stepindex;
01011 tail_pos = pos;
01012 }
01013 pos += srcline->step (stepindex);
01014 }
01015 if (left_edge >= chop_coord - pitch_error)
01016 return FALSE;
01017
01018 startindex = tail_index;
01019 first_frag = TRUE;
01020 head_index = tail_index;
01021 head_pos = tail_pos;
01022 do {
01023 do {
01024 tail_pos += srcline->step (tail_index);
01025 tail_index++;
01026 if (tail_index == length)
01027 tail_index = 0;
01028 }
01029 while (tail_pos.x () != chop_coord && tail_index != startindex);
01030 if (tail_index == startindex) {
01031 if (first_frag)
01032 return FALSE;
01033 else
01034 break;
01035 }
01036
01037 ASSERT_HOST (head_index != tail_index);
01038
01039 if (!first_frag) {
01040 save_chop_cfragment(head_index,
01041 head_pos,
01042 tail_index,
01043 tail_pos,
01044 srcline,
01045 left_frags);
01046 }
01047 else {
01048 first_index = tail_index;
01049 first_pos = tail_pos;
01050 first_frag = FALSE;
01051 }
01052 while (srcline->step (tail_index).x () == 0) {
01053 tail_pos += srcline->step (tail_index);
01054 tail_index++;
01055 if (tail_index == length)
01056 tail_index = 0;
01057 }
01058 head_index = tail_index;
01059 head_pos = tail_pos;
01060 while (srcline->step (tail_index).x () > 0) {
01061 do {
01062 tail_pos += srcline->step (tail_index);
01063 tail_index++;
01064 if (tail_index == length)
01065 tail_index = 0;
01066 }
01067 while (tail_pos.x () != chop_coord);
01068
01069 ASSERT_HOST (head_index != tail_index);
01070
01071 save_chop_cfragment(head_index,
01072 head_pos,
01073 tail_index,
01074 tail_pos,
01075 srcline,
01076 right_frags);
01077 while (srcline->step (tail_index).x () == 0) {
01078 tail_pos += srcline->step (tail_index);
01079 tail_index++;
01080 if (tail_index == length)
01081 tail_index = 0;
01082 }
01083 head_index = tail_index;
01084 head_pos = tail_pos;
01085 }
01086 }
01087 while (tail_index != startindex);
01088 save_chop_cfragment(head_index,
01089 head_pos,
01090 first_index,
01091 first_pos,
01092 srcline,
01093 left_frags);
01094 return TRUE;
01095 }
01096
01097
01098
01105 INT16 next_anti_left_seg(
01106 C_OUTLINE *srcline,
01107 INT16 tail_index,
01108 INT16 startindex,
01109 INT32 length,
01110 INT16 chop_coord,
01111 float pitch_error,
01112 ICOORD *tail_pos
01113 ) {
01114 BOOL8 test_valid;
01115 INT16 chop_starty;
01116 INT16 test_index;
01117 ICOORD test_pos;
01118 ICOORD prev_step;
01119
01120 test_valid = FALSE;
01121 chop_starty = -MAX_INT16;
01122 test_index = tail_index;
01123 do {
01124 *tail_pos += srcline->step (tail_index);
01125 prev_step = srcline->step (tail_index);
01126 tail_index++;
01127 if (tail_index >= length)
01128 tail_index = 0;
01129 if (test_valid && tail_pos->x () == chop_coord && prev_step.x () < 0) {
01130 if (tail_pos->y () >= chop_starty) {
01131 chop_starty = -MAX_INT16;
01132 test_valid = FALSE;
01133 }
01134 else {
01135 *tail_pos = test_pos;
01136 tail_index = test_index;
01137 break;
01138 }
01139 }
01140 if (tail_pos->x () == chop_coord
01141 && srcline->step (tail_index).x () > 0
01142 && tail_pos->y () > chop_starty) {
01143 chop_starty = tail_pos->y ();
01144 test_index = tail_index;
01145 test_pos = *tail_pos;
01146 test_valid = TRUE;
01147 }
01148 else if (tail_pos->x () == chop_coord
01149 && srcline->step (tail_index).y () < 0
01150 && prev_step.x () > 0 && tail_pos->y () > chop_starty)
01151 break;
01152 }
01153 while (tail_index != startindex
01154 && tail_pos->x () < chop_coord + pitch_error);
01155 return tail_index;
01156 }
01157
01158
01159
01166 INT16 next_anti_right_seg(
01167 C_OUTLINE *srcline,
01168 INT16 tail_index,
01169 INT16 startindex,
01170 INT32 length,
01171 INT16 chop_coord,
01172 float pitch_error,
01173 ICOORD *tail_pos
01174 ) {
01175 BOOL8 test_valid;
01176 INT16 chop_starty;
01177 INT16 test_index;
01178 ICOORD test_pos;
01179 ICOORD prev_step;
01180
01181 test_valid = FALSE;
01182 chop_starty = MAX_INT16;
01183 test_index = tail_index;
01184 do {
01185
01186 *tail_pos += srcline->step (tail_index);
01187 prev_step = srcline->step (tail_index);
01188 tail_index++;
01189 if (tail_index >= length)
01190 tail_index = 0;
01191 if (test_valid && tail_pos->x () == chop_coord && prev_step.x () > 0) {
01192 if (tail_pos->y () <= chop_starty) {
01193 chop_starty = MAX_INT16;
01194 test_valid = FALSE;
01195 }
01196 else {
01197 *tail_pos = test_pos;
01198 tail_index = test_index;
01199 break;
01200 }
01201 }
01202 if (tail_pos->x () == chop_coord
01203 && srcline->step (tail_index).x () < 0
01204 && tail_pos->y () < chop_starty) {
01205 chop_starty = tail_pos->y ();
01206 test_index = tail_index;
01207 test_pos = *tail_pos;
01208 test_valid = TRUE;
01209 }
01210 else if (tail_pos->x () == chop_coord
01211 && srcline->step (tail_index).y () > 0
01212 && prev_step.x () < 0 && tail_pos->y () < chop_starty)
01213 break;
01214 }
01215 while (tail_index != startindex
01216 && tail_pos->x () > chop_coord - pitch_error);
01217 return tail_index;
01218 }
01219
01220
01221
01228 INT16 next_clock_left_seg(
01229 C_OUTLINE *srcline,
01230 INT16 tail_index,
01231 INT16 startindex,
01232 INT32 length,
01233 INT16 chop_coord,
01234 float pitch_error,
01235 ICOORD *tail_pos
01236 ) {
01237 BOOL8 test_valid;
01238 INT16 chop_starty;
01239 INT16 test_index;
01240 ICOORD test_pos;
01241 ICOORD prev_step;
01242
01243 test_valid = FALSE;
01244 chop_starty = MAX_INT16;
01245 test_index = tail_index;
01246 do {
01247 *tail_pos += srcline->step (tail_index);
01248 prev_step = srcline->step (tail_index);
01249 tail_index++;
01250 if (tail_index >= length)
01251 tail_index = 0;
01252 if (test_valid && tail_pos->x () == chop_coord && prev_step.x () < 0) {
01253 if (tail_pos->y () <= chop_starty) {
01254 chop_starty = MAX_INT16;
01255 test_valid = FALSE;
01256 }
01257 else {
01258 *tail_pos = test_pos;
01259 tail_index = test_index;
01260 break;
01261 }
01262 }
01263 if (tail_pos->x () == chop_coord
01264 && srcline->step (tail_index).x () > 0
01265 && tail_pos->y () < chop_starty) {
01266 chop_starty = tail_pos->y ();
01267 test_index = tail_index;
01268 test_pos = *tail_pos;
01269 test_valid = TRUE;
01270 }
01271 else if (tail_pos->x () == chop_coord
01272 && srcline->step (tail_index).y () > 0
01273 && prev_step.x () > 0 && tail_pos->y () < chop_starty)
01274 break;
01275 }
01276 while (tail_index != startindex
01277 && tail_pos->x () < chop_coord + pitch_error);
01278 return tail_index;
01279 }
01280
01281
01282
01289 INT16 next_clock_right_seg(
01290 C_OUTLINE *srcline,
01291 INT16 tail_index,
01292 INT16 startindex,
01293 INT32 length,
01294 INT16 chop_coord,
01295 float pitch_error,
01296 ICOORD *tail_pos
01297 ) {
01298 BOOL8 test_valid;
01299 INT16 chop_starty;
01300 INT16 test_index;
01301 ICOORD test_pos;
01302 ICOORD prev_step;
01303
01304 test_valid = FALSE;
01305 chop_starty = MAX_INT16;
01306 test_index = tail_index;
01307 do {
01308
01309 *tail_pos += srcline->step (tail_index);
01310 prev_step = srcline->step (tail_index);
01311 tail_index++;
01312 if (tail_index >= length)
01313 tail_index = 0;
01314 if (test_valid && tail_pos->x () == chop_coord && prev_step.x () > 0) {
01315 if (tail_pos->y () >= chop_starty) {
01316 chop_starty = MAX_INT16;
01317 test_valid = FALSE;
01318 }
01319 else {
01320 *tail_pos = test_pos;
01321 tail_index = test_index;
01322 break;
01323 }
01324 }
01325 if (tail_pos->x () == chop_coord
01326 && srcline->step (tail_index).x () < 0
01327 && tail_pos->y () > chop_starty) {
01328 chop_starty = tail_pos->y ();
01329 test_index = tail_index;
01330 test_pos = *tail_pos;
01331 test_valid = TRUE;
01332 }
01333 else if (tail_pos->x () == chop_coord
01334 && srcline->step (tail_index).y () < 0
01335 && prev_step.x () < 0 && tail_pos->y () > chop_starty)
01336 break;
01337 }
01338 while (tail_index != startindex
01339 && tail_pos->x () > chop_coord - pitch_error);
01340 return tail_index;
01341 }
01342
01343
01344
01350 void save_chop_cfragment(
01351 INT16 head_index,
01352 ICOORD head_pos,
01353 INT16 tail_index,
01354 ICOORD tail_pos,
01355 C_OUTLINE *srcline,
01356 C_OUTLINE_FRAG_LIST *frags
01357 ) {
01358 INT16 jump;
01359 INT16 stepcount;
01360 C_OUTLINE_FRAG *head;
01361 C_OUTLINE_FRAG *tail;
01362 INT16 tail_y;
01363
01364 ASSERT_HOST (tail_pos.x () == head_pos.x ());
01365 ASSERT_HOST (tail_index != head_index);
01366 stepcount = tail_index - head_index;
01367 if (stepcount < 0)
01368 stepcount += srcline->pathlength ();
01369 jump = tail_pos.y () - head_pos.y ();
01370 if (jump < 0)
01371 jump = -jump;
01372 if (jump == stepcount)
01373 return;
01374 tail_y = tail_pos.y ();
01375 head = new C_OUTLINE_FRAG (head_pos, tail_pos, srcline,
01376 head_index, tail_index);
01377 tail = new C_OUTLINE_FRAG (head, tail_y);
01378 head->other_end = tail;
01379 add_frag_to_list(head, frags);
01380 add_frag_to_list(tail, frags);
01381 }
01382
01383
01384
01390 C_OUTLINE_FRAG::C_OUTLINE_FRAG(
01391 ICOORD start_pt,
01392 ICOORD end_pt,
01393 C_OUTLINE *outline,
01394 INT16 start_index,
01395 INT16 end_index) {
01396 start = start_pt;
01397 end = end_pt;
01398 ycoord = start_pt.y ();
01399 stepcount = end_index - start_index;
01400 if (stepcount < 0)
01401 stepcount += outline->pathlength ();
01402 ASSERT_HOST (stepcount > 0);
01403 steps = new DIR128[stepcount];
01404 if (end_index > start_index) {
01405 for (int i = start_index; i < end_index; ++i)
01406 steps[i - start_index] = outline->step_dir(i);
01407 }
01408 else {
01409 int len = outline->pathlength();
01410 int i = start_index;
01411 for (; i < len; ++i)
01412 steps[i - start_index] = outline->step_dir(i);
01413 if (end_index > 0)
01414 for (; i < end_index + len; ++i)
01415 steps[i - start_index] = outline->step_dir(i - len);
01416 }
01417 other_end = NULL;
01418 delete close();
01419 }
01420
01421
01422
01426 C_OUTLINE_FRAG::C_OUTLINE_FRAG(
01427 C_OUTLINE_FRAG *head,
01428 INT16 tail_y) {
01429 ycoord = tail_y;
01430 other_end = head;
01431 start = head->start;
01432 end = head->end;
01433 steps = NULL;
01434 stepcount = 0;
01435 }
01436
01437
01438
01445 void add_frag_to_list(
01446 C_OUTLINE_FRAG *frag,
01447 C_OUTLINE_FRAG_LIST *frags
01448 ) {
01449
01450 C_OUTLINE_FRAG_IT frag_it = frags;
01451
01452 if (!frags->empty ()) {
01453 for (frag_it.mark_cycle_pt (); !frag_it.cycled_list ();
01454 frag_it.forward ()) {
01455 if (frag_it.data ()->ycoord > frag->ycoord
01456 || frag_it.data ()->ycoord == frag->ycoord
01457 && frag->other_end->ycoord < frag->ycoord) {
01458 frag_it.add_before_then_move (frag);
01459 return;
01460 }
01461 }
01462 }
01463 frag_it.add_to_end (frag);
01464 }
01465
01466
01467
01474 void close_chopped_cfragments(
01475 C_OUTLINE_FRAG_LIST *frags,
01476 C_OUTLINE_LIST *children,
01477 float pitch_error,
01478 C_OUTLINE_IT *dest_it
01479 ) {
01480
01481 C_OUTLINE_FRAG_IT frag_it = frags;
01482 C_OUTLINE_FRAG *bottom_frag;
01483 C_OUTLINE_FRAG *top_frag;
01484 C_OUTLINE *outline;
01485 C_OUTLINE *child;
01486 C_OUTLINE_IT child_it = children;
01487 C_OUTLINE_IT olchild_it;
01488
01489 while (!frag_it.empty ()) {
01490 frag_it.move_to_first ();
01491
01492 bottom_frag = frag_it.extract ();
01493 frag_it.forward ();
01494 top_frag = frag_it.data ();
01495 if (bottom_frag->steps == 0 && top_frag->steps == 0
01496 || bottom_frag->steps != 0 && top_frag->steps != 0) {
01497 if (frag_it.data_relative (1)->ycoord == top_frag->ycoord)
01498 frag_it.forward ();
01499 }
01500 top_frag = frag_it.extract ();
01501 if (top_frag->other_end != bottom_frag) {
01502 outline = join_chopped_fragments (bottom_frag, top_frag);
01503 ASSERT_HOST (outline == NULL);
01504 }
01505 else {
01506 outline = join_chopped_fragments (bottom_frag, top_frag);
01507 ASSERT_HOST (outline != NULL);
01508 olchild_it.set_to_list (outline->child ());
01509 for (child_it.mark_cycle_pt (); !child_it.cycled_list ();
01510 child_it.forward ()) {
01511 child = child_it.data ();
01512 if (*child < *outline)
01513 olchild_it.add_to_end (child_it.extract ());
01514 }
01515 if (outline->bounding_box ().width () > pitch_error)
01516 dest_it->add_after_then_move (outline);
01517 else
01518 delete outline;
01519 }
01520 }
01521 while (!child_it.empty ()) {
01522 dest_it->add_after_then_move (child_it.extract ());
01523 child_it.forward ();
01524 }
01525 }
01526
01527
01528
01535 C_OUTLINE *join_chopped_fragments(
01536 C_OUTLINE_FRAG *bottom,
01537 C_OUTLINE_FRAG *top
01538 ) {
01539 C_OUTLINE *outline;
01540
01541 if (bottom->other_end == top) {
01542 if (bottom->steps == 0)
01543 outline = top->close ();
01544 else
01545 outline = bottom->close ();
01546 delete top;
01547 delete bottom;
01548 return outline;
01549 }
01550 if (bottom->steps == 0) {
01551 ASSERT_HOST (top->steps != 0);
01552 join_segments (bottom->other_end, top);
01553 }
01554 else {
01555 ASSERT_HOST (top->steps == 0);
01556 join_segments (top->other_end, bottom);
01557 }
01558 top->other_end->other_end = bottom->other_end;
01559 bottom->other_end->other_end = top->other_end;
01560 delete bottom;
01561 delete top;
01562 return NULL;
01563 }
01564
01565
01566
01573 void join_segments(
01574 C_OUTLINE_FRAG *bottom,
01575 C_OUTLINE_FRAG *top
01576 ) {
01577 DIR128 *steps;
01578 INT32 stepcount;
01579 INT16 fake_count;
01580 DIR128 fake_step;
01581
01582 ASSERT_HOST (bottom->end.x () == top->start.x ());
01583 fake_count = top->start.y () - bottom->end.y ();
01584 if (fake_count < 0) {
01585 fake_count = -fake_count;
01586 fake_step = 32;
01587 }
01588 else
01589 fake_step = 96;
01590
01591 stepcount = bottom->stepcount + fake_count + top->stepcount;
01592 steps = new DIR128[stepcount];
01593 memmove (steps, bottom->steps, bottom->stepcount);
01594 memset (steps + bottom->stepcount, fake_step.get_dir(), fake_count);
01595 memmove (steps + bottom->stepcount + fake_count, top->steps,
01596 top->stepcount);
01597 delete [] bottom->steps;
01598 bottom->steps = steps;
01599 bottom->stepcount = stepcount;
01600 bottom->end = top->end;
01601 bottom->other_end->end = top->end;
01602 }
01603
01604
01605
01611 C_OUTLINE *C_OUTLINE_FRAG::close() {
01612 DIR128 *new_steps;
01613 INT32 new_stepcount;
01614 INT16 fake_count;
01615 DIR128 fake_step;
01616
01617 ASSERT_HOST (start.x () == end.x ());
01618 fake_count = start.y () - end.y ();
01619 if (fake_count < 0) {
01620 fake_count = -fake_count;
01621 fake_step = 32;
01622 }
01623 else
01624 fake_step = 96;
01625
01626 new_stepcount = stepcount + fake_count;
01627 new_steps = new DIR128[new_stepcount];
01628 memmove(new_steps, steps, stepcount);
01629 memset (new_steps + stepcount, fake_step.get_dir(), fake_count);
01630 C_OUTLINE* result = new C_OUTLINE (start, new_steps, new_stepcount);
01631 delete [] new_steps;
01632 return result;
01633 }
01634
01635
01636
01642 C_OUTLINE_FRAG & C_OUTLINE_FRAG::operator= (
01643 const C_OUTLINE_FRAG & src
01644 ) {
01645 if (steps != NULL)
01646 delete [] steps;
01647
01648 stepcount = src.stepcount;
01649 steps = new DIR128[stepcount];
01650 memmove (steps, src.steps, stepcount);
01651 start = src.start;
01652 end = src.end;
01653 ycoord = src.ycoord;
01654 return *this;
01655 }