Tesseract
3.02
|
00001 /********************************************************************** 00002 * File: coutln.c (Formerly coutline.c) 00003 * Description: Code for the C_OUTLINE class. 00004 * Author: Ray Smith 00005 * Created: Mon Oct 07 16:01:57 BST 1991 00006 * 00007 * (C) Copyright 1991, Hewlett-Packard Ltd. 00008 ** Licensed under the Apache License, Version 2.0 (the "License"); 00009 ** you may not use this file except in compliance with the License. 00010 ** You may obtain a copy of the License at 00011 ** http://www.apache.org/licenses/LICENSE-2.0 00012 ** Unless required by applicable law or agreed to in writing, software 00013 ** distributed under the License is distributed on an "AS IS" BASIS, 00014 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 ** See the License for the specific language governing permissions and 00016 ** limitations under the License. 00017 * 00018 **********************************************************************/ 00019 00020 #include "mfcpch.h" 00021 #include <string.h> 00022 #ifdef __UNIX__ 00023 #include <assert.h> 00024 #endif 00025 #include "coutln.h" 00026 #include "allheaders.h" 00027 00028 // Include automatically generated configuration file if running autoconf. 00029 #ifdef HAVE_CONFIG_H 00030 #include "config_auto.h" 00031 #endif 00032 00033 ELISTIZE (C_OUTLINE) 00034 ICOORD C_OUTLINE::step_coords[4] = { 00035 ICOORD (-1, 0), ICOORD (0, -1), ICOORD (1, 0), ICOORD (0, 1) 00036 }; 00037 00038 /********************************************************************** 00039 * C_OUTLINE::C_OUTLINE 00040 * 00041 * Constructor to build a C_OUTLINE from a CRACKEDGE LOOP. 00042 **********************************************************************/ 00043 00044 C_OUTLINE::C_OUTLINE ( 00045 //constructor 00046 CRACKEDGE * startpt, //outline to convert 00047 ICOORD bot_left, //bounding box 00048 ICOORD top_right, inT16 length //length of loop 00049 ):box (bot_left, top_right), start (startpt->pos) { 00050 inT16 stepindex; //index to step 00051 CRACKEDGE *edgept; //current point 00052 00053 stepcount = length; //no of steps 00054 if (length == 0) { 00055 steps = NULL; 00056 return; 00057 } 00058 //get memory 00059 steps = (uinT8 *) alloc_mem (step_mem()); 00060 memset(steps, 0, step_mem()); 00061 edgept = startpt; 00062 00063 for (stepindex = 0; stepindex < length; stepindex++) { 00064 //set compact step 00065 set_step (stepindex, edgept->stepdir); 00066 edgept = edgept->next; 00067 } 00068 } 00069 00070 00071 /********************************************************************** 00072 * C_OUTLINE::C_OUTLINE 00073 * 00074 * Constructor to build a C_OUTLINE from a C_OUTLINE_FRAG. 00075 **********************************************************************/ 00076 C_OUTLINE::C_OUTLINE ( 00077 //constructor 00078 //steps to copy 00079 ICOORD startpt, DIR128 * new_steps, 00080 inT16 length //length of loop 00081 ):start (startpt) { 00082 inT8 dirdiff; //direction difference 00083 DIR128 prevdir; //previous direction 00084 DIR128 dir; //current direction 00085 DIR128 lastdir; //dir of last step 00086 TBOX new_box; //easy bounding 00087 inT16 stepindex; //index to step 00088 inT16 srcindex; //source steps 00089 ICOORD pos; //current position 00090 00091 pos = startpt; 00092 stepcount = length; //no of steps 00093 //get memory 00094 steps = (uinT8 *) alloc_mem (step_mem()); 00095 memset(steps, 0, step_mem()); 00096 00097 lastdir = new_steps[length - 1]; 00098 prevdir = lastdir; 00099 for (stepindex = 0, srcindex = 0; srcindex < length; 00100 stepindex++, srcindex++) { 00101 new_box = TBOX (pos, pos); 00102 box += new_box; 00103 //copy steps 00104 dir = new_steps[srcindex]; 00105 set_step(stepindex, dir); 00106 dirdiff = dir - prevdir; 00107 pos += step (stepindex); 00108 if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) { 00109 stepindex -= 2; //cancel there-and-back 00110 prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir; 00111 } 00112 else 00113 prevdir = dir; 00114 } 00115 ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ()); 00116 do { 00117 dirdiff = step_dir (stepindex - 1) - step_dir (0); 00118 if (dirdiff == 64 || dirdiff == -64) { 00119 start += step (0); 00120 stepindex -= 2; //cancel there-and-back 00121 for (int i = 0; i < stepindex; ++i) 00122 set_step(i, step_dir(i + 1)); 00123 } 00124 } 00125 while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64)); 00126 stepcount = stepindex; 00127 ASSERT_HOST (stepcount >= 4); 00128 } 00129 00130 /********************************************************************** 00131 * C_OUTLINE::C_OUTLINE 00132 * 00133 * Constructor to build a C_OUTLINE from a rotation of a C_OUTLINE. 00134 **********************************************************************/ 00135 00136 C_OUTLINE::C_OUTLINE( //constructor 00137 C_OUTLINE *srcline, //outline to 00138 FCOORD rotation //rotate 00139 ) { 00140 TBOX new_box; //easy bounding 00141 inT16 stepindex; //index to step 00142 inT16 dirdiff; //direction change 00143 ICOORD pos; //current position 00144 ICOORD prevpos; //previous dest point 00145 00146 ICOORD destpos; //destination point 00147 inT16 destindex; //index to step 00148 DIR128 dir; //coded direction 00149 uinT8 new_step; 00150 00151 stepcount = srcline->stepcount * 2; 00152 if (stepcount == 0) { 00153 steps = NULL; 00154 box = srcline->box; 00155 box.rotate(rotation); 00156 return; 00157 } 00158 //get memory 00159 steps = (uinT8 *) alloc_mem (step_mem()); 00160 memset(steps, 0, step_mem()); 00161 00162 for (int iteration = 0; iteration < 2; ++iteration) { 00163 DIR128 round1 = iteration == 0 ? 32 : 0; 00164 DIR128 round2 = iteration != 0 ? 32 : 0; 00165 pos = srcline->start; 00166 prevpos = pos; 00167 prevpos.rotate (rotation); 00168 start = prevpos; 00169 box = TBOX (start, start); 00170 destindex = 0; 00171 for (stepindex = 0; stepindex < srcline->stepcount; stepindex++) { 00172 pos += srcline->step (stepindex); 00173 destpos = pos; 00174 destpos.rotate (rotation); 00175 // printf("%i %i %i %i ", destpos.x(), destpos.y(), pos.x(), pos.y()); 00176 while (destpos.x () != prevpos.x () || destpos.y () != prevpos.y ()) { 00177 dir = DIR128 (FCOORD (destpos - prevpos)); 00178 dir += 64; //turn to step style 00179 new_step = dir.get_dir (); 00180 // printf(" %i\n", new_step); 00181 if (new_step & 31) { 00182 set_step(destindex++, dir + round1); 00183 prevpos += step(destindex - 1); 00184 if (destindex < 2 00185 || ((dirdiff = 00186 step_dir (destindex - 1) - step_dir (destindex - 2)) != 00187 -64 && dirdiff != 64)) { 00188 set_step(destindex++, dir + round2); 00189 prevpos += step(destindex - 1); 00190 } else { 00191 prevpos -= step(destindex - 1); 00192 destindex--; 00193 prevpos -= step(destindex - 1); 00194 set_step(destindex - 1, dir + round2); 00195 prevpos += step(destindex - 1); 00196 } 00197 } 00198 else { 00199 set_step(destindex++, dir); 00200 prevpos += step(destindex - 1); 00201 } 00202 while (destindex >= 2 && 00203 ((dirdiff = 00204 step_dir (destindex - 1) - step_dir (destindex - 2)) == -64 || 00205 dirdiff == 64)) { 00206 prevpos -= step(destindex - 1); 00207 prevpos -= step(destindex - 2); 00208 destindex -= 2; // Forget u turn 00209 } 00210 //ASSERT_HOST(prevpos.x() == destpos.x() && prevpos.y() == destpos.y()); 00211 new_box = TBOX (destpos, destpos); 00212 box += new_box; 00213 } 00214 } 00215 ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ()); 00216 dirdiff = step_dir (destindex - 1) - step_dir (0); 00217 while ((dirdiff == 64 || dirdiff == -64) && destindex > 1) { 00218 start += step (0); 00219 destindex -= 2; 00220 for (int i = 0; i < destindex; ++i) 00221 set_step(i, step_dir(i + 1)); 00222 dirdiff = step_dir (destindex - 1) - step_dir (0); 00223 } 00224 if (destindex >= 4) 00225 break; 00226 } 00227 ASSERT_HOST(destindex <= stepcount); 00228 stepcount = destindex; 00229 destpos = start; 00230 for (stepindex = 0; stepindex < stepcount; stepindex++) { 00231 destpos += step (stepindex); 00232 } 00233 ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ()); 00234 } 00235 00236 // Build a fake outline, given just a bounding box and append to the list. 00237 void C_OUTLINE::FakeOutline(const TBOX& box, C_OUTLINE_LIST* outlines) { 00238 C_OUTLINE_IT ol_it(outlines); 00239 // Make a C_OUTLINE from the bounds. This is a bit of a hack, 00240 // as there is no outline, just a bounding box, but it works nicely. 00241 CRACKEDGE start; 00242 start.pos = box.topleft(); 00243 C_OUTLINE* outline = new C_OUTLINE(&start, box.topleft(), box.botright(), 0); 00244 ol_it.add_to_end(outline); 00245 } 00246 00247 /********************************************************************** 00248 * C_OUTLINE::area 00249 * 00250 * Compute the area of the outline. 00251 **********************************************************************/ 00252 00253 inT32 C_OUTLINE::area() { //winding number 00254 int stepindex; //current step 00255 inT32 total_steps; //steps to do 00256 inT32 total; //total area 00257 ICOORD pos; //position of point 00258 ICOORD next_step; //step to next pix 00259 C_OUTLINE_IT it = child (); 00260 00261 pos = start_pos (); 00262 total_steps = pathlength (); 00263 total = 0; 00264 for (stepindex = 0; stepindex < total_steps; stepindex++) { 00265 //all intersected 00266 next_step = step (stepindex); 00267 if (next_step.x () < 0) 00268 total += pos.y (); 00269 else if (next_step.x () > 0) 00270 total -= pos.y (); 00271 pos += next_step; 00272 } 00273 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) 00274 total += it.data ()->area ();//add areas of children 00275 00276 return total; 00277 } 00278 00279 /********************************************************************** 00280 * C_OUTLINE::perimeter 00281 * 00282 * Compute the perimeter of the outline and its first level children. 00283 **********************************************************************/ 00284 00285 inT32 C_OUTLINE::perimeter() { 00286 inT32 total_steps; // Return value. 00287 C_OUTLINE_IT it = child(); 00288 00289 total_steps = pathlength(); 00290 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) 00291 total_steps += it.data()->pathlength(); // Add perimeters of children. 00292 00293 return total_steps; 00294 } 00295 00296 00297 /********************************************************************** 00298 * C_OUTLINE::outer_area 00299 * 00300 * Compute the area of the outline. 00301 **********************************************************************/ 00302 00303 inT32 C_OUTLINE::outer_area() { //winding number 00304 int stepindex; //current step 00305 inT32 total_steps; //steps to do 00306 inT32 total; //total area 00307 ICOORD pos; //position of point 00308 ICOORD next_step; //step to next pix 00309 00310 pos = start_pos (); 00311 total_steps = pathlength (); 00312 if (total_steps == 0) 00313 return box.area(); 00314 total = 0; 00315 for (stepindex = 0; stepindex < total_steps; stepindex++) { 00316 //all intersected 00317 next_step = step (stepindex); 00318 if (next_step.x () < 0) 00319 total += pos.y (); 00320 else if (next_step.x () > 0) 00321 total -= pos.y (); 00322 pos += next_step; 00323 } 00324 00325 return total; 00326 } 00327 00328 00329 /********************************************************************** 00330 * C_OUTLINE::count_transitions 00331 * 00332 * Compute the number of x and y maxes and mins in the outline. 00333 **********************************************************************/ 00334 00335 inT32 C_OUTLINE::count_transitions( //winding number 00336 inT32 threshold //on size 00337 ) { 00338 BOOL8 first_was_max_x; //what was first 00339 BOOL8 first_was_max_y; 00340 BOOL8 looking_for_max_x; //what is next 00341 BOOL8 looking_for_min_x; 00342 BOOL8 looking_for_max_y; //what is next 00343 BOOL8 looking_for_min_y; 00344 int stepindex; //current step 00345 inT32 total_steps; //steps to do 00346 //current limits 00347 inT32 max_x, min_x, max_y, min_y; 00348 inT32 initial_x, initial_y; //initial limits 00349 inT32 total; //total changes 00350 ICOORD pos; //position of point 00351 ICOORD next_step; //step to next pix 00352 00353 pos = start_pos (); 00354 total_steps = pathlength (); 00355 total = 0; 00356 max_x = min_x = pos.x (); 00357 max_y = min_y = pos.y (); 00358 looking_for_max_x = TRUE; 00359 looking_for_min_x = TRUE; 00360 looking_for_max_y = TRUE; 00361 looking_for_min_y = TRUE; 00362 first_was_max_x = FALSE; 00363 first_was_max_y = FALSE; 00364 initial_x = pos.x (); 00365 initial_y = pos.y (); //stop uninit warning 00366 for (stepindex = 0; stepindex < total_steps; stepindex++) { 00367 //all intersected 00368 next_step = step (stepindex); 00369 pos += next_step; 00370 if (next_step.x () < 0) { 00371 if (looking_for_max_x && pos.x () < min_x) 00372 min_x = pos.x (); 00373 if (looking_for_min_x && max_x - pos.x () > threshold) { 00374 if (looking_for_max_x) { 00375 initial_x = max_x; 00376 first_was_max_x = FALSE; 00377 } 00378 total++; 00379 looking_for_max_x = TRUE; 00380 looking_for_min_x = FALSE; 00381 min_x = pos.x (); //reset min 00382 } 00383 } 00384 else if (next_step.x () > 0) { 00385 if (looking_for_min_x && pos.x () > max_x) 00386 max_x = pos.x (); 00387 if (looking_for_max_x && pos.x () - min_x > threshold) { 00388 if (looking_for_min_x) { 00389 initial_x = min_x; //remember first min 00390 first_was_max_x = TRUE; 00391 } 00392 total++; 00393 looking_for_max_x = FALSE; 00394 looking_for_min_x = TRUE; 00395 max_x = pos.x (); 00396 } 00397 } 00398 else if (next_step.y () < 0) { 00399 if (looking_for_max_y && pos.y () < min_y) 00400 min_y = pos.y (); 00401 if (looking_for_min_y && max_y - pos.y () > threshold) { 00402 if (looking_for_max_y) { 00403 initial_y = max_y; //remember first max 00404 first_was_max_y = FALSE; 00405 } 00406 total++; 00407 looking_for_max_y = TRUE; 00408 looking_for_min_y = FALSE; 00409 min_y = pos.y (); //reset min 00410 } 00411 } 00412 else { 00413 if (looking_for_min_y && pos.y () > max_y) 00414 max_y = pos.y (); 00415 if (looking_for_max_y && pos.y () - min_y > threshold) { 00416 if (looking_for_min_y) { 00417 initial_y = min_y; //remember first min 00418 first_was_max_y = TRUE; 00419 } 00420 total++; 00421 looking_for_max_y = FALSE; 00422 looking_for_min_y = TRUE; 00423 max_y = pos.y (); 00424 } 00425 } 00426 00427 } 00428 if (first_was_max_x && looking_for_min_x) { 00429 if (max_x - initial_x > threshold) 00430 total++; 00431 else 00432 total--; 00433 } 00434 else if (!first_was_max_x && looking_for_max_x) { 00435 if (initial_x - min_x > threshold) 00436 total++; 00437 else 00438 total--; 00439 } 00440 if (first_was_max_y && looking_for_min_y) { 00441 if (max_y - initial_y > threshold) 00442 total++; 00443 else 00444 total--; 00445 } 00446 else if (!first_was_max_y && looking_for_max_y) { 00447 if (initial_y - min_y > threshold) 00448 total++; 00449 else 00450 total--; 00451 } 00452 00453 return total; 00454 } 00455 00456 00457 /********************************************************************** 00458 * C_OUTLINE::operator< 00459 * 00460 * Return TRUE if the left operand is inside the right one. 00461 **********************************************************************/ 00462 00463 BOOL8 00464 C_OUTLINE::operator< ( //winding number 00465 const C_OUTLINE & other //other outline 00466 ) const 00467 { 00468 inT16 count = 0; //winding count 00469 ICOORD pos; //position of point 00470 inT32 stepindex; //index to cstep 00471 00472 if (!box.overlap (other.box)) 00473 return FALSE; //can't be contained 00474 if (stepcount == 0) 00475 return other.box.contains(this->box); 00476 00477 pos = start; 00478 for (stepindex = 0; stepindex < stepcount 00479 && (count = other.winding_number (pos)) == INTERSECTING; stepindex++) 00480 pos += step (stepindex); //try all points 00481 if (count == INTERSECTING) { 00482 //all intersected 00483 pos = other.start; 00484 for (stepindex = 0; stepindex < other.stepcount 00485 && (count = winding_number (pos)) == INTERSECTING; stepindex++) 00486 //try other way round 00487 pos += other.step (stepindex); 00488 return count == INTERSECTING || count == 0; 00489 } 00490 return count != 0; 00491 } 00492 00493 00494 /********************************************************************** 00495 * C_OUTLINE::winding_number 00496 * 00497 * Return the winding number of the outline around the given point. 00498 **********************************************************************/ 00499 00500 inT16 C_OUTLINE::winding_number( //winding number 00501 ICOORD point //point to wind around 00502 ) const { 00503 inT16 stepindex; //index to cstep 00504 inT16 count; //winding count 00505 ICOORD vec; //to current point 00506 ICOORD stepvec; //step vector 00507 inT32 cross; //cross product 00508 00509 vec = start - point; //vector to it 00510 count = 0; 00511 for (stepindex = 0; stepindex < stepcount; stepindex++) { 00512 stepvec = step (stepindex); //get the step 00513 //crossing the line 00514 if (vec.y () <= 0 && vec.y () + stepvec.y () > 0) { 00515 cross = vec * stepvec; //cross product 00516 if (cross > 0) 00517 count++; //crossing right half 00518 else if (cross == 0) 00519 return INTERSECTING; //going through point 00520 } 00521 else if (vec.y () > 0 && vec.y () + stepvec.y () <= 0) { 00522 cross = vec * stepvec; 00523 if (cross < 0) 00524 count--; //crossing back 00525 else if (cross == 0) 00526 return INTERSECTING; //illegal 00527 } 00528 vec += stepvec; //sum vectors 00529 } 00530 return count; //winding number 00531 } 00532 00533 00534 /********************************************************************** 00535 * C_OUTLINE::turn_direction 00536 * 00537 * Return the sum direction delta of the outline. 00538 **********************************************************************/ 00539 00540 inT16 C_OUTLINE::turn_direction() const { //winding number 00541 DIR128 prevdir; //previous direction 00542 DIR128 dir; //current direction 00543 inT16 stepindex; //index to cstep 00544 inT8 dirdiff; //direction difference 00545 inT16 count; //winding count 00546 00547 if (stepcount == 0) 00548 return 128; 00549 count = 0; 00550 prevdir = step_dir (stepcount - 1); 00551 for (stepindex = 0; stepindex < stepcount; stepindex++) { 00552 dir = step_dir (stepindex); 00553 dirdiff = dir - prevdir; 00554 ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32); 00555 count += dirdiff; 00556 prevdir = dir; 00557 } 00558 ASSERT_HOST (count == 128 || count == -128); 00559 return count; //winding number 00560 } 00561 00562 00563 /********************************************************************** 00564 * C_OUTLINE::reverse 00565 * 00566 * Reverse the direction of an outline. 00567 **********************************************************************/ 00568 00569 void C_OUTLINE::reverse() { //reverse drection 00570 DIR128 halfturn = MODULUS / 2; //amount to shift 00571 DIR128 stepdir; //direction of step 00572 inT16 stepindex; //index to cstep 00573 inT16 farindex; //index to other side 00574 inT16 halfsteps; //half of stepcount 00575 00576 halfsteps = (stepcount + 1) / 2; 00577 for (stepindex = 0; stepindex < halfsteps; stepindex++) { 00578 farindex = stepcount - stepindex - 1; 00579 stepdir = step_dir (stepindex); 00580 set_step (stepindex, step_dir (farindex) + halfturn); 00581 set_step (farindex, stepdir + halfturn); 00582 } 00583 } 00584 00585 00586 /********************************************************************** 00587 * C_OUTLINE::move 00588 * 00589 * Move C_OUTLINE by vector 00590 **********************************************************************/ 00591 00592 void C_OUTLINE::move( // reposition OUTLINE 00593 const ICOORD vec // by vector 00594 ) { 00595 C_OUTLINE_IT it(&children); // iterator 00596 00597 box.move (vec); 00598 start += vec; 00599 00600 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) 00601 it.data ()->move (vec); // move child outlines 00602 } 00603 00604 // If this outline is smaller than the given min_size, delete this and 00605 // remove from its list, via *it, after checking that *it points to this. 00606 // Otherwise, if any children of this are too small, delete them. 00607 // On entry, *it must be an iterator pointing to this. If this gets deleted 00608 // then this is extracted from *it, so an iteration can continue. 00609 void C_OUTLINE::RemoveSmallRecursive(int min_size, C_OUTLINE_IT* it) { 00610 if (box.width() < min_size || box.height() < min_size) { 00611 ASSERT_HOST(this == it->data()); 00612 delete it->extract(); // Too small so get rid of it and any children. 00613 } else if (!children.empty()) { 00614 // Search the children of this, deleting any that are too small. 00615 C_OUTLINE_IT child_it(&children); 00616 for (child_it.mark_cycle_pt(); !child_it.cycled_list(); 00617 child_it.forward()) { 00618 C_OUTLINE* child = child_it.data(); 00619 child->RemoveSmallRecursive(min_size, &child_it); 00620 } 00621 } 00622 } 00623 00624 // Renders the outline to the given pix, with left and top being 00625 // the coords of the upper-left corner of the pix. 00626 void C_OUTLINE::render(int left, int top, Pix* pix) const { 00627 ICOORD pos = start; 00628 for (int stepindex = 0; stepindex < stepcount; ++stepindex) { 00629 ICOORD next_step = step(stepindex); 00630 if (next_step.y() < 0) { 00631 pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1, 00632 PIX_NOT(PIX_DST), NULL, 0, 0); 00633 } else if (next_step.y() > 0) { 00634 pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1, 00635 PIX_NOT(PIX_DST), NULL, 0, 0); 00636 } 00637 pos += next_step; 00638 } 00639 } 00640 00641 // Renders just the outline to the given pix (no fill), with left and top 00642 // being the coords of the upper-left corner of the pix. 00643 void C_OUTLINE::render_outline(int left, int top, Pix* pix) const { 00644 ICOORD pos = start; 00645 for (int stepindex = 0; stepindex < stepcount; ++stepindex) { 00646 ICOORD next_step = step(stepindex); 00647 if (next_step.y() < 0) { 00648 pixSetPixel(pix, pos.x() - left, top - pos.y(), 1); 00649 } else if (next_step.y() > 0) { 00650 pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1); 00651 } else if (next_step.x() < 0) { 00652 pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1); 00653 } else if (next_step.x() > 0) { 00654 pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1); 00655 } 00656 pos += next_step; 00657 } 00658 } 00659 00660 /********************************************************************** 00661 * C_OUTLINE::plot 00662 * 00663 * Draw the outline in the given colour. 00664 **********************************************************************/ 00665 00666 #ifndef GRAPHICS_DISABLED 00667 void C_OUTLINE::plot( //draw it 00668 ScrollView* window, // window to draw in 00669 ScrollView::Color colour // colour to draw in 00670 ) const { 00671 inT16 stepindex; // index to cstep 00672 ICOORD pos; // current position 00673 DIR128 stepdir; // direction of step 00674 00675 pos = start; // current position 00676 window->Pen(colour); 00677 if (stepcount == 0) { 00678 window->Rectangle(box.left(), box.top(), box.right(), box.bottom()); 00679 return; 00680 } 00681 window->SetCursor(pos.x(), pos.y()); 00682 00683 stepindex = 0; 00684 while (stepindex < stepcount) { 00685 pos += step(stepindex); // step to next 00686 stepdir = step_dir(stepindex); 00687 stepindex++; // count steps 00688 // merge straight lines 00689 while (stepindex < stepcount && 00690 stepdir.get_dir() == step_dir(stepindex).get_dir()) { 00691 pos += step(stepindex); 00692 stepindex++; 00693 } 00694 window->DrawTo(pos.x(), pos.y()); 00695 } 00696 } 00697 #endif 00698 00699 00700 /********************************************************************** 00701 * C_OUTLINE::operator= 00702 * 00703 * Assignment - deep copy data 00704 **********************************************************************/ 00705 00706 //assignment 00707 C_OUTLINE & C_OUTLINE::operator= ( 00708 const C_OUTLINE & source //from this 00709 ) { 00710 box = source.box; 00711 start = source.start; 00712 if (steps != NULL) 00713 free_mem(steps); 00714 stepcount = source.stepcount; 00715 steps = (uinT8 *) alloc_mem (step_mem()); 00716 memmove (steps, source.steps, step_mem()); 00717 if (!children.empty ()) 00718 children.clear (); 00719 children.deep_copy(&source.children, &deep_copy); 00720 return *this; 00721 } 00722 00723 ICOORD C_OUTLINE::chain_step(int chaindir) { 00724 return step_coords[chaindir % 4]; 00725 }