[gnome-photos/wip/baedert/gtkimageview: 8/10] geglimage; Pre-render to surface



commit dea6a365799c92f18793b4fc4bdbd7319a44e47d
Author: Timm Bäder <mail baedert org>
Date:   Fri Apr 15 17:07:31 2016 +0200

    geglimage; Pre-render to surface

 src/photos-gegl-image.c          |  162 ++++++++++++++++++++++++++------------
 src/photos-gegl-image.h          |    5 +-
 src/photos-preview-nav-buttons.c |    2 +-
 src/photos-tool-crop.c           |    4 +-
 4 files changed, 120 insertions(+), 53 deletions(-)
---
diff --git a/src/photos-gegl-image.c b/src/photos-gegl-image.c
index cb3cab1..8c9e875 100644
--- a/src/photos-gegl-image.c
+++ b/src/photos-gegl-image.c
@@ -23,70 +23,108 @@ photos_gegl_image_get_scale_factor (GtkAbstractImage *_image)
 }
 
 static void
-photos_gegl_image_render_surface (PhotosGeglImage *image)
+photos_gegl_image_update_bbox (PhotosGeglImage *image)
 {
   GeglRectangle roi = image->roi;
+  GeglRectangle box = gegl_node_get_bounding_box (image->node);
+  gboolean bbox_changed = !gegl_rectangle_equal (&roi, &box);
 
-  roi.x *= image->view_scale;
-  roi.y *= image->view_scale;
+  image->width = box.width;
+  image->height = box.height;
 
-  gegl_node_blit (image->node,
-                  image->view_scale,
-                  &roi,
-                  image->format,
-                  image->buf,
-                  GEGL_AUTO_ROWSTRIDE,
-                  GEGL_BLIT_CACHE | GEGL_BLIT_DIRTY);
-
-  /*if (!image->surface)*/
-    /*{*/
-      image->surface = cairo_image_surface_create_for_data (image->buf,
-                                                            CAIRO_FORMAT_ARGB32,
-                                                            image->width * image->view_scale,
-                                                            image->height * image->view_scale,
-                                                            image->stride);
-    /*}*/
+  image->roi = box;
+  g_message ("%s: New roi: %d, %d, %d, %d", __FUNCTION__, box.x, box.y, box.width, box.height);
 
-  g_signal_emit_by_name (G_OBJECT (image), "changed", 0);
+  if (bbox_changed)
+    g_signal_emit_by_name (G_OBJECT (image), "changed", 0);
 }
 
+
 static void
-photos_gegl_image_update_bbox (PhotosGeglImage *image)
+photos_gegl_image_render_surface (PhotosGeglImage *image)
 {
+  int w, h;
+  GeglRectangle roi = image->roi;
   GeglRectangle box;
+  gboolean bbox_changed;
+  gboolean bbox_size_changed;
+  gboolean height_changed;
+  gboolean stride_changed = FALSE;
+  gboolean scale_changed = (image->view_scale != image->rendered_scale);
 
-  if (!image->node)
-    return;
+  g_assert (image->node);
 
   box = gegl_node_get_bounding_box (image->node);
 
-#if 0
-  g_message ("old size: %d, %d; new size: %d, %d", image->width, image->height,
-             box.width, box.height);
-  g_message ("bbox: %d, %d, %d, %d", box.x, box.y, box.width, box.height);
-#endif
+  bbox_changed = !gegl_rectangle_equal (&box, &image->roi);
+  bbox_size_changed = (box.width != image->width || box.height != image->height);
+  height_changed = (box.height != image->height);
 
-  /*if (image->width != box.width || image->height != box.height ||*/
-      /*image->roi.x != box.x     || image->roi.y != box.y)*/
-    /*{*/
+  if (bbox_size_changed || scale_changed)
+    {
+      int new_stride;
       image->width  = box.width;
       image->height = box.height;
 
-      image->roi.x      = box.x;
-      image->roi.y      = box.y;
-      image->roi.width  = box.width  /* image->scale_factor */* image->view_scale;
-      image->roi.height = box.height /* image->scale_factor */* image->view_scale;
-
+      image->roi = box;
+      g_message ("%s: New roi: %d, %d, %d, %d", __FUNCTION__, box.x, box.y, box.width, box.height);
+      new_stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
+                                                  box.width * image->view_scale);
+      stride_changed = (image->stride != new_stride);
+      image->stride = new_stride;
+    }
 
+  roi = image->roi;
 
-      image->stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
-                                                     box.width * image->view_scale);
+  roi.x      *= image->view_scale;
+  roi.y      *= image->view_scale;
+  roi.width  *= image->view_scale;
+  roi.height *= image->view_scale;
 
+  if (stride_changed || height_changed)
+    {
       g_clear_pointer (&image->buf, g_free);
-      g_clear_pointer (&image->buf, cairo_surface_destroy);
+      image->buf = g_malloc (image->stride * image->height); /* stride is already scaled */
+    }
+
+  if (scale_changed || bbox_changed)
+    {
+      g_message ("Blit");
+      gegl_node_blit (image->node,
+                      image->view_scale,
+                      &roi,
+                      image->format,
+                      image->buf,
+                      GEGL_AUTO_ROWSTRIDE,
+                      GEGL_BLIT_CACHE | GEGL_BLIT_DIRTY);
+    }
+
+  if (image->surface)
+    {
+      w = cairo_image_surface_get_width (image->surface);
+      h = cairo_image_surface_get_height (image->surface);
+    }
+  else
+    {
+      w = 0;
+      h = 0;
+    }
 
-      image->buf = g_malloc (image->stride * box.height); /* stride is already scaled */
-    /*}*/
+  if (!image->surface ||
+      w != (image->width  * image->view_scale) ||
+      h != (image->height * image->view_scale))
+    {
+      g_message ("New surface");
+      g_clear_pointer (&image->surface, cairo_surface_destroy);
+      image->surface = cairo_image_surface_create_for_data (image->buf,
+                                                            CAIRO_FORMAT_ARGB32,
+                                                            image->width  * image->view_scale,
+                                                            image->height * image->view_scale,
+                                                            image->stride);
+    }
+
+  image->rendered_scale = image->view_scale;
+  g_signal_emit_by_name (G_OBJECT (image), "changed", 0);
 }
 
 static void
@@ -96,7 +134,8 @@ photos_gegl_image_draw (GtkAbstractImage *_image, cairo_t *ct)
 
   if (image->surface)
     {
-      cairo_scale (ct, 1.0 / image->view_scale, 1.0 / image->view_scale);
+      cairo_scale (ct, 1.0 / image->rendered_scale, 1.0 / image->rendered_scale);
+      /*cairo_scale (ct, 1.0 / image->view_scale, 1.0 / image->view_scale);*/
       cairo_set_source_surface (ct, image->surface, 0, 0);
     }
 }
@@ -104,7 +143,9 @@ photos_gegl_image_draw (GtkAbstractImage *_image, cairo_t *ct)
 static void
 photos_gegl_image_computed (PhotosGeglImage *image)
 {
-  photos_gegl_image_update_bbox (image);
+  static int i = -1;
+
+  g_message ("%s: %d", __FUNCTION__, ++i);
   photos_gegl_image_render_surface (image);
 }
 
@@ -119,7 +160,6 @@ photos_gegl_image_new (GeglNode *node, int scale_factor)
   image->scale_factor = scale_factor;
   image->format = babl_format ("cairo-ARGB32");
 
-  photos_gegl_image_update_bbox (image);
   photos_gegl_image_render_surface (image);
 
   return image;
@@ -130,6 +170,7 @@ photos_gegl_image_init (PhotosGeglImage *image)
 {
   image->surface = NULL;
   image->view_scale = 1.0;
+  image->rendered_scale = 1.0;
 }
 
 static void
@@ -137,11 +178,8 @@ photos_gegl_image_finalize (GObject *_image)
 {
   PhotosGeglImage *image = PHOTOS_GEGL_IMAGE (_image);
 
-  if (image->surface)
-    cairo_surface_destroy (image->surface);
-
-  if (image->buf)
-    g_free (image->buf);
+  g_clear_pointer (&image->surface, cairo_surface_destroy);
+  g_clear_pointer (&image->buf, g_free);
 
   G_OBJECT_CLASS (photos_gegl_image_parent_class)->finalize (_image);
 }
@@ -160,6 +198,19 @@ photos_gegl_image_class_init (PhotosGeglImageClass *klass)
   image_class->get_scale_factor = photos_gegl_image_get_scale_factor;
 }
 
+static gboolean
+redraw_cb (gpointer data)
+{
+  PhotosGeglImage *image = data;
+
+
+  if (G_LIKELY (image->node))
+    photos_gegl_image_render_surface (image);
+
+  image->redraw_id = 0;
+  return G_SOURCE_REMOVE;
+}
+
 void
 photos_gegl_image_set_view_scale (PhotosGeglImage *image, double view_scale)
 {
@@ -168,5 +219,16 @@ photos_gegl_image_set_view_scale (PhotosGeglImage *image, double view_scale)
 
   image->view_scale = view_scale;
 
-  photos_gegl_image_render_surface (image);
+  if (!image->node)
+    return;
+
+  photos_gegl_image_update_bbox (image);
+
+  if (image->redraw_id != 0)
+    {
+      g_source_remove (image->redraw_id);
+      image->redraw_id = 0;
+    }
+
+  image->redraw_id = g_timeout_add (200, redraw_cb, image);
 }
diff --git a/src/photos-gegl-image.h b/src/photos-gegl-image.h
index 57c8e05..aafde0e 100644
--- a/src/photos-gegl-image.h
+++ b/src/photos-gegl-image.h
@@ -19,13 +19,16 @@ struct _PhotosGeglImage
   GeglNode *node;
   int width;
   int height;
-  double view_scale;
   cairo_surface_t *surface;
   guchar *buf;
   const Babl *format;
   GeglRectangle roi;
   int stride;
   int scale_factor;
+
+  double view_scale;
+  double rendered_scale;
+  guint redraw_id;
 };
 
 struct _PhotosGeglImageClass
diff --git a/src/photos-preview-nav-buttons.c b/src/photos-preview-nav-buttons.c
index 166e8d8..410175d 100644
--- a/src/photos-preview-nav-buttons.c
+++ b/src/photos-preview-nav-buttons.c
@@ -114,7 +114,7 @@ photos_preview_nav_buttons_fade_in_button (PhotosPreviewNavButtons *self, GtkWid
     return;
 
   gtk_widget_show_all (widget);
-  gtk_revealer_set_reveal_child (GTK_REVEALER (widget), TRUE);
+  gtk_revealer_set_reveal_child (GTK_REVEALER (widget), FALSE);
 }
 
 
diff --git a/src/photos-tool-crop.c b/src/photos-tool-crop.c
index 7120e77..8fc7c18 100644
--- a/src/photos-tool-crop.c
+++ b/src/photos-tool-crop.c
@@ -233,8 +233,10 @@ photos_tool_crop_surface_create (PhotosToolCrop *self)
 
   window = gtk_widget_get_window (self->view);
   zoom = photos_image_view_get_zoom (PHOTOS_IMAGE_VIEW (self->view));
-  self->bbox_zoomed.height = (gint) (zoom * self->bbox_source.height + 0.5);
+  g_message ("bbox_source: %d, %d (zoom: %f)", self->bbox_source.width, self->bbox_source.height, zoom);
+  /*zoom = 1.0;*/
   self->bbox_zoomed.width = (gint) (zoom * self->bbox_source.width + 0.5);
+  self->bbox_zoomed.height = (gint) (zoom * self->bbox_source.height + 0.5);
   self->surface = gdk_window_create_similar_surface (window,
                                                      CAIRO_CONTENT_COLOR_ALPHA,
                                                      self->bbox_zoomed.width,


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