From 2a497a06d9297712778b9bfde3f21a2bd867967c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ball=C3=B3=20Gy=C3=B6rgy?= Date: Tue, 21 Feb 2017 01:06:06 +0100 Subject: [PATCH] Fix displaying images with GTK3 We have to use the cairo context provided by the draw event, otherwise the scrolling does not work properly. Don't paint the whole image when scale == 1, it's unneeded and slow. --- src/image-view.c | 86 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/src/image-view.c b/src/image-view.c index b367f2a..820b843 100644 --- a/src/image-view.c +++ b/src/image-view.c @@ -24,11 +24,10 @@ static void image_view_finalize(GObject *iv); static void image_view_clear( ImageView* iv ); -static gboolean on_idle( ImageView* iv ); static void calc_image_area( ImageView* iv ); -static void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type ); #if GTK_CHECK_VERSION(3, 0, 0) +static void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type, cairo_t* cr ); static void image_view_paint( ImageView* iv, cairo_t* cr ); @@ -37,6 +36,8 @@ static void on_get_preferred_height( GtkWidget* widget, gint* minimal_height, gi static gboolean on_draw_event(GtkWidget* widget, cairo_t* cr); #else // GTK2 +static gboolean on_idle( ImageView* iv ); +static void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type ); static void image_view_paint( ImageView* iv, GdkEventExpose* evt ); @@ -268,16 +269,13 @@ void image_view_paint( ImageView* iv, cairo_t *cr ) { cairo_rectangle_int_t rectangle; cairo_region_get_rectangle(region, i, &rectangle); - paint( iv, &rectangle, GDK_INTERP_NEAREST ); + paint( iv, &rectangle, GDK_INTERP_NEAREST, cr ); } cairo_region_destroy (region); - - if( 0 == iv->idle_handler ) - iv->idle_handler = g_idle_add( (GSourceFunc)on_idle, iv ); } } -#else +#else // GTK2 gboolean on_expose_event( GtkWidget* widget, GdkEventExpose* evt ) { @@ -390,6 +388,8 @@ void image_view_set_scale( ImageView* iv, gdouble new_scale, GdkInterpType type } } +#if GTK_CHECK_VERSION(3, 0, 0) +#else // GTK2 gboolean on_idle( ImageView* iv ) { GDK_THREADS_ENTER(); @@ -435,6 +435,7 @@ gboolean on_idle( ImageView* iv ) iv->idle_handler = 0; return FALSE; } +#endif void calc_image_area( ImageView* iv ) { @@ -460,7 +461,11 @@ void calc_image_area( ImageView* iv ) } } +#if GTK_CHECK_VERSION(3, 0, 0) +void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type, cairo_t* cr ) +#else // GTK2 void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type ) +#endif { GdkRectangle rect; if( ! gdk_rectangle_intersect( invalid_rect, &iv->img_area, &rect ) ) @@ -470,51 +475,48 @@ void paint( ImageView* iv, GdkRectangle* invalid_rect, GdkInterpType type ) int dest_y; GdkPixbuf* src_pix = NULL; - if( iv->scale == 1.0 ) // original size - { - src_pix = (GdkPixbuf*)g_object_ref( iv->pix ); - dest_x = iv->img_area.x; - dest_y = iv->img_area.y; - } - else // scaling is needed + GdkPixbuf* scaled_pix = NULL; + + dest_x = rect.x; + dest_y = rect.y; + + rect.x -= iv->img_area.x; + rect.y -= iv->img_area.y; + + int src_x = (int)floor( ((gdouble)rect.x) / iv->scale + 0.5 ); + int src_y = (int)floor( ((gdouble)rect.y) / iv->scale + 0.5 ); + int src_w = (int)floor( ((gdouble)rect.width) / iv->scale + 0.5 ); + int src_h = (int)floor( ((gdouble)rect.height) / iv->scale + 0.5 ); + if( src_y > gdk_pixbuf_get_height( iv->pix ) ) + src_y = gdk_pixbuf_get_height( iv->pix ); + if( src_x + src_w > gdk_pixbuf_get_width( iv->pix ) ) + src_w = gdk_pixbuf_get_width( iv->pix ) - src_x; + if( src_y + src_h > gdk_pixbuf_get_height( iv->pix ) ) + src_h = gdk_pixbuf_get_height( iv->pix ) - src_y; + //g_debug("orig src: x=%d, y=%d, w=%d, h=%d", + // src_x, src_y, src_w, src_h ); + + if ((src_w > 0) && (src_h > 0)) { - dest_x = rect.x; - dest_y = rect.y; - - rect.x -= iv->img_area.x; - rect.y -= iv->img_area.y; - - GdkPixbuf* scaled_pix = NULL; - int src_x = (int)floor( ((gdouble)rect.x) / iv->scale + 0.5 ); - int src_y = (int)floor( ((gdouble)rect.y) / iv->scale + 0.5 ); - int src_w = (int)floor( ((gdouble)rect.width) / iv->scale + 0.5 ); - int src_h = (int)floor( ((gdouble)rect.height) / iv->scale + 0.5 ); - if( src_y > gdk_pixbuf_get_height( iv->pix ) ) - src_y = gdk_pixbuf_get_height( iv->pix ); - if( src_x + src_w > gdk_pixbuf_get_width( iv->pix ) ) - src_w = gdk_pixbuf_get_width( iv->pix ) - src_x; - if( src_y + src_h > gdk_pixbuf_get_height( iv->pix ) ) - src_h = gdk_pixbuf_get_height( iv->pix ) - src_y; - //g_debug("orig src: x=%d, y=%d, w=%d, h=%d", - // src_x, src_y, src_w, src_h ); - - if ((src_w > 0) && (src_h > 0)) - { - src_pix = gdk_pixbuf_new_subpixbuf( iv->pix, src_x, src_y, src_w, src_h ); - scaled_pix = gdk_pixbuf_scale_simple( src_pix, rect.width, rect.height, type ); - g_object_unref( src_pix ); - src_pix = scaled_pix; - } - + src_pix = gdk_pixbuf_new_subpixbuf( iv->pix, src_x, src_y, src_w, src_h ); + scaled_pix = gdk_pixbuf_scale_simple( src_pix, rect.width, rect.height, type ); + g_object_unref( src_pix ); + src_pix = scaled_pix; } if( G_LIKELY(src_pix) ) { GtkWidget* widget = (GtkWidget*)iv; +#if GTK_CHECK_VERSION(3, 0, 0) +#else // GTK2 cairo_t *cr = gdk_cairo_create (gtk_widget_get_window(widget)); +#endif gdk_cairo_set_source_pixbuf (cr, src_pix, dest_x, dest_y); cairo_paint (cr); +#if GTK_CHECK_VERSION(3, 0, 0) +#else // GTK2 cairo_destroy (cr); +#endif g_object_unref( src_pix ); } -- 2.11.1