mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
eliminate recursion from polyfill #2300
This commit is contained in:
parent
2ce3c0ef4e
commit
8f9608eb19
@ -1262,25 +1262,72 @@ int ncvisual_at_yx(const ncvisual* n, int y, int x, uint32_t* pixel){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a neighbor on which to polyfill. by the time we get to it, it might or
|
||||||
|
// might not have been filled in. if so, discard immediately. otherwise,
|
||||||
|
// check self, and if valid, push all neighbors.
|
||||||
|
struct topolyfill {
|
||||||
|
int y, x;
|
||||||
|
struct topolyfill* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct topolyfill*
|
||||||
|
create_polyfill_op(int y, int x, struct topolyfill** stack){
|
||||||
|
struct topolyfill* n = malloc(sizeof(*n));
|
||||||
|
if(n){
|
||||||
|
n->y = y;
|
||||||
|
n->x = x;
|
||||||
|
n->next = *stack;
|
||||||
|
*stack = n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// originally i wrote this recursively, at which point it promptly began
|
||||||
|
// exploding once i multithreaded the [yield] demo. hence the clumsy stack
|
||||||
|
// and hand-rolled iteration. alas, poor yorick!
|
||||||
static int
|
static int
|
||||||
ncvisual_polyfill_recurse(ncvisual* n, int y, int x, uint32_t rgba, uint32_t match){
|
ncvisual_polyfill_core(ncvisual* n, int y, int x, uint32_t rgba, uint32_t match){
|
||||||
if(y < 0 || y >= n->pixy){
|
struct topolyfill* stack = malloc(sizeof(*stack));
|
||||||
return 0;
|
if(stack == NULL){
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if(x < 0 || x >= n->pixx){
|
stack->y = y;
|
||||||
return 0;
|
stack->x = x;
|
||||||
}
|
stack->next = NULL;
|
||||||
uint32_t* pixel = &n->data[y * (n->rowstride / 4) + x];
|
int ret = 0;
|
||||||
if(*pixel != match || *pixel == rgba){
|
do{
|
||||||
return 0;
|
struct topolyfill* s = stack;
|
||||||
}
|
stack = s->next;
|
||||||
// fprintf(stderr, "%d/%d: setting %08x to %08x\n", y, x, *pixel, rgba);
|
y = s->y;
|
||||||
*pixel = rgba;
|
x = s->x;
|
||||||
int ret = 1;
|
uint32_t* pixel = &n->data[y * (n->rowstride / 4) + x];
|
||||||
ret += ncvisual_polyfill_recurse(n, y - 1, x, rgba, match);
|
if(*pixel == match && *pixel != rgba){
|
||||||
ret += ncvisual_polyfill_recurse(n, y + 1, x, rgba, match);
|
++ret;
|
||||||
ret += ncvisual_polyfill_recurse(n, y, x - 1, rgba, match);
|
// fprintf(stderr, "%d/%d: setting %08x to %08x\n", y, x, *pixel, rgba);
|
||||||
ret += ncvisual_polyfill_recurse(n, y, x + 1, rgba, match);
|
*pixel = rgba;
|
||||||
|
if(y){
|
||||||
|
if(create_polyfill_op(y - 1, x, &stack) == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(y + 1 < n->pixy){
|
||||||
|
if(create_polyfill_op(y + 1, x, &stack) == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(x){
|
||||||
|
if(create_polyfill_op(y, x - 1, &stack) == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(x + 1 < n->pixx){
|
||||||
|
if(create_polyfill_op(y, x + 1, &stack) == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
}while(stack);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1292,7 +1339,7 @@ int ncvisual_polyfill_yx(ncvisual* n, int y, int x, uint32_t rgba){
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint32_t* pixel = &n->data[y * (n->rowstride / 4) + x];
|
uint32_t* pixel = &n->data[y * (n->rowstride / 4) + x];
|
||||||
return ncvisual_polyfill_recurse(n, y, x, rgba, *pixel);
|
return ncvisual_polyfill_core(n, y, x, rgba, *pixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool notcurses_canopen_images(const notcurses* nc __attribute__ ((unused))){
|
bool notcurses_canopen_images(const notcurses* nc __attribute__ ((unused))){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user