[gnome-photos] base-item: Implement check_effects_and_update_info



commit fbcd774fb6d27ebfdc9d64d4ca5029cdcedcc1be
Author: Debarshi Ray <debarshir gnome org>
Date:   Sun Jul 15 18:34:02 2012 +0200

    base-item: Implement check_effects_and_update_info
    
    Added cairo to the list of build requirements.

 configure.ac             |    1 +
 data/Makefile.am         |    6 ++
 data/thumbnail-frame.png |  Bin 0 -> 832 bytes
 src/Makefile.am          |    3 +
 src/photos-base-item.c   |  101 ++++++++++++++++++++++++++++
 src/photos-utils.c       |  162 ++++++++++++++++++++++++++++++++++++++++++++++
 src/photos-utils.h       |   10 +++
 7 files changed, 283 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a8a4aaf..72b7c14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -41,6 +41,7 @@ AM_GLIB_GNU_GETTEXT
 
 LT_INIT
 
+PKG_CHECK_MODULES(CAIRO, [cairo])
 PKG_CHECK_MODULES(CLUTTER, [clutter-1.0])
 PKG_CHECK_MODULES(CLUTTER_GTK, [clutter-gtk-1.0])
 PKG_CHECK_MODULES(GDK_PIXBUF, [gdk-pixbuf-2.0])
diff --git a/data/Makefile.am b/data/Makefile.am
index 4a77272..40a41ff 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -8,6 +8,12 @@ desktop_DATA = $(desktop_in_files:.desktop.in.in=.desktop)
 gsettings_in_files = org.gnome.photos.gschema.xml.in
 gsettings_SCHEMAS = $(gsettings_in_files:.xml.in=.xml)
 .PRECIOUS: $(gsettings_SCHEMAS)
+
+iconsdir = $(pkgdatadir)/icons
+dist_icons_DATA = \
+	thumbnail-frame.png \
+	$(NULL)
+
 @INTLTOOL_XML_NOMERGE_RULE@
 @GSETTINGS_RULES@
 
diff --git a/data/thumbnail-frame.png b/data/thumbnail-frame.png
new file mode 100644
index 0000000..ba5d721
Binary files /dev/null and b/data/thumbnail-frame.png differ
diff --git a/src/Makefile.am b/src/Makefile.am
index 6dcd2e9..3b57004 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -97,7 +97,9 @@ EXTRA_DIST = \
 	$(null)
 
 AM_CPPFLAGS = \
+	-DPACKAGE_ICONS_DIR=\""${pkgdatadir}/icons"\" \
 	-DPACKAGE_LOCALE_DIR=\""${datadir}/locale"\" \
+	$(CAIRO_CFLAGS) \
 	$(CLUTTER_CFLAGS) \
 	$(CLUTTER_GTK_CFLAGS) \
 	$(GDK_PIXBUF_CFLAGS) \
@@ -112,6 +114,7 @@ AM_CPPFLAGS = \
 gnome_photos_LDFLAGS = 
 
 gnome_photos_LDADD = \
+	$(CAIRO_LIBS) \
 	$(CLUTTER_LIBS) \
 	$(CLUTTER_GTK_LIBS) \
 	$(GDK_PIXBUF_LIBS) \
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index 9da32d7..fe7e3cc 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -33,6 +33,7 @@
 struct _PhotosBaseItemPrivate
 {
   GdkPixbuf *icon;
+  GdkPixbuf *pristine_icon;
   gboolean failed_thumbnailing;
   gboolean favorite;
   gboolean thumbnailed;
@@ -61,9 +62,108 @@ enum
 G_DEFINE_TYPE (PhotosBaseItem, photos_base_item, G_TYPE_OBJECT);
 
 
+static GIcon *
+photos_base_item_create_symbolic_emblem (const gchar *name)
+{
+  GIcon *pix;
+  gint size;
+
+  size = photos_utils_get_icon_size ();
+  pix = photos_utils_create_symbolic_icon (name, size);
+  if (pix == NULL)
+    pix = g_themed_icon_new (name);
+
+  return pix;
+}
+
+
 static void
 photos_base_item_check_effects_and_update_info (PhotosBaseItem *self)
 {
+  PhotosBaseItemPrivate *priv = self->priv;
+  GIcon *pix;
+  GList *emblem_icons = NULL;
+  GdkPixbuf *icon;
+
+  icon = g_object_ref (priv->icon);
+  priv->pristine_icon = g_object_ref (icon);
+
+  if (priv->favorite)
+    {
+      pix = photos_base_item_create_symbolic_emblem ("emblem-favorite");
+      emblem_icons = g_list_prepend (emblem_icons, pix);
+    }
+
+  if (g_list_length (emblem_icons) > 0)
+    {
+      GIcon *emblemed_icon;
+      GList *l;
+      GtkIconInfo *icon_info;
+      GtkIconTheme *theme;
+      gint height;
+      gint size;
+      gint width;
+
+      emblem_icons = g_list_reverse (emblem_icons);
+      emblemed_icon = g_emblemed_icon_new (G_ICON (priv->icon), NULL);
+      for (l = g_list_first (emblem_icons); l != NULL; l = g_list_next (l))
+        {
+          GEmblem *emblem;
+          GIcon *emblem_icon = G_ICON (l->data);
+
+          emblem = g_emblem_new (emblem_icon);
+          g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (emblemed_icon), emblem);
+          g_object_unref (emblem);
+        }
+
+      theme = gtk_icon_theme_get_default ();
+
+      width = gdk_pixbuf_get_width (priv->icon);
+      height = gdk_pixbuf_get_height (priv->icon);
+      size = (width > height) ? width : height;
+
+      icon_info = gtk_icon_theme_lookup_by_gicon (theme, emblemed_icon, size, GTK_ICON_LOOKUP_FORCE_SIZE);
+      g_object_unref (theme);
+
+      if (icon_info != NULL)
+        {
+          GError *error = NULL;
+          GdkPixbuf *tmp;
+
+          tmp = gtk_icon_info_load_icon (icon_info, &error);
+          if (error != NULL)
+            {
+              g_warning ("Unable to render the emblem: %s", error->message);
+              g_error_free (error);
+            }
+          else
+            {
+              g_object_unref (icon);
+              icon = tmp;
+            }
+
+          gtk_icon_info_free (icon_info);
+        }
+    }
+
+  g_object_unref (priv->icon);
+
+  if (priv->thumbnailed)
+    {
+      GtkBorder *slice;
+
+      slice = photos_utils_get_thumbnail_frame_border ();
+      priv->icon = photos_utils_embed_image_in_frame (icon,
+                                                      PACKAGE_ICONS_DIR "/thumbnail-frame.png",
+                                                      slice,
+                                                      slice);
+      gtk_border_free (slice);
+    }
+  else
+    priv->icon = g_object_ref (icon);
+
+  g_object_unref (icon);
+  g_list_free_full (emblem_icons, g_object_unref);
 }
 
 
@@ -351,6 +451,7 @@ photos_base_item_dispose (GObject *object)
   PhotosBaseItemPrivate *priv = self->priv;
 
   g_clear_object (&priv->icon);
+  g_clear_object (&priv->pristine_icon);
 
   G_OBJECT_CLASS (photos_base_item_parent_class)->dispose (object);
 }
diff --git a/src/photos-utils.c b/src/photos-utils.c
index e57ec6f..5a1cb55 100644
--- a/src/photos-utils.c
+++ b/src/photos-utils.c
@@ -26,6 +26,7 @@
 
 #include <string.h>
 
+#include <cairo.h>
 #include <glib.h>
 #include <libgnome-desktop/gnome-desktop-thumbnail.h>
 
@@ -41,6 +42,74 @@ photos_utils_alpha_gtk_widget (GtkWidget *widget)
 }
 
 
+GIcon *
+photos_utils_create_symbolic_icon (const gchar *name, gint base_size)
+{
+  GIcon *icon;
+  GIcon *ret_val = NULL;
+  GdkPixbuf *pixbuf;
+  GtkIconInfo *info;
+  GtkIconTheme *theme;
+  GtkStyleContext *style;
+  GtkWidgetPath *path;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  gchar *symbolic_name;
+  const gint bg_min_size = 20;
+  const gint emblem_min_size = 8;
+  gint bg_size;
+  gint emblem_size;
+  gint total_size;
+
+  total_size = base_size / 2;
+  bg_size = MAX (total_size / 2, bg_min_size);
+  emblem_size = MAX (bg_size - 8, emblem_min_size);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, total_size, total_size);
+  cr = cairo_create (surface);
+
+  style = gtk_style_context_new ();
+
+  path = gtk_widget_path_new ();
+  gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
+  gtk_style_context_set_path (style, path);
+  gtk_widget_path_unref (path);
+
+  gtk_style_context_add_class (style, "documents-icon-bg");
+
+  gtk_render_background (style, cr, (total_size - bg_size) / 2, (total_size - bg_size) / 2, bg_size, bg_size);
+
+  symbolic_name = g_strconcat (name, "-symbolic", NULL);
+  icon = g_themed_icon_new_with_default_fallbacks (symbolic_name);
+  g_free (symbolic_name);
+
+  theme = gtk_icon_theme_get_default();
+  info = gtk_icon_theme_lookup_by_gicon (theme, icon, emblem_size, GTK_ICON_LOOKUP_FORCE_SIZE);
+  g_object_unref (icon);
+
+  if (info == NULL)
+    goto out;
+
+  pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL);
+  gtk_icon_info_free (info);
+
+  if (pixbuf == NULL)
+    goto out;
+
+  gtk_render_icon (style, cr, pixbuf, (total_size - emblem_size) / 2,  (total_size - emblem_size) / 2);
+  g_object_unref (pixbuf);
+
+  ret_val = G_ICON (gdk_pixbuf_get_from_surface (surface, 0, 0, total_size, total_size));
+
+ out:
+  g_object_unref (style);
+  cairo_surface_destroy (surface);
+  cairo_destroy (cr);
+
+  return ret_val;
+}
+
+
 static gboolean
 photos_utils_create_thumbnail (GIOSchedulerJob *job, GCancellable *cancellable, gpointer user_data)
 {
@@ -91,6 +160,84 @@ photos_utils_create_thumbnail (GIOSchedulerJob *job, GCancellable *cancellable,
 }
 
 
+GdkPixbuf *
+photos_utils_embed_image_in_frame (GdkPixbuf *source_image,
+                                   const gchar *frame_image_path,
+                                   GtkBorder *slice_width,
+                                   GtkBorder *border_width)
+{
+  GError *error = NULL;
+  GdkPixbuf *ret_val;
+  GtkCssProvider *provider;
+  GtkStyleContext *context;
+  GtkWidgetPath *path;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  gchar *css_str;
+  int dest_height;
+  int dest_width;
+  int source_height;
+  int source_width;
+
+  source_width = gdk_pixbuf_get_width (source_image);
+  source_height = gdk_pixbuf_get_height (source_image);
+
+  dest_width = source_width +  border_width->left + border_width->right;
+  dest_height = source_height + border_width->top + border_width->bottom;
+
+  css_str = g_strdup_printf (".embedded-image { border-image: url(\"%s\") %d %d %d %d / %dpx %dpx %dpx %dpx }",
+                             frame_image_path,
+                             slice_width->top, slice_width->right, slice_width->bottom, slice_width->left,
+                             border_width->top, border_width->right, border_width->bottom, border_width->left);
+  provider = gtk_css_provider_new ();
+  gtk_css_provider_load_from_data (provider, css_str, -1, &error);
+
+  if (error != NULL)
+    {
+      g_warning ("Unable to create the thumbnail frame image: %s", error->message);
+      g_error_free (error);
+      g_free (css_str);
+
+      return g_object_ref (source_image);
+    }
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, dest_width, dest_height);
+  cr = cairo_create (surface);
+
+  context = gtk_style_context_new ();
+  path = gtk_widget_path_new ();
+  gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
+
+  gtk_style_context_set_path (context, path);
+  gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), 600);
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "embedded-image");
+
+  gtk_render_frame (context, cr,
+                    0, 0,
+                    dest_width, dest_height);
+
+  gtk_style_context_restore (context);
+
+  gtk_render_icon (context, cr,
+                   source_image,
+                   border_width->left, border_width->top);
+
+  ret_val = gdk_pixbuf_get_from_surface (surface, 0, 0, dest_width, dest_height);
+
+  cairo_surface_destroy (surface);
+  cairo_destroy (cr);
+
+  gtk_widget_path_unref (path);
+  g_object_unref (provider);
+  g_object_unref (context);
+  g_free (css_str);
+
+  return ret_val;
+}
+
+
 static gchar *
 photos_utils_filename_get_extension_offset (const gchar *filename)
 {
@@ -144,6 +291,21 @@ photos_utils_get_icon_size (void)
 }
 
 
+GtkBorder *
+photos_utils_get_thumbnail_frame_border (void)
+{
+  GtkBorder *slice;
+
+  slice = gtk_border_new ();
+  slice->top = 3;
+  slice->right = 3;
+  slice->bottom = 6;
+  slice->left = 4;
+
+  return slice;
+}
+
+
 GList *
 photos_utils_get_urns_from_paths (GList *paths, GtkTreeModel *model)
 {
diff --git a/src/photos-utils.h b/src/photos-utils.h
index a13a479..35e021f 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -24,6 +24,7 @@
 #ifndef PHOTOS_UTILS_H
 #define PHOTOS_UTILS_H
 
+#include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gio/gio.h>
 #include <glib.h>
 #include <gtk/gtk.h>
@@ -32,10 +33,19 @@ G_BEGIN_DECLS
 
 void             photos_utils_alpha_gtk_widget            (GtkWidget *widget);
 
+GIcon           *photos_utils_create_symbolic_icon        (const gchar *name, gint base_size);
+
+GdkPixbuf       *photos_utils_embed_image_in_frame        (GdkPixbuf *source_image,
+                                                           const gchar *frame_image_path,
+                                                           GtkBorder *slice_width,
+                                                           GtkBorder *border_width);
+
 gchar           *photos_utils_filename_strip_extension    (const gchar *filename_with_extension);
 
 gint             photos_utils_get_icon_size               (void);
 
+GtkBorder       *photos_utils_get_thumbnail_frame_border  (void);
+
 GList           *photos_utils_get_urns_from_paths         (GList *paths, GtkTreeModel *model);
 
 void             photos_utils_queue_thumbnail_job_for_file_async (GFile *file,



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