Huw Davies : gdi32: Better handling of non-trivial source and destination areas.

Alexandre Julliard julliard at winehq.org
Thu Jul 28 13:55:44 CDT 2011


Module: wine
Branch: master
Commit: 863eb31bba7d5b59e52444de6afd500946812764
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=863eb31bba7d5b59e52444de6afd500946812764

Author: Huw Davies <huw at codeweavers.com>
Date:   Thu Jul 28 11:01:04 2011 +0100

gdi32: Better handling of non-trivial source and destination areas.

---

 dlls/gdi32/dib.c |   87 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 72 insertions(+), 15 deletions(-)

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 94a69a7..a590b94 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -1035,28 +1035,84 @@ INT WINAPI GetDIBits(
         char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
         BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
         struct gdi_image_bits src_bits;
-        struct bitblt_coords src;
+        struct bitblt_coords src, dst;
         DWORD err;
+        int dst_to_src_offset;
+        BOOL empty_rect;
 
-        src.visrect.left = 0;
-        src.visrect.right = min( width, bmp->bitmap.bmWidth );
+        src.visrect.left   = 0;
+        src.visrect.top    = 0;
+        src.visrect.right  = bmp->bitmap.bmWidth;
+        src.visrect.bottom = bmp->bitmap.bmHeight;
 
-        if (startscan >= bmp->bitmap.bmHeight)                       /* constrain lines to within src bitmap */
-            lines = 0;
+        dst.visrect.left   = 0;
+        dst.visrect.top    = 0;
+        dst.visrect.right  = dst_info->bmiHeader.biWidth;
+        dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
+
+        if (startscan >= dst.visrect.bottom)
+        {
+            lines = 1; /* yes, this is strange */
+            goto empty_image;
+        }
+
+        if (dst_info->bmiHeader.biHeight > 0)
+        {
+            dst_to_src_offset = -startscan;
+            lines = min( lines, dst.visrect.bottom - startscan );
+            if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
+        }
         else
-            lines = min( lines, bmp->bitmap.bmHeight - startscan );
-        lines = min( lines, abs(height) );                           /* and constrain to within dest bitmap */
+        {
+            dst_to_src_offset = dst.visrect.bottom - lines - startscan;
+            if (dst_to_src_offset < 0)
+            {
+                dst_to_src_offset = 0;
+                lines = dst.visrect.bottom - startscan;
+            }
+            if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
+        }
 
-        if (lines == 0) goto done;
+        offset_rect( &dst.visrect, 0, dst_to_src_offset );
+        empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
+        dst.visrect = src.visrect;
+        offset_rect( &dst.visrect, 0, -dst_to_src_offset );
+
+        if (dst_info->bmiHeader.biHeight > 0)
+        {
+            if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
+            {
+                int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
+                int pad_bytes = pad_lines * get_dib_stride( width, bpp );
+                memset( bits, 0, pad_bytes );
+                bits = (char *)bits + pad_bytes;
+            }
+        }
+        else
+        {
+            if (dst.visrect.bottom < lines)
+            {
+                int pad_lines = lines - dst.visrect.bottom, stride = get_dib_stride( width, bpp );
+                int pad_bytes = pad_lines * stride;
+                memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
+            }
+        }
 
-        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;
+        if (empty_rect)
+        {
+            lines = 0;
+            goto empty_image;
+        }
+
+        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;
 
+        lines = src.height;
+
         err = bmp->funcs->pGetImage( NULL, hbitmap, src_info, &src_bits, &src );
+
         if(err)
         {
             lines = 0;
@@ -1072,15 +1128,16 @@ INT WINAPI GetDIBits(
         }
 
         if(dst_info->bmiHeader.biHeight > 0)
-            dst_info->bmiHeader.biHeight = lines;
+            dst_info->bmiHeader.biHeight = src.height;
         else
-            dst_info->bmiHeader.biHeight = -lines;
+            dst_info->bmiHeader.biHeight = -src.height;
 
         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);
 
+empty_image:
     if (coloruse == DIB_PAL_COLORS)
     {
         WORD *index = (WORD *)dst_info->bmiColors;




More information about the wine-cvs mailing list