rollback evas_async_reinit and rebuild evas GL engine
[framework/uifw/evas.git] / src / lib / engines / common / evas_gradient2_main.c
1 #include "evas_common.h"
2 #include "evas_blend_private.h"
3 #include "evas_private.h"
4 #include <math.h>
5
6 static void _evas_common_gradient2_stops_free(RGBA_Gradient2 *gr);
7 static void _evas_common_gradient2_stops_scale(RGBA_Gradient2 *gr);
8
9 static void _evas_common_gradient2_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len);
10 static void _evas_common_gradient2_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len);
11
12 static  int grad_initialised = 0;
13
14 EAPI void
15 evas_common_gradient2_init(void)
16 {
17    RGBA_Gradient2_Type  *geom;
18
19    if (grad_initialised)
20         return;
21    geom = evas_common_gradient2_type_linear_get();
22    if (geom)
23         geom->init();
24    geom = evas_common_gradient2_type_radial_get();
25    if (geom)
26         geom->init();
27    grad_initialised = 1;
28 }
29
30 void
31 evas_common_gradient2_shutdown(void)
32 {
33    RGBA_Gradient2_Type  *geom;
34
35    if (!grad_initialised)
36         return;
37    geom = evas_common_gradient2_type_linear_get();
38    if (geom)
39         geom->shutdown();
40    geom = evas_common_gradient2_type_radial_get();
41    if (geom)
42         geom->shutdown();
43    grad_initialised = 0;
44 }
45
46 static void
47 _evas_common_gradient2_stops_free(RGBA_Gradient2 *gr)
48 {
49    if (!gr) return;
50    if (gr->stops.stops)
51      {
52         Eina_Inlist *l;
53
54         while (gr->stops.stops)
55           {
56            l = gr->stops.stops;
57            gr->stops.stops = eina_inlist_remove(gr->stops.stops, gr->stops.stops);
58            free(l);
59           }
60         gr->stops.stops = NULL;
61         gr->stops.nstops = 0;
62      }
63 }
64
65 EAPI void
66 evas_common_gradient2_free(RGBA_Gradient2 *gr)
67 {
68    if (!gr) return;
69    gr->references--;
70    if (gr->references > 0) return;
71 #ifdef EVAS_FRAME_QUEUING
72    LKL(gr->ref_fq_add);  LKL(gr->ref_fq_del);
73    if (gr->ref_fq[0] != gr->ref_fq[1])
74      {
75         LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
76         return;
77      }
78    LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
79 #endif
80    evas_common_gradient2_clear(gr);
81    if (gr->stops.cdata) free(gr->stops.cdata);
82    if (gr->stops.adata) free(gr->stops.adata);
83    if (gr->type.geometer && gr->type.gdata)
84         gr->type.geometer->geom_free(gr->type.gdata);
85    if (gr->map.data) free(gr->map.data);
86    free(gr);
87 }
88
89 EAPI void
90 evas_common_gradient2_clear(RGBA_Gradient2 *gr)
91 {
92    if (!gr) return;
93
94    _evas_common_gradient2_stops_free(gr);
95    gr->has_alpha = 0;
96 }
97
98 EAPI void
99 evas_common_gradient2_color_np_stop_insert(RGBA_Gradient2 *gr, int r, int g, int b, int a, float pos)
100 {
101    RGBA_Gradient2_Color_Np_Stop *gc;
102    Eina_Inlist *l;
103
104    if (!gr) return;
105    if (!gr->stops.stops)
106      {
107         RGBA_Gradient2_Color_Np_Stop *gc1;
108
109         gc = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
110         if (!gc) return;
111         gc1 = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
112         if (!gc1) { free(gc);  return; }
113         gc->r = gc->g = gc->b = gc->a = 255;  gc->pos = 0.0;  gc->dist = 0;
114         gc1->r = gc1->g = gc1->b = gc1->a = 255;  gc1->pos = 1.0;  gc1->dist = 0;
115
116         gr->stops.stops = eina_inlist_append(gr->stops.stops, EINA_INLIST_GET(gc));
117         gr->stops.stops = eina_inlist_append(gr->stops.stops, EINA_INLIST_GET(gc1));
118         gr->stops.nstops = 2;
119         gr->stops.len = 0;
120      }
121
122    if (r < 0) r = 0;  if (r > 255) r = 255;
123    if (g < 0) g = 0;  if (g > 255) g = 255;
124    if (b < 0) b = 0;  if (b > 255) b = 255;
125    if (a < 0) a = 0;  if (a > 255) a = 255;
126    if (pos < 0.0) pos = 0.0;
127    if (pos > 1.0) pos = 1.0;
128
129    if (pos == 0.0)
130      {
131         gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
132         gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
133         if (a < 255) gr->has_alpha = 1;
134         return;
135      }
136    if (pos == 1.0)
137      {
138         gc = (RGBA_Gradient2_Color_Np_Stop *)(gr->stops.stops->last);
139         gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
140         if (a < 255) gr->has_alpha = 1;
141         return;
142      }
143
144    l = gr->stops.stops->next;
145    while (l)
146      {
147         gc = (RGBA_Gradient2_Color_Np_Stop *)l;
148         if (pos <= gc->pos)
149           {
150             if (pos == gc->pos)
151               {
152                 gc->r = r;  gc->g = g;  gc->b = b;  gc->a = a;  gc->dist = 0;
153                 if (a < 255) gr->has_alpha = 1;
154                 return;
155               }
156             break;
157           }
158         l = l->next;
159      }
160
161    gc = malloc(sizeof(RGBA_Gradient2_Color_Np_Stop));
162    if (!gc) return;
163    gc->r = r;
164    gc->g = g;
165    gc->b = b;
166    gc->a = a;
167    gc->pos = pos;
168    gc->dist = 0;
169
170    gr->stops.stops = eina_inlist_prepend_relative(gr->stops.stops, EINA_INLIST_GET(gc), l);
171    gr->stops.nstops++;
172    if (a < 255)
173         gr->has_alpha = 1;
174 }
175
176 EAPI void
177 evas_common_gradient2_fill_transform_set(RGBA_Gradient2 *gr, Evas_Common_Transform *t)
178 {
179    if (!gr) return;
180    if (!t)
181      {
182         gr->fill.transform.mxx = 1;  gr->fill.transform.mxy = 0;  gr->fill.transform.mxz = 0;
183         gr->fill.transform.myx = 0;  gr->fill.transform.myy = 1;  gr->fill.transform.myz = 0;
184         gr->fill.transform.mzx = 1;  gr->fill.transform.mzy = 0;  gr->fill.transform.mzz = 1;
185         return;
186      }
187    gr->fill.transform.mxx = t->mxx;  gr->fill.transform.mxy = t->mxy;  gr->fill.transform.mxz = t->mxz;
188    gr->fill.transform.myx = t->myx;  gr->fill.transform.myy = t->myy;  gr->fill.transform.myz = t->myz;
189    gr->fill.transform.mzx = t->mzx;  gr->fill.transform.mzy = t->mzy;  gr->fill.transform.mzz = t->mzz;
190 }
191
192 EAPI void
193 evas_common_gradient2_fill_spread_set(RGBA_Gradient2 *gr, int spread)
194 {
195    if (!gr) return;
196    gr->fill.spread = spread;
197 }
198
199 EAPI void
200 evas_common_gradient2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
201                            int x, int y, int w, int h, RGBA_Gradient2 *gr)
202 {
203    Gfx_Func_Gradient2_Fill   gfunc;
204    RGBA_Gfx_Func            bfunc = NULL;
205    int             len;
206    int             xin, yin, xoff, yoff;
207    int             clx, cly, clw, clh;
208    DATA32          *pdst, *dst_end, *buf, *map;
209    RGBA_Image      *argb_buf = NULL, *alpha_buf = NULL;
210    DATA8           *mask = NULL;
211    void            *gdata;
212    int             direct_copy = 0, buf_step = 0;
213
214    if (!dst || !dc || !gr || !dst || !dst->image.data)
215         return;
216    if (!gr->map.data || !gr->type.geometer)
217         return;
218    if ((w < 1) || (h < 1))
219         return;
220    clx = 0;  cly = 0;  clw = dst->cache_entry.w;  clh = dst->cache_entry.h;
221    if ((clw < 1) || (clh < 1))  return;
222
223    if (dc->clip.use)
224      RECTS_CLIP_TO_RECT(clx,cly,clw,clh, dc->clip.x,dc->clip.y,dc->clip.w,dc->clip.h);
225    if ((clw < 1) || (clh < 1))  return;
226
227    xin = x;  yin = y;
228    RECTS_CLIP_TO_RECT(x,y,w,h, clx,cly,clw,clh);
229    if ((w < 1) || (h < 1))  return;
230
231    xoff = (x - xin);
232    yoff = (y - yin);
233
234    if (!gr->type.geometer->has_mask(gr, dc->render_op))
235      {
236         if ((dc->render_op == _EVAS_RENDER_FILL) ||
237              (dc->render_op == _EVAS_RENDER_COPY))
238           {
239              direct_copy = 1;  buf_step = dst->cache_entry.w;
240              if (gr->type.geometer->has_alpha(gr, dc->render_op))
241                 dst->cache_entry.flags.alpha = 1;
242           }
243         else if ((dc->render_op == _EVAS_RENDER_BLEND) &&
244                   !gr->type.geometer->has_alpha(gr, dc->render_op))
245           {
246              direct_copy = 1;  buf_step = dst->cache_entry.w;
247           }
248      }
249    if (!direct_copy)
250      {
251         argb_buf = evas_common_image_line_buffer_obtain(w);
252         if (!argb_buf)
253            return;
254         argb_buf->cache_entry.flags.alpha = gr->type.geometer->has_alpha(gr, dc->render_op) ? 1 : 0;
255
256         if (gr->type.geometer->has_mask(gr, dc->render_op))
257           {
258             alpha_buf = evas_common_image_alpha_line_buffer_obtain(w);
259             if (!alpha_buf)
260               {
261                 evas_common_image_line_buffer_release(argb_buf);
262                 return;
263               }
264             bfunc = evas_common_gfx_func_composite_pixel_mask_span_get(argb_buf, dst, w, dc->render_op);
265           }
266         else
267            bfunc = evas_common_gfx_func_composite_pixel_span_get(argb_buf, dst, w, dc->render_op);
268      }
269
270    gfunc = gr->type.geometer->get_fill_func(gr, dc->render_op);
271    gdata = gr->type.gdata;
272    if (!gdata)
273      {
274         if (!direct_copy)
275           {
276             evas_common_image_line_buffer_release(argb_buf);
277             if (alpha_buf)
278                 evas_common_image_alpha_line_buffer_release(alpha_buf);
279           }
280         return;
281      }
282
283    map = gr->map.data;
284    len = gr->map.len;
285    pdst = dst->image.data + (y * dst->cache_entry.w) + x;
286    dst_end = pdst + (h * dst->cache_entry.w);
287    if (!direct_copy)
288      {
289         buf = argb_buf->image.data;
290         if (alpha_buf)
291            mask = (DATA8 *)alpha_buf->image.data;
292      }
293    else
294         buf = pdst;
295
296    while (pdst < dst_end)
297      {
298 #ifdef EVAS_SLI
299         if ((y % dc->sli.h) == dc->sli.y)
300 #endif
301           {
302              gfunc(map, len, buf, mask, w, xoff, yoff, gdata);
303              if (!direct_copy)
304                bfunc(buf, mask, 0, pdst, w);
305           }
306         buf += buf_step;
307         pdst += dst->cache_entry.w;
308         yoff++;
309 #ifdef EVAS_SLI
310         y++;
311 #endif
312      }
313
314    if (!direct_copy)
315      {
316         evas_common_image_line_buffer_release(argb_buf);
317         if (alpha_buf)
318            evas_common_image_alpha_line_buffer_release(alpha_buf);
319      }
320    evas_common_cpu_end_opt();
321 }
322
323 static void
324 _evas_common_gradient2_stops_scale(RGBA_Gradient2 *gr)
325 {
326    Eina_Inlist  *l;
327    RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
328    double  scale;
329    int  len;
330
331    if (!gr || !gr->stops.stops) return;
332
333    scale = 1.0;
334    gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
335    l = gr->stops.stops->next;
336    while (l)
337      {
338         double dp;
339
340         gc_next = (RGBA_Gradient2_Color_Np_Stop *)l;
341         dp = gc_next->pos - gc->pos;
342         if (dp > 0.000030517)
343             scale = MIN(scale, dp);
344         gc = gc_next;
345         l = l->next;
346     }
347
348    scale = 2.0 / scale;
349    len = 1;
350    gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
351    l = gr->stops.stops->next;
352    while (l)
353      {
354         int dist;
355
356         gc_next = (RGBA_Gradient2_Color_Np_Stop *)l;
357         dist = 0.5 + (scale * (gc_next->pos - gc->pos));
358         if (dist < 1)
359            dist = 1;
360         len += dist;
361         gc->dist = dist;
362         gc = gc_next;
363         l = l->next;
364      }
365
366    if (len > 65535)
367         len = 65535;
368    gr->stops.len = len;
369 }
370
371 static void
372 _evas_common_gradient2_map_argb(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
373 {
374    if (!gr || !dc)
375         return;
376    if ((len < 1) || (len > 65535))
377      {
378         if (gr->map.data)
379            free(gr->map.data);
380         gr->map.data = NULL;
381         gr->map.len = 0;
382         return;
383      }
384    if ((len != gr->map.len) || (!gr->map.data))
385         gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
386    if (!gr->map.data)
387      { gr->map.len = 0; return; }
388    gr->map.len = len;
389    gr->map.has_alpha = gr->has_alpha;
390
391    if (!gr->stops.stops) return;
392
393    _evas_common_gradient2_stops_scale(gr);
394
395      {
396         Eina_Inlist  *lc;
397         RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
398         DATA32  *pmap, *map_end;
399         DATA8   *pamap = NULL;
400         int   i, dii;
401         int   r, g, b, a;
402         int   next_r, next_g, next_b, next_a;
403         int   rr, drr, gg, dgg, bb, dbb, aa, daa;
404
405         gr->stops.cdata = realloc(gr->stops.cdata, gr->stops.len * sizeof(DATA32));
406         if (!gr->stops.cdata)  return;
407         pmap = gr->stops.cdata;  map_end = pmap + gr->stops.len;
408
409         if (gr->has_alpha)
410           {
411             gr->stops.adata = realloc(gr->stops.adata, gr->stops.len * sizeof(DATA8));
412             if (!gr->stops.adata)
413               { free(gr->stops.cdata);  gr->stops.cdata = NULL;  return; }
414             pamap = gr->stops.adata;
415           }
416
417         gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
418         r = gc->r;  g = gc->g;  b = gc->b;  a = gc->a;
419         lc = gr->stops.stops->next;
420
421         while (pmap < map_end)
422           {
423             if (lc)
424               {
425                 i = gc->dist;
426                 dii = 65536 / i;
427                 gc_next = (RGBA_Gradient2_Color_Np_Stop *)lc;
428                 next_r = gc_next->r;  next_g = gc_next->g;  next_b = gc_next->b;  next_a = gc_next->a;
429                 rr = r << 16;  drr = ((next_r - r) * dii);
430                 gg = g << 16;  dgg = ((next_g - g) * dii);
431                 bb = b << 16;  dbb = ((next_b - b) * dii);
432                 aa = a << 16;  daa = ((next_a - a) * dii);
433                 while (i--)
434                   {
435                     r = rr >> 16;  r += (rr - (r << 16)) >> 15;
436                     g = gg >> 16;  g += (gg - (g << 16)) >> 15;
437                     b = bb >> 16;  b += (bb - (b << 16)) >> 15;
438                     *pmap++ = 0xff000000 + RGB_JOIN(r,g,b);
439                     if (pamap)
440                       {
441                         a = aa >> 16;  a += (aa - (a << 16)) >> 15;
442                         *pamap++ = a;
443                         aa += daa;
444                       }
445                     rr += drr;  gg += dgg;  bb += dbb;
446                   }
447                 gc = gc_next;
448                 r = next_r;  g = next_g;  b = next_b;  a = next_a;
449                 lc = lc->next;
450               }
451             else
452               {
453                 *pmap++ = 0xff000000 + RGB_JOIN(gc->r,gc->g,gc->b);
454                 if (pamap) *pamap++ = gc->a;
455               }
456           }
457      }
458
459    if (gr->stops.cdata && gr->stops.adata)
460      {
461         evas_common_scale_rgba_a8_span(gr->stops.cdata, gr->stops.adata, gr->stops.len,
462                                         dc->mul.col, gr->map.data, gr->map.len, 1);
463         return;
464      }
465
466    evas_common_scale_rgba_span(gr->stops.cdata, NULL, gr->stops.len,
467                                 dc->mul.col, gr->map.data, gr->map.len, 1);
468    gr->map.has_alpha |= (!!(255 - (dc->mul.col >> 24)));
469 }
470
471 static void
472 _evas_common_gradient2_map_ahsv(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
473 {
474    if (!gr || !dc)
475         return;
476    if ((len < 1) || (len > 65535))
477      {
478         if (gr->map.data)
479            free(gr->map.data);
480         gr->map.data = NULL;
481         gr->map.len = 0;
482         return;
483      }
484    if ((len != gr->map.len) || (!gr->map.data))
485         gr->map.data = realloc(gr->map.data, len * sizeof(DATA32));
486    if (!gr->map.data)
487      { gr->map.len = 0; return; }
488    gr->map.len = len;
489    gr->map.has_alpha = gr->has_alpha;
490
491    if (!gr->stops.stops) return;
492
493    _evas_common_gradient2_stops_scale(gr);
494
495      {
496         Eina_Inlist  *lc;
497         RGBA_Gradient2_Color_Np_Stop  *gc, *gc_next;
498         DATA32  *pmap, *map_end;
499         DATA8   *pamap = NULL;
500         int   i, dii;
501         int   h, s, v;
502         int   next_h, next_s, next_v;
503         int   hh, dhh, ss, dss, vv, dvv, aa, daa;
504         int   r, g, b, a;
505         int   next_r, next_g, next_b, next_a;
506
507         gr->stops.cdata = realloc(gr->stops.cdata, gr->stops.len * sizeof(DATA32));
508         if (!gr->stops.cdata)  return;
509         pmap = gr->stops.cdata;  map_end = pmap + gr->stops.len;
510
511         if (gr->has_alpha)
512           {
513             gr->stops.adata = realloc(gr->stops.adata, gr->stops.len * sizeof(DATA8));
514             if (!gr->stops.adata)
515               { free(gr->stops.cdata);  gr->stops.cdata = NULL;  return; }
516             pamap = gr->stops.adata;
517           }
518
519         gc = (RGBA_Gradient2_Color_Np_Stop *)gr->stops.stops;
520         r = gc->r;  g = gc->g;  b = gc->b;  a = gc->a;
521         evas_common_convert_color_rgb_to_hsv_int(r, g, b, &h, &s, &v);
522         lc = gr->stops.stops->next;
523
524         while (pmap < map_end)
525           {
526             if (lc)
527               {
528                 i = gc->dist;
529                 dii = 65536 / i;
530                 gc_next = (RGBA_Gradient2_Color_Np_Stop *)lc;
531
532                 next_r = gc_next->r;  next_g = gc_next->g;  next_b = gc_next->b;  next_a = gc_next->a;
533                 evas_common_convert_color_rgb_to_hsv_int(next_r, next_g, next_b,
534                                                          &next_h, &next_s, &next_v);
535                 hh = h << 16;  dhh = ((next_h - h) * dii);
536                 ss = s << 16;  dss = ((next_s - s) * dii);
537                 vv = v << 16;  dvv = ((next_v - v) * dii);
538                 aa = a << 16;  daa = ((next_a - a) * dii);
539                 while (i--)
540                   {
541                     h = hh >> 16;  h += (hh - (h << 16)) >> 15;
542                     s = ss >> 16;  s += (ss - (s << 16)) >> 15;
543                     v = vv >> 16;  v += (vv - (v << 16)) >> 15;
544                     evas_common_convert_color_hsv_to_rgb_int(h, s, v, &r, &g, &b);
545                     *pmap++ = 0xff000000 + RGB_JOIN(r,g,b);
546                     if (pamap)
547                       {
548                         a = aa >> 16;  a += (aa - (a << 16)) >> 15;
549                         *pamap++ = a;
550                         aa += daa;
551                       }
552                     hh += dhh;  ss += dss;  vv += dvv;
553                   }
554                 gc = gc_next;
555                 h = next_h;  s = next_s;  v = next_v;  a = next_a;
556                 lc = lc->next;
557               }
558             else
559               {
560                 *pmap++ = 0xff000000 + RGB_JOIN(gc->r,gc->g,gc->b);
561                 if (pamap) *pamap++ = gc->a;
562               }
563           }
564      }
565
566    if (gr->stops.cdata && gr->stops.adata)
567      {
568         evas_common_scale_hsva_a8_span(gr->stops.cdata, gr->stops.adata, gr->stops.len,
569                                            dc->mul.col, gr->map.data, gr->map.len, 1);
570         return;
571      }
572    evas_common_scale_hsva_span(gr->stops.cdata, NULL, gr->stops.len,
573                                 dc->mul.col, gr->map.data, gr->map.len, 1);
574    gr->map.has_alpha |= (!!(255 - (dc->mul.col >> 24)));
575 }
576
577 EAPI void
578 evas_common_gradient2_map(RGBA_Draw_Context *dc, RGBA_Gradient2 *gr, int len)
579 {
580    if (!gr || !dc) return;
581    if (dc->interpolation.color_space == _EVAS_COLOR_SPACE_AHSV)
582      {
583         _evas_common_gradient2_map_ahsv(dc, gr, len);
584         return;
585      }
586    _evas_common_gradient2_map_argb(dc, gr, len);
587 }