diff options
35 files changed, 975 insertions, 43 deletions
@@ -404,6 +404,15 @@ This library acts as a porting library for Windows to provide missing libc calls not in Mingw32 that EFL needs. +**Heif:** + +//LGPL v3 license// + +The license doesnt affect efl or apps using efl, but gpl3 or lgpl3 +affects the entire os requiring any gpl/lgpl3 component be +user-replacable. +The end user must be able to modify the libheif code and still be +able to use the efl. COMPILING AND INSTALLING diff --git a/data/elementary/themes/edc/elm/progress.edc b/data/elementary/themes/edc/elm/progress.edc index d5d848737d..f9f54f1e11 100644 --- a/data/elementary/themes/edc/elm/progress.edc +++ b/data/elementary/themes/edc/elm/progress.edc @@ -165,6 +165,41 @@ group { name: "elm/progressbar/horizontal/default"; description { state: "default" 0.0; rel1.to: "bg"; rel2.to: "bg"; + min: 5 16; + align: 1.0 0.5; + } + } + part { name: "inside-hi"; + scale: 1; + description { state: "default" 0.0; + rel1.to: "inside"; + rel1.offset: 0 1; + rel2.to: "inside"; + rel2.offset: -1 0; + image.normal: "inset_bar_horiz_inside_light.png"; + image.border: 8 8 0 0; + image.border_scale_by: 0.25; image.border_scale: 1; + } + } + part { name: "inside"; + scale: 1; + description { state: "default" 0.0; + fixed: 1 1; + min: 4 4; + rel1.to: "ins0"; + rel1.relative: 1.0 (6/16); + rel2.to: "ins1"; + rel2.relative: 0.0 (10/16); + image.normal: "inset_bar_horiz_inside_base.png"; + image.border: 8 8 0 0; + image.border_scale_by: 0.25; image.border_scale: 1; + } + } + part { name: "elm.swallow.bar"; type: SWALLOW; mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "inside"; + rel2.to: "inside"; +>>>>>>> master } } part { name: "elm.cur.progressbar"; mouse_events: 0; type: SPACER; diff --git a/data/evas/evas.xml b/data/evas/evas.xml new file mode 100644 index 0000000000..7764c0c05e --- /dev/null +++ b/data/evas/evas.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> +>------<mime-type type="image/heif"> +>------>-------<comment>HEIF image file</comment> +>------>-------<glob pattern="*.heif"/> +>------>-------<glob pattern="*.heic"/> +>------</mime-type> +>------<mime-type type="image/avif"> +>------>-------<comment>AVIF image file</comment> +>------>--------<glob pattern="*.avif"/> +>------</mime-type> +</mime-info> + diff --git a/data/evas/meson.build b/data/evas/meson.build new file mode 100644 index 0000000000..ddcc57dcad --- /dev/null +++ b/data/evas/meson.build @@ -0,0 +1,4 @@ +install_data(files('evas.xml'), + install_dir : join_paths(dir_data, 'mime', 'packages') +) + diff --git a/data/meson.build b/data/meson.build index 4e1f68d406..5944dad07c 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,4 +1,4 @@ -checkme_files = ['ecore', 'ecore_imf', 'ecore_x', 'eeze', 'efreet', 'elua', 'emotion', 'ethumb', 'ethumb_client', 'evas'] +checkme_files = ['ecore', 'ecore_imf', 'ecore_x', 'eeze', 'efreet', 'elua', 'emotion', 'ethumb', 'ethumb_client'] foreach checkme : checkme_files install_data(join_paths(checkme, 'checkme'), install_dir : join_paths(dir_data, checkme) @@ -10,3 +10,4 @@ subdir('edje') subdir('embryo') subdir(join_paths('ethumb', 'frames')) subdir('elementary') +subdir('evas') diff --git a/meson_options.txt b/meson_options.txt index 1e1d545cd3..e6e2b958d7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -189,8 +189,8 @@ option('unmount-path', option('evas-loaders-disabler', type : 'array', description : 'List of modular image/vector loaders to disable in efl', - choices : ['', 'gst', 'pdf', 'ps', 'raw', 'svg', 'rsvg', 'xcf', 'bmp', 'dds', 'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 'tgv', 'tiff', 'wbmp', 'webp', 'xpm', 'json', 'avif'], - value : ['avif'] + choices : ['', 'gst', 'pdf', 'ps', 'raw', 'svg', 'rsvg', 'xcf', 'bmp', 'dds', 'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 'tgv', 'tiff', 'wbmp', 'webp', 'xpm', 'json', 'avif', 'heif'], + value : ['avif', 'heif'] ) option('ecore-imf-loaders-disabler', diff --git a/src/bin/elementary/config.c b/src/bin/elementary/config.c index ff05307700..70c9a519f1 100644 --- a/src/bin/elementary/config.c +++ b/src/bin/elementary/config.c @@ -4414,25 +4414,25 @@ efl_main(void *data EINA_UNUSED, const Efl_Event *ev) else if ((!strcmp(arg, "-t")) && (i < eina_array_count(arge->argv))) { i++; - theme_set = arg; + theme_set = eina_array_data_get(arge->argv, i); interactive = 0; } else if ((!strcmp(arg, "-f")) && (i < eina_array_count(arge->argv))) { i++; - finger_size_set = arg; + finger_size_set = eina_array_data_get(arge->argv, i); interactive = 0; } else if ((!strcmp(arg, "-s")) && (i < eina_array_count(arge->argv))) { i++; - scale_set = arg; + scale_set = eina_array_data_get(arge->argv, i); interactive = 0; } else if ((!strcmp(arg, "-w")) && (i < eina_array_count(arge->argv))) { i++; - web_backend = arg; + web_backend = eina_array_data_get(arge->argv, i); interactive = 0; } } diff --git a/src/bin/elementary/test_genlist.c b/src/bin/elementary/test_genlist.c index bf6ba4c9d9..41ff4a3903 100644 --- a/src/bin/elementary/test_genlist.c +++ b/src/bin/elementary/test_genlist.c @@ -292,6 +292,24 @@ _gl_selected(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i } static void +_gl_unselected(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + printf("unselected: %p\n", event_info); +} + +static void +_gl_highlighted(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + printf("highlighted: %p\n", event_info); +} + +static void +_gl_unhighlighted(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) +{ + printf("unhighlighted: %p\n", event_info); +} + +static void _gl_double_clicked(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { printf("double clicked: %p\n", event_info); @@ -445,6 +463,9 @@ test_genlist(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i gl = elm_genlist_add(win); evas_object_smart_callback_add(gl, "selected", _gl_selected, NULL); + evas_object_smart_callback_add(gl, "unselected", _gl_unselected, NULL); + evas_object_smart_callback_add(gl, "highlighted", _gl_highlighted, NULL); + evas_object_smart_callback_add(gl, "unhighlighted", _gl_unhighlighted, NULL); evas_object_smart_callback_add(gl, "clicked,double", _gl_double_clicked, NULL); evas_object_smart_callback_add(gl, "clicked,right", _gl_right_clicked, NULL); evas_object_smart_callback_add(gl, "longpressed", _gl_longpress, NULL); diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c index 23409d96ef..a579abff97 100644 --- a/src/lib/ecore_evas/ecore_evas.c +++ b/src/lib/ecore_evas/ecore_evas.c @@ -3088,11 +3088,18 @@ _ecore_evas_animator_detach(Ecore_Animator *a) ee = a->ee; if (a->suspended) - ee->ee_anim.suspended = eina_inlist_remove(ee->ee_anim.suspended, EINA_INLIST_GET(a)); - else if ((!tmp->next) && (!tmp->prev) && (EINA_INLIST_GET(a) != ee->ee_anim.active)) + { + ee->ee_anim.suspended = + eina_inlist_remove(ee->ee_anim.suspended, EINA_INLIST_GET(a)); + } + else if ((!tmp->next) && (!tmp->prev) && + (EINA_INLIST_GET(a) != ee->ee_anim.active)) return; else - ee->ee_anim.active = eina_inlist_remove(ee->ee_anim.active, EINA_INLIST_GET(a)); + { + ee->ee_anim.active = + eina_inlist_remove(ee->ee_anim.active, EINA_INLIST_GET(a)); + } a->suspended = EINA_FALSE; } diff --git a/src/lib/ecore_file/ecore_file_monitor_kevent.c b/src/lib/ecore_file/ecore_file_monitor_kevent.c new file mode 100644 index 0000000000..e8c4c1e238 --- /dev/null +++ b/src/lib/ecore_file/ecore_file_monitor_kevent.c @@ -0,0 +1,290 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <sys/event.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "ecore_file_private.h" + +#define KEVENT_NUM_EVENTS 5 + +typedef struct _Ecore_File_Monitor_Kevent Ecore_File_Monitor_Kevent; + +#define ECORE_FILE_MONITOR_KEVENT(x) ((Ecore_File_Monitor_Kevent *)(x)) + +struct _Ecore_File_Monitor_Kevent +{ + Ecore_File_Monitor monitor; + Eina_List *prev; + int fd; +}; + +typedef struct _File_Info File_Info; +struct _File_Info +{ + const char *path; + Eina_Stat st; +}; + +static Ecore_Fd_Handler *_kevent_fdh = NULL; +static Eina_Hash *_kevent_monitors = NULL; + +static Eina_Bool _ecore_file_monitor_kevent_handler(void *data, Ecore_Fd_Handler *fdh); +static int _ecore_file_monitor_kevent_monitor(Ecore_File_Monitor *em, const char *path); +static void _ecore_file_monitor_kevent_find(Ecore_File_Monitor *em); +static void _ecore_file_monitor_kevent_hash_del_cb(void *data); +static Eina_List * _ecore_file_monitor_kevent_ls(const char *directory); +static void _ecore_file_monitor_kevent_ls_free(Eina_List *); + +int +ecore_file_monitor_backend_init(void) +{ + int fd; + + if (_kevent_fdh != NULL) return 0; + + fd = kqueue(); + if (fd < 0) + return 0; + + _kevent_fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_kevent_handler, + NULL, NULL, NULL); + if (!_kevent_fdh) + { + close(fd); + return 0; + } + + _kevent_monitors = eina_hash_int32_new(_ecore_file_monitor_kevent_hash_del_cb); + return 1; +} + +int +ecore_file_monitor_backend_shutdown(void) +{ + int fd; + + if (!_kevent_fdh) return 1; + + eina_hash_free(_kevent_monitors); + + fd = ecore_main_fd_handler_fd_get(_kevent_fdh); + ecore_main_fd_handler_del(_kevent_fdh); + _kevent_fdh = NULL; + + if (fd != -1) + close(fd); + + return 1; +} + +Ecore_File_Monitor * +ecore_file_monitor_backend_add(const char *path, + void (*func) (void *data, Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + Ecore_File_Monitor *em; + char *path2; + size_t len; + + if (!path) return NULL; + if (!func) return NULL; + + em = (Ecore_File_Monitor *)calloc(1, sizeof(Ecore_File_Monitor_Kevent)); + if (!em) return NULL; + + em->func = func; + em->data = data; + + len = strlen(path); + path2 = alloca(len + 1); + strcpy(path2, path); + if (path2[len - 1] == '/' && strcmp(path2, "/")) path2[len - 1] = 0; + em->path = eina_stringshare_add(path2); + + if (!_ecore_file_monitor_kevent_monitor(em, em->path)) + return NULL; + + return em; +} + +static Eina_List * +_ecore_file_monitor_kevent_ls(const char *directory) +{ + Eina_Iterator *it; + Eina_File_Direct_Info *info; + Eina_List *files = NULL; + + it = eina_file_direct_ls(directory); + if (!it) return NULL; + + EINA_ITERATOR_FOREACH(it, info) + { + File_Info *file = malloc(sizeof(File_Info)); + if (eina_file_statat(eina_iterator_container_get(it), info, &file->st)) + { + free(file); + continue; + } + file->path = eina_stringshare_add(info->path); + files = eina_list_append(files, file); + } + + eina_iterator_free(it); + + return files; +} + +static void +_ecore_file_monitor_kevent_ls_free(Eina_List *list) +{ + File_Info *file; + + EINA_LIST_FREE(list, file) + { + eina_stringshare_del(file->path); + free(file); + } +} + +static void +_ecore_file_monitor_kevent_hash_del_cb(void *data) +{ + Ecore_File_Monitor *em = data; + + if (ECORE_FILE_MONITOR_KEVENT(em)->fd >= 0) + close(ECORE_FILE_MONITOR_KEVENT(em)->fd); + eina_stringshare_del(em->path); + _ecore_file_monitor_kevent_ls_free(ECORE_FILE_MONITOR_KEVENT(em)->prev); + + free(em); +} + +void +ecore_file_monitor_backend_del(Ecore_File_Monitor *em) +{ + eina_hash_del(_kevent_monitors, &(ECORE_FILE_MONITOR_KEVENT(em)->fd), em); +} + +static Eina_Bool +_ecore_file_monitor_kevent_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh) +{ + Ecore_File_Monitor *em; + struct kevent evs[KEVENT_NUM_EVENTS]; + int fd; + const struct timespec timeout = { 0, 0 }; + + fd = ecore_main_fd_handler_fd_get(fdh); + if (fd < 0) return ECORE_CALLBACK_RENEW; + + int res = kevent(fd, 0, 0, evs, KEVENT_NUM_EVENTS, &timeout); + for (int i = 0; i < res; i++) + { + em = eina_hash_find(_kevent_monitors, &evs[i].ident); + if (evs[i].fflags & NOTE_DELETE) + { + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path); + } + if ((evs[i].fflags & NOTE_WRITE) || (evs[i].fflags & NOTE_ATTRIB)) + { + _ecore_file_monitor_kevent_find(em); + } + } + + return ECORE_CALLBACK_RENEW; +} + +static void +_ecore_file_monitor_kevent_find(Ecore_File_Monitor *em) +{ + Eina_List *l, *l2; + File_Info *file, *file2; + Eina_List *files; + + files = _ecore_file_monitor_kevent_ls(em->path); + + EINA_LIST_FOREACH(ECORE_FILE_MONITOR_KEVENT(em)->prev, l, file) + { + Eina_Bool exists = EINA_FALSE; + EINA_LIST_FOREACH(files, l2, file2) + { + if (file->st.ino == file2->st.ino) + { + if (file->path == file2->path) + exists = EINA_TRUE; + + if (file->st.mtime != file2->st.mtime) + em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, file->path); + } + } + + if (!exists) + { + if (S_ISDIR(file->st.mode)) + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, file->path); + else + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, file->path); + } + } + + EINA_LIST_FOREACH(files, l, file) + { + Eina_Bool exists = EINA_FALSE; + EINA_LIST_FOREACH(ECORE_FILE_MONITOR_KEVENT(em)->prev, l2, file2) + { + if ((file->path == file2->path) && (file->st.ino == file2->st.ino)) + { + exists = EINA_TRUE; + break; + } + } + + if (!exists) + { + if (S_ISDIR(file->st.mode)) + em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, file->path); + else + em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, file->path); + } + } + + _ecore_file_monitor_kevent_ls_free(ECORE_FILE_MONITOR_KEVENT(em)->prev); + ECORE_FILE_MONITOR_KEVENT(em)->prev = files; +} + +static int +_ecore_file_monitor_kevent_monitor(Ecore_File_Monitor *em, const char *path) +{ + struct kevent ev; + int fd, res = 0; + + if ((!ecore_file_exists(path)) || (!ecore_file_is_dir(path))) + return 0; + + fd = open(path, O_RDONLY); + if (fd < 0) + { + INF("open failed, %s", strerror(errno)); + ecore_file_monitor_backend_del(em); + return 0; + } + + eina_file_close_on_exec(fd, EINA_TRUE); + + ECORE_FILE_MONITOR_KEVENT(em)->fd = fd; + ECORE_FILE_MONITOR_KEVENT(em)->prev = _ecore_file_monitor_kevent_ls(em->path); + + eina_hash_direct_add(_kevent_monitors, &(ECORE_FILE_MONITOR_KEVENT(em)->fd), em); + + EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, + NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB, 0, NULL); + res = kevent(ecore_main_fd_handler_fd_get(_kevent_fdh), &ev, 1, 0, 0, 0); + if (res) + eina_hash_del(_kevent_monitors, &(ECORE_FILE_MONITOR_KEVENT(em)->fd), em); + + return 1; +} diff --git a/src/lib/ecore_file/meson.build b/src/lib/ecore_file/meson.build index 9e0212d6c0..a25d98dffb 100644 --- a/src/lib/ecore_file/meson.build +++ b/src/lib/ecore_file/meson.build @@ -14,6 +14,8 @@ if sys_windows == true ecore_file_src += files([ 'ecore_file_monitor_win32.c']) elif sys_linux == true ecore_file_src += files([ 'ecore_file_monitor_inotify.c']) +elif sys_bsd == true + ecore_file_src += files([ 'ecore_file_monitor_kevent.c']) else ecore_file_src += files([ 'ecore_file_monitor_poll.c']) endif diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h index ae82a549ce..8eb235b5fb 100644 --- a/src/lib/ecore_x/Ecore_X.h +++ b/src/lib/ecore_x/Ecore_X.h @@ -2610,6 +2610,7 @@ EAPI void *ecore_x_input_device_property_get(int slot, const char *prop EAPI void ecore_x_input_device_property_set(int slot, const char *prop, void *data, int num, Ecore_X_Atom format, int unit_size); /**< @since 1.24 */ EAPI Eina_Bool ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win); +EAPI void ecore_x_vsync_animator_tick_delay_set(double delay); /** < @since 1.26 */ typedef enum _Ecore_X_Gesture_Event_Mask { diff --git a/src/lib/ecore_x/ecore_x_vsync.c b/src/lib/ecore_x/ecore_x_vsync.c index ff72d9f270..5ad828d0fe 100644 --- a/src/lib/ecore_x/ecore_x_vsync.c +++ b/src/lib/ecore_x/ecore_x_vsync.c @@ -29,6 +29,8 @@ int _ecore_x_image_shm_check(void); static int _vsync_log_dom = -1; +static double _ecore_x_vsync_animator_tick_delay = 0.0; + #undef ERR #define ERR(...) EINA_LOG_DOM_ERR(_vsync_log_dom, __VA_ARGS__) @@ -288,17 +290,58 @@ _drm_send_time(double t) { if (threaded_vsync) { + static double t_last = 0.0; double *tim = malloc(sizeof(*tim)); + + // you won't believe this + if (t <= t_last) + { + fprintf(stderr, "EEEEEEK! time went backwards! %1.5f -> %1.5f\n", t_last, t); + t = ecore_time_get(); + if (t <= t_last) t = t_last + 0.001; + } if (tim) { *tim = t; DBG(" ... send %1.8f", t); + // if we are the wm/compositor we need to offset out vsync by 1/2 + // a frame ... we should never offset by more than + // frame_time - render_time though ... but we don't know what + // this is and this varies... so for now this will do.a + if (_ecore_x_vsync_animator_tick_delay > 0.0) + { + static double t_delta_hist[10] = { 0.0 }; + double t_delta = t - t_last; + double t_delta_min = 0.0; + double t_sleep = 0.0; + + // if time delta is sane like 1/20th of a sec or less.. + if (t_delta < (1.0 / 20.0)) + { + int i; + + for (i = 0; i < 9; i++) + t_delta_hist[i] = t_delta_hist[i + 1]; + t_delta_hist[9] = t_delta; + t_delta_min = t_delta_hist[0]; + for (i = 1; i < 10; i++) + { + if (t_delta_hist[i] < t_delta_min) + t_delta_min = t_delta_hist[i]; + } + t_sleep = t_delta_min * _ecore_x_vsync_animator_tick_delay; + // if w'ere sleeping too long - don't sleep at all. + if (t_sleep > (1.0 / 20.0)) t_sleep = 0.0; + } + if (t_sleep > 0.0) usleep(t_sleep * 1000000.0); + } D(" @%1.5f ... send %1.8f\n", ecore_time_get(), t); eina_spinlock_take(&tick_queue_lock); tick_queue_count++; eina_spinlock_release(&tick_queue_lock); ecore_thread_feedback(drm_thread, tim); } + t_last = t; } else { @@ -341,12 +384,20 @@ _drm_vblank_handler(int fd EINA_UNUSED, if (pframe != frame) { #define DELTA_COUNT 10 - double t = (double)sec + ((double)usec / 1000000); double tnow = ecore_time_get(); + double t = (double)sec + ((double)usec / 1000000); + unsigned long long tusec, ptusec; static double tdelta[DELTA_COUNT]; static double tdelta_avg = 0.0; static int tdelta_n = 0; + static unsigned int psec = 0, pusec = 0; + tusec = ((unsigned long long)sec) * 1000000 + usec; + ptusec = ((unsigned long long)psec) * 1000000 + pusec; + if (tusec <= ptusec) + fprintf(stderr, + "EEEEEEK! drm time went backwards! %u.%06u -> %u.%06u\n", + psec, pusec, sec, usec); if (t > tnow) { if (tdelta_n > DELTA_COUNT) @@ -377,6 +428,8 @@ _drm_vblank_handler(int fd EINA_UNUSED, _drm_fail_count = 0; _drm_send_time(t); pframe = frame; + psec = sec; + pusec = usec; } } else @@ -929,3 +982,9 @@ ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win) } return EINA_TRUE; } + +EAPI void +ecore_x_vsync_animator_tick_delay_set(double delay) +{ + _ecore_x_vsync_animator_tick_delay = delay; +} diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c index ab48c3dd3a..b62c12b631 100644 --- a/src/lib/edje/edje_entry.c +++ b/src/lib/edje/edje_entry.c @@ -1279,6 +1279,8 @@ _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en) { Evas_Textblock_Rectangle *r; + if (!range) break; + r = range->data; *(&(sel->rect)) = *r; if (_is_anchors_outside_viewport(y, r->y, r->h, vy, tvh) || diff --git a/src/lib/eet/eet_cipher.c b/src/lib/eet/eet_cipher.c index 51f8513dce..025750cc98 100644 --- a/src/lib/eet/eet_cipher.c +++ b/src/lib/eet/eet_cipher.c @@ -564,6 +564,11 @@ eet_identity_sign(FILE *fp, /* Do the signature. */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + { + err = EET_ERROR_OUT_OF_MEMORY; + goto on_error; + } EVP_SignInit(md_ctx, EVP_sha1()); EVP_SignUpdate(md_ctx, data, st_buf.st_size); err = EVP_SignFinal(md_ctx, @@ -776,6 +781,16 @@ eet_identity_check(const void *data_base, /* Verify the signature */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + { + err = EET_ERROR_OUT_OF_MEMORY; + + X509_free(x509); + EVP_PKEY_free(pkey); + + return NULL; + } + EVP_VerifyInit(md_ctx, EVP_sha1()); EVP_VerifyUpdate(md_ctx, data_base, data_length); err = EVP_VerifyFinal(md_ctx, sign, sign_len, pkey); diff --git a/src/lib/eeze/eeze_udev_syspath.c b/src/lib/eeze/eeze_udev_syspath.c index 87b2c0fa78..4d2a5c237a 100644 --- a/src/lib/eeze/eeze_udev_syspath.c +++ b/src/lib/eeze/eeze_udev_syspath.c @@ -53,7 +53,10 @@ eeze_udev_syspath_get_parents(const char *syspath) return NULL; if (!(parent = udev_device_get_parent(device))) - return NULL; + { + udev_device_unref(device); + return NULL; + } for (; parent; child = parent, parent = udev_device_get_parent(child)) { diff --git a/src/lib/eeze/eeze_udev_walk.c b/src/lib/eeze/eeze_udev_walk.c index 78e2aabda4..4cd661b184 100644 --- a/src/lib/eeze/eeze_udev_walk.c +++ b/src/lib/eeze/eeze_udev_walk.c @@ -49,17 +49,18 @@ eeze_udev_walk_get_sysattr(const char *syspath, if (!(device = _new_device(syspath))) return NULL; - for (parent = device; parent; - child = parent, parent = udev_device_get_parent(child)) + for (parent = device; parent;) { if ((test = udev_device_get_sysattr_value(parent, sysattr))) { test = eina_stringshare_add(test); - udev_device_unref(device); + udev_device_unref(parent); return test; } + child = parent; + parent = udev_device_get_parent(child); + udev_device_unref(child); } - udev_device_unref(device); return NULL; } diff --git a/src/lib/efreet/efreet_base.c b/src/lib/efreet/efreet_base.c index 736a3a05fc..7b1490af46 100644 --- a/src/lib/efreet/efreet_base.c +++ b/src/lib/efreet/efreet_base.c @@ -134,7 +134,13 @@ EAPI const char * efreet_desktop_dir_get(void) { if (xdg_desktop_dir) return xdg_desktop_dir; - xdg_desktop_dir = efreet_user_dir_get("XDG_DESKTOP_DIR", _("Desktop")); + xdg_desktop_dir = efreet_user_dir_get("XDG_DESKTOP_DIR", +#ifdef _WIN32 + "Desktop" +#else + _("Desktop") +#endif + ); return xdg_desktop_dir; } @@ -142,7 +148,13 @@ EAPI const char * efreet_download_dir_get(void) { if (xdg_download_dir) return xdg_download_dir; - xdg_download_dir = efreet_user_dir_get("XDG_DOWNLOAD_DIR", _("Downloads")); + xdg_download_dir = efreet_user_dir_get("XDG_DOWNLOAD_DIR", +#ifdef _WIN32 + "Downloads" +#else + _("Downloads") +#endif + ); return xdg_download_dir; } @@ -151,7 +163,12 @@ efreet_templates_dir_get(void) { if (xdg_templates_dir) return xdg_templates_dir; xdg_templates_dir = efreet_user_dir_get("XDG_TEMPLATES_DIR", - _("Templates")); +#ifdef _WIN32 + "Templates" +#else + _("Templates") +#endif + ); return xdg_templates_dir; } @@ -177,7 +194,13 @@ EAPI const char * efreet_music_dir_get(void) { if (xdg_music_dir) return xdg_music_dir; - xdg_music_dir = efreet_user_dir_get("XDG_MUSIC_DIR", _("Music")); + xdg_music_dir = efreet_user_dir_get("XDG_MUSIC_DIR", +#ifdef _WIN32 + "Music" +#else + _("Music") +#endif + ); return xdg_music_dir; } @@ -185,7 +208,13 @@ EAPI const char * efreet_pictures_dir_get(void) { if (xdg_pictures_dir) return xdg_pictures_dir; - xdg_pictures_dir = efreet_user_dir_get("XDG_PICTURES_DIR", _("Pictures")); + xdg_pictures_dir = efreet_user_dir_get("XDG_PICTURES_DIR", +#ifdef _WIN32 + "Pictures" +#else + _("Pictures") +#endif + ); return xdg_pictures_dir; } @@ -193,7 +222,13 @@ EAPI const char * efreet_videos_dir_get(void) { if (xdg_videos_dir) return xdg_videos_dir; - xdg_videos_dir = efreet_user_dir_get("XDG_VIDEOS_DIR", _("Videos")); + xdg_videos_dir = efreet_user_dir_get("XDG_VIDEOS_DIR", +#ifdef _WIN32 + "Videos" +#else + _("Videos") +#endif + ); return xdg_videos_dir; } diff --git a/src/lib/efreet/efreet_uri.c b/src/lib/efreet/efreet_uri.c index 44fe54a35f..2b64556159 100644 --- a/src/lib/efreet/efreet_uri.c +++ b/src/lib/efreet/efreet_uri.c @@ -2,8 +2,15 @@ # include <config.h> #endif +#include <stdlib.h> +#include <string.h> #include <ctype.h> +#ifdef _WIN32 +# include <windows.h> +# include <shlwapi.h> +#endif + #ifndef _POSIX_HOST_NAME_MAX #define _POSIX_HOST_NAME_MAX 255 #endif @@ -28,6 +35,64 @@ efreet_uri_decode(const char *full_uri) EINA_SAFETY_ON_NULL_RETURN_VAL(full_uri, NULL); /* An uri should be in the form <scheme>:[<authority>][<path>][<query>][<fragment>] */ + + /* + * Specific code for Windows when the scheme part of full_uri is 'file', + * for local Windows file path. + * see https://docs.microsoft.com/en-us/archive/blogs/ie/file-uris-in-windows + * + * Correct syntax : + * file:///c:/path/to/file + * + * The returned path must be c:\path\to\file + */ +#ifdef _WIN32 + + *scheme = 0; + *authority = 0; + *path = 0; + + if (strncasecmp(full_uri, "file://", strlen("file://")) == 0) + { + HRESULT res; + DWORD len; +# ifdef UNICODE + wchar_t buf[MAX_PATH]; + wchar_t *w_full_uri; + char *uri; + + w_full_uri = evil_utf8_to_utf16(full_uri); + if (!w_full_uri) + return NULL; + + if (wcslen(w_full_uri) > 2048) + { + free(w_full_uri); + return NULL; + } + + len = sizeof(buf); + res = PathCreateFromUrl(w_full_uri, buf, &len, 0UL); + free(w_full_uri); + if (res != S_OK) + return NULL; + uri = evil_utf16_to_utf8(buf); + if (uri) + { + strncpy(path, uri, sizeof(path)); + path[sizeof(path)-1] = 0; + goto win32_file_scheme; + } +#else + len = sizeof(path); + res = PathCreateFromUrl(full_uri, path, &len, 0UL); + if (res == S_OK) + goto win32_file_scheme; +#endif + return NULL; + } +#endif + sep = strchr(full_uri, ':'); if (!sep) return NULL; /* check if we have a Windows PATH, that is a letter follow by a colon */ @@ -77,6 +142,11 @@ efreet_uri_decode(const char *full_uri) path[i] = *p; } +#ifdef _WIN32 + win32_file_scheme: + strcpy(scheme, "file"); +#endif + uri = NEW(Efreet_Uri, 1); if (!uri) return NULL; diff --git a/src/lib/efreet/meson.build b/src/lib/efreet/meson.build index 41d3113566..1d02f3db1f 100644 --- a/src/lib/efreet/meson.build +++ b/src/lib/efreet/meson.build @@ -36,6 +36,11 @@ efreet_ext_deps = [buildsystem_simple, intl, m] package_c_args += ['-DDATA_DIR="'+dir_data+'"'] +if sys_windows + shlwapi = cc.find_library('shlwapi') + efreet_ext_deps += [shlwapi] +endif + efreet_lib = library('efreet', efreet_src, dependencies: efreet_pub_deps + efreet_ext_deps + efreet_deps, diff --git a/src/lib/elementary/efl_ui_textpath.c b/src/lib/elementary/efl_ui_textpath.c index 321cd20568..6638de5456 100644 --- a/src/lib/elementary/efl_ui_textpath.c +++ b/src/lib/elementary/efl_ui_textpath.c @@ -264,7 +264,7 @@ static void _text_on_line_draw(Efl_Ui_Textpath_Data *pd, int w1, int w2, int cmp, Evas_Map *map, Efl_Ui_Textpath_Line line) { double x1, x2, y1, y2; - double line_len, len, sina, cosa; + double line_len_2, line_len, len, sina, cosa; Eina_Rect r; x1 = line.start.x; @@ -272,15 +272,17 @@ _text_on_line_draw(Efl_Ui_Textpath_Data *pd, int w1, int w2, int cmp, Evas_Map * x2 = line.end.x; y2 = line.end.y; - line_len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); + line_len_2 = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1); len = w2 - w1; - if (line_len > len) + if (line_len_2 > (len * len)) { + line_len = sqrt(line_len_2); x2 = x1 + len * (x2 - x1) / line_len; y2 = y1 + len * (y2 - y1) / line_len; + line_len_2 = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1); } - len = sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); + len = sqrt(line_len_2); sina = (y2 - y1) / len; cosa = (x2 - x1) / len; diff --git a/src/lib/emile/emile_cipher_openssl.c b/src/lib/emile/emile_cipher_openssl.c index b09897ec9b..e5a1ed4135 100644 --- a/src/lib/emile/emile_cipher_openssl.c +++ b/src/lib/emile/emile_cipher_openssl.c @@ -75,10 +75,16 @@ emile_binbuf_sha1(const Eina_Binbuf * data, unsigned char digest[20]) Eina_Slice slice = eina_binbuf_slice_get(data); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) return EINA_FALSE; EVP_DigestInit_ex(ctx, md, NULL); - EVP_DigestUpdate(ctx, slice.mem, slice.len); + if (!EVP_DigestUpdate(ctx, slice.mem, slice.len)) + { + EVP_MD_CTX_free(ctx); + return EINA_FALSE; + } + EVP_DigestFinal_ex(ctx, digest, NULL); EVP_MD_CTX_free(ctx); diff --git a/src/lib/ethumb_client/ethumb_client.c b/src/lib/ethumb_client/ethumb_client.c index 1175402887..70e56bce94 100644 --- a/src/lib/ethumb_client/ethumb_client.c +++ b/src/lib/ethumb_client/ethumb_client.c @@ -204,6 +204,7 @@ _ethumb_client_free(Ethumb_Client *client) if (client->invalid) return; + if (client->dbus_pending) { Eldbus_Pending *pending; EINA_LIST_FREE(client->dbus_pending, pending) @@ -216,8 +217,11 @@ _ethumb_client_free(Ethumb_Client *client) struct _ethumb_pending_add *pending = data; if (pending->pending_call) { - eldbus_pending_cancel(pending->pending_call); + Eldbus_Pending *call = pending->pending_call; + + pending->pending_call = NULL; pending->client = NULL; + eldbus_pending_cancel(call); } else { @@ -245,8 +249,11 @@ _ethumb_client_free(Ethumb_Client *client) pending->free_data(pending->data); if (pending->pending_call) { - eldbus_pending_cancel(pending->pending_call); + Eldbus_Pending *call = pending->pending_call; + + pending->pending_call = NULL; pending->client = NULL; + eldbus_pending_cancel(call); } else { diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 3b369060c9..7ebb1f4143 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -737,6 +737,8 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, user_entry->path_bounds.w, user_entry->path_bounds.h); } + // If size of the drawing area is 0, no render. + else return; if (pd->viewbox.w != 0 && pd->viewbox.h !=0) { diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index b206d09bb1..f44dfaab5c 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -4372,6 +4372,10 @@ _layout_format_push(Ctxt *c, Evas_Object_Textblock_Format *fmt, (int)(((double) _FMT_INFO(size)) * evas_obj->cur->scale), fmt->font.bitmap_scalable); } + else if (_FMT_INFO(size)) // if font size specified alone, without font + { + fmt->font.size = _FMT_INFO(size); + } if (_FMT_INFO(gfx_filter_name)) { if (!fmt->gfx_filter) diff --git a/src/lib/evas/common/evas_image_load.c b/src/lib/evas/common/evas_image_load.c index 8ed04dda2e..797fae37ea 100644 --- a/src/lib/evas/common/evas_image_load.c +++ b/src/lib/evas/common/evas_image_load.c @@ -69,6 +69,10 @@ static const struct ext_loader_s loaders[] = MATCHING(".avif", "avif"), MATCHING(".avifs", "avif"), + MATCHING(".heif", "heif"), + MATCHING(".heic", "heif"), + // MATCHING(".avif", "heif"), + /* xcf - gefenric */ MATCHING(".xcf", "generic"), MATCHING(".xcf.gz", "generic"), @@ -167,7 +171,8 @@ static const struct ext_loader_s loaders[] = static const char *loaders_name[] = { /* in order of most likely needed */ "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", - "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "generic" + "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "heif", + "generic" }; struct evas_image_foreach_loader_data diff --git a/src/lib/evas/file/evas_module.c b/src/lib/evas/file/evas_module.c index 6292c1bb42..1362a004d8 100644 --- a/src/lib/evas/file/evas_module.c +++ b/src/lib/evas/file/evas_module.c @@ -202,6 +202,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, generic); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, gif); +EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, heif); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jpeg); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jp2k); @@ -307,6 +308,9 @@ static const struct { #ifdef EVAS_STATIC_BUILD_GIF EVAS_EINA_STATIC_MODULE_USE(image_loader, gif), #endif +#ifdef EVAS_STATIC_BUILD_HEIF + EVAS_EINA_STATIC_MODULE_USE(image_loader, heif), +#endif #ifdef EVAS_STATIC_BUILD_ICO EVAS_EINA_STATIC_MODULE_USE(image_loader, ico), #endif diff --git a/src/lib/evas/meson.build b/src/lib/evas/meson.build index 8dcfd98713..1bf5fa0801 100644 --- a/src/lib/evas/meson.build +++ b/src/lib/evas/meson.build @@ -11,6 +11,7 @@ webp = dependency('libwebp', version: ['>=0.5.0'], required: get_option('evas-lo webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) libopenjp2 = dependency('libopenjp2', required: get_option('evas-loaders-disabler').contains('jp2k') == false) libavif = dependency('libavif', required: get_option('evas-loaders-disabler').contains('avif') == false, version: '>= 0.8.2') +heif= dependency('libheif', required: get_option('evas-loaders-disabler').contains('heif') == false) evas_image_loaders_file = [ ['avif', 'shared', [libavif]], @@ -18,6 +19,7 @@ evas_image_loaders_file = [ ['eet', 'static', [eet]], ['generic', 'shared', [rt]], ['gif', 'shared', [giflib]], + ['heif', 'shared', [heif]], ['ico', 'shared', []], ['jpeg', 'static', [jpeg]], ['jp2k', 'shared', [libopenjp2]], diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 5b40037560..26ff021cd4 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -381,7 +381,8 @@ evas_gl_symbols(void *(*GetProcAddress)(const char *name), const char *extsn) FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", "GL_EXT_geometry_shader4", glsym_func_void); FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", "GL_ARB_geometry_shader4", glsym_func_void); - FINDSYMN(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image_external", glsym_func_void); + FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image_external", glsym_func_void); + FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image", glsym_func_void); // Old SEC extensions FINDSYMN(secsym_eglMapImageSEC, "eglMapImageSEC", NULL, secsym_func_void_ptr); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index a1c48ae451..021e798169 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -1167,7 +1167,6 @@ eng_image_orient_set(void *engine, void *image, Evas_Image_Orient orient) { im_new->tex = im->tex; im_new->tex->references++; - im_new->tex->pt->references++; } evas_gl_common_image_free(im); diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c index a22e9d95db..580921ff01 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.c +++ b/src/modules/evas/engines/gl_x11/evas_engine.c @@ -1376,8 +1376,8 @@ eng_gl_symbols(Outbuf *ob) // This is a GL extension exts = (const char *) glGetString(GL_EXTENSIONS); - FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image", glsym_func_void); FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image_external", glsym_func_void); + FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", "GL_OES_EGL_image", glsym_func_void); #else diff --git a/src/modules/evas/image_loaders/heif/evas_image_load_heif.c b/src/modules/evas/image_loaders/heif/evas_image_load_heif.c new file mode 100644 index 0000000000..bc9f2a1e06 --- /dev/null +++ b/src/modules/evas/image_loaders/heif/evas_image_load_heif.c @@ -0,0 +1,300 @@ +#define _XOPEN_SOURCE 600 + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <math.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif + +#include <libheif/heif.h> + +#include "evas_common_private.h" +#include "evas_private.h" + +static int _evas_loader_heif_log_dom = -1; + +#ifdef ERR +# undef ERR +#endif +#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_heif_log_dom, __VA_ARGS__) + +#ifdef INF +# undef INF +#endif +#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_heif_log_dom, __VA_ARGS__) + + +static void * +evas_image_load_file_open_heif(Eina_File *f, Eina_Stringshare *key EINA_UNUSED, + Evas_Image_Load_Opts *opts EINA_UNUSED, + Evas_Image_Animated *animated EINA_UNUSED, + int *error EINA_UNUSED) +{ + return f; +} + +static void +evas_image_load_file_close_heif(void *loader_data EINA_UNUSED) +{ +} + +static Eina_Bool +evas_image_load_file_head_heif(void *loader_data, + Emile_Image_Property *prop, + int *error) +{ + Eina_File *f = loader_data; + void *map; + size_t length; + struct heif_error err; + struct heif_context* hc = NULL; + struct heif_image_handle* hdl = NULL; + struct heif_image* img = NULL; + Eina_Bool r = EINA_FALSE; + + *error = EVAS_LOAD_ERROR_NONE; + + map = eina_file_map_all(f, EINA_FILE_RANDOM); + length = eina_file_size_get(f); + + // init prop struct with some default null values + prop->w = 0; + prop->h = 0; + + if (!map || length < 1) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto on_error; + } + + hc = heif_context_alloc(); + if (!hc) { + INF("cannot allocate heif_context"); + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto on_error; + } + + err = heif_context_read_from_memory_without_copy(hc, map, length, NULL); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + + err = heif_context_get_primary_image_handle(hc, &hdl); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + + int has_alpha = heif_image_handle_has_alpha_channel(hdl); + + err = heif_decode_image(hdl, &img, heif_colorspace_RGB, + has_alpha ? heif_chroma_interleaved_RGBA : heif_chroma_interleaved_RGB, + NULL); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + + prop->w = heif_image_get_width(img, heif_channel_interleaved); + prop->h = heif_image_get_height(img, heif_channel_interleaved); + if (has_alpha != 3) + prop->alpha = 1; + + r = EINA_TRUE; + + on_error: + if (img) { + heif_image_release(img); + } + + if (hdl) { + heif_image_handle_release(hdl); + } + + if (hc) { + heif_context_free(hc); + } + eina_file_map_free(f, map); + return r; +} + +static Eina_Bool +evas_image_load_file_data_heif(void *loader_data, + Emile_Image_Property *prop, + void *pixels, + int *error) +{ + Eina_File *f = loader_data; + + void *map; + size_t length; + struct heif_error err; + struct heif_context* hc = NULL; + struct heif_image_handle* hdl = NULL; + struct heif_image* img = NULL; + unsigned int x, y; + int stride, bps = 3; + const uint8_t* data; + uint8_t* dd = (uint8_t*)pixels, *ds = NULL; + Eina_Bool result = EINA_FALSE; + + map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); + length = eina_file_size_get(f); + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + if (!map || length < 1) + goto on_error; + + *error = EVAS_LOAD_ERROR_GENERIC; + result = EINA_FALSE; + + hc = heif_context_alloc(); + if (!hc) { + INF("cannot allocate heif_context"); + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto on_error; + } + + err = heif_context_read_from_memory_without_copy(hc, map, length, NULL); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + + err = heif_context_get_primary_image_handle(hc, &hdl); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + + err = heif_decode_image(hdl, &img, heif_colorspace_RGB, + prop->alpha ? heif_chroma_interleaved_RGBA : heif_chroma_interleaved_RGB, + NULL); + if (err.code != heif_error_Ok) { + INF("%s", err.message); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto on_error; + } + if (prop->alpha) bps = 4; + data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride); + ds = (uint8_t*)data; + for (y = 0; y < prop->h; y++) + for (x = 0; x < prop->w; x++) + { + if (bps == 3) + { + dd[3] = 0xff; + dd[0] = ds[2]; + dd[1] = ds[1]; + dd[2] = ds[0]; + ds+=3; + dd+=4; + } + else + { + dd[0] = ds[2]; + dd[1] = ds[1]; + dd[2] = ds[0]; + dd[3] = ds[3]; + ds+=4; + dd+=4; + } + } + result = EINA_TRUE; + + *error = EVAS_LOAD_ERROR_NONE; + prop->premul = EINA_TRUE; + +on_error: + + if (map) eina_file_map_free(f, map); + + if (img) { + // Do not free the image here when we pass it to gdk-pixbuf, as its memory will still be used by gdk-pixbuf. + heif_image_release(img); + } + + if (hdl) { + heif_image_handle_release(hdl); + } + + if (hc) { + heif_context_free(hc); + } + + return result; +} + +static const Evas_Image_Load_Func evas_image_load_heif_func = { + EVAS_IMAGE_LOAD_VERSION, + evas_image_load_file_open_heif, + evas_image_load_file_close_heif, + (void*) evas_image_load_file_head_heif, + NULL, + (void*) evas_image_load_file_data_heif, + NULL, + EINA_TRUE, + EINA_FALSE +}; + +static int +module_open(Evas_Module *em) +{ + if (!em) return 0; + _evas_loader_heif_log_dom = eina_log_domain_register + ("evas-heif", EVAS_DEFAULT_LOG_COLOR); + if (_evas_loader_heif_log_dom < 0) + { + EINA_LOG_ERR("Can not create a module log domain."); + return 0; + } + + em->functions = (void *)(&evas_image_load_heif_func); + return 1; +} + +static void +module_close(Evas_Module *em EINA_UNUSED) +{ + if (_evas_loader_heif_log_dom >= 0) + { + eina_log_domain_unregister(_evas_loader_heif_log_dom); + _evas_loader_heif_log_dom = -1; + } +} + +static Evas_Module_Api evas_modapi = + { + EVAS_MODULE_API_VERSION, + "heif", + "none", + { + module_open, + module_close + } + }; + +EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, heif); + + +#ifndef EVAS_STATIC_BUILD_HEIF +EVAS_EINA_MODULE_DEFINE(image_loader, heif); +#endif diff --git a/src/modules/evas/image_loaders/tga/evas_image_load_tga.c b/src/modules/evas/image_loaders/tga/evas_image_load_tga.c index d8ef67fc59..34ee83e0b1 100644 --- a/src/modules/evas/image_loaders/tga/evas_image_load_tga.c +++ b/src/modules/evas/image_loaders/tga/evas_image_load_tga.c @@ -77,7 +77,7 @@ evas_image_load_file_head_tga(void *loader_data, tga_footer *footer, tfooter; char hasa = 0; int w, h, bpp; - int x, y; +// int x, y; Eina_Bool r = EINA_FALSE; *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; @@ -104,7 +104,6 @@ evas_image_load_file_head_tga(void *loader_data, } } // else goto close_file; - //printf("1\n"); filedata = (unsigned char *)filedata + sizeof(tga_header); switch (header->imageType) @@ -135,13 +134,14 @@ evas_image_load_file_head_tga(void *loader_data, (header->colorMapSize == 24) || (header->colorMapSize == 32))) goto close_file; - x = (header->xOriginHi << 8) | (header->xOriginLo); - y = (header->yOriginHi << 8) | (header->yOriginLo); +// x = (header->xOriginHi << 8) | (header->xOriginLo); +// y = (header->yOriginHi << 8) | (header->yOriginLo); w = (header->widthHi << 8) | header->widthLo; h = (header->heightHi << 8) | header->heightLo; // x origin gerater that width, y origin greater than height - wrong file - if ((x >= w) || (y >= h)) - goto close_file; +// if ((x >= w) || (y >= h)) +// goto close_file; + printf("x\n"); // if descriptor has either of the top 2 bits set... not tga if (header->descriptor & 0xc0) goto close_file; @@ -237,13 +237,13 @@ evas_image_load_file_data_tga(void *loader_data, (header->colorMapSize == 24) || (header->colorMapSize == 32))) goto close_file; - x = (header->xOriginHi << 8) | (header->xOriginLo); - y = (header->yOriginHi << 8) | (header->yOriginLo); +// x = (header->xOriginHi << 8) | (header->xOriginLo); +// y = (header->yOriginHi << 8) | (header->yOriginLo); w = (header->widthHi << 8) | header->widthLo; h = (header->heightHi << 8) | header->heightLo; // x origin gerater that width, y origin greater than height - wrong file - if ((x >= w) || (y >= h)) - goto close_file; +// if ((x >= w) || (y >= h)) +// goto close_file; // if descriptor has either of the top 2 bits set... not tga if (header->descriptor & 0xc0) goto close_file; diff --git a/src/tests/evas/evas_test_image.c b/src/tests/evas/evas_test_image.c index c2530632a3..5753651f30 100644 --- a/src/tests/evas/evas_test_image.c +++ b/src/tests/evas/evas_test_image.c @@ -53,6 +53,11 @@ static const char *exts[] = { ,"jpeg" ,"jpg" #endif +#ifdef BUILD_LOADER_HEIF + ,"heif" + ,"heic" +// ,"avif" +#endif }; EFL_START_TEST(evas_object_image_loader) diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c index f78c2888d1..40dbb70967 100644 --- a/src/tests/evas/evas_test_textblock.c +++ b/src/tests/evas/evas_test_textblock.c @@ -5203,6 +5203,27 @@ EFL_START_TEST(efl_text_font_source) } EFL_END_TEST +EFL_START_TEST(efl_text_default_format) +{ + Evas *evas; + Eo *txt; + evas = EVAS_TEST_INIT_EVAS(); + txt = efl_add(EFL_CANVAS_TEXTBLOCK_CLASS, evas); + + Eina_Size2D size; + + efl_text_markup_set(txt, "<font=Sans>Hello</font>"); + + efl_text_font_size_set(txt, 80); + efl_text_color_set(txt, 255, 255, 255, 255); + size = efl_canvas_textblock_size_native_get(txt); + + ck_assert_int_gt(size.h, 20); + efl_del(txt); + evas_free(evas); +} +EFL_END_TEST + void evas_test_textblock(TCase *tc) { tcase_add_test(tc, evas_textblock_simple); @@ -5246,5 +5267,6 @@ void evas_test_textblock(TCase *tc) tcase_add_test(tc, efl_text_style); tcase_add_test(tc, efl_text_markup); tcase_add_test(tc, efl_text_font_source); + tcase_add_test(tc, efl_text_default_format); } |