[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