summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2007-12-03 17:44:27 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2007-12-03 17:44:27 +0000
commitf9e4618bdae4adce0e675f54dd6ebf9a48be76e4 (patch)
tree6b88d124474785093218846f3c6ec49df950c7fa
parentf83588f87e9ae756016073e80f3cfc6187d8a816 (diff)
downloadgdk-pixbuf-f9e4618bdae4adce0e675f54dd6ebf9a48be76e4.tar.gz
Two optimizations for icon cache lookups.
2007-12-03 Matthias Clasen <mclasen@redhat.com> Two optimizations for icon cache lookups. * gtk/gtkiconcache.[hc]: * gtk/gtkicontheme.c: Remember the directory index for subdirectories, instead of running over the directory list again and again. * gtk/gtkiconcache.c (find_image_offset): Remember the last chain and try it first; this helps with the the usage patterns in gtkicontheme.c, where the same icon is queried for a lot of subdirectories. svn path=/trunk/; revision=19099
-rw-r--r--ChangeLog14
-rw-r--r--gtk/gtkiconcache.c55
-rw-r--r--gtk/gtkiconcache.h10
-rw-r--r--gtk/gtkicontheme.c34
4 files changed, 75 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 51782e2a7..fb810c016 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-12-03 Matthias Clasen <mclasen@redhat.com>
+
+ Two optimizations for icon cache lookups.
+
+ * gtk/gtkiconcache.[hc]:
+ * gtk/gtkicontheme.c: Remember the directory index for
+ subdirectories, instead of running over the directory list
+ again and again.
+
+ * gtk/gtkiconcache.c (find_image_offset): Remember the last
+ chain and try it first; this helps with the the usage patterns
+ in gtkicontheme.c, where the same icon is queried for a lot
+ of subdirectories.
+
2007-12-03 15:18:17 Tim Janik <timj@imendio.com>
* gtk/Makefile.am (gtktypefuncs.c): use 'grep -o' to extract _get_type
diff --git a/gtk/gtkiconcache.c b/gtk/gtkiconcache.c
index 021b64c89..c8a90e20a 100644
--- a/gtk/gtkiconcache.c
+++ b/gtk/gtkiconcache.c
@@ -49,11 +49,14 @@
#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 *
@@ -191,11 +194,11 @@ get_directory_index (GtkIconCache *cache,
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
@@ -214,19 +217,28 @@ icon_name_hash (gconstpointer key)
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);
@@ -236,20 +248,19 @@ find_image_offset (GtkIconCache *cache,
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);
@@ -266,11 +277,11 @@ find_image_offset (GtkIconCache *cache,
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;
@@ -417,7 +428,7 @@ pixbuf_destroy_cb (guchar *pixels,
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;
@@ -425,7 +436,7 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
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);
@@ -478,13 +489,13 @@ _gtk_icon_cache_get_icon (GtkIconCache *cache,
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;
diff --git a/gtk/gtkiconcache.h b/gtk/gtkiconcache.h
index c404d16d7..1b09cb686 100644
--- a/gtk/gtkiconcache.h
+++ b/gtk/gtkiconcache.h
@@ -38,8 +38,8 @@ struct _GtkIconData
GtkIconCache *_gtk_icon_cache_new (const gchar *data);
GtkIconCache *_gtk_icon_cache_new_for_path (const gchar *path);
-gboolean _gtk_icon_cache_has_directory (GtkIconCache *cache,
- const gchar *directory);
+gint _gtk_icon_cache_get_directory_index (GtkIconCache *cache,
+ const gchar *directory);
gboolean _gtk_icon_cache_has_icon (GtkIconCache *cache,
const gchar *icon_name);
gboolean _gtk_icon_cache_has_icon_in_directory (GtkIconCache *cache,
@@ -51,13 +51,13 @@ void _gtk_icon_cache_add_icons (GtkIconCache *cache,
gint _gtk_icon_cache_get_icon_flags (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory);
+ gint directory_index);
GdkPixbuf *_gtk_icon_cache_get_icon (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory);
+ gint directory_index);
GtkIconData *_gtk_icon_cache_get_icon_data (GtkIconCache *cache,
const gchar *icon_name,
- const gchar *directory);
+ gint directory_index);
GtkIconCache *_gtk_icon_cache_ref (GtkIconCache *cache);
void _gtk_icon_cache_unref (GtkIconCache *cache);
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index 3121d86c9..5175f20ce 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -161,6 +161,7 @@ typedef struct
char *dir;
char *subdir;
+ int subdir_index;
GtkIconCache *cache;
@@ -1149,11 +1150,11 @@ _gtk_icon_theme_ensure_builtin_cache (void)
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;
@@ -1167,6 +1168,7 @@ _gtk_icon_theme_ensure_builtin_cache (void)
{
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);
}
@@ -1612,6 +1614,9 @@ gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme,
{
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)
{
@@ -1627,6 +1632,9 @@ gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme,
{
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)
{
@@ -2019,7 +2027,7 @@ theme_dir_get_icon_suffix (IconThemeDir *dir,
{
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;
@@ -2058,7 +2066,7 @@ theme_lookup_icon (IconTheme *theme,
/* 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,
@@ -2078,7 +2086,7 @@ theme_lookup_icon (IconTheme *theme,
{
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)
@@ -2178,7 +2186,7 @@ theme_lookup_icon (IconTheme *theme,
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)
@@ -2212,7 +2220,7 @@ theme_lookup_icon (IconTheme *theme,
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;
@@ -2520,10 +2528,14 @@ theme_subdir_load (GtkIconTheme *icon_theme,
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);
}