[gtk+/wip/baedert/gtkimageview: 138/160] Implement image abstraction for pixbuf images



commit ce9f8a5454e50cbd97013cf20f9c006ad28728f7
Author: Timm Bäder <mail baedert org>
Date:   Sun Apr 17 10:36:16 2016 +0200

    Implement image abstraction for pixbuf images

 demos/gtk-demo/image_view.c |   27 ++-----
 gtk/gtkabstractimage.c      |  179 ++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkabstractimage.h      |   77 ++++++++++++++++++-
 gtk/gtkimageview.c          |   57 +++++++++-----
 4 files changed, 297 insertions(+), 43 deletions(-)
---
diff --git a/demos/gtk-demo/image_view.c b/demos/gtk-demo/image_view.c
index 69173b5..6f1a68c 100644
--- a/demos/gtk-demo/image_view.c
+++ b/demos/gtk-demo/image_view.c
@@ -154,38 +154,27 @@ scale_scale_format_value_cb (GtkScale *scale,
 void
 load_pixbuf_button_clicked_cb ()
 {
-
-
   GtkPixbufImage *image = gtk_pixbuf_image_new ("/usr/share/backgrounds/gnome/Fabric.jpg", 1);
 
   gtk_image_view_set_abstract_image (GTK_IMAGE_VIEW (image_view),
                                      GTK_ABSTRACT_IMAGE (image));
-
-  /*GdkPixbuf *pixbuf;*/
-
-  /*pixbuf = gdk_pixbuf_new_from_file ("/usr/share/backgrounds/gnome/Fabric.jpg",*/
-                                     /*NULL);*/
-
-  /*g_assert (pixbuf != NULL);*/
-  /*gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (image_view), pixbuf, 0);*/
-
-  /*g_object_unref (G_OBJECT (pixbuf));*/
 }
 
 
 void
 load_hidpi_pixbuf_button_clicked_cb ()
 {
-  GdkPixbuf *pixbuf;
+  GdkPixbufAnimation *animation;
+  GtkPixbufAnimationImage *image;
 
-  /* I really hope you have this. */
-  pixbuf = gdk_pixbuf_new_from_file ("/usr/share/backgrounds/gnome/Fabric.jpg",
-                                     NULL);
+  g_warning ("Reminder: This just loads an animation right now.");
 
-  g_assert (pixbuf != NULL);
-  gtk_image_view_set_pixbuf (GTK_IMAGE_VIEW (image_view), pixbuf, 2);
+  animation = gdk_pixbuf_animation_new_from_file ("/home/baedert/0mKXcg1.gif", NULL);
+  image = gtk_pixbuf_animation_image_new (animation, 1);
 
-  g_object_unref (G_OBJECT (pixbuf));
+  g_message ("%s", g_type_name (G_TYPE_FROM_INSTANCE (image)));
+
+  gtk_image_view_set_abstract_image (GTK_IMAGE_VIEW (image_view), GTK_ABSTRACT_IMAGE (image));
 }
 
 void
diff --git a/gtk/gtkabstractimage.c b/gtk/gtkabstractimage.c
index d073c3f..82d40ed 100644
--- a/gtk/gtkabstractimage.c
+++ b/gtk/gtkabstractimage.c
@@ -17,19 +17,37 @@
 
 #include "config.h"
 #include "gtkabstractimage.h"
+#include "gtkmarshalers.h"
+#include "gtkintl.h"
 
 
 G_DEFINE_ABSTRACT_TYPE (GtkAbstractImage, gtk_abstract_image, G_TYPE_OBJECT)
 
 /* GtkAbstractImage {{{ */
 
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+static guint image_signals[LAST_SIGNAL] = { 0 };
+
 static void
 gtk_abstract_image_init (GtkAbstractImage *image)
 {}
 
 static void
 gtk_abstract_image_class_init (GtkAbstractImageClass *klass)
-{}
+{
+  image_signals[CHANGED] = g_signal_new (I_("changed"),
+                                         G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),
+                                         G_SIGNAL_RUN_FIRST,
+                                         G_STRUCT_OFFSET (GtkAbstractImageClass, changed),
+                                         NULL, NULL,
+                                         _gtk_marshal_VOID__VOID,
+                                         G_TYPE_NONE, 0);
+}
 
 int
 gtk_abstract_image_get_width (GtkAbstractImage *image)
@@ -55,11 +73,17 @@ gtk_abstract_image_draw (GtkAbstractImage *image, cairo_t *ct)
   GTK_ABSTRACT_IMAGE_GET_CLASS (image)->draw (image, ct);
 }
 
-/* }}} */
+int
+gtk_abstract_image_get_scale_factor (GtkAbstractImage *image)
+{
+  g_return_val_if_fail (GTK_IS_ABSTRACT_IMAGE (image), 1);
 
+  return GTK_ABSTRACT_IMAGE_GET_CLASS (image)->get_scale_factor (image);
+}
 
-/* GtkPixbufImage {{{ */
+/* }}} */
 
+/* GtkPixbufImage {{{ */
 G_DEFINE_TYPE (GtkPixbufImage, gtk_pixbuf_image, GTK_TYPE_ABSTRACT_IMAGE)
 
 
@@ -116,6 +140,155 @@ gtk_pixbuf_image_class_init (GtkPixbufImageClass *klass)
   image_class->get_scale_factor = gtk_pixbuf_image_get_scale_factor;
   image_class->draw = gtk_pixbuf_image_draw;
 }
+/* }}} */
+
+/* GtkPixbufAnimationImage {{{ */
+G_DEFINE_TYPE (GtkPixbufAnimationImage, gtk_pixbuf_animation_image, GTK_TYPE_ABSTRACT_IMAGE)
+
+GtkPixbufAnimationImage *
+gtk_pixbuf_animation_image_new (GdkPixbufAnimation *animation, int scale_factor)
+{
+  GtkPixbufAnimationImage *image = g_object_new (GTK_TYPE_PIXBUF_ANIMATION_IMAGE, NULL);
+  g_assert (animation);
+
+  image->scale_factor = scale_factor;
+  image->animation = animation;
+  image->iter = gdk_pixbuf_animation_get_iter (animation, NULL);
+  /* TODO: Use the delay for the CURRENT iter... */
+  image->delay_ms = gdk_pixbuf_animation_iter_get_delay_time (image->iter);
+  g_assert (image->iter);
+  g_assert (gdk_pixbuf_animation_iter_get_pixbuf (image->iter));
+  image->frame = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_iter_get_pixbuf (image->iter),
+                                                       scale_factor, NULL);
+
+  g_assert (image->frame);
+
+  g_message ("CTOR");
+  return image;
+}
+
+static int
+gtk_pixbuf_animation_image_get_width (GtkAbstractImage *image)
+{
+  return gdk_pixbuf_animation_get_width (GTK_PIXBUF_ANIMATION_IMAGE (image)->animation);
+}
+
+static int
+gtk_pixbuf_animation_image_get_height (GtkAbstractImage *image)
+{
+  return gdk_pixbuf_animation_get_height (GTK_PIXBUF_ANIMATION_IMAGE (image)->animation);
+}
+
+static int
+gtk_pixbuf_animation_image_get_scale_factor (GtkAbstractImage *image)
+{
+  /*return GTK_PIXBUF_ANIMATION_IMAGE (image)->scale_factor;*/
+  return 1;
+}
+
+static gboolean
+gtk_pixbuf_animation_image_advance (gpointer user_data)
+{
+  GtkPixbufAnimationImage *image = user_data;
+
+  gdk_pixbuf_animation_iter_advance (image->iter, NULL);
+  image->frame = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_iter_get_pixbuf (image->iter),
+                                                       image->scale_factor, NULL);
+
+  g_signal_emit (image, image_signals[CHANGED], 0);
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_pixbuf_animation_image_draw (GtkAbstractImage *_image, cairo_t *ct)
+{
+  GtkPixbufAnimationImage *image = GTK_PIXBUF_ANIMATION_IMAGE (_image);
+
+  /* We start the animation at the first draw() call... */
+  if (image->timeout_id == 0)
+    {
+      image->timeout_id = g_timeout_add (image->delay_ms, gtk_pixbuf_animation_image_advance, image);
+    }
+
+  cairo_set_source_surface (ct, image->frame, 0, 0);
+}
 
+static void
+gtk_pixbuf_animation_image_init (GtkPixbufAnimationImage *image)
+{
+  image->timeout_id = 0;
+}
+
+static void
+gtk_pixbuf_animation_image_class_init (GtkPixbufAnimationImageClass *klass)
+{
+  GtkAbstractImageClass *image_class = GTK_ABSTRACT_IMAGE_CLASS (klass);
+
+  image_class->get_width = gtk_pixbuf_animation_image_get_width;
+  image_class->get_height = gtk_pixbuf_animation_image_get_height;
+  image_class->get_scale_factor = gtk_pixbuf_animation_image_get_scale_factor;
+  image_class->draw = gtk_pixbuf_animation_image_draw;
+}
+/* }}} */
+
+/* GtkSurfaceImage {{{ */
+
+G_DEFINE_TYPE (GtkSurfaceImage, gtk_surface_image, GTK_TYPE_ABSTRACT_IMAGE)
+
+static int
+gtk_surface_image_get_width (GtkAbstractImage *image)
+{
+  return cairo_image_surface_get_width (GTK_SURFACE_IMAGE (image)->surface);
+}
+
+static int
+gtk_surface_image_get_height (GtkAbstractImage *image)
+{
+  return cairo_image_surface_get_height (GTK_SURFACE_IMAGE (image)->surface);
+}
+
+static int
+gtk_surface_image_get_scale_factor (GtkAbstractImage *image)
+{
+  double sx, sy;
+  cairo_surface_t *surface = GTK_SURFACE_IMAGE (image)->surface;
+
+  cairo_surface_get_device_scale (surface, &sx, &sy);
+
+  return (int)sx;
+}
+
+static void
+gtk_surface_image_draw (GtkAbstractImage *image, cairo_t *ct)
+{
+  cairo_set_source_surface (ct, GTK_SURFACE_IMAGE (image)->surface, 0, 0);
+}
+
+GtkSurfaceImage *
+gtk_surface_image_new (cairo_surface_t *surface)
+{
+  GtkSurfaceImage *image = g_object_new (GTK_TYPE_SURFACE_IMAGE, NULL);
+  image->surface = surface;
+
+  return image;
+}
+
+static void
+gtk_surface_image_init (GtkSurfaceImage *image)
+{
+
+}
+
+static void
+gtk_surface_image_class_init (GtkSurfaceImageClass *klass)
+{
+  GtkAbstractImageClass *image_class = GTK_ABSTRACT_IMAGE_CLASS (klass);
+
+  image_class->get_width = gtk_surface_image_get_width;
+  image_class->get_height = gtk_surface_image_get_height;
+  image_class->get_scale_factor = gtk_surface_image_get_scale_factor;
+  image_class->draw = gtk_surface_image_draw;
+}
 
 /* }}} */
diff --git a/gtk/gtkabstractimage.h b/gtk/gtkabstractimage.h
index 2eb9083..1e1569a 100644
--- a/gtk/gtkabstractimage.h
+++ b/gtk/gtkabstractimage.h
@@ -50,6 +50,8 @@ struct _GtkAbstractImageClass
   int    (*get_height) (GtkAbstractImage *image);
   int    (*get_scale_factor) (GtkAbstractImage *image);
   void   (*draw) (GtkAbstractImage *image, cairo_t *ct);
+
+  void   (*changed) (GtkAbstractImage image);
 };
 
 GDK_AVAILABLE_IN_3_20
@@ -61,6 +63,9 @@ int gtk_abstract_image_get_height (GtkAbstractImage *image);
 
 void gtk_abstract_image_draw (GtkAbstractImage *image, cairo_t *ct);
 
+int gtk_abstract_image_get_scale_factor (GtkAbstractImage *image);
+
+/* ------------------------------------------------------------------------------------ */
 
 typedef struct _GtkPixbufImage GtkPixbufImage;
 typedef struct _GtkPixbufImageClass GtkPixbufImageClass;
@@ -68,8 +73,8 @@ typedef struct _GtkPixbufImageClass GtkPixbufImageClass;
 #define GTK_TYPE_PIXBUF_IMAGE           (gtk_pixbuf_image_get_type ())
 #define GTK_PIXBUF_IMAGE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_PIXBUF_IMAGE, 
GtkPixbufImage))
 #define GTK_PIXBUF_IMAGE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_PIXBUF_IMAGE, 
GtkPixbufImageClass))
-#define GTK_IS_pixbuf_image(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_PIXBUF_IMAGE))
-#define GTK_IS_pixbuf_image_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_PIXBUF_IMAGE))
+#define GTK_IS_PIXBUF_IMAGE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_PIXBUF_IMAGE))
+#define GTK_IS_PIXBUF_IMAGE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_PIXBUF_IMAGE))
 #define GTK_PIXBUF_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PIXBUF_IMAGE, 
GtkPixbufImageClass))
 
 struct _GtkPixbufImage
@@ -85,9 +90,77 @@ struct _GtkPixbufImageClass
 };
 
 GDK_AVAILABLE_IN_3_20
+GType gtk_pixbuf_image_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_20
 GtkPixbufImage *gtk_pixbuf_image_new (const char *path, int scale_factor);
 
 
+/* ------------------------------------------------------------------------------------ */
+
+
+typedef struct _GtkPixbufAnimationImage GtkPixbufAnimationImage;
+typedef struct _GtkPixbufAnimationImageClass GtkPixbufAnimationImageClass;
+
+#define GTK_TYPE_PIXBUF_ANIMATION_IMAGE           (gtk_pixbuf_animation_image_get_type ())
+#define GTK_PIXBUF_ANIMATION_IMAGE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, 
GTK_TYPE_PIXBUF_ANIMATION_IMAGE, GtkPixbufAnimationImage))
+#define GTK_PIXBUF_ANIMATION_IMAGE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, 
GTK_TYPE_PIXBUF_ANIMATION_IMAGE, GtkPixbufAnimationImageClass))
+#define GTK_IS_PIXBUX_ANIMATION_IMAGE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, 
GTK_TYPE_PIXBUF_ANIMATION_IMAGE))
+#define GTK_IS_PIXBUX_ANIMATION_IMAGE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, 
GTK_TYPE_PIXBUF_ANIMATION_IMAGE))
+#define GTK_PIXBUF_ANIMATION_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_PIXBUF_ANIMATION_IMAGE, GtkPixbufAnimationImageClass))
+
+struct _GtkPixbufAnimationImage
+{
+  GtkAbstractImage parent;
+  GdkPixbufAnimation *animation;
+  GdkPixbufAnimationIter *iter;
+  cairo_surface_t *frame;
+  int scale_factor;
+  int delay_ms;
+  guint timeout_id;
+};
+
+struct _GtkPixbufAnimationImageClass
+{
+  GtkAbstractImageClass parent_class;
+};
+
+GDK_AVAILABLE_IN_3_20
+GType gtk_pixbuf_animation_image_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_20
+GtkPixbufAnimationImage *gtk_pixbuf_animation_image_new (GdkPixbufAnimation *animation,
+                                                         int scale_factor);
+
+
+/* ------------------------------------------------------------------------------------ */
+
+typedef struct _GtkSurfaceImage GtkSurfaceImage;
+typedef struct _GtkSurfaceImageClass GtkSurfaceImageClass;
+
+
+#define GTK_TYPE_SURFACE_IMAGE           (gtk_surface_image_get_type ())
+#define GTK_SURFACE_IMAGE(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_SURFACE_IMAGE, 
GtkSurfaceImage))
+#define GTK_SURFACE_IMAGE_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_SURFACE_IMAGE, 
GtkSurfaceImageClass))
+#define GTK_IS_SURFACE_IMAGE(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_SURFACE_IMAGE))
+#define GTK_IS_SURFACE_IMAGE_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_SURFACE_IMAGE))
+#define GTK_SURFACE_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SURFACE_IMAGE, 
GtkSurfaceImageClass))
+
+struct _GtkSurfaceImage
+{
+  GtkAbstractImage parent;
+  cairo_surface_t *surface;
+};
+
+struct _GtkSurfaceImageClass
+{
+  GtkAbstractImageClass parent_class;
+};
+
+GDK_AVAILABLE_IN_3_20
+GType gtk_surface_image_get_type (void) G_GNUC_CONST;
+
+GtkSurfaceImage *gtk_surface_image_new (cairo_surface_t *surface);
 
 G_END_DECLS
 
diff --git a/gtk/gtkimageview.c b/gtk/gtkimageview.c
index e79202e..424dfbb 100644
--- a/gtk/gtkimageview.c
+++ b/gtk/gtkimageview.c
@@ -51,6 +51,7 @@
 #include "gtkgesturezoom.h"
 #include "gtkscrollable.h"
 #include "gtkadjustment.h"
+#include "gtkabstractimage.h"
 #include <gdk/gdkcairo.h>
 #include <math.h>
 
@@ -605,6 +606,7 @@ gtk_image_view_compute_bounding_box (GtkImageView *image_view,
   gtk_widget_get_allocation (GTK_WIDGET (image_view), &alloc);
   angle = gtk_image_view_get_real_angle (image_view);
 
+  g_message ("%s", g_type_name (G_TYPE_FROM_INSTANCE (priv->image)));
   image_width = gtk_abstract_image_get_width (priv->image) /
                 gtk_abstract_image_get_scale_factor (priv->image);
   image_height = gtk_abstract_image_get_height (priv->image) /
@@ -2175,25 +2177,24 @@ gtk_image_view_new ()
 }
 
 static void
-gtk_image_view_replace_surface (GtkImageView    *image_view,
-                                cairo_surface_t *surface,
-                                int              scale_factor)
+gtk_image_view_replace_image (GtkImageView     *image_view,
+                              GtkAbstractImage *image)
 {
   GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
 
-  /*if (priv->image_surface)*/
-    /*cairo_surface_destroy (priv->image_surface);*/
+  if (priv->image)
+    g_object_unref (priv->image);
 
-  if (scale_factor == 0)
-    priv->scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image_view));
-  else
-    priv->scale_factor = scale_factor;
+  /*if (scale_factor == 0)*/
+    /*priv->scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image_view));*/
+  /*else*/
+    /*priv->scale_factor = scale_factor;*/
 
-  /*priv->image_surface = surface;*/
+  priv->image = image;
   priv->size_valid = FALSE;
 
-  /*if (surface)*/
-    /*cairo_surface_reference (priv->image_surface);*/
+  if (priv->image)
+    g_object_ref (priv->image);
 }
 
 static void
@@ -2219,9 +2220,9 @@ gtk_image_view_update_surface (GtkImageView    *image_view,
                      /*(scale_factor != priv->scale_factor);*/
     /*}*/
 
-  gtk_image_view_replace_surface (image_view,
-                                  new_surface,
-                                  scale_factor);
+  /*gtk_image_view_replace_image (image_view,*/
+                                  /*new_surface,*/
+                                  /*scale_factor);*/
 
   if (priv->fit_allocation || !size_changed)
     gtk_widget_queue_draw (GTK_WIDGET (image_view));
@@ -2520,6 +2521,7 @@ gtk_image_view_set_surface (GtkImageView    *image_view,
                             cairo_surface_t *surface)
 {
   GtkImageViewPrivate *priv = gtk_image_view_get_instance_private (image_view);
+  GtkSurfaceImage *image;
   double scale_x = 0.0;
   double scale_y;
 
@@ -2541,9 +2543,9 @@ gtk_image_view_set_surface (GtkImageView    *image_view,
       priv->is_animation = FALSE;
     }
 
-  gtk_image_view_replace_surface (image_view,
-                                  surface,
-                                  scale_x);
+  image = gtk_surface_image_new (surface);
+
+  gtk_image_view_replace_image (image_view, GTK_ABSTRACT_IMAGE (image));
 
   gtk_image_view_update_adjustments (image_view);
 
@@ -2571,11 +2573,22 @@ gtk_image_view_set_animation (GtkImageView       *image_view,
                               GdkPixbufAnimation *animation,
                               int                 scale_factor)
 {
+  /*GtkPixbufAnimationImage *image;*/
   g_return_if_fail (GTK_IS_IMAGE_VIEW (image_view));
   g_return_if_fail (GDK_IS_PIXBUF_ANIMATION (animation));
   g_return_if_fail (scale_factor >= 0);
 
-  gtk_image_view_replace_animation (image_view, animation, scale_factor);
+  /*gtk_image_view_replace_animation (image_view, animation, scale_factor);*/
+
+  /*image = gtk_pixbuf_animation_image-nwe (animation, scale_factor);*/
+}
+
+void
+image_changed_cb (GtkAbstractImage *image, gpointer user_data)
+{
+  GtkImageView *image_view = user_data;
+
+  gtk_widget_queue_draw (GTK_WIDGET (image_view));
 }
 
 void
@@ -2587,7 +2600,13 @@ gtk_image_view_set_abstract_image (GtkImageView     *image_view,
   g_return_if_fail (GTK_IS_IMAGE_VIEW (image_view));
   g_return_if_fail (GTK_IS_ABSTRACT_IMAGE (abstract_image));
 
+
+  g_message ("%s", g_type_name (G_TYPE_FROM_INSTANCE (abstract_image)));
+
   priv->image = abstract_image;
 
+  g_signal_connect (G_OBJECT (priv->image),
+                    "changed", G_CALLBACK (image_changed_cb), image_view);
+
   gtk_widget_queue_resize (GTK_WIDGET (image_view));
 }


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