x11_grab: Rework clipping

Source clipping in imlib_copy_drawable_to_image() was broken and is
already dealt with in __imlib_GrabDrawableToRGBA().
Destination clipping has now been added.
This commit is contained in:
Kim Woelders 2023-02-20 16:40:22 +01:00
parent de79c704eb
commit e41499a528
2 changed files with 64 additions and 100 deletions

View File

@ -385,7 +385,6 @@ imlib_copy_drawable_to_image(Pixmap mask, int src_x, int src_y, int src_width,
{ {
ImlibImage *im; ImlibImage *im;
char domask = 0; char domask = 0;
int pre_adj;
CHECK_PARAM_POINTER_RETURN("image", ctx->image, 0); CHECK_PARAM_POINTER_RETURN("image", ctx->image, 0);
if (mask) if (mask)
@ -400,44 +399,6 @@ imlib_copy_drawable_to_image(Pixmap mask, int src_x, int src_y, int src_width,
if (ctx->error) if (ctx->error)
return 0; return 0;
pre_adj = 0;
if (src_x < 0)
{
src_width += src_x;
pre_adj = src_x;
src_x = 0;
}
if (src_width < 0)
src_width = 0;
if (dst_x < 0)
{
src_width += dst_x;
src_x -= dst_x - pre_adj;
dst_x = 0;
}
if ((dst_x + src_width) >= im->w)
src_width = im->w - dst_x;
pre_adj = 0;
if (src_y < 0)
{
src_height += src_y;
pre_adj = src_y;
src_y = 0;
}
if (src_height < 0)
src_height = 0;
if (dst_y < 0)
{
src_height += dst_y;
src_y -= dst_y - pre_adj;
dst_y = 0;
}
if ((dst_y + src_height) >= im->h)
src_height = im->h - dst_y;
if ((src_width <= 0) || (src_height <= 0))
return 0;
__imlib_DirtyImage(im); __imlib_DirtyImage(im);
return !__imlib_GrabDrawableToRGBA(&ctx->x11, im->data, return !__imlib_GrabDrawableToRGBA(&ctx->x11, im->data,

View File

@ -606,12 +606,11 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data,
int x_src, int y_src, int w_src, int h_src, int x_src, int y_src, int w_src, int h_src,
char *pdomask, int grab) char *pdomask, int grab)
{ {
XWindowAttributes xatt, ratt; XWindowAttributes xatt;
bool is_pixmap, is_shm, is_mshm; bool is_pixmap, is_shm, is_mshm;
char domask; char domask;
int i; int i;
int src_x, src_y, src_w, src_h; int width, height;
int width, height, clipx, clipy;
Pixmap mask = mask_; Pixmap mask = mask_;
XShmSegmentInfo shminfo, mshminfo; XShmSegmentInfo shminfo, mshminfo;
XImage *xim, *mxim; XImage *xim, *mxim;
@ -619,85 +618,96 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data,
domask = (pdomask) ? *pdomask : 0; domask = (pdomask) ? *pdomask : 0;
h_dst = 0; /* h_dst is not used */
if (grab) if (grab)
XGrabServer(x11->dpy); XGrabServer(x11->dpy);
width = w_src;
height = h_src;
is_pixmap = _DrawableCheck(x11->dpy, draw, &xatt); is_pixmap = _DrawableCheck(x11->dpy, draw, &xatt);
if (is_pixmap) if (is_pixmap)
{ {
Window dw; Window rret;
unsigned int bw;
XGetGeometry(x11->dpy, draw, &dw, &src_x, &src_y, XGetGeometry(x11->dpy, draw, &rret, &xatt.x, &xatt.y,
(unsigned int *)&src_w, (unsigned int *)&src_h, (unsigned int *)&xatt.width, (unsigned int *)&xatt.height,
(unsigned int *)&src_x, (unsigned int *)&xatt.depth); &bw, (unsigned int *)&xatt.depth);
src_x = 0;
src_y = 0;
} }
else else
{ {
Window dw; XWindowAttributes ratt;
Window cret;
XGetWindowAttributes(x11->dpy, xatt.root, &ratt);
XTranslateCoordinates(x11->dpy, draw, xatt.root,
0, 0, &src_x, &src_y, &dw);
src_w = xatt.width;
src_h = xatt.height;
if ((xatt.map_state != IsViewable) && (xatt.backing_store == NotUseful)) if ((xatt.map_state != IsViewable) && (xatt.backing_store == NotUseful))
goto bail; goto bail;
/* Clip source to screen */
XGetWindowAttributes(x11->dpy, xatt.root, &ratt);
XTranslateCoordinates(x11->dpy, draw, xatt.root,
0, 0, &xatt.x, &xatt.y, &cret);
if (xatt.x + x_src < 0)
{
width += xatt.x + x_src;
x_src = -xatt.x;
}
if (xatt.x + x_src + width > ratt.width)
width = ratt.width - (xatt.x + x_src);
if (xatt.y + y_src < 0)
{
height += xatt.y + y_src;
y_src = -xatt.y;
}
if (xatt.y + y_src + height > ratt.height)
height = ratt.height - (xatt.y + y_src);
/* Is this ever relevant? */
if (xatt.colormap == None)
xatt.colormap = ratt.colormap;
} }
/* clip to the drawable tree and screen */ /* Clip source to drawable */
clipx = 0;
clipy = 0;
width = src_w - x_src;
height = src_h - y_src;
if (width > w_src)
width = w_src;
if (height > h_src)
height = h_src;
if (!is_pixmap)
{
if ((src_x + x_src + width) > ratt.width)
width = ratt.width - (src_x + x_src);
if ((src_y + y_src + height) > ratt.height)
height = ratt.height - (src_y + y_src);
}
if (x_src < 0) if (x_src < 0)
{ {
clipx = -x_src; x_dst += -x_src;
width += x_src; width += x_src;
x_src = 0; x_src = 0;
} }
if (x_src + width > xatt.width)
width = xatt.width - x_src;
if (y_src < 0) if (y_src < 0)
{ {
clipy = -y_src; y_dst += -y_src;
height += y_src; height += y_src;
y_src = 0; y_src = 0;
} }
if (y_src + height > xatt.height)
height = xatt.height - y_src;
if (!is_pixmap) /* Clip source to destination */
if (x_dst < 0)
{ {
if ((src_x + x_src) < 0) x_src -= x_dst;
{ width += x_dst;
clipx -= (src_x + x_src); x_dst = 0;
width += (src_x + x_src);
x_src = -src_x;
}
if ((src_y + y_src) < 0)
{
clipy -= (src_y + y_src);
height += (src_y + y_src);
y_src = -src_y;
}
} }
if (x_dst + width > w_dst)
width = w_dst - x_dst;
if ((width <= 0) || (height <= 0)) if (y_dst < 0)
{
y_src -= y_dst;
height += y_dst;
y_dst = 0;
}
else if (y_dst + height > h_dst)
height = h_dst - y_dst;
if (width <= 0 || height <= 0)
goto bail; goto bail;
w_src = width; w_src = width;
@ -757,15 +767,9 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data,
if (!cmap) if (!cmap)
{ {
if (is_pixmap) if (is_pixmap)
{ cmap = DefaultColormap(x11->dpy, DefaultScreen(x11->dpy));
cmap = DefaultColormap(x11->dpy, DefaultScreen(x11->dpy));
}
else else
{ cmap = xatt.colormap;
cmap = xatt.colormap;
if (cmap == None)
cmap = ratt.colormap;
}
} }
for (i = 0; i < (1 << xatt.depth); i++) for (i = 0; i < (1 << xatt.depth); i++)
@ -782,8 +786,7 @@ __imlib_GrabDrawableToRGBA(const ImlibContextX11 * x11, uint32_t * data,
} }
} }
__imlib_GrabXImageToRGBA(x11, data, __imlib_GrabXImageToRGBA(x11, data, x_dst, y_dst, w_dst, h_dst,
x_dst + clipx, y_dst + clipy, w_dst, h_dst,
xim, mxim, x_src, y_src, w_src, h_src, 0); xim, mxim, x_src, y_src, w_src, h_src, 0);
/* destroy the Ximage */ /* destroy the Ximage */