pca...@zytor.com (Paulo C. A. Cavalcanti Jr) writes:

> Just follow a patch that fixes a bug with
> evas_object_precise_is_inside_set() users on OpenGL backend.
>
> The _pixel_alpha_get() function used in evas_object_image_is_inside()
> relies on engine_data pointer being *always* an RGBA_Image * - but
> that's not true on OpenGL backend, since that pointer will be a
> Evas_GL_Image * instead. Given that, evas_object_image_is_inside() won't
> be able to get alpha from the pixels of the image being handled.
>
> The patch introduces a pixel_alpha_get() function on engines, and it has
> been implemented for Software and OpenGL backend so far.
>
> Besides, please consider backporting this patch to Evas 1.7.x as well.

Just updated the patch with an unused "if" that got removed.
>From 100b08ad520ada28d150dd2ffeaafdee5349a28e Mon Sep 17 00:00:00 2001
From: "Paulo C. A. Cavalcanti Jr" <paulo.cavalca...@intel.com>
Date: Fri, 15 Feb 2013 18:35:20 -0200
Subject: [PATCH] efl/engines: Introduce pixel_alpha_get()

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.

Signed-off-by: Paulo C. A. Cavalcanti Jr <paulo.cavalca...@intel.com>
---
 src/lib/evas/canvas/evas_object_image.c            |  123 +++++++-------------
 src/lib/evas/include/evas_private.h                |    2 +
 src/modules/evas/engines/gl_x11/evas_engine.c      |   83 +++++++++++++
 .../evas/engines/software_generic/evas_engine.c    |   88 ++++++++++++++
 4 files changed, 212 insertions(+), 84 deletions(-)

diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c
index f3492e2..b1c59bb 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -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;
    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;
              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",
+                      pixels, im, data, err);
                   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))
+
+                                 if (eng->pixel_alpha_get(pixels, px, py, &alpha,
+                                                          0, 0,
+                                                          imagew, imageh,
+                                                          obj->cur.geometry.x + ix,
+                                                          obj->cur.geometry.y + iy,
+                                                          iw, ih))
                                    {
                                       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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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;
                               }
                             // .--
-                            // #  
+                            // #
                             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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                          inx, iny, inw, inh,
+                                                          outx, outy, outw, outh))
                                    {
                                       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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  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,
+                                                     inx, iny, inw, inh,
+                                                     outx, outy, outw, outh))
                               {
                                  is_inside = alpha > 0;
                                  dobreak_h = 1;
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index 9f377e4..995f00e 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -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);
+
+   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);
 };
 
 struct _Evas_Image_Load_Func
diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c
index 9b059fc..c217173 100644
--- a/src/modules/evas/engines/gl_x11/evas_engine.c
+++ b/src/modules/evas/engines/gl_x11/evas_engine.c
@@ -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
+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)
+{
+   Evas_GL_Image *im = image;
+   int px, py, dx, dy, sx, sy, src_w, src_h;
+   double scale_w, scale_h;
+
+   if (!im) return EINA_FALSE;
+
+   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->im->cache_entry.w;
+   src_h = im->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->im->cache_entry.space)
+     {
+     case EVAS_COLORSPACE_ARGB8888:
+       {
+          DATA32 *pixel;
+
+          evas_cache_image_load_data(&im->im->cache_entry);
+          if (!im->im->cache_entry.flags.loaded)
+            {
+               ERR("im %p has no pixels loaded yet", im);
+               return EINA_FALSE;
+            }
+
+          pixel = im->im->image.data;
+          pixel += ((py * src_w) + px);
+          *alpha = ((*pixel) >> 24) & 0xff;
+       }
+       break;
+
+     default:
+        ERR("Colorspace %d not supported.", im->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
 module_open(Evas_Module *em)
 {
@@ -2981,6 +3062,8 @@ module_open(Evas_Module *em)
 
    ORD(image_max_size_get);
 
+   ORD(pixel_alpha_get);
+
    /* now advertise out own api */
    em->functions = (void *)(&func);
    return 1;
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index b35a9a1..8eea25c 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1831,6 +1831,93 @@ eng_multi_font_draw(void *data EINA_UNUSED, void *context, void *surface, Evas_F
    return EINA_FALSE;
 }
 
+static Eina_Bool
+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)
+{
+   RGBA_Image *im = image;
+   int px, py, dx, dy, sx, sy, src_w, src_h;
+   double scale_w, scale_h;
+
+   if (!im) return EINA_FALSE;
+
+   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;
+
+#ifdef EVAS_CSERVE2
+          if (evas_cserve2_use_get())
+            evas_cache2_image_load_data(&im->cache_entry);
+          else
+#endif
+            evas_cache_image_load_data(&im->cache_entry);
+
+          if (!im->cache_entry.flags.loaded)
+            {
+               ERR("im %p has no pixels loaded yet", im);
+               return EINA_FALSE;
+            }
+
+          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 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,
    /* FUTURE software generic calls go here */
 };
 
-- 
1.7.10.4

-- 
Paulo C. A. Cavalcanti Jr, Intel Open Source Technology Center
I speak only for myself.
------------------------------------------------------------------------------
The Go Parallel Website, sponsored by Intel - in partnership with Geeknet, 
is your hub for all things parallel software development, from weekly thought 
leadership blogs to news, videos, case studies, tutorials, tech docs, 
whitepapers, evaluation guides, and opinion stories. Check out the most 
recent posts - join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to