From 3b21892c772e72727f3a74cb9c8a4f421e79816f Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Tue, 14 Feb 2023 15:30:05 +0100 Subject: [PATCH] x11_grab: Clear image pixels not actually grabbed When using imlib_create[_scaled]_image_from_drawable() with non-zero source offsets the output image could contain pixels either not set or copied from uninitialised parts of intermediary pixmap. --- src/lib/api_x11.c | 8 ++++---- src/lib/x11_grab.c | 23 +++++++++++++++++++---- src/lib/x11_grab.h | 6 ++++-- src/lib/x11_rend.c | 4 ++-- test/test_grab.cpp | 5 ----- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/lib/api_x11.c b/src/lib/api_x11.c index 09c7f75..1ceda39 100644 --- a/src/lib/api_x11.c +++ b/src/lib/api_x11.c @@ -307,7 +307,7 @@ imlib_create_image_from_drawable(Pixmap mask, int x, int y, int width, err = __imlib_GrabDrawableToRGBA(&ctx->x11, im->data, 0, 0, width, height, ctx->drawable, mask, x, y, width, height, - &domask, need_to_grab_x); + &domask, need_to_grab_x, true); if (err) { __imlib_FreeImage(im); @@ -359,14 +359,14 @@ imlib_create_scaled_image_from_drawable(Pixmap mask, int src_x, int src_y, 0, 0, dst_width, dst_height, ctx->drawable, mask, src_x, src_y, src_width, src_height, - &domask, need_to_grab_x); + &domask, need_to_grab_x, true); else err = __imlib_GrabDrawableScaledToRGBA(&ctx->x11, im->data, 0, 0, dst_width, dst_height, ctx->drawable, mask, src_x, src_y, src_width, src_height, - &domask, need_to_grab_x); + &domask, need_to_grab_x, true); if (err) { __imlib_FreeImage(im); @@ -405,7 +405,7 @@ imlib_copy_drawable_to_image(Pixmap mask, int src_x, int src_y, int src_width, dst_x, dst_y, im->w, im->h, ctx->drawable, mask, src_x, src_y, src_width, src_height, - &domask, need_to_grab_x); + &domask, need_to_grab_x, false); } EAPI void diff --git a/src/lib/x11_grab.c b/src/lib/x11_grab.c index 0038555..f409888 100644 --- a/src/lib/x11_grab.c +++ b/src/lib/x11_grab.c @@ -604,12 +604,12 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data, int w_dst, int h_dst, Drawable draw, Pixmap mask_, int x_src, int y_src, int w_src, int h_src, - char *pdomask, int grab) + char *pdomask, int grab, bool clear) { XWindowAttributes xatt; bool is_pixmap, is_shm, is_mshm; char domask; - int i; + int i, j; int width, height; Pixmap mask = mask_; XShmSegmentInfo shminfo, mshminfo; @@ -786,6 +786,21 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data, } } +#define CLEAR(x0, x1, y0, y1) \ + do { \ + for (j = y0; j < y1; j++) \ + for (i = x0; i < x1; i++) \ + data[j * w_dst + i] = 0; \ + } while(0) + + if (clear) + { + CLEAR(0, w_dst, 0, y_dst); + CLEAR(0, w_dst, y_dst + h_src, h_dst); + CLEAR(0, x_dst, y_dst, y_dst + h_src); + CLEAR(x_dst + w_src, w_dst, y_dst, y_dst + h_src); + } + __imlib_GrabXImageToRGBA(x11, data, x_dst, y_dst, w_dst, h_dst, xim, mxim, x_src, y_src, w_src, h_src, 0); @@ -829,7 +844,7 @@ __imlib_GrabDrawableScaledToRGBA(const ImlibContextX11 * x11, uint32_t * data, int w_dst, int h_dst, Drawable draw, Pixmap mask_, int x_src, int y_src, int w_src, int h_src, - char *pdomask, int grab) + char *pdomask, int grab, bool clear) { int rc; int h_tmp, i, xx; @@ -897,7 +912,7 @@ __imlib_GrabDrawableScaledToRGBA(const ImlibContextX11 * x11, uint32_t * data, } rc = __imlib_GrabDrawableToRGBA(x11, data, 0, 0, w_dst, h_dst, psc, msc, - 0, 0, w_dst, h_dst, pdomask, grab); + 0, 0, w_dst, h_dst, pdomask, grab, clear); if (mgc) XFreeGC(x11->dpy, mgc); diff --git a/src/lib/x11_grab.h b/src/lib/x11_grab.h index 48e48fc..3999274 100644 --- a/src/lib/x11_grab.h +++ b/src/lib/x11_grab.h @@ -11,7 +11,8 @@ int __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, Drawable p, Pixmap m, int x_src, int y_src, int w_src, int h_src, - char *domask, int grab); + char *domask, int grab, + bool clear); int __imlib_GrabDrawableScaledToRGBA(const ImlibContextX11 * x11, uint32_t * data, @@ -20,7 +21,8 @@ int __imlib_GrabDrawableScaledToRGBA(const ImlibContextX11 * Drawable p, Pixmap m, int x_src, int y_src, int w_src, int h_src, - char *domask, int grab); + char *domask, int grab, + bool clear); void __imlib_GrabXImageToRGBA(const ImlibContextX11 * x11, uint32_t * data, diff --git a/src/lib/x11_rend.c b/src/lib/x11_rend.c index 9bb04fc..4fd73ec 100644 --- a/src/lib/x11_rend.c +++ b/src/lib/x11_rend.c @@ -319,7 +319,7 @@ __imlib_RenderImage(const ImlibContextX11 * x11, ImlibImage * im, { back = malloc(dw * dh * sizeof(uint32_t)); if (__imlib_GrabDrawableToRGBA(x11, back, 0, 0, dw, dh, - w, 0, dx, dy, dw, dh, 0, 1)) + w, 0, dx, dy, dw, dh, 0, 1, false)) { free(back); back = NULL; @@ -568,7 +568,7 @@ __imlib_RenderImageSkewed(const ImlibContextX11 * x11, ImlibImage * im, __imlib_GetContext(x11); __imlib_GrabDrawableToRGBA(x11, back->data, 0, 0, dw, dh, - w, 0, dx1, dy1, dw, dh, 0, 1); + w, 0, dx1, dy1, dw, dh, 0, 1, false); __imlib_BlendImageToImageSkewed(im, back, antialias, 1, 0, sx, sy, sw, sh, dx - dx1, dy - dy1, hsx, hsy, vsx, vsy, diff --git a/test/test_grab.cpp b/test/test_grab.cpp index 7ccc0f0..51591b4 100644 --- a/test/test_grab.cpp +++ b/test/test_grab.cpp @@ -322,11 +322,6 @@ _test_grab_1(const int wsrc, const int hsrc, const int xsrc, const int ysrc, x - xo < xi || y - yo < yi || x - xo >= xi + wimg || y - yo >= yi + himg) { -#if 1 - // FIXME - Pixels outside source drawable are not properly initialized - if (xo != 0 || yo != 0) - continue; -#endif col = 0x00000000; } else if (x < xo + bw || y < yo + bw ||