remove xcb support in ecore_x and evas engines as per mailing list
[platform/upstream/efl.git] / src / lib / ecore_x / ecore_x_image.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <stddef.h>
8 #else
9 # ifdef HAVE_STDLIB_H
10 #  include <stdlib.h>
11 # endif
12 #endif
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/ipc.h>
17 #include <sys/shm.h>
18
19 #include "ecore_x_private.h"
20 #include "Ecore_X.h"
21
22 #include <X11/extensions/XShm.h>
23 #include <X11/Xutil.h>
24
25 static int _ecore_x_image_shm_can = -1;
26 static int _ecore_x_image_err = 0;
27
28 static int
29 _ecore_x_image_error_handler(Display *d EINA_UNUSED, XErrorEvent *ev)
30 {
31    _ecore_x_image_err = 1;
32    switch (ev->error_code)
33      {
34       case BadRequest:  /* bad request code */
35         ERR("BadRequest");
36         break;
37       case BadValue:    /* int parameter out of range */
38         ERR("BadValue");
39         break;
40       case BadWindow:   /* parameter not a Window */
41         ERR("BadWindow");
42         break;
43       case BadPixmap:   /* parameter not a Pixmap */
44         ERR("BadPixmap");
45         break;
46       case BadAtom:     /* parameter not an Atom */
47         ERR("BadAtom");
48         break;
49       case BadCursor:   /* parameter not a Cursor */
50         ERR("BadCursor");
51         break;
52       case BadFont:     /* parameter not a Font */
53         ERR("BadFont");
54         break;
55       case BadMatch:    /* parameter mismatch */
56         ERR("BadMatch");
57         break;
58       case BadDrawable: /* parameter not a Pixmap or Window */
59         ERR("BadDrawable");
60         break;
61       case BadAccess:   /* depending on context */
62         ERR("BadAccess");
63         break;
64       case BadAlloc:    /* insufficient resources */
65         ERR("BadAlloc");
66         break;
67       case BadColor:    /* no such colormap */
68         ERR("BadColor");
69         break;
70       case BadGC:       /* parameter not a GC */
71         ERR("BadGC");
72         break;
73       case BadIDChoice: /* choice not in range or already used */
74         ERR("BadIDChoice");
75         break;
76       case BadName:     /* font or color name doesn't exist */
77         ERR("BadName");
78         break;
79       case BadLength:   /* Request length incorrect */
80         ERR("BadLength");
81         break;
82       case BadImplementation:   /* server is defective */
83         ERR("BadImplementation");
84         break;
85      }
86    return 0;
87 }
88
89 int
90 _ecore_x_image_shm_check(void)
91 {
92    XErrorHandler ph;
93    XShmSegmentInfo shminfo;
94    XImage *xim;
95
96    if (_ecore_x_image_shm_can != -1)
97      return _ecore_x_image_shm_can;
98
99    if (!XShmQueryExtension(_ecore_x_disp))
100      {
101         _ecore_x_image_shm_can = 0;
102         return _ecore_x_image_shm_can;
103      }
104    
105    XSync(_ecore_x_disp, False);
106    _ecore_x_image_err = 0;
107
108    xim = XShmCreateImage(_ecore_x_disp,
109                          DefaultVisual(_ecore_x_disp,
110                                        DefaultScreen(_ecore_x_disp)),
111                          DefaultDepth(_ecore_x_disp,
112                                       DefaultScreen(_ecore_x_disp)),
113                          ZPixmap, NULL,
114                          &shminfo, 1, 1);
115    if (_ecore_xlib_sync) ecore_x_sync();
116    if (!xim)
117      {
118         _ecore_x_image_shm_can = 0;
119         return _ecore_x_image_shm_can;
120      }
121
122    shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
123                           IPC_CREAT | 0600);
124    if (shminfo.shmid == -1)
125      {
126         ERR("%s", strerror(errno));
127         XDestroyImage(xim);
128         _ecore_x_image_shm_can = 0;
129         return _ecore_x_image_shm_can;
130      }
131
132    shminfo.readOnly = False;
133    shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
134    xim->data = shminfo.shmaddr;
135
136    if (xim->data == (char *)-1)
137      {
138         XDestroyImage(xim);
139         _ecore_x_image_shm_can = 0;
140         return _ecore_x_image_shm_can;
141      }
142
143    ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
144    XShmAttach(_ecore_x_disp, &shminfo);
145    XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp),
146                 xim, 0, 0, 0xffffffff);
147    XSync(_ecore_x_disp, False);
148    XSetErrorHandler((XErrorHandler)ph);
149    if (_ecore_x_image_err)
150      {
151         XShmDetach(_ecore_x_disp, &shminfo);
152         XDestroyImage(xim);
153         shmdt(shminfo.shmaddr);
154         shmctl(shminfo.shmid, IPC_RMID, 0);
155         _ecore_x_image_shm_can = 0;
156         return _ecore_x_image_shm_can;
157      }
158
159    XShmDetach(_ecore_x_disp, &shminfo);
160    XDestroyImage(xim);
161    shmdt(shminfo.shmaddr);
162    shmctl(shminfo.shmid, IPC_RMID, 0);
163
164    _ecore_x_image_shm_can = 1;
165    return _ecore_x_image_shm_can;
166 }
167
168 struct _Ecore_X_Image
169 {
170    XShmSegmentInfo shminfo;
171    Ecore_X_Visual  vis;
172    XImage         *xim;
173    int             depth;
174    int             w, h;
175    int             bpl, bpp, rows;
176    unsigned char  *data;
177    Eina_Bool       shm : 1;
178 };
179
180 EAPI Ecore_X_Image *
181 ecore_x_image_new(int w,
182                   int h,
183                   Ecore_X_Visual vis,
184                   int depth)
185 {
186    Ecore_X_Image *im;
187
188    im = calloc(1, sizeof(Ecore_X_Image));
189    if (!im)
190      return NULL;
191
192    LOGFN(__FILE__, __LINE__, __FUNCTION__);
193    im->w = w;
194    im->h = h;
195    im->vis = vis;
196    im->depth = depth;
197    if (depth <= 8) im->bpp = 1;
198    else if (depth <= 16) im->bpp = 2;
199    else if (depth <= 24) im->bpp = 3;
200    else im->bpp = 4;
201    _ecore_x_image_shm_check();
202    im->shm = _ecore_x_image_shm_can;
203    return im;
204 }
205
206 EAPI void
207 ecore_x_image_free(Ecore_X_Image *im)
208 {
209    LOGFN(__FILE__, __LINE__, __FUNCTION__);
210    if (im->shm)
211      {
212         if (im->xim)
213           {
214              XShmDetach(_ecore_x_disp, &(im->shminfo));
215              XDestroyImage(im->xim);
216              shmdt(im->shminfo.shmaddr);
217              shmctl(im->shminfo.shmid, IPC_RMID, 0);
218           }
219      }
220    else if (im->xim)
221      {
222         free(im->xim->data);
223         im->xim->data = NULL;
224         XDestroyImage(im->xim);
225      }
226
227    free(im);
228 }
229
230 static void
231 _ecore_x_image_finalize(Ecore_X_Image *im)
232 {
233    im->data = (unsigned char *)im->xim->data;
234    im->bpl = im->xim->bytes_per_line;
235    im->rows = im->xim->height;
236    if (im->xim->bits_per_pixel <= 8) im->bpp = 1;
237    else if (im->xim->bits_per_pixel <= 16) im->bpp = 2;
238    else if (im->xim->bits_per_pixel <= 24) im->bpp = 3;
239    else im->bpp = 4;
240 }
241
242 static void
243 _ecore_x_image_shm_create(Ecore_X_Image *im)
244 {
245    im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth,
246                              ZPixmap, NULL, &(im->shminfo),
247                              im->w, im->h);
248    if (!im->xim)
249      return;
250
251    im->shminfo.shmid = shmget(IPC_PRIVATE,
252                               im->xim->bytes_per_line * im->xim->height,
253                               IPC_CREAT | 0600);
254    if (im->shminfo.shmid == -1)
255      {
256         ERR("shmget failed: %s", strerror(errno));
257         XDestroyImage(im->xim);
258         im->xim = NULL;
259         return;
260      }
261
262    im->shminfo.readOnly = False;
263    im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
264    im->xim->data = im->shminfo.shmaddr;
265    if ((im->xim->data == (char *)-1) ||
266        (!im->xim->data))
267      {
268         ERR("shmat failed: %s", strerror(errno));
269         shmdt(im->shminfo.shmaddr);
270         shmctl(im->shminfo.shmid, IPC_RMID, 0);
271         XDestroyImage(im->xim);
272         im->xim = NULL;
273         return;
274      }
275
276    XShmAttach(_ecore_x_disp, &im->shminfo);
277    _ecore_x_image_finalize(im);
278 }
279
280 static void
281 _ecore_x_image_create(Ecore_X_Image *im)
282 {
283    im->xim = XCreateImage(_ecore_x_disp, im->vis, im->depth,
284                           ZPixmap, 0, NULL, im->w, im->h, 32, 0);
285    if (!im->xim) return;
286    im->xim->data = malloc(im->xim->bytes_per_line * im->h);
287    if (!im->xim->data)
288      {
289         XDestroyImage(im->xim);
290         im->xim = NULL;
291         return;
292      }
293    _ecore_x_image_finalize(im);
294 }
295
296 EAPI Eina_Bool
297 ecore_x_image_get(Ecore_X_Image *im,
298                   Ecore_X_Drawable draw,
299                   int x,
300                   int y,
301                   int sx,
302                   int sy,
303                   int w,
304                   int h)
305 {
306    Eina_Bool ret = EINA_TRUE;
307    XErrorHandler ph;
308
309    LOGFN(__FILE__, __LINE__, __FUNCTION__);
310    if (im->shm)
311      {
312         if (!im->xim) _ecore_x_image_shm_create(im);
313
314         if (!im->xim)
315           return EINA_FALSE;
316
317         _ecore_x_image_err = 0;
318
319         ecore_x_sync();
320         // optimised path
321         ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
322         if ((sx == 0) && (w == im->w))
323           {
324              im->xim->data = (char *)
325                im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp);
326              im->xim->width = MIN(w, im->w);
327              im->xim->height = MIN(h, im->h);
328              XGrabServer(_ecore_x_disp);
329              if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff))
330                ret = EINA_FALSE;
331              XUngrabServer(_ecore_x_disp);
332              ecore_x_sync();
333           }
334         // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it
335         else
336           {
337              Ecore_X_Image *tim;
338              unsigned char *spixels, *sp, *pixels, *p;
339              int bpp, bpl, rows, sbpp, sbpl, srows;
340              int r;
341
342              tim = ecore_x_image_new(w, h, im->vis, im->depth);
343              if (tim)
344                {
345                   ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
346                   if (ret)
347                     {
348                        spixels = ecore_x_image_data_get(tim,
349                                                         &sbpl,
350                                                         &srows,
351                                                         &sbpp);
352                        pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
353                        if ((pixels) && (spixels))
354                          {
355                             p = pixels + (sy * bpl) + (sx * bpp);
356                             sp = spixels;
357                             for (r = srows; r > 0; r--)
358                               {
359                                  memcpy(p, sp, sbpl);
360                                  p += bpl;
361                                  sp += sbpl;
362                               }
363                          }
364                     }
365
366                   ecore_x_image_free(tim);
367                }
368           }
369
370         XSetErrorHandler((XErrorHandler)ph);
371         if (_ecore_x_image_err)
372           ret = EINA_FALSE;
373      }
374    else
375      {
376         if (!im->xim)
377           _ecore_x_image_create(im);
378
379         if (!im->xim)
380           return EINA_FALSE;
381
382         if (XGetSubImage(_ecore_x_disp, draw, sx, sy, w, h,
383                          0xffffffff, ZPixmap, im->xim, x, y) != im->xim)
384           ret = EINA_FALSE;
385      }
386
387    return ret;
388 }
389
390 EAPI void
391 ecore_x_image_put(Ecore_X_Image *im,
392                   Ecore_X_Drawable draw,
393                   Ecore_X_GC gc,
394                   int x,
395                   int y,
396                   int sx,
397                   int sy,
398                   int w,
399                   int h)
400 {
401    Ecore_X_GC tgc = 0;
402
403    LOGFN(__FILE__, __LINE__, __FUNCTION__);
404    if (!gc)
405      {
406         XGCValues gcv;
407         memset(&gcv, 0, sizeof(gcv));
408         gcv.subwindow_mode = IncludeInferiors;
409         tgc = XCreateGC(_ecore_x_disp, draw, GCSubwindowMode, &gcv);
410         if (_ecore_xlib_sync) ecore_x_sync();
411         gc = tgc;
412      }
413    if (!im->xim)
414      {
415         if (im->shm) _ecore_x_image_shm_create(im);
416         else _ecore_x_image_create(im);
417      }
418    if (im->xim)
419      {
420         if (im->shm)
421           XShmPutImage(_ecore_x_disp, draw, gc, im->xim,
422                        sx, sy, x, y, w, h, False);
423         else
424           XPutImage(_ecore_x_disp, draw, gc, im->xim,
425                     sx, sy, x, y, w, h);
426         if (_ecore_xlib_sync) ecore_x_sync();
427      }
428    if (tgc) ecore_x_gc_free(tgc);
429 }
430
431 EAPI void *
432 ecore_x_image_data_get(Ecore_X_Image *im,
433                        int *bpl,
434                        int *rows,
435                        int *bpp)
436 {
437    LOGFN(__FILE__, __LINE__, __FUNCTION__);
438    if (!im->xim)
439      {
440         if (im->shm) _ecore_x_image_shm_create(im);
441         else _ecore_x_image_create(im);
442         if (!im->xim) return NULL;
443      }
444    if (bpl) *bpl = im->bpl;
445    if (rows) *rows = im->rows;
446    if (bpp) *bpp = im->bpp;
447    return im->data;
448 }
449
450 EAPI Eina_Bool
451 ecore_x_image_is_argb32_get(Ecore_X_Image *im)
452 {
453    Visual *vis = im->vis;
454    if (((vis->class == TrueColor) ||
455         (vis->class == DirectColor)) &&
456        (im->bpp == 4) &&
457        (vis->red_mask == 0xff0000) &&
458        (vis->green_mask == 0x00ff00) &&
459        (vis->blue_mask == 0x0000ff))
460      {
461 #ifdef WORDS_BIGENDIAN
462         if (BitmapBitOrder(_ecore_x_disp) == MSBFirst) return EINA_TRUE;
463 #else
464         if (BitmapBitOrder(_ecore_x_disp) == LSBFirst) return EINA_TRUE;
465 #endif
466      }
467    return EINA_FALSE;
468 }
469
470 EAPI Eina_Bool
471 ecore_x_image_to_argb_convert(void *src,
472                               int sbpp,
473                               int sbpl,
474                               Ecore_X_Colormap c,
475                               Ecore_X_Visual v,
476                               int x,
477                               int y,
478                               int w,
479                               int h,
480                               unsigned int *dst,
481                               int dbpl,
482                               int dx,
483                               int dy)
484 {
485    Visual *vis = v;
486    XColor *cols = NULL;
487    int n = 0, nret = 0, i, row;
488    unsigned int pal[256], r, g, b;
489    enum
490    {
491       rgbnone = 0,
492       rgb565,
493       bgr565,
494       rgbx555,
495       rgb888,
496       bgr888,
497       argbx888,
498       abgrx888,
499       rgba888x,
500       bgra888x,
501       argbx666
502    };
503    int mode = 0;
504
505    sbpp *= 8;
506
507    n = vis->map_entries;
508    if ((n <= 256) &&
509        ((vis->class == PseudoColor) ||
510         (vis->class == StaticColor) ||
511         (vis->class == GrayScale) ||
512         (vis->class == StaticGray)))
513      {
514         if (!c)
515           c = DefaultColormap(_ecore_x_disp,
516                               DefaultScreen(_ecore_x_disp));
517         cols = alloca(n * sizeof(XColor));
518         for (i = 0; i < n; i++)
519           {
520              cols[i].pixel = i;
521              cols[i].flags = DoRed | DoGreen | DoBlue;
522              cols[i].red = 0;
523              cols[i].green = 0;
524              cols[i].blue = 0;
525           }
526         XQueryColors(_ecore_x_disp, c, cols, n);
527         for (i = 0; i < n; i++)
528           {
529              pal[i] = 0xff000000 |
530                ((cols[i].red >> 8) << 16) |
531                ((cols[i].green >> 8) << 8) |
532                ((cols[i].blue >> 8));
533           }
534         nret = n;
535      }
536    else if ((vis->class == TrueColor) ||
537             (vis->class == DirectColor))
538      {
539         if (sbpp == 24)
540           {
541              if ((vis->red_mask == 0x00ff0000) &&
542                  (vis->green_mask == 0x0000ff00) &&
543                  (vis->blue_mask == 0x000000ff))
544                mode = rgb888;
545              else if ((vis->red_mask == 0x000000ff) &&
546                       (vis->green_mask == 0x0000ff00) &&
547                       (vis->blue_mask == 0x00ff0000))
548                mode = bgr888;
549              else
550                return EINA_FALSE;
551           }
552         else
553           {
554              if ((vis->red_mask == 0x00ff0000) &&
555                  (vis->green_mask == 0x0000ff00) &&
556                  (vis->blue_mask == 0x000000ff))
557                mode = argbx888;
558              else if ((vis->red_mask == 0x000000ff) &&
559                       (vis->green_mask == 0x0000ff00) &&
560                       (vis->blue_mask == 0x00ff0000))
561                mode = abgrx888;
562              else if ((vis->red_mask == 0xff000000) &&
563                       (vis->green_mask == 0x00ff0000) &&
564                       (vis->blue_mask == 0x0000ff00))
565                mode = rgba888x;
566              else if ((vis->red_mask == 0x0000ff00) &&
567                       (vis->green_mask == 0x00ff0000) &&
568                       (vis->blue_mask == 0xff000000))
569                mode = bgra888x;
570              else if ((vis->red_mask == 0x0003f000) &&
571                       (vis->green_mask == 0x00000fc0) &&
572                       (vis->blue_mask == 0x0000003f))
573                mode = argbx666;
574              else if ((vis->red_mask == 0x0000f800) &&
575                       (vis->green_mask == 0x000007e0) &&
576                       (vis->blue_mask == 0x0000001f))
577                mode = rgb565;
578              else if ((vis->red_mask == 0x0000001f) &&
579                       (vis->green_mask == 0x000007e0) &&
580                       (vis->blue_mask == 0x0000f800))
581                mode = bgr565;
582              else if ((vis->red_mask == 0x00007c00) &&
583                       (vis->green_mask == 0x000003e0) &&
584                       (vis->blue_mask == 0x0000001f))
585                mode = rgbx555;
586              else
587                return EINA_FALSE;
588           }
589      }
590    for (row = 0; row < h; row++)
591      {
592         unsigned char *s8;
593         unsigned short *s16;
594         unsigned int *s32;
595         unsigned int *dp, *de;
596
597         dp = ((unsigned int *)(((unsigned char *)dst) +
598                                ((dy + row) * dbpl))) + dx;
599         de = dp + w;
600         switch (sbpp)
601           {
602            case 8:
603              s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
604              if (nret > 0)
605                {
606                   while (dp < de)
607                     {
608                        *dp = pal[*s8];
609                        s8++; dp++;
610                     }
611                }
612              else
613                return EINA_FALSE;
614              break;
615
616            case 16:
617              s16 = ((unsigned short *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
618              switch (mode)
619                {
620                 case rgb565:
621                   while (dp < de)
622                     {
623                        r = (*s16 & 0xf800) << 8;
624                        g = (*s16 & 0x07e0) << 5;
625                        b = (*s16 & 0x001f) << 3;
626                        r |= (r >> 5) & 0xff0000;
627                        g |= (g >> 6) & 0x00ff00;
628                        b |= (b >> 5);
629                        *dp = 0xff000000 | r | g | b;
630                        s16++; dp++;
631                     }
632                   break;
633
634                 case bgr565:
635                   while (dp < de)
636                     {
637                        r = (*s16 & 0x001f) << 19;
638                        g = (*s16 & 0x07e0) << 5;
639                        b = (*s16 & 0xf800) >> 8;
640                        r |= (r >> 5) & 0xff0000;
641                        g |= (g >> 6) & 0x00ff00;
642                        b |= (b >> 5);
643                        *dp = 0xff000000 | r | g | b;
644                        s16++; dp++;
645                     }
646                   break;
647
648                 case rgbx555:
649                   while (dp < de)
650                     {
651                        r = (*s16 & 0x7c00) << 9;
652                        g = (*s16 & 0x03e0) << 6;
653                        b = (*s16 & 0x001f) << 3;
654                        r |= (r >> 5) & 0xff0000;
655                        g |= (g >> 5) & 0x00ff00;
656                        b |= (b >> 5);
657                        *dp = 0xff000000 | r | g | b;
658                        s16++; dp++;
659                     }
660                   break;
661
662                 default:
663                   return EINA_FALSE;
664                   break;
665                }
666              break;
667
668            case 24:
669              s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + (x * (sbpp / 8));
670              switch (mode)
671                {
672                 case rgb888:
673                   while (dp < de)
674                     {
675                        *dp = 0xff000000 | (s8[2] << 16) | (s8[1] << 8) | s8[0];
676                        s8 += 3; dp++;
677                     }
678                   break;
679                 case bgr888:
680                   while (dp < de)
681                     {
682                        *dp = 0xff000000 | (s8[0] << 16) | (s8[1] << 8) | s8[2];
683                        s8 += 3; dp++;
684                     }
685                   break;
686                 default:
687                   return EINA_FALSE;
688                   break;
689                }
690              break;
691              
692            case 32:
693              s32 = ((unsigned int *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
694              switch (mode)
695                {
696                 case argbx888:
697                   while (dp < de)
698                     {
699                        *dp = 0xff000000 | *s32;
700                        s32++; dp++;
701                     }
702                   break;
703
704                 case abgrx888:
705                   while (dp < de)
706                     {
707                        r = *s32 & 0x000000ff;
708                        g = *s32 & 0x0000ff00;
709                        b = *s32 & 0x00ff0000;
710                        *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
711                        s32++; dp++;
712                     }
713                   break;
714
715                 case rgba888x:
716                   while (dp < de)
717                     {
718                        *dp = 0xff000000 | (*s32 >> 8);
719                        s32++; dp++;
720                     }
721                   break;
722
723                 case bgra888x:
724                   while (dp < de)
725                     {
726                        r = *s32 & 0x0000ff00;
727                        g = *s32 & 0x00ff0000;
728                        b = *s32 & 0xff000000;
729                        *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
730                        s32++; dp++;
731                     }
732                   break;
733
734                 case argbx666:
735                   while (dp < de)
736                     {
737                        r = (*s32 & 0x3f000) << 6;
738                        g = (*s32 & 0x00fc0) << 4;
739                        b = (*s32 & 0x0003f) << 2;
740                        r |= (r >> 6) & 0xff0000;
741                        g |= (g >> 6) & 0x00ff00;
742                        b |= (b >> 6);
743                        *dp = 0xff000000 | r | g | b;
744                        s32++; dp++;
745                     }
746                   break;
747
748                 default:
749                   return EINA_FALSE;
750                   break;
751                }
752              break;
753
754            default:
755              return EINA_FALSE;
756              break;
757           }
758      }
759    return EINA_TRUE;
760 }