[gnome-shell] [ShellTextureCache] add methods for caching raw image data
- From: Dan Winship <danw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell] [ShellTextureCache] add methods for caching raw image data
- Date: Wed, 13 Jan 2010 20:13:44 +0000 (UTC)
commit c90371d9d5cae3c7b7d060bfa8e17bd15ffaccac
Author: Dan Winship <danw gnome org>
Date: Wed Jan 13 15:04:10 2010 -0500
[ShellTextureCache] add methods for caching raw image data
shell_texture_cache_load_from_data() takes the contents of an image
file, while shell_texture_cache_load_from_raw() takes the actual pixel
data.
src/shell-texture-cache.c | 184 +++++++++++++++++++++++++++++++++++++++------
src/shell-texture-cache.h | 15 ++++
2 files changed, 175 insertions(+), 24 deletions(-)
---
diff --git a/src/shell-texture-cache.c b/src/shell-texture-cache.c
index 90402ee..9b022ba 100644
--- a/src/shell-texture-cache.c
+++ b/src/shell-texture-cache.c
@@ -8,6 +8,7 @@
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnomeui/gnome-desktop-thumbnail.h>
#include <string.h>
+#include <glib.h>
typedef struct
{
@@ -17,6 +18,7 @@ typedef struct
GIcon *icon;
gchar *uri;
gchar *thumbnail_uri;
+ gchar *checksum;
/* This one is common to all */
guint size;
@@ -51,6 +53,8 @@ cache_key_hash (gconstpointer a)
base_hash = g_str_hash (akey->uri);
else if (akey->thumbnail_uri)
base_hash = g_str_hash (akey->thumbnail_uri);
+ else if (akey->checksum)
+ base_hash = g_str_hash (akey->checksum);
else
g_assert_not_reached ();
return base_hash + 31*akey->size;
@@ -76,6 +80,8 @@ cache_key_equal (gconstpointer a,
return strcmp (akey->uri, bkey->uri) == 0;
else if (akey->thumbnail_uri && bkey->thumbnail_uri)
return strcmp (akey->thumbnail_uri, bkey->thumbnail_uri) == 0;
+ else if (akey->checksum && bkey->checksum)
+ return strcmp (akey->checksum, bkey->checksum) == 0;
return FALSE;
}
@@ -89,6 +95,7 @@ cache_key_dup (CacheKey *key)
ret->icon = g_object_ref (key->icon);
ret->uri = g_strdup (key->uri);
ret->thumbnail_uri = g_strdup (key->thumbnail_uri);
+ ret->checksum = g_strdup (key->checksum);
ret->size = key->size;
return ret;
}
@@ -101,6 +108,7 @@ cache_key_destroy (gpointer a)
g_object_unref (akey->icon);
g_free (akey->uri);
g_free (akey->thumbnail_uri);
+ g_free (akey->checksum);
g_free (akey);
}
@@ -318,7 +326,8 @@ on_image_size_prepared (GdkPixbufLoader *pixbuf_loader,
}
static GdkPixbuf *
-impl_load_pixbuf_file (const char *uri,
+impl_load_pixbuf_data (const guchar *data,
+ gsize size,
int available_width,
int available_height,
GError **error)
@@ -326,22 +335,10 @@ impl_load_pixbuf_file (const char *uri,
GdkPixbufLoader *pixbuf_loader = NULL;
GdkPixbuf *rotated_pixbuf = NULL;
GdkPixbuf *pixbuf;
- GFile *file = NULL;
- char *contents = NULL;
- gsize size;
gboolean success;
Dimensions available_dimensions;
int width_before_rotation, width_after_rotation;
- file = g_file_new_for_uri (uri);
-
- success = g_file_load_contents (file, NULL, &contents, &size, NULL, error);
-
- if (!success)
- {
- goto out;
- }
-
pixbuf_loader = gdk_pixbuf_loader_new ();
available_dimensions.width = available_width;
@@ -349,10 +346,7 @@ impl_load_pixbuf_file (const char *uri,
g_signal_connect (pixbuf_loader, "size-prepared",
G_CALLBACK (on_image_size_prepared), &available_dimensions);
- success = gdk_pixbuf_loader_write (pixbuf_loader,
- (const guchar *) contents,
- size,
- error);
+ success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
if (!success)
goto out;
success = gdk_pixbuf_loader_close (pixbuf_loader, error);
@@ -384,10 +378,7 @@ impl_load_pixbuf_file (const char *uri,
g_signal_connect (pixbuf_loader, "size-prepared",
G_CALLBACK (on_image_size_prepared), &available_dimensions);
- success = gdk_pixbuf_loader_write (pixbuf_loader,
- (const guchar *) contents,
- size,
- error);
+ success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
if (!success)
goto out;
@@ -401,15 +392,37 @@ impl_load_pixbuf_file (const char *uri,
}
out:
- g_free (contents);
- if (file)
- g_object_unref (file);
if (pixbuf_loader)
g_object_unref (pixbuf_loader);
return rotated_pixbuf;
}
static GdkPixbuf *
+impl_load_pixbuf_file (const char *uri,
+ int available_width,
+ int available_height,
+ GError **error)
+{
+ GdkPixbuf *pixbuf = NULL;
+ GFile *file;
+ char *contents = NULL;
+ gsize size;
+
+ file = g_file_new_for_uri (uri);
+ if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
+ {
+ pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
+ available_width, available_height,
+ error);
+ }
+
+ g_object_unref (file);
+ g_free (contents);
+
+ return pixbuf;
+}
+
+static GdkPixbuf *
impl_load_thumbnail (ShellTextureCache *cache,
const char *uri,
const char *mime_type,
@@ -655,6 +668,7 @@ typedef struct {
gboolean thumbnail;
char *mimetype;
GtkRecentInfo *recent_info;
+ char *checksum;
GIcon *icon;
GtkIconInfo *icon_info;
guint width;
@@ -1138,6 +1152,128 @@ shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
}
/**
+ * shell_texture_cache_load_from_data:
+ * @cache: The texture cache instance
+ * @data: Image data in PNG, GIF, etc format
+ * @len: length of @data
+ * @size: Size in pixels to use for the resulting texture
+ * @error: Return location for error
+ *
+ * Synchronously creates an image from @data. The image is scaled down
+ * to fit the available width and height dimensions, but the image is
+ * never scaled up beyond its actual size. The pixbuf is rotated
+ * according to the associated orientation setting.
+ *
+ * Return value: (transfer none): A new #ClutterActor with the image data loaded if it was
+ * generated succesfully, %NULL otherwise
+ */
+ClutterActor *
+shell_texture_cache_load_from_data (ShellTextureCache *cache,
+ const guchar *data,
+ gsize len,
+ int size,
+ GError **error)
+{
+ ClutterTexture *texture;
+ CoglHandle texdata;
+ GdkPixbuf *pixbuf;
+ CacheKey key;
+ gchar *checksum;
+
+ texture = create_default_texture (cache);
+ clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
+
+ checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
+
+ memset (&key, 0, sizeof(key));
+ key.size = size;
+ key.checksum = checksum;
+
+ texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
+ if (texdata == NULL)
+ {
+ pixbuf = impl_load_pixbuf_data (data, len, size, size, error);
+ if (!pixbuf)
+ {
+ g_object_unref (texture);
+ return NULL;
+ }
+
+ texdata = pixbuf_to_cogl_handle (pixbuf);
+ g_object_unref (pixbuf);
+
+ set_texture_cogl_texture (texture, texdata);
+
+ g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
+ }
+
+ g_free (key.checksum);
+
+ set_texture_cogl_texture (texture, texdata);
+ return CLUTTER_ACTOR (texture);
+}
+
+/**
+ * shell_texture_cache_load_from_raw:
+ * @cache: a #ShellTextureCache
+ * @data: raw pixel data
+ * @len: the length of @data
+ * @has_alpha: whether @data includes an alpha channel
+ * @width: width in pixels of @data
+ * @height: width in pixels of @data
+ * @rowstride: rowstride of @data
+ * @size: size of icon to return
+ *
+ * Creates (or retrieves from cache) an icon based on raw pixel data.
+ *
+ * Return value: (transfer none): a new #ClutterActor displaying a
+ * pixbuf created from @data and the other parameters.
+ **/
+ClutterActor *
+shell_texture_cache_load_from_raw (ShellTextureCache *cache,
+ const guchar *data,
+ gsize len,
+ gboolean has_alpha,
+ int width,
+ int height,
+ int rowstride,
+ int size,
+ GError **error)
+{
+ ClutterTexture *texture;
+ CoglHandle texdata;
+ CacheKey key;
+ gchar *checksum;
+
+ texture = create_default_texture (cache);
+ clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
+
+ /* In theory, two images of different size could have the same
+ * pixel data. We ignore that theory.
+ */
+ checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
+
+ memset (&key, 0, sizeof(key));
+ key.size = size;
+ key.checksum = checksum;
+
+ texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
+ if (texdata == NULL)
+ {
+ texdata = cogl_texture_new_from_data (width, height, COGL_TEXTURE_NONE,
+ has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_ANY,
+ rowstride, data);
+ g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
+ }
+
+ g_free (key.checksum);
+
+ set_texture_cogl_texture (texture, texdata);
+ return CLUTTER_ACTOR (texture);
+}
+
+/**
* shell_texture_cache_load_thumbnail:
* @cache:
* @size: Size in pixels to use for thumbnail
diff --git a/src/shell-texture-cache.h b/src/shell-texture-cache.h
index 21dc7d7..d7280c4 100644
--- a/src/shell-texture-cache.h
+++ b/src/shell-texture-cache.h
@@ -80,6 +80,21 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
int available_height,
GError **error);
+ClutterActor *shell_texture_cache_load_from_data (ShellTextureCache *cache,
+ const guchar *data,
+ gsize len,
+ int size,
+ GError **error);
+ClutterActor *shell_texture_cache_load_from_raw (ShellTextureCache *cache,
+ const guchar *data,
+ gsize len,
+ gboolean has_alpha,
+ int width,
+ int height,
+ int rowstride,
+ int size,
+ GError **error);
+
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
#endif /* __SHELL_TEXTURE_CACHE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]