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
This commit is contained in:
Olivier Fourdan 2020-02-04 14:58:30 +01:00
parent e76ff8530b
commit 840c50b00d

View File

@ -1259,32 +1259,36 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
cr_height = cairo_image_surface_get_height (image); cr_height = cairo_image_surface_get_height (image);
cr_stride = cairo_image_surface_get_stride (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; uint8_t *src, *dst;
src = cr_data; src = cr_data;
dst = data; dst = data;
for (int i = 0; i < cr_height; i++) for (int i = 0; i < height; i++)
{ {
memcpy (dst, src, cr_stride); memcpy (dst, src, stride);
if (cr_width < bounds->width) if (width < bounds->width)
memset (dst + cr_stride, 0, (bounds->width * bpp) - cr_stride); memset (dst + stride, 0, (bounds->width * bpp) - stride);
src += cr_stride; src += cr_stride;
dst += bounds->width * bpp; 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); memset (dst, 0, bounds->width * bpp);
dst += bounds->width * bpp; dst += bounds->width * bpp;
} }
} }
else
{
memcpy (data, cr_data, cr_height * cr_stride);
}
cairo_surface_destroy (image); cairo_surface_destroy (image);
} }