From 04e660c5c76fa9168be08de1f979a1684c464154 Mon Sep 17 00:00:00 2001 From: "Paulo C. A. Cavalcanti Jr" Date: Sat, 16 Feb 2013 11:10:47 +0100 Subject: [PATCH] evas: 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. --- AUTHORS | 2 + ChangeLog | 4 + NEWS | 1 + 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 ++++++++++++ .../engines/software_generic/evas_engine.c | 88 +++++++++++++ 7 files changed, 219 insertions(+), 84 deletions(-) diff --git a/AUTHORS b/AUTHORS index 32fe9ea536..430e4315f9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -122,6 +122,8 @@ Eduardo Lima (Etrunko) Leandro Dorileo (dorileo) Patryk Kaczmarek Zbigniew Kosinski +Paulo C. A. Cavalcanti Jr + Ecore ----- diff --git a/ChangeLog b/ChangeLog index dfb55b64d3..392ee8fca1 100644 --- 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 a5c702aece..b70c510a08 100644 --- 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 diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index f3492e2627..b3df22b65a 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 9f377e4317..088107eb5a 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 9b059fc194..f273959d12 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 b35a9a100c..a2e43ff971 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 */ };