diff --git a/README.md b/README.md index b5d3479..0d9a24b 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,15 @@ Clone and run: ## TODO +- add high-DPI support + + for 2900% desktop scale (for example) we probably need to render our + 256x256 tiles as 128x128 gtk pixels + + however, this seems to cause filtering problems, mysteriously, see + https://github.com/jcupitt/vipsdisp/tree/add-high-dpi for a quick test + hack + - skip unknown files on next / prev? - need to add the test to next-image, not glob, since we can't test the diff --git a/src/imagedisplay.c b/src/imagedisplay.c index 0959f13..bb83501 100644 --- a/src/imagedisplay.c +++ b/src/imagedisplay.c @@ -666,9 +666,17 @@ imagedisplay_snapshot(GtkWidget *widget, GtkSnapshot *snapshot) paint.size.width = imagedisplay->paint_rect.width; paint.size.height = imagedisplay->paint_rect.height; + /* If there's no gtk snapping, we do our own based on the hardware pixel + * size for the surface this snapshot will be rendered to. + */ + GtkNative *native = gtk_widget_get_native(widget); + GdkSurface *surface = gtk_native_get_surface(native); + double pixel_size = 1.0 / gdk_surface_get_scale_factor(surface); + if (imagedisplay->tilecache && imagedisplay->tilecache->n_levels > 0) tilecache_snapshot(imagedisplay->tilecache, snapshot, + pixel_size, imagedisplay->scale, imagedisplay->x, imagedisplay->y, &paint, imagedisplay->debug); diff --git a/src/tilecache.c b/src/tilecache.c index 23b3111..b2543f9 100644 --- a/src/tilecache.c +++ b/src/tilecache.c @@ -835,15 +835,41 @@ tilecache_draw_bounds(GtkSnapshot *snapshot, } } +#ifndef HAVE_GTK_SNAPSHOT_SET_SNAP +/* Snap a graphene rect to a hardware pixel boundary on the output surface. We + * need to do this if the gtk snap mechachanism is missing or we'll get thin + * white lines on tile edges. + */ +static void +tilecache_snap_rect_to_boundary(graphene_rect_t *bounds, double pixel_size) +{ + double left = rint(bounds->origin.x * pixel_size) / pixel_size; + double top = rint(bounds->origin.y * pixel_size) / pixel_size; + double right = + rint((bounds->origin.x + bounds->size.width) * pixel_size) / pixel_size; + double bottom = + rint((bounds->origin.y + bounds->size.height) * pixel_size) / pixel_size; + + bounds->origin.x = left; + bounds->origin.y = top; + bounds->size.width = right - left; + bounds->size.height = bottom - top; +} +#endif /*!HAVE_GTK_SNAPSHOT_SET_SNAP*/ + /* Scale is how much the level0 image has been scaled, x/y is the position of - * the top-left corner of the paint_rect area in the scaled image. + * the top-left corner of @paint in the scaled image. + * + * @pixel_scale is gdk_surface_get_scale() for the surface this snapshot will + * be rendered to. * - * paint_rect is the pixel area in gtk coordinates that we paint in the widget. + * @paint is the pixel area in gtk coordinates that we paint in the widget. * * Set debug to draw tile boundaries for debugging. */ void tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot, + double pixel_size, double scale, double x, double y, graphene_rect_t *paint, gboolean debug) { /* In debug mode, scale and offset so we can see tile clipping. @@ -914,6 +940,9 @@ tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot, /* Paint the backdrop. */ graphene_rect_t backdrop = *paint; +#ifndef HAVE_GTK_SNAPSHOT_SET_SNAP + tilecache_snap_rect_to_boundary(&backdrop, pixel_size); +#endif /*!HAVE_GTK_SNAPSHOT_SET_SNAP*/ gtk_snapshot_push_repeat(snapshot, &backdrop, NULL); backdrop.origin.x = 0; @@ -947,11 +976,7 @@ tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot, bounds.size.height = tile->bounds0.height * scale; #ifndef HAVE_GTK_SNAPSHOT_SET_SNAP - /* Without set snap, we have to hide tile edges by expanding the - * tile. - */ - bounds.size.width += 1; - bounds.size.height += 1; + tilecache_snap_rect_to_boundary(&bounds, pixel_size); #endif /*!HAVE_GTK_SNAPSHOT_SET_SNAP*/ gtk_snapshot_append_scaled_texture(snapshot, diff --git a/src/tilecache.h b/src/tilecache.h index 3e54755..4dcef1d 100644 --- a/src/tilecache.h +++ b/src/tilecache.h @@ -110,6 +110,7 @@ Tilecache *tilecache_new(); /* Render the tiles to a snapshot. */ void tilecache_snapshot(Tilecache *tilecache, GtkSnapshot *snapshot, + double pixel_size, double scale, double x, double y, graphene_rect_t *paint, gboolean debug); #endif /*__TILECACHE_H*/