21 #include "config_auto.h"
25 #include "allheaders.h"
41 static void position_outline(
43 C_OUTLINE_LIST *destlist
46 C_OUTLINE_IT it = destlist;
48 C_OUTLINE_IT child_it = outline->
child ();
52 dest_outline = it.data ();
54 if (*dest_outline < *outline) {
56 dest_outline = it.extract ();
58 it.add_after_then_move (outline);
60 child_it.add_to_end (dest_outline);
61 while (!it.at_last ()) {
64 dest_outline = it.data ();
65 if (*dest_outline < *outline) {
67 dest_outline = it.extract ();
68 child_it.add_to_end (dest_outline);
77 else if (*outline < *dest_outline) {
78 position_outline (outline, dest_outline->
child ());
84 while (!it.at_first ());
86 it.add_to_end (outline);
97 #ifndef GRAPHICS_DISABLED
98 static void plot_outline_list(
105 C_OUTLINE_IT it = list;
107 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
108 outline = it.data ();
110 outline->
plot (window, colour);
111 if (!outline->
child ()->empty ())
112 plot_outline_list (outline->
child (), window,
113 child_colour, child_colour);
119 static void plot_normed_outline_list(
const DENORM& denorm,
120 C_OUTLINE_LIST *list,
124 C_OUTLINE_IT it(list);
125 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
128 if (!outline->
child()->empty())
129 plot_normed_outline_list(denorm, outline->
child(), child_colour,
130 child_colour, window);
142 static void reverse_outline_list(C_OUTLINE_LIST *list) {
143 C_OUTLINE_IT it = list;
145 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
149 if (!outline->
child()->empty())
150 reverse_outline_list(outline->
child());
164 for (C_OUTLINE_IT ol_it(outline_list); !ol_it.empty(); ol_it.forward()) {
167 position_outline(outline, &outlines);
175 C_OUTLINE_IT it(&outlines);
176 it.add_to_end(outline);
190 C_OUTLINE_LIST* outline_list,
191 C_BLOB_IT* good_blobs_it,
192 C_BLOB_IT* bad_blobs_it) {
194 C_OUTLINE_LIST nested_outlines;
195 for (C_OUTLINE_IT ol_it(outline_list); !ol_it.empty(); ol_it.forward()) {
198 position_outline(outline, &nested_outlines);
201 for (C_OUTLINE_IT ol_it(&nested_outlines); !ol_it.empty(); ol_it.forward()) {
203 bool blob_is_good = good_blob;
207 blob_is_good =
false;
208 ol_it.add_list_after(outline->
child());
210 auto* blob =
new C_BLOB(outline);
212 blob->CheckInverseFlagAndDirection();
214 if (!blob_is_good && bad_blobs_it !=
nullptr)
215 bad_blobs_it->add_after_then_move(blob);
217 good_blobs_it->add_after_then_move(blob);
225 C_OUTLINE_IT ol_it(&outlines);
226 for (ol_it.mark_cycle_pt(); !ol_it.cycled_list(); ol_it.forward()) {
230 reverse_outline_list(outline->
child());
242 C_OUTLINE_LIST outlines;
244 return new C_BLOB(&outlines);
256 C_OUTLINE_IT it = const_cast<C_OUTLINE_LIST*>(&outlines);
259 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
260 outline = it.data ();
275 C_OUTLINE_IT it = &outlines;
279 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
280 outline = it.data ();
281 total += outline->
area ();
294 C_OUTLINE_IT it = &outlines;
298 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
314 C_OUTLINE_IT it = &outlines;
318 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
319 outline = it.data ();
337 C_OUTLINE_IT it = &outlines;
341 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
342 outline = it.data ();
358 C_OUTLINE_IT it(&outlines);
360 for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
361 it.data ()->move (vec);
365 static void RotateOutlineList(
const FCOORD& rotation,
366 C_OUTLINE_LIST* outlines) {
367 C_OUTLINE_LIST new_outlines;
368 C_OUTLINE_IT src_it(outlines);
369 C_OUTLINE_IT dest_it(&new_outlines);
370 while (!src_it.empty()) {
371 C_OUTLINE* old_outline = src_it.extract();
373 auto* new_outline =
new C_OUTLINE(old_outline, rotation);
374 if (!old_outline->
child()->empty()) {
375 RotateOutlineList(rotation, old_outline->
child());
376 C_OUTLINE_IT child_it(new_outline->child());
377 child_it.add_list_after(old_outline->
child());
380 dest_it.add_to_end(new_outline);
382 src_it.add_list_after(&new_outlines);
392 RotateOutlineList(rotation, &outlines);
397 static void ComputeEdgeOffsetsOutlineList(
int threshold, Pix*
pix,
398 C_OUTLINE_LIST *list) {
399 C_OUTLINE_IT it(list);
400 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
402 if (
pix !=
nullptr && pixGetDepth(
pix) == 8)
406 if (!outline->
child()->empty())
407 ComputeEdgeOffsetsOutlineList(threshold,
pix, outline->
child());
414 ComputeEdgeOffsetsOutlineList(threshold,
pix, &outlines);
433 int left = box.
left();
434 int width = box.
width();
435 int bottom = box.
bottom();
441 C_OUTLINE_IT it(&outlines);
442 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
445 for (
int s = 0; s < outline->
pathlength(); ++s) {
446 if (pos.
y() < y_mins[pos.
x() - left])
447 y_mins[pos.
x() - left] = pos.
y();
448 pos += outline->
step(s);
452 int bottom_extent = 0;
453 for (
int x = 0; x <= width; ++x) {
454 if (y_mins[x] == bottom || y_mins[x] == bottom + 1)
458 int best_min = box.
top();
460 int prev_y = box.
top();
461 int prev_prev_y = box.
top();
462 for (
int x = 0; x < width; x += prev_run) {
464 int y_at_x = y_mins[x];
466 while (x + run <= width && y_mins[x + run] == y_at_x) ++run;
467 if (y_at_x > bottom + 1) {
471 while (x + total_run <= width &&
472 (y_mins[x + total_run] == y_at_x ||
473 y_mins[x + total_run] == y_at_x + 1)) ++total_run;
475 if (prev_prev_y > y_at_x + 1 || x + total_run > width ||
476 y_mins[x + total_run] > y_at_x + 1) {
479 if (prev_run > 0 && prev_y == y_at_x + 1) total_run += prev_run;
480 if (total_run > bottom_extent && y_at_x < best_min) {
486 prev_prev_y = prev_y;
489 return best_min == box.
top() ? bottom : best_min;
492 static void render_outline_list(C_OUTLINE_LIST *list,
493 int left,
int top, Pix*
pix) {
494 C_OUTLINE_IT it(list);
495 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
498 if (!outline->
child()->empty())
499 render_outline_list(outline->
child(), left, top,
pix);
503 static void render_outline_list_outline(C_OUTLINE_LIST *list,
504 int left,
int top, Pix*
pix) {
505 C_OUTLINE_IT it(list);
506 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
516 render_outline_list(&outlines, box.
left(), box.
top(),
pix);
525 render_outline_list_outline(&outlines, box.
left(), box.
top(),
pix);
535 #ifndef GRAPHICS_DISABLED
539 plot_outline_list(&outlines, window, blob_colour, child_colour);
548 plot_normed_outline_list(denorm, &outlines, blob_colour, child_colour,