From 73dc9833b700fe07f9dee1adfe4a18c7771054f3 Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Thu, 21 Jul 2011 11:17:13 +0200
Subject: [PATCH] gdi32: Pass the full bitblt_coords structure to the
 Get/PutImage entry points.

---
 dlls/gdi32/bitblt.c       | 13 ++++-----
 dlls/gdi32/dib.c          | 20 +++++++-------
 dlls/gdi32/driver.c       |  5 ++--
 dlls/winex11.drv/bitblt.c | 55 +++++++++++++++++++++++----------------
 dlls/winex11.drv/x11drv.h |  4 +--
 include/wine/gdi_driver.h |  6 ++---
 6 files changed, 56 insertions(+), 47 deletions(-)

diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c
index 0f266ec4ec..2d81ad53d4 100644
--- a/dlls/gdi32/bitblt.c
+++ b/dlls/gdi32/bitblt.c
@@ -209,7 +209,7 @@ try_get_image:
 
     if (!(dc_src = get_dc_ptr( src_dev->hdc ))) return FALSE;
     src_dev = GET_DC_PHYSDEV( dc_src, pGetImage );
-    err = src_dev->funcs->pGetImage( src_dev, 0, src_info, &src_bits, &src->visrect );
+    err = src_dev->funcs->pGetImage( src_dev, 0, src_info, &src_bits, src );
     release_dc_ptr( dc_src );
     if (err) return FALSE;
 
@@ -220,11 +220,9 @@ try_get_image:
                src->width, src->height, dst->width, dst->height );
 
     memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
-    err = dst_dev->funcs->pPutImage( dst_dev, 0, dst_info, &src_bits, &dst->visrect, rop );
+    err = dst_dev->funcs->pPutImage( dst_dev, 0, dst_info, &src_bits, src, dst, rop );
     if (err == ERROR_BAD_FORMAT)
     {
-        RECT src_rect = src->visrect;
-
         /* 1-bpp source without a color table uses the destination DC colors */
         if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed)
         {
@@ -253,19 +251,18 @@ try_get_image:
             dst_info->bmiHeader.biClrUsed = 1;
         }
 
-        offset_rect( &src_rect, src_bits.offset - src->visrect.left, -src->visrect.top );
-        dst_info->bmiHeader.biWidth = src_rect.right - src_rect.left;
+        dst_info->bmiHeader.biWidth = src->visrect.right - src->visrect.left;
         dst_bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
         if (dst_bits.ptr)
         {
             dst_bits.is_copy = TRUE;
             dst_bits.offset = 0;
             dst_bits.free = free_heap_bits;
-            if (!(err = convert_bitmapinfo( src_info, src_bits.ptr, &src_rect, dst_info, dst_bits.ptr )))
+            if (!(err = convert_bitmapinfo( src_info, src_bits.ptr, &src->visrect, dst_info, dst_bits.ptr )))
             {
                 /* get rid of the fake 1-bpp table */
                 if (dst_info->bmiHeader.biClrUsed == 1) dst_info->bmiHeader.biClrUsed = 0;
-                err = dst_dev->funcs->pPutImage( dst_dev, 0, dst_info, &dst_bits, &dst->visrect, rop );
+                err = dst_dev->funcs->pPutImage( dst_dev, 0, dst_info, &dst_bits, src, dst, rop );
             }
             if (dst_bits.free) dst_bits.free( &dst_bits );
         }
diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 181515111e..7e5354bd69 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -693,10 +693,10 @@ INT WINAPI GetDIBits(
     if (bits && lines)
     {
         PHYSDEV physdev;
-        RECT rect;
         char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
         BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
         struct gdi_image_bits src_bits;
+        struct bitblt_coords src;
         DWORD err;
 
         /* FIXME: will need updating once the dib driver has pGetImage. */
@@ -704,8 +704,8 @@ INT WINAPI GetDIBits(
 
         if (!BITMAP_SetOwnerDC( hbitmap, physdev )) lines = 0;
 
-        rect.left = 0;
-        rect.right = min( width, bmp->bitmap.bmWidth );
+        src.visrect.left = 0;
+        src.visrect.right = min( width, bmp->bitmap.bmWidth );
 
         if (startscan >= bmp->bitmap.bmHeight)                       /* constrain lines to within src bitmap */
             lines = 0;
@@ -715,10 +715,14 @@ INT WINAPI GetDIBits(
 
         if (lines == 0) goto done;
 
-        rect.bottom = bmp->bitmap.bmHeight - startscan;
-        rect.top = rect.bottom - lines;
+        src.visrect.bottom = bmp->bitmap.bmHeight - startscan;
+        src.visrect.top = src.visrect.bottom - lines;
+        src.x = src.visrect.left;
+        src.y = src.visrect.top;
+        src.width = src.visrect.right - src.visrect.left;
+        src.height = src.visrect.bottom - src.visrect.top;
 
-        err = physdev->funcs->pGetImage( physdev, hbitmap, src_info, &src_bits, &rect );
+        err = physdev->funcs->pGetImage( physdev, hbitmap, src_info, &src_bits, &src );
 
         if(err)
         {
@@ -734,14 +738,12 @@ INT WINAPI GetDIBits(
                 fill_default_color_table( src_info );
         }
 
-        offset_rect( &rect, src_bits.offset, -rect.top );
-
         if(dst_info->bmiHeader.biHeight > 0)
             dst_info->bmiHeader.biHeight = lines;
         else
             dst_info->bmiHeader.biHeight = -lines;
 
-        convert_bitmapinfo( src_info, src_bits.ptr, &rect, dst_info, bits );
+        convert_bitmapinfo( src_info, src_bits.ptr, &src.visrect, dst_info, bits );
         if (src_bits.free) src_bits.free( &src_bits );
     }
     else lines = abs(height);
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 0c268399d5..71d15cd7a4 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -348,7 +348,7 @@ static BOOL nulldrv_GetICMProfile( PHYSDEV dev, LPDWORD size, LPWSTR filename )
 }
 
 static DWORD nulldrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
-                               struct gdi_image_bits *bits, const RECT *rect )
+                               struct gdi_image_bits *bits, struct bitblt_coords *src )
 {
     return ERROR_NOT_SUPPORTED;
 }
@@ -428,7 +428,8 @@ static BOOL nulldrv_Polyline( PHYSDEV dev, const POINT *points, INT count )
 }
 
 static DWORD nulldrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
-                               const struct gdi_image_bits *bits, const RECT *rect, DWORD rop )
+                               const struct gdi_image_bits *bits, struct bitblt_coords *src,
+                               struct bitblt_coords *dst, DWORD rop )
 {
     return ERROR_SUCCESS;
 }
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c
index c1dc6c4fbf..015a3e07c4 100644
--- a/dlls/winex11.drv/bitblt.c
+++ b/dlls/winex11.drv/bitblt.c
@@ -1711,7 +1711,7 @@ static BOOL matching_color_info( PHYSDEV dev, const ColorShifts *color_shifts, c
 /* copy the image bits, fixing up alignment and byte swapping as necessary */
 static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts, XImage *image,
                               const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,
-                              const int *mapping, unsigned int zeropad_mask )
+                              struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask )
 {
 #ifdef WORDS_BIGENDIAN
     static const int client_byte_order = MSBFirst;
@@ -1719,7 +1719,7 @@ static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts,
     static const int client_byte_order = LSBFirst;
 #endif
     BOOL need_byteswap;
-    int x, y, height = abs(info->bmiHeader.biHeight);
+    int x, y, height = coords->visrect.bottom - coords->visrect.top;
     int width_bytes = image->bytes_per_line;
     int padding_pos;
     unsigned char *src, *dst;
@@ -1745,6 +1745,12 @@ static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts,
         break;
     }
 
+    src = src_bits->ptr;
+    if (info->bmiHeader.biHeight > 0)
+        src += (info->bmiHeader.biHeight - coords->visrect.bottom) * width_bytes;
+    else
+        src += coords->visrect.top * width_bytes;
+
     if ((need_byteswap && !src_bits->is_copy) ||  /* need to swap bytes */
         (zeropad_mask != ~0u && !src_bits->is_copy) ||  /* need to clear padding bytes */
         (mapping && !src_bits->is_copy) ||  /* need to remap pixels */
@@ -1762,14 +1768,13 @@ static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts,
     else
     {
         /* swap bits in place */
-        dst_bits->ptr = src_bits->ptr;
+        dst_bits->ptr = src;
         dst_bits->offset = src_bits->offset;
         dst_bits->is_copy = src_bits->is_copy;
         dst_bits->free = NULL;
         if (!need_byteswap && zeropad_mask == ~0u && !mapping) return ERROR_SUCCESS;  /* nothing to do */
     }
 
-    src = src_bits->ptr;
     dst = dst_bits->ptr;
     padding_pos = width_bytes/sizeof(unsigned int) - 1;
 
@@ -1859,7 +1864,7 @@ static DWORD copy_image_bits( BITMAPINFO *info, const ColorShifts *color_shifts,
  *           X11DRV_PutImage
  */
 DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const struct gdi_image_bits *bits,
-                       const RECT *rect, DWORD rop )
+                       struct bitblt_coords *src, struct bitblt_coords *dst, DWORD rop )
 {
     X11DRV_PDEVICE *physdev;
     X_PHYSBITMAP *bitmap;
@@ -1896,7 +1901,7 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const str
 
     wine_tsx11_lock();
     image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0, NULL,
-                          info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), 32, 0 );
+                          info->bmiHeader.biWidth, src->visrect.bottom - src->visrect.top, 32, 0 );
     wine_tsx11_unlock();
     if (!image) return ERROR_OUTOFMEMORY;
 
@@ -1906,20 +1911,20 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const str
             mapping = X11DRV_PALETTE_PaletteToXPixel;
     }
 
-    ret = copy_image_bits( info, color_shifts, image, bits, &dst_bits, mapping, ~0u );
+    ret = copy_image_bits( info, color_shifts, image, bits, &dst_bits, src, mapping, ~0u );
 
     if (!ret)
     {
-        int width = rect->right - rect->left;
-        int height = rect->bottom - rect->top;
+        int width = dst->visrect.right - dst->visrect.left;
+        int height = dst->visrect.bottom - dst->visrect.top;
 
         image->data = dst_bits.ptr;
         if (bitmap)
         {
             X11DRV_DIB_Lock( bitmap, DIB_Status_GdiMod );
             wine_tsx11_lock();
-            XPutImage( gdi_display, bitmap->pixmap, get_bitmap_gc(depth), image, dst_bits.offset, 0,
-                       rect->left, rect->top, width, height );
+            XPutImage( gdi_display, bitmap->pixmap, get_bitmap_gc(depth), image, src->visrect.left, 0,
+                       dst->visrect.left, dst->visrect.top, width, height );
             wine_tsx11_unlock();
             X11DRV_DIB_Unlock( bitmap, TRUE );
         }
@@ -1932,9 +1937,9 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const str
             {
                 wine_tsx11_lock();
                 XSetFunction( gdi_display, physdev->gc, OP_ROP(*opcode) );
-                XPutImage( gdi_display, physdev->drawable, physdev->gc, image, dst_bits.offset, 0,
-                           physdev->dc_rect.left + rect->left, physdev->dc_rect.top + rect->top,
-                           width, height );
+                XPutImage( gdi_display, physdev->drawable, physdev->gc, image, src->visrect.left, 0,
+                           physdev->dc_rect.left + dst->visrect.left,
+                           physdev->dc_rect.top + dst->visrect.top, width, height );
                 wine_tsx11_unlock();
             }
             else
@@ -1947,10 +1952,10 @@ DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const str
                 XSetSubwindowMode( gdi_display, gc, IncludeInferiors );
                 XSetGraphicsExposures( gdi_display, gc, False );
                 src_pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
-                XPutImage( gdi_display, src_pixmap, gc, image, dst_bits.offset, 0, 0, 0, width, height );
+                XPutImage( gdi_display, src_pixmap, gc, image, src->visrect.left, 0, 0, 0, width, height );
                 wine_tsx11_unlock();
 
-                execute_rop( physdev, src_pixmap, gc, rect, rop );
+                execute_rop( physdev, src_pixmap, gc, &dst->visrect, rop );
 
                 wine_tsx11_lock();
                 XFreePixmap( gdi_display, src_pixmap );
@@ -1981,7 +1986,7 @@ update_format:
  *           X11DRV_GetImage
  */
 DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
-                       struct gdi_image_bits *bits, const RECT *rect )
+                       struct gdi_image_bits *bits, struct bitblt_coords *src )
 {
     X11DRV_PDEVICE *physdev;
     X_PHYSBITMAP *bitmap;
@@ -2023,12 +2028,16 @@ DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
         FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
         return ERROR_BAD_FORMAT;
     }
-    src_bits.offset = rect->left & (align - 1);
-    x = rect->left - src_bits.offset;
-    y = rect->top;
-    width = rect->right - x;
-    height = rect->bottom - rect->top;
+    src_bits.offset = src->visrect.left & (align - 1);
+    x = src->visrect.left - src_bits.offset;
+    y = src->visrect.top;
+    width = src->visrect.right - x;
+    height = src->visrect.bottom - src->visrect.top;
     if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
+    /* make the source rectangle relative to the returned bits */
+    src->x -= x;
+    src->y -= y;
+    OffsetRect( &src->visrect, -x, -y );
 
     if (bitmap)
     {
@@ -2082,7 +2091,7 @@ DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
 
     src_bits.ptr     = image->data;
     src_bits.is_copy = TRUE;
-    ret = copy_image_bits( info, color_shifts, image, &src_bits, bits, mapping,
+    ret = copy_image_bits( info, color_shifts, image, &src_bits, bits, src, mapping,
                            zeropad_masks[(width * image->bits_per_pixel) & 31] );
 
     if (!ret && bits->ptr == image->data)
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 1729546e2d..1754b1b343 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -203,7 +203,7 @@ extern BOOL X11DRV_GetCharWidth( PHYSDEV dev, UINT firstChar, UINT lastChar, LPI
 extern BOOL X11DRV_GetDeviceGammaRamp( PHYSDEV dev, LPVOID ramp ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_GetICMProfile( PHYSDEV dev, LPDWORD size, LPWSTR filename ) DECLSPEC_HIDDEN;
 extern DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
-                              struct gdi_image_bits *bits, const RECT *rect ) DECLSPEC_HIDDEN;
+                              struct gdi_image_bits *bits, struct bitblt_coords *src ) DECLSPEC_HIDDEN;
 extern COLORREF X11DRV_GetNearestColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
 extern COLORREF X11DRV_GetPixel( PHYSDEV dev, INT x, INT y) DECLSPEC_HIDDEN;
 extern UINT X11DRV_GetSystemPaletteEntries( PHYSDEV dev, UINT start, UINT count, LPPALETTEENTRY entries ) DECLSPEC_HIDDEN;
@@ -220,7 +220,7 @@ extern BOOL X11DRV_Polygon( PHYSDEV dev, const POINT* pt, INT count ) DECLSPEC_H
 extern BOOL X11DRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polylines) DECLSPEC_HIDDEN;
 extern DWORD X11DRV_PutImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info, const struct gdi_image_bits *bits,
-                              const RECT *rect, DWORD rop ) DECLSPEC_HIDDEN;
+                              struct bitblt_coords *src, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN;
 extern UINT X11DRV_RealizeDefaultPalette( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern UINT X11DRV_RealizePalette( PHYSDEV dev, HPALETTE hpal, BOOL primary ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN;
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 3a9685ce5d..b4166bf104 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -95,7 +95,7 @@ struct gdi_dc_funcs
     INT      (*pGetDeviceCaps)(PHYSDEV,INT);
     BOOL     (*pGetDeviceGammaRamp)(PHYSDEV,LPVOID);
     BOOL     (*pGetICMProfile)(PHYSDEV,LPDWORD,LPWSTR);
-    DWORD    (*pGetImage)(PHYSDEV,HBITMAP,BITMAPINFO*,struct gdi_image_bits*,const RECT*);
+    DWORD    (*pGetImage)(PHYSDEV,HBITMAP,BITMAPINFO*,struct gdi_image_bits*,struct bitblt_coords*);
     COLORREF (*pGetNearestColor)(PHYSDEV,COLORREF);
     COLORREF (*pGetPixel)(PHYSDEV,INT,INT);
     INT      (*pGetPixelFormat)(PHYSDEV);
@@ -121,7 +121,7 @@ struct gdi_dc_funcs
     BOOL     (*pPolygon)(PHYSDEV,const POINT*,INT);
     BOOL     (*pPolyline)(PHYSDEV,const POINT*,INT);
     BOOL     (*pPolylineTo)(PHYSDEV,const POINT*,INT);
-    DWORD    (*pPutImage)(PHYSDEV,HBITMAP,BITMAPINFO*,const struct gdi_image_bits*,const RECT*,DWORD);
+    DWORD    (*pPutImage)(PHYSDEV,HBITMAP,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,DWORD);
     UINT     (*pRealizeDefaultPalette)(PHYSDEV);
     UINT     (*pRealizePalette)(PHYSDEV,HPALETTE,BOOL);
     BOOL     (*pRectangle)(PHYSDEV,INT,INT,INT,INT);
@@ -192,7 +192,7 @@ struct gdi_dc_funcs
 };
 
 /* increment this when you change the DC function table */
-#define WINE_GDI_DRIVER_VERSION 4
+#define WINE_GDI_DRIVER_VERSION 5
 
 static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset )
 {
-- 
2.32.0.93.g670b81a890