Alexandre Julliard : gdi32: Add a SetDIBitsToDevice implementation in the null driver using PutImage.

Alexandre Julliard julliard at winehq.org
Tue Sep 6 11:35:52 CDT 2011


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Sep  6 13:27:03 2011 +0200

gdi32: Add a SetDIBitsToDevice implementation in the null driver using PutImage.

---

 dlls/gdi32/dib.c          |  101 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/gdi32/driver.c       |    7 ---
 dlls/gdi32/gdi_private.h  |    3 +
 dlls/gdi32/tests/bitmap.c |    5 ++
 4 files changed, 109 insertions(+), 7 deletions(-)

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 927a74f..c1de074 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -610,6 +610,107 @@ done:
 }
 
 
+INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD cx, DWORD cy,
+                               INT x_src, INT y_src, UINT startscan, UINT lines,
+                               const void *bits, BITMAPINFO *src_info, UINT coloruse )
+{
+    DC *dc = get_nulldrv_dc( dev );
+    char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
+    BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer;
+    struct bitblt_coords src, dst;
+    struct gdi_image_bits src_bits;
+    DWORD err;
+    UINT height;
+    BOOL top_down;
+    POINT pt;
+    RECT rect;
+
+    top_down = (src_info->bmiHeader.biHeight < 0);
+    height = abs( src_info->bmiHeader.biHeight );
+
+    src_bits.ptr = (void *)bits;
+    src_bits.is_copy = FALSE;
+    src_bits.free = NULL;
+
+    if (coloruse == DIB_PAL_COLORS && !fill_color_table_from_palette( src_info, dev->hdc )) return 0;
+
+    if (!lines || (startscan >= height)) return 0;
+    if (!top_down && lines > height - startscan) lines = height - startscan;
+
+    /* map src to top-down coordinates with startscan as origin */
+    src.x = x_src;
+    src.y = startscan + lines - (y_src + cy);
+    src.width = cx;
+    src.height = cy;
+    if (src.y > 0)
+    {
+        if (!top_down)
+        {
+            /* get rid of unnecessary lines */
+            if (src.y >= lines) return 0;
+            lines -= src.y;
+            src.y = 0;
+        }
+        else if (src.y >= lines) return lines;
+    }
+    src_info->bmiHeader.biHeight = top_down ? -lines : lines;
+
+    src.visrect.left = src.x;
+    src.visrect.top = src.y;
+    src.visrect.right = src.x + cx;
+    src.visrect.bottom = src.y + cy;
+    rect.left = 0;
+    rect.top = 0;
+    rect.right = src_info->bmiHeader.biWidth;
+    rect.bottom = abs( src_info->bmiHeader.biHeight );
+    if (!intersect_rect( &src.visrect, &src.visrect, &rect )) return 0;
+
+    pt.x = x_dst;
+    pt.y = y_dst;
+    LPtoDP( dev->hdc, &pt, 1 );
+    dst.x = pt.x;
+    dst.y = pt.y;
+    dst.width = cx;
+    dst.height = cy;
+    if (GetLayout( dev->hdc ) & LAYOUT_RTL) dst.x -= cx - 1;
+
+    dst.visrect.left = dst.x;
+    dst.visrect.top = dst.y;
+    dst.visrect.right = dst.x + cx;
+    dst.visrect.bottom = dst.y + cy;
+    if (get_clip_box( dc, &rect )) intersect_rect( &dst.visrect, &dst.visrect, &rect );
+
+    offset_rect( &src.visrect, dst.x - src.x, dst.y - src.y );
+    intersect_rect( &rect, &src.visrect, &dst.visrect );
+    src.visrect = dst.visrect = rect;
+    offset_rect( &src.visrect, src.x - dst.x, src.y - dst.y );
+    if (is_rect_empty( &dst.visrect )) return lines;
+
+    dev = GET_DC_PHYSDEV( dc, pPutImage );
+    memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
+    err = dev->funcs->pPutImage( dev, 0, 0, dst_info, &src_bits, &src, &dst, SRCCOPY );
+    if (err == ERROR_BAD_FORMAT)
+    {
+        void *ptr;
+
+        dst_info->bmiHeader.biWidth = src.visrect.right - src.visrect.left;
+        ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
+        if (ptr)
+        {
+            err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
+            if (src_bits.free) src_bits.free( &src_bits );
+            src_bits.ptr = ptr;
+            src_bits.is_copy = TRUE;
+            src_bits.free = free_heap_bits;
+            if (!err) err = dev->funcs->pPutImage( dev, 0, 0, dst_info, &src_bits, &src, &dst, SRCCOPY );
+        }
+        else err = ERROR_OUTOFMEMORY;
+    }
+    if (err) lines = 0;
+    if (src_bits.free) src_bits.free( &src_bits );
+    return lines;
+}
+
 /***********************************************************************
  *           SetDIBitsToDevice   (GDI32.@)
  */
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 6233525..5beb04d 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -502,13 +502,6 @@ static UINT nulldrv_SetDIBColorTable( PHYSDEV dev, UINT pos, UINT count, const R
     return 0;
 }
 
-static INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height,
-                                      INT x_src, INT y_src, UINT start, UINT lines,
-                                      const void *bits, BITMAPINFO *info, UINT coloruse )
-{
-    return 0;
-}
-
 static void nulldrv_SetDeviceClipping( PHYSDEV dev, HRGN vis_rgn, HRGN clip_rgn )
 {
 }
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 82dbc36..c4ed75a 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -499,6 +499,9 @@ extern INT  nulldrv_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
+extern INT nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height,
+                                      INT x_src, INT y_src, UINT start, UINT lines,
+                                      const void *bits, BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN;
 extern INT  nulldrv_SetMapMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_SetViewportExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size ) DECLSPEC_HIDDEN;
 extern BOOL nulldrv_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index 6a80232..a2dbfd9 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -4265,6 +4265,11 @@ static void test_SetDIBitsToDevice(void)
     for (i = 0; i < 64; i++) ok( dib_bits[i] == 0xaaaaaaaa, "%d: got %08x\n", i, dib_bits[i] );
     memset( dib_bits, 0xaa, 64 * 4 );
 
+    ret = SetDIBitsToDevice( hdc, 0, 2, 8, 4, 0, -1, 3, 12, data, info, DIB_RGB_COLORS );
+    ok( ret == 0, "got %d\n", ret );
+    for (i = 0; i < 64; i++) ok( dib_bits[i] == 0xaaaaaaaa, "%d: got %08x\n", i, dib_bits[i] );
+    memset( dib_bits, 0xaa, 64 * 4 );
+
     SetMapMode( hdc, MM_ANISOTROPIC );
     SetWindowExtEx( hdc, 3, 3, NULL );
     ret = SetDIBitsToDevice( hdc, 2, 2, 2, 2, 1, 2, 1, 5, data, info, DIB_RGB_COLORS );




More information about the wine-cvs mailing list