elm - elm image orientation api fix - major bug in implementation

@fix

The elm image orient_set api looks like it is a state, and it is
documented to SET the orietnation, but the code actually DOEs that
orientation when you set it. so docs and api name didnt match
functionality at all. this was bad an an oversight. you didn't notice
until you set orientation multiple times to an image. this fixes the
implementation to be as documented - a state that is applied and
remains that way until set to something else. setting to the same
orientation has no efect as with color, size, etc. etc. in evas.

you could look on this as an api break, but then either the docs
change AND api name changes to match the code, or code changes to
match the docs. we don't keep bug compatibility in efl and in this
case i'm making the call to break the behavior of a  function as it
was broken already with respect to name and docs.
This commit is contained in:
Carsten Haitzler 2015-01-12 11:28:13 +09:00
parent ab0e050102
commit 97e625c68c
2 changed files with 300 additions and 187 deletions

View File

@ -324,96 +324,6 @@ _elm_image_resize_down_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
return sd->resize_up;
}
static void
_elm_image_flip_horizontal(Evas_Object *obj, Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, y, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, EINA_TRUE);
for (y = 0; y < ih; y++)
{
p1 = data + (y * iw);
p2 = data + ((y + 1) * iw) - 1;
for (x = 0; x < (iw >> 1); x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
evas_object_image_data_set(sd->img, data);
evas_object_image_data_update_add(sd->img, 0, 0, iw, ih);
_elm_image_internal_sizing_eval(obj, sd);
}
static void
_elm_image_flip_vertical(Evas_Object *obj, Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, y, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, EINA_TRUE);
for (y = 0; y < (ih >> 1); y++)
{
p1 = data + (y * iw);
p2 = data + ((ih - 1 - y) * iw);
for (x = 0; x < iw; x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2++;
}
}
evas_object_image_data_set(sd->img, data);
evas_object_image_data_update_add(sd->img, 0, 0, iw, ih);
_elm_image_internal_sizing_eval(obj, sd);
}
static void
_elm_image_smart_rotate_180(Evas_Object *obj, Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, hw, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, 1);
hw = iw * ih;
x = (hw / 2);
p1 = data;
p2 = data + hw - 1;
for (; --x > 0; )
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
evas_object_image_data_set(sd->img, data);
evas_object_image_data_update_add(sd->img, 0, 0, iw, ih);
_elm_image_internal_sizing_eval(obj, sd);
}
static Eina_Bool
_elm_image_drag_n_drop_cb(void *elm_obj,
Evas_Object *obj,
@ -1090,116 +1000,316 @@ _elm_image_efl_image_load_size_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int
if (h) *h = sd->load_size;
}
static void
_elm_image_flip_horizontal(Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, y, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, EINA_TRUE);
for (y = 0; y < ih; y++)
{
p1 = data + (y * iw);
p2 = data + ((y + 1) * iw) - 1;
for (x = 0; x < (iw >> 1); x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
evas_object_image_data_set(sd->img, data);
}
static void
_elm_image_flip_vertical(Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, y, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, EINA_TRUE);
for (y = 0; y < (ih >> 1); y++)
{
p1 = data + (y * iw);
p2 = data + ((ih - 1 - y) * iw);
for (x = 0; x < iw; x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2++;
}
}
evas_object_image_data_set(sd->img, data);
}
static void
_elm_image_smart_rotate_180(Elm_Image_Data *sd)
{
unsigned int *p1, *p2, tmp;
unsigned int *data;
int x, hw, iw, ih;
evas_object_image_size_get(sd->img, &iw, &ih);
data = evas_object_image_data_get(sd->img, 1);
hw = iw * ih;
x = (hw / 2);
p1 = data;
p2 = data + hw - 1;
for (; --x > 0; )
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
evas_object_image_data_set(sd->img, data);
}
#define GETDAT(neww, newh) \
unsigned int *data, *data2; \
int iw, ih, w, h; \
evas_object_image_size_get(sd->img, &iw, &ih); \
data = evas_object_image_data_get(sd->img, EINA_FALSE); \
if (!data) return; \
data2 = malloc(iw * ih * sizeof(int)); \
if (!data2) { \
evas_object_image_data_set(sd->img, data); \
return; \
} \
memcpy(data2, data, iw * ih * sizeof(int)); \
evas_object_image_data_set(sd->img, data); \
w = neww; h = newh; \
evas_object_image_size_set(sd->img, w, h); \
data = evas_object_image_data_get(sd->img, EINA_TRUE); \
if (!data) return
#define PUTDAT \
evas_object_image_data_set(sd->img, data); \
free(data2)
#define TILE 32
static void
_elm_image_smart_rotate_90(Elm_Image_Data *sd)
{
GETDAT(ih, iw);
int x, y, xx, yy, xx2, yy2;
unsigned int *src, *dst;
for (y = 0; y < ih; y += TILE)
{
yy2 = y + TILE;
if (yy2 > ih) yy2 = ih;
for (x = 0; x < iw; x += TILE)
{
xx2 = x + TILE;
if (xx2 > iw) xx2 = iw;
for (yy = y; yy < yy2; yy++)
{
src = data2 + (yy * iw) + x;
dst = data + (x * w) + (w - yy - 1);
for (xx = x; xx < xx2; xx++)
{
*dst = *src;
src++;
dst += w;
}
}
}
}
PUTDAT;
}
static void
_elm_image_smart_rotate_270(Elm_Image_Data *sd)
{
GETDAT(ih, iw);
int x, y, xx, yy, xx2, yy2;
unsigned int *src, *dst;
for (y = 0; y < ih; y += TILE)
{
yy2 = y + TILE;
if (yy2 > ih) yy2 = ih;
for (x = 0; x < iw; x += TILE)
{
xx2 = x + TILE;
if (xx2 > iw) xx2 = iw;
for (yy = y; yy < yy2; yy++)
{
src = data2 + (yy * iw) + x;
dst = data + ((h - x - 1) * w) + yy;
for (xx = x; xx < xx2; xx++)
{
*dst = *src;
src++;
dst -= w;
}
}
}
}
PUTDAT;
}
static void
_elm_image_smart_flip_transverse(Elm_Image_Data *sd)
{
GETDAT(ih, iw);
int x, y;
unsigned int *src, *dst;
src = data2;
for (y = 0; y < ih; y++)
{
dst = data + y;
for (x = 0; x < iw; x++)
{
*dst = *src;
src++;
dst += w;
}
}
PUTDAT;
}
static void
_elm_image_smart_flip_transpose(Elm_Image_Data *sd)
{
GETDAT(ih, iw);
int x, y;
unsigned int *src, *dst;
src = data2 + (iw * ih) - 1;
for (y = 0; y < ih; y++)
{
dst = data + y;
for (x = 0; x < iw; x++)
{
*dst = *src;
src--;
dst += w;
}
}
PUTDAT;
}
EOLIAN static void
_elm_image_orient_set(Eo *obj, Elm_Image_Data *sd, Elm_Image_Orient orient)
{
unsigned int *data, *data2 = NULL, *to, *from;
int x, y, w, hw, iw, ih;
int iw, ih;
if (sd->edje)
return;
if (sd->edje) return;
if (sd->orient == orient) return;
switch (orient)
evas_object_image_size_get(sd->img, &iw, &ih);
if ((sd->orient >= ELM_IMAGE_ORIENT_0) &&
(sd->orient <= ELM_IMAGE_ROTATE_270) &&
(orient >= ELM_IMAGE_ORIENT_0) &&
(orient <= ELM_IMAGE_ROTATE_270))
{
case ELM_IMAGE_FLIP_HORIZONTAL:
_elm_image_flip_horizontal(obj, sd);
sd->orient = orient;
return;
case ELM_IMAGE_FLIP_VERTICAL:
_elm_image_flip_vertical(obj, sd);
sd->orient = orient;
return;
case ELM_IMAGE_ROTATE_180:
_elm_image_smart_rotate_180(obj, sd);
sd->orient = orient;
return;
case ELM_IMAGE_ORIENT_NONE:
// we are rotating from one anglee to another, so figure out delta
// and apply that delta
Elm_Image_Orient rot_delta = (4 + orient - sd->orient) % 4;
switch (rot_delta)
{
case ELM_IMAGE_ORIENT_0:
// this should never hppen
break;
case ELM_IMAGE_ORIENT_90:
_elm_image_smart_rotate_90(sd);
sd->orient = orient;
break;
case ELM_IMAGE_ORIENT_180:
_elm_image_smart_rotate_180(sd);
sd->orient = orient;
break;
case ELM_IMAGE_ORIENT_270:
_elm_image_smart_rotate_270(sd);
sd->orient = orient;
break;
default:
// this should never hppen
break;
}
}
else if (((sd->orient == ELM_IMAGE_ORIENT_NONE) &&
(orient == ELM_IMAGE_FLIP_HORIZONTAL)) ||
((sd->orient == ELM_IMAGE_FLIP_HORIZONTAL) &&
(orient == ELM_IMAGE_ORIENT_NONE)))
{
// flip horizontally to get thew new orientation
_elm_image_flip_horizontal(sd);
sd->orient = orient;
return;
}
else if (((sd->orient == ELM_IMAGE_ORIENT_NONE) &&
(orient == ELM_IMAGE_FLIP_VERTICAL)) ||
((sd->orient == ELM_IMAGE_FLIP_VERTICAL) &&
(orient == ELM_IMAGE_ORIENT_NONE)))
{
// flipvertically to get thew new orientation
_elm_image_flip_vertical(sd);
sd->orient = orient;
}
else
{
// generic solution - undo the previous orientation and then apply the
// new one after that
int i;
default:
break;
for (i = 0; i < 2; i++)
{
switch (sd->orient)
{
case ELM_IMAGE_ORIENT_0:
break;
case ELM_IMAGE_ORIENT_90:
_elm_image_smart_rotate_270(sd);
break;
case ELM_IMAGE_ORIENT_180:
_elm_image_smart_rotate_180(sd);
break;
case ELM_IMAGE_ORIENT_270:
_elm_image_smart_rotate_90(sd);
break;
case ELM_IMAGE_FLIP_HORIZONTAL:
_elm_image_flip_horizontal(sd);
break;
case ELM_IMAGE_FLIP_VERTICAL:
_elm_image_flip_vertical(sd);
break;
case ELM_IMAGE_FLIP_TRANSPOSE:
_elm_image_smart_flip_transpose(sd);
break;
case ELM_IMAGE_FLIP_TRANSVERSE:
_elm_image_smart_flip_transverse(sd);
break;
default:
// this should never hppen
break;
}
sd->orient = orient;
}
}
evas_object_image_size_get(sd->img, &iw, &ih);
/* we need separate destination memory if we want to rotate 90 or
* 270 degree */
data = evas_object_image_data_get(sd->img, EINA_FALSE);
if (!data) return;
data2 = malloc(sizeof(unsigned int) * (iw * ih));
if (!data2) return;
memcpy(data2, data, sizeof(unsigned int) * (iw * ih));
w = ih;
ih = iw;
iw = w;
hw = w * ih;
evas_object_image_size_set(sd->img, iw, ih);
data = evas_object_image_data_get(sd->img, EINA_TRUE);
if (!data)
{
free(data2);
return;
}
switch (orient)
{
case ELM_IMAGE_FLIP_TRANSPOSE:
to = data;
hw = -hw + 1;
sd->orient = orient;
break;
case ELM_IMAGE_FLIP_TRANSVERSE:
to = data + hw - 1;
w = -w;
hw = hw - 1;
sd->orient = orient;
break;
case ELM_IMAGE_ROTATE_90:
to = data + w - 1;
hw = -hw - 1;
sd->orient = orient;
break;
case ELM_IMAGE_ROTATE_270:
to = data + hw - w;
w = -w;
hw = hw + 1;
sd->orient = orient;
break;
default:
ERR("unknown orient %d", orient);
evas_object_image_data_set(sd->img, data); // give it back
free(data2);
return;
}
from = data2;
for (x = iw; --x >= 0; )
{
for (y = ih; --y >= 0; )
{
*to = *from;
from++;
to += w;
}
to += hw;
}
free(data2);
evas_object_image_data_set(sd->img, data);
evas_object_image_data_update_add(sd->img, 0, 0, iw, ih);
_elm_image_internal_sizing_eval(obj, sd);
}

View File

@ -15,8 +15,11 @@ typedef enum
ELM_IMAGE_ORIENT_NONE = 0, /**< no orientation change */
ELM_IMAGE_ORIENT_0 = 0, /**< no orientation change */
ELM_IMAGE_ROTATE_90 = 1, /**< rotate 90 degrees clockwise */
ELM_IMAGE_ORIENT_90 = 1, /**< rotate 90 degrees clockwise @since 1.13 */
ELM_IMAGE_ROTATE_180 = 2, /**< rotate 180 degrees clockwise */
ELM_IMAGE_ORIENT_180 = 2, /**< rotate 180 degrees clockwise @since 1.13 */
ELM_IMAGE_ROTATE_270 = 3, /**< rotate 90 degrees counter-clockwise (i.e. 270 degrees clockwise) */
ELM_IMAGE_ORIENT_270 = 3, /**< rotate 90 degrees counter-clockwise (i.e. 270 degrees clockwise) @since 1.13 */
ELM_IMAGE_FLIP_HORIZONTAL = 4, /**< flip image horizontally */
ELM_IMAGE_FLIP_VERTICAL = 5, /**< flip image vertically */
ELM_IMAGE_FLIP_TRANSPOSE = 6, /**< flip the image along the y = (width - x) line (bottom-left to top-right) */