From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- .../evas/src/lib/engines/common/evas_regionbuf.c | 357 +++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 libraries/evas/src/lib/engines/common/evas_regionbuf.c (limited to 'libraries/evas/src/lib/engines/common/evas_regionbuf.c') diff --git a/libraries/evas/src/lib/engines/common/evas_regionbuf.c b/libraries/evas/src/lib/engines/common/evas_regionbuf.c new file mode 100644 index 0000000..f381da5 --- /dev/null +++ b/libraries/evas/src/lib/engines/common/evas_regionbuf.c @@ -0,0 +1,357 @@ +#include "evas_common.h" + +#if 0 +Regionbuf * +evas_common_regionbuf_new(int w, int h) +{ + Regionbuf *rb; + + 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; + + for (y = 0; y < rb->h; y++) + { + while (rb->spans[y]) + { + Regionspan *span; + + span = rb->spans[y]; + rb->spans[y] = eina_inlist_remove(rb->spans[y], rb->spans[y]); + free(span); + } + } +} + +void +evas_common_regionbuf_span_add(Regionbuf *rb, int x1, int x2, int y) +{ + 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; + EINA_INLIST_FOREACH(rb->spans[y], span) + { + nspan = (Regionspan *)(EINA_INLIST_GET(span))->next; + /* we dont know what t do with the span yet */ + if (!sp_start) + { + /* if new span starts before or on this span or just after + * 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] = eina_inlist_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 + { + Eina_Inlist *l; + + /* remove all nodes after sp_start and before_sp_stop because + * the new */ + for (l = (EINA_INLIST_GET(sp_start))->next; l != EINA_INLIST_GET(sp_stop);) + { + span = (Regionspan *)l; + l = l->next; + rb->spans[y] = eina_inlist_remove(rb->spans[y], span); + free(span); + } + /* remove the end span */ + rb->spans[y] = eina_inlist_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] = eina_inlist_append(rb->spans[y], span2); +} + +void +evas_common_regionbuf_span_del(Regionbuf *rb, int x1, int x2, int y) +{ + /* FIXME: del span */ + 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; + EINA_INLIST_FOREACH(rb->spans[y], span) + { + nspan = (Regionspan *)(EINA_INLIST_GET(l))->next; + /* we dont know what t do with the span yet */ + if (!sp_start) + { + /* if new span starts before or on this span or just after + * 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] = eina_inlist_remove(rb->spans[y], sp_start); + return; + } + } + /* it ends on or after the end of this 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] = eina_inlist_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] = eina_inlist_prepend_relative(rb->spans[y], span2, sp_start); + sp_start->x1 = x2 + 1; + return; + } + } + else + { + Eina_Inlist *l; + + /* remove all nodes after sp_start and before_sp_stop because + * the new */ + for (l = (EINA_INLIST_GET(sp_start))->next; l != EINA_INLIST_GET(sp_stop);) + { + span = (Regionspan *)l; + l = l->next; + rb->spans[y] = eina_inlist_remove(rb->spans[y], span); + free(span); + } + /* all of the start span is cut out */ + if (x1 <= sp_start->x1) + { + rb->spans[y] = eina_inlist_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] = eina_inlist_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; + + /* FIXME: take spans, make rects */ + for (y = 0; y < rb->h; y++) + { + Regionspan *sp_start; + Eina_Inlist *l, *ll; + + for (l = EINA_INLIST_GET(rb->spans[y]); l;) + { + Regionspan *span; + int yy; + + sp_start = (Regionspan *)l; + l = l->next; + rb->spans[y] = eina_inlist_remove(rb->spans[y], sp_start); + for (yy = y + 1; yy < rb->h; yy++) + { + int match = 0; + + for (ll = EINA_INLIST_GET(rb->spans[yy]); ll;) + { + span = (Regionspan *)ll; + ll = ll->next; + if (span->x1 == sp_start->x1) + { + if ((span->x1 != sp_start->x1) || + (span->x2 != sp_start->x2)) + { + goto coallate; + } + match = 1; + rb->spans[yy] = eina_inlist_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 = eina_inlist_append(rects, r); + free(sp_start); + } + } + evas_common_regionbuf_clear(rb); + return rects; +} +#endif -- cgit v1.1