evas: Introduce pixel_alpha_get()
authorPaulo C. A. Cavalcanti Jr <paulo.cavalcanti@intel.com>
Sat, 16 Feb 2013 10:10:47 +0000 (11:10 +0100)
committerCedric BAIL <cedric@efl.so>
Sat, 16 Feb 2013 10:14:40 +0000 (11:14 +0100)
The _pixel_alpha_get() function used in evas_object_image_is_inside won't
work with engines other than software - since it relies on engine data
being *always* RGBA_Image * - which is wrong for OpenGL backend that uses
Evas_GL_Image * for "engine_data" pointer.

AUTHORS
ChangeLog
NEWS
src/lib/evas/canvas/evas_object_image.c
src/lib/evas/include/evas_private.h
src/modules/evas/engines/gl_x11/evas_engine.c
src/modules/evas/engines/software_generic/evas_engine.c

diff --git a/AUTHORS b/AUTHORS
index 32fe9ea..430e431 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -122,6 +122,8 @@ Eduardo Lima (Etrunko) <eblima@gmail.com>
 Leandro Dorileo (dorileo) <dorileo@profusion.mobi>
 Patryk Kaczmarek <patryk.k@samsung.com>
 Zbigniew Kosinski <z.kosinski@samsung.com>
+Paulo C. A. Cavalcanti Jr <paulo.cavalcanti@intel.com>
+
 
 Ecore
 -----
index dfb55b6..392ee8f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-02-16  Paulo C. A. Cavalcanti Jr
+
+       * Evas: add pixels_alpha_get to evas engine.
+
 2013-02-16  Cedric Bail
 
        * Eina: improved Eina_Clist support for 64bits system.
diff --git a/NEWS b/NEWS
index a5c702a..b70c510 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -53,6 +53,7 @@ Additions:
      - Add ellipsis support in Evas_Object_Text.
      - Add EVAS_GL_LINE_OFFSET_HACK_DISABLE to turn off line shift correction by evas.
      - Add EVAS_GL_DIRECT_MEM_OPT to enable on-demand fallback memory allocation policy for EvasGL direct rendering.
+     - Add engine specific alpha_get.
     * Add ecore_audio API
     * Added eina_xattr_fd_get(), eina_xattr_fd_set(),
       eina_xattr_del(), eina_xattr_fd_del(), eina_xattr_copy() and
index f3492e2..b3df22b 100644 (file)
@@ -4459,83 +4459,13 @@ evas_object_image_was_opaque(Evas_Object *eo_obj, Evas_Object_Protected_Data *ob
    return obj->prev.opaque;
 }
 
-static inline Eina_Bool
-_pixel_alpha_get(RGBA_Image *im, int x, int y, DATA8 *alpha,
-                 int src_region_x, int src_region_y, int src_region_w, int src_region_h,
-                 int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h)
-{
-   int px, py, dx, dy, sx, sy, src_w, src_h;
-   double scale_w, scale_h;
-
-   if ((dst_region_x > x) || (x >= (dst_region_x + dst_region_w)) ||
-       (dst_region_y > y) || (y >= (dst_region_y + dst_region_h)))
-     {
-        *alpha = 0;
-        return EINA_FALSE;
-     }
-
-   src_w = im->cache_entry.w;
-   src_h = im->cache_entry.h;
-   if ((src_w == 0) || (src_h == 0))
-     {
-        *alpha = 0;
-        return EINA_TRUE;
-     }
-
-   EINA_SAFETY_ON_TRUE_GOTO(src_region_x < 0, error_oob);
-   EINA_SAFETY_ON_TRUE_GOTO(src_region_y < 0, error_oob);
-   EINA_SAFETY_ON_TRUE_GOTO(src_region_x + src_region_w > src_w, error_oob);
-   EINA_SAFETY_ON_TRUE_GOTO(src_region_y + src_region_h > src_h, error_oob);
-
-   scale_w = (double)dst_region_w / (double)src_region_w;
-   scale_h = (double)dst_region_h / (double)src_region_h;
-
-   /* point at destination */
-   dx = x - dst_region_x;
-   dy = y - dst_region_y;
-
-   /* point at source */
-   sx = dx / scale_w;
-   sy = dy / scale_h;
-
-   /* pixel point (translated) */
-   px = src_region_x + sx;
-   py = src_region_y + sy;
-   EINA_SAFETY_ON_TRUE_GOTO(px >= src_w, error_oob);
-   EINA_SAFETY_ON_TRUE_GOTO(py >= src_h, error_oob);
-
-   switch (im->cache_entry.space)
-     {
-     case EVAS_COLORSPACE_ARGB8888:
-       {
-          DATA32 *pixel = im->image.data;
-          pixel += ((py * src_w) + px);
-          *alpha = ((*pixel) >> 24) & 0xff;
-       }
-       break;
-
-     default:
-        ERR("Colorspace %d not supported.", im->cache_entry.space);
-        *alpha = 0;
-     }
-
-   return EINA_TRUE;
-
- error_oob:
-   ERR("Invalid region src=(%d, %d, %d, %d), dst=(%d, %d, %d, %d), image=%dx%d",
-       src_region_x, src_region_y, src_region_w, src_region_h,
-       dst_region_x, dst_region_y, dst_region_w, dst_region_h,
-       src_w, src_h);
-   *alpha = 0;
-   return EINA_TRUE;
-}
-
 static int
 evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Coord px, Evas_Coord py)
 {
    Evas_Object_Image *o = eo_data_get(eo_obj, MY_CLASS);
    int imagew, imageh, uvw, uvh;
    void *pixels;
+   Evas_Func *eng = obj->layer->evas->engine.func;\r
    int is_inside = 0;
 
    /* the following code is similar to evas_object_image_render(), but doesn't
@@ -4609,7 +4539,7 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
           }
         else
           {
-             RGBA_Image *im;
+             void *im;\r
              DATA32 *data = NULL;
              int err = 0;
 
@@ -4617,7 +4547,8 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                (obj->layer->evas->engine.data.output, pixels, 0, &data, &err);
              if ((!im) || (!data) || (err))
                {
-                  ERR("Couldn't get image pixels RGBA_Image %p: im=%p, data=%p, err=%d", pixels, im, data, err);
+                  ERR("Couldn't get image pixels %p: im=%p, data=%p, err=%d",\r
+                      pixels, im, data, err);\r
                   goto end;
                }
 
@@ -4665,7 +4596,13 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                              */
                               {
                                  DATA8 alpha = 0;
-                                 if (_pixel_alpha_get(pixels, px, py, &alpha, 0, 0, imagew, imageh, obj->cur.geometry.x + ix, obj->cur.geometry.y + iy, iw, ih))
+\r
+                                 if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                          0, 0,\r
+                                                          imagew, imageh,\r
+                                                          obj->cur.geometry.x + ix,\r
+                                                          obj->cur.geometry.y + iy,\r
+                                                          iw, ih))\r
                                    {
                                       is_inside = alpha > 0;
                                       dobreak_h = 1;
@@ -4726,7 +4663,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = bl; inh = bt;
                             outx = ox; outy = oy;
                             outw = bsl; outh = bst;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4740,7 +4679,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = imw - bl - br; inh = bt;
                             outx = ox + bsl; outy = oy;
                             outw = iw - bsl - bsr; outh = bst;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4753,7 +4694,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = br; inh = bt;
                             outx = ox + iw - bsr; outy = oy;
                             outw = bsr; outh = bst;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4761,12 +4704,14 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                                  break;
                               }
                             // .--
-                            // #  
+                            // #\r
                             inx = 0; iny = bt;
                             inw = bl; inh = imh - bt - bb;
                             outx = ox; outy = oy + bst;
                             outw = bsl; outh = ih - bst - bsb;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4781,7 +4726,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                                  inw = imw - bl - br; inh = imh - bt - bb;
                                  outx = ox + bsl; outy = oy + bst;
                                  outw = iw - bsl - bsr; outh = ih - bst - bsb;
-                                 if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                                 if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                          inx, iny, inw, inh,\r
+                                                          outx, outy, outw, outh))\r
                                    {
                                       is_inside = alpha > 0;
                                       dobreak_h = 1;
@@ -4795,7 +4742,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = br; inh = imh - bt - bb;
                             outx = ox + iw - bsr; outy = oy + bst;
                             outw = bsr; outh = ih - bst - bsb;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4808,7 +4757,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = bl; inh = bb;
                             outx = ox; outy = oy + ih - bsb;
                             outw = bsl; outh = bsb;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4821,7 +4772,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = imw - bl - br; inh = bb;
                             outx = ox + bsl; outy = oy + ih - bsb;
                             outw = iw - bsl - bsr; outh = bsb;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
@@ -4834,7 +4787,9 @@ evas_object_image_is_inside(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj
                             inw = br; inh = bb;
                             outx = ox + iw - bsr; outy = oy + ih - bsb;
                             outw = bsr; outh = bsb;
-                            if (_pixel_alpha_get(pixels, px, py, &alpha, inx, iny, inw, inh, outx, outy, outw, outh))
+                            if (eng->pixel_alpha_get(pixels, px, py, &alpha,\r
+                                                     inx, iny, inw, inh,\r
+                                                     outx, outy, outw, outh))\r
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
index 9f377e4..088107e 100644 (file)
@@ -905,6 +905,8 @@ struct _Evas_Func
 
    /* multiple font draws */
    Eina_Bool (*multi_font_draw)          (void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w, int h, int ow, int oh, Evas_Font_Array *texts, Eina_Bool do_async);
+\r
+   Eina_Bool (*pixel_alpha_get)          (void *image, int x, int y, DATA8 *alpha, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);\r
 };
 
 struct _Evas_Image_Load_Func
index 9b059fc..f273959 100644 (file)
@@ -2866,6 +2866,87 @@ eng_image_max_size_get(void *data, int *maxw, int *maxh)
    if (maxh) *maxh = re->win->gl_context->shared->info.max_texture_size;
 }
 
+static Eina_Bool\r
+eng_pixel_alpha_get(void *image, int x, int y, DATA8 *alpha, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h)\r
+{\r
+   Evas_GL_Image *im = image;\r
+   int px, py, dx, dy, sx, sy, src_w, src_h;\r
+   double scale_w, scale_h;\r
+\r
+   if (!im) return EINA_FALSE;\r
+\r
+   if ((dst_region_x > x) || (x >= (dst_region_x + dst_region_w)) ||\r
+       (dst_region_y > y) || (y >= (dst_region_y + dst_region_h)))\r
+     {\r
+        *alpha = 0;\r
+        return EINA_FALSE;\r
+     }\r
+\r
+   src_w = im->im->cache_entry.w;\r
+   src_h = im->im->cache_entry.h;\r
+   if ((src_w == 0) || (src_h == 0))\r
+     {\r
+        *alpha = 0;\r
+        return EINA_TRUE;\r
+     }\r
+\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_x < 0, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_y < 0, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_x + src_region_w > src_w, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_y + src_region_h > src_h, error_oob);\r
+\r
+   scale_w = (double)dst_region_w / (double)src_region_w;\r
+   scale_h = (double)dst_region_h / (double)src_region_h;\r
+\r
+   /* point at destination */\r
+   dx = x - dst_region_x;\r
+   dy = y - dst_region_y;\r
+\r
+   /* point at source */\r
+   sx = dx / scale_w;\r
+   sy = dy / scale_h;\r
+\r
+   /* pixel point (translated) */\r
+   px = src_region_x + sx;\r
+   py = src_region_y + sy;\r
+   EINA_SAFETY_ON_TRUE_GOTO(px >= src_w, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(py >= src_h, error_oob);\r
+\r
+   switch (im->im->cache_entry.space)\r
+     {\r
+     case EVAS_COLORSPACE_ARGB8888:\r
+       {\r
+          DATA32 *pixel;\r
+\r
+          evas_cache_image_load_data(&im->im->cache_entry);\r
+          if (!im->im->cache_entry.flags.loaded)\r
+            {\r
+               ERR("im %p has no pixels loaded yet", im);\r
+               return EINA_FALSE;\r
+            }\r
+\r
+          pixel = im->im->image.data;\r
+          pixel += ((py * src_w) + px);\r
+          *alpha = ((*pixel) >> 24) & 0xff;\r
+       }\r
+       break;\r
+\r
+     default:\r
+        ERR("Colorspace %d not supported.", im->im->cache_entry.space);\r
+        *alpha = 0;\r
+     }\r
+\r
+   return EINA_TRUE;\r
+\r
+ error_oob:\r
+   ERR("Invalid region src=(%d, %d, %d, %d), dst=(%d, %d, %d, %d), image=%dx%d",\r
+       src_region_x, src_region_y, src_region_w, src_region_h,\r
+       dst_region_x, dst_region_y, dst_region_w, dst_region_h,\r
+       src_w, src_h);\r
+   *alpha = 0;\r
+   return EINA_TRUE;\r
+}\r
+\r
 static int
 module_open(Evas_Module *em)
 {
@@ -2981,6 +3062,8 @@ module_open(Evas_Module *em)
 
    ORD(image_max_size_get);
 
+   ORD(pixel_alpha_get);\r
+\r
    /* now advertise out own api */
    em->functions = (void *)(&func);
    return 1;
index b35a9a1..a2e43ff 100644 (file)
@@ -1831,6 +1831,93 @@ eng_multi_font_draw(void *data EINA_UNUSED, void *context, void *surface, Evas_F
    return EINA_FALSE;
 }
 
+static Eina_Bool\r
+eng_pixel_alpha_get(void *image, int x, int y, DATA8 *alpha, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h)\r
+{\r
+   RGBA_Image *im = image;\r
+   int px, py, dx, dy, sx, sy, src_w, src_h;\r
+   double scale_w, scale_h;\r
+\r
+   if (!im) return EINA_FALSE;\r
+\r
+   if ((dst_region_x > x) || (x >= (dst_region_x + dst_region_w)) ||\r
+       (dst_region_y > y) || (y >= (dst_region_y + dst_region_h)))\r
+     {\r
+        *alpha = 0;\r
+        return EINA_FALSE;\r
+     }\r
+\r
+   src_w = im->cache_entry.w;\r
+   src_h = im->cache_entry.h;\r
+   if ((src_w == 0) || (src_h == 0))\r
+     {\r
+        *alpha = 0;\r
+        return EINA_TRUE;\r
+     }\r
+\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_x < 0, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_y < 0, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_x + src_region_w > src_w, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(src_region_y + src_region_h > src_h, error_oob);\r
+\r
+   scale_w = (double)dst_region_w / (double)src_region_w;\r
+   scale_h = (double)dst_region_h / (double)src_region_h;\r
+\r
+   /* point at destination */\r
+   dx = x - dst_region_x;\r
+   dy = y - dst_region_y;\r
+\r
+   /* point at source */\r
+   sx = dx / scale_w;\r
+   sy = dy / scale_h;\r
+\r
+   /* pixel point (translated) */\r
+   px = src_region_x + sx;\r
+   py = src_region_y + sy;\r
+   EINA_SAFETY_ON_TRUE_GOTO(px >= src_w, error_oob);\r
+   EINA_SAFETY_ON_TRUE_GOTO(py >= src_h, error_oob);\r
+\r
+   switch (im->cache_entry.space)\r
+     {\r
+     case EVAS_COLORSPACE_ARGB8888:\r
+       {\r
+          DATA32 *pixel;\r
+\r
+#ifdef EVAS_CSERVE2\r
+          if (evas_cserve2_use_get())\r
+            evas_cache2_image_load_data(&im->cache_entry);\r
+          else\r
+#endif\r
+            evas_cache_image_load_data(&im->cache_entry);\r
+\r
+          if (!im->cache_entry.flags.loaded)\r
+            {\r
+               ERR("im %p has no pixels loaded yet", im);\r
+               return EINA_FALSE;\r
+            }\r
+\r
+          pixel = im->image.data;\r
+          pixel += ((py * src_w) + px);\r
+          *alpha = ((*pixel) >> 24) & 0xff;\r
+       }\r
+       break;\r
+\r
+     default:\r
+        ERR("Colorspace %d not supported.", im->cache_entry.space);\r
+        *alpha = 0;\r
+     }\r
+\r
+   return EINA_TRUE;\r
+\r
+ error_oob:\r
+   ERR("Invalid region src=(%d, %d, %d, %d), dst=(%d, %d, %d, %d), image=%dx%d",\r
+       src_region_x, src_region_y, src_region_w, src_region_h,\r
+       dst_region_x, dst_region_y, dst_region_w, dst_region_h,\r
+       src_w, src_h);\r
+   *alpha = 0;\r
+   return EINA_TRUE;\r
+}\r
+\r
 static void
 eng_image_cache_flush(void *data EINA_UNUSED)
 {
@@ -2565,6 +2652,7 @@ static Evas_Func func =
      eng_image_animated_frame_set,
      NULL,
      eng_multi_font_draw,
+     eng_pixel_alpha_get,\r
    /* FUTURE software generic calls go here */
 };