diff --git a/legacy/emotion/src/examples/emotion_border_example.c b/legacy/emotion/src/examples/emotion_border_example.c index f83790a7d7..6772b0b836 100644 --- a/legacy/emotion/src/examples/emotion_border_example.c +++ b/legacy/emotion/src/examples/emotion_border_example.c @@ -70,6 +70,30 @@ _on_key_down(void *data, Evas *e, Evas_Object *o, void *event_info) fprintf(stderr, "playing next file: %s\n", file); emotion_object_file_set(em, file); } + else if (!strcmp(ev->keyname, "b")) + { + emotion_object_border_set(em, 0, 0, 50, 50); + } + else if (!strcmp(ev->keyname, "0")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_NONE); + } + else if (!strcmp(ev->keyname, "w")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_WIDTH); + } + else if (!strcmp(ev->keyname, "h")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_HEIGHT); + } + else if (!strcmp(ev->keyname, "2")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); + } + else if (!strcmp(ev->keyname, "c")) + { + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_CROP); + } else { fprintf(stderr, "unhandled key: %s\n", ev->keyname); @@ -179,7 +203,7 @@ main(int argc, const char *argv[]) evas_object_move(em, 10, 10); evas_object_resize(em, WIDTH, HEIGHT); evas_object_resize(em, WIDTH - 20, HEIGHT - 20); - emotion_object_border_set(em, 0, 0, 50, 50); + emotion_object_keep_aspect_set(em, EMOTION_ASPECT_KEEP_BOTH); emotion_object_bg_color_set(em, 0, 128, 0, 255); evas_object_show(em); diff --git a/legacy/emotion/src/lib/Emotion.h b/legacy/emotion/src/lib/Emotion.h index ba2f15c955..0483bebba7 100644 --- a/legacy/emotion/src/lib/Emotion.h +++ b/legacy/emotion/src/lib/Emotion.h @@ -210,10 +210,21 @@ typedef enum EMOTION_HIBERNATE } Emotion_Suspend; +enum _Emotion_Aspect +{ + EMOTION_ASPECT_KEEP_NONE, /**< ignore video aspect ratio */ + EMOTION_ASPECT_KEEP_WIDTH, /**< respect video aspect, fitting its width inside the object width */ + EMOTION_ASPECT_KEEP_HEIGHT, /**< respect video aspect, fitting its height inside the object height */ + EMOTION_ASPECT_KEEP_BOTH, /**< respect video aspect, fitting it inside the object area */ + EMOTION_ASPECT_CROP, /**< respect video aspect, cropping exceding area */ + EMOTION_ASPECT_CUSTOM, /**< use custom borders/crop for the video */ +}; + typedef enum _Emotion_Module Emotion_Module; typedef enum _Emotion_Event Emotion_Event; typedef enum _Emotion_Meta_Info Emotion_Meta_Info; /**< Meta info type to be retrieved. */ typedef enum _Emotion_Vis Emotion_Vis; /**< Type of visualization. */ +typedef enum _Emotion_Aspect Emotion_Aspect; /**< Aspect ratio option. */ #define EMOTION_CHANNEL_AUTO -1 #define EMOTION_CHANNEL_DEFAULT 0 @@ -448,6 +459,59 @@ EAPI void emotion_object_bg_color_set(Evas_Object *obj, int r, int g, int b, int */ EAPI void emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a); +/** + * @brief Set whether emotion should keep the aspect ratio of the video. + * + * @param obj The emotion object where to set the aspect. + * @param a The aspect ratio policy. + * + * Instead of manually calculating the required border to set with + * emotion_object_border_set(), and using this to fix the aspect ratio of the + * video when the emotion object has a different aspect, it's possible to just + * set the policy to be used. + * + * The options are: + * + * - @b #EMOTION_ASPECT_KEEP_NONE - ignore the video aspect ratio, and reset any + * border set to 0, stretching the video inside the emotion object area. This + * option is similar to EVAS_ASPECT_CONTROL_NONE size hint. + * - @b #EMOTION_ASPECT_KEEP_WIDTH - respect the video aspect ratio, fitting the + * video width inside the object width. This option is similar to + * EVAS_ASPECT_CONTROL_HORIZONTAL size hint. + * - @b #EMOTION_ASPECT_KEEP_HEIGHT - respect the video aspect ratio, fitting + * the video height inside the object height. This option is similar to + * EVAS_ASPECT_CONTROL_VERTIAL size hint. + * - @b #EMOTION_ASPECT_KEEP_BOTH - respect the video aspect ratio, fitting both + * its width and height inside the object area. This option is similar to + * EVAS_ASPECT_CONTROL_BOTH size hint. It's the effect called letterboxing. + * - @b #EMOTION_ASPECT_CROP - respect the video aspect ratio, fitting the width + * or height inside the object area, and cropping the exceding areas of the + * video in height or width. It's the effect called pan-and-scan. + * - @b #EMOTION_ASPECT_CUSTOM - ignore the video aspect ratio, and use the + * current set from emotion_object_border_set(). + * + * @note Calling this function with any value except #EMOTION_ASPECT_CUSTOM will + * invalidate borders set with emotion_object_border_set(). + * + * @note Calling emotion_object_border_set() will automatically set the aspect + * policy to #EMOTION_ASPECT_CUSTOM. + * + * @see emotion_object_border_set() + * @see emotion_object_keep_aspect_get() + */ +EAPI void emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a); + +/** + * @brief Get the current emotion aspect ratio policy. + * + * @param obj The emotion object from which we are fetching the aspect ratio + * policy. + * @return The current aspect ratio policy. + * + * @see emotion_object_keep_aspect_set() + */ +EAPI Emotion_Aspect emotion_object_keep_aspect_get(const Evas_Object *obj); + /** * @brief Set the file to be played in the Emotion object. * diff --git a/legacy/emotion/src/lib/emotion_smart.c b/legacy/emotion/src/lib/emotion_smart.c index f9882b096c..cde9351980 100644 --- a/legacy/emotion/src/lib/emotion_smart.c +++ b/legacy/emotion/src/lib/emotion_smart.c @@ -94,6 +94,7 @@ struct _Smart_Data Emotion_Module_Options module_options; Emotion_Suspend state; + Emotion_Aspect aspect; Eina_Bool open : 1; Eina_Bool play : 1; @@ -289,16 +290,15 @@ _emotion_module_open(const char *name, Evas_Object *obj, Emotion_Video_Module ** } static void -_clipper_position_size_update(Evas_Object *obj, int vid_w, int vid_h) +_clipper_position_size_update(Evas_Object *obj, int w, int h, int vid_w, int vid_h) { Smart_Data *sd; double scale_w, scale_h; int x, y; - int w, h; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); - evas_object_geometry_get(obj, &x, &y, &w, &h); + evas_object_geometry_get(obj, &x, &y, NULL, NULL); evas_object_move(sd->crop.clipper, x, y); scale_w = (double)w / (double)(vid_w - sd->crop.l - sd->crop.r); scale_h = (double)h / (double)(vid_h - sd->crop.t - sd->crop.b); @@ -450,30 +450,25 @@ emotion_object_file_get(const Evas_Object *obj) return sd->file; } -EAPI void -emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b) +static void +_emotion_aspect_borders_apply(Evas_Object *obj, Smart_Data *sd, int w, int h, int iw, int ih) { - Smart_Data *sd; - - E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); - sd->crop.l = -l; - sd->crop.r = -r; - sd->crop.t = -t; - sd->crop.b = -b; - if (l == 0 && r == 0 && t == 0 && b == 0) + /* applying calculated borders */ + if (sd->crop.l == 0 && sd->crop.r == 0 && + sd->crop.t == 0 && sd->crop.b == 0) { Evas_Object *old_clipper; - if (!sd->crop.clipper) - return; - old_clipper = evas_object_clip_get(sd->crop.clipper); - evas_object_clip_unset(sd->obj); - evas_object_clip_set(sd->obj, old_clipper); - evas_object_del(sd->crop.clipper); - sd->crop.clipper = NULL; + if (sd->crop.clipper) + { + old_clipper = evas_object_clip_get(sd->crop.clipper); + evas_object_clip_unset(sd->obj); + evas_object_clip_set(sd->obj, old_clipper); + evas_object_del(sd->crop.clipper); + sd->crop.clipper = NULL; + } } else { - int vid_w, vid_h; if (!sd->crop.clipper) { Evas_Object *old_clipper; @@ -487,9 +482,108 @@ emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b) if (evas_object_visible_get(sd->obj)) evas_object_show(sd->crop.clipper); } - sd->module->video_data_size_get(sd->video, &vid_w, &vid_h); - _clipper_position_size_update(obj, vid_w, vid_h); } + _clipper_position_size_update(obj, w, h, iw, ih); +} + +static void +_emotion_object_aspect_border_apply(Evas_Object *obj, Smart_Data *sd, int w, int h) +{ + int iw, ih; + double ir; + double r; + + int aspect_opt; + sd->module->video_data_size_get(sd->video, &iw, &ih); + + ir = (double)iw / ih; + r = (double)w / h; + + /* First check if we should fit the width or height of the video inside the + * width/height of the object. This check takes into account the original + * aspect ratio and the object aspect ratio, if we are keeping both sizes or + * cropping the exceding area. + */ + if (sd->aspect == EMOTION_ASPECT_KEEP_NONE) + { + sd->crop.l = 0; + sd->crop.r = 0; + sd->crop.t = 0; + sd->crop.b = 0; + aspect_opt = 0; // just ignore keep_aspect + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_WIDTH) + { + aspect_opt = 1; + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_HEIGHT) + { + aspect_opt = 2; + } + else if (sd->aspect == EMOTION_ASPECT_KEEP_BOTH) + { + if (ir > r) + aspect_opt = 1; + else + aspect_opt = 2; + } + else if (sd->aspect == EMOTION_ASPECT_CROP) + { + if (ir > r) + aspect_opt = 2; + else + aspect_opt = 1; + } + else if (sd->aspect == EMOTION_ASPECT_CUSTOM) + { + // nothing to do, just respect the border settings + aspect_opt = 0; + } + + /* updating borders based on keep_aspect settings */ + if (aspect_opt == 1) // keep width + { + int th, dh; + double scale; + + sd->crop.l = 0; + sd->crop.r = 0; + scale = (double)iw / w; + th = h * scale; + dh = ih - th; + sd->crop.t = sd->crop.b = dh / 2; + } + else if (aspect_opt == 2) // keep height + { + int tw, dw; + double scale; + + sd->crop.t = 0; + sd->crop.b = 0; + scale = (double)ih / h; + tw = w * scale; + dw = iw - tw; + sd->crop.l = sd->crop.r = dw / 2; + } + + _emotion_aspect_borders_apply(obj, sd, w, h, iw, ih); +} + +EAPI void +emotion_object_border_set(Evas_Object *obj, int l, int r, int t, int b) +{ + Smart_Data *sd; + int w, h; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + sd->aspect = EMOTION_ASPECT_CUSTOM; + sd->crop.l = -l; + sd->crop.r = -r; + sd->crop.t = -t; + sd->crop.b = -b; + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); } EAPI void @@ -531,6 +625,32 @@ emotion_object_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int evas_object_color_get(sd->bg, r, g, b, a); } +EAPI void +emotion_object_keep_aspect_set(Evas_Object *obj, Emotion_Aspect a) +{ + Smart_Data *sd; + int w, h; + + E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); + + if (a == sd->aspect) + return; + + sd->aspect = a; + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); +} + +EAPI Emotion_Aspect +emotion_object_keep_aspect_get(const Evas_Object *obj) +{ + Smart_Data *sd; + + E_SMART_OBJ_GET_RETURN(sd, obj, E_OBJ_NAME, EMOTION_ASPECT_KEEP_NONE); + + return sd->aspect; +} + EAPI void emotion_object_play_set(Evas_Object *obj, Eina_Bool play) { @@ -653,8 +773,6 @@ emotion_object_size_get(const Evas_Object *obj, int *iw, int *ih) if (ih) *ih = 0; E_SMART_OBJ_GET(sd, obj, E_OBJ_NAME); evas_object_image_size_get(sd->obj, iw, ih); - *iw -= (sd->crop.l + sd->crop.r); - *ih -= (sd->crop.t + sd->crop.b); } EAPI void @@ -1364,7 +1482,8 @@ _emotion_frame_resize(Evas_Object *obj, int w, int h, double ratio) { evas_object_size_hint_request_set(obj, w, h); evas_object_smart_callback_call(obj, SIG_FRAME_RESIZE, NULL); - _clipper_position_size_update(obj, w, h); + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _emotion_object_aspect_border_apply(obj, sd, w, h); } } @@ -1750,7 +1869,8 @@ _smart_move(Evas_Object * obj, Evas_Coord x, Evas_Coord y) int vid_w, vid_h, w, h; sd->module->video_data_size_get(sd->video, &vid_w, &vid_h); - _clipper_position_size_update(obj, vid_w, vid_h); + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + _clipper_position_size_update(obj, w, h, vid_w, vid_h); evas_object_move(sd->bg, x, y); } @@ -1765,7 +1885,8 @@ _smart_resize(Evas_Object * obj, Evas_Coord w, Evas_Coord h) int vid_w, vid_h; sd->module->video_data_size_get(sd->video, &vid_w, &vid_h); - _clipper_position_size_update(obj, vid_w, vid_h); + fprintf(stderr, "smart resize: %dx%d\n", w, h); + _emotion_object_aspect_border_apply(obj, sd, w, h); evas_object_resize(sd->bg, w, h); }