move around - flatter.
[profile/ivi/evas.git] / src / lib / engines / common / evas_regionbuf.c
1 #include "evas_common.h"
2
3 #if 0
4 Regionbuf *
5 evas_common_regionbuf_new(int w, int h)
6 {
7    Regionbuf *rb;
8
9    rb = calloc(1, sizeof(Regionbuf) + (h * sizeof(Regionspan)));
10    if (!rb) return NULL;
11    rb->spans = (Regionspan **)(rb + sizeof(Regionbuf));
12    rb->w = w;
13    rb->h = h;
14    return rb;
15 }
16
17 void
18 evas_common_regionbuf_free(Regionbuf *rb)
19 {
20    evas_common_regionbuf_clear(rb);
21    free(rb);
22 }
23
24 void
25 evas_common_regionbuf_clear(Regionbuf *rb)
26 {
27    int y;
28
29    for (y = 0; y < rb->h; y++)
30      {
31         while (rb->spans[y])
32           {
33              Regionspan *span;
34
35              span = rb->spans[y];
36              rb->spans[y] = evas_object_list_remove(rb->spans[y], rb->spans[y]);
37              free(span);
38           }
39      }
40 }
41
42 void
43 evas_common_regionbuf_span_add(Regionbuf *rb, int x1, int x2, int y)
44 {
45    Evas_Object_List *l;
46    Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
47
48    /* abort if outside */
49    if ((y < 0) ||
50        (y >= rb->h) ||
51        (x2 < 0) ||
52        (x1 >= rb->w)) return;
53    /* clip to horiz bounds */
54    if (x1 < 0) x1 = 0;
55    if (x2 < (rb->w - 1)) x2 = rb->w - 1;
56    sp_start = NULL;
57    sp_stop = NULL;
58    for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
59      {
60         span = (Regionspan *)l;
61         nspan = (Regionspan *)l->next;
62         /* we dont know what t do with the span yet */
63         if (!sp_start)
64           {
65              /* if new span starts before or on this span or just after
66               * with no gap */
67              if (x1 <= (span->x2 + 1))
68                sp_start = span;
69              /* if there is no next span */
70              if (!nspan)
71                {
72                   sp_stop = span;
73                   break;
74                }
75              /* if new span ends before the next span starts with a gap of
76               * 1 pixel (or more) */
77              else if (x2 < (nspan->x1 - 1))
78                {
79                   sp_stop = span;
80                   break;
81                }
82           }
83         /* we already know it already starts before or in sp_start */
84         else
85           {
86              /* there is no span after this one, so this has to be the stop */
87              if (!nspan)
88                {
89                   sp_stop = span;
90                   break;
91                }
92              /* if new span ends before the next span starts with a gap of
93               * 1 pixel (or more) */
94              else if (x2 < (nspan->x1 - 1))
95                {
96                   sp_stop = span;
97                   break;
98                }
99           }
100      }
101    /* sp_start is where the new span starts in or before */
102    /* sp_stop is where the new span stops in or after */
103    if ((sp_start) && (sp_stop))
104      {
105         /* same start and stop */
106         if (sp_start == sp_stop)
107           {
108              if (x2 < (sp_start->x1 - 1))
109                {
110                   span2 = calloc(1, sizeof(Regionspan));
111                   span2->x1 = x1;
112                   span2->x2 = x2;
113                   rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
114                   return;
115                }
116              if (x1 < sp_start->x1)
117                sp_start->x1 = x1;
118              if (x2 > sp_start->x2)
119                sp_start->x2 = x2;
120              return;
121           }
122         else
123           {
124              /* remove all nodes after sp_start and before_sp_stop because
125               * the new  */
126              for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
127                {
128                   span = (Regionspan *)l;
129                   l = l->next;
130                   rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
131                   free(span);
132                }
133              /* remove the end span */
134              rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
135              /* if the new span is before the start span - extend */
136              if (x1 < sp_start->x1)
137                sp_start->x1 = x1;
138              /* if it goes beyond the stop span - extend stop span */
139              if (x2 > sp_stop->x2)
140                sp_stop->x2 = x2;
141              /* extend start span to stop span */
142              sp_start->x2 = sp_stop->x2;
143              /* don't need stop span anymore */
144              free(sp_stop);
145              return;
146           }
147      }
148    /* no start AND stop... just append */
149    span2 = calloc(1, sizeof(Regionspan));
150    span2->x1 = x1;
151    span2->x2 = x2;
152    rb->spans[y] = evas_object_list_append(rb->spans[y], span2);
153 }
154
155 void
156 evas_common_regionbuf_span_del(Regionbuf *rb, int x1, int x2, int y)
157 {
158    /* FIXME: del span */
159    Evas_Object_List *l;
160    Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
161
162    /* abort if outside */
163    if ((y < 0) ||
164        (y >= rb->h) ||
165        (x2 < 0) ||
166        (x1 >= rb->w)) return;
167    /* clip to horiz bounds */
168    if (x1 < 0) x1 = 0;
169    if (x2 < (rb->w - 1)) x2 = rb->w - 1;
170    sp_start = NULL;
171    sp_stop = NULL;
172    for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
173      {
174         span = (Regionspan *)l;
175         nspan = (Regionspan *)l->next;
176         /* we dont know what t do with the span yet */
177         if (!sp_start)
178           {
179              /* if new span starts before or on this span or just after
180               * with no gap */
181              if (x1 <= (span->x2))
182                sp_start = span;
183              /* if there is no next span */
184              if (!nspan)
185                {
186                   sp_stop = span;
187                   break;
188                }
189              /* if new span ends before the next span starts with a gap of
190               * 1 pixel (or more) */
191              else if (x2 < nspan->x1)
192                {
193                   sp_stop = span;
194                   break;
195                }
196           }
197         /* we already know it already starts before or in sp_start */
198         else
199           {
200              /* there is no span after this one, so this has to be the stop */
201              if (!nspan)
202                {
203                   sp_stop = span;
204                   break;
205                }
206              /* if new span ends before the next span starts with a gap of
207               * 1 pixel (or more) */
208              else if (x2 < nspan->x1)
209                {
210                   sp_stop = span;
211                   break;
212                }
213           }
214      }
215    /* sp_start is where the new span starts in or before */
216    /* sp_stop is where the new span stops in or after */
217    if ((sp_start) && (sp_stop))
218      {
219         /* same start and stop */
220         if (sp_start == sp_stop)
221           {
222              /* if it ends before this the span start starts... return */
223              if (x2 < sp_start->x1)
224                return;
225              /* it starts on or before this span */
226              else if (x1 <= sp_start->x1)
227                {
228                   /* right edge is within the span */
229                   if (x2 < sp_start->x2)
230                     {
231                        sp_start->x2 = x2;
232                        return;
233                     }
234                   else
235                     {
236                        rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
237                        return;
238                     }
239                }
240              /* it ends on or after the end of thsi span */
241              else if (x2 >= sp_start->x2)
242                {
243                   /* it starts after the start */
244                   if (x1 > sp_start->x1)
245                     {
246                        sp_start->x1 = x1;
247                        return;
248                     }
249                   /* remove it all */
250                   else
251                     {
252                        rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
253                        return;
254                     }
255                   return;
256                }
257              /* this breaks the span into 2 */
258              else
259                {
260                   span2 = calloc(1, sizeof(Regionspan));
261                   span2->x1 = sp_start->x1;
262                   span2->x2 = x1 - 1;
263                   rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
264                   sp_start->x1 = x2 + 1;
265                   return;
266                }
267           }
268         else
269           {
270              /* remove all nodes after sp_start and before_sp_stop because
271               * the new  */
272              for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
273                {
274                   span = (Regionspan *)l;
275                   l = l->next;
276                   rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
277                   free(span);
278                }
279              /* all of the start span is cut out */
280              if (x1 <= sp_start->x1)
281                {
282                   rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
283                   free(sp_start);
284                }
285              /* chup it off at the new span start */
286              else
287                sp_start->x2 = x1 - 1;
288              /* all of the end span is cut out */
289              if (x2 >= sp_stop->x2)
290                {
291                   rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
292                   free(sp_stop);
293                }
294              /* chop it up at the end */
295              else
296                sp_stop->x1 = x2 + 1;
297              return;
298           }
299      }
300 }
301
302 Tilebuf_Rect *
303 evas_common_regionbuf_rects_get(Regionbuf *rb)
304 {
305    Tilebuf_Rect *rects = NULL, *r;
306    int y;
307
308    /* FIXME: take spans, make rects */
309    for (y = 0; y < rb->h; y++)
310      {
311         Evas_Object_List *l, *ll;
312
313         for (l = (Evas_Object_List *)rb->spans[y]; l;)
314           {
315              Regionspan *span;
316              Regionspan *sp_start;
317              int yy;
318
319              sp_start = (Regionspan *)l;
320              l = l->next;
321              rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
322              for (yy = y + 1; yy < rb->h; yy++)
323                {
324                   int match = 0;
325
326                   for (ll = (Evas_Object_List *)rb->spans[yy]; ll;)
327                     {
328                        span = (Regionspan *)ll;
329                        ll = ll->next;
330                        if (span->x1 == sp_start->x1)
331                          {
332                             if ((span->x1 != sp_start->x1) ||
333                                 (span->x2 != sp_start->x2))
334                               {
335                                  goto coallate;
336                               }
337                             match = 1;
338                             rb->spans[yy] = evas_object_list_remove(rb->spans[yy], span);
339                             free(span);
340                          }
341                     }
342                   if (!match) goto coallate;
343                }
344              coallate:
345              r = calloc(1, sizeof(Tilebuf_Rect));
346              r->x = sp_start->x1;
347              r->y = y;
348              r->w = sp_start->x2 - sp_start->x1 + 1;
349              r->h = yy - y;
350              rects = evas_object_list_append(rects, r);
351              free(sp_start);
352           }
353      }
354    evas_common_regionbuf_clear(rb);
355    return rects;
356 }
357 #endif