[RFC PATCH 4/5] winex11.drv: Make GetImage return black for areas outside the drawable.
Giovanni Mascellani
gmascellani at codeweavers.com
Tue May 18 09:44:12 CDT 2021
Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
---
dlls/user32/tests/win.c | 6 ++--
dlls/winex11.drv/bitblt.c | 75 +++++++++++++++++++++++++++++++++++----
2 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index b50c8e1ff00..30514a05234 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -12580,7 +12580,7 @@ static void test_surface_composition(void)
flush_events( TRUE );
paint_client_rect(hwnd, BGRA2RGB(COLOR1));
check_client_surface(hwnd, painted_surface, sizeof(painted_surface), FALSE);
- check_screen_surface(hwnd, partial_surface, sizeof(partial_surface), TRUE);
+ check_screen_surface(hwnd, partial_surface, sizeof(partial_surface), FALSE);
SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE);
flush_events( TRUE );
@@ -12682,7 +12682,7 @@ static void test_surface_composition(void)
SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
paint_client_rect(hwnd, BGRA2RGB(COLOR1));
- check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), FALSE);
check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
ShowWindow(hwnd, SW_SHOW);
@@ -12807,7 +12807,7 @@ static void test_surface_composition(void)
SetWindowLongW(hwnd, GWL_EXSTYLE, GetWindowLongW(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
paint_client_rect(hwnd, BGRA2RGB(COLOR1));
- check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), TRUE);
+ check_client_surface(hwnd, hidden_surface, sizeof(hidden_surface), FALSE);
check_screen_surface(hwnd, screen_surface, sizeof(screen_surface), FALSE);
ret = UpdateLayeredWindow(hwnd, hdc_dst, NULL, (SIZE *)&rect.right, hdc_src, (POINT *)&rect.left, 0, NULL, ULW_OPAQUE);
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c
index fad183b0b01..3a083ea415c 100644
--- a/dlls/winex11.drv/bitblt.c
+++ b/dlls/winex11.drv/bitblt.c
@@ -1297,6 +1297,65 @@ update_format:
return ERROR_BAD_FORMAT;
}
+static XImage *safe_get_image( Drawable drawable, RECT *dc_rect, XVisualInfo *vis,
+ int x, int y, int width, int height, BOOL *use_xfree )
+{
+ XImage *image;
+ int dest_x = 0, dest_y = 0;
+
+ if (width < 0 || height < 0)
+ return NULL;
+
+ if (x >= dc_rect->left && y >= dc_rect->top
+ && x + width <= dc_rect->right && y + height <= dc_rect->bottom)
+ {
+ *use_xfree = TRUE;
+ return XGetImage( gdi_display, drawable, x, y, width, height, AllPlanes, ZPixmap );
+ }
+
+ *use_xfree = FALSE;
+ image = XCreateImage( gdi_display, vis->visual, vis->depth, ZPixmap, 0, NULL,
+ width, height, 32, 0 );
+ if (!image)
+ return NULL;
+
+ image->data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, image->bytes_per_line * image->height );
+ if (!image->data)
+ {
+ XDestroyImage( image );
+ return NULL;
+ }
+
+ if (x >= dc_rect->right || y >= dc_rect->bottom
+ || x + width <= dc_rect->left || y + height <= dc_rect->top)
+ return image;
+
+ if (x < dc_rect->left)
+ {
+ dest_x = dc_rect->left - x;
+ width -= dest_x;
+ x += dest_x;
+ }
+ if (y < dc_rect->top)
+ {
+ dest_y = dc_rect->top - y;
+ height -= dest_y;
+ y += dest_y;
+ }
+ if (x + width > dc_rect->right)
+ width -= dc_rect->right - (x + width);
+ if (y + height > dc_rect->bottom)
+ height -= dc_rect->bottom - (y + height);
+
+ if (XGetSubImage( gdi_display, drawable, x, y, width, height, AllPlanes, ZPixmap, image, dest_x, dest_y ))
+ return image;
+
+ HeapFree( GetProcessHeap(), 0, image->data );
+ image->data = NULL;
+ XDestroyImage( image );
+ return NULL;
+}
+
/***********************************************************************
* X11DRV_GetImage
*/
@@ -1311,6 +1370,7 @@ DWORD CDECL X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
struct gdi_image_bits src_bits;
const XPixmapFormatValues *format;
const int *mapping = NULL;
+ BOOL use_xfree = FALSE;
vis.depth = physdev->depth;
if (physdev->color_shifts)
@@ -1356,14 +1416,17 @@ DWORD CDECL X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
OffsetRect( &src->visrect, -x, -y );
X11DRV_expect_error( gdi_display, XGetImage_handler, NULL );
- image = XGetImage( gdi_display, physdev->drawable,
+ image = safe_get_image ( physdev->drawable, &physdev->dc_rect, &vis,
physdev->dc_rect.left + x, physdev->dc_rect.top + y,
- width, height, AllPlanes, ZPixmap );
+ width, height, &use_xfree );
if (X11DRV_check_error())
{
/* use a temporary pixmap to avoid the BadMatch error */
Pixmap pixmap = XCreatePixmap( gdi_display, root_window, width, height, vis.depth );
GC gc = XCreateGC( gdi_display, pixmap, 0, NULL );
+ int black = BlackPixel( gdi_display, DefaultScreen(gdi_display) );
+ XSetForeground( gdi_display, gc, black );
+ XFillRectangle( gdi_display, pixmap, gc, 0, 0, width, height );
XSetGraphicsExposures( gdi_display, gc, False );
XCopyArea( gdi_display, physdev->drawable, pixmap, gc,
@@ -1385,10 +1448,10 @@ DWORD CDECL X11DRV_GetImage( PHYSDEV dev, BITMAPINFO *info,
zeropad_masks[(width * image->bits_per_pixel) & 31] );
if (!ret && bits->ptr == image->data)
- {
- bits->free = free_ximage_bits;
- image->data = NULL;
- }
+ bits->free = use_xfree ? free_ximage_bits : free_heap_bits;
+ else
+ use_xfree ? XFree(image->data) : HeapFree( GetProcessHeap(), 0, image->data );
+ image->data = NULL;
XDestroyImage( image );
return ret;
}
--
2.31.1
More information about the wine-devel
mailing list