#define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
#define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
+
struct _GtkIconCache {
gint ref_count;
GMappedFile *map;
gchar *buffer;
+
+ guint32 last_chain_offset;
};
GtkIconCache *
return -1;
}
-gboolean
-_gtk_icon_cache_has_directory (GtkIconCache *cache,
- const gchar *directory)
+gint
+_gtk_icon_cache_get_directory_index (GtkIconCache *cache,
+ const gchar *directory)
{
- return get_directory_index (cache, directory) != -1;
+ return get_directory_index (cache, directory);
}
static guint
static gint
find_image_offset (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory)
+ gint directory_index)
{
guint32 hash_offset;
guint32 n_buckets;
guint32 chain_offset;
- int hash, directory_index;
+ int hash;
guint32 image_list_offset, n_images;
gboolean found = FALSE;
int i;
-
+
+ chain_offset = cache->last_chain_offset;
+ if (chain_offset)
+ {
+ guint32 name_offset = GET_UINT32 (cache->buffer, chain_offset + 4);
+ gchar *name = cache->buffer + name_offset;
+
+ if (strcmp (name, icon_name) == 0)
+ goto find_dir;
+ }
+
hash_offset = GET_UINT32 (cache->buffer, 4);
n_buckets = GET_UINT32 (cache->buffer, hash_offset);
-
hash = icon_name_hash (icon_name) % n_buckets;
chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * hash);
gchar *name = cache->buffer + name_offset;
if (strcmp (name, icon_name) == 0)
- {
- found = TRUE;
- break;
+ {
+ cache->last_chain_offset = chain_offset;
+ goto find_dir;
}
-
+
chain_offset = GET_UINT32 (cache->buffer, chain_offset);
}
- if (!found) {
- return 0;
- }
+ cache->last_chain_offset = 0;
+ return 0;
+find_dir:
/* We've found an icon list, now check if we have the right icon in it */
- directory_index = get_directory_index (cache, directory);
image_list_offset = GET_UINT32 (cache->buffer, chain_offset + 8);
n_images = GET_UINT32 (cache->buffer, image_list_offset);
gint
_gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory)
+ gint directory_index)
{
guint32 image_offset;
- image_offset = find_image_offset (cache, icon_name, directory);
+ image_offset = find_image_offset (cache, icon_name, directory_index);
if (!image_offset)
return 0;
GdkPixbuf *
_gtk_icon_cache_get_icon (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory)
+ gint directory_index)
{
guint32 offset, image_data_offset, pixel_data_offset;
guint32 length, type;
GdkPixdata pixdata;
GError *error = NULL;
- offset = find_image_offset (cache, icon_name, directory);
+ offset = find_image_offset (cache, icon_name, directory_index);
image_data_offset = GET_UINT32 (cache->buffer, offset + 4);
GtkIconData *
_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory)
+ gint directory_index)
{
guint32 offset, image_data_offset, meta_data_offset;
GtkIconData *data;
int i;
- offset = find_image_offset (cache, icon_name, directory);
+ offset = find_image_offset (cache, icon_name, directory_index);
if (!offset)
return NULL;
char *dir;
char *subdir;
+ int subdir_index;
GtkIconCache *cache;
IconThemeDir *dir;
static IconThemeDir dirs[5] =
{
- { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", NULL, NULL, NULL },
- { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", NULL, NULL, NULL }
+ { ICON_THEME_DIR_THRESHOLD, 0, 16, 16, 16, 2, NULL, "16", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 20, 20, 20, 2, NULL, "20", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 24, 24, 24, 2, NULL, "24", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 32, 32, 32, 2, NULL, "32", -1, NULL, NULL, NULL },
+ { ICON_THEME_DIR_THRESHOLD, 0, 48, 48, 48, 2, NULL, "48", -1, NULL, NULL, NULL }
};
gint i;
{
dir = &(dirs[i]);
dir->cache = _gtk_icon_cache_ref (_builtin_cache);
+ dir->subdir_index = _gtk_icon_cache_get_directory_index (dir->cache, dir->subdir);
builtin_dirs = g_list_append (builtin_dirs, dir);
}
{
IconThemeDir *dir = d->data;
+ if (dir->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir->size), NULL, NULL))
+ continue;
+
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
if (suffix != ICON_SUFFIX_NONE)
{
{
IconThemeDir *dir = d->data;
+ if (dir->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir->size), NULL, NULL))
+ continue;
+
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
if (suffix != ICON_SUFFIX_NONE)
{
{
suffix = (IconSuffix)_gtk_icon_cache_get_icon_flags (dir->cache,
icon_name,
- dir->subdir);
+ dir->subdir_index);
if (has_icon_file)
*has_icon_file = suffix & HAS_ICON_FILE;
/* Builtin icons are logically part of the default theme and
* are searched before other subdirectories of the default theme.
*/
- if (strcmp (theme->name, DEFAULT_THEME_NAME) == 0 && use_builtin)
+ if (use_builtin && strcmp (theme->name, DEFAULT_THEME_NAME) == 0)
{
closest_builtin = find_builtin_icon (icon_name,
size,
{
dir = l->data;
- GTK_NOTE (ICONTHEME,
+ GTK_NOTE (ICONTHEME,
g_print ("theme_lookup_icon dir %s\n", dir->dir));
suffix = theme_dir_get_icon_suffix (dir, icon_name, NULL);
if (best_suffix (suffix, allow_svg) != ICON_SUFFIX_NONE)
if (icon_info->data == NULL && min_dir->cache != NULL)
{
- icon_info->data = _gtk_icon_cache_get_icon_data (min_dir->cache, icon_name, min_dir->subdir);
+ icon_info->data = _gtk_icon_cache_get_icon_data (min_dir->cache, icon_name, min_dir->subdir_index);
if (icon_info->data)
{
if (min_dir->icon_data == NULL)
if (min_dir->cache)
{
icon_info->cache_pixbuf = _gtk_icon_cache_get_icon (min_dir->cache, icon_name,
- min_dir->subdir);
+ min_dir->subdir_index);
}
icon_info->dir_type = min_dir->type;
dir->icon_data = NULL;
dir->subdir = g_strdup (subdir);
if (dir_mtime->cache != NULL)
- dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
+ {
+ dir->cache = _gtk_icon_cache_ref (dir_mtime->cache);
+ dir->subdir_index = _gtk_icon_cache_get_directory_index (dir->cache, dir->subdir);
+ }
else
{
dir->cache = NULL;
+ dir->subdir_index = -1;
scan_directory (icon_theme->priv, dir, full_dir);
}