[gtk: 1/5] icon-cache: Add new function to list all the icons in a directory



commit 0a8d7603ea7448d80e5d1c39bdeb050d7ca926d8
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Feb 3 10:00:17 2020 +0100

    icon-cache: Add new function to list all the icons in a directory
    
    This lists the icons in a particular director, with their flags in a
    hashtable. We also convert from "icon.symbolic" + SUFFIX_PNG to
    "icon" + SUFFIX_SYMBOLIC_PNG.

 gtk/gtkiconcache.c        | 84 +++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkiconcacheprivate.h |  2 ++
 gtk/gtkicontheme.c        |  1 +
 3 files changed, 87 insertions(+)
---
diff --git a/gtk/gtkiconcache.c b/gtk/gtkiconcache.c
index bcbfe83071..bc238e0028 100644
--- a/gtk/gtkiconcache.c
+++ b/gtk/gtkiconcache.c
@@ -43,6 +43,18 @@
 #define GET_UINT16(cache, offset) (GUINT16_FROM_BE (*(guint16 *)((cache) + (offset))))
 #define GET_UINT32(cache, offset) (GUINT32_FROM_BE (*(guint32 *)((cache) + (offset))))
 
+/* Keep in sync with gtkicontheme.c */
+typedef enum
+{
+  /* These are used in the file format: */
+  ICON_SUFFIX_NONE = 0,
+  ICON_SUFFIX_XPM = 1 << 0,
+  ICON_SUFFIX_SVG = 1 << 1,
+  ICON_SUFFIX_PNG = 1 << 2,
+  HAS_ICON_FILE = 1 << 3,
+  /* This is just used by Gtk, so we convert internally to this: */
+  ICON_SUFFIX_SYMBOLIC_PNG = 1 << 4
+} IconSuffix;
 
 struct _GtkIconCache {
   gint ref_count;
@@ -334,6 +346,78 @@ gtk_icon_cache_has_icons (GtkIconCache *cache,
   return FALSE;
 }
 
+GHashTable *
+gtk_icon_cache_list_icons_in_directory (GtkIconCache *cache,
+                                        const gchar  *directory)
+{
+  gint directory_index;
+  guint32 hash_offset, n_buckets;
+  guint32 chain_offset;
+  guint32 image_list_offset, n_images;
+  int i, j;
+  GHashTable *icons = NULL;
+
+  directory_index = get_directory_index (cache, directory);
+
+  if (directory_index == -1)
+    return NULL;
+
+  hash_offset = GET_UINT32 (cache->buffer, 4);
+  n_buckets = GET_UINT32 (cache->buffer, hash_offset);
+
+  for (i = 0; i < n_buckets; i++)
+    {
+      chain_offset = GET_UINT32 (cache->buffer, hash_offset + 4 + 4 * i);
+      while (chain_offset != 0xffffffff)
+        {
+          guint32 flags = 0;
+
+          image_list_offset = GET_UINT32 (cache->buffer, chain_offset + 8);
+          n_images = GET_UINT32 (cache->buffer, image_list_offset);
+
+          for (j = 0; j < n_images; j++)
+            {
+              if (GET_UINT16 (cache->buffer, image_list_offset + 4 + 8 * j) ==
+                  directory_index)
+                {
+                  flags = GET_UINT16 (cache->buffer, image_list_offset + 4 + 8 * j + 2);
+                  break;
+                }
+            }
+
+          if (flags != 0)
+            {
+              guint32 name_offset = GET_UINT32 (cache->buffer, chain_offset + 4);
+              const char *name = cache->buffer + name_offset;
+              char *converted_name;
+              guint32 hash_flags = 0;
+
+              /* Icons named foo.symbolic.png are stored in the cache as "foo.symbolic" with ICON_SUFFIX_PNG,
+               * but we convert it internally to ICON_SUFFIX_SYMBOLIC_PNG.
+               * Otherwise we use the same enum values and names as on disk. */
+              if (g_str_has_suffix (name, ".symbolic") && (flags & ICON_SUFFIX_PNG) != 0)
+                {
+                  flags |= ICON_SUFFIX_SYMBOLIC_PNG;
+                  flags &= ~ICON_SUFFIX_PNG;
+                  converted_name = g_strndup (name, strlen(name) - 9);
+                }
+              else
+                converted_name = g_strdup (name);
+
+              if (!icons)
+                icons = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+              hash_flags = GPOINTER_TO_INT (g_hash_table_lookup (icons, converted_name));
+              g_hash_table_replace (icons, converted_name, GUINT_TO_POINTER (hash_flags|flags));
+            }
+
+          chain_offset = GET_UINT32 (cache->buffer, chain_offset);
+        }
+    }
+
+  return icons;
+}
+
 void
 gtk_icon_cache_add_icons (GtkIconCache *cache,
                           const gchar  *directory,
diff --git a/gtk/gtkiconcacheprivate.h b/gtk/gtkiconcacheprivate.h
index 08e581fe9a..2f73891e6b 100644
--- a/gtk/gtkiconcacheprivate.h
+++ b/gtk/gtkiconcacheprivate.h
@@ -32,6 +32,8 @@ gboolean      gtk_icon_cache_has_icon                   (GtkIconCache *cache,
 gboolean      gtk_icon_cache_has_icon_in_directory      (GtkIconCache *cache,
                                                          const gchar  *icon_name,
                                                          const gchar  *directory);
+GHashTable   *gtk_icon_cache_list_icons_in_directory    (GtkIconCache *cache,
+                                                         const gchar  *directory);
 gboolean      gtk_icon_cache_has_icons                  (GtkIconCache *cache,
                                                          const gchar  *directory);
 void         gtk_icon_cache_add_icons                  (GtkIconCache *cache,
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index d437094063..ae33375bce 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -167,6 +167,7 @@ typedef enum
 } IconThemeDirType;
 
 /* In reverse search order: */
+/* Keep in sync with gtkiconcache.c */
 typedef enum
 {
   ICON_SUFFIX_NONE = 0,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]