22 #include "config_auto.h" 26 #include "allheaders.h" 43 static void position_outline(
45 C_OUTLINE_LIST *destlist
48 C_OUTLINE_IT it = destlist;
50 C_OUTLINE_IT child_it = outline->
child ();
54 dest_outline = it.data ();
56 if (*dest_outline < *outline) {
58 dest_outline = it.extract ();
60 it.add_after_then_move (outline);
62 child_it.add_to_end (dest_outline);
63 while (!it.at_last ()) {
66 dest_outline = it.data ();
67 if (*dest_outline < *outline) {
69 dest_outline = it.extract ();
70 child_it.add_to_end (dest_outline);
79 else if (*outline < *dest_outline) {
80 position_outline (outline, dest_outline->
child ());
86 while (!it.at_first ());
88 it.add_to_end (outline);
99 #ifndef GRAPHICS_DISABLED 100 static void plot_outline_list(
101 C_OUTLINE_LIST *list,
107 C_OUTLINE_IT it = list;
109 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
110 outline = it.data ();
112 outline->
plot (window, colour);
113 if (!outline->
child ()->empty ())
114 plot_outline_list (outline->
child (), window,
115 child_colour, child_colour);
121 static void plot_normed_outline_list(
const DENORM& denorm,
122 C_OUTLINE_LIST *list,
126 C_OUTLINE_IT it(list);
127 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
130 if (!outline->
child()->empty())
131 plot_normed_outline_list(denorm, outline->
child(), child_colour,
132 child_colour, window);
144 static void reverse_outline_list(C_OUTLINE_LIST *list) {
145 C_OUTLINE_IT it = list;
147 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
151 if (!outline->
child()->empty())
152 reverse_outline_list(outline->
child());
166 for (C_OUTLINE_IT ol_it(outline_list); !ol_it.empty(); ol_it.forward()) {
169 position_outline(outline, &outlines);
177 C_OUTLINE_IT it(&outlines);
178 it.add_to_end(outline);
192 C_OUTLINE_LIST* outline_list,
193 C_BLOB_IT* good_blobs_it,
194 C_BLOB_IT* bad_blobs_it) {
196 C_OUTLINE_LIST nested_outlines;
197 for (C_OUTLINE_IT ol_it(outline_list); !ol_it.empty(); ol_it.forward()) {
200 position_outline(outline, &nested_outlines);
203 for (C_OUTLINE_IT ol_it(&nested_outlines); !ol_it.empty(); ol_it.forward()) {
205 bool blob_is_good = good_blob;
209 blob_is_good =
false;
210 ol_it.add_list_after(outline->
child());
216 if (!blob_is_good && bad_blobs_it !=
nullptr)
217 bad_blobs_it->add_after_then_move(blob);
219 good_blobs_it->add_after_then_move(blob);
227 C_OUTLINE_IT ol_it(&outlines);
228 for (ol_it.mark_cycle_pt(); !ol_it.cycled_list(); ol_it.forward()) {
232 reverse_outline_list(outline->
child());
244 C_OUTLINE_LIST outlines;
246 return new C_BLOB(&outlines);
258 C_OUTLINE_IT it =
const_cast<C_OUTLINE_LIST*
>(&outlines);
261 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
262 outline = it.data ();
277 C_OUTLINE_IT it = &outlines;
281 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
282 outline = it.data ();
283 total += outline->
area ();
296 C_OUTLINE_IT it = &outlines;
300 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
316 C_OUTLINE_IT it = &outlines;
320 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
321 outline = it.data ();
339 C_OUTLINE_IT it = &outlines;
343 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
344 outline = it.data ();
360 C_OUTLINE_IT it(&outlines);
362 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
363 it.data ()->move (vec);
367 static void RotateOutlineList(
const FCOORD& rotation,
368 C_OUTLINE_LIST* outlines) {
369 C_OUTLINE_LIST new_outlines;
370 C_OUTLINE_IT src_it(outlines);
371 C_OUTLINE_IT dest_it(&new_outlines);
372 while (!src_it.empty()) {
373 C_OUTLINE* old_outline = src_it.extract();
376 if (!old_outline->
child()->empty()) {
377 RotateOutlineList(rotation, old_outline->
child());
378 C_OUTLINE_IT child_it(new_outline->
child());
379 child_it.add_list_after(old_outline->
child());
382 dest_it.add_to_end(new_outline);
384 src_it.add_list_after(&new_outlines);
394 RotateOutlineList(rotation, &outlines);
399 static void ComputeEdgeOffsetsOutlineList(
int threshold, Pix*
pix,
400 C_OUTLINE_LIST *list) {
401 C_OUTLINE_IT it(list);
402 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
404 if (
pix !=
nullptr && pixGetDepth(
pix) == 8)
408 if (!outline->
child()->empty())
409 ComputeEdgeOffsetsOutlineList(threshold,
pix, outline->
child());
416 ComputeEdgeOffsetsOutlineList(threshold,
pix, &outlines);
435 int left = box.
left();
436 int width = box.
width();
437 int bottom = box.
bottom();
443 C_OUTLINE_IT it(&outlines);
444 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
447 for (
int s = 0; s < outline->
pathlength(); ++s) {
448 if (pos.
y() < y_mins[pos.
x() - left])
449 y_mins[pos.
x() - left] = pos.
y();
450 pos += outline->
step(s);
454 int bottom_extent = 0;
455 for (
int x = 0; x <= width; ++x) {
456 if (y_mins[x] == bottom || y_mins[x] == bottom + 1)
460 int best_min = box.
top();
462 int prev_y = box.
top();
463 int prev_prev_y = box.
top();
464 for (
int x = 0; x < width; x += prev_run) {
466 int y_at_x = y_mins[x];
468 while (x + run <= width && y_mins[x + run] == y_at_x) ++run;
469 if (y_at_x > bottom + 1) {
473 while (x + total_run <= width &&
474 (y_mins[x + total_run] == y_at_x ||
475 y_mins[x + total_run] == y_at_x + 1)) ++total_run;
477 if (prev_prev_y > y_at_x + 1 || x + total_run > width ||
478 y_mins[x + total_run] > y_at_x + 1) {
481 if (prev_run > 0 && prev_y == y_at_x + 1) total_run += prev_run;
482 if (total_run > bottom_extent && y_at_x < best_min) {
488 prev_prev_y = prev_y;
491 return best_min == box.
top() ? bottom : best_min;
494 static void render_outline_list(C_OUTLINE_LIST *list,
495 int left,
int top, Pix*
pix) {
496 C_OUTLINE_IT it(list);
497 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
500 if (!outline->
child()->empty())
501 render_outline_list(outline->
child(), left, top,
pix);
505 static void render_outline_list_outline(C_OUTLINE_LIST *list,
506 int left,
int top, Pix*
pix) {
507 C_OUTLINE_IT it(list);
508 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
518 render_outline_list(&outlines, box.
left(), box.
top(),
pix);
527 render_outline_list_outline(&outlines, box.
left(), box.
top(),
pix);
537 #ifndef GRAPHICS_DISABLED 541 plot_outline_list(&outlines, window, blob_colour, child_colour);
550 plot_normed_outline_list(denorm, &outlines, blob_colour, child_colour,
void ComputeBinaryOffsets()
void plot_normed(const DENORM &denorm, ScrollView::Color blob_colour, ScrollView::Color child_colour, ScrollView *window)
const double kMaxPerimeterWidthRatio
void ComputeEdgeOffsets(int threshold, Pix *pix)
int16_t y() const
access_function
int32_t perimeter() const
const ICOORD & start_pos() const
void ComputeEdgeOffsets(int threshold, Pix *pix)
int16_t turn_direction() const
void render_outline(int left, int top, Pix *pix) const
int16_t x() const
access function
void init_to_size(int size, const T &t)
void render(int left, int top, Pix *pix) const
#define ELISTIZE(CLASSNAME)
int32_t pathlength() const
const TBOX & bounding_box() const
void plot(ScrollView *window, ScrollView::Color colour) const
void set_flag(C_OUTLINE_FLAGS mask, bool value)
void plot_normed(const DENORM &denorm, ScrollView::Color colour, ScrollView *window) const
static void ConstructBlobsFromOutlines(bool good_blob, C_OUTLINE_LIST *outline_list, C_BLOB_IT *good_blobs_it, C_BLOB_IT *bad_blobs_it)
int16_t EstimateBaselinePosition()
TBOX bounding_box() const
int32_t count_transitions(int32_t threshold)
bool IsLegallyNested() const
void plot(ScrollView *window, ScrollView::Color blob_colour, ScrollView::Color child_colour)
int32_t count_transitions(int32_t threshold)
static void FakeOutline(const TBOX &box, C_OUTLINE_LIST *outlines)
static C_BLOB * FakeBlob(const TBOX &box)
int32_t outer_area() const
ICOORD step(int index) const
void move(const ICOORD vec)
void rotate(const FCOORD &rotation)
void CheckInverseFlagAndDirection()