From 79be403101d055d2fde3611a5f133135d4094ee9 Mon Sep 17 00:00:00 2001 From: James Sutton Date: Sun, 29 Dec 2024 18:22:40 +1300 Subject: [PATCH] GTK 3: account for window scale in blitter. Commit 97a0dc0 adjusted the backing surface size based on the GTK window scale, and used cairo_scale so that drawing code is oblivious to this. The blitter operates on the underlying pixels and so should account for the scaling, but no code was added for this. Now we multiply the blitter dimensions by the window scale, scale the pixel coordinates to save from, and set the scaling factor to 1:1 when loading. This fixes rendering artefacts with "GDK_SCALE=2", or when using display scaling with Wayland. Also adjust the backing surface position in draw_area so that it is centered properly. --- gtk.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/gtk.c b/gtk.c index 1c43ae9..b649c2b 100644 --- a/gtk.c +++ b/gtk.c @@ -639,9 +639,9 @@ static void do_draw_circle(frontend *fe, int cx, int cy, int radius, cairo_stroke(fe->cr); } -static void setup_blitter(blitter *bl, int w, int h) +static void setup_blitter(frontend *fe, blitter *bl, int w, int h) { - bl->image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w, h); + bl->image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w*fe->ps, h*fe->ps); } static void teardown_blitter(blitter *bl) @@ -653,15 +653,21 @@ static void do_blitter_save(frontend *fe, blitter *bl, int x, int y) { cairo_t *cr = cairo_create(bl->image); - cairo_set_source_surface(cr, fe->image, -x, -y); + cairo_set_source_surface(cr, fe->image, -x*fe->ps, -y*fe->ps); cairo_paint(cr); cairo_destroy(cr); } static void do_blitter_load(frontend *fe, blitter *bl, int x, int y) { - cairo_set_source_surface(fe->cr, bl->image, x, y); + cairo_save(fe->cr); + cairo_translate(fe->cr, x, y); + cairo_scale(fe->cr, 1.0/fe->ps, 1.0/fe->ps); + + cairo_set_source_surface(fe->cr, bl->image, 0, 0); cairo_paint(fe->cr); + + cairo_restore(fe->cr); } static void clear_backing_store(frontend *fe) @@ -916,7 +922,7 @@ static void do_draw_circle(frontend *fe, int cx, int cy, int radius, 2 * radius, 2 * radius, 0, 360 * 64); } -static void setup_blitter(blitter *bl, int w, int h) +static void setup_blitter(frontend *fe, blitter *bl, int w, int h) { /* * We can't create the pixmap right now, because fe->window @@ -1260,8 +1266,9 @@ static void gtk_draw_circle(drawing *dr, int cx, int cy, int radius, static blitter *gtk_blitter_new(drawing *dr, int w, int h) { + frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend); blitter *bl = snew(blitter); - setup_blitter(bl, w, h); + setup_blitter(fe, bl, w, h); bl->w = w; bl->h = h; return bl; @@ -1643,7 +1650,7 @@ static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data) cairo_translate(cr, m.x0 * (orig_sx - 1.0), m.y0 * (orig_sy - 1.0)); gdk_cairo_get_clip_rectangle(cr, &dirtyrect); - cairo_set_source_surface(cr, fe->image, fe->ox, fe->oy); + cairo_set_source_surface(cr, fe->image, fe->ox*fe->ps, fe->oy*fe->ps); cairo_rectangle(cr, dirtyrect.x, dirtyrect.y, dirtyrect.width, dirtyrect.height); cairo_fill(cr);