[eog/wip/baedert/gtkimageview: 50/75] EogImage: Implement GtkAbstractImage



commit 64c80c625569d4374f27670c7528e2331dd37774
Author: Timm Bäder <mail baedert org>
Date:   Mon Mar 14 21:10:17 2016 +0100

    EogImage: Implement GtkAbstractImage

 src/eog-image-private.h |    4 +
 src/eog-image.c         |   64 ++++++++++++++++----
 src/eog-image.h         |    8 +-
 src/eog-scroll-view.c   |  151 +++++++++++++---------------------------------
 4 files changed, 103 insertions(+), 124 deletions(-)
---
diff --git a/src/eog-image-private.h b/src/eog-image-private.h
index e0c1592..6919b7e 100644
--- a/src/eog-image-private.h
+++ b/src/eog-image-private.h
@@ -46,6 +46,10 @@ struct _EogImagePrivate {
        GdkPixbufAnimationIter *anim_iter;
        GdkPixbuf        *image;
        GdkPixbuf        *thumbnail;
+
+    cairo_surface_t *surface;
+
+
 #ifdef HAVE_RSVG
        RsvgHandle       *svg;
 #endif
diff --git a/src/eog-image.c b/src/eog-image.c
index 0d6e091..a5e371d 100644
--- a/src/eog-image.c
+++ b/src/eog-image.c
@@ -73,10 +73,9 @@
 #include <librsvg/rsvg.h>
 #endif
 
-G_DEFINE_TYPE_WITH_PRIVATE (EogImage, eog_image, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_PRIVATE (EogImage, eog_image, GTK_TYPE_ABSTRACT_IMAGE)
 
 enum {
-       SIGNAL_CHANGED,
        SIGNAL_SIZE_PREPARED,
        SIGNAL_THUMBNAIL_CHANGED,
        SIGNAL_SAVE_PROGRESS,
@@ -220,10 +219,46 @@ eog_image_finalize (GObject *object)
        G_OBJECT_CLASS (eog_image_parent_class)->finalize (object);
 }
 
+static int
+__get_width (GtkAbstractImage *_image)
+{
+  return EOG_IMAGE (_image)->priv->width;
+}
+
+static int
+__get_height (GtkAbstractImage *_image)
+{
+  return EOG_IMAGE (_image)->priv->height;
+}
+
+static int
+__get_scale_factor (GtkAbstractImage *_image)
+{
+  return 1;
+}
+
+static void
+__draw (GtkAbstractImage *_image, cairo_t *ct)
+{
+  EogImagePrivate *priv = EOG_IMAGE (_image)->priv;
+
+  if (eog_image_is_svg (EOG_IMAGE (_image))) {
+    rsvg_handle_render_cairo (priv->svg, ct);
+  } else {
+    cairo_set_source_surface (ct, priv->surface, 0, 0);
+  }
+}
+
 static void
 eog_image_class_init (EogImageClass *klass)
 {
        GObjectClass *object_class = (GObjectClass*) klass;
+    GtkAbstractImageClass *image_class = GTK_ABSTRACT_IMAGE_CLASS (klass);
+
+    image_class->get_width        = __get_width;
+    image_class->get_height       = __get_height;
+    image_class->get_scale_factor = __get_scale_factor;
+    image_class->draw             = __draw;
 
        object_class->dispose = eog_image_dispose;
        object_class->finalize = eog_image_finalize;
@@ -239,15 +274,6 @@ eog_image_class_init (EogImageClass *klass)
                              G_TYPE_INT,
                              G_TYPE_INT);
 
-       signals[SIGNAL_CHANGED] =
-               g_signal_new ("changed",
-                             EOG_TYPE_IMAGE,
-                             G_SIGNAL_RUN_LAST,
-                             G_STRUCT_OFFSET (EogImageClass, changed),
-                             NULL, NULL,
-                             g_cclosure_marshal_VOID__VOID,
-                             G_TYPE_NONE, 0);
-
        signals[SIGNAL_THUMBNAIL_CHANGED] =
                g_signal_new ("thumbnail-changed",
                              EOG_TYPE_IMAGE,
@@ -594,6 +620,7 @@ eog_image_apply_transformations (EogImage *img, GError **error)
 
        g_object_unref (priv->image);
        priv->image = transformed;
+    priv->surface = gdk_cairo_surface_create_from_pixbuf (priv->image, 1, NULL);
 
        if (transformed != NULL) {
                priv->width = gdk_pixbuf_get_width (priv->image);
@@ -1176,6 +1203,7 @@ eog_image_real_load (EogImage *img,
                        priv->image = gdk_pixbuf_animation_iter_get_pixbuf (priv->anim_iter);
                }
 
+
                }
 
                if (G_LIKELY (priv->image != NULL)) {
@@ -1184,6 +1212,7 @@ eog_image_real_load (EogImage *img,
 
                        priv->width = gdk_pixbuf_get_width (priv->image);
                        priv->height = gdk_pixbuf_get_height (priv->image);
+            priv->surface = gdk_cairo_surface_create_from_pixbuf (priv->image, 1, NULL);
 
                        if (use_rsvg) {
                                format = NULL;
@@ -2166,7 +2195,7 @@ eog_image_modified (EogImage *img)
 {
        g_return_if_fail (EOG_IS_IMAGE (img));
 
-       g_signal_emit (G_OBJECT (img), signals[SIGNAL_CHANGED], 0);
+    g_signal_emit_by_name (G_OBJECT (img), "changed", 0);
 }
 
 gchar*
@@ -2343,6 +2372,8 @@ eog_image_iter_advance (EogImage *img)
                        priv->width = gdk_pixbuf_get_width (transformed);
                        priv->height = gdk_pixbuf_get_height (transformed);
                }
+        priv->surface = gdk_cairo_surface_create_from_pixbuf (priv->image, 1, NULL);
+
                g_mutex_unlock (&priv->status_mutex);
                /* Emit next frame signal so we can update the display */
                g_signal_emit (img, signals[SIGNAL_NEXT_FRAME], 0,
@@ -2548,3 +2579,12 @@ eog_image_is_multipaged (EogImage *img)
 
        return result;
 }
+
+gboolean
+eog_image_has_alpha (EogImage *img)
+{
+    EogImagePrivate *priv = img->priv;
+
+    return priv->image != NULL &&
+           gdk_pixbuf_get_has_alpha (priv->image);
+}
diff --git a/src/eog-image.h b/src/eog-image.h
index de8feba..23d298e 100644
--- a/src/eog-image.h
+++ b/src/eog-image.h
@@ -89,15 +89,13 @@ typedef enum {
 } EogImageMetadataStatus;
 
 struct _EogImage {
-       GObject parent;
+  GtkAbstractImage parent;
 
        EogImagePrivate *priv;
 };
 
 struct _EogImageClass {
-       GObjectClass parent_class;
-
-       void (* changed)           (EogImage *img);
+  GtkAbstractImageClass parent_class;
 
        void (* size_prepared)     (EogImage *img,
                                    int       width,
@@ -221,6 +219,8 @@ gboolean          eog_image_is_file_writable         (EogImage *img);
 
 gboolean          eog_image_is_multipaged            (EogImage *img);
 
+gboolean          eog_image_has_alpha                (EogImage *img);
+
 G_END_DECLS
 
 #endif /* __EOG_IMAGE_H__ */
diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index 4539498..df10658 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -108,8 +108,6 @@ struct _EogScrollViewPrivate {
        EogImage *image;
        guint image_changed_id;
        guint frame_changed_id;
-       GdkPixbuf *pixbuf;
-       cairo_surface_t *surface;
 
        /* zoom mode, either ZOOM_MODE_FIT or ZOOM_MODE_FREE */
        EogZoomMode zoom_mode;
@@ -201,24 +199,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (EogScrollView, eog_scroll_view, GTK_TYPE_GRID)
         util functions
   ---------------------------------*/
 
-static cairo_surface_t *
-create_surface_from_pixbuf (EogScrollView *view, GdkPixbuf *pixbuf)
-{
-       cairo_surface_t *surface;
-       cairo_t *cr;
-
-       surface = gdk_window_create_similar_surface (gtk_widget_get_window (view->priv->display),
-                                                    CAIRO_CONTENT_COLOR | CAIRO_CONTENT_ALPHA,
-                                                    gdk_pixbuf_get_width (pixbuf),
-                                                    gdk_pixbuf_get_height (pixbuf));
-       cr = cairo_create (surface);
-       gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
-       cairo_paint (cr);
-       cairo_destroy (cr);
-
-       return surface;
-}
-
 /* Disconnects from the EogImage and removes references to it */
 static void
 free_image_resources (EogScrollView *view)
@@ -241,31 +221,24 @@ free_image_resources (EogScrollView *view)
                eog_image_data_unref (priv->image);
                priv->image = NULL;
        }
-
-       if (priv->pixbuf != NULL) {
-               g_object_unref (priv->pixbuf);
-               priv->pixbuf = NULL;
-       }
-
-       if (priv->surface != NULL) {
-               cairo_surface_destroy (priv->surface);
-               priv->surface = NULL;
-       }
 }
 
 /* Computes the size in pixels of the scaled image */
 static void
 compute_scaled_size (EogScrollView *view, double zoom, int *width, int *height)
 {
-       EogScrollViewPrivate *priv;
+       EogScrollViewPrivate *priv = view->priv;
 
-       priv = view->priv;
 
-       if (priv->pixbuf) {
-               *width = floor (gdk_pixbuf_get_width (priv->pixbuf) * zoom + 0.5);
-               *height = floor (gdk_pixbuf_get_height (priv->pixbuf) * zoom + 0.5);
-       } else
-               *width = *height = 0;
+    if (priv->image) {
+      GtkAbstractImage *image = GTK_ABSTRACT_IMAGE (priv->image);
+
+      *width  = floor (gtk_abstract_image_get_width  (image) * zoom + 0.5);
+      *height = floor (gtk_abstract_image_get_height (image) * zoom + 0.5);
+    } else {
+      *width  = 0;
+      *height = 0;
+    }
 }
 
 /* Computes the offsets for the new zoom value so that they keep the image
@@ -726,10 +699,12 @@ drag_to (EogScrollView *view, int x, int y)
 static void
 set_minimum_zoom_factor (EogScrollView *view)
 {
+    GtkAbstractImage *image = GTK_ABSTRACT_IMAGE (view->priv->image);
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
 
-       view->priv->min_zoom = MAX (1.0 / gdk_pixbuf_get_width (view->priv->pixbuf),
-                                   MAX(1.0 / gdk_pixbuf_get_height (view->priv->pixbuf),
+
+       view->priv->min_zoom = MAX (1.0 / gtk_abstract_image_get_width (image),
+                                   MAX(1.0 / gtk_abstract_image_get_height (image),
                                        MIN_ZOOM_FACTOR) );
        return;
 }
@@ -760,8 +735,9 @@ set_zoom (EogScrollView *view, double zoom,
 
        priv = view->priv;
 
-       if (priv->pixbuf == NULL)
-               return;
+    if (priv->image == NULL)
+      return;
+
 
        if (zoom > MAX_ZOOM_FACTOR)
                zoom = MAX_ZOOM_FACTOR;
@@ -834,15 +810,15 @@ set_zoom_fit (EogScrollView *view)
        if (!gtk_widget_get_mapped (GTK_WIDGET (view)))
                return;
 
-       if (priv->pixbuf == NULL)
+       if (priv->image == NULL)
                return;
 
        gtk_widget_get_allocation (GTK_WIDGET(priv->display), &allocation);
 
        new_zoom = zoom_fit_scale (allocation.width, allocation.height,
-                                  gdk_pixbuf_get_width (priv->pixbuf),
-                                  gdk_pixbuf_get_height (priv->pixbuf),
-                                  priv->upscale);
+                               gtk_abstract_image_get_width (GTK_ABSTRACT_IMAGE (priv->image)),
+                               gtk_abstract_image_get_height (GTK_ABSTRACT_IMAGE (priv->image)),
+                               priv->upscale);
 
        if (new_zoom > MAX_ZOOM_FACTOR)
                new_zoom = MAX_ZOOM_FACTOR;
@@ -1298,6 +1274,7 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
        EogScrollView *view;
        EogScrollViewPrivate *priv;
        GtkAllocation allocation;
+    GtkAbstractImage *image;
        int scaled_width, scaled_height;
        int xofs, yofs;
 
@@ -1308,9 +1285,11 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
 
        priv = view->priv;
 
-       if (priv->pixbuf == NULL)
+       if (priv->image == NULL)
                return TRUE;
 
+    image = GTK_ABSTRACT_IMAGE (priv->image);
+
        eog_scroll_view_get_image_coords (view, &xofs, &yofs,
                                          &scaled_width, &scaled_height);
 
@@ -1338,7 +1317,7 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
        cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
        cairo_fill (cr);
 
-       if (gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
+    if (eog_image_has_alpha (priv->image)) {
                if (priv->background_surface == NULL) {
                        priv->background_surface = create_background_surface (view);
                }
@@ -1370,17 +1349,17 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                        switch (eog_transform_get_transform_type (transform)) {
                        case EOG_TRANSFORM_ROT_90:
                        case EOG_TRANSFORM_FLIP_HORIZONTAL:
-                               image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
+                               image_offset_x = (double) gtk_abstract_image_get_width (image);
                                break;
                        case EOG_TRANSFORM_ROT_270:
                        case EOG_TRANSFORM_FLIP_VERTICAL:
-                               image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
+                               image_offset_y = (double) gtk_abstract_image_get_height (image);
                                break;
                        case EOG_TRANSFORM_ROT_180:
                        case EOG_TRANSFORM_TRANSPOSE:
                        case EOG_TRANSFORM_TRANSVERSE:
-                               image_offset_x = (double) gdk_pixbuf_get_width (priv->pixbuf);
-                               image_offset_y = (double) gdk_pixbuf_get_height (priv->pixbuf);
+                               image_offset_x = (double) gtk_abstract_image_get_width (image);
+                               image_offset_y = (double) gtk_abstract_image_get_height (image);
                                break;
                        case EOG_TRANSFORM_NONE:
                        default:
@@ -1398,7 +1377,7 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                cairo_matrix_multiply (&matrix, &matrix, &original);
                cairo_set_matrix (cr, &matrix);
 
-               rsvg_handle_render_cairo (eog_image_get_svg (priv->image), cr);
+        gtk_abstract_image_draw (GTK_ABSTRACT_IMAGE (priv->image), cr);
 
        } else
 #endif /* HAVE_RSVG */
@@ -1421,7 +1400,9 @@ display_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                        priv->force_unfiltered = TRUE;
                }
                cairo_scale (cr, priv->zoom, priv->zoom);
-               cairo_set_source_surface (cr, priv->surface, xofs/priv->zoom, yofs/priv->zoom);
+        cairo_translate (cr, xofs / priv->zoom, yofs / priv->zoom);
+        gtk_abstract_image_draw (GTK_ABSTRACT_IMAGE (priv->image), cr);
+
                cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_PAD);
                if (is_zoomed_in (view) || is_zoomed_out (view))
                        cairo_pattern_set_filter (cairo_get_source (cr), interp_type);
@@ -1639,33 +1620,10 @@ rotate_gesture_angle_changed_cb (GtkGestureRotate *rotate,
    image loading callbacks
 
    -----------------------------------*/
-
-/* Use when the pixbuf in the view is changed, to keep a
-   reference to it and create its cairo surface. */
-static void
-update_pixbuf (EogScrollView *view, GdkPixbuf *pixbuf)
-{
-       EogScrollViewPrivate *priv;
-
-       priv = view->priv;
-
-       if (priv->pixbuf != NULL) {
-               g_object_unref (priv->pixbuf);
-               priv->pixbuf = NULL;
-       }
-
-       priv->pixbuf = pixbuf;
-
-       if (priv->surface) {
-               cairo_surface_destroy (priv->surface);
-       }
-       priv->surface = create_surface_from_pixbuf (view, priv->pixbuf);
-}
-
 static void
 image_changed_cb (EogImage *img, gpointer data)
 {
-       update_pixbuf (EOG_SCROLL_VIEW (data), eog_image_get_pixbuf (img));
+    gtk_widget_queue_draw (GTK_WIDGET (data));
 
        _set_zoom_mode_internal (EOG_SCROLL_VIEW (data),
                                 EOG_ZOOM_MODE_SHRINK_TO_FIT);
@@ -1750,7 +1708,7 @@ _transp_background_changed (EogScrollView *view)
 {
        EogScrollViewPrivate *priv = view->priv;
 
-       if (priv->pixbuf != NULL && gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
+    if (priv->image && eog_image_has_alpha (priv->image)) {
                if (priv->background_surface) {
                        cairo_surface_destroy (priv->background_surface);
                        /* Will be recreated if needed during redraw */
@@ -1786,7 +1744,7 @@ eog_scroll_view_set_transparency (EogScrollView        *view,
        EogScrollViewPrivate *priv;
 
        g_return_if_fail (EOG_IS_SCROLL_VIEW (view));
-       
+
        priv = view->priv;
 
        if (priv->transp_style != style) {
@@ -1933,9 +1891,7 @@ display_next_frame_cb (EogImage *image, gint delay, gpointer data)
        view = EOG_SCROLL_VIEW (data);
        priv = view->priv;
 
-       update_pixbuf (view, eog_image_get_pixbuf (image));
-
-       gtk_widget_queue_draw (GTK_WIDGET (priv->display)); 
+       gtk_widget_queue_draw (GTK_WIDGET (priv->display));
 }
 
 void
@@ -1955,34 +1911,16 @@ eog_scroll_view_set_image (EogScrollView *view, EogImage *image)
                free_image_resources (view);
        }
        g_assert (priv->image == NULL);
-       g_assert (priv->pixbuf == NULL);
 
        /* priv->progressive_state = PROGRESSIVE_NONE; */
        if (image != NULL) {
                eog_image_data_ref (image);
 
-               if (priv->pixbuf == NULL) {
-                       update_pixbuf (view, eog_image_get_pixbuf (image));
-                       /* priv->progressive_state = PROGRESSIVE_NONE; */
-                       _set_zoom_mode_internal (view,
-                                                EOG_ZOOM_MODE_SHRINK_TO_FIT);
-
-               }
-#if 0
-               else if ((is_zoomed_in (view) && priv->interp_type_in != CAIRO_FILTER_NEAREST) ||
-                        (is_zoomed_out (view) && priv->interp_type_out != CAIRO_FILTER_NEAREST))
-               {
-                       /* paint antialiased image version */
-                       priv->progressive_state = PROGRESSIVE_POLISHING;
-                       gtk_widget_queue_draw (GTK_WIDGET (priv->display));
-               }
-#endif
-
                priv->image_changed_id = g_signal_connect (image, "changed",
                                                           (GCallback) image_changed_cb, view);
                if (eog_image_is_animation (image) == TRUE ) {
                        eog_image_start_animation (image);
-                       priv->frame_changed_id = g_signal_connect (image, "next-frame", 
+                       priv->frame_changed_id = g_signal_connect (image, "next-frame",
                                                                    (GCallback) display_next_frame_cb, view);
                }
        }
@@ -2159,9 +2097,6 @@ eog_scroll_view_init (EogScrollView *view)
        priv->scroll_wheel_zoom = FALSE;
        priv->zoom_multiplier = IMAGE_VIEW_ZOOM_MULTIPLIER;
        priv->image = NULL;
-       priv->pixbuf = NULL;
-       priv->surface = NULL;
-       /* priv->progressive_state = PROGRESSIVE_NONE; */
        priv->transp_style = EOG_TRANSP_BACKGROUND;
        g_warn_if_fail (gdk_rgba_parse(&priv->transp_color, CHECK_BLACK));
        priv->cursor = EOG_SCROLL_VIEW_CURSOR_NORMAL;
@@ -2291,7 +2226,7 @@ eog_scroll_view_init (EogScrollView *view)
                          G_CALLBACK (pan_gesture_pan_cb), view);
        g_signal_connect (priv->pan_gesture, "end",
                          G_CALLBACK (pan_gesture_end_cb), view);
-       gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->pan_gesture), 
+       gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->pan_gesture),
                                           TRUE);
        gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->pan_gesture),
                                                    GTK_PHASE_CAPTURE);
@@ -2653,7 +2588,7 @@ eog_scroll_view_class_init (EogScrollViewClass *klass)
                g_param_spec_boxed ("transparency-color", NULL, NULL,
                                    GDK_TYPE_RGBA,
                                    G_PARAM_WRITABLE | G_PARAM_STATIC_NAME));
-       
+
        /**
         * EogScrollView:transparency-style:
         *
@@ -2951,7 +2886,7 @@ _set_zoom_mode_internal (EogScrollView *view, EogZoomMode mode)
                eog_scroll_view_zoom_fit (view);
        else
                view->priv->zoom_mode = mode;
-       
+
        if (notify)
                g_object_notify (G_OBJECT (view), "zoom-mode");
 }
@@ -3046,7 +2981,7 @@ eog_scroll_view_event_is_over_image (EogScrollView *view, const GdkEvent *ev)
        priv = view->priv;
        window = gtk_widget_get_window (GTK_WIDGET (priv->display));
 
-       if (G_UNLIKELY (priv->pixbuf == NULL 
+       if (G_UNLIKELY (priv->image == NULL
            || window != ((GdkEventAny*) ev)->window))
                return FALSE;
 


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