2005-02-04 18:30:13 -08:00
|
|
|
#include "evas_common.h"
|
|
|
|
|
|
|
|
Regionbuf *
|
|
|
|
evas_common_regionbuf_new(int w, int h)
|
|
|
|
{
|
|
|
|
Regionbuf *rb;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
rb = calloc(1, sizeof(Regionbuf) + (h * sizeof(Regionspan)));
|
|
|
|
if (!rb) return NULL;
|
|
|
|
rb->spans = (Regionspan **)(rb + sizeof(Regionbuf));
|
|
|
|
rb->w = w;
|
|
|
|
rb->h = h;
|
|
|
|
return rb;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_common_regionbuf_free(Regionbuf *rb)
|
|
|
|
{
|
|
|
|
evas_common_regionbuf_clear(rb);
|
|
|
|
free(rb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_common_regionbuf_clear(Regionbuf *rb)
|
|
|
|
{
|
|
|
|
int y;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
for (y = 0; y < rb->h; y++)
|
|
|
|
{
|
|
|
|
while (rb->spans[y])
|
|
|
|
{
|
|
|
|
Regionspan *span;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
span = rb->spans[y];
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], rb->spans[y]);
|
|
|
|
free(span);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_common_regionbuf_span_add(Regionbuf *rb, int x1, int x2, int y)
|
|
|
|
{
|
|
|
|
Evas_Object_List *l;
|
|
|
|
Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
|
|
|
|
|
|
|
|
/* abort if outside */
|
|
|
|
if ((y < 0) ||
|
|
|
|
(y >= rb->h) ||
|
|
|
|
(x2 < 0) ||
|
|
|
|
(x1 >= rb->w)) return;
|
|
|
|
/* clip to horiz bounds */
|
|
|
|
if (x1 < 0) x1 = 0;
|
|
|
|
if (x2 < (rb->w - 1)) x2 = rb->w - 1;
|
|
|
|
sp_start = NULL;
|
|
|
|
sp_stop = NULL;
|
|
|
|
for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
|
|
|
|
{
|
|
|
|
span = (Regionspan *)l;
|
|
|
|
nspan = (Regionspan *)l->next;
|
|
|
|
/* we dont know what t do with the span yet */
|
|
|
|
if (!sp_start)
|
|
|
|
{
|
2005-05-21 19:49:50 -07:00
|
|
|
/* if new span starts before or on this span or just after
|
2005-02-04 18:30:13 -08:00
|
|
|
* with no gap */
|
|
|
|
if (x1 <= (span->x2 + 1))
|
|
|
|
sp_start = span;
|
|
|
|
/* if there is no next span */
|
|
|
|
if (!nspan)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* if new span ends before the next span starts with a gap of
|
|
|
|
* 1 pixel (or more) */
|
|
|
|
else if (x2 < (nspan->x1 - 1))
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* we already know it already starts before or in sp_start */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* there is no span after this one, so this has to be the stop */
|
|
|
|
if (!nspan)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* if new span ends before the next span starts with a gap of
|
|
|
|
* 1 pixel (or more) */
|
|
|
|
else if (x2 < (nspan->x1 - 1))
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* sp_start is where the new span starts in or before */
|
|
|
|
/* sp_stop is where the new span stops in or after */
|
|
|
|
if ((sp_start) && (sp_stop))
|
|
|
|
{
|
|
|
|
/* same start and stop */
|
|
|
|
if (sp_start == sp_stop)
|
|
|
|
{
|
|
|
|
if (x2 < (sp_start->x1 - 1))
|
|
|
|
{
|
|
|
|
span2 = calloc(1, sizeof(Regionspan));
|
|
|
|
span2->x1 = x1;
|
|
|
|
span2->x2 = x2;
|
|
|
|
rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (x1 < sp_start->x1)
|
|
|
|
sp_start->x1 = x1;
|
|
|
|
if (x2 > sp_start->x2)
|
|
|
|
sp_start->x2 = x2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* remove all nodes after sp_start and before_sp_stop because
|
|
|
|
* the new */
|
|
|
|
for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
|
|
|
|
{
|
|
|
|
span = (Regionspan *)l;
|
|
|
|
l = l->next;
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
|
|
|
|
free(span);
|
|
|
|
}
|
|
|
|
/* remove the end span */
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
|
|
|
|
/* if the new span is before the start span - extend */
|
|
|
|
if (x1 < sp_start->x1)
|
|
|
|
sp_start->x1 = x1;
|
|
|
|
/* if it goes beyond the stop span - extend stop span */
|
|
|
|
if (x2 > sp_stop->x2)
|
|
|
|
sp_stop->x2 = x2;
|
|
|
|
/* extend start span to stop span */
|
|
|
|
sp_start->x2 = sp_stop->x2;
|
|
|
|
/* don't need stop span anymore */
|
|
|
|
free(sp_stop);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* no start AND stop... just append */
|
|
|
|
span2 = calloc(1, sizeof(Regionspan));
|
|
|
|
span2->x1 = x1;
|
|
|
|
span2->x2 = x2;
|
|
|
|
rb->spans[y] = evas_object_list_append(rb->spans[y], span2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_common_regionbuf_span_del(Regionbuf *rb, int x1, int x2, int y)
|
|
|
|
{
|
|
|
|
/* FIXME: del span */
|
|
|
|
Evas_Object_List *l;
|
|
|
|
Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
|
|
|
|
|
|
|
|
/* abort if outside */
|
|
|
|
if ((y < 0) ||
|
|
|
|
(y >= rb->h) ||
|
|
|
|
(x2 < 0) ||
|
|
|
|
(x1 >= rb->w)) return;
|
|
|
|
/* clip to horiz bounds */
|
|
|
|
if (x1 < 0) x1 = 0;
|
|
|
|
if (x2 < (rb->w - 1)) x2 = rb->w - 1;
|
|
|
|
sp_start = NULL;
|
|
|
|
sp_stop = NULL;
|
|
|
|
for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
|
|
|
|
{
|
|
|
|
span = (Regionspan *)l;
|
|
|
|
nspan = (Regionspan *)l->next;
|
|
|
|
/* we dont know what t do with the span yet */
|
|
|
|
if (!sp_start)
|
|
|
|
{
|
2005-05-21 19:49:50 -07:00
|
|
|
/* if new span starts before or on this span or just after
|
2005-02-04 18:30:13 -08:00
|
|
|
* with no gap */
|
|
|
|
if (x1 <= (span->x2))
|
|
|
|
sp_start = span;
|
|
|
|
/* if there is no next span */
|
|
|
|
if (!nspan)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* if new span ends before the next span starts with a gap of
|
|
|
|
* 1 pixel (or more) */
|
|
|
|
else if (x2 < nspan->x1)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* we already know it already starts before or in sp_start */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* there is no span after this one, so this has to be the stop */
|
|
|
|
if (!nspan)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* if new span ends before the next span starts with a gap of
|
|
|
|
* 1 pixel (or more) */
|
|
|
|
else if (x2 < nspan->x1)
|
|
|
|
{
|
|
|
|
sp_stop = span;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* sp_start is where the new span starts in or before */
|
|
|
|
/* sp_stop is where the new span stops in or after */
|
|
|
|
if ((sp_start) && (sp_stop))
|
|
|
|
{
|
|
|
|
/* same start and stop */
|
|
|
|
if (sp_start == sp_stop)
|
|
|
|
{
|
|
|
|
/* if it ends before this the span start starts... return */
|
|
|
|
if (x2 < sp_start->x1)
|
|
|
|
return;
|
|
|
|
/* it starts on or before this span */
|
|
|
|
else if (x1 <= sp_start->x1)
|
|
|
|
{
|
|
|
|
/* right edge is within the span */
|
|
|
|
if (x2 < sp_start->x2)
|
|
|
|
{
|
|
|
|
sp_start->x2 = x2;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* it ends on or after the end of thsi span */
|
|
|
|
else if (x2 >= sp_start->x2)
|
|
|
|
{
|
|
|
|
/* it starts after the start */
|
|
|
|
if (x1 > sp_start->x1)
|
|
|
|
{
|
|
|
|
sp_start->x1 = x1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* remove it all */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* this breaks the span into 2 */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
span2 = calloc(1, sizeof(Regionspan));
|
|
|
|
span2->x1 = sp_start->x1;
|
|
|
|
span2->x2 = x1 - 1;
|
|
|
|
rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
|
|
|
|
sp_start->x1 = x2 + 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* remove all nodes after sp_start and before_sp_stop because
|
|
|
|
* the new */
|
|
|
|
for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
|
|
|
|
{
|
|
|
|
span = (Regionspan *)l;
|
|
|
|
l = l->next;
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
|
|
|
|
free(span);
|
|
|
|
}
|
|
|
|
/* all of the start span is cut out */
|
|
|
|
if (x1 <= sp_start->x1)
|
|
|
|
{
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
|
|
|
|
free(sp_start);
|
|
|
|
}
|
|
|
|
/* chup it off at the new span start */
|
|
|
|
else
|
|
|
|
sp_start->x2 = x1 - 1;
|
|
|
|
/* all of the end span is cut out */
|
|
|
|
if (x2 >= sp_stop->x2)
|
|
|
|
{
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
|
|
|
|
free(sp_stop);
|
|
|
|
}
|
|
|
|
/* chop it up at the end */
|
|
|
|
else
|
|
|
|
sp_stop->x1 = x2 + 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Tilebuf_Rect *
|
|
|
|
evas_common_regionbuf_rects_get(Regionbuf *rb)
|
|
|
|
{
|
|
|
|
Tilebuf_Rect *rects = NULL, *r;
|
|
|
|
int y;
|
|
|
|
|
2005-05-21 19:49:50 -07:00
|
|
|
/* FIXME: take spans, make rects */
|
2005-02-04 18:30:13 -08:00
|
|
|
for (y = 0; y < rb->h; y++)
|
|
|
|
{
|
|
|
|
Evas_Object_List *l, *ll;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
for (l = (Evas_Object_List *)rb->spans[y]; l;)
|
2005-05-21 19:49:50 -07:00
|
|
|
{
|
2005-02-04 18:30:13 -08:00
|
|
|
Regionspan *span;
|
|
|
|
Regionspan *sp_start;
|
|
|
|
int yy;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
sp_start = (Regionspan *)l;
|
|
|
|
l = l->next;
|
|
|
|
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
|
|
|
|
for (yy = y + 1; yy < rb->h; yy++)
|
|
|
|
{
|
|
|
|
int match = 0;
|
2005-05-21 19:49:50 -07:00
|
|
|
|
2005-02-04 18:30:13 -08:00
|
|
|
for (ll = (Evas_Object_List *)rb->spans[yy]; ll;)
|
|
|
|
{
|
|
|
|
span = (Regionspan *)ll;
|
|
|
|
ll = ll->next;
|
|
|
|
if (span->x1 == sp_start->x1)
|
|
|
|
{
|
2005-05-21 19:49:50 -07:00
|
|
|
if ((span->x1 != sp_start->x1) ||
|
2005-02-04 18:30:13 -08:00
|
|
|
(span->x2 != sp_start->x2))
|
|
|
|
{
|
|
|
|
goto coallate;
|
|
|
|
}
|
|
|
|
match = 1;
|
|
|
|
rb->spans[yy] = evas_object_list_remove(rb->spans[yy], span);
|
|
|
|
free(span);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!match) goto coallate;
|
|
|
|
}
|
|
|
|
coallate:
|
|
|
|
r = calloc(1, sizeof(Tilebuf_Rect));
|
|
|
|
r->x = sp_start->x1;
|
|
|
|
r->y = y;
|
|
|
|
r->w = sp_start->x2 - sp_start->x1 + 1;
|
|
|
|
r->h = yy - y;
|
|
|
|
rects = evas_object_list_append(rects, r);
|
|
|
|
free(sp_start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
evas_common_regionbuf_clear(rb);
|
|
|
|
return rects;
|
|
|
|
}
|