changeset 2710:79b668de97df

Partially fix #561: Hi-DPI-aware rendering of images. Displayed images are no longer blurry on Hi-DPI displays, nor they have a grid artifact any more. Image overlays and thumbnails are not addresset yet and are still blurry.
author Zoltan Ivanfi <zivanfi@apache.org>
date Thu, 28 Dec 2017 19:32:22 +0100
parents 8ba86a100c53
children 70457fceb02c
files src/renderer-tiles.c
diffstat 1 files changed, 50 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/renderer-tiles.c	Mon Jan 01 13:40:30 2018 +0100
+++ b/src/renderer-tiles.c	Thu Dec 28 19:32:22 2017 +0100
@@ -147,6 +147,7 @@
 	gint x_scroll;  /* allow local adjustment and mirroring */
 	gint y_scroll;
 
+	gint hidpi_scale;
 };
 
 
@@ -499,6 +500,25 @@
 	return PR_TILE_SIZE * PR_TILE_SIZE * 4 / 8;
 }
 
+static void rt_hidpi_aware_draw(
+	RendererTiles *rt,
+	cairo_t *cr,
+	GdkPixbuf *pixbuf,
+	double x,
+	double y)
+{
+#if GTK_CHECK_VERSION(3, 10, 0)
+	cairo_surface_t *surface;
+	surface = gdk_cairo_surface_create_from_pixbuf(pixbuf, rt->hidpi_scale, NULL);
+	cairo_set_source_surface(cr, surface, x, y);
+	cairo_fill(cr);
+	cairo_surface_destroy(surface);
+#else
+	gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y);
+	cairo_fill(cr);
+#endif
+}
+
 static void rt_tile_prepare(RendererTiles *rt, ImageTile *it)
 {
 	PixbufRenderer *pr = rt->pr;
@@ -511,7 +531,7 @@
 		                                            CAIRO_CONTENT_COLOR,
 		                                            rt->tile_width, rt->tile_height);
 
-		size = pixmap_calc_size(surface);
+		size = pixmap_calc_size(surface) * rt->hidpi_scale * rt->hidpi_scale;
 		rt_tile_free_space(rt, size, it);
 
 		it->surface = surface;
@@ -523,9 +543,9 @@
 		{
 		GdkPixbuf *pixbuf;
 		guint size;
-		pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, rt->tile_width, rt->tile_height);
+		pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, rt->hidpi_scale * rt->tile_width, rt->hidpi_scale * rt->tile_height);
 
-		size = gdk_pixbuf_get_rowstride(pixbuf) * rt->tile_height;
+		size = gdk_pixbuf_get_rowstride(pixbuf) * rt->tile_height * rt->hidpi_scale;
 		rt_tile_free_space(rt, size, it);
 
 		it->pixbuf = pixbuf;
@@ -623,7 +643,7 @@
 				cairo_fill_preserve(cr);
 
 				gdk_cairo_set_source_pixbuf(cr, od->pixbuf, px - rx, py - ry);
-				cairo_fill (cr);
+				cairo_fill(cr);
 				cairo_destroy (cr);
 
 				cr = gdk_cairo_create(od->window);
@@ -881,7 +901,7 @@
 
 static GdkPixbuf *rt_get_spare_tile(RendererTiles *rt)
 {
-	if (!rt->spare_tile) rt->spare_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, rt->tile_width, rt->tile_height);
+	if (!rt->spare_tile) rt->spare_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, rt->tile_width * rt->hidpi_scale, rt->tile_height * rt->hidpi_scale);
 	return rt->spare_tile;
 }
 
@@ -896,7 +916,7 @@
 	guchar *sp, *dp;
 	guchar *ip, *spi, *dpi;
 	gint i, j;
-	gint tw = rt->tile_width;
+	gint tw = rt->tile_width * rt->hidpi_scale;
 
 	srs = gdk_pixbuf_get_rowstride(src);
 	s_pix = gdk_pixbuf_get_pixels(src);
@@ -932,7 +952,7 @@
 	guchar *sp, *dp;
 	guchar *ip, *spi, *dpi;
 	gint i, j;
-	gint th = rt->tile_height;
+	gint th = rt->tile_height * rt->hidpi_scale;
 
 	srs = gdk_pixbuf_get_rowstride(src);
 	s_pix = gdk_pixbuf_get_pixels(src);
@@ -969,7 +989,7 @@
 	guchar *spi, *dpi;
 	gint i, j;
 
-	gint tw = rt->tile_width;
+	gint tw = rt->tile_width * rt->hidpi_scale;
 
 	srs = gdk_pixbuf_get_rowstride(src);
 	s_pix = gdk_pixbuf_get_pixels(src);
@@ -1005,8 +1025,8 @@
 	guchar *sp, *dp;
 	guchar *dpi;
 	gint i, j;
-	gint tw = rt->tile_width;
-	gint th = rt->tile_height;
+	gint tw = rt->tile_width * rt->hidpi_scale;
+	gint th = rt->tile_height * rt->hidpi_scale;
 
 	srs = gdk_pixbuf_get_rowstride(src);
 	s_pix = gdk_pixbuf_get_pixels(src);
@@ -1041,7 +1061,7 @@
 	guchar *sp, *dp;
 	guchar *spi, *dpi;
 	gint i;
-	gint th = rt->tile_height;
+	gint th = rt->tile_height * rt->hidpi_scale;
 
 	srs = gdk_pixbuf_get_rowstride(src);
 	s_pix = gdk_pixbuf_get_pixels(src);
@@ -1150,12 +1170,12 @@
 				if (st->blank)
 					{
 					cairo_set_source_rgb(cr, 0, 0, 0);
+					cairo_fill (cr);
 					}
 				else /* (pr->zoom == 1.0 || pr->scale == 1.0) */
 					{
-					gdk_cairo_set_source_pixbuf(cr, st->pixbuf, -it->x + st->x, -it->y + st->y);
+					rt_hidpi_aware_draw(rt, cr, st->pixbuf, -it->x + st->x, -it->y + st->y);
 					}
-				cairo_fill (cr);
 				cairo_destroy (cr);
 				}
 			}
@@ -1356,8 +1376,8 @@
 
 		if (pr->image_width == 0 || pr->image_height == 0) return;
 
-		scale_x = (gdouble)pr->width / pr->image_width;
-		scale_y = (gdouble)pr->height / pr->image_height;
+		scale_x = rt->hidpi_scale * (gdouble)pr->width / pr->image_width;
+		scale_y = rt->hidpi_scale * (gdouble)pr->height / pr->image_height;
 
 		pr_tile_coords_map_orientation(orientation, it->x, it->y,
 					    pr->width, pr->height,
@@ -1369,6 +1389,13 @@
 					    &pb_x, &pb_y,
 					    &pb_w, &pb_h);
 
+		src_x *= rt->hidpi_scale;
+		src_y *= rt->hidpi_scale;
+		pb_x *= rt->hidpi_scale;
+		pb_y *= rt->hidpi_scale;
+		pb_w *= rt->hidpi_scale;
+		pb_h *= rt->hidpi_scale;
+
 		switch (orientation)
 			{
 			gdouble tmp;
@@ -1424,8 +1451,7 @@
 
 		cr = cairo_create(it->surface);
 		cairo_rectangle (cr, x, y, w, h);
-		gdk_cairo_set_source_pixbuf(cr, it->pixbuf, 0, 0);
-		cairo_fill (cr);
+		rt_hidpi_aware_draw(rt, cr, it->pixbuf, 0, 0);
 		cairo_destroy (cr);
 		}
 }
@@ -2164,6 +2190,12 @@
 	rt->stereo_off_x = 0;
 	rt->stereo_off_y = 0;
 
+#if GTK_CHECK_VERSION(3, 10, 0)
+	rt->hidpi_scale = gtk_widget_get_scale_factor(GTK_WIDGET(rt->pr));
+#else
+	rt->hidpi_scale = 1;
+#endif
+
 	g_signal_connect(G_OBJECT(pr), "hierarchy-changed",
 			 G_CALLBACK(rt_hierarchy_changed_cb), rt);
 
@@ -2174,6 +2206,7 @@
 	g_signal_connect(G_OBJECT(pr), "expose_event",
 	                 G_CALLBACK(rt_expose_cb), rt);
 #endif
+
 	return (RendererFuncs *) rt;
 }