From 840c50b00d2f7d8a8f9620872eae1ecbb81e1f3f Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Tue, 4 Feb 2020 14:58:30 +0100 Subject: [PATCH] window-actor: Ensure clipping in `capture_into()` The clip bounds passed in `meta_window_actor_capture_into()` represent the actual allocated buffer size where the window actor image will be eventually copied. As such, it is completely agnostic to the scaling factors that might affect the different surface actors which compose the window actor. So instead of trying to compute the scale factor by which the given clipping bounds need to be adjusted, simply clip the resulting image based on the given bounds to make sure we never overflow the destination buffer. https://gitlab.gnome.org/GNOME/mutter/merge_requests/1022 --- src/compositor/meta-window-actor.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 9f4568662..8ce6bc609 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1259,32 +1259,36 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, cr_height = cairo_image_surface_get_height (image); cr_stride = cairo_image_surface_get_stride (image); - if (cr_width < bounds->width || cr_height < bounds->height) + if (cr_width == bounds->width && cr_height == bounds->height) { + memcpy (data, cr_data, cr_height * cr_stride); + } + else + { + int width = MIN (bounds->width, cr_width); + int height = MIN (bounds->height, cr_height); + int stride = width * bpp; uint8_t *src, *dst; + src = cr_data; dst = data; - for (int i = 0; i < cr_height; i++) + for (int i = 0; i < height; i++) { - memcpy (dst, src, cr_stride); - if (cr_width < bounds->width) - memset (dst + cr_stride, 0, (bounds->width * bpp) - cr_stride); + memcpy (dst, src, stride); + if (width < bounds->width) + memset (dst + stride, 0, (bounds->width * bpp) - stride); src += cr_stride; dst += bounds->width * bpp; } - for (int i = cr_height; i < bounds->height; i++) + for (int i = height; i < bounds->height; i++) { memset (dst, 0, bounds->width * bpp); dst += bounds->width * bpp; } } - else - { - memcpy (data, cr_data, cr_height * cr_stride); - } cairo_surface_destroy (image); }