From f93cc6fe3b0b3022955f528a154918b6f34be635 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 27 Apr 2015 19:15:58 +0200 Subject: [PATCH] evas: fix issue of using two times the same image with different orient in software. Fixing T2338 --- .../engines/software_generic/evas_engine.c | 393 ++++++++++-------- 1 file changed, 216 insertions(+), 177 deletions(-) diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index fa41a5a0c2..dfdcb5c3bc 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -1319,128 +1319,80 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) return im; } -static void * -_image_flip_horizontal(void *data, Image_Entry *im) +static void +_image_flip_horizontal(DATA32 *pixels_out, const DATA32 *pixels_in, + int iw, int ih) { - unsigned int *p1, *p2, tmp; - DATA32 *image_data; - int x, y, iw, ih; - Image_Entry *im2; + const unsigned int *pi1, *pi2; + unsigned int *po1, *po2; + int x, y; - eng_image_size_get(data, im, &iw, &ih); - im = eng_image_data_get(data, im , 1, &image_data, NULL); for (y = 0; y < ih; y++) { - p1 = image_data + (y * iw); - p2 = image_data + ((y + 1) * iw) - 1; + pi1 = pixels_in + (y * iw); + pi2 = pixels_in + ((y + 1) * iw) - 1; + po1 = pixels_out + (y * iw); + po2 = pixels_out + ((y + 1) * iw) - 1; for (x = 0; x < (iw >> 1); x++) { - tmp = *p1; - *p1 = *p2; - *p2 = tmp; - p1++; - p2--; + *po2 = *pi1; + *po1 = *pi2; + pi1++; po1++; + pi2--; po2--; } } - im2 = eng_image_new_from_data(data, iw, ih, image_data, - eng_image_alpha_get(data, im), - eng_image_colorspace_get(data, im)); - im = im2; - return im; } -static void * -_image_flip_vertical(void *data, Image_Entry *im) +static void +_image_flip_vertical(DATA32 *pixels_out, const DATA32 *pixels_in, + int iw, int ih) { - unsigned int *p1, *p2, tmp; - DATA32 *image_data; - int x, y, iw, ih; - Image_Entry *im2; + const unsigned int *pi1, *pi2; + unsigned int *po1, *po2; + int x, y; - eng_image_size_get(data, im, &iw, &ih); - im = eng_image_data_get(data, im , 1, &image_data, NULL); for (y = 0; y < (ih >> 1); y++) { - p1 = image_data + (y * iw); - p2 = image_data + ((ih - 1 - y) * iw); + pi1 = pixels_in + (y * iw); + pi2 = pixels_in + ((ih - 1 - y) * iw); + po1 = pixels_out + (y * iw); + po2 = pixels_out + ((ih - 1 - y) * iw); for (x = 0; x < iw; x++) { - tmp = *p1; - *p1 = *p2; - *p2 = tmp; - p1++; - p2++; + *po2 = *pi1; + *po1 = *pi2; + pi1++; po1++; + pi2++; po2++; } } - im2 = eng_image_new_from_data(data, iw, ih, image_data, - eng_image_alpha_get(data, im), - eng_image_colorspace_get(data, im)); - im = im2; - return im; } -static void * -_image_rotate_180(void *data, Image_Entry *im) +static void +_image_rotate_180(DATA32 *pixels_out, const DATA32 *pixels_in, + int iw, int ih) { - unsigned int *p1, *p2, tmp; - DATA32 *image_data; - int hw, iw, ih; - Image_Entry *im2; + const unsigned int *pi1, *pi2; + unsigned int *po1, *po2; + int hw; - eng_image_size_get(data, im, &iw, &ih); - im = eng_image_data_get(data, im , 1, &image_data, NULL); - if(!image_data) return im; hw = iw * ih; - p1 = image_data; - p2 = image_data + hw - 1; - for (; p1 < p2; ) + pi1 = pixels_in; + pi2 = pixels_in + hw - 1; + po1 = pixels_out; + po2 = pixels_out + hw - 1; + for (; pi1 < pi2; ) { - tmp = *p1; - *p1 = *p2; - *p2 = tmp; - p1++; - p2--; + *po2 = *pi1; + *po1 = *pi2; + pi1++; po1++; + pi2--; po2--; } - im2 = eng_image_new_from_data(data, iw, ih, image_data, - eng_image_alpha_get(data, im), - eng_image_colorspace_get(data, im)); - im = im2; - return im; } -# define GETDAT(neww, newh) \ - DATA32 *image_data, *image_data2; \ - int iw, ih, w, h; \ - Image_Entry *im2; \ - eng_image_size_get(data, im, &iw, &ih); \ - im = eng_image_data_get(data, im , 0, &image_data, NULL); \ - if (!image_data) return im; \ - image_data2 = malloc(iw * ih * sizeof(DATA32) + 1); \ - if (!image_data2) { \ - return im; \ - } \ - memcpy(image_data2, image_data, iw * ih * sizeof(DATA32)); \ - im = eng_image_new_from_data(data, iw, ih, image_data, \ - eng_image_alpha_get(data, im), \ - eng_image_colorspace_get(data, im)); \ - w = neww; h = newh; \ - im = eng_image_data_get(data, im , 1, &image_data, NULL); \ - -# define PUTDAT \ - im2 = eng_image_new_from_data(data, w, h, image_data, \ - eng_image_alpha_get(data, im), \ - eng_image_colorspace_get(data, im)); \ - im2 = eng_image_size_set(data, im2, w, h); \ - im = im2; \ - free(image_data2); \ - return im; \ - -static void * -_image_rotate_90(void *data, Image_Entry *im) +static void +_image_rotate_90(DATA32 *pixels_out, const DATA32 *pixels_in, int iw, int ih) { - GETDAT(ih, iw); int x, y, xx, yy, xx2, yy2; - unsigned int *src, *dst; for (y = 0; y < ih; y += TILE) { @@ -1452,26 +1404,26 @@ _image_rotate_90(void *data, Image_Entry *im) if (xx2 > iw) xx2 = iw; for (yy = y; yy < yy2; yy++) { - src = image_data2 + (yy * iw) + x; - dst = image_data + (x * w) + (w - yy - 1); + const unsigned int *src; + unsigned int *dst; + + src = pixels_in + (yy * iw) + x; + dst = pixels_out + (x * ih) + (ih - yy - 1); for (xx = x; xx < xx2; xx++) { *dst = *src; src++; - dst += w; + dst += ih; } } } } - PUTDAT; } -static void * -_image_rotate_270(void *data, Image_Entry *im) +static void +_image_rotate_270(DATA32 *pixels_out, const DATA32 *pixels_in, int iw, int ih) { - GETDAT(ih, iw); int x, y, xx, yy, xx2, yy2; - unsigned int *src, *dst; for (y = 0; y < ih; y += TILE) { @@ -1483,74 +1435,126 @@ _image_rotate_270(void *data, Image_Entry *im) if (xx2 > iw) xx2 = iw; for (yy = y; yy < yy2; yy++) { - src = image_data2 + (yy * iw) + x; - dst = image_data + ((h - x - 1) * w) + yy; + const unsigned int *src; + unsigned int *dst; + + src = pixels_in + (yy * iw) + x; + dst = pixels_out + ((iw - x - 1) * ih) + yy; for (xx = x; xx < xx2; xx++) { *dst = *src; src++; - dst -= w; + dst -= ih; } } } } - PUTDAT; } -static void * -_image_flip_transpose(void *data, Image_Entry *im) +static void +_image_flip_transpose(DATA32 *pixels_out, const DATA32 *pixels_in, + int iw, int ih) { - GETDAT(ih, iw); int x, y; - unsigned int *src, *dst; + const unsigned int *src; - src = image_data2; + src = pixels_in; for (y = 0; y < ih; y++) { - dst = image_data + y; + unsigned int *dst; + + dst = pixels_out + y; for (x = 0; x < iw; x++) { - *dst = *src; + unsigned int tmp = *src; + *dst = tmp; src++; - dst += w; + dst += ih; } } - PUTDAT; } -static void * -_image_flip_transverse(void *data, Image_Entry *im) +static void +_image_flip_transverse(DATA32 *pixels_out, const DATA32 *pixels_in, + int iw, int ih) { - GETDAT(ih, iw); int x, y; - unsigned int *src, *dst; + const unsigned int *src; - src = image_data2 + (iw * ih) - 1; + src = pixels_in + (iw * ih) - 1; for (y = 0; y < ih; y++) { - dst = image_data + y; + unsigned int *dst; + + dst = pixels_out + y; for (x = 0; x < iw; x++) { *dst = *src; src--; - dst += w; + dst += ih; } } - PUTDAT; } -#undef GETDAT -#undef PUTDAT - static void * -eng_image_orient_set(void *data, void *image, Evas_Image_Orient orient) +eng_image_orient_set(void *data EINA_UNUSED, void *image, Evas_Image_Orient orient) { Image_Entry *im; + Image_Entry *im_new; + void *pixels_in; + void *pixels_out; + int tw, th; + int w, h; if (!image) return NULL; im = image; if (im->orient == orient) return im; + if (im->orient == EVAS_IMAGE_ORIENT_90 || + im->orient == EVAS_IMAGE_ORIENT_270 || + im->orient == EVAS_IMAGE_FLIP_TRANSPOSE || + im->orient == EVAS_IMAGE_FLIP_TRANSVERSE) + { + tw = im->h; + th = im->w; + } + else + { + th = im->h; + tw = im->w; + } + + if (orient == EVAS_IMAGE_ORIENT_90 || + orient == EVAS_IMAGE_ORIENT_270 || + orient == EVAS_IMAGE_FLIP_TRANSPOSE || + orient == EVAS_IMAGE_FLIP_TRANSVERSE) + { + w = th; + h = tw; + } + else + { + h = th; + w = tw; + } + + im_new = evas_cache_image_copied_data(evas_common_image_cache_get(), + w, h, NULL, im->flags.alpha, + EVAS_COLORSPACE_ARGB8888); + if (!im_new) return im; + +#if EVAS_CSERVE2 + if (evas_cserve2_use_get() && evas_cache2_image_cached(im)) + evas_cache2_image_load_data(im); + else +#endif + evas_cache_image_load_data(im); + + pixels_in = evas_cache_image_pixels(im); + pixels_out = evas_cache_image_pixels(im_new); + + if (!pixels_out || !pixels_in) goto on_error; + if ((im->orient >= EVAS_IMAGE_ORIENT_0) && (im->orient <= EVAS_IMAGE_ORIENT_270) && (orient >= EVAS_IMAGE_ORIENT_0) && @@ -1562,23 +1566,20 @@ eng_image_orient_set(void *data, void *image, Evas_Image_Orient orient) switch (rot_delta) { case EVAS_IMAGE_ORIENT_0: - ERR("You shouldn't get this message, wrong orient value"); - break; + ERR("You shouldn't get this message, wrong orient value"); + goto on_error; case EVAS_IMAGE_ORIENT_90: - im = _image_rotate_90(data, im); - im->orient = orient; - break; + _image_rotate_90(pixels_out, pixels_in, im->w, im->h); + break; case EVAS_IMAGE_ORIENT_180: - im = _image_rotate_180(data, im); - im->orient = orient; - break; + _image_rotate_180(pixels_out, pixels_in, im->w, im->h); + break; case EVAS_IMAGE_ORIENT_270: - im = _image_rotate_270(data, im); - im->orient = orient; - break; + _image_rotate_270(pixels_out, pixels_in, im->w, im->h); + break; default: - ERR("Wrong orient value"); - break; + ERR("Wrong orient value"); + goto on_error; } } else if (((im->orient == EVAS_IMAGE_ORIENT_NONE) && @@ -1587,8 +1588,7 @@ eng_image_orient_set(void *data, void *image, Evas_Image_Orient orient) (orient == EVAS_IMAGE_ORIENT_NONE))) { // flip horizontally to get the new orientation - im = _image_flip_horizontal(data, im); - im->orient = orient; + _image_flip_horizontal(pixels_out, pixels_in, im->w, im->h); } else if (((im->orient == EVAS_IMAGE_ORIENT_NONE) && (orient == EVAS_IMAGE_FLIP_VERTICAL)) || @@ -1596,51 +1596,90 @@ eng_image_orient_set(void *data, void *image, Evas_Image_Orient orient) (orient == EVAS_IMAGE_ORIENT_NONE))) { // flip vertically to get the new orientation - im = _image_flip_vertical(data, im); - im->orient = orient; + _image_flip_vertical(pixels_out, pixels_in, im->w, im->h); } else { // generic solution - undo the previous orientation and then apply the // new one after that - int i; + void *pixels_tmp; - for (i = 0; i < 2; i++) + pixels_tmp = malloc(sizeof (unsigned int) * w * h); + if (!pixels_tmp) goto on_error; + + // Undoing previous rotation + switch (im->orient) { - switch (im->orient) - { - case EVAS_IMAGE_ORIENT_0: - break; - case EVAS_IMAGE_ORIENT_90: - if(i == 1) im = _image_rotate_90(data, im); - else im = _image_rotate_270(data, im); - break; - case EVAS_IMAGE_ORIENT_180: - im = _image_rotate_180(data, im); - break; - case EVAS_IMAGE_ORIENT_270: - if(i == 1) im = _image_rotate_270(data, im); - else im = _image_rotate_90(data, im); - break; - case EVAS_IMAGE_FLIP_HORIZONTAL: - im = _image_flip_horizontal(data, im); - break; - case EVAS_IMAGE_FLIP_VERTICAL: - im = _image_flip_vertical(data, im); - break; - case EVAS_IMAGE_FLIP_TRANSPOSE: - im = _image_flip_transpose(data, im); - break; - case EVAS_IMAGE_FLIP_TRANSVERSE: - im = _image_flip_transverse(data, im); - break; - default: - ERR("Wrong orient value"); - break; - } - im->orient = orient; + case EVAS_IMAGE_ORIENT_0: + // FIXME: could be easily optimized away + memcpy(pixels_tmp, pixels_in, sizeof (unsigned int) * w * h); + break; + case EVAS_IMAGE_ORIENT_90: + _image_rotate_270(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_ORIENT_180: + _image_rotate_180(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_ORIENT_270: + _image_rotate_90(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_FLIP_HORIZONTAL: + _image_flip_horizontal(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_FLIP_VERTICAL: + _image_flip_vertical(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_FLIP_TRANSPOSE: + _image_flip_transpose(pixels_tmp, pixels_in, im->w, im->h); + break; + case EVAS_IMAGE_FLIP_TRANSVERSE: + _image_flip_transverse(pixels_tmp, pixels_in, im->w, im->h); + break; + default: + ERR("Wrong orient value"); + goto on_error; } + + // Doing the new requested one + switch (orient) + { + case EVAS_IMAGE_ORIENT_0: + // FIXME: could be easily optimized away + memcpy(pixels_out, pixels_tmp, sizeof (unsigned int) * w * h); + break; + case EVAS_IMAGE_ORIENT_90: + _image_rotate_90(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_ORIENT_180: + _image_rotate_180(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_ORIENT_270: + _image_rotate_270(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_FLIP_HORIZONTAL: + _image_flip_horizontal(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_FLIP_VERTICAL: + _image_flip_vertical(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_FLIP_TRANSPOSE: + _image_flip_transpose(pixels_out, pixels_tmp, tw, th); + break; + case EVAS_IMAGE_FLIP_TRANSVERSE: + _image_flip_transverse(pixels_out, pixels_tmp, tw, th); + break; + } + + free(pixels_tmp); } + + im_new->orient = orient; + evas_cache_image_drop(im); + + return im_new; + + on_error: + evas_cache_image_drop(im_new); return im; }