From 027c174f9d0720ab28b197f4f134e2f35eead38a Mon Sep 17 00:00:00 2001 From: Sebastian Dransfeld Date: Tue, 16 Nov 2010 21:50:53 +0000 Subject: [PATCH] Find icons in cache SVN revision: 54616 --- legacy/efreet/src/lib/efreet_cache.c | 32 ++++ legacy/efreet/src/lib/efreet_icon.c | 208 +++++++++++++++++++++++-- legacy/efreet/src/lib/efreet_private.h | 5 +- 3 files changed, 232 insertions(+), 13 deletions(-) diff --git a/legacy/efreet/src/lib/efreet_cache.c b/legacy/efreet/src/lib/efreet_cache.c index 02e62b51cc..dd5190d98b 100644 --- a/legacy/efreet/src/lib/efreet_cache.c +++ b/legacy/efreet/src/lib/efreet_cache.c @@ -12,6 +12,9 @@ static Eet_Data_Descriptor *cache_icon_edd = NULL; static Eet_Data_Descriptor *cache_icon_element_edd = NULL; static Eet_Data_Descriptor *cache_icon_fallback_edd = NULL; +static Eet_File *cache = NULL; +static const char *cache_name; + static void efreet_icon_edd_shutdown(void); int @@ -142,6 +145,8 @@ efreet_cache_icon_free(Efreet_Cache_Icon *icon) { void *data; + if (!icon) return; + if (icon->free) { #if 0 @@ -176,3 +181,30 @@ efreet_cache_icon_free(Efreet_Cache_Icon *icon) } free(icon); } + +Efreet_Cache_Icon * +efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon) +{ + if (cache) + { + if (!strcmp(cache_name, theme->name.internal)) + { + eet_close(cache); + eina_stringshare_del(cache_name); + cache = NULL; + cache_name = NULL; + } + } + if (!cache) + { + const char *path; + + path = efreet_icon_cache_file(theme->name.internal); + cache = eet_open(path, EET_FILE_MODE_READ); + if (cache) + cache_name = eina_stringshare_add(theme->name.internal); + } + if (cache) + return eet_data_read(cache, cache_icon_edd, icon); + return NULL; +} diff --git a/legacy/efreet/src/lib/efreet_icon.c b/legacy/efreet/src/lib/efreet_icon.c index 1f4c4f3b0a..cf2ef493fc 100644 --- a/legacy/efreet/src/lib/efreet_icon.c +++ b/legacy/efreet/src/lib/efreet_icon.c @@ -16,10 +16,17 @@ #include "Efreet.h" #include "efreet_private.h" +#ifdef EFREET_MODULE_LOG_DOM +#undef EFREET_MODULE_LOG_DOM +#endif +#define EFREET_MODULE_LOG_DOM _efreet_icon_log_dom + +static int _efreet_icon_log_dom = -1; + /* TODO: Scan efreet_extra_icon_dirs for themes */ -static char *efreet_icon_deprecated_user_dir = NULL; -static char *efreet_icon_user_dir = NULL; +static const char *efreet_icon_deprecated_user_dir = NULL; +static const char *efreet_icon_user_dir = NULL; static Eina_Hash *efreet_icon_themes = NULL; static Eina_List *efreet_icon_extensions = NULL; static Eina_List *efreet_extra_icon_dirs = NULL; @@ -90,6 +97,14 @@ static void efreet_icon_cache_free(Efreet_Icon_Cache *value); static const char *efreet_icon_cache_check(Efreet_Icon_Theme *theme, const char *icon, unsigned int size); static void efreet_icon_cache_add(Efreet_Icon_Theme *theme, const char *icon, unsigned int size, const char *value); +#ifdef ICON_CACHE +static const char *efreet_cache_icon_lookup_icon(Efreet_Cache_Icon *icon, unsigned int size); +static int efreet_cache_icon_size_match(Efreet_Cache_Icon_Element *elem, unsigned int size); +static double efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size); +static const char *efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem); +static const char *efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path); +#endif + /** * @internal * @return Returns 1 on success or 0 on failure @@ -104,7 +119,13 @@ efreet_icon_init(void) int i; if (!ecore_init()) + return 0; + + _efreet_icon_log_dom = eina_log_domain_register + ("efreet_icon", EFREET_DEFAULT_LOG_COLOR); + if (_efreet_icon_log_dom < 0) { + ecore_shutdown(); return 0; } @@ -129,8 +150,8 @@ efreet_icon_init(void) void efreet_icon_shutdown(void) { - IF_FREE(efreet_icon_user_dir); - IF_FREE(efreet_icon_deprecated_user_dir); + IF_RELEASE(efreet_icon_user_dir); + IF_RELEASE(efreet_icon_deprecated_user_dir); IF_FREE_LIST(efreet_icon_extensions, eina_stringshare_del); IF_FREE_HASH(efreet_icon_themes); @@ -138,6 +159,8 @@ efreet_icon_shutdown(void) IF_FREE_HASH(efreet_icon_cache); + eina_log_domain_unregister(_efreet_icon_log_dom); + ecore_shutdown(); } @@ -149,15 +172,17 @@ EAPI const char * efreet_icon_deprecated_user_dir_get(void) { const char *user; + char *tmp; int len; if (efreet_icon_deprecated_user_dir) return efreet_icon_deprecated_user_dir; user = efreet_home_dir_get(); len = strlen(user) + strlen("/.icons") + 1; - efreet_icon_deprecated_user_dir = malloc(len); - if (!efreet_icon_deprecated_user_dir) return NULL; - snprintf(efreet_icon_deprecated_user_dir, len, "%s/.icons", user); + tmp = alloca(len); + snprintf(tmp, len, "%s/.icons", user); + + efreet_icon_deprecated_user_dir = eina_stringshare_add_length(tmp, len - 1); return efreet_icon_deprecated_user_dir; } @@ -166,15 +191,17 @@ EAPI const char * efreet_icon_user_dir_get(void) { const char *user; + char *tmp; int len; if (efreet_icon_user_dir) return efreet_icon_user_dir; user = efreet_data_home_get(); len = strlen(user) + strlen("/icons") + 1; - efreet_icon_user_dir = malloc(len); - if (!efreet_icon_user_dir) return NULL; - snprintf(efreet_icon_user_dir, len, "%s/icons", user); + tmp = alloca(len); + snprintf(tmp, len, "%s/icons", user); + + efreet_icon_user_dir = eina_stringshare_add_length(tmp, len - 1); return efreet_icon_user_dir; } @@ -355,6 +382,9 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz { const char *value = NULL; Efreet_Icon_Theme *theme; +#ifdef ICON_CACHE + Efreet_Cache_Icon *cache; +#endif theme = efreet_icon_find_theme_check(theme_name); @@ -366,18 +396,35 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz tmp = efreet_icon_remove_extension(icon); if (!tmp) return NULL; +#ifdef ICON_CACHE + cache = efreet_cache_icon_find(theme, tmp); + value = efreet_cache_icon_lookup_icon(cache, size); + efreet_cache_icon_free(cache); +#else value = efreet_icon_find_helper(theme, tmp, size); +#endif FREE(tmp); } +#else +#ifdef ICON_CACHE + cache = efreet_cache_icon_find(theme, icon); + value = efreet_cache_icon_lookup_icon(cache, size); + efreet_cache_icon_free(cache); #else value = efreet_icon_find_helper(theme, icon, size); +#endif #endif } /* we didn't find the icon in the theme or in the inherited directories * then just look for a non theme icon */ - if (!value || (value == NON_EXISTING)) value = efreet_icon_fallback_icon(icon); + if (!value || (value == NON_EXISTING)) +#if 0//def ICON_CACHE + value = efreet_cache_icon_fallback_icon(icon); +#else + value = efreet_icon_fallback_icon(icon); +#endif if (value == NON_EXISTING) value = NULL; return value; @@ -1638,3 +1685,142 @@ efreet_icon_cache_add(Efreet_Icon_Theme *theme, const char *icon, unsigned int s eina_hash_set(efreet_icon_cache, key, cache); } + +#ifdef ICON_CACHE +static const char * +efreet_cache_icon_lookup_icon(Efreet_Cache_Icon *icon, unsigned int size) +{ + Eina_List *l; + Efreet_Cache_Icon_Element *elem; + const char *path = NULL; + const char *tmp = NULL; + double minimal_distance = INT_MAX; + unsigned int ret_size = 0; + + if (!icon) return NULL; + + /* search for allowed size == requested size */ + EINA_LIST_FOREACH(icon->icons, l, elem) + { + if (!efreet_cache_icon_size_match(elem, size)) continue; + path = efreet_cache_icon_lookup_path(elem); + if (path) return path; + } + + /* search for any icon that matches */ + EINA_LIST_FOREACH(icon->icons, l, elem) + { + double distance; + + distance = efreet_cache_icon_size_distance(elem, size); + if (distance > minimal_distance) continue; + // prefer downsizing + if ((distance == minimal_distance) && (size < ret_size)) continue; + + tmp = efreet_cache_icon_lookup_path(elem); + if (tmp) + { + path = tmp; + minimal_distance = distance; + ret_size = size; + } + } + + return path; +} + +static int +efreet_cache_icon_size_match(Efreet_Cache_Icon_Element *elem, unsigned int size) +{ + if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED) + return (elem->size.normal == size); + + if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) || + (elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD)) + return ((elem->size.min < size) && (size < elem->size.max)); + + return 0; +} + +static double +efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size) +{ + if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED) + return (abs(elem->size.normal - size)); + + if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) || + (elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD)) + { +#ifdef STRICT_SPEC + if (size < elem->size.min) + return (elem->size.min - size); + if (elem->size.max < size) + return (size - elem->size.max); +#else + if (size < elem->size.min) + return (elem->size.min / (double)size); + if (elem->size.max < size) + return (size / (double)elem->size.max); +#endif + return 0; + } + + return 0; +} + +static const char * +efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem) +{ + const char *path; + Eina_List *xdg_dirs, *l; + const char *dir; + char buf[PATH_MAX]; + + + path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_deprecated_user_dir_get()); + if (path) return path; + path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_user_dir_get()); + if (path) return path; +#if 0 + EINA_LIST_FOREACH(efreet_extra_icon_dirs, l, dir) + { + path = efreet_cache_icon_lookup_path_path(elem, dir); + if (path) return path; + } +#endif + + xdg_dirs = efreet_data_dirs_get(); + + EINA_LIST_FOREACH(xdg_dirs, l, dir) + { + snprintf(buf, sizeof(buf), "%s/icons", dir); + path = efreet_cache_icon_lookup_path_path(elem, buf); + if (path) return path; + } + + return NULL; +} + +static const char * +efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path) +{ + Eina_List *l, *ll; + const char *ext, *p, *pp; + int len; + + len = strlen(path); + + EINA_LIST_FOREACH(elem->paths, l, p) + { + + if (strncmp(path, p, len)) continue; + pp = strrchr(p, '.'); + if (!pp) continue; + + EINA_LIST_FOREACH(efreet_icon_extensions, ll, ext) + if (!strcmp(pp, ext)) + return p; + } + return NULL; +} +#endif diff --git a/legacy/efreet/src/lib/efreet_private.h b/legacy/efreet/src/lib/efreet_private.h index ebe6256325..64a2428bdc 100644 --- a/legacy/efreet/src/lib/efreet_private.h +++ b/legacy/efreet/src/lib/efreet_private.h @@ -93,7 +93,7 @@ extern int _efreet_log_dom_global; #endif #define EFREET_DEFAULT_LOG_COLOR "\033[36m" -#define EFREET_MODULE_LOG_DOM _efreet_log_dom_global; /*default log domain for each module. It can redefined inside each module */ +#define EFREET_MODULE_LOG_DOM _efreet_log_dom_global /*default log domain for each module. It can redefined inside each module */ #ifdef ERROR #undef ERROR #endif @@ -116,7 +116,7 @@ extern int _efreet_log_dom_global; * four macros are defined ERR, WRN, DGB, INF. * EFREET_MODULE_LOG_DOM should be defined individually for each module */ -#define EFREET_MODULE_LOG_DOM _efreet_log_dom_global; /*default log domain for each module. It can redefined inside each module */ +#define EFREET_MODULE_LOG_DOM _efreet_log_dom_global /*default log domain for each module. It can redefined inside each module */ #ifdef ERR #undef ERR #endif @@ -213,6 +213,7 @@ EAPI const char *efreet_icon_cache_file(const char *theme); EAPI Eet_Data_Descriptor *efreet_icon_edd_init(void); EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd_init(void); EAPI void efreet_cache_icon_free(Efreet_Cache_Icon *icon); +Efreet_Cache_Icon *efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon); #endif #define NON_EXISTING (void *)-1