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.
This commit is contained in:
James Sutton
2024-12-29 18:22:40 +13:00
committed by Simon Tatham
parent 5eea14c6c3
commit 79be403101

21
gtk.c
View File

@ -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);